Merge "Round off attestation tests." into rvc-dev am: 2023afbe66 am: 40d453312c

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

Change-Id: I961fd9d6668c22d1a27ef351febb14706d6f48ba
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..d97975c
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,3 @@
+third_party {
+  license_type: NOTICE
+}
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/atrace/1.0/Android.bp b/atrace/1.0/Android.bp
index c7e8d04..5290a9a 100644
--- a/atrace/1.0/Android.bp
+++ b/atrace/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.atrace@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IAtraceDevice.hal",
diff --git a/audio/2.0/Android.bp b/audio/2.0/Android.bp
index 02f8b40..35f6803 100644
--- a/audio/2.0/Android.bp
+++ b/audio/2.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.audio@2.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IDevice.hal",
diff --git a/audio/4.0/Android.bp b/audio/4.0/Android.bp
index 862c711..4957a14 100644
--- a/audio/4.0/Android.bp
+++ b/audio/4.0/Android.bp
@@ -3,9 +3,8 @@
 hidl_interface {
     name: "android.hardware.audio@4.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
+    // TODO(b/153609531): remove when no longer needed.
+    native_bridge_supported: true,
     srcs: [
         "types.hal",
         "IDevice.hal",
diff --git a/audio/5.0/Android.bp b/audio/5.0/Android.bp
index 9b28497..365a654 100644
--- a/audio/5.0/Android.bp
+++ b/audio/5.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.audio@5.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IDevice.hal",
diff --git a/audio/6.0/Android.bp b/audio/6.0/Android.bp
index 16abc52..d7880b6 100644
--- a/audio/6.0/Android.bp
+++ b/audio/6.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.audio@6.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IDevice.hal",
diff --git a/audio/6.0/IStreamOutEventCallback.hal b/audio/6.0/IStreamOutEventCallback.hal
index de17d73..9c88713 100644
--- a/audio/6.0/IStreamOutEventCallback.hal
+++ b/audio/6.0/IStreamOutEventCallback.hal
@@ -25,11 +25,116 @@
     /**
      * Codec format changed.
      *
+     * onCodecFormatChanged returns an AudioMetadata object in read-only ByteString format.
+     * It represents the most recent codec format decoded by a HW audio decoder.
+     *
+     * Codec format is an optional message from HW audio decoders. It serves to
+     * notify the application about the codec format and audio objects contained
+     * within the compressed audio stream for control, informational,
+     * and display purposes.
+     *
+     * audioMetadata ByteString is convertible to an AudioMetadata object through
+     * both a C++ and a C API present in Metadata.h [1], or through a Java API present
+     * in AudioMetadata.java [2].
+     *
+     * The ByteString format is a stable format used for parcelling (marshalling) across
+     * JNI, AIDL, and HIDL interfaces.  The test for R compatibility for native marshalling
+     * is TEST(metadata_tests, compatibility_R) [3].  The test for R compatibility for JNI
+     * marshalling is android.media.cts.AudioMetadataTest#testCompatibilityR [4].
+     *
+     * R (audio HAL 6.0) defined keys are as follows [2]:
+     * "bitrate", int32
+     * "channel-mask", int32
+     * "mime", string
+     * "sample-rate", int32
+     * "bit-width", int32
+     * "has-atmos", int32
+     * "audio-encoding", int32
+     *
+     * Parceling Format:
+     * All values are native endian order. [1]
+     *
+     * using type_size_t = uint32_t;
+     * using index_size_t = uint32_t;
+     * using datum_size_t = uint32_t;
+     *
+     * Permitted type indexes are
+     * TYPE_NONE = 0, // Reserved
+     * TYPE_INT32 = 1,
+     * TYPE_INT64 = 2,
+     * TYPE_FLOAT = 3,
+     * TYPE_DOUBLE = 4,
+     * TYPE_STRING = 5,
+     * TYPE_DATA = 6,  // A data table of <String, Datum>
+     *
+     * Datum = {
+     *           (type_size_t)  Type (the type index from type_as_value<T>.)
+     *           (datum_size_t) Size (size of the Payload)
+     *           (byte string)  Payload<Type>
+     *         }
+     *
+     * The data is specified in native endian order.
+     * Since the size of the Payload is always present, unknown types may be skipped.
+     *
+     * Payload<Fixed-size Primitive_Value>
+     * [ sizeof(Primitive_Value) in raw bytes ]
+     *
+     * Example of Payload<Int32> of 123:
+     * Payload<Int32>
+     * [ value of 123                   ] =  0x7b 0x00 0x00 0x00       123
+     *
+     * Payload<String>
+     * [ (index_size_t) length, not including zero terminator.]
+     * [ (length) raw bytes ]
+     *
+     * Example of Payload<String> of std::string("hi"):
+     * [ (index_size_t) length          ] = 0x02 0x00 0x00 0x00        2 strlen("hi")
+     * [ raw bytes "hi"                 ] = 0x68 0x69                  "hi"
+     *
+     * Payload<Data>
+     * [ (index_size_t) entries ]
+     * [ raw bytes   (entry 1) Key   (Payload<String>)
+     *                         Value (Datum)
+     *                ...  (until #entries) ]
+     *
+     * Example of Payload<Data> of {{"hello", "world"},
+     *                              {"value", (int32_t)1000}};
+     * [ (index_size_t) #entries        ] = 0x02 0x00 0x00 0x00        2 entries
+     *    Key (Payload<String>)
+     *    [ index_size_t length         ] = 0x05 0x00 0x00 0x00        5 strlen("hello")
+     *    [ raw bytes "hello"           ] = 0x68 0x65 0x6c 0x6c 0x6f   "hello"
+     *    Value (Datum)
+     *    [ (type_size_t) type          ] = 0x05 0x00 0x00 0x00        5 (TYPE_STRING)
+     *    [ (datum_size_t) size         ] = 0x09 0x00 0x00 0x00        sizeof(index_size_t) +
+     *                                                                 strlen("world")
+     *       Payload<String>
+     *       [ (index_size_t) length    ] = 0x05 0x00 0x00 0x00        5 strlen("world")
+     *       [ raw bytes "world"        ] = 0x77 0x6f 0x72 0x6c 0x64   "world"
+     *    Key (Payload<String>)
+     *    [ index_size_t length         ] = 0x05 0x00 0x00 0x00        5 strlen("value")
+     *    [ raw bytes "value"           ] = 0x76 0x61 0x6c 0x75 0x65   "value"
+     *    Value (Datum)
+     *    [ (type_size_t) type          ] = 0x01 0x00 0x00 0x00        1 (TYPE_INT32)
+     *    [ (datum_size_t) size         ] = 0x04 0x00 0x00 0x00        4 sizeof(int32_t)
+     *        Payload<Int32>
+     *        [ raw bytes 1000          ] = 0xe8 0x03 0x00 0x00        1000
+     *
+     * The contents of audioMetadata is a Payload<Data>.
+     * An implementation dependent detail is that the Keys are always
+     * stored sorted, so the byte string representation generated is unique.
+     *
+     * Vendor keys are allowed for informational and debugging purposes.
+     * Vendor keys should consist of the vendor company name followed
+     * by a dot; for example, "vendorCompany.someVolume" [2].
+     *
+     * [1] system/media/audio_utils/include/audio_utils/Metadata.h
+     * [2] frameworks/base/media/java/android/media/AudioMetadata.java
+     * [3] system/media/audio_utils/tests/metadata_tests.cpp
+     * [4] cts/tests/tests/media/src/android/media/cts/AudioMetadataTest.java
+     *
      * @param audioMetadata is a buffer containing decoded format changes
      *     reported by codec. The buffer contains data that can be transformed
-     *     to audio metadata, which is a C++ object based map. See
-     *     `system/media/audio_utils/include/audio_utils/Metadata.h` for
-     *     more details.
+     *     to audio metadata, which is a C++ object based map.
      */
     oneway onCodecFormatChanged(vec<uint8_t> audioMetadata);
 };
diff --git a/audio/common/2.0/Android.bp b/audio/common/2.0/Android.bp
index bd3b069..56b43ff 100644
--- a/audio/common/2.0/Android.bp
+++ b/audio/common/2.0/Android.bp
@@ -3,6 +3,8 @@
 hidl_interface {
     name: "android.hardware.audio.common@2.0",
     root: "android.hardware",
+    // TODO(b/153609531): remove when no longer needed.
+    native_bridge_supported: true,
     vndk: {
         enabled: true,
     },
diff --git a/audio/common/4.0/Android.bp b/audio/common/4.0/Android.bp
index c01c486..dc4bca4 100644
--- a/audio/common/4.0/Android.bp
+++ b/audio/common/4.0/Android.bp
@@ -3,9 +3,8 @@
 hidl_interface {
     name: "android.hardware.audio.common@4.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
+    // TODO(b/153609531): remove when no longer needed.
+    native_bridge_supported: true,
     srcs: [
         "types.hal",
     ],
diff --git a/audio/common/5.0/Android.bp b/audio/common/5.0/Android.bp
index 761c171..bf265a5 100644
--- a/audio/common/5.0/Android.bp
+++ b/audio/common/5.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.audio.common@5.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
     ],
diff --git a/audio/common/6.0/Android.bp b/audio/common/6.0/Android.bp
index 94f1cf8..caeee6f 100644
--- a/audio/common/6.0/Android.bp
+++ b/audio/common/6.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.audio.common@6.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
     ],
diff --git a/audio/common/all-versions/default/service/Android.bp b/audio/common/all-versions/default/service/Android.bp
index 3e8b715..f163a2f 100644
--- a/audio/common/all-versions/default/service/Android.bp
+++ b/audio/common/all-versions/default/service/Android.bp
@@ -4,11 +4,11 @@
     init_rc: ["android.hardware.audio.service.rc"],
     relative_install_path: "hw",
     vendor: true,
-    // Only support 32 bit  as the binary must always be installed at the same
+    // Prefer 32 bit as the binary must always be installed at the same
     // location for init to start it and the build system does not support
     // having two binaries installable to the same location even if they are
     // not installed in the same build.
-    compile_multilib: "32",
+    compile_multilib: "prefer32",
     srcs: ["service.cpp"],
 
     cflags: [
diff --git a/audio/common/all-versions/default/service/android.hardware.audio.service.rc b/audio/common/all-versions/default/service/android.hardware.audio.service.rc
index f7e1e24..45fef9a 100644
--- a/audio/common/all-versions/default/service/android.hardware.audio.service.rc
+++ b/audio/common/all-versions/default/service/android.hardware.audio.service.rc
@@ -2,7 +2,7 @@
     class hal
     user audioserver
     # media gid needed for /dev/fm (radio) and for /data/misc/media (tee)
-    group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock
+    group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub
     capabilities BLOCK_SUSPEND
     ioprio rt 4
     task_profiles ProcessCapacityHigh HighPerformance
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp
index 0af81b2..8fdb70d 100644
--- a/audio/core/all-versions/default/Android.bp
+++ b/audio/core/all-versions/default/Android.bp
@@ -1,8 +1,5 @@
-cc_defaults {
-    name: "android.hardware.audio-impl_default",
-    relative_install_path: "hw",
-    proprietary: true,
-    vendor: true,
+filegroup {
+    name: "android.hardware.audio-impl_srcs",
     srcs: [
         "Conversions.cpp",
         "Device.cpp",
@@ -13,11 +10,24 @@
         "StreamIn.cpp",
         "StreamOut.cpp",
     ],
+}
+
+cc_library_headers {
+    name: "android.hardware.audio-impl_headers",
+    proprietary: true,
+    vendor: true,
+    export_include_dirs: ["include"],
+}
+
+cc_defaults {
+    name: "android.hardware.audio-impl_default",
+    relative_install_path: "hw",
+    proprietary: true,
+    vendor: true,
+    srcs: [":android.hardware.audio-impl_srcs"],
 
     defaults: ["hidl_defaults"],
 
-    export_include_dirs: ["include"],
-
     static_libs: [
         "libaudiofoundation",
     ],
@@ -35,12 +45,17 @@
     ],
 
     header_libs: [
+        "android.hardware.audio-impl_headers",
         "android.hardware.audio.common.util@all-versions",
         "libaudioclient_headers",
         "libaudio_system_headers",
         "libhardware_headers",
         "libmedia_headers",
     ],
+
+    export_header_lib_headers: [
+        "android.hardware.audio-impl_headers",
+    ],
 }
 
 cc_library_shared {
@@ -89,8 +104,8 @@
     ],
 }
 
-cc_library_shared {
-    name: "android.hardware.audio@6.0-impl",
+cc_defaults {
+    name: "android.hardware.audio@6.0-impl_default",
     defaults: ["android.hardware.audio-impl_default"],
     shared_libs: [
         "android.hardware.audio@6.0",
@@ -103,3 +118,8 @@
         "-include common/all-versions/VersionMacro.h",
     ],
 }
+
+cc_library_shared {
+    name: "android.hardware.audio@6.0-impl",
+    defaults: ["android.hardware.audio@6.0-impl_default"],
+}
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index 729ee7a..2d5e8a5 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -55,7 +55,7 @@
     data: [
         ":audio_policy_configuration_V2_0",
     ],
-    // Use test_config for vts-core suite.
+    // Use test_config for vts suite.
     // TODO(b/146104851): Add auto-gen rules and remove it.
     test_config: "VtsHalAudioV2_0TargetTest.xml",
 }
@@ -78,7 +78,7 @@
     data: [
         ":audio_policy_configuration_V4_0",
     ],
-    // Use test_config for vts-core suite.
+    // Use test_config for vts suite.
     // TODO(b/146104851): Add auto-gen rules and remove it.
     test_config: "VtsHalAudioV4_0TargetTest.xml",
 }
@@ -101,7 +101,7 @@
     data: [
         ":audio_policy_configuration_V5_0",
     ],
-    // Use test_config for vts-core suite.
+    // Use test_config for vts suite.
     // TODO(b/146104851): Add auto-gen rules and remove it.
     test_config: "VtsHalAudioV5_0TargetTest.xml",
 }
@@ -124,7 +124,7 @@
     data: [
         ":audio_policy_configuration_V6_0",
     ],
-    // Use test_config for vts-core suite.
+    // Use test_config for vts suite.
     // TODO(b/146104851): Add auto-gen rules and remove it.
     test_config: "VtsHalAudioV6_0TargetTest.xml",
 }
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index d5af335..10a1144 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -331,6 +331,9 @@
 INSTANTIATE_TEST_CASE_P(AudioHidl, AudioPolicyConfigTest,
                         ::testing::ValuesIn(getDeviceParametersForFactoryTests()),
                         &DeviceParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioPolicyConfigTest);
 
 //////////////////////////////////////////////////////////////////////////////
 ////////////////////// getService audio_devices_factory //////////////////////
@@ -366,6 +369,9 @@
 INSTANTIATE_TEST_CASE_P(AudioHidl, AudioHidlTest,
                         ::testing::ValuesIn(getDeviceParametersForFactoryTests()),
                         &DeviceParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioHidlTest);
 
 //////////////////////////////////////////////////////////////////////////////
 /////////////////////////////// openDevice ///////////////////////////////////
@@ -391,6 +397,9 @@
 
 INSTANTIATE_TEST_CASE_P(AudioHidlDevice, AudioHidlDeviceTest,
                         ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioHidlDeviceTest);
 
 //////////////////////////////////////////////////////////////////////////////
 /////////////////////////////// openDevice primary ///////////////////////////
@@ -418,6 +427,9 @@
 INSTANTIATE_TEST_CASE_P(AudioPrimaryHidl, AudioPrimaryHidlTest,
                         ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
                         &DeviceParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioPrimaryHidlTest);
 
 //////////////////////////////////////////////////////////////////////////////
 ///////////////////// {set,get}{Master,Mic}{Mute,Volume} /////////////////////
@@ -513,6 +525,10 @@
 INSTANTIATE_TEST_CASE_P(BoolAccessorPrimaryHidl, BoolAccessorPrimaryHidlTest,
                         ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
                         &DeviceParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BoolAccessorHidlTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BoolAccessorPrimaryHidlTest);
 
 using FloatAccessorHidlTest = AccessorHidlTest<float>;
 TEST_P(FloatAccessorHidlTest, MasterVolumeTest) {
@@ -525,6 +541,9 @@
 
 INSTANTIATE_TEST_CASE_P(FloatAccessorHidl, FloatAccessorHidlTest,
                         ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(FloatAccessorHidlTest);
 
 //////////////////////////////////////////////////////////////////////////////
 //////////////////////////////// AudioPatches ////////////////////////////////
@@ -547,6 +566,9 @@
 
 INSTANTIATE_TEST_CASE_P(AudioPatchHidl, AudioPatchHidlTest,
                         ::testing::ValuesIn(getDeviceParameters()), &DeviceParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioPatchHidlTest);
 
 // Nesting a tuple in another tuple allows to use GTest Combine function to generate
 // all combinations of devices and configs.
@@ -717,11 +739,15 @@
                 ::testing::ValuesIn(ConfigHelper::getRecommendedSupportCaptureAudioConfig()),
                 ::testing::Values(AudioInputFlag::NONE)),
         &DeviceConfigParameterToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OptionalInputBufferSizeTest);
 #elif MAJOR_VERSION >= 6
 INSTANTIATE_TEST_CASE_P(SupportedInputBufferSize, RequiredInputBufferSizeTest,
                         ::testing::ValuesIn(getInputDeviceConfigParameters()),
                         &DeviceConfigParameterToString);
 #endif
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RequiredInputBufferSizeTest);
 
 //////////////////////////////////////////////////////////////////////////////
 /////////////////////////////// setScreenState ///////////////////////////////
@@ -960,6 +986,9 @@
                         ::testing::ValuesIn(getOutputDeviceConfigParameters()),
                         &DeviceConfigParameterToString);
 #endif
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(OutputStreamTest);
 
 ////////////////////////////// openInputStream //////////////////////////////
 
@@ -1015,6 +1044,9 @@
                         ::testing::ValuesIn(getInputDeviceConfigParameters()),
                         &DeviceConfigParameterToString);
 #endif
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(InputStreamTest);
 
 //////////////////////////////////////////////////////////////////////////////
 ////////////////////////////// IStream getters ///////////////////////////////
@@ -1553,6 +1585,9 @@
 INSTANTIATE_TEST_CASE_P(TtyModeAccessorPrimaryHidl, TtyModeAccessorPrimaryHidlTest,
                         ::testing::ValuesIn(getDeviceParametersForPrimaryDeviceTests()),
                         &DeviceParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TtyModeAccessorPrimaryHidlTest);
 
 TEST_P(BoolAccessorPrimaryHidlTest, setGetHac) {
     doc::test("Query and set the HAC state");
diff --git a/audio/core/all-versions/vts/functional/VtsHalAudioV2_0TargetTest.xml b/audio/core/all-versions/vts/functional/VtsHalAudioV2_0TargetTest.xml
index 67fcdb6..3793bb5 100644
--- a/audio/core/all-versions/vts/functional/VtsHalAudioV2_0TargetTest.xml
+++ b/audio/core/all-versions/vts/functional/VtsHalAudioV2_0TargetTest.xml
@@ -17,13 +17,11 @@
     <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.RootTargetPreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup"/>
 
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="stop"/>
         <option name="run-command" value="setprop vts.native_server.on 1"/>
-        <option name="teardown-command" value="start"/>
         <option name="teardown-command" value="setprop vts.native_server.on 0"/>
     </target_preparer>
 
diff --git a/audio/core/all-versions/vts/functional/VtsHalAudioV4_0TargetTest.xml b/audio/core/all-versions/vts/functional/VtsHalAudioV4_0TargetTest.xml
index 2084060..f74ca1c 100644
--- a/audio/core/all-versions/vts/functional/VtsHalAudioV4_0TargetTest.xml
+++ b/audio/core/all-versions/vts/functional/VtsHalAudioV4_0TargetTest.xml
@@ -17,13 +17,11 @@
     <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.RootTargetPreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup"/>
 
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="stop"/>
         <option name="run-command" value="setprop vts.native_server.on 1"/>
-        <option name="teardown-command" value="start"/>
         <option name="teardown-command" value="setprop vts.native_server.on 0"/>
     </target_preparer>
 
diff --git a/audio/core/all-versions/vts/functional/VtsHalAudioV5_0TargetTest.xml b/audio/core/all-versions/vts/functional/VtsHalAudioV5_0TargetTest.xml
index 8b01e41..ccbb629 100644
--- a/audio/core/all-versions/vts/functional/VtsHalAudioV5_0TargetTest.xml
+++ b/audio/core/all-versions/vts/functional/VtsHalAudioV5_0TargetTest.xml
@@ -17,13 +17,11 @@
     <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.RootTargetPreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup"/>
 
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="stop"/>
         <option name="run-command" value="setprop vts.native_server.on 1"/>
-        <option name="teardown-command" value="start"/>
         <option name="teardown-command" value="setprop vts.native_server.on 0"/>
     </target_preparer>
 
diff --git a/audio/core/all-versions/vts/functional/VtsHalAudioV6_0TargetTest.xml b/audio/core/all-versions/vts/functional/VtsHalAudioV6_0TargetTest.xml
index 05edc0d..f035baf 100644
--- a/audio/core/all-versions/vts/functional/VtsHalAudioV6_0TargetTest.xml
+++ b/audio/core/all-versions/vts/functional/VtsHalAudioV6_0TargetTest.xml
@@ -17,13 +17,11 @@
     <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.RootTargetPreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup"/>
 
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="stop"/>
         <option name="run-command" value="setprop vts.native_server.on 1"/>
-        <option name="teardown-command" value="start"/>
         <option name="teardown-command" value="setprop vts.native_server.on 0"/>
     </target_preparer>
 
diff --git a/audio/effect/2.0/Android.bp b/audio/effect/2.0/Android.bp
index d4482c2..a5a8b34 100644
--- a/audio/effect/2.0/Android.bp
+++ b/audio/effect/2.0/Android.bp
@@ -3,9 +3,8 @@
 hidl_interface {
     name: "android.hardware.audio.effect@2.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
+    // TODO(b/153609531): remove when no longer needed.
+    native_bridge_supported: true,
     srcs: [
         "types.hal",
         "IAcousticEchoCancelerEffect.hal",
diff --git a/audio/effect/4.0/Android.bp b/audio/effect/4.0/Android.bp
index 8c1900f..31f94ae 100644
--- a/audio/effect/4.0/Android.bp
+++ b/audio/effect/4.0/Android.bp
@@ -3,9 +3,8 @@
 hidl_interface {
     name: "android.hardware.audio.effect@4.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
+    // TODO(b/153609531): remove when no longer needed.
+    native_bridge_supported: true,
     srcs: [
         "types.hal",
         "IAcousticEchoCancelerEffect.hal",
diff --git a/audio/effect/5.0/Android.bp b/audio/effect/5.0/Android.bp
index b7dad8d..a3081c6 100644
--- a/audio/effect/5.0/Android.bp
+++ b/audio/effect/5.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.audio.effect@5.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IAcousticEchoCancelerEffect.hal",
diff --git a/audio/effect/6.0/Android.bp b/audio/effect/6.0/Android.bp
index b6184f3..de4bde7 100644
--- a/audio/effect/6.0/Android.bp
+++ b/audio/effect/6.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.audio.effect@6.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IAcousticEchoCancelerEffect.hal",
diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
index 070242f..4787c09 100644
--- a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectTargetTest.cpp
@@ -845,3 +845,9 @@
                                    IEffectsFactory::descriptor)),
                            ::testing::Values(LOUDNESS_ENHANCER_EFFECT_TYPE)),
         EffectParameterToString);
+// When the VTS test runs on a device lacking the corresponding HAL version the parameter
+// list is empty, this isn't a problem.
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEffectsFactoryHidlTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEffectHidlTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EqualizerAudioEffectHidlTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerAudioEffectHidlTest);
diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV2_0TargetTest.xml b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV2_0TargetTest.xml
index b6e720b..36d9324 100644
--- a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV2_0TargetTest.xml
+++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV2_0TargetTest.xml
@@ -17,13 +17,11 @@
     <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.RootTargetPreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup"/>
 
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="stop"/>
         <option name="run-command" value="setprop vts.native_server.on 1"/>
-        <option name="teardown-command" value="start"/>
         <option name="teardown-command" value="setprop vts.native_server.on 0"/>
     </target_preparer>
 
diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV4_0TargetTest.xml b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV4_0TargetTest.xml
index df826c8..091a4dc 100644
--- a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV4_0TargetTest.xml
+++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV4_0TargetTest.xml
@@ -17,13 +17,11 @@
     <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.RootTargetPreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup"/>
 
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="stop"/>
         <option name="run-command" value="setprop vts.native_server.on 1"/>
-        <option name="teardown-command" value="start"/>
         <option name="teardown-command" value="setprop vts.native_server.on 0"/>
     </target_preparer>
 
diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV5_0TargetTest.xml b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV5_0TargetTest.xml
index 14bdf43..14e90a1 100644
--- a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV5_0TargetTest.xml
+++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV5_0TargetTest.xml
@@ -17,13 +17,11 @@
     <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.RootTargetPreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup"/>
 
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="stop"/>
         <option name="run-command" value="setprop vts.native_server.on 1"/>
-        <option name="teardown-command" value="start"/>
         <option name="teardown-command" value="setprop vts.native_server.on 0"/>
     </target_preparer>
 
diff --git a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV6_0TargetTest.xml b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV6_0TargetTest.xml
index 23adad0..8b6c08f 100644
--- a/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV6_0TargetTest.xml
+++ b/audio/effect/all-versions/vts/functional/VtsHalAudioEffectV6_0TargetTest.xml
@@ -17,13 +17,11 @@
     <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.RootTargetPreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup"/>
 
     <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="stop"/>
         <option name="run-command" value="setprop vts.native_server.on 1"/>
-        <option name="teardown-command" value="start"/>
         <option name="teardown-command" value="setprop vts.native_server.on 0"/>
     </target_preparer>
 
diff --git a/authsecret/1.0/Android.bp b/authsecret/1.0/Android.bp
index 3b84c3b..5c556d2 100644
--- a/authsecret/1.0/Android.bp
+++ b/authsecret/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.authsecret@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "IAuthSecret.hal",
     ],
diff --git a/automotive/audiocontrol/1.0/Android.bp b/automotive/audiocontrol/1.0/Android.bp
index 7ef7909..8835f51 100644
--- a/automotive/audiocontrol/1.0/Android.bp
+++ b/automotive/audiocontrol/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.automotive.audiocontrol@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IAudioControl.hal",
diff --git a/automotive/audiocontrol/2.0/Android.bp b/automotive/audiocontrol/2.0/Android.bp
index 2a9f849..e9ce638 100644
--- a/automotive/audiocontrol/2.0/Android.bp
+++ b/automotive/audiocontrol/2.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.automotive.audiocontrol@2.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IAudioControl.hal",
@@ -13,8 +10,9 @@
         "IFocusListener.hal",
     ],
     interfaces: [
-        "android.hidl.base@1.0",
         "android.hardware.audio.common@6.0",
+        "android.hidl.base@1.0",
+        "android.hidl.safe_union@1.0",
     ],
     gen_java: true,
 }
diff --git a/automotive/can/1.0/Android.bp b/automotive/can/1.0/Android.bp
index 2221e66..2ddfaf9 100644
--- a/automotive/can/1.0/Android.bp
+++ b/automotive/can/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.automotive.can@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ICanBus.hal",
diff --git a/automotive/can/1.0/default/libnetdevice/Android.bp b/automotive/can/1.0/default/libnetdevice/Android.bp
index 31e5ad0..d49b9ab 100644
--- a/automotive/can/1.0/default/libnetdevice/Android.bp
+++ b/automotive/can/1.0/default/libnetdevice/Android.bp
@@ -20,11 +20,27 @@
     vendor_available: true,
     relative_install_path: "hw",
     srcs: [
+        "protocols/common/Empty.cpp",
+        "protocols/common/Error.cpp",
+        "protocols/generic/Ctrl.cpp",
+        "protocols/generic/Generic.cpp",
+        "protocols/generic/GenericMessageBase.cpp",
+        "protocols/generic/Unknown.cpp",
+        "protocols/route/Link.cpp",
+        "protocols/route/Route.cpp",
+        "protocols/route/structs.cpp",
+        "protocols/MessageDefinition.cpp",
+        "protocols/NetlinkProtocol.cpp",
+        "protocols/all.cpp",
         "NetlinkRequest.cpp",
         "NetlinkSocket.cpp",
         "can.cpp",
         "common.cpp",
+        "ethtool.cpp",
+        "ifreqs.cpp",
         "libnetdevice.cpp",
+        "printer.cpp",
+        "vlan.cpp",
     ],
     export_include_dirs: ["include"],
 }
diff --git a/automotive/can/1.0/default/libnetdevice/NetlinkRequest.cpp b/automotive/can/1.0/default/libnetdevice/NetlinkRequest.cpp
index 556debf..4c06f7c 100644
--- a/automotive/can/1.0/default/libnetdevice/NetlinkRequest.cpp
+++ b/automotive/can/1.0/default/libnetdevice/NetlinkRequest.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "NetlinkRequest.h"
+#include <libnetdevice/NetlinkRequest.h>
 
 #include <android-base/logging.h>
 
diff --git a/automotive/can/1.0/default/libnetdevice/NetlinkSocket.cpp b/automotive/can/1.0/default/libnetdevice/NetlinkSocket.cpp
index 7817169..91149c0 100644
--- a/automotive/can/1.0/default/libnetdevice/NetlinkSocket.cpp
+++ b/automotive/can/1.0/default/libnetdevice/NetlinkSocket.cpp
@@ -14,13 +14,21 @@
  * limitations under the License.
  */
 
-#include "NetlinkSocket.h"
+#include <libnetdevice/NetlinkSocket.h>
+
+#include <libnetdevice/printer.h>
 
 #include <android-base/logging.h>
 
 namespace android::netdevice {
 
-NetlinkSocket::NetlinkSocket(int protocol) {
+/**
+ * Print all outbound/inbound Netlink messages.
+ */
+static constexpr bool kSuperVerbose = false;
+
+NetlinkSocket::NetlinkSocket(int protocol, unsigned int pid, uint32_t groups)
+    : mProtocol(protocol) {
     mFd.reset(socket(AF_NETLINK, SOCK_RAW, protocol));
     if (!mFd.ok()) {
         PLOG(ERROR) << "Can't open Netlink socket";
@@ -28,29 +36,37 @@
         return;
     }
 
-    struct sockaddr_nl sa = {};
+    sockaddr_nl sa = {};
     sa.nl_family = AF_NETLINK;
+    sa.nl_pid = pid;
+    sa.nl_groups = groups;
 
-    if (bind(mFd.get(), reinterpret_cast<struct sockaddr*>(&sa), sizeof(sa)) < 0) {
+    if (bind(mFd.get(), reinterpret_cast<sockaddr*>(&sa), sizeof(sa)) < 0) {
         PLOG(ERROR) << "Can't bind Netlink socket";
         mFd.reset();
         mFailed = true;
     }
 }
 
-bool NetlinkSocket::send(struct nlmsghdr* nlmsg) {
+bool NetlinkSocket::send(nlmsghdr* nlmsg, size_t totalLen) {
+    if constexpr (kSuperVerbose) {
+        nlmsg->nlmsg_seq = mSeq;
+        LOG(VERBOSE) << (mFailed ? "(not) " : "")
+                     << "sending Netlink message: " << toString({nlmsg, totalLen}, mProtocol);
+    }
+
     if (mFailed) return false;
 
     nlmsg->nlmsg_pid = 0;  // kernel
     nlmsg->nlmsg_seq = mSeq++;
     nlmsg->nlmsg_flags |= NLM_F_ACK;
 
-    struct iovec iov = {nlmsg, nlmsg->nlmsg_len};
+    iovec iov = {nlmsg, nlmsg->nlmsg_len};
 
-    struct sockaddr_nl sa = {};
+    sockaddr_nl sa = {};
     sa.nl_family = AF_NETLINK;
 
-    struct msghdr msg = {};
+    msghdr msg = {};
     msg.msg_name = &sa;
     msg.msg_namelen = sizeof(sa);
     msg.msg_iov = &iov;
@@ -63,15 +79,65 @@
     return true;
 }
 
+bool NetlinkSocket::send(const nlbuf<nlmsghdr>& msg, const sockaddr_nl& sa) {
+    if constexpr (kSuperVerbose) {
+        LOG(VERBOSE) << (mFailed ? "(not) " : "")
+                     << "sending Netlink message: " << toString(msg, mProtocol);
+    }
+
+    if (mFailed) return false;
+    const auto rawMsg = msg.getRaw();
+    const auto bytesSent = sendto(mFd.get(), rawMsg.ptr(), rawMsg.len(), 0,
+                                  reinterpret_cast<const sockaddr*>(&sa), sizeof(sa));
+    if (bytesSent < 0) {
+        PLOG(ERROR) << "Can't send Netlink message";
+        return false;
+    }
+    return true;
+}
+
+std::optional<nlbuf<nlmsghdr>> NetlinkSocket::receive(void* buf, size_t bufLen) {
+    sockaddr_nl sa = {};
+    return receive(buf, bufLen, sa);
+}
+
+std::optional<nlbuf<nlmsghdr>> NetlinkSocket::receive(void* buf, size_t bufLen, sockaddr_nl& sa) {
+    if (mFailed) return std::nullopt;
+
+    socklen_t saLen = sizeof(sa);
+    if (bufLen == 0) {
+        LOG(ERROR) << "Receive buffer has zero size!";
+        return std::nullopt;
+    }
+    const auto bytesReceived =
+            recvfrom(mFd.get(), buf, bufLen, MSG_TRUNC, reinterpret_cast<sockaddr*>(&sa), &saLen);
+    if (bytesReceived <= 0) {
+        PLOG(ERROR) << "Failed to receive Netlink message";
+        return std::nullopt;
+    } else if (unsigned(bytesReceived) > bufLen) {
+        PLOG(ERROR) << "Received data larger than the receive buffer! " << bytesReceived << " > "
+                    << bufLen;
+        return std::nullopt;
+    }
+
+    nlbuf<nlmsghdr> msg(reinterpret_cast<nlmsghdr*>(buf), bytesReceived);
+    if constexpr (kSuperVerbose) {
+        LOG(VERBOSE) << "received " << toString(msg, mProtocol);
+    }
+    return msg;
+}
+
+/* TODO(161389935): Migrate receiveAck to use nlmsg<> internally. Possibly reuse
+ * NetlinkSocket::receive(). */
 bool NetlinkSocket::receiveAck() {
     if (mFailed) return false;
 
     char buf[8192];
 
-    struct sockaddr_nl sa;
-    struct iovec iov = {buf, sizeof(buf)};
+    sockaddr_nl sa;
+    iovec iov = {buf, sizeof(buf)};
 
-    struct msghdr msg = {};
+    msghdr msg = {};
     msg.msg_name = &sa;
     msg.msg_namelen = sizeof(sa);
     msg.msg_iov = &iov;
@@ -89,8 +155,13 @@
         return false;
     }
 
-    for (auto nlmsg = reinterpret_cast<struct nlmsghdr*>(buf); NLMSG_OK(nlmsg, remainingLen);
+    for (auto nlmsg = reinterpret_cast<nlmsghdr*>(buf); NLMSG_OK(nlmsg, remainingLen);
          nlmsg = NLMSG_NEXT(nlmsg, remainingLen)) {
+        if constexpr (kSuperVerbose) {
+            LOG(VERBOSE) << "received Netlink response: "
+                         << toString({nlmsg, nlmsg->nlmsg_len}, mProtocol);
+        }
+
         // We're looking for error/ack message only, ignoring others.
         if (nlmsg->nlmsg_type != NLMSG_ERROR) {
             LOG(WARNING) << "Received unexpected Netlink message (ignored): " << nlmsg->nlmsg_type;
@@ -98,9 +169,9 @@
         }
 
         // Found error/ack message, return status.
-        auto nlerr = reinterpret_cast<struct nlmsgerr*>(NLMSG_DATA(nlmsg));
+        const auto nlerr = reinterpret_cast<nlmsgerr*>(NLMSG_DATA(nlmsg));
         if (nlerr->error != 0) {
-            LOG(ERROR) << "Received Netlink error message: " << nlerr->error;
+            LOG(ERROR) << "Received Netlink error message: " << strerror(-nlerr->error);
             return false;
         }
         return true;
@@ -109,4 +180,14 @@
     return false;
 }
 
+std::optional<unsigned int> NetlinkSocket::getSocketPid() {
+    sockaddr_nl sa = {};
+    socklen_t sasize = sizeof(sa);
+    if (getsockname(mFd.get(), reinterpret_cast<sockaddr*>(&sa), &sasize) < 0) {
+        PLOG(ERROR) << "Failed to getsockname() for netlink_fd!";
+        return std::nullopt;
+    }
+    return sa.nl_pid;
+}
+
 }  // namespace android::netdevice
diff --git a/automotive/can/1.0/default/libnetdevice/NetlinkSocket.h b/automotive/can/1.0/default/libnetdevice/NetlinkSocket.h
deleted file mode 100644
index 2b40ea2..0000000
--- a/automotive/can/1.0/default/libnetdevice/NetlinkSocket.h
+++ /dev/null
@@ -1,66 +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.
- */
-
-#pragma once
-
-#include "NetlinkRequest.h"
-
-#include <android-base/macros.h>
-#include <android-base/unique_fd.h>
-
-#include <linux/netlink.h>
-
-namespace android::netdevice {
-
-/**
- * A wrapper around AF_NETLINK sockets.
- *
- * This class is not thread safe to use a single instance between multiple threads, but it's fine to
- * use multiple instances over multiple threads.
- */
-struct NetlinkSocket {
-    NetlinkSocket(int protocol);
-
-    /**
-     * Send Netlink message to Kernel.
-     *
-     * \param msg Message to send, nlmsg_seq will be set to next sequence number
-     * \return true, if succeeded
-     */
-    template <class T, unsigned int BUFSIZE>
-    bool send(NetlinkRequest<T, BUFSIZE>& req) {
-        if (!req.isGood()) return false;
-        return send(req.header());
-    }
-
-    /**
-     * Receive Netlink ACK message from Kernel.
-     *
-     * \return true if received ACK message, false in case of error
-     */
-    bool receiveAck();
-
-  private:
-    uint32_t mSeq = 0;
-    base::unique_fd mFd;
-    bool mFailed = false;
-
-    bool send(struct nlmsghdr* msg);
-
-    DISALLOW_COPY_AND_ASSIGN(NetlinkSocket);
-};
-
-}  // namespace android::netdevice
diff --git a/automotive/can/1.0/default/libnetdevice/can.cpp b/automotive/can/1.0/default/libnetdevice/can.cpp
index a2a85dc..b0a2432 100644
--- a/automotive/can/1.0/default/libnetdevice/can.cpp
+++ b/automotive/can/1.0/default/libnetdevice/can.cpp
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-#include <libnetdevice/libnetdevice.h>
+#include <libnetdevice/can.h>
 
-#include "NetlinkRequest.h"
-#include "NetlinkSocket.h"
 #include "common.h"
 
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
+#include <libnetdevice/NetlinkRequest.h>
+#include <libnetdevice/NetlinkSocket.h>
 
 #include <linux/can.h>
 #include <linux/can/error.h>
diff --git a/automotive/can/1.0/default/libnetdevice/common.cpp b/automotive/can/1.0/default/libnetdevice/common.cpp
index 5c62443..f2968fc 100644
--- a/automotive/can/1.0/default/libnetdevice/common.cpp
+++ b/automotive/can/1.0/default/libnetdevice/common.cpp
@@ -26,11 +26,33 @@
     const auto ifidx = if_nametoindex(ifname.c_str());
     if (ifidx != 0) return ifidx;
 
-    const auto err = errno;
-    if (err != ENODEV) {
-        LOG(ERROR) << "if_nametoindex(" << ifname << ") failed: " << err;
+    if (errno != ENODEV) {
+        PLOG(ERROR) << "if_nametoindex(" << ifname << ") failed";
     }
     return 0;
 }
 
+std::string sanitize(std::string str) {
+    str.erase(std::find(str.begin(), str.end(), '\0'), str.end());
+
+    const auto isInvalid = [](char c) { return !isprint(c); };
+    std::replace_if(str.begin(), str.end(), isInvalid, '?');
+
+    return str;
+}
+
+uint16_t crc16(const nlbuf<uint8_t> data, uint16_t crc) {
+    for (const auto byte : data.getRaw()) {
+        crc ^= byte;
+        for (unsigned i = 0; i < 8; i++) {
+            if (crc & 1) {
+                crc = (crc >> 1) ^ 0xA001;
+            } else {
+                crc >>= 1;
+            }
+        }
+    }
+    return crc;
+}
+
 }  // namespace android::netdevice
diff --git a/automotive/can/1.0/default/libnetdevice/common.h b/automotive/can/1.0/default/libnetdevice/common.h
index 8097f37..1e0d5b7 100644
--- a/automotive/can/1.0/default/libnetdevice/common.h
+++ b/automotive/can/1.0/default/libnetdevice/common.h
@@ -16,6 +16,11 @@
 
 #pragma once
 
+#include <libnetdevice/nlbuf.h>
+
+#include <linux/can.h>
+#include <net/if.h>
+
 #include <string>
 
 namespace android::netdevice {
@@ -31,4 +36,24 @@
  */
 unsigned int nametoindex(const std::string& ifname);
 
+/**
+ * Sanitize a string of unknown contents.
+ *
+ * Trims the string to the first '\0' character and replaces all non-printable characters with '?'.
+ */
+std::string sanitize(std::string str);
+
+/**
+ * Calculates a (optionally running) CRC16 checksum.
+ *
+ * CRC16 isn't a strong checksum, but is good for quick comparison purposes.
+ * One benefit (and also a drawback too) is that all-zero payloads with any length will
+ * always have a checksum of 0x0000.
+ *
+ * \param data Buffer to calculate checksum for
+ * \param crc Previous CRC16 value to continue calculating running checksum
+ * \return CRC16 checksum
+ */
+uint16_t crc16(const nlbuf<uint8_t> data, uint16_t crc = 0);
+
 }  // namespace android::netdevice
diff --git a/automotive/can/1.0/default/libnetdevice/ethtool.cpp b/automotive/can/1.0/default/libnetdevice/ethtool.cpp
new file mode 100644
index 0000000..762ef5c
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/ethtool.cpp
@@ -0,0 +1,47 @@
+/*
+ * 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 <libnetdevice/ethtool.h>
+
+#include "ifreqs.h"
+
+#include <linux/ethtool.h>
+
+namespace android::netdevice::ethtool {
+
+std::optional<uint32_t> getValue(const std::string& ifname, uint32_t command) {
+    struct ethtool_value valueop = {};
+    valueop.cmd = command;
+
+    auto ifr = ifreqs::fromName(ifname);
+    ifr.ifr_data = &valueop;
+
+    if (!ifreqs::send(SIOCETHTOOL, ifr)) return std::nullopt;
+    return valueop.data;
+}
+
+bool setValue(const std::string& ifname, uint32_t command, uint32_t value) {
+    struct ethtool_value valueop = {};
+    valueop.cmd = command;
+    valueop.data = value;
+
+    auto ifr = ifreqs::fromName(ifname);
+    ifr.ifr_data = &valueop;
+
+    return ifreqs::send(SIOCETHTOOL, ifr);
+}
+
+}  // namespace android::netdevice::ethtool
diff --git a/automotive/can/1.0/default/libnetdevice/ifreqs.cpp b/automotive/can/1.0/default/libnetdevice/ifreqs.cpp
new file mode 100644
index 0000000..8df6434
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/ifreqs.cpp
@@ -0,0 +1,72 @@
+/*
+ * 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 "ifreqs.h"
+
+#include "common.h"
+
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+
+#include <map>
+
+namespace android::netdevice::ifreqs {
+
+static constexpr int defaultSocketDomain = AF_INET;
+std::atomic_int socketDomain = defaultSocketDomain;
+
+struct SocketParams {
+    int domain;
+    int type;
+    int protocol;
+};
+
+static const std::map<int, SocketParams> socketParams = {
+        {AF_INET, {AF_INET, SOCK_DGRAM, 0}},
+        {AF_CAN, {AF_CAN, SOCK_RAW, CAN_RAW}},
+};
+
+static SocketParams getSocketParams(int domain) {
+    if (socketParams.count(domain)) return socketParams.find(domain)->second;
+
+    auto params = socketParams.find(defaultSocketDomain)->second;
+    params.domain = domain;
+    return params;
+}
+
+bool send(unsigned long request, struct ifreq& ifr) {
+    const auto sp = getSocketParams(socketDomain);
+    base::unique_fd sock(socket(sp.domain, sp.type, sp.protocol));
+    if (!sock.ok()) {
+        LOG(ERROR) << "Can't create socket";
+        return false;
+    }
+
+    if (ioctl(sock.get(), request, &ifr) < 0) {
+        PLOG(ERROR) << "ioctl(" << std::hex << request << std::dec << ") failed";
+        return false;
+    }
+
+    return true;
+}
+
+struct ifreq fromName(const std::string& ifname) {
+    struct ifreq ifr = {};
+    strlcpy(ifr.ifr_name, ifname.c_str(), IF_NAMESIZE);
+    return ifr;
+}
+
+}  // namespace android::netdevice::ifreqs
diff --git a/automotive/can/1.0/default/libnetdevice/ifreqs.h b/automotive/can/1.0/default/libnetdevice/ifreqs.h
new file mode 100644
index 0000000..74e5877
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/ifreqs.h
@@ -0,0 +1,47 @@
+/*
+ * 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 <net/if.h>
+
+#include <string>
+
+namespace android::netdevice::ifreqs {
+
+/**
+ * \see useSocketDomain()
+ */
+extern std::atomic_int socketDomain;
+
+/**
+ * Sends ioctl interface request.
+ *
+ * \param request Request type (such as SIOCGIFFLAGS)
+ * \param ifr Request data (both input and output)
+ * \return true if the call succeeded, false otherwise
+ */
+bool send(unsigned long request, struct ifreq& ifr);
+
+/**
+ * Initializes interface request with interface name.
+ *
+ * \param ifname Interface to initialize request with
+ * \return Interface request with ifr_name field set to ifname
+ */
+struct ifreq fromName(const std::string& ifname);
+
+}  // namespace android::netdevice::ifreqs
diff --git a/automotive/can/1.0/default/libnetdevice/NetlinkRequest.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/NetlinkRequest.h
similarity index 94%
rename from automotive/can/1.0/default/libnetdevice/NetlinkRequest.h
rename to automotive/can/1.0/default/libnetdevice/include/libnetdevice/NetlinkRequest.h
index 3e28d78..c19d04d 100644
--- a/automotive/can/1.0/default/libnetdevice/NetlinkRequest.h
+++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/NetlinkRequest.h
@@ -17,18 +17,18 @@
 #pragma once
 
 #include <android-base/macros.h>
+#include <libnetdevice/types.h>
+
 #include <linux/rtnetlink.h>
 
 #include <string>
 
 namespace android::netdevice {
 
-typedef unsigned short rtattrtype_t;  // as in rtnetlink.h
-typedef __u16 nlmsgtype_t;            // as in netlink.h
-
 /** Implementation details, do not use outside NetlinkRequest template. */
 namespace impl {
 
+// TODO(twasilczyk): use nlattr instead of rtattr
 struct rtattr* addattr_l(struct nlmsghdr* n, size_t maxLen, rtattrtype_t type, const void* data,
                          size_t dataLen);
 struct rtattr* addattr_nest(struct nlmsghdr* n, size_t maxLen, rtattrtype_t type);
@@ -36,6 +36,7 @@
 
 }  // namespace impl
 
+// TODO(twasilczyk): rename to NetlinkMessage
 /**
  * Wrapper around NETLINK_ROUTE messages, to build them in C++ style.
  *
@@ -44,6 +45,14 @@
  */
 template <class T, unsigned int BUFSIZE = 128>
 struct NetlinkRequest {
+    struct RequestData {
+        struct nlmsghdr nlmsg;
+        T data;
+        char buf[BUFSIZE];
+    };
+
+    static constexpr size_t totalLength = sizeof(RequestData);
+
     /**
      * Create empty message.
      *
@@ -131,12 +140,7 @@
 
   private:
     bool mIsGood = true;
-
-    struct {
-        struct nlmsghdr nlmsg;
-        T data;
-        char buf[BUFSIZE];
-    } mRequest = {};
+    RequestData mRequest = {};
 
     struct rtattr* nestStart(rtattrtype_t type) {
         if (!mIsGood) return nullptr;
diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/NetlinkSocket.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/NetlinkSocket.h
new file mode 100644
index 0000000..826b6b8
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/NetlinkSocket.h
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android-base/macros.h>
+#include <android-base/unique_fd.h>
+#include <libnetdevice/NetlinkRequest.h>
+#include <libnetdevice/nlbuf.h>
+
+#include <linux/netlink.h>
+
+#include <optional>
+
+namespace android::netdevice {
+
+/**
+ * A wrapper around AF_NETLINK sockets.
+ *
+ * This class is not thread safe to use a single instance between multiple threads, but it's fine to
+ * use multiple instances over multiple threads.
+ */
+struct NetlinkSocket {
+    /**
+     * NetlinkSocket constructor.
+     *
+     * \param protocol the Netlink protocol to use.
+     * \param pid port id. Default value of 0 allows the kernel to assign us a unique pid. (NOTE:
+     * this is NOT the same as process id!)
+     * \param groups Netlink multicast groups to listen to. This is a 32-bit bitfield, where each
+     * bit is a different group. Default value of 0 means no groups are selected. See man netlink.7
+     * for more details.
+     */
+    NetlinkSocket(int protocol, unsigned int pid = 0, uint32_t groups = 0);
+
+    /**
+     * Send Netlink message to Kernel. The sequence number will be automatically incremented, and
+     * the NLM_F_ACK (request ACK) flag will be set.
+     *
+     * \param msg Message to send.
+     * \return true, if succeeded
+     */
+    template <class T, unsigned int BUFSIZE>
+    bool send(NetlinkRequest<T, BUFSIZE>& req) {
+        if (!req.isGood()) return false;
+        return send(req.header(), req.totalLength);
+    }
+
+    /**
+     * Send Netlink message. The message will be sent as is, without any modification.
+     *
+     * \param msg Message to send.
+     * \param sa Destination address.
+     * \return true, if succeeded
+     */
+    bool send(const nlbuf<nlmsghdr>& msg, const sockaddr_nl& sa);
+
+    /**
+     * Receive Netlink data.
+     *
+     * \param buf buffer to hold message data.
+     * \param bufLen length of buf.
+     * \return nlbuf with message data, std::nullopt on error.
+     */
+    std::optional<nlbuf<nlmsghdr>> receive(void* buf, size_t bufLen);
+
+    /**
+     * Receive Netlink data with address info.
+     *
+     * \param buf buffer to hold message data.
+     * \param bufLen length of buf.
+     * \param sa Blank struct that recvfrom will populate with address info.
+     * \return nlbuf with message data, std::nullopt on error.
+     */
+    std::optional<nlbuf<nlmsghdr>> receive(void* buf, size_t bufLen, sockaddr_nl& sa);
+
+    /**
+     * Receive Netlink ACK message from Kernel.
+     *
+     * \return true if received ACK message, false in case of error
+     */
+    bool receiveAck();
+
+    /**
+     * Gets the PID assigned to mFd.
+     *
+     * \return pid that mSocket is bound to.
+     */
+    std::optional<unsigned int> getSocketPid();
+
+  private:
+    const int mProtocol;
+
+    uint32_t mSeq = 0;
+    base::unique_fd mFd;
+    bool mFailed = false;
+
+    bool send(nlmsghdr* msg, size_t totalLen);
+
+    DISALLOW_COPY_AND_ASSIGN(NetlinkSocket);
+};
+
+}  // namespace android::netdevice
diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/ethtool.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/ethtool.h
new file mode 100644
index 0000000..26bfdce
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/ethtool.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <optional>
+#include <string>
+
+namespace android::netdevice::ethtool {
+
+/**
+ * Fetch a single value with ethtool_value.
+ *
+ * \see linux/ethtool.h
+ * \param ifname Interface to fetch data for
+ * \param command Fetch command (ETHTOOL_G*)
+ * \return value, or nullopt if fetch failed
+ */
+std::optional<uint32_t> getValue(const std::string& ifname, uint32_t command);
+
+/**
+ * Set a single value with ethtool_value.
+ *
+ * \see linux/ethtool.h
+ * \param ifname Interface to set data for
+ * \param command Set command (ETHTOOL_S*)
+ * \param value New value
+ * \return true if succeeded, false otherwise
+ */
+bool setValue(const std::string& ifname, uint32_t command, uint32_t value);
+
+}  // namespace android::netdevice::ethtool
diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h
index 3818a31..9a26ff1 100644
--- a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h
+++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/libnetdevice.h
@@ -16,11 +16,26 @@
 
 #pragma once
 
+#include <linux/if_ether.h>
+
+#include <array>
 #include <optional>
 #include <string>
 
 namespace android::netdevice {
 
+typedef std::array<uint8_t, ETH_ALEN> hwaddr_t;
+
+/**
+ * Configures libnetdevice to use other socket domain than AF_INET,
+ * what requires less permissive SEPolicy rules for a given process.
+ *
+ * In such case, the process would only be able to control interfaces of a given kind.
+
+ * \param domain Socket domain to use (e.g. AF_CAN), see socket(2) for details
+ */
+void useSocketDomain(int domain);
+
 /**
  * Checks, if the network interface exists.
  *
@@ -38,6 +53,16 @@
 std::optional<bool> isUp(std::string ifname);
 
 /**
+ * Checks, if the network interface exists and is up.
+ *
+ * This is a convenience function to call both exists() and isUp().
+ *
+ * \param ifname Interface to check
+ * \return true if the interface is up, false otherwise
+ */
+bool existsAndIsUp(const std::string& ifname);
+
+/**
  * Brings network interface up.
  *
  * \param ifname Interface to bring up
@@ -70,4 +95,22 @@
  */
 bool del(std::string dev);
 
+/**
+ * Fetches interface's hardware address.
+ *
+ * \param ifname Interface name
+ * \return Hardware address (MAC address) or nullopt if the lookup failed
+ */
+std::optional<hwaddr_t> getHwAddr(const std::string& ifname);
+
+/**
+ * Changes interface's hardware address.
+ *
+ * \param ifname Interface name
+ * \param hwaddr New hardware address to set
+ */
+bool setHwAddr(const std::string& ifname, hwaddr_t hwaddr);
+
 }  // namespace android::netdevice
+
+bool operator==(const android::netdevice::hwaddr_t lhs, const unsigned char rhs[ETH_ALEN]);
diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/nlbuf.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/nlbuf.h
new file mode 100644
index 0000000..601ab94
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/nlbuf.h
@@ -0,0 +1,202 @@
+/*
+ * 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/logging.h>
+
+#include <linux/netlink.h>
+
+#include <optional>
+
+namespace android::netdevice {
+
+/**
+ * Buffer containing netlink structure (e.g. struct nlmsghdr, struct nlattr).
+ *
+ * This is a C++-style, memory safe(r) and generic implementation of linux/netlink.h macros.
+ *
+ * While netlink structures contain information about their total length (with payload), they can
+ * not be trusted - the value may either be larger than the buffer message is allocated in or
+ * smaller than the header itself (so it couldn't even fit itself).
+ *
+ * As a solution, nlbuf<> keeps track of two lengths (both attribute for header with payload):
+ * - buffer length - how much memory was allocated to a given structure
+ * - declared length - what nlmsg_len or nla_len says how long the structure is
+ *
+ * In most cases buffer length would be larger than declared length (or equal - modulo alignment -
+ * for continuous data). If that's not the case, there is a potential of ouf-of-bounds read which
+ * this template attempts to protect against.
+ */
+template <typename T>
+class nlbuf {
+    // The following definitions are C++ equivalents of NLMSG_* macros from linux/netlink.h
+
+    static constexpr size_t alignto = NLMSG_ALIGNTO;
+    static_assert(NLMSG_ALIGNTO == NLA_ALIGNTO);
+
+    static constexpr size_t align(size_t ptr) { return (ptr + alignto - 1) & ~(alignto - 1); }
+
+    static constexpr size_t hdrlen = align(sizeof(T));
+
+  public:
+    /**
+     * Constructor for nlbuf.
+     *
+     * \param data A pointer to the data the nlbuf wraps.
+     * \param bufferLen Length of buffer.
+     */
+    nlbuf(const T* data, size_t bufferLen) : mData(data), mBufferEnd(pointerAdd(data, bufferLen)) {}
+
+    const T* operator->() const {
+        CHECK(firstOk()) << "buffer can't fit the first element's header";
+        return mData;
+    }
+
+    std::pair<bool, const T&> getFirst() const {
+        if (!ok()) {
+            static const T dummy = {};
+            return {false, dummy};
+        }
+        return {true, *mData};
+    }
+
+    /**
+     * Copy the first element of the buffer.
+     *
+     * This is a memory-safe cast operation, useful for reading e.g. uint32_t values
+     * from 1-byte buffer.
+     */
+    T copyFirst() const {
+        T val = {};
+        memcpy(&val, mData, std::min(sizeof(val), remainingLength()));
+        return val;
+    }
+
+    bool firstOk() const { return sizeof(T) <= remainingLength(); }
+
+    template <typename D>
+    const nlbuf<D> data(size_t offset = 0) const {
+        // Equivalent to NLMSG_DATA(hdr) + NLMSG_ALIGN(offset)
+        const D* dptr = reinterpret_cast<const D*>(uintptr_t(mData) + hdrlen + align(offset));
+        return {dptr, dataEnd()};
+    }
+
+    class iterator {
+      public:
+        iterator() : mCurrent(nullptr, size_t(0)) {
+            CHECK(!mCurrent.ok()) << "end() iterator should indicate it's beyond end";
+        }
+        iterator(const nlbuf<T>& buf) : mCurrent(buf) {}
+
+        iterator operator++() {
+            // mBufferEnd stays the same
+            mCurrent.mData = reinterpret_cast<const T*>(  //
+                    uintptr_t(mCurrent.mData) + align(mCurrent.declaredLength()));
+
+            return *this;
+        }
+
+        bool operator==(const iterator& other) const {
+            // all iterators beyond end are the same
+            if (!mCurrent.ok() && !other.mCurrent.ok()) return true;
+
+            return uintptr_t(other.mCurrent.mData) == uintptr_t(mCurrent.mData);
+        }
+
+        const nlbuf<T>& operator*() const { return mCurrent; }
+
+      protected:
+        nlbuf<T> mCurrent;
+    };
+    iterator begin() const { return {*this}; }
+    iterator end() const { return {}; }
+
+    class raw_iterator : public iterator {
+      public:
+        iterator operator++() {
+            this->mCurrent.mData++;  // ignore alignment
+            return *this;
+        }
+        const T& operator*() const { return *this->mCurrent.mData; }
+    };
+
+    class raw_view {
+      public:
+        raw_view(const nlbuf<T>& buffer) : mBuffer(buffer) {}
+        raw_iterator begin() const { return {mBuffer}; }
+        raw_iterator end() const { return {}; }
+
+        const T* ptr() const { return mBuffer.mData; }
+        size_t len() const { return mBuffer.remainingLength(); }
+
+      private:
+        const nlbuf<T> mBuffer;
+    };
+
+    raw_view getRaw() const { return {*this}; }
+
+  private:
+    const T* mData;
+    const void* mBufferEnd;
+
+    nlbuf(const T* data, const void* bufferEnd) : mData(data), mBufferEnd(bufferEnd) {}
+
+    bool ok() const { return declaredLength() <= remainingLength(); }
+
+    // to be specialized individually for each T with payload after a header
+    inline size_t declaredLengthImpl() const { return sizeof(T); }
+
+    size_t declaredLength() const {
+        // We can't even fit a header, so let's return some absurd high value to trip off
+        // buffer overflow checks.
+        static constexpr size_t badHeaderLength = std::numeric_limits<size_t>::max() / 2;
+
+        if (sizeof(T) > remainingLength()) return badHeaderLength;
+        const auto len = declaredLengthImpl();
+        if (sizeof(T) > len) return badHeaderLength;
+        return len;
+    }
+
+    size_t remainingLength() const {
+        auto len = intptr_t(mBufferEnd) - intptr_t(mData);
+        return (len >= 0) ? len : 0;
+    }
+
+    const void* dataEnd() const {
+        auto declaredEnd = pointerAdd(mData, declaredLength());
+        return std::min(declaredEnd, mBufferEnd);
+    }
+
+    static const void* pointerAdd(const void* ptr, size_t len) {
+        return reinterpret_cast<const void*>(uintptr_t(ptr) + len);
+    }
+
+    template <typename D>
+    friend class nlbuf;  // calling private constructor of data buffers
+};
+
+template <>
+inline size_t nlbuf<nlmsghdr>::declaredLengthImpl() const {
+    return mData->nlmsg_len;
+}
+
+template <>
+inline size_t nlbuf<nlattr>::declaredLengthImpl() const {
+    return mData->nla_len;
+}
+
+}  // namespace android::netdevice
diff --git a/automotive/can/1.0/default/libnetdevice/include/libnetdevice/printer.h b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/printer.h
new file mode 100644
index 0000000..071fa63
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/printer.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 <libnetdevice/nlbuf.h>
+
+#include <linux/netlink.h>
+
+#include <string>
+
+namespace android::netdevice {
+
+/**
+ * Stringify a Netlink message.
+ *
+ * \param hdr Pointer to the message(s) to print.
+ * \param protocol Which Netlink protocol hdr uses.
+ * \param printPayload True will stringify message data, false will only stringify the header(s).
+ * \return Stringified message.
+ */
+std::string toString(const nlbuf<nlmsghdr> hdr, int protocol, bool printPayload = false);
+
+}  // namespace android::netdevice
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/types.h
similarity index 67%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to automotive/can/1.0/default/libnetdevice/include/libnetdevice/types.h
index 7edec47..9d90c8a 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/types.h
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#pragma once
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+#include <linux/types.h>
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+namespace android::netdevice {
+
+typedef __u16 nlmsgtype_t;            // nlmsghdr::nlmsg_type
+typedef __u16 nlattrtype_t;           // nlattr::nla_type
+typedef unsigned short rtattrtype_t;  // rtattr::rta_type
+
+}  // namespace android::netdevice
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/vlan.h
similarity index 69%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to automotive/can/1.0/default/libnetdevice/include/libnetdevice/vlan.h
index 7edec47..3e1b736 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/automotive/can/1.0/default/libnetdevice/include/libnetdevice/vlan.h
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#pragma once
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+#include <string>
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+namespace android::netdevice::vlan {
+
+bool add(const std::string& eth, const std::string& vlan, uint16_t id);
+
+}  // namespace android::netdevice::vlan
diff --git a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
index b051442..4293cad 100644
--- a/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
+++ b/automotive/can/1.0/default/libnetdevice/libnetdevice.cpp
@@ -16,62 +16,48 @@
 
 #include <libnetdevice/libnetdevice.h>
 
-#include "NetlinkRequest.h"
-#include "NetlinkSocket.h"
 #include "common.h"
+#include "ifreqs.h"
 
 #include <android-base/logging.h>
+#include <libnetdevice/NetlinkRequest.h>
+#include <libnetdevice/NetlinkSocket.h>
 
 #include <linux/can.h>
 #include <net/if.h>
 
 namespace android::netdevice {
 
+void useSocketDomain(int domain) {
+    ifreqs::socketDomain = domain;
+}
+
 bool exists(std::string ifname) {
     return nametoindex(ifname) != 0;
 }
 
-static bool sendIfreq(unsigned long request, struct ifreq& ifr) {
-    /* For general interfaces it would be socket(AF_INET, SOCK_DGRAM, 0),
-     * but SEPolicy forces us to limit our flexibility here. */
-    base::unique_fd sock(socket(PF_CAN, SOCK_RAW, CAN_RAW));
-    if (!sock.ok()) {
-        LOG(ERROR) << "Can't create socket";
-        return false;
-    }
-
-    if (ioctl(sock.get(), request, &ifr) < 0) {
-        PLOG(ERROR) << "ioctl(" << std::hex << request << std::dec << ") failed";
-        return false;
-    }
-
-    return true;
-}
-
-static struct ifreq ifreqFromName(const std::string& ifname) {
-    struct ifreq ifr = {};
-    strlcpy(ifr.ifr_name, ifname.c_str(), IF_NAMESIZE);
-    return ifr;
-}
-
 std::optional<bool> isUp(std::string ifname) {
-    struct ifreq ifr = ifreqFromName(ifname);
-    if (!sendIfreq(SIOCGIFFLAGS, ifr)) return std::nullopt;
+    auto ifr = ifreqs::fromName(ifname);
+    if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return std::nullopt;
     return ifr.ifr_flags & IFF_UP;
 }
 
+bool existsAndIsUp(const std::string& ifname) {
+    return exists(ifname) && isUp(ifname).value_or(false);
+}
+
 bool up(std::string ifname) {
-    struct ifreq ifr = ifreqFromName(ifname);
-    if (!sendIfreq(SIOCGIFFLAGS, ifr)) return false;
+    auto ifr = ifreqs::fromName(ifname);
+    if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return false;
     ifr.ifr_flags |= IFF_UP;
-    return sendIfreq(SIOCSIFFLAGS, ifr);
+    return ifreqs::send(SIOCSIFFLAGS, ifr);
 }
 
 bool down(std::string ifname) {
-    struct ifreq ifr = ifreqFromName(ifname);
-    if (!sendIfreq(SIOCGIFFLAGS, ifr)) return false;
+    auto ifr = ifreqs::fromName(ifname);
+    if (!ifreqs::send(SIOCGIFFLAGS, ifr)) return false;
     ifr.ifr_flags &= ~IFF_UP;
-    return sendIfreq(SIOCSIFFLAGS, ifr);
+    return ifreqs::send(SIOCSIFFLAGS, ifr);
 }
 
 bool add(std::string dev, std::string type) {
@@ -95,4 +81,28 @@
     return sock.send(req) && sock.receiveAck();
 }
 
+std::optional<hwaddr_t> getHwAddr(const std::string& ifname) {
+    auto ifr = ifreqs::fromName(ifname);
+    if (!ifreqs::send(SIOCGIFHWADDR, ifr)) return std::nullopt;
+
+    hwaddr_t hwaddr;
+    memcpy(hwaddr.data(), ifr.ifr_hwaddr.sa_data, hwaddr.size());
+    return hwaddr;
+}
+
+bool setHwAddr(const std::string& ifname, hwaddr_t hwaddr) {
+    auto ifr = ifreqs::fromName(ifname);
+
+    // fetch sa_family
+    if (!ifreqs::send(SIOCGIFHWADDR, ifr)) return false;
+
+    memcpy(ifr.ifr_hwaddr.sa_data, hwaddr.data(), hwaddr.size());
+    return ifreqs::send(SIOCSIFHWADDR, ifr);
+}
+
 }  // namespace android::netdevice
+
+bool operator==(const android::netdevice::hwaddr_t lhs, const unsigned char rhs[ETH_ALEN]) {
+    static_assert(lhs.size() == ETH_ALEN);
+    return 0 == memcmp(lhs.data(), rhs, lhs.size());
+}
diff --git a/automotive/can/1.0/default/libnetdevice/printer.cpp b/automotive/can/1.0/default/libnetdevice/printer.cpp
new file mode 100644
index 0000000..179d501
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/printer.cpp
@@ -0,0 +1,177 @@
+/*
+ * 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 <libnetdevice/printer.h>
+
+#include "common.h"
+#include "protocols/all.h"
+
+#include <android-base/logging.h>
+#include <libnetdevice/nlbuf.h>
+
+#include <algorithm>
+#include <iomanip>
+#include <sstream>
+
+namespace android::netdevice {
+
+static void flagsToStream(std::stringstream& ss, __u16 nlmsg_flags) {
+    bool first = true;
+    auto printFlag = [&ss, &first, &nlmsg_flags](__u16 flag, const std::string& name) {
+        if (!(nlmsg_flags & flag)) return;
+        nlmsg_flags &= ~flag;
+
+        if (first) {
+            first = false;
+        } else {
+            ss << '|';
+        }
+
+        ss << name;
+    };
+    printFlag(NLM_F_REQUEST, "REQUEST");
+    printFlag(NLM_F_MULTI, "MULTI");
+    printFlag(NLM_F_ACK, "ACK");
+    printFlag(NLM_F_ECHO, "ECHO");
+    printFlag(NLM_F_DUMP_INTR, "DUMP_INTR");
+    printFlag(NLM_F_DUMP_FILTERED, "DUMP_FILTERED");
+
+    // TODO(twasilczyk): print flags depending on request type
+    printFlag(NLM_F_ROOT, "ROOT-REPLACE");
+    printFlag(NLM_F_MATCH, "MATCH-EXCL");
+    printFlag(NLM_F_ATOMIC, "ATOMIC-CREATE");
+    printFlag(NLM_F_APPEND, "APPEND");
+
+    if (nlmsg_flags != 0) {
+        if (!first) ss << '|';
+        ss << std::hex << nlmsg_flags << std::dec;
+    }
+}
+
+static void toStream(std::stringstream& ss, const nlbuf<uint8_t> data) {
+    const auto rawData = data.getRaw();
+    const auto dataLen = rawData.len();
+    ss << std::hex;
+    int i = 0;
+    for (const auto byte : rawData) {
+        if (i % 16 == 0 && dataLen > 16) {
+            ss << std::endl << ' ' << std::dec << std::setw(4) << i << std::hex;
+        }
+        if (i++ > 0 || dataLen > 16) ss << ' ';
+        ss << std::setw(2) << unsigned(byte);
+    }
+    ss << std::dec;
+    if (dataLen > 16) ss << std::endl;
+}
+
+static void toStream(std::stringstream& ss, const nlbuf<nlattr> attr,
+                     const protocols::AttributeMap& attrMap) {
+    using DataType = protocols::AttributeDefinition::DataType;
+    const auto attrtype = attrMap[attr->nla_type];
+
+    ss << attrtype.name << ": ";
+    switch (attrtype.dataType) {
+        case DataType::Raw:
+            toStream(ss, attr.data<uint8_t>());
+            break;
+        case DataType::Nested: {
+            ss << '{';
+            bool first = true;
+            for (const auto childattr : attr.data<nlattr>()) {
+                if (!first) ss << ", ";
+                first = false;
+                toStream(ss, childattr, std::get<protocols::AttributeMap>(attrtype.ops));
+            }
+            ss << '}';
+            break;
+        }
+        case DataType::String: {
+            const auto str = attr.data<char>().getRaw();
+            ss << '"' << sanitize({str.ptr(), str.len()}) << '"';
+            break;
+        }
+        case DataType::Uint:
+            ss << attr.data<uint32_t>().copyFirst();
+            break;
+        case DataType::Struct: {
+            const auto structToStream =
+                    std::get<protocols::AttributeDefinition::ToStream>(attrtype.ops);
+            structToStream(ss, attr);
+            break;
+        }
+    }
+}
+
+std::string toString(const nlbuf<nlmsghdr> hdr, int protocol, bool printPayload) {
+    if (!hdr.firstOk()) return "nlmsg{buffer overflow}";
+
+    std::stringstream ss;
+    ss << std::setfill('0');
+
+    auto protocolMaybe = protocols::get(protocol);
+    if (!protocolMaybe.has_value()) {
+        ss << "nlmsg{protocol=" << protocol << "}";
+        return ss.str();
+    }
+    protocols::NetlinkProtocol& protocolDescr = *protocolMaybe;
+
+    auto msgDescMaybe = protocolDescr.getMessageDescriptor(hdr->nlmsg_type);
+    const auto msgTypeName = msgDescMaybe.has_value()
+                                     ? msgDescMaybe->get().getMessageName(hdr->nlmsg_type)
+                                     : std::to_string(hdr->nlmsg_type);
+
+    ss << "nlmsg{" << protocolDescr.getName() << " ";
+
+    ss << "hdr={";
+    ss << "type=" << msgTypeName;
+    if (hdr->nlmsg_flags != 0) {
+        ss << ", flags=";
+        flagsToStream(ss, hdr->nlmsg_flags);
+    }
+    if (hdr->nlmsg_seq != 0) ss << ", seq=" << hdr->nlmsg_seq;
+    if (hdr->nlmsg_pid != 0) ss << ", pid=" << hdr->nlmsg_pid;
+    ss << ", len=" << hdr->nlmsg_len;
+
+    ss << ", crc=" << std::hex << std::setw(4) << crc16(hdr.data<uint8_t>()) << std::dec;
+    ss << "} ";
+
+    if (!printPayload) return ss.str();
+
+    if (!msgDescMaybe.has_value()) {
+        toStream(ss, hdr.data<uint8_t>());
+    } else {
+        const protocols::MessageDescriptor& msgDesc = *msgDescMaybe;
+        msgDesc.dataToStream(ss, hdr);
+
+        bool first = true;
+        for (auto attr : hdr.data<nlattr>(msgDesc.getContentsSize())) {
+            if (first) {
+                ss << " attributes: {";
+                first = false;
+            } else {
+                ss << ", ";
+            }
+            toStream(ss, attr, msgDesc.getAttributeMap());
+        }
+        if (!first) ss << '}';
+    }
+
+    ss << "}";
+
+    return ss.str();
+}
+
+}  // namespace android::netdevice
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/MessageDefinition.cpp b/automotive/can/1.0/default/libnetdevice/protocols/MessageDefinition.cpp
new file mode 100644
index 0000000..cb42896
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/protocols/MessageDefinition.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 "MessageDefinition.h"
+
+namespace android::netdevice::protocols {
+
+AttributeMap::AttributeMap(const std::initializer_list<value_type> attrTypes)
+    : std::map<std::optional<nlattrtype_t>, AttributeDefinition>(attrTypes) {}
+
+const AttributeDefinition AttributeMap::operator[](nlattrtype_t nla_type) const {
+    if (count(nla_type) == 0) {
+        if (count(std::nullopt) == 0) return {std::to_string(nla_type)};
+
+        auto definition = find(std::nullopt)->second;
+        definition.name += std::to_string(nla_type);
+        return definition;
+    }
+    return find(nla_type)->second;
+}
+
+MessageDescriptor::MessageDescriptor(const std::string& name, const MessageTypeMap&& messageTypes,
+                                     const AttributeMap&& attrTypes, size_t contentsSize)
+    : mName(name),
+      mContentsSize(contentsSize),
+      mMessageTypes(messageTypes),
+      mAttributeMap(attrTypes) {}
+
+MessageDescriptor::~MessageDescriptor() {}
+
+size_t MessageDescriptor::getContentsSize() const {
+    return mContentsSize;
+}
+
+const MessageDescriptor::MessageTypeMap& MessageDescriptor::getMessageTypeMap() const {
+    return mMessageTypes;
+}
+
+const AttributeMap& MessageDescriptor::getAttributeMap() const {
+    return mAttributeMap;
+}
+
+const std::string MessageDescriptor::getMessageName(nlmsgtype_t msgtype) const {
+    const auto it = mMessageTypes.find(msgtype);
+    if (it == mMessageTypes.end()) return "?";
+    return it->second;
+}
+
+}  // namespace android::netdevice::protocols
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/MessageDefinition.h b/automotive/can/1.0/default/libnetdevice/protocols/MessageDefinition.h
new file mode 100644
index 0000000..3a8b2b5
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/protocols/MessageDefinition.h
@@ -0,0 +1,126 @@
+/*
+ * 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 <libnetdevice/nlbuf.h>
+#include <libnetdevice/types.h>
+
+#include <map>
+#include <sstream>
+#include <variant>
+
+namespace android::netdevice::protocols {
+
+struct AttributeDefinition;
+
+/**
+ * Mapping between nlattrtype_t identifier and attribute definition.
+ *
+ * The map contains values for all nlattrtype_t identifiers - if some is missing, a generic
+ * definition with a identifier as its name will be generated.
+ *
+ * It's possible to define a default attribute to return instead of to_string of its identifier
+ * (useful for nested attribute lists). In such case, an entry with id=std::nullopt needs to be
+ * present in the map.
+ */
+class AttributeMap : private std::map<std::optional<nlattrtype_t>, AttributeDefinition> {
+  public:
+    using std::map<std::optional<nlattrtype_t>, AttributeDefinition>::value_type;
+
+    AttributeMap(const std::initializer_list<value_type> attrTypes);
+
+    const AttributeDefinition operator[](nlattrtype_t nla_type) const;
+};
+
+/**
+ * Attribute definition.
+ *
+ * Describes the name and type (optionally sub types, in case of Nested attribute)
+ * for a given message attribute.
+ */
+struct AttributeDefinition {
+    enum class DataType : uint8_t {
+        Raw,
+        Nested,
+        String,
+        Uint,
+        Struct,
+    };
+    using ToStream = std::function<void(std::stringstream& ss, const nlbuf<nlattr> attr)>;
+
+    std::string name;
+    DataType dataType = DataType::Raw;
+    std::variant<AttributeMap, ToStream> ops = AttributeMap{};
+};
+
+/**
+ * Message family descriptor.
+ *
+ * Describes the structure of all message types with the same header and attributes.
+ */
+class MessageDescriptor {
+  protected:
+    typedef std::map<nlmsgtype_t, std::string> MessageTypeMap;
+
+    MessageDescriptor(const std::string& name, const MessageTypeMap&& messageTypes,
+                      const AttributeMap&& attrTypes, size_t contentsSize);
+
+  public:
+    virtual ~MessageDescriptor();
+
+    size_t getContentsSize() const;
+    const MessageTypeMap& getMessageTypeMap() const;
+    const AttributeMap& getAttributeMap() const;
+    const std::string getMessageName(nlmsgtype_t msgtype) const;
+    virtual void dataToStream(std::stringstream& ss, const nlbuf<nlmsghdr> hdr) const = 0;
+
+  private:
+    const std::string mName;
+    const size_t mContentsSize;
+    const MessageTypeMap mMessageTypes;
+    const AttributeMap mAttributeMap;
+};
+
+/**
+ * Message definition template.
+ *
+ * A convenience initialization helper of a message descriptor.
+ */
+template <typename T>
+class MessageDefinition : public MessageDescriptor {
+  public:
+    MessageDefinition(
+            const std::string& name,
+            const std::initializer_list<MessageDescriptor::MessageTypeMap::value_type> messageTypes,
+            const std::initializer_list<AttributeMap::value_type> attrTypes = {})
+        : MessageDescriptor(name, messageTypes, attrTypes, sizeof(T)) {}
+
+    void dataToStream(std::stringstream& ss, const nlbuf<nlmsghdr> hdr) const override {
+        const auto& [ok, msg] = hdr.data<T>().getFirst();
+        if (!ok) {
+            ss << "{incomplete payload}";
+            return;
+        }
+
+        toStream(ss, msg);
+    }
+
+  protected:
+    virtual void toStream(std::stringstream& ss, const T& data) const = 0;
+};
+
+}  // namespace android::netdevice::protocols
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/NetlinkProtocol.cpp b/automotive/can/1.0/default/libnetdevice/protocols/NetlinkProtocol.cpp
new file mode 100644
index 0000000..4b6cefb
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/protocols/NetlinkProtocol.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "NetlinkProtocol.h"
+
+namespace android::netdevice::protocols {
+
+NetlinkProtocol::NetlinkProtocol(int protocol, const std::string name,
+                                 const MessageDescriptorList&& messageDescrs)
+    : mProtocol(protocol), mName(name), mMessageDescrs(toMap(messageDescrs, protocol)) {}
+
+NetlinkProtocol::~NetlinkProtocol() {}
+
+int NetlinkProtocol::getProtocol() const {
+    return mProtocol;
+}
+
+const std::string& NetlinkProtocol::getName() const {
+    return mName;
+}
+
+const std::optional<std::reference_wrapper<const MessageDescriptor>>
+NetlinkProtocol::getMessageDescriptor(nlmsgtype_t nlmsg_type) {
+    if (mMessageDescrs.count(nlmsg_type) == 0) return std::nullopt;
+    return *mMessageDescrs.find(nlmsg_type)->second;
+}
+
+NetlinkProtocol::MessageDescriptorMap NetlinkProtocol::toMap(
+        const NetlinkProtocol::MessageDescriptorList& descrs, int protocol) {
+    MessageDescriptorMap map;
+    for (const auto& descr : descrs) {
+        for (const auto& [mtype, mname] : descr->getMessageTypeMap()) {
+            map.emplace(mtype, descr);
+        }
+    }
+
+    const MessageDescriptorList baseDescriptors = {
+            std::make_shared<base::Empty>(),
+            std::make_shared<base::Error>(protocol),
+    };
+
+    for (const auto& descr : baseDescriptors) {
+        for (const auto& [mtype, mname] : descr->getMessageTypeMap()) {
+            map.emplace(mtype, descr);
+        }
+    }
+
+    return map;
+}
+
+}  // namespace android::netdevice::protocols
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/NetlinkProtocol.h b/automotive/can/1.0/default/libnetdevice/protocols/NetlinkProtocol.h
new file mode 100644
index 0000000..7b12efa
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/protocols/NetlinkProtocol.h
@@ -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.
+ */
+
+#pragma once
+
+#include "MessageDefinition.h"
+#include "common/Empty.h"
+#include "common/Error.h"
+
+#include <libnetdevice/types.h>
+
+#include <string>
+#include <vector>
+
+namespace android::netdevice::protocols {
+
+/**
+ * Netlink-based protocol definition.
+ *
+ * Usually it's just an id/name and a list of supported messages.
+ */
+class NetlinkProtocol {
+  public:
+    virtual ~NetlinkProtocol();
+
+    int getProtocol() const;
+
+    const std::string& getName() const;
+
+    virtual const std::optional<std::reference_wrapper<const MessageDescriptor>>
+    getMessageDescriptor(nlmsgtype_t nlmsg_type);
+
+  protected:
+    typedef std::vector<std::shared_ptr<const MessageDescriptor>> MessageDescriptorList;
+
+    NetlinkProtocol(int protocol, const std::string name,
+                    const MessageDescriptorList&& messageDescrs);
+
+  private:
+    typedef std::map<nlmsgtype_t, std::shared_ptr<const MessageDescriptor>> MessageDescriptorMap;
+
+    const int mProtocol;
+    const std::string mName;
+    const MessageDescriptorMap mMessageDescrs;
+
+    static MessageDescriptorMap toMap(const MessageDescriptorList& descrs, int protocol);
+};
+
+}  // namespace android::netdevice::protocols
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/README b/automotive/can/1.0/default/libnetdevice/protocols/README
new file mode 100644
index 0000000..45c95c4
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/protocols/README
@@ -0,0 +1,8 @@
+This folder contains message definitions for various protocols based on Netlink.
+
+The structure is as follows:
+protocols/*.(cpp|h)                - base definition classes and protocol definition lookup
+protocols/common/                  - common message types that apply to all protocols
+protocols/<proto>/<proto>.(cpp|h)  - protocol definition (usually just a list of message types)
+protocols/<proto>/*.(cpp|h)        - message definition that covers all message types with the same
+                                     header (T type in MessageDefinition template) and attributes
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/all.cpp b/automotive/can/1.0/default/libnetdevice/protocols/all.cpp
new file mode 100644
index 0000000..980e3d0
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/protocols/all.cpp
@@ -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.
+ */
+
+#include "all.h"
+
+#include "generic/Generic.h"
+#include "route/Route.h"
+
+#include <map>
+
+namespace android::netdevice::protocols {
+
+// This should be a map of unique_ptr, but it's not trivial to uniformly initialize such a map
+static std::map<int, std::shared_ptr<NetlinkProtocol>> toMap(
+        std::initializer_list<std::shared_ptr<NetlinkProtocol>> l) {
+    std::map<int, std::shared_ptr<NetlinkProtocol>> map;
+    for (auto p : l) {
+        map[p->getProtocol()] = p;
+    }
+    return map;
+}
+
+static auto all = toMap({
+        std::make_unique<generic::Generic>(),
+        std::make_unique<route::Route>(),
+});
+
+std::optional<std::reference_wrapper<NetlinkProtocol>> get(int protocol) {
+    if (all.count(protocol) == 0) return std::nullopt;
+    return *all.find(protocol)->second.get();
+}
+
+}  // namespace android::netdevice::protocols
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/automotive/can/1.0/default/libnetdevice/protocols/all.h
similarity index 61%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to automotive/can/1.0/default/libnetdevice/protocols/all.h
index 7edec47..2180ebb 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/automotive/can/1.0/default/libnetdevice/protocols/all.h
@@ -14,13 +14,18 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#pragma once
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+#include "NetlinkProtocol.h"
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+namespace android::netdevice::protocols {
+
+/**
+ * Protocol definition lookup.
+ *
+ * \param protocol Protocol identifier from linux/netlink.h
+ * \return Protocol definition or nullopt if it's not implemented
+ */
+std::optional<std::reference_wrapper<NetlinkProtocol>> get(int protocol);
+
+}  // namespace android::netdevice::protocols
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/automotive/can/1.0/default/libnetdevice/protocols/common/Empty.cpp
similarity index 62%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to automotive/can/1.0/default/libnetdevice/protocols/common/Empty.cpp
index 7edec47..9f25203 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/automotive/can/1.0/default/libnetdevice/protocols/common/Empty.cpp
@@ -14,13 +14,18 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#include "Empty.h"
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+namespace android::netdevice::protocols::base {
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+// clang-format off
+Empty::Empty() : MessageDefinition<char>("nlmsg", {
+    {NLMSG_NOOP, "NOOP"},
+    {NLMSG_DONE, "DONE"},
+    {NLMSG_OVERRUN, "OVERRUN"},
+}) {}
+// clang-format on
+
+void Empty::toStream(std::stringstream&, const char&) const {}
+
+}  // namespace android::netdevice::protocols::base
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/common/Empty.h b/automotive/can/1.0/default/libnetdevice/protocols/common/Empty.h
new file mode 100644
index 0000000..b5b317f
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/protocols/common/Empty.h
@@ -0,0 +1,32 @@
+/*
+ * 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 "../MessageDefinition.h"
+
+#include <libnetdevice/printer.h>
+
+namespace android::netdevice::protocols::base {
+
+// no-payload (like NLMSG_NOOP) messages can't be defined with T=void, so let's use char
+class Empty : public MessageDefinition<char> {
+  public:
+    Empty();
+    void toStream(std::stringstream&, const char&) const override;
+};
+
+}  // namespace android::netdevice::protocols::base
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/common/Error.cpp b/automotive/can/1.0/default/libnetdevice/protocols/common/Error.cpp
new file mode 100644
index 0000000..25ae680
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/protocols/common/Error.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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 "Error.h"
+
+#include "../MessageDefinition.h"
+
+#include <libnetdevice/printer.h>
+
+namespace android::netdevice::protocols::base {
+
+// clang-format off
+Error::Error(int protocol) : MessageDefinition<nlmsgerr>("nlmsg", {
+    {NLMSG_ERROR, "ERROR"},
+}), mProtocol(protocol) {}
+// clang-format on
+
+void Error::toStream(std::stringstream& ss, const nlmsgerr& data) const {
+    ss << "nlmsgerr{error=" << data.error
+       << ", msg=" << toString({&data.msg, sizeof(data.msg)}, mProtocol) << "}";
+}
+
+}  // namespace android::netdevice::protocols::base
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/automotive/can/1.0/default/libnetdevice/protocols/common/Error.h
similarity index 63%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to automotive/can/1.0/default/libnetdevice/protocols/common/Error.h
index 7edec47..1f3c1dd 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/automotive/can/1.0/default/libnetdevice/protocols/common/Error.h
@@ -14,13 +14,19 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#pragma once
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+#include "../MessageDefinition.h"
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+namespace android::netdevice::protocols::base {
+
+class Error : public MessageDefinition<nlmsgerr> {
+  public:
+    Error(int protocol);
+    void toStream(std::stringstream& ss, const nlmsgerr& data) const override;
+
+  private:
+    const int mProtocol;
+};
+
+}  // namespace android::netdevice::protocols::base
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/generic/Ctrl.cpp b/automotive/can/1.0/default/libnetdevice/protocols/generic/Ctrl.cpp
new file mode 100644
index 0000000..4120008
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/protocols/generic/Ctrl.cpp
@@ -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.
+ */
+
+#include "Ctrl.h"
+
+namespace android::netdevice::protocols::generic {
+
+using DataType = AttributeDefinition::DataType;
+
+// clang-format off
+Ctrl::Ctrl() : GenericMessageBase(GENL_ID_CTRL, "ID_CTRL", {
+    {CTRL_CMD_NEWFAMILY, "NEWFAMILY"},
+    {CTRL_CMD_DELFAMILY, "DELFAMILY"},
+    {CTRL_CMD_GETFAMILY, "GETFAMILY"},
+    {CTRL_CMD_NEWOPS, "NEWOPS"},
+    {CTRL_CMD_DELOPS, "DELOPS"},
+    {CTRL_CMD_GETOPS, "GETOPS"},
+    {CTRL_CMD_NEWMCAST_GRP, "NEWMCAST_GRP"},
+    {CTRL_CMD_DELMCAST_GRP, "DELMCAST_GRP"},
+    {CTRL_CMD_GETMCAST_GRP, "GETMCAST_GRP"},
+}, {
+    {CTRL_ATTR_FAMILY_ID, {"FAMILY_ID", DataType::Uint}},
+    {CTRL_ATTR_FAMILY_NAME, {"FAMILY_NAME", DataType::String}},
+    {CTRL_ATTR_VERSION, {"VERSION", DataType::Uint}},
+    {CTRL_ATTR_HDRSIZE, {"HDRSIZE", DataType::Uint}},
+    {CTRL_ATTR_MAXATTR, {"MAXATTR", DataType::Uint}},
+    {CTRL_ATTR_OPS, {"OPS", DataType::Nested, AttributeMap{
+        {std::nullopt, {"OP", DataType::Nested, AttributeMap{
+            {CTRL_ATTR_OP_ID, {"ID", DataType::Uint}},
+            {CTRL_ATTR_OP_FLAGS, {"FLAGS", DataType::Uint}},
+        }}},
+    }}},
+    {CTRL_ATTR_MCAST_GROUPS, {"MCAST_GROUPS", DataType::Nested, AttributeMap{
+        {std::nullopt, {"GRP", DataType::Nested, AttributeMap{
+            {CTRL_ATTR_MCAST_GRP_NAME, {"NAME", DataType::String}},
+            {CTRL_ATTR_MCAST_GRP_ID, {"ID", DataType::Uint}},
+        }}},
+    }}},
+}) {}
+// clang-format on
+
+}  // namespace android::netdevice::protocols::generic
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/automotive/can/1.0/default/libnetdevice/protocols/generic/Ctrl.h
similarity index 69%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to automotive/can/1.0/default/libnetdevice/protocols/generic/Ctrl.h
index 7edec47..804ed2c 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/automotive/can/1.0/default/libnetdevice/protocols/generic/Ctrl.h
@@ -14,13 +14,15 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#pragma once
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+#include "GenericMessageBase.h"
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+namespace android::netdevice::protocols::generic {
+
+class Ctrl : public GenericMessageBase {
+  public:
+    Ctrl();
+};
+
+}  // namespace android::netdevice::protocols::generic
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/generic/Generic.cpp b/automotive/can/1.0/default/libnetdevice/protocols/generic/Generic.cpp
new file mode 100644
index 0000000..633ef3c
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/protocols/generic/Generic.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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 "Generic.h"
+
+#include "Ctrl.h"
+#include "Unknown.h"
+
+namespace android::netdevice::protocols::generic {
+
+Generic::Generic() : NetlinkProtocol(NETLINK_GENERIC, "GENERIC", {std::make_shared<Ctrl>()}) {}
+
+const std::optional<std::reference_wrapper<const MessageDescriptor>> Generic::getMessageDescriptor(
+        nlmsgtype_t nlmsg_type) {
+    const auto desc = NetlinkProtocol::getMessageDescriptor(nlmsg_type);
+    if (desc.has_value()) return desc;
+
+    auto it = mFamilyRegister.find(nlmsg_type);
+    if (it != mFamilyRegister.end()) return *it->second;
+    return *(mFamilyRegister[nlmsg_type] = std::make_shared<Unknown>(nlmsg_type));
+}
+
+}  // namespace android::netdevice::protocols::generic
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/generic/Generic.h b/automotive/can/1.0/default/libnetdevice/protocols/generic/Generic.h
new file mode 100644
index 0000000..b4352f6
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/protocols/generic/Generic.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 "../NetlinkProtocol.h"
+
+namespace android::netdevice::protocols::generic {
+
+/**
+ * Definition of NETLINK_GENERIC protocol.
+ */
+class Generic : public NetlinkProtocol {
+  public:
+    Generic();
+
+    const std::optional<std::reference_wrapper<const MessageDescriptor>> getMessageDescriptor(
+            nlmsgtype_t nlmsg_type);
+
+  private:
+    std::map<nlmsgtype_t, std::shared_ptr<const MessageDescriptor>> mFamilyRegister;
+};
+
+}  // namespace android::netdevice::protocols::generic
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/generic/GenericMessageBase.cpp b/automotive/can/1.0/default/libnetdevice/protocols/generic/GenericMessageBase.cpp
new file mode 100644
index 0000000..c9f0813
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/protocols/generic/GenericMessageBase.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GenericMessageBase.h"
+
+namespace android::netdevice::protocols::generic {
+
+GenericMessageBase::GenericMessageBase(
+        nlmsgtype_t msgtype, std::string msgname,
+        const std::initializer_list<GenericCommandNameMap::value_type> commandNames,
+        const std::initializer_list<AttributeMap::value_type> attrTypes)
+    : MessageDefinition<struct genlmsghdr>(msgname, {{msgtype, msgname}}, attrTypes),
+      mCommandNames(commandNames) {}
+
+void GenericMessageBase::toStream(std::stringstream& ss, const struct genlmsghdr& data) const {
+    ss << "genlmsghdr{";
+    if (mCommandNames.count(data.cmd) == 0) {
+        ss << "cmd=" << unsigned(data.cmd);
+    } else {
+        ss << "cmd=" << mCommandNames.find(data.cmd)->second;
+    }
+    ss << ", version=" << unsigned(data.version);
+    if (data.reserved != 0) ss << ", reserved=" << data.reserved;
+    ss << "}";
+}
+
+}  // namespace android::netdevice::protocols::generic
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/generic/GenericMessageBase.h b/automotive/can/1.0/default/libnetdevice/protocols/generic/GenericMessageBase.h
new file mode 100644
index 0000000..2a19034
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/protocols/generic/GenericMessageBase.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include "../MessageDefinition.h"
+
+#include <linux/genetlink.h>
+
+namespace android::netdevice::protocols::generic {
+
+class GenericMessageBase : public MessageDefinition<struct genlmsghdr> {
+  public:
+    typedef std::map<uint8_t, std::string> GenericCommandNameMap;
+
+    GenericMessageBase(
+            nlmsgtype_t msgtype, std::string msgname,
+            const std::initializer_list<GenericCommandNameMap::value_type> commandNames = {},
+            const std::initializer_list<AttributeMap::value_type> attrTypes = {});
+
+    void toStream(std::stringstream& ss, const struct genlmsghdr& data) const override;
+
+  private:
+    const GenericCommandNameMap mCommandNames;
+};
+
+}  // namespace android::netdevice::protocols::generic
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/automotive/can/1.0/default/libnetdevice/protocols/generic/Unknown.cpp
similarity index 69%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to automotive/can/1.0/default/libnetdevice/protocols/generic/Unknown.cpp
index 7edec47..9a71d89 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/automotive/can/1.0/default/libnetdevice/protocols/generic/Unknown.cpp
@@ -14,13 +14,11 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#include "Unknown.h"
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+namespace android::netdevice::protocols::generic {
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+Unknown::Unknown(nlmsgtype_t msgtype)
+    : GenericMessageBase(msgtype, "Unknown(" + std::to_string(msgtype) + ")") {}
+
+}  // namespace android::netdevice::protocols::generic
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/automotive/can/1.0/default/libnetdevice/protocols/generic/Unknown.h
similarity index 69%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to automotive/can/1.0/default/libnetdevice/protocols/generic/Unknown.h
index 7edec47..82a5501 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/automotive/can/1.0/default/libnetdevice/protocols/generic/Unknown.h
@@ -14,13 +14,15 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#pragma once
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+#include "GenericMessageBase.h"
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+namespace android::netdevice::protocols::generic {
+
+class Unknown : public GenericMessageBase {
+  public:
+    Unknown(nlmsgtype_t msgtype);
+};
+
+}  // namespace android::netdevice::protocols::generic
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/route/Link.cpp b/automotive/can/1.0/default/libnetdevice/protocols/route/Link.cpp
new file mode 100644
index 0000000..53e1700
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/protocols/route/Link.cpp
@@ -0,0 +1,117 @@
+/*
+ * 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 "Link.h"
+
+#include "structs.h"
+
+#include <net/if.h>
+
+namespace android::netdevice::protocols::route {
+
+using DataType = AttributeDefinition::DataType;
+
+// clang-format off
+Link::Link() : MessageDefinition<struct ifinfomsg>("link", {
+    {RTM_NEWLINK, "NEWLINK"},
+    {RTM_DELLINK, "DELLINK"},
+    {RTM_GETLINK, "GETLINK"},
+}, {
+    {IFLA_ADDRESS, {"ADDRESS"}},
+    {IFLA_BROADCAST, {"BROADCAST"}},
+    {IFLA_IFNAME, {"IFNAME", DataType::String}},
+    {IFLA_MTU, {"MTU", DataType::Uint}},
+    {IFLA_LINK, {"LINK", DataType::Uint}},
+    {IFLA_QDISC, {"QDISC", DataType::String}},
+    {IFLA_STATS, {"STATS", DataType::Struct, statsToStream<rtnl_link_stats>}},
+    {IFLA_COST, {"COST"}},
+    {IFLA_PRIORITY, {"PRIORITY"}},
+    {IFLA_MASTER, {"MASTER", DataType::Uint}},
+    {IFLA_WIRELESS, {"WIRELESS"}},
+    {IFLA_PROTINFO, {"PROTINFO"}},
+    {IFLA_TXQLEN, {"TXQLEN", DataType::Uint}},
+    {IFLA_MAP, {"MAP", DataType::Struct, mapToStream}},
+    {IFLA_WEIGHT, {"WEIGHT", DataType::Uint}},
+    {IFLA_OPERSTATE, {"OPERSTATE", DataType::Uint}},
+    {IFLA_LINKMODE, {"LINKMODE", DataType::Uint}},
+    {IFLA_LINKINFO, {"LINKINFO", DataType::Nested, AttributeMap{
+        {IFLA_INFO_KIND, {"INFO_KIND", DataType::String}},
+        {IFLA_INFO_DATA, {"INFO_DATA", DataType::Nested}},
+        {IFLA_INFO_XSTATS, {"INFO_XSTATS"}},
+        {IFLA_INFO_SLAVE_KIND, {"INFO_SLAVE_KIND", DataType::String}},
+        {IFLA_INFO_SLAVE_DATA, {"INFO_SLAVE_DATA"}},
+    }}},
+    {IFLA_NET_NS_PID, {"NET_NS_PID", DataType::Uint}},
+    {IFLA_IFALIAS, {"IFALIAS", DataType::String}},
+    {IFLA_NUM_VF, {"NUM_VF", DataType::Uint}},
+    {IFLA_VFINFO_LIST, {"VFINFO_LIST"}},
+    {IFLA_STATS64, {"STATS64", DataType::Struct, statsToStream<rtnl_link_stats64>}},
+    {IFLA_VF_PORTS, {"VF_PORTS"}},
+    {IFLA_PORT_SELF, {"PORT_SELF"}},
+    {IFLA_AF_SPEC, {"AF_SPEC", DataType::Nested, AttributeMap{
+        {AF_INET, {"AF_INET", DataType::Nested, AttributeMap{
+            {IFLA_INET_CONF, {"INET_CONF", DataType::Struct, arrayToStream<int32_t>}},
+        }}},
+        {AF_INET6, {"AF_INET6", DataType::Nested, AttributeMap{
+            {IFLA_INET6_FLAGS, {"INET6_FLAGS", DataType::Uint}},
+            {IFLA_INET6_CONF, {"INET6_CONF", DataType::Struct, arrayToStream<int32_t>}},
+            {IFLA_INET6_STATS, {"INET6_STATS", DataType::Struct, arrayToStream<uint64_t>}},
+            {IFLA_INET6_MCAST, {"INET6_MCAST"}},
+            {IFLA_INET6_CACHEINFO, {"INET6_CACHEINFO", DataType::Struct, ifla_cacheinfoToStream}},
+            {IFLA_INET6_ICMP6STATS, {"INET6_ICMP6STATS", DataType::Struct, arrayToStream<uint64_t>}},
+            {IFLA_INET6_TOKEN, {"INET6_TOKEN"}},
+            {IFLA_INET6_ADDR_GEN_MODE, {"INET6_ADDR_GEN_MODE", DataType::Uint}},
+        }}},
+    }}},
+    {IFLA_GROUP, {"GROUP", DataType::Uint}},
+    {IFLA_NET_NS_FD, {"NET_NS_FD", DataType::Uint}},
+    {IFLA_EXT_MASK, {"EXT_MASK", DataType::Uint}},
+    {IFLA_PROMISCUITY, {"PROMISCUITY", DataType::Uint}},
+    {IFLA_NUM_TX_QUEUES, {"NUM_TX_QUEUES", DataType::Uint}},
+    {IFLA_NUM_RX_QUEUES, {"NUM_RX_QUEUES", DataType::Uint}},
+    {IFLA_CARRIER, {"CARRIER", DataType::Uint}},
+    {IFLA_PHYS_PORT_ID, {"PHYS_PORT_ID"}},
+    {IFLA_CARRIER_CHANGES, {"CARRIER_CHANGES", DataType::Uint}},
+    {IFLA_PHYS_SWITCH_ID, {"PHYS_SWITCH_ID"}},
+    {IFLA_LINK_NETNSID, {"LINK_NETNSID"}},  // NLA_S32
+    {IFLA_PHYS_PORT_NAME, {"PHYS_PORT_NAME", DataType::String}},
+    {IFLA_PROTO_DOWN, {"PROTO_DOWN", DataType::Uint}},
+    {IFLA_GSO_MAX_SEGS, {"GSO_MAX_SEGS", DataType::Uint}},
+    {IFLA_GSO_MAX_SIZE, {"GSO_MAX_SIZE", DataType::Uint}},
+    {IFLA_PAD, {"PAD"}},
+    {IFLA_XDP, {"XDP"}},
+    {IFLA_EVENT, {"EVENT", DataType::Uint}},
+    {IFLA_NEW_NETNSID, {"NEW_NETNSID"}},  // NLA_S32
+    {IFLA_TARGET_NETNSID, {"TARGET_NETNSID"}},  // NLA_S32
+    {IFLA_CARRIER_UP_COUNT, {"CARRIER_UP_COUNT", DataType::Uint}},
+    {IFLA_CARRIER_DOWN_COUNT, {"CARRIER_DOWN_COUNT", DataType::Uint}},
+    {IFLA_NEW_IFINDEX, {"NEW_IFINDEX"}},  // NLA_S32
+    {IFLA_MIN_MTU, {"MIN_MTU", DataType::Uint}},
+    {IFLA_MAX_MTU, {"MAX_MTU", DataType::Uint}},
+    {IFLA_PROP_LIST, {"PROP_LIST"}},
+    {IFLA_ALT_IFNAME, {"ALT_IFNAME", DataType::String}},
+    {IFLA_PERM_ADDRESS, {"PERM_ADDRESS"}},
+}) {}
+// clang-format off
+
+void Link::toStream(std::stringstream& ss, const struct ifinfomsg& data) const {
+    ss << "ifinfomsg{"
+       << "family=" << unsigned(data.ifi_family) << ", type=" << data.ifi_type
+       << ", index=" << data.ifi_index << ", flags=" << data.ifi_flags
+       << ", change=" << data.ifi_change << "}";
+}
+
+}  // namespace android::netdevice::protocols::route
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/automotive/can/1.0/default/libnetdevice/protocols/route/Link.h
similarity index 63%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to automotive/can/1.0/default/libnetdevice/protocols/route/Link.h
index 7edec47..bcfce19 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/automotive/can/1.0/default/libnetdevice/protocols/route/Link.h
@@ -14,13 +14,18 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#pragma once
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+#include "../MessageDefinition.h"
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+#include <linux/rtnetlink.h>
+
+namespace android::netdevice::protocols::route {
+
+class Link : public MessageDefinition<struct ifinfomsg> {
+  public:
+    Link();
+    void toStream(std::stringstream& ss, const struct ifinfomsg& data) const override;
+};
+
+}  // namespace android::netdevice::protocols::route
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/automotive/can/1.0/default/libnetdevice/protocols/route/Route.cpp
similarity index 69%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to automotive/can/1.0/default/libnetdevice/protocols/route/Route.cpp
index 7edec47..456072b 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/automotive/can/1.0/default/libnetdevice/protocols/route/Route.cpp
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#include "Route.h"
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+#include "Link.h"
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+namespace android::netdevice::protocols::route {
+
+Route::Route() : NetlinkProtocol(NETLINK_ROUTE, "ROUTE", {std::make_shared<Link>()}) {}
+
+}  // namespace android::netdevice::protocols::route
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/automotive/can/1.0/default/libnetdevice/protocols/route/Route.h
similarity index 69%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to automotive/can/1.0/default/libnetdevice/protocols/route/Route.h
index 7edec47..3051cf9 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/automotive/can/1.0/default/libnetdevice/protocols/route/Route.h
@@ -14,13 +14,18 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#pragma once
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+#include "../NetlinkProtocol.h"
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+namespace android::netdevice::protocols::route {
+
+/**
+ * Definition of NETLINK_ROUTE protocol.
+ */
+class Route : public NetlinkProtocol {
+  public:
+    Route();
+};
+
+}  // namespace android::netdevice::protocols::route
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/route/structs.cpp b/automotive/can/1.0/default/libnetdevice/protocols/route/structs.cpp
new file mode 100644
index 0000000..48d64f0
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/protocols/route/structs.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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 "structs.h"
+
+namespace android::netdevice::protocols::route {
+
+void mapToStream(std::stringstream& ss, const nlbuf<nlattr> attr) {
+    const auto& [ok, data] = attr.data<rtnl_link_ifmap>().getFirst();
+    if (!ok) {
+        ss << "invalid structure";
+        return;
+    }
+    ss << '{'                        //
+       << data.mem_start << ','      //
+       << data.mem_end << ','        //
+       << data.base_addr << ','      //
+       << data.irq << ','            //
+       << unsigned(data.dma) << ','  //
+       << unsigned(data.port) << '}';
+}
+
+void ifla_cacheinfoToStream(std::stringstream& ss, const nlbuf<nlattr> attr) {
+    const auto& [ok, data] = attr.data<ifla_cacheinfo>().getFirst();
+    if (!ok) {
+        ss << "invalid structure";
+        return;
+    }
+    ss << '{'                         //
+       << data.max_reasm_len << ','   //
+       << data.tstamp << ','          //
+       << data.reachable_time << ','  //
+       << data.retrans_time << '}';
+}
+
+}  // namespace android::netdevice::protocols::route
diff --git a/automotive/can/1.0/default/libnetdevice/protocols/route/structs.h b/automotive/can/1.0/default/libnetdevice/protocols/route/structs.h
new file mode 100644
index 0000000..e532704
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/protocols/route/structs.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 <libnetdevice/nlbuf.h>
+
+#include <linux/rtnetlink.h>
+
+#include <sstream>
+
+namespace android::netdevice::protocols::route {
+
+// rtnl_link_ifmap
+void mapToStream(std::stringstream& ss, const nlbuf<nlattr> attr);
+
+// ifla_cacheinfo
+void ifla_cacheinfoToStream(std::stringstream& ss, const nlbuf<nlattr> attr);
+
+template <typename T>
+void arrayToStream(std::stringstream& ss, const nlbuf<nlattr> attr) {
+    ss << '{';
+    for (const auto it : attr.data<T>().getRaw()) {
+        ss << it << ',';
+    }
+    ss.seekp(-1, std::ios_base::cur);
+    ss << '}';
+}
+
+// rtnl_link_stats or rtnl_link_stats64
+template <typename T>
+void statsToStream(std::stringstream& ss, const nlbuf<nlattr> attr) {
+    const auto& [ok, data] = attr.data<T>().getFirst();
+    if (!ok) {
+        ss << "invalid structure";
+        return;
+    }
+    ss << '{'                              //
+       << data.rx_packets << ','           //
+       << data.tx_packets << ','           //
+       << data.rx_bytes << ','             //
+       << data.tx_bytes << ','             //
+       << data.rx_errors << ','            //
+       << data.tx_errors << ','            //
+       << data.rx_dropped << ','           //
+       << data.tx_dropped << ','           //
+       << data.multicast << ','            //
+       << data.collisions << ','           //
+       << data.rx_length_errors << ','     //
+       << data.rx_over_errors << ','       //
+       << data.rx_crc_errors << ','        //
+       << data.rx_frame_errors << ','      //
+       << data.rx_fifo_errors << ','       //
+       << data.rx_missed_errors << ','     //
+       << data.tx_aborted_errors << ','    //
+       << data.tx_carrier_errors << ','    //
+       << data.tx_fifo_errors << ','       //
+       << data.tx_heartbeat_errors << ','  //
+       << data.tx_window_errors << ','     //
+       << data.rx_compressed << ','        //
+       << data.tx_compressed << ','        //
+       << data.rx_nohandler << '}';
+}
+
+}  // namespace android::netdevice::protocols::route
diff --git a/automotive/can/1.0/default/libnetdevice/vlan.cpp b/automotive/can/1.0/default/libnetdevice/vlan.cpp
new file mode 100644
index 0000000..f0caacd
--- /dev/null
+++ b/automotive/can/1.0/default/libnetdevice/vlan.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libnetdevice/vlan.h>
+
+#include "common.h"
+
+#include <android-base/logging.h>
+#include <libnetdevice/NetlinkRequest.h>
+#include <libnetdevice/NetlinkSocket.h>
+
+namespace android::netdevice::vlan {
+
+bool add(const std::string& eth, const std::string& vlan, uint16_t id) {
+    const auto ethidx = nametoindex(eth);
+    if (ethidx == 0) {
+        LOG(ERROR) << "Ethernet interface " << eth << " doesn't exist";
+        return false;
+    }
+
+    NetlinkRequest<struct ifinfomsg> req(RTM_NEWLINK, NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL);
+    req.addattr(IFLA_IFNAME, vlan);
+    req.addattr<uint32_t>(IFLA_LINK, ethidx);
+
+    {
+        auto linkinfo = req.nest(IFLA_LINKINFO);
+        req.addattr(IFLA_INFO_KIND, "vlan");
+
+        {
+            auto linkinfo = req.nest(IFLA_INFO_DATA);
+            req.addattr(IFLA_VLAN_ID, id);
+        }
+    }
+
+    NetlinkSocket sock(NETLINK_ROUTE);
+    return sock.send(req) && sock.receiveAck();
+}
+
+}  // namespace android::netdevice::vlan
diff --git a/automotive/can/1.0/default/service.cpp b/automotive/can/1.0/default/service.cpp
index b52a54a..9a9d322 100644
--- a/automotive/can/1.0/default/service.cpp
+++ b/automotive/can/1.0/default/service.cpp
@@ -18,6 +18,7 @@
 
 #include <android-base/logging.h>
 #include <hidl/HidlTransportSupport.h>
+#include <libnetdevice/libnetdevice.h>
 
 namespace android::hardware::automotive::can::V1_0::implementation {
 
@@ -27,6 +28,8 @@
     configureRpcThreadpool(16, true);
     LOG(DEBUG) << "CAN controller service starting...";
 
+    netdevice::useSocketDomain(AF_CAN);
+
     sp<CanController> canController(new CanController);
     if (canController->registerAsService("socketcan") != OK) {
         LOG(FATAL) << "Failed to register CAN controller";
diff --git a/automotive/evs/1.0/Android.bp b/automotive/evs/1.0/Android.bp
index 51f8e20..279c09a 100644
--- a/automotive/evs/1.0/Android.bp
+++ b/automotive/evs/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.automotive.evs@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IEvsCamera.hal",
diff --git a/automotive/evs/1.1/Android.bp b/automotive/evs/1.1/Android.bp
index f9bccef..443422e 100644
--- a/automotive/evs/1.1/Android.bp
+++ b/automotive/evs/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.automotive.evs@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IEvsCamera.hal",
diff --git a/automotive/evs/1.1/types.hal b/automotive/evs/1.1/types.hal
index 1f69f09..e699fd0 100644
--- a/automotive/evs/1.1/types.hal
+++ b/automotive/evs/1.1/types.hal
@@ -105,6 +105,10 @@
      * Master role has become available
      */
     MASTER_RELEASED,
+    /**
+     * Any other erroneous streaming events
+     */
+    STREAM_ERROR,
 };
 
 /**
diff --git a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
index 6a386c3..8b68fd6 100644
--- a/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
+++ b/automotive/evs/1.1/vts/functional/VtsHalEvsV1_1TargetTest.cpp
@@ -2262,6 +2262,7 @@
 
     // Allocate buffers to use
     hidl_vec<BufferDesc> buffers;
+    buffers.resize(kBuffersToHold);
     for (auto i = 0; i < kBuffersToHold; ++i) {
         unsigned pixelsPerLine;
         buffer_handle_t memHandle = nullptr;
diff --git a/automotive/sv/1.0/Android.bp b/automotive/sv/1.0/Android.bp
index 769bdc6..3a39148 100644
--- a/automotive/sv/1.0/Android.bp
+++ b/automotive/sv/1.0/Android.bp
@@ -3,22 +3,19 @@
 hidl_interface {
     name: "android.hardware.automotive.sv@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
-        "ISurroundViewStream.hal",
-        "ISurroundViewSession.hal",
         "ISurroundView2dSession.hal",
         "ISurroundView3dSession.hal",
         "ISurroundViewService.hal",
+        "ISurroundViewSession.hal",
+        "ISurroundViewStream.hal",
     ],
     interfaces: [
-        "android.hidl.base@1.0",
         "android.hardware.graphics.common@1.0",
         "android.hardware.graphics.common@1.1",
         "android.hardware.graphics.common@1.2",
+        "android.hidl.base@1.0",
     ],
     gen_java: true,
 }
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index 0e73d85..4fa8773 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.automotive.vehicle@2.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IVehicle.hal",
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index 872b35b..d9ac239 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -27,6 +27,15 @@
     ],
 }
 
+cc_defaults {
+    name: "vhal_v2_0_target_defaults",
+    defaults: ["vhal_v2_0_defaults"],
+    shared_libs: [
+        "libbinder_ndk",
+        "carwatchdog_aidl_interface-ndk_platform",
+    ],
+}
+
 cc_library_headers {
     name: "vhal_v2_0_common_headers",
     vendor: true,
@@ -37,7 +46,7 @@
 cc_library {
     name: "android.hardware.automotive.vehicle@2.0-manager-lib",
     vendor: true,
-    defaults: ["vhal_v2_0_defaults"],
+    defaults: ["vhal_v2_0_target_defaults"],
     srcs: [
         "common/src/Obd2SensorStore.cpp",
         "common/src/SubscriptionManager.cpp",
@@ -46,6 +55,7 @@
         "common/src/VehiclePropertyStore.cpp",
         "common/src/VehicleUtils.cpp",
         "common/src/VmsUtils.cpp",
+        "common/src/WatchdogClient.cpp",
     ],
     shared_libs: [
         "libbase",
@@ -58,7 +68,7 @@
 cc_library_static {
     name: "android.hardware.automotive.vehicle@2.0-default-impl-lib",
     vendor: true,
-    defaults: ["vhal_v2_0_defaults"],
+    defaults: ["vhal_v2_0_target_defaults"],
     srcs: [
         "impl/vhal_v2_0/CommConn.cpp",
         "impl/vhal_v2_0/EmulatedVehicleConnector.cpp",
@@ -94,16 +104,59 @@
 cc_library_static {
     name: "android.hardware.automotive.vehicle@2.0-emulated-user-hal-lib",
     vendor: true,
-    defaults: ["vhal_v2_0_defaults"],
+    defaults: ["vhal_v2_0_target_defaults"],
     srcs: [
         "impl/vhal_v2_0/EmulatedUserHal.cpp",
     ],
 }
 
+// Vehicle HAL Server reference impl lib
+cc_library_static {
+    name: "android.hardware.automotive.vehicle@2.0-server-common-lib",
+    vendor: true,
+    host_supported: true,
+    defaults: ["vhal_v2_0_defaults"],
+    local_include_dirs: ["common/include/vhal_v2_0"],
+    export_include_dirs: ["common/include"],
+    srcs: [
+        "common/src/Obd2SensorStore.cpp",
+        "common/src/VehicleObjectPool.cpp",
+        "common/src/VehicleUtils.cpp",
+    ],
+}
+
+// Vehicle HAL Server default implementation
+cc_library_static {
+    name: "android.hardware.automotive.vehicle@2.0-server-impl-lib",
+    vendor: true,
+    host_supported: true,
+    defaults: ["vhal_v2_0_defaults"],
+    local_include_dirs: ["common/include/vhal_v2_0"],
+    export_include_dirs: ["impl"],
+    srcs: [
+        "impl/vhal_v2_0/EmulatedUserHal.cpp",
+        "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",
+    ],
+    whole_static_libs: [
+        "android.hardware.automotive.vehicle@2.0-server-common-lib",
+    ],
+    static_libs: [
+        "android.hardware.automotive.vehicle@2.0-libproto-native",
+    ],
+    shared_libs: [
+        "libbase",
+        "libjsoncpp",
+    ],
+}
+
 cc_test {
     name: "android.hardware.automotive.vehicle@2.0-manager-unit-tests",
     vendor: true,
-    defaults: ["vhal_v2_0_defaults"],
+    defaults: ["vhal_v2_0_target_defaults"],
     whole_static_libs: ["android.hardware.automotive.vehicle@2.0-manager-lib"],
     srcs: [
         "tests/RecurrentTimer_test.cpp",
@@ -123,7 +176,7 @@
 cc_test {
     name: "android.hardware.automotive.vehicle@2.0-default-impl-unit-tests",
     vendor: true,
-    defaults: ["vhal_v2_0_defaults"],
+    defaults: ["vhal_v2_0_target_defaults"],
     srcs: [
         "impl/vhal_v2_0/tests/ProtoMessageConverter_test.cpp",
     ],
@@ -137,7 +190,7 @@
 
 cc_binary {
     name: "android.hardware.automotive.vehicle@2.0-service",
-    defaults: ["vhal_v2_0_defaults"],
+    defaults: ["vhal_v2_0_target_defaults"],
     vintf_fragments: [
         "android.hardware.automotive.vehicle@2.0-service.xml",
     ],
diff --git a/automotive/vehicle/2.0/default/VehicleService.cpp b/automotive/vehicle/2.0/default/VehicleService.cpp
index 127eb98..47133fd 100644
--- a/automotive/vehicle/2.0/default/VehicleService.cpp
+++ b/automotive/vehicle/2.0/default/VehicleService.cpp
@@ -20,9 +20,13 @@
 
 #include <iostream>
 
+#include <android/binder_process.h>
+#include <utils/Looper.h>
+#include <vhal_v2_0/EmulatedUserHal.h>
 #include <vhal_v2_0/EmulatedVehicleConnector.h>
 #include <vhal_v2_0/EmulatedVehicleHal.h>
 #include <vhal_v2_0/VehicleHalManager.h>
+#include <vhal_v2_0/WatchdogClient.h>
 
 using namespace android;
 using namespace android::hardware;
@@ -31,12 +35,13 @@
 int main(int /* argc */, char* /* argv */ []) {
     auto store = std::make_unique<VehiclePropertyStore>();
     auto connector = impl::makeEmulatedPassthroughConnector();
-    auto hal = std::make_unique<impl::EmulatedVehicleHal>(store.get(), connector.get());
+    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 service = std::make_unique<VehicleHalManager>(hal.get());
     connector->setValuePool(hal->getValuePool());
 
-    configureRpcThreadpool(4, true /* callerWillJoin */);
+    configureRpcThreadpool(4, false /* callerWillJoin */);
 
     ALOGI("Registering as service...");
     status_t status = service->registerAsService();
@@ -46,8 +51,22 @@
         return 1;
     }
 
+    // Setup a binder thread pool to be a car watchdog client.
+    ABinderProcess_setThreadPoolMaxThreadCount(1);
+    ABinderProcess_startThreadPool();
+    sp<Looper> looper(Looper::prepare(0 /* opts */));
+    std::shared_ptr<WatchdogClient> watchdogClient =
+            ndk::SharedRefBase::make<WatchdogClient>(looper, service.get());
+    // The current health check is done in the main thread, so it falls short of capturing the real
+    // situation. Checking through HAL binder thread should be considered.
+    if (!watchdogClient->initialize()) {
+        ALOGE("Failed to initialize car watchdog client");
+        return 1;
+    }
     ALOGI("Ready");
-    joinRpcThreadpool();
+    while (true) {
+        looper->pollAll(-1 /* timeoutMillis */);
+    }
 
     return 1;
 }
diff --git a/automotive/vehicle/2.0/default/common/include/vhal_v2_0/WatchdogClient.h b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/WatchdogClient.h
new file mode 100644
index 0000000..578606d
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/include/vhal_v2_0/WatchdogClient.h
@@ -0,0 +1,74 @@
+/*
+ * 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_WatchdogClient_H_
+#define android_hardware_automotive_vehicle_V2_0_WatchdogClient_H_
+
+#include "VehicleHalManager.h"
+
+#include <aidl/android/automotive/watchdog/BnCarWatchdog.h>
+#include <aidl/android/automotive/watchdog/BnCarWatchdogClient.h>
+#include <utils/Looper.h>
+#include <utils/Mutex.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+class WatchdogClient : public aidl::android::automotive::watchdog::BnCarWatchdogClient {
+  public:
+    explicit WatchdogClient(const ::android::sp<::android::Looper>& handlerLooper,
+                            VehicleHalManager* vhalManager);
+
+    ndk::ScopedAStatus checkIfAlive(
+            int32_t sessionId, aidl::android::automotive::watchdog::TimeoutLength timeout) override;
+    ndk::ScopedAStatus prepareProcessTermination() override;
+
+    bool initialize();
+
+  private:
+    class MessageHandlerImpl : public ::android::MessageHandler {
+      public:
+        explicit MessageHandlerImpl(WatchdogClient* client);
+        void handleMessage(const ::android::Message& message) override;
+
+      private:
+        WatchdogClient* mClient;
+    };
+
+  private:
+    void respondToWatchdog();
+    bool isClientHealthy() const;
+
+  private:
+    ::android::sp<::android::Looper> mHandlerLooper;
+    ::android::sp<MessageHandlerImpl> mMessageHandler;
+    std::shared_ptr<aidl::android::automotive::watchdog::ICarWatchdog> mWatchdogServer;
+    std::shared_ptr<aidl::android::automotive::watchdog::ICarWatchdogClient> mTestClient;
+    VehicleHalManager* mVhalManager;
+    ::android::Mutex mMutex;
+    int mCurrentSessionId GUARDED_BY(mMutex);
+};
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_automotive_vehicle_V2_0_WatchdogClient_H_
diff --git a/automotive/vehicle/2.0/default/common/src/WatchdogClient.cpp b/automotive/vehicle/2.0/default/common/src/WatchdogClient.cpp
new file mode 100644
index 0000000..c067216
--- /dev/null
+++ b/automotive/vehicle/2.0/default/common/src/WatchdogClient.cpp
@@ -0,0 +1,140 @@
+/*
+ * 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 "automotive.vehicle@2.0-watchdog"
+
+#include <common/include/vhal_v2_0/WatchdogClient.h>
+
+#include <android/binder_manager.h>
+#include <android/hardware/automotive/vehicle/2.0/types.h>
+
+using aidl::android::automotive::watchdog::ICarWatchdog;
+using aidl::android::automotive::watchdog::TimeoutLength;
+
+namespace {
+
+enum { WHAT_CHECK_ALIVE = 1 };
+
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace vehicle {
+namespace V2_0 {
+
+WatchdogClient::WatchdogClient(const sp<Looper>& handlerLooper, VehicleHalManager* vhalManager)
+    : mHandlerLooper(handlerLooper), mVhalManager(vhalManager), mCurrentSessionId(-1) {
+    mMessageHandler = new MessageHandlerImpl(this);
+}
+
+ndk::ScopedAStatus WatchdogClient::checkIfAlive(int32_t sessionId, TimeoutLength /*timeout*/) {
+    mHandlerLooper->removeMessages(mMessageHandler, WHAT_CHECK_ALIVE);
+    {
+        Mutex::Autolock lock(mMutex);
+        mCurrentSessionId = sessionId;
+    }
+    mHandlerLooper->sendMessage(mMessageHandler, Message(WHAT_CHECK_ALIVE));
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus WatchdogClient::prepareProcessTermination() {
+    return ndk::ScopedAStatus::ok();
+}
+
+bool WatchdogClient::initialize() {
+    ndk::SpAIBinder binder(
+            AServiceManager_getService("android.automotive.watchdog.ICarWatchdog/default"));
+    if (binder.get() == nullptr) {
+        ALOGE("Failed to get carwatchdog daemon");
+        return false;
+    }
+    std::shared_ptr<ICarWatchdog> server = ICarWatchdog::fromBinder(binder);
+    if (server == nullptr) {
+        ALOGE("Failed to connect to carwatchdog daemon");
+        return false;
+    }
+    mWatchdogServer = server;
+
+    binder = this->asBinder();
+    if (binder.get() == nullptr) {
+        ALOGE("Failed to get car watchdog client binder object");
+        return false;
+    }
+    std::shared_ptr<ICarWatchdogClient> client = ICarWatchdogClient::fromBinder(binder);
+    if (client == nullptr) {
+        ALOGE("Failed to get ICarWatchdogClient from binder");
+        return false;
+    }
+    mTestClient = client;
+    mWatchdogServer->registerClient(client, TimeoutLength::TIMEOUT_NORMAL);
+    ALOGI("Successfully registered the client to car watchdog server");
+    return true;
+}
+
+void WatchdogClient::respondToWatchdog() {
+    if (mWatchdogServer == nullptr) {
+        ALOGW("Cannot respond to car watchdog daemon: car watchdog daemon is not connected");
+        return;
+    }
+    int sessionId;
+    {
+        Mutex::Autolock lock(mMutex);
+        sessionId = mCurrentSessionId;
+    }
+    if (isClientHealthy()) {
+        ndk::ScopedAStatus status = mWatchdogServer->tellClientAlive(mTestClient, sessionId);
+        if (!status.isOk()) {
+            ALOGE("Failed to call tellClientAlive(session id = %d): %d", sessionId,
+                  status.getStatus());
+            return;
+        }
+    }
+}
+
+bool WatchdogClient::isClientHealthy() const {
+    // We consider that default vehicle HAL is healthy if we can get PERF_VEHICLE_SPEED value.
+    StatusCode status = StatusCode::TRY_AGAIN;
+    VehiclePropValue propValue = {.prop = (int32_t)VehicleProperty::PERF_VEHICLE_SPEED};
+    while (status == StatusCode::TRY_AGAIN) {
+        mVhalManager->get(propValue,
+                          [&propValue, &status](StatusCode s, const VehiclePropValue& v) {
+                              status = s;
+                              if (s == StatusCode::OK) {
+                                  propValue = v;
+                              }
+                          });
+    }
+    return status == StatusCode::OK;
+}
+
+WatchdogClient::MessageHandlerImpl::MessageHandlerImpl(WatchdogClient* client) : mClient(client) {}
+
+void WatchdogClient::MessageHandlerImpl::handleMessage(const Message& message) {
+    switch (message.what) {
+        case WHAT_CHECK_ALIVE:
+            mClient->respondToWatchdog();
+            break;
+        default:
+            ALOGW("Unknown message: %d", message.what);
+    }
+}
+
+}  // namespace V2_0
+}  // namespace vehicle
+}  // namespace automotive
+}  // namespace hardware
+}  // namespace android
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 b8a606a..16c33b9 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
@@ -1039,6 +1039,22 @@
         {
                 .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,
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
index c49fadc..a5c2930 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.cpp
@@ -30,11 +30,18 @@
 
 constexpr int INITIAL_USER_INFO = static_cast<int>(VehicleProperty::INITIAL_USER_INFO);
 constexpr int SWITCH_USER = static_cast<int>(VehicleProperty::SWITCH_USER);
+constexpr int CREATE_USER = static_cast<int>(VehicleProperty::CREATE_USER);
+constexpr int REMOVE_USER = static_cast<int>(VehicleProperty::REMOVE_USER);
+constexpr int USER_IDENTIFICATION_ASSOCIATION =
+        static_cast<int>(VehicleProperty::USER_IDENTIFICATION_ASSOCIATION);
 
 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;
@@ -50,17 +57,63 @@
             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 android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
+            return android::base::Error((int)StatusCode::INVALID_ARG)
                    << "Unsupported property: " << toString(value);
     }
 }
 
+android::base::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 android::base::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 android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
+                   << "not supported by User HAL";
+    }
+}
+
+android::base::Result<std::unique_ptr<VehiclePropValue>>
+EmulatedUserHal::onGetUserIdentificationAssociation(const VehiclePropValue& value) {
+    if (mSetUserIdentificationAssociationResponseFromCmd != nullptr) {
+        ALOGI("get(USER_IDENTIFICATION_ASSOCIATION): returning %s",
+              toString(*mSetUserIdentificationAssociationResponseFromCmd).c_str());
+        auto newValue = std::unique_ptr<VehiclePropValue>(
+                new VehiclePropValue(*mSetUserIdentificationAssociationResponseFromCmd));
+        // Must use the same requestId
+        if (value.value.int32Values.size() > 0) {
+            newValue->value.int32Values[0] = value.value.int32Values[0];
+        } else {
+            ALOGE("get(USER_IDENTIFICATION_ASSOCIATION): no requestId on %s",
+                  toString(value).c_str());
+        }
+        return newValue;
+    }
+    return defaultUserIdentificationAssociation(value);
+}
+
 android::base::Result<std::unique_ptr<VehiclePropValue>>
 EmulatedUserHal::onSetInitialUserInfoResponse(const VehiclePropValue& value) {
     if (value.value.int32Values.size() == 0) {
         ALOGE("set(INITIAL_USER_INFO): no int32values, ignoring it: %s", toString(value).c_str());
-        return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
+        return android::base::Error((int)StatusCode::INVALID_ARG)
                << "no int32values on " << toString(value);
     }
 
@@ -97,11 +150,20 @@
         const VehiclePropValue& value) {
     if (value.value.int32Values.size() == 0) {
         ALOGE("set(SWITCH_USER): no int32values, ignoring it: %s", toString(value).c_str());
-        return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
+        return android::base::Error((int)StatusCode::INVALID_ARG)
                << "no int32values on " << toString(value);
     }
 
     if (value.areaId != 0) {
+        if (value.value.int32Values.size() >= 2 &&
+            static_cast<SwitchUserMessageType>(value.value.int32Values[1]) ==
+                    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 {};
@@ -115,6 +177,20 @@
         return sendUserHalResponse(std::move(mSwitchUserResponseFromCmd), requestId);
     }
 
+    if (value.value.int32Values.size() > 1) {
+        auto messageType = static_cast<SwitchUserMessageType>(value.value.int32Values[1]);
+        switch (messageType) {
+            case SwitchUserMessageType::LEGACY_ANDROID_SWITCH:
+                ALOGI("request is LEGACY_ANDROID_SWITCH; ignoring it");
+                return {};
+            case SwitchUserMessageType::ANDROID_POST_SWITCH:
+                ALOGI("request is ANDROID_POST_SWITCH; ignoring it");
+                return {};
+            default:
+                break;
+        }
+    }
+
     // Returns default response
     auto updatedValue = std::unique_ptr<VehiclePropValue>(new VehiclePropValue);
     updatedValue->prop = SWITCH_USER;
@@ -130,6 +206,79 @@
     return updatedValue;
 }
 
+android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::onSetCreateUserResponse(
+        const VehiclePropValue& value) {
+    if (value.value.int32Values.size() == 0) {
+        ALOGE("set(CREATE_USER): no int32values, ignoring it: %s", toString(value).c_str());
+        return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
+               << "no int32values on " << toString(value);
+    }
+
+    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());
+
+    int32_t requestId = value.value.int32Values[0];
+    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 = std::unique_ptr<VehiclePropValue>(new VehiclePropValue);
+    updatedValue->prop = CREATE_USER;
+    updatedValue->timestamp = elapsedRealtimeNano();
+    updatedValue->value.int32Values.resize(2);
+    updatedValue->value.int32Values[0] = requestId;
+    updatedValue->value.int32Values[1] = (int32_t)CreateUserStatus::SUCCESS;
+
+    ALOGI("no lshal response; replying with SUCCESS: %s", toString(*updatedValue).c_str());
+
+    return updatedValue;
+}
+
+android::base::Result<std::unique_ptr<VehiclePropValue>>
+EmulatedUserHal::onSetUserIdentificationAssociation(const VehiclePropValue& value) {
+    if (value.value.int32Values.size() == 0) {
+        ALOGE("set(USER_IDENTIFICATION_ASSOCIATION): no int32values, ignoring it: %s",
+              toString(value).c_str());
+        return android::base::Error(static_cast<int>(StatusCode::INVALID_ARG))
+               << "no int32values on " << toString(value);
+    }
+
+    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());
+
+    int32_t requestId = value.value.int32Values[0];
+    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);
+}
+
+android::base::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 android::base::Error(static_cast<int>(StatusCode::NOT_AVAILABLE)) << "not set by lshal";
+}
+
 android::base::Result<std::unique_ptr<VehiclePropValue>> EmulatedUserHal::sendUserHalResponse(
         std::unique_ptr<VehiclePropValue> response, int32_t requestId) {
     switch (response->areaId) {
@@ -144,12 +293,12 @@
         case 3:
             ALOGD("not generating a property change event because of lshal prop: %s",
                   toString(*response).c_str());
-            return android::base::Error(static_cast<int>(StatusCode::NOT_AVAILABLE))
+            return android::base::Error((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 android::base::Error(static_cast<int>(StatusCode::INTERNAL_ERROR))
+            return android::base::Error((int)StatusCode::INTERNAL_ERROR)
                    << "invalid action on lshal response: " << toString(*response);
     }
 
@@ -175,6 +324,18 @@
     } 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
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
index b25efcb..db2f117 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedUserHal.h
@@ -46,7 +46,7 @@
     bool isSupported(int32_t prop);
 
     /**
-     * Lets the emulator handle the property.
+     * Lets the emulator set the property.
      *
      * @return updated property and StatusCode
      */
@@ -54,6 +54,14 @@
             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);
@@ -97,11 +105,39 @@
     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
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
index 02c00c1..a0b566d 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -92,12 +92,14 @@
     return sensorStore;
 }
 
-EmulatedVehicleHal::EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client)
+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) {
+      mVehicleClient(client),
+      mEmulatedUserHal(emulatedUserHal) {
     initStaticConfig();
     for (size_t i = 0; i < arraysize(kVehicleProperties); i++) {
         mPropStore->registerProperty(kVehicleProperties[i].config);
@@ -134,6 +136,8 @@
 VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::get(
         const VehiclePropValue& requestedPropValue, StatusCode* outStatus) {
     auto propId = requestedPropValue.prop;
+    ALOGV("get(%d)", propId);
+
     auto& pool = *getValuePool();
     VehiclePropValuePtr v = nullptr;
 
@@ -147,6 +151,26 @@
             *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);
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 cba4b8a..eb38d7d 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
@@ -30,6 +30,7 @@
 #include "vhal_v2_0/VehiclePropertyStore.h"
 
 #include "DefaultConfig.h"
+#include "EmulatedUserHal.h"
 #include "EmulatedVehicleConnector.h"
 #include "GeneratorHub.h"
 #include "VehicleEmulator.h"
@@ -45,8 +46,8 @@
 /** Implementation of VehicleHal that connected to emulator instead of real vehicle network. */
 class EmulatedVehicleHal : public EmulatedVehicleHalIface {
 public:
-    EmulatedVehicleHal(VehiclePropertyStore* propStore,
-                       VehicleHalClient* client);
+    EmulatedVehicleHal(VehiclePropertyStore* propStore, VehicleHalClient* client,
+                       EmulatedUserHal* emulatedUserHal = nullptr);
     ~EmulatedVehicleHal() = default;
 
     //  Methods from VehicleHal
@@ -90,6 +91,7 @@
     bool mInEmulator;
     bool mInitVhalValueOverride;
     std::vector<VehiclePropValue> mVehiclePropertiesOverride;
+    EmulatedUserHal* mEmulatedUserHal;
 };
 
 }  // impl
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
index ad5096e..36f2534 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/VehicleHalServer.cpp
@@ -41,6 +41,10 @@
     return mValuePool;
 }
 
+EmulatedUserHal* VehicleHalServer::getEmulatedUserHal() {
+    return &mEmulatedUserHal;
+}
+
 void VehicleHalServer::setValuePool(VehiclePropValuePool* valuePool) {
     if (!valuePool) {
         LOG(WARNING) << __func__ << ": Setting value pool to nullptr!";
@@ -197,6 +201,7 @@
         }
         return StatusCode::OK;
     }
+    LOG(DEBUG) << "onSetProperty(" << value.prop << ")";
 
     // Some properties need to be treated non-trivially
     switch (value.prop) {
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 2841fbe..fca78bc 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
@@ -38,6 +38,8 @@
     // Set the Property Value Pool used in this server
     void setValuePool(VehiclePropValuePool* valuePool);
 
+    EmulatedUserHal* getEmulatedUserHal();
+
   private:
     using VehiclePropValuePtr = recyclable_ptr<VehiclePropValue>;
 
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 31ba8ab..c5b9ed6 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
@@ -16,6 +16,7 @@
 cc_library_static {
     name: "android.hardware.automotive.vehicle@2.0-libproto-native",
     vendor: true,
+    host_supported: true,
     proto: {
         export_proto_headers: true,
         type: "lite",
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index ee34e42..f7a42e9 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -2527,21 +2527,28 @@
      * 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 "Admin", the
+     * 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]: -1    // userToSwitchOrCreate.userId (not used as user will be created)
-     * int32[3]:  8    // userToSwitchOrCreate.flags = ADMIN
-     * string: "Admin" // userNameToCreate
+     * 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
-     * user-related properties (INITIAL_USER_INFO, SWITCH_USER, CREATE_USER, REMOVE_USER,
-     *       and USER_IDENTIFICATION_ASSOCIATION).
+     * 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
@@ -2620,7 +2627,7 @@
      * 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[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)
@@ -2654,7 +2661,7 @@
      * 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 issuye an ANDROID_POST_SWITCH call which the same
+     * 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
@@ -2698,7 +2705,7 @@
      *    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 crentials, then
+     *    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
@@ -2811,9 +2818,13 @@
      * 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, updating the VehiclePropValue
+     * 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
@@ -2828,45 +2839,50 @@
      * 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]: 10  (Android user id)
-     * int32[1]: 0   (Android user flags)
-     * int32[2]: 2   (number of types queried)
-     * int32[3]: 1   (1st type queried, UserIdentificationAssociationType::KEY_FOB)
-     * int32[4]: 101 (2nd type queried, UserIdentificationAssociationType::CUSTOM_1)
+     * 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[9]: 2   (number of associations in the response)
-     * int32[1]: 1   (1st type: UserIdentificationAssociationType::KEY_FOB)
-     * int32[2]: 2   (1st value: UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER)
-     * int32[3]: 101 (2st type: UserIdentificationAssociationType::CUSTOM_1)
-     * int32[4]: 4   (2nd value: UserIdentificationAssociationValue::NOT_ASSOCIATED_ANY_USER)
+     * 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]: 10  (Android user id)
-     * int32[0]: 0   (Android user flags)
-     * int32[1]: 1   (number of associations being set)
-     * int32[2]: 101 (1st type: UserIdentificationAssociationType::CUSTOM_1)
-     * int32[3]: 1   (1st value: UserIdentificationAssociationSetValue::ASSOCIATE_CURRENT_USER)
+     * 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]: 2   (number of associations in the response)
-     * int32[1]: 101 (1st type: UserIdentificationAssociationType::CUSTOM_1)
-     * int32[2]: 1   (1st value: UserIdentificationAssociationValue::ASSOCIATED_CURRENT_USER)
+     * 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]: 10  (Android user id)
-     * int32[1]: 2   (number of types set)
-     * int32[2]: 1   (1st type: UserIdentificationAssociationType::KEY_FOB)
-     * int32[3]: 2   (1st value: UserIdentificationAssociationValue::DISASSOCIATE_CURRENT_USER)
-     * int32[3]: 101 (2nd type: UserIdentificationAssociationType::CUSTOM_1)
-     * int32[5]: 1   (2nd value: UserIdentificationAssociationValue::ASSOCIATE_CURRENT_USER)
+     * 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
@@ -4265,6 +4281,16 @@
      * Admin users have additional privileges such as permission to create other users.
      */
     ADMIN = 0x08,
+
+    /**
+     * Disabled users are marked for deletion.
+     */
+    DISABLED = 0x10,
+
+     /**
+     * Profile user is a profile of another user.
+     */
+    PROFILE = 0x20,
 };
 
 /**
@@ -4279,10 +4305,16 @@
     /** The current foreground user. */
     UserInfo currentUser;
 
-    /** Number of existing users (includes the current user). */
+    /**
+     * Number of existing users; includes the current user, recently removed users (with DISABLED
+     * flag), and profile users (with PROFILE flag).
+     */
     int32_t numberUsers;
 
-    /** List of existing users (includes the current user). */
+    /**
+     * List of existing users; includes the current user, recently removed users (with DISABLED
+     * flag), and profile users (with PROFILE flag).
+     */
     vec<UserInfo> existingUsers;
  };
 
@@ -4359,6 +4391,12 @@
     UserInfo userToSwitchOrCreate;
 
     /**
+     * System locales of the initial user (value will be passed as-is to
+     * android.provider.Settings.System.SYSTEM_LOCALES)
+     */
+    string userLocales;
+
+    /**
      * Name of the user that should be created.
      */
     string userNameToCreate;
@@ -4639,6 +4677,11 @@
  */
 struct UserIdentificationGetRequest {
     /**
+     * Id of the request being responded.
+     */
+    UserRequestId requestId;
+
+    /**
      * Information about the current foreground Android user.
      */
     UserInfo userInfo;
@@ -4662,6 +4705,11 @@
  */
 struct UserIdentificationSetRequest {
     /**
+     * Id of the request being responded.
+     */
+    UserRequestId requestId;
+
+    /**
      * Information about the current foreground Android user.
      */
     UserInfo userInfo;
@@ -4674,7 +4722,7 @@
     /**
      * Associations being set.
      */
-    vec<UserIdentificationAssociationSetValue> associations;
+    vec<UserIdentificationSetAssociation> associations;
 };
 
 /**
@@ -4685,6 +4733,11 @@
  */
 struct UserIdentificationResponse {
     /**
+     * Id of the request being responded.
+     */
+    UserRequestId requestId;
+
+    /**
      * Number of associations being returned.
      */
     int32_t numberAssociation;
diff --git a/biometrics/face/1.0/Android.bp b/biometrics/face/1.0/Android.bp
index ebb8668..dd406f9 100644
--- a/biometrics/face/1.0/Android.bp
+++ b/biometrics/face/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.biometrics.face@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IBiometricsFace.hal",
diff --git a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
index 7ac44a4..78f93af 100644
--- a/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
+++ b/biometrics/face/1.0/vts/functional/VtsHalBiometricsFaceV1_0TargetTest.cpp
@@ -28,6 +28,7 @@
 #include <chrono>
 #include <cstdint>
 #include <random>
+#include <thread>
 
 using android::sp;
 using android::hardware::hidl_vec;
@@ -144,7 +145,10 @@
         ASSERT_EQ(Status::OK, static_cast<Status>(ret2));
     }
 
-    void TearDown() override {}
+    void TearDown() override {
+        // Hack to allow the asynchronous operations to finish on time.
+        std::this_thread::sleep_for(std::chrono::milliseconds(250));
+    }
 
     sp<IBiometricsFace> mService;
     sp<FaceCallback> mCallback;
diff --git a/biometrics/face/1.1/Android.bp b/biometrics/face/1.1/Android.bp
new file mode 100644
index 0000000..14a86f1
--- /dev/null
+++ b/biometrics/face/1.1/Android.bp
@@ -0,0 +1,14 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.biometrics.face@1.1",
+    root: "android.hardware",
+    srcs: [
+        "IBiometricsFace.hal",
+    ],
+    interfaces: [
+        "android.hardware.biometrics.face@1.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/biometrics/face/1.1/IBiometricsFace.hal b/biometrics/face/1.1/IBiometricsFace.hal
new file mode 100644
index 0000000..84e7443
--- /dev/null
+++ b/biometrics/face/1.1/IBiometricsFace.hal
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+package android.hardware.biometrics.face@1.1;
+
+import @1.0::IBiometricsFace;
+import @1.0::Status;
+import @1.0::Feature;
+
+/**
+ * The HAL interface for biometric face authentication.
+ */
+interface IBiometricsFace extends @1.0::IBiometricsFace {
+    /**
+     * Enrolls a user's face for a remote client, for example Android Auto.
+     *
+     * The HAL implementation is responsible for creating a secure communication
+     * channel and receiving the enrollment images from a mobile device with
+     * face authentication hardware.
+     *
+     * Note that the Hardware Authentication Token must be valid for the
+     * duration of enrollment and thus should be explicitly invalidated by a
+     * call to revokeChallenge() when enrollment is complete, to reduce the
+     * window of opportunity to re-use the challenge and HAT. For example,
+     * Settings calls generateChallenge() once to allow the user to enroll one
+     * or more faces or toggle secure settings without having to re-enter the
+     * PIN/pattern/password. Once the user completes the operation, Settings
+     * invokes revokeChallenge() to close the transaction. If the HAT is expired,
+     * the implementation must invoke onError with UNABLE_TO_PROCESS.
+     *
+     * Requirements for using this API:
+     * - Mobile devices MUST NOT delegate enrollment to another device by calling
+     * this API. This feature is intended only to allow enrollment on devices
+     * where it is impossible to enroll locally on the device.
+     * - The path MUST be protected by a secret key with rollback protection.
+     * - Synchronizing between devices MUST be accomplished by having both
+     * devices agree on a secret PIN entered by the user (similar to BT
+     * pairing procedure) and use a salted version of that PIN plus other secret
+     * to encrypt traffic.
+     * - All communication to/from the remote device MUST be encrypted and signed
+     * to prevent image injection and other man-in-the-middle type attacks.
+     * - generateChallenge() and revokeChallenge() MUST be implemented on both
+     * remote and local host (e.g. hash the result of the remote host with a
+     * local secret before responding to the API call) and any transmission of
+     * the challenge between hosts MUST be signed to prevent man-in-the-middle
+     * attacks.
+     * - In the event of a lost connection, the result of the last
+     * generateChallenge() MUST be invalidated and the process started over.
+     * - Both the remote and local host MUST honor the timeout and invalidate the
+     * challenge.
+     *
+     * This method triggers the IBiometricsFaceClientCallback#onEnrollResult()
+     * method.
+     *
+     * @param hat A valid Hardware Authentication Token, generated as a result
+     *     of a generateChallenge() challenge being wrapped by the gatekeeper
+     *     after a successful strong authentication request.
+     * @param timeoutSec A timeout in seconds, after which this enroll
+     *     attempt is cancelled. Note that the framework can continue
+     *     enrollment by calling this again with a valid HAT. This timeout is
+     *     expected to be used to limit power usage if the device becomes idle
+     *     during enrollment. The implementation is expected to send
+     *     ERROR_TIMEOUT if this happens.
+     * @param disabledFeatures A list of features to be disabled during
+     *     enrollment. Note that all features are enabled by default.
+     * @return status The status of this method call.
+     */
+    enrollRemotely(vec<uint8_t> hat, uint32_t timeoutSec, vec<Feature> disabledFeatures)
+        generates (Status status);
+
+    /**
+     * Enrolls a user's face.
+     *
+     * Note that the Hardware Authentication Token must be valid for the
+     * duration of enrollment and thus should be explicitly invalidated by a
+     * call to revokeChallenge() when enrollment is complete, to reduce the
+     * window of opportunity to re-use the challenge and HAT. For example,
+     * Settings calls generateChallenge() once to allow the user to enroll one
+     * or more faces or toggle secure settings without having to re-enter the
+     * PIN/pattern/password. Once the user completes the operation, Settings
+     * invokes revokeChallenge() to close the transaction. If the HAT is expired,
+     * the implementation must invoke onError with UNABLE_TO_PROCESS.
+     *
+     * This method triggers the IBiometricsFaceClientCallback#onEnrollResult()
+     * method.
+     *
+     * @param hat A valid Hardware Authentication Token, generated as a result
+     *     of a generateChallenge() challenge being wrapped by the gatekeeper
+     *     after a successful strong authentication request.
+     * @param timeoutSec A timeout in seconds, after which this enroll
+     *     attempt is cancelled. Note that the framework can continue
+     *     enrollment by calling this again with a valid HAT. This timeout is
+     *     expected to be used to limit power usage if the device becomes idle
+     *     during enrollment. The implementation is expected to send
+     *     ERROR_TIMEOUT if this happens.
+     * @param disabledFeatures A list of features to be disabled during
+     *     enrollment. Note that all features are enabled by default.
+     * @param windowId optional ID of a camera preview window for a
+     *     single-camera device. Must be null if not used.
+     * @return status The status of this method call.
+     */
+    enroll_1_1(vec<uint8_t> hat, uint32_t timeoutSec, vec<Feature> disabledFeatures,
+        handle windowId) generates (Status status);
+};
diff --git a/biometrics/face/1.0/default/Android.bp b/biometrics/face/1.1/default/Android.bp
similarity index 84%
rename from biometrics/face/1.0/default/Android.bp
rename to biometrics/face/1.1/default/Android.bp
index d6ff087..360071f 100644
--- a/biometrics/face/1.0/default/Android.bp
+++ b/biometrics/face/1.1/default/Android.bp
@@ -15,10 +15,10 @@
  */
 
 cc_binary {
-    name: "android.hardware.biometrics.face@1.0-service.example",
+    name: "android.hardware.biometrics.face@1.1-service.example",
     defaults: ["hidl_defaults"],
     vendor: true,
-    init_rc: ["android.hardware.biometrics.face@1.0-service.rc"],
+    init_rc: ["android.hardware.biometrics.face@1.1-service.rc"],
     vintf_fragments: ["manifest_face_default.xml"],
     relative_install_path: "hw",
     proprietary: true,
@@ -31,5 +31,6 @@
         "libutils",
         "liblog",
         "android.hardware.biometrics.face@1.0",
+        "android.hardware.biometrics.face@1.1",
     ],
 }
diff --git a/biometrics/face/1.0/default/BiometricsFace.cpp b/biometrics/face/1.1/default/BiometricsFace.cpp
similarity index 81%
rename from biometrics/face/1.0/default/BiometricsFace.cpp
rename to biometrics/face/1.1/default/BiometricsFace.cpp
index 2dd6476..2143880 100644
--- a/biometrics/face/1.0/default/BiometricsFace.cpp
+++ b/biometrics/face/1.1/default/BiometricsFace.cpp
@@ -110,4 +110,20 @@
     return Status::OK;
 }
 
+// Methods from ::android::hardware::biometrics::face::V1_1::IBiometricsFace follow.
+Return<Status> BiometricsFace::enroll_1_1(const hidl_vec<uint8_t>& /* hat */,
+                                          uint32_t /* timeoutSec */,
+                                          const hidl_vec<Feature>& /* disabledFeatures */,
+                                          const hidl_handle& /* windowId */) {
+    mClientCallback->onError(kDeviceId, mUserId, FaceError::UNABLE_TO_PROCESS, 0 /* vendorCode */);
+    return Status::OK;
+}
+
+Return<Status> BiometricsFace::enrollRemotely(const hidl_vec<uint8_t>& /* hat */,
+                                              uint32_t /* timeoutSec */,
+                                              const hidl_vec<Feature>& /* disabledFeatures */) {
+    mClientCallback->onError(kDeviceId, mUserId, FaceError::UNABLE_TO_PROCESS, 0 /* vendorCode */);
+    return Status::OK;
+}
+
 }  // namespace android::hardware::biometrics::face::implementation
diff --git a/biometrics/face/1.0/default/BiometricsFace.h b/biometrics/face/1.1/default/BiometricsFace.h
similarity index 81%
rename from biometrics/face/1.0/default/BiometricsFace.h
rename to biometrics/face/1.1/default/BiometricsFace.h
index 1d99ed2..5ce5771 100644
--- a/biometrics/face/1.0/default/BiometricsFace.h
+++ b/biometrics/face/1.1/default/BiometricsFace.h
@@ -16,7 +16,7 @@
 
 #pragma once
 
-#include <android/hardware/biometrics/face/1.0/IBiometricsFace.h>
+#include <android/hardware/biometrics/face/1.1/IBiometricsFace.h>
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 #include <random>
@@ -34,7 +34,7 @@
 using ::android::hardware::biometrics::face::V1_0::IBiometricsFaceClientCallback;
 using ::android::hardware::biometrics::face::V1_0::Status;
 
-class BiometricsFace : public V1_0::IBiometricsFace {
+class BiometricsFace : public V1_1::IBiometricsFace {
   public:
     BiometricsFace();
 
@@ -71,6 +71,14 @@
 
     Return<Status> resetLockout(const hidl_vec<uint8_t>& hat) override;
 
+    // Methods from ::android::hardware::biometrics::face::V1_1::IBiometricsFace follow.
+    Return<Status> enroll_1_1(const hidl_vec<uint8_t>& hat, uint32_t timeoutSec,
+                              const hidl_vec<Feature>& disabledFeatures,
+                              const hidl_handle& windowId) override;
+
+    Return<Status> enrollRemotely(const hidl_vec<uint8_t>& hat, uint32_t timeoutSec,
+                                  const hidl_vec<Feature>& disabledFeatures) override;
+
   private:
     std::mt19937 mRandom;
     int32_t mUserId;
diff --git a/biometrics/face/1.0/default/android.hardware.biometrics.face@1.0-service.rc b/biometrics/face/1.1/default/android.hardware.biometrics.face@1.1-service.rc
similarity index 75%
rename from biometrics/face/1.0/default/android.hardware.biometrics.face@1.0-service.rc
rename to biometrics/face/1.1/default/android.hardware.biometrics.face@1.1-service.rc
index 6c7362f..687e2d8 100644
--- a/biometrics/face/1.0/default/android.hardware.biometrics.face@1.0-service.rc
+++ b/biometrics/face/1.1/default/android.hardware.biometrics.face@1.1-service.rc
@@ -1,4 +1,4 @@
-service vendor.face-hal-1-0-default /vendor/bin/hw/android.hardware.biometrics.face@1.0-service.example
+service vendor.face-hal-1-1-default /vendor/bin/hw/android.hardware.biometrics.face@1.1-service.example
     # "class hal" causes a race condition on some devices due to files created
     # in /data. As a workaround, postpone startup until later in boot once
     # /data is mounted.
diff --git a/biometrics/face/1.0/default/manifest_face_default.xml b/biometrics/face/1.1/default/manifest_face_default.xml
similarity index 90%
rename from biometrics/face/1.0/default/manifest_face_default.xml
rename to biometrics/face/1.1/default/manifest_face_default.xml
index 380ae49..ec71d9c 100644
--- a/biometrics/face/1.0/default/manifest_face_default.xml
+++ b/biometrics/face/1.1/default/manifest_face_default.xml
@@ -2,7 +2,7 @@
     <hal format="hidl">
         <name>android.hardware.biometrics.face</name>
         <transport>hwbinder</transport>
-        <version>1.0</version>
+        <version>1.1</version>
         <interface>
             <name>IBiometricsFace</name>
             <instance>default</instance>
diff --git a/biometrics/face/1.0/default/service.cpp b/biometrics/face/1.1/default/service.cpp
similarity index 88%
rename from biometrics/face/1.0/default/service.cpp
rename to biometrics/face/1.1/default/service.cpp
index 9818c95..344bdb9 100644
--- a/biometrics/face/1.0/default/service.cpp
+++ b/biometrics/face/1.1/default/service.cpp
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "android.hardware.biometrics.face@1.0-service"
+#define LOG_TAG "android.hardware.biometrics.face@1.1-service"
 
 #include <android/hardware/biometrics/face/1.0/types.h>
-#include <android/hardware/biometrics/face/1.0/IBiometricsFace.h>
+#include <android/hardware/biometrics/face/1.1/IBiometricsFace.h>
 #include <android/log.h>
 #include <hidl/HidlSupport.h>
 #include <hidl/HidlTransportSupport.h>
@@ -27,7 +27,7 @@
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
 using android::hardware::biometrics::face::implementation::BiometricsFace;
-using android::hardware::biometrics::face::V1_0::IBiometricsFace;
+using android::hardware::biometrics::face::V1_1::IBiometricsFace;
 
 int main() {
     ALOGI("BiometricsFace HAL is being started.");
diff --git a/biometrics/face/1.0/default/Android.bp b/biometrics/face/1.1/vts/functional/Android.bp
similarity index 60%
copy from biometrics/face/1.0/default/Android.bp
copy to biometrics/face/1.1/vts/functional/Android.bp
index d6ff087..aa0b1fa 100644
--- a/biometrics/face/1.0/default/Android.bp
+++ b/biometrics/face/1.1/vts/functional/Android.bp
@@ -14,22 +14,16 @@
  * limitations under the License.
  */
 
-cc_binary {
-    name: "android.hardware.biometrics.face@1.0-service.example",
-    defaults: ["hidl_defaults"],
-    vendor: true,
-    init_rc: ["android.hardware.biometrics.face@1.0-service.rc"],
-    vintf_fragments: ["manifest_face_default.xml"],
-    relative_install_path: "hw",
-    proprietary: true,
-    srcs: [
-        "BiometricsFace.cpp",
-        "service.cpp",
-    ],
-    shared_libs: [
-        "libhidlbase",
-        "libutils",
-        "liblog",
+cc_test {
+    name: "VtsHalBiometricsFaceV1_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalBiometricsFaceV1_1TargetTest.cpp"],
+    static_libs: [
         "android.hardware.biometrics.face@1.0",
+        "android.hardware.biometrics.face@1.1",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
     ],
 }
diff --git a/biometrics/face/1.1/vts/functional/VtsHalBiometricsFaceV1_1TargetTest.cpp b/biometrics/face/1.1/vts/functional/VtsHalBiometricsFaceV1_1TargetTest.cpp
new file mode 100644
index 0000000..a105d8f
--- /dev/null
+++ b/biometrics/face/1.1/vts/functional/VtsHalBiometricsFaceV1_1TargetTest.cpp
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "biometrics_face_hidl_hal_test"
+
+#include <android/hardware/biometrics/face/1.0/IBiometricsFaceClientCallback.h>
+#include <android/hardware/biometrics/face/1.1/IBiometricsFace.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <android-base/logging.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include <chrono>
+#include <cstdint>
+#include <random>
+
+using android::sp;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::biometrics::face::V1_0::FaceAcquiredInfo;
+using android::hardware::biometrics::face::V1_0::FaceError;
+using android::hardware::biometrics::face::V1_0::IBiometricsFaceClientCallback;
+using android::hardware::biometrics::face::V1_0::OptionalUint64;
+using android::hardware::biometrics::face::V1_0::Status;
+using android::hardware::biometrics::face::V1_1::IBiometricsFace;
+
+namespace {
+
+// Arbitrary, nonexistent userId
+constexpr uint32_t kUserId = 9;
+constexpr uint32_t kTimeoutSec = 3;
+constexpr auto kTimeout = std::chrono::seconds(kTimeoutSec);
+constexpr char kFacedataDir[] = "/data/vendor_de/0/facedata";
+constexpr char kCallbackNameOnError[] = "onError";
+
+// Callback arguments that need to be captured for the tests.
+struct FaceCallbackArgs {
+    // The error passed to the last onError() callback.
+    FaceError error;
+
+    // The userId passed to the last callback.
+    int32_t userId;
+};
+
+// Test callback class for the BiometricsFace HAL.
+// The HAL will call these callback methods to notify about completed operations
+// or encountered errors.
+class FaceCallback : public ::testing::VtsHalHidlTargetCallbackBase<FaceCallbackArgs>,
+                     public IBiometricsFaceClientCallback {
+  public:
+    Return<void> onEnrollResult(uint64_t, uint32_t, int32_t, uint32_t) override { return Void(); }
+
+    Return<void> onAuthenticated(uint64_t, uint32_t, int32_t, const hidl_vec<uint8_t>&) override {
+        return Void();
+    }
+
+    Return<void> onAcquired(uint64_t, int32_t, FaceAcquiredInfo, int32_t) override {
+        return Void();
+    }
+
+    Return<void> onError(uint64_t, int32_t userId, FaceError error, int32_t) override {
+        FaceCallbackArgs args = {};
+        args.error = error;
+        args.userId = userId;
+        NotifyFromCallback(kCallbackNameOnError, args);
+        return Void();
+    }
+
+    Return<void> onRemoved(uint64_t, const hidl_vec<uint32_t>&, int32_t) override { return Void(); }
+
+    Return<void> onEnumerate(uint64_t, const hidl_vec<uint32_t>&, int32_t) override {
+        return Void();
+    }
+
+    Return<void> onLockoutChanged(uint64_t) override { return Void(); }
+};
+
+// Test class for the BiometricsFace HAL.
+class FaceHidlTest : public ::testing::TestWithParam<std::string> {
+  public:
+    void SetUp() override {
+        mService = IBiometricsFace::getService(GetParam());
+        ASSERT_NE(mService, nullptr);
+        mCallback = new FaceCallback();
+        mCallback->SetWaitTimeoutDefault(kTimeout);
+        Return<void> ret1 = mService->setCallback(mCallback, [](const OptionalUint64& res) {
+            ASSERT_EQ(Status::OK, res.status);
+            // Makes sure the "deviceId" represented by "res.value" is not 0.
+            // 0 would mean the HIDL is not available.
+            ASSERT_NE(0UL, res.value);
+        });
+        ASSERT_TRUE(ret1.isOk());
+        Return<Status> ret2 = mService->setActiveUser(kUserId, kFacedataDir);
+        ASSERT_EQ(Status::OK, static_cast<Status>(ret2));
+    }
+
+    void TearDown() override {}
+
+    sp<IBiometricsFace> mService;
+    sp<FaceCallback> mCallback;
+};
+
+// enroll with an invalid (all zeroes) HAT should fail.
+TEST_P(FaceHidlTest, Enroll1_1ZeroHatTest) {
+    // Filling HAT with zeros
+    hidl_vec<uint8_t> token(69);
+    for (size_t i = 0; i < 69; i++) {
+        token[i] = 0;
+    }
+
+    hidl_handle windowId = nullptr;
+    Return<Status> ret = mService->enroll_1_1(token, kTimeoutSec, {}, windowId);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
+
+    // onError should be called with a meaningful (nonzero) error.
+    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(kUserId, res.args->userId);
+    EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
+}
+
+// enroll with an invalid HAT should fail.
+TEST_P(FaceHidlTest, Enroll1_1GarbageHatTest) {
+    // Filling HAT with pseudorandom invalid data.
+    // Using default seed to make the test reproducible.
+    std::mt19937 gen(std::mt19937::default_seed);
+    std::uniform_int_distribution<uint8_t> dist;
+    hidl_vec<uint8_t> token(69);
+    for (size_t i = 0; i < 69; ++i) {
+        token[i] = dist(gen);
+    }
+
+    hidl_handle windowId = nullptr;
+    Return<Status> ret = mService->enroll_1_1(token, kTimeoutSec, {}, windowId);
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
+
+    // onError should be called with a meaningful (nonzero) error.
+    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(kUserId, res.args->userId);
+    EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
+}
+
+// enroll with an invalid (all zeroes) HAT should fail.
+TEST_P(FaceHidlTest, EnrollRemotelyZeroHatTest) {
+    // Filling HAT with zeros
+    hidl_vec<uint8_t> token(69);
+    for (size_t i = 0; i < 69; i++) {
+        token[i] = 0;
+    }
+
+    Return<Status> ret = mService->enrollRemotely(token, kTimeoutSec, {});
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
+
+    // onError should be called with a meaningful (nonzero) error.
+    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(kUserId, res.args->userId);
+    EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
+}
+
+// enroll with an invalid HAT should fail.
+TEST_P(FaceHidlTest, EnrollRemotelyGarbageHatTest) {
+    // Filling HAT with pseudorandom invalid data.
+    // Using default seed to make the test reproducible.
+    std::mt19937 gen(std::mt19937::default_seed);
+    std::uniform_int_distribution<uint8_t> dist;
+    hidl_vec<uint8_t> token(69);
+    for (size_t i = 0; i < 69; ++i) {
+        token[i] = dist(gen);
+    }
+
+    Return<Status> ret = mService->enrollRemotely(token, kTimeoutSec, {});
+    ASSERT_EQ(Status::OK, static_cast<Status>(ret));
+
+    // onError should be called with a meaningful (nonzero) error.
+    auto res = mCallback->WaitForCallback(kCallbackNameOnError);
+    EXPECT_TRUE(res.no_timeout);
+    EXPECT_EQ(kUserId, res.args->userId);
+    EXPECT_EQ(FaceError::UNABLE_TO_PROCESS, res.args->error);
+}
+
+}  // anonymous namespace
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, FaceHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBiometricsFace::descriptor)),
+        android::hardware::PrintInstanceNameToString);
diff --git a/biometrics/fingerprint/2.1/Android.bp b/biometrics/fingerprint/2.1/Android.bp
index c8cc0f1..25bd48d 100644
--- a/biometrics/fingerprint/2.1/Android.bp
+++ b/biometrics/fingerprint/2.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.biometrics.fingerprint@2.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IBiometricsFingerprint.hal",
diff --git a/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp b/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp
index bdbf72d..6093caa 100644
--- a/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp
+++ b/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp
@@ -49,7 +49,7 @@
 static const std::chrono::seconds kTimeoutInSeconds = std::chrono::seconds(kTimeout);
 static const uint32_t kGroupId = 99;
 static std::string kTmpDir = "";
-static const uint32_t kIterations = 1000;
+static const uint32_t kIterations = 10;
 
 // 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
diff --git a/biometrics/fingerprint/2.2/Android.bp b/biometrics/fingerprint/2.2/Android.bp
index 6c769ac..a8f202c 100644
--- a/biometrics/fingerprint/2.2/Android.bp
+++ b/biometrics/fingerprint/2.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.biometrics.fingerprint@2.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IBiometricsFingerprint.hal",
diff --git a/biometrics/fingerprint/2.3/Android.bp b/biometrics/fingerprint/2.3/Android.bp
new file mode 100644
index 0000000..cf63502
--- /dev/null
+++ b/biometrics/fingerprint/2.3/Android.bp
@@ -0,0 +1,15 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.biometrics.fingerprint@2.3",
+    root: "android.hardware",
+    srcs: [
+        "IBiometricsFingerprint.hal",
+    ],
+    interfaces: [
+        "android.hardware.biometrics.fingerprint@2.1",
+        "android.hardware.biometrics.fingerprint@2.2",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/biometrics/fingerprint/2.3/IBiometricsFingerprint.hal b/biometrics/fingerprint/2.3/IBiometricsFingerprint.hal
new file mode 100644
index 0000000..13f03c5
--- /dev/null
+++ b/biometrics/fingerprint/2.3/IBiometricsFingerprint.hal
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics.fingerprint@2.3;
+
+import @2.2::IBiometricsFingerprint;
+
+/**
+ * The interface for biometric fingerprint authentication.
+ */
+interface IBiometricsFingerprint extends @2.2::IBiometricsFingerprint {
+    /**
+     * Returns whether the fingerprint sensor is an under-display fingerprint
+     * sensor.
+     * @param sensorId the unique sensor ID for which the operation should be
+     * performed.
+     * @return isUdfps indicating whether the specified sensor is an
+     * under-display fingerprint sensor.
+     */
+    isUdfps(uint32_t sensorId) generates (bool isUdfps);
+
+    /**
+     * Notifies about a touch occurring within the under-display fingerprint
+     * sensor area.
+     *
+     * It it assumed that the device can only have one active under-display
+     * fingerprint sensor at a time.
+     *
+     * If multiple fingers are detected within the sensor area, only the
+     * chronologically first event will be reported.
+     *
+     * @param x The screen x-coordinate of the center of the touch contact area, in
+     * display pixels.
+     * @param y The screen y-coordinate of the center of the touch contact area, in
+     * display pixels.
+     * @param minor The length of the minor axis of an ellipse that describes the
+     * touch area, in display pixels.
+     * @param major The length of the major axis of an ellipse that describes the
+     * touch area, in display pixels.
+     */
+    onFingerDown(uint32_t x, uint32_t y, float minor, float major);
+
+    /**
+     * Notifies about a finger leaving the under-display fingerprint sensor area.
+     *
+     * It it assumed that the device can only have one active under-display
+     * fingerprint sensor at a time.
+     *
+     * If multiple fingers have left the sensor area, only the finger which
+     * previously caused a "finger down" event will be reported.
+     */
+    onFingerUp();
+};
diff --git a/biometrics/fingerprint/2.3/vts/functional/Android.bp b/biometrics/fingerprint/2.3/vts/functional/Android.bp
new file mode 100644
index 0000000..521c0f4
--- /dev/null
+++ b/biometrics/fingerprint/2.3/vts/functional/Android.bp
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_test {
+    name: "VtsHalBiometricsFingerprintV2_3TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalBiometricsFingerprintV2_3TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.biometrics.fingerprint@2.1",
+        "android.hardware.biometrics.fingerprint@2.2",
+        "android.hardware.biometrics.fingerprint@2.3",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/biometrics/fingerprint/2.3/vts/functional/VtsHalBiometricsFingerprintV2_3TargetTest.cpp b/biometrics/fingerprint/2.3/vts/functional/VtsHalBiometricsFingerprintV2_3TargetTest.cpp
new file mode 100644
index 0000000..7242016
--- /dev/null
+++ b/biometrics/fingerprint/2.3/vts/functional/VtsHalBiometricsFingerprintV2_3TargetTest.cpp
@@ -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.
+ */
+
+#define ASSERT_OK(v) ASSERT_TRUE(v.isOk())
+
+#include <android/hardware/biometrics/fingerprint/2.3/IBiometricsFingerprint.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/ServiceManagement.h>
+
+namespace {
+
+namespace hidl_interface_2_3 = android::hardware::biometrics::fingerprint::V2_3;
+
+using hidl_interface_2_3::IBiometricsFingerprint;
+
+using android::sp;
+
+// Callback arguments that need to be captured for the tests.
+struct FingerprintCallbackArgs {};
+
+class FingerprintHidlTest : public ::testing::TestWithParam<std::string> {
+  public:
+    void SetUp() override {
+        mService = IBiometricsFingerprint::getService(GetParam());
+        ASSERT_NE(mService, nullptr);
+    }
+
+    sp<IBiometricsFingerprint> mService;
+};
+
+// This method returns true or false depending on the implementation.
+TEST_P(FingerprintHidlTest, isUdfpsTest) {
+    // Arbitrary ID
+    uint32_t sensorId = 1234;
+    ASSERT_OK(mService->isUdfps(sensorId));
+}
+
+// This method that doesn't return anything.
+TEST_P(FingerprintHidlTest, onFingerDownTest) {
+    ASSERT_OK(mService->onFingerDown(1, 2, 3.0f, 4.0f));
+}
+
+// This method that doesn't return anything.
+TEST_P(FingerprintHidlTest, onFingerUp) {
+    ASSERT_OK(mService->onFingerUp());
+}
+
+}  // anonymous namespace
+
+INSTANTIATE_TEST_SUITE_P(PerInstance, FingerprintHidlTest,
+                         testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+                                 IBiometricsFingerprint::descriptor)),
+                         android::hardware::PrintInstanceNameToString);
diff --git a/bluetooth/1.0/Android.bp b/bluetooth/1.0/Android.bp
index 7036d6e..1cac820 100644
--- a/bluetooth/1.0/Android.bp
+++ b/bluetooth/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.bluetooth@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IBluetoothHci.hal",
diff --git a/bluetooth/1.0/default/Android.bp b/bluetooth/1.0/default/Android.bp
index f66c25e..6e39d54 100644
--- a/bluetooth/1.0/default/Android.bp
+++ b/bluetooth/1.0/default/Android.bp
@@ -102,13 +102,13 @@
     srcs: [
         "bluetooth_address.cc",
         "test/bluetooth_address_test.cc",
-        "test/properties.cc",
     ],
     local_include_dirs: [
         "test",
     ],
     shared_libs: [
         "libbase",
+        "libcutils",
         "liblog",
     ],
 }
diff --git a/bluetooth/1.0/default/test/bluetooth_address_test.cc b/bluetooth/1.0/default/test/bluetooth_address_test.cc
index 2c8dbe5..ee52d33 100644
--- a/bluetooth/1.0/default/test/bluetooth_address_test.cc
+++ b/bluetooth/1.0/default/test/bluetooth_address_test.cc
@@ -120,95 +120,6 @@
   EXPECT_FALSE(memcmp(addrA, addrB, BluetoothAddress::kStringLength) == 0);
 }
 
-TEST_F(BluetoothAddressTest, property_set) {
-  // Set the properties to empty strings.
-  property_set(PERSIST_BDADDR_PROPERTY, "");
-  property_set(PROPERTY_BT_BDADDR_PATH, "");
-  property_set(FACTORY_BDADDR_PROPERTY, "");
-
-  // Get returns 0.
-  char prop[PROP_VALUE_MAX] = "";
-  EXPECT_TRUE(property_get(PERSIST_BDADDR_PROPERTY, prop, NULL) == 0);
-  EXPECT_TRUE(property_get(PROPERTY_BT_BDADDR_PATH, prop, NULL) == 0);
-  EXPECT_TRUE(property_get(FACTORY_BDADDR_PROPERTY, prop, NULL) == 0);
-
-  // Set the properties to known strings.
-  property_set(PERSIST_BDADDR_PROPERTY, "1");
-  property_set(PROPERTY_BT_BDADDR_PATH, "22");
-  property_set(FACTORY_BDADDR_PROPERTY, "333");
-
-  // Get returns the correct length.
-  EXPECT_TRUE(property_get(PERSIST_BDADDR_PROPERTY, prop, NULL) == 1);
-  EXPECT_TRUE(property_get(PROPERTY_BT_BDADDR_PATH, prop, NULL) == 2);
-  EXPECT_TRUE(property_get(FACTORY_BDADDR_PROPERTY, prop, NULL) == 3);
-
-  // Set the properties to empty strings again.
-  property_set(PERSIST_BDADDR_PROPERTY, "");
-  property_set(PROPERTY_BT_BDADDR_PATH, "");
-  property_set(FACTORY_BDADDR_PROPERTY, "");
-
-  // Get returns 0.
-  EXPECT_TRUE(property_get(PERSIST_BDADDR_PROPERTY, prop, NULL) == 0);
-  EXPECT_TRUE(property_get(PROPERTY_BT_BDADDR_PATH, prop, NULL) == 0);
-  EXPECT_TRUE(property_get(FACTORY_BDADDR_PROPERTY, prop, NULL) == 0);
-}
-
-TEST_F(BluetoothAddressTest, property_get) {
-  // Set the properties to known strings.
-  property_set(PERSIST_BDADDR_PROPERTY, PERSIST_BDADDR_PROPERTY);
-  property_set(PROPERTY_BT_BDADDR_PATH, PROPERTY_BT_BDADDR_PATH);
-  property_set(FACTORY_BDADDR_PROPERTY, FACTORY_BDADDR_PROPERTY);
-
-  // Get returns the same strings.
-  char prop[PROP_VALUE_MAX] = "";
-  EXPECT_TRUE(property_get(PERSIST_BDADDR_PROPERTY, prop, NULL) > 0);
-  EXPECT_TRUE(strcmp(PERSIST_BDADDR_PROPERTY, prop) == 0);
-
-  EXPECT_TRUE(property_get(PROPERTY_BT_BDADDR_PATH, prop, NULL) > 0);
-  EXPECT_TRUE(strcmp(PROPERTY_BT_BDADDR_PATH, prop) == 0);
-
-  EXPECT_TRUE(property_get(FACTORY_BDADDR_PROPERTY, prop, NULL) > 0);
-  EXPECT_TRUE(strcmp(FACTORY_BDADDR_PROPERTY, prop) == 0);
-
-  // Set a property to a different known string.
-  char prop2[PROP_VALUE_MAX] = "Erased";
-  property_set(PERSIST_BDADDR_PROPERTY, prop2);
-
-  // Get returns the correct strings.
-  EXPECT_TRUE(property_get(PERSIST_BDADDR_PROPERTY, prop, NULL) > 0);
-  EXPECT_TRUE(strcmp(prop2, prop) == 0);
-
-  EXPECT_TRUE(property_get(PROPERTY_BT_BDADDR_PATH, prop, NULL) > 0);
-  EXPECT_TRUE(strcmp(PROPERTY_BT_BDADDR_PATH, prop) == 0);
-
-  EXPECT_TRUE(property_get(FACTORY_BDADDR_PROPERTY, prop, NULL) > 0);
-  EXPECT_TRUE(strcmp(FACTORY_BDADDR_PROPERTY, prop) == 0);
-
-  // Set another property to prop2.
-  property_set(PROPERTY_BT_BDADDR_PATH, prop2);
-
-  EXPECT_TRUE(property_get(PERSIST_BDADDR_PROPERTY, prop, NULL) > 0);
-  EXPECT_TRUE(strcmp(prop2, prop) == 0);
-
-  EXPECT_TRUE(property_get(PROPERTY_BT_BDADDR_PATH, prop, NULL) > 0);
-  EXPECT_TRUE(strcmp(prop2, prop) == 0);
-
-  EXPECT_TRUE(property_get(FACTORY_BDADDR_PROPERTY, prop, NULL) > 0);
-  EXPECT_TRUE(strcmp(FACTORY_BDADDR_PROPERTY, prop) == 0);
-
-  // Set the third property to prop2.
-  property_set(FACTORY_BDADDR_PROPERTY, prop2);
-
-  EXPECT_TRUE(property_get(PERSIST_BDADDR_PROPERTY, prop, NULL) > 0);
-  EXPECT_TRUE(strcmp(prop2, prop) == 0);
-
-  EXPECT_TRUE(property_get(PROPERTY_BT_BDADDR_PATH, prop, NULL) > 0);
-  EXPECT_TRUE(strcmp(prop2, prop) == 0);
-
-  EXPECT_TRUE(property_get(FACTORY_BDADDR_PROPERTY, prop, NULL) > 0);
-  EXPECT_TRUE(strcmp(prop2, prop) == 0);
-}
-
 TEST_F(BluetoothAddressTest, get_local_address) {
   EXPECT_TRUE(property_set(PERSIST_BDADDR_PROPERTY, "") == 0);
   EXPECT_TRUE(property_set(FACTORY_BDADDR_PROPERTY, "") == 0);
diff --git a/bluetooth/1.0/default/test/properties.cc b/bluetooth/1.0/default/test/properties.cc
deleted file mode 100644
index 70de01e..0000000
--- a/bluetooth/1.0/default/test/properties.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-//
-// Copyright 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 "properties"
-
-#include <ctype.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <cutils/properties.h>
-#include <log/log.h>
-
-static const int MAX_PROPERTIES = 5;
-
-struct property {
-  char key[PROP_KEY_MAX + 2];
-  char value[PROP_VALUE_MAX + 2];
-};
-
-int num_properties = 0;
-struct property properties[MAX_PROPERTIES];
-
-// Find the correct entry.
-static int property_find(const char* key) {
-  for (int i = 0; i < num_properties; i++) {
-    if (strncmp(properties[i].key, key, PROP_KEY_MAX) == 0) {
-      return i;
-    }
-  }
-  return MAX_PROPERTIES;
-}
-
-int property_set(const char* key, const char* value) {
-  if (strnlen(value, PROP_VALUE_MAX) > PROP_VALUE_MAX) return -1;
-
-  // Check to see if the property exists.
-  int prop_index = property_find(key);
-
-  if (prop_index == MAX_PROPERTIES) {
-    if (num_properties >= MAX_PROPERTIES) return -1;
-    prop_index = num_properties;
-    num_properties += 1;
-  }
-
-  // This is test code.  Be nice and don't push the boundary cases!
-  strncpy(properties[prop_index].key, key, PROP_KEY_MAX + 1);
-  strncpy(properties[prop_index].value, value, PROP_VALUE_MAX + 1);
-  return 0;
-}
-
-int property_get(const char* key, char* value, const char* default_value) {
-  // This doesn't mock the behavior of default value
-  if (default_value != NULL) ALOGE("%s: default_value is ignored!", __func__);
-
-  // Check to see if the property exists.
-  int prop_index = property_find(key);
-
-  if (prop_index == MAX_PROPERTIES) return 0;
-
-  int len = strlen(properties[prop_index].value);
-  memcpy(value, properties[prop_index].value, len);
-  value[len] = '\0';
-  return len;
-}
diff --git a/bluetooth/1.0/default/test/sys/system_properties.h b/bluetooth/1.0/default/test/sys/system_properties.h
deleted file mode 100644
index b477a6b..0000000
--- a/bluetooth/1.0/default/test/sys/system_properties.h
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// Copyright 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.
-//
-
-// Mock sys/system_properties.h for testing
-
-#define PROP_VALUE_MAX 50
-#define PROP_KEY_MAX 50
diff --git a/bluetooth/1.0/vts/functional/Android.bp b/bluetooth/1.0/vts/functional/Android.bp
index 463ed84..e9f867f 100644
--- a/bluetooth/1.0/vts/functional/Android.bp
+++ b/bluetooth/1.0/vts/functional/Android.bp
@@ -26,4 +26,5 @@
         "general-tests",
         "vts",
     ],
+    disable_framework: true,
 }
diff --git a/bluetooth/1.1/Android.bp b/bluetooth/1.1/Android.bp
index 4204aed..c3967f0 100644
--- a/bluetooth/1.1/Android.bp
+++ b/bluetooth/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.bluetooth@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "IBluetoothHci.hal",
         "IBluetoothHciCallbacks.hal",
diff --git a/bluetooth/a2dp/1.0/Android.bp b/bluetooth/a2dp/1.0/Android.bp
index 02f224a..d9ec982 100644
--- a/bluetooth/a2dp/1.0/Android.bp
+++ b/bluetooth/a2dp/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.bluetooth.a2dp@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IBluetoothAudioHost.hal",
diff --git a/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp b/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp
index 44b138a..f7fdf31 100644
--- a/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp
+++ b/bluetooth/a2dp/1.0/vts/functional/VtsHalBluetoothA2dpV1_0TargetTest.cpp
@@ -107,4 +107,6 @@
     PerInstance, BluetoothA2dpHidlTest,
     testing::ValuesIn(android::hardware::getAllHalInstanceNames(
         IBluetoothAudioOffload::descriptor)),
-    android::hardware::PrintInstanceNameToString);
\ No newline at end of file
+    android::hardware::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BluetoothA2dpHidlTest);
diff --git a/bluetooth/audio/2.0/Android.bp b/bluetooth/audio/2.0/Android.bp
index 6bf0070..3fbd51f 100644
--- a/bluetooth/audio/2.0/Android.bp
+++ b/bluetooth/audio/2.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.bluetooth.audio@2.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IBluetoothAudioPort.hal",
diff --git a/bluetooth/audio/2.0/default/session/BluetoothAudioSession.cpp b/bluetooth/audio/2.0/default/session/BluetoothAudioSession.cpp
index d60e732..50119bf 100644
--- a/bluetooth/audio/2.0/default/session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/2.0/default/session/BluetoothAudioSession.cpp
@@ -90,14 +90,16 @@
 // bluetooth_audio outputs
 void BluetoothAudioSession::OnSessionEnded() {
   std::lock_guard<std::recursive_mutex> guard(mutex_);
-  if (IsSessionReady()) {
-    ReportSessionStatus();
-  }
+  bool toggled = IsSessionReady();
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
   audio_config_ = (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH
                        ? kInvalidOffloadAudioConfiguration
                        : kInvalidSoftwareAudioConfiguration);
   stack_iface_ = nullptr;
   UpdateDataPath(nullptr);
+  if (toggled) {
+    ReportSessionStatus();
+  }
 }
 
 // invoking the registered session_changed_cb_
diff --git a/bluetooth/audio/2.0/default/session/BluetoothAudioSupportedCodecsDB.cpp b/bluetooth/audio/2.0/default/session/BluetoothAudioSupportedCodecsDB.cpp
index 6ea61e1..c368197 100644
--- a/bluetooth/audio/2.0/default/session/BluetoothAudioSupportedCodecsDB.cpp
+++ b/bluetooth/audio/2.0/default/session/BluetoothAudioSupportedCodecsDB.cpp
@@ -74,7 +74,7 @@
     .objectType = AacObjectType::MPEG2_LC,
     .sampleRate = SampleRate::RATE_44100,
     .channelMode = ChannelMode::STEREO,
-    .variableBitRateEnabled = AacVariableBitRate::DISABLED,
+    .variableBitRateEnabled = AacVariableBitRate::ENABLED,
     .bitsPerSample = BitsPerSample::BITS_16};
 
 // LDAC: mSampleRate:(44100|48000|88200|96000), mBitsPerSample:(16|24|32),
diff --git a/boot/1.0/Android.bp b/boot/1.0/Android.bp
index 5568436..844cf9b 100644
--- a/boot/1.0/Android.bp
+++ b/boot/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.boot@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IBootControl.hal",
diff --git a/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp b/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
index fbddf6d..2f6b23e 100644
--- a/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
+++ b/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
@@ -80,8 +80,11 @@
     }
 }
 
-// Sanity check Boot::setActiveBootSlot() on good and bad inputs.
 TEST_P(BootHidlTest, SetActiveBootSlot) {
+    Slot curSlot = boot->getCurrentSlot();
+    Slot otherSlot = curSlot ? 0 : 1;
+    auto otherBootable = boot->isSlotBootable(otherSlot);
+
     for (Slot s = 0; s < 2; s++) {
         CommandResult cr;
         Return<void> result = boot->setActiveBootSlot(s, generate_callback(&cr));
@@ -90,7 +93,17 @@
     {
         // Restore original flags to avoid problems on reboot
         CommandResult cr;
-        Return<void> result = boot->markBootSuccessful(generate_callback(&cr));
+        auto result = boot->setActiveBootSlot(curSlot, generate_callback(&cr));
+        EXPECT_TRUE(result.isOk());
+        EXPECT_TRUE(cr.success);
+
+        if (otherBootable == BoolResult::FALSE) {
+            result = boot->setSlotAsUnbootable(otherSlot, generate_callback(&cr));
+            EXPECT_TRUE(result.isOk());
+            EXPECT_TRUE(cr.success);
+        }
+
+        result = boot->markBootSuccessful(generate_callback(&cr));
         EXPECT_TRUE(result.isOk());
         EXPECT_TRUE(cr.success);
     }
@@ -103,21 +116,23 @@
     }
 }
 
-// Sanity check Boot::setSlotAsUnbootable() on good and bad inputs.
 TEST_P(BootHidlTest, SetSlotAsUnbootable) {
+    Slot curSlot = boot->getCurrentSlot();
+    Slot otherSlot = curSlot ? 0 : 1;
+    auto otherBootable = boot->isSlotBootable(otherSlot);
     {
         CommandResult cr;
-        Slot curSlot = boot->getCurrentSlot();
-        Slot otherSlot = curSlot ? 0 : 1;
         Return<void> result = boot->setSlotAsUnbootable(otherSlot, generate_callback(&cr));
         EXPECT_TRUE(result.isOk());
         if (cr.success) {
             EXPECT_EQ(BoolResult::FALSE, boot->isSlotBootable(otherSlot));
 
             // Restore original flags to avoid problems on reboot
-            result = boot->setActiveBootSlot(otherSlot, generate_callback(&cr));
-            EXPECT_TRUE(result.isOk());
-            EXPECT_TRUE(cr.success);
+            if (otherBootable == BoolResult::TRUE) {
+                result = boot->setActiveBootSlot(otherSlot, generate_callback(&cr));
+                EXPECT_TRUE(result.isOk());
+                EXPECT_TRUE(cr.success);
+            }
             result = boot->setActiveBootSlot(curSlot, generate_callback(&cr));
             EXPECT_TRUE(result.isOk());
             EXPECT_TRUE(cr.success);
diff --git a/boot/1.1/Android.bp b/boot/1.1/Android.bp
index 6a8d57a..3f505e6 100644
--- a/boot/1.1/Android.bp
+++ b/boot/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.boot@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IBootControl.hal",
diff --git a/broadcastradio/1.0/Android.bp b/broadcastradio/1.0/Android.bp
index 8239d74..5fc120d 100644
--- a/broadcastradio/1.0/Android.bp
+++ b/broadcastradio/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.broadcastradio@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IBroadcastRadio.hal",
diff --git a/broadcastradio/1.1/Android.bp b/broadcastradio/1.1/Android.bp
index 1cc9b62..5efa3d4 100644
--- a/broadcastradio/1.1/Android.bp
+++ b/broadcastradio/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.broadcastradio@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IBroadcastRadio.hal",
diff --git a/broadcastradio/2.0/Android.bp b/broadcastradio/2.0/Android.bp
index 1040ba1..0ef635e 100644
--- a/broadcastradio/2.0/Android.bp
+++ b/broadcastradio/2.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.broadcastradio@2.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IAnnouncementListener.hal",
diff --git a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
index d170a6d..694d52a 100644
--- a/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
+++ b/broadcastradio/2.0/vts/functional/VtsHalBroadcastradioV2_0TargetTest.cpp
@@ -116,7 +116,10 @@
 };
 
 static void printSkipped(std::string msg) {
-    std::cout << "[  SKIPPED ] " << msg << std::endl;
+    const auto testInfo = testing::UnitTest::GetInstance()->current_test_info();
+    std::cout << "[  SKIPPED ] " << testInfo->test_case_name() << "." << testInfo->name()
+              << std::endl;
+    std::cout << msg << std::endl;
 }
 
 MATCHER_P(InfoHasId, id,
@@ -428,8 +431,9 @@
     ProgramInfo infoCb = {};
     EXPECT_TIMEOUT_CALL(*mCallback, onCurrentProgramInfoChanged_,
                         InfoHasId(utils::make_identifier(IdentifierType::AMFM_FREQUENCY, freq)))
-        .Times(AnyNumber())
-        .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))));
+            .Times(AnyNumber())
+            .WillOnce(DoAll(SaveArg<0>(&infoCb), testing::Return(ByMove(Void()))))
+            .WillRepeatedly(testing::InvokeWithoutArgs([] { return Void(); }));
     auto result = mSession->tune(sel);
 
     // expect a failure if it's not supported
diff --git a/camera/common/1.0/Android.bp b/camera/common/1.0/Android.bp
index ed64060..bd00dbb 100644
--- a/camera/common/1.0/Android.bp
+++ b/camera/common/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.camera.common@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
     ],
diff --git a/camera/common/1.0/default/Android.bp b/camera/common/1.0/default/Android.bp
index f4390b2..3b8b239 100644
--- a/camera/common/1.0/default/Android.bp
+++ b/camera/common/1.0/default/Android.bp
@@ -8,7 +8,7 @@
         "CameraParameters.cpp",
         "VendorTagDescriptor.cpp",
         "HandleImporter.cpp",
-        "Exif.cpp"
+        "Exif.cpp",
     ],
     cflags: [
         "-Werror",
@@ -17,6 +17,7 @@
     ],
     shared_libs: [
         "liblog",
+        "libgralloctypes",
         "libhardware",
         "libcamera_metadata",
         "android.hardware.graphics.mapper@2.0",
@@ -25,6 +26,5 @@
         "libexif",
     ],
     include_dirs: ["system/media/private/camera/include"],
-    export_include_dirs : ["include"]
+    export_include_dirs: ["include"],
 }
-
diff --git a/camera/common/1.0/default/HandleImporter.cpp b/camera/common/1.0/default/HandleImporter.cpp
index 7792b31..05a552c 100644
--- a/camera/common/1.0/default/HandleImporter.cpp
+++ b/camera/common/1.0/default/HandleImporter.cpp
@@ -16,6 +16,8 @@
 
 #define LOG_TAG "HandleImporter"
 #include "HandleImporter.h"
+
+#include <gralloctypes/Gralloc4.h>
 #include <log/log.h>
 
 namespace android {
@@ -25,6 +27,9 @@
 namespace V1_0 {
 namespace helper {
 
+using aidl::android::hardware::graphics::common::PlaneLayout;
+using aidl::android::hardware::graphics::common::PlaneLayoutComponent;
+using aidl::android::hardware::graphics::common::PlaneLayoutComponentType;
 using MapperErrorV2 = android::hardware::graphics::mapper::V2_0::Error;
 using MapperErrorV3 = android::hardware::graphics::mapper::V3_0::Error;
 using MapperErrorV4 = android::hardware::graphics::mapper::V4_0::Error;
@@ -118,6 +123,79 @@
     return layout;
 }
 
+template <>
+YCbCrLayout HandleImporter::lockYCbCrInternal<IMapperV4, MapperErrorV4>(
+        const sp<IMapperV4> mapper, buffer_handle_t& buf, uint64_t cpuUsage,
+        const IMapper::Rect& accessRegion) {
+    hidl_handle acquireFenceHandle;
+    auto buffer = const_cast<native_handle_t*>(buf);
+    YCbCrLayout layout = {};
+    void* mapped = nullptr;
+
+    typename IMapperV4::Rect accessRegionV4 = {accessRegion.left, accessRegion.top,
+                                               accessRegion.width, accessRegion.height};
+    mapper->lock(buffer, cpuUsage, accessRegionV4, acquireFenceHandle,
+                 [&](const auto& tmpError, const auto& tmpPtr) {
+                     if (tmpError == MapperErrorV4::NONE) {
+                         mapped = tmpPtr;
+                     } else {
+                         ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
+                     }
+                 });
+
+    if (mapped == nullptr) {
+        return layout;
+    }
+
+    hidl_vec<uint8_t> encodedPlaneLayouts;
+    mapper->get(buffer, gralloc4::MetadataType_PlaneLayouts,
+                [&](const auto& tmpError, const auto& tmpEncodedPlaneLayouts) {
+                    if (tmpError == MapperErrorV4::NONE) {
+                        encodedPlaneLayouts = tmpEncodedPlaneLayouts;
+                    } else {
+                        ALOGE("%s: failed to get plane layouts %d!", __FUNCTION__, tmpError);
+                    }
+                });
+
+    std::vector<PlaneLayout> planeLayouts;
+    gralloc4::decodePlaneLayouts(encodedPlaneLayouts, &planeLayouts);
+
+    for (const auto& planeLayout : planeLayouts) {
+        for (const auto& planeLayoutComponent : planeLayout.components) {
+            const auto& type = planeLayoutComponent.type;
+
+            if (!gralloc4::isStandardPlaneLayoutComponentType(type)) {
+                continue;
+            }
+
+            uint8_t* data = reinterpret_cast<uint8_t*>(mapped);
+            data += planeLayout.offsetInBytes;
+            data += planeLayoutComponent.offsetInBits / 8;
+
+            switch (static_cast<PlaneLayoutComponentType>(type.value)) {
+                case PlaneLayoutComponentType::Y:
+                    layout.y = data;
+                    layout.yStride = planeLayout.strideInBytes;
+                    break;
+                case PlaneLayoutComponentType::CB:
+                    layout.cb = data;
+                    layout.cStride = planeLayout.strideInBytes;
+                    layout.chromaStep = planeLayout.sampleIncrementInBits / 8;
+                    break;
+                case PlaneLayoutComponentType::CR:
+                    layout.cr = data;
+                    layout.cStride = planeLayout.strideInBytes;
+                    layout.chromaStep = planeLayout.sampleIncrementInBits / 8;
+                    break;
+                default:
+                    break;
+            }
+        }
+    }
+
+    return layout;
+}
+
 template<class M, class E>
 int HandleImporter::unlockInternal(const sp<M> mapper, buffer_handle_t& buf) {
     int releaseFence = -1;
@@ -232,13 +310,20 @@
 
 void* HandleImporter::lock(
         buffer_handle_t& buf, uint64_t cpuUsage, size_t size) {
+    IMapper::Rect accessRegion{0, 0, static_cast<int>(size), 1};
+    return lock(buf, cpuUsage, accessRegion);
+}
+
+void* HandleImporter::lock(buffer_handle_t& buf, uint64_t cpuUsage,
+                           const IMapper::Rect& accessRegion) {
     Mutex::Autolock lock(mLock);
-    void *ret = 0;
 
     if (!mInitialized) {
         initializeLocked();
     }
 
+    void* ret = nullptr;
+
     if (mMapperV4 == nullptr && mMapperV3 == nullptr && mMapperV2 == nullptr) {
         ALOGE("%s: mMapperV4, mMapperV3 and mMapperV2 are all null!", __FUNCTION__);
         return ret;
@@ -247,10 +332,10 @@
     hidl_handle acquireFenceHandle;
     auto buffer = const_cast<native_handle_t*>(buf);
     if (mMapperV4 != nullptr) {
-        IMapperV4::Rect accessRegion{0, 0, static_cast<int>(size), 1};
-        // No need to use bytesPerPixel and bytesPerStride because we are using
-        // an 1-D buffer and accressRegion.
-        mMapperV4->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+        IMapperV4::Rect accessRegionV4{accessRegion.left, accessRegion.top, accessRegion.width,
+                                       accessRegion.height};
+
+        mMapperV4->lock(buffer, cpuUsage, accessRegionV4, acquireFenceHandle,
                         [&](const auto& tmpError, const auto& tmpPtr) {
                             if (tmpError == MapperErrorV4::NONE) {
                                 ret = tmpPtr;
@@ -259,33 +344,33 @@
                             }
                         });
     } else if (mMapperV3 != nullptr) {
-        IMapperV3::Rect accessRegion { 0, 0, static_cast<int>(size), 1 };
-        // No need to use bytesPerPixel and bytesPerStride because we are using
-        // an 1-D buffer and accressRegion.
-        mMapperV3->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
-                [&](const auto& tmpError, const auto& tmpPtr, const auto& /*bytesPerPixel*/,
-                        const auto& /*bytesPerStride*/) {
-                    if (tmpError == MapperErrorV3::NONE) {
-                        ret = tmpPtr;
-                    } else {
-                        ALOGE("%s: failed to lock error %d!",
-                              __FUNCTION__, tmpError);
-                    }
-               });
+        IMapperV3::Rect accessRegionV3{accessRegion.left, accessRegion.top, accessRegion.width,
+                                       accessRegion.height};
+
+        mMapperV3->lock(buffer, cpuUsage, accessRegionV3, acquireFenceHandle,
+                        [&](const auto& tmpError, const auto& tmpPtr, const auto& /*bytesPerPixel*/,
+                            const auto& /*bytesPerStride*/) {
+                            if (tmpError == MapperErrorV3::NONE) {
+                                ret = tmpPtr;
+                            } else {
+                                ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
+                            }
+                        });
     } else {
-        IMapper::Rect accessRegion { 0, 0, static_cast<int>(size), 1 };
         mMapperV2->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
                 [&](const auto& tmpError, const auto& tmpPtr) {
                     if (tmpError == MapperErrorV2::NONE) {
                         ret = tmpPtr;
                     } else {
-                        ALOGE("%s: failed to lock error %d!",
-                              __FUNCTION__, tmpError);
+                        ALOGE("%s: failed to lock error %d!", __FUNCTION__, tmpError);
                     }
                });
     }
 
-    ALOGV("%s: ptr %p size: %zu", __FUNCTION__, ret, size);
+    ALOGV("%s: ptr %p accessRegion.top: %d accessRegion.left: %d accessRegion.width: %d "
+          "accessRegion.height: %d",
+          __FUNCTION__, ret, accessRegion.top, accessRegion.left, accessRegion.width,
+          accessRegion.height);
     return ret;
 }
 
@@ -299,13 +384,7 @@
     }
 
     if (mMapperV4 != nullptr) {
-        // No device currently supports IMapper 4.0 so it is safe to just return an error code here.
-        //
-        // This will be supported by a combination of lock and BufferMetadata getters. We are going
-        // to refactor all the IAllocator/IMapper versioning code into a shared library. We will
-        // then add the IMapper 4.0 lockYCbCr support then.
-        ALOGE("%s: MapperV4 doesn't support lockYCbCr directly!", __FUNCTION__);
-        return {};
+        return lockYCbCrInternal<IMapperV4, MapperErrorV4>(mMapperV4, buf, cpuUsage, accessRegion);
     }
 
     if (mMapperV3 != nullptr) {
diff --git a/camera/common/1.0/default/include/HandleImporter.h b/camera/common/1.0/default/include/HandleImporter.h
index fc2bbd1..edc97ad 100644
--- a/camera/common/1.0/default/include/HandleImporter.h
+++ b/camera/common/1.0/default/include/HandleImporter.h
@@ -46,10 +46,13 @@
     bool importFence(const native_handle_t* handle, int& fd) const;
     void closeFence(int fd) const;
 
-    // Assume caller has done waiting for acquire fences
+    // Locks 1-D buffer. Assumes caller has waited for acquire fences.
     void* lock(buffer_handle_t& buf, uint64_t cpuUsage, size_t size);
 
-    // Assume caller has done waiting for acquire fences
+    // Locks 2-D buffer. Assumes caller has waited for acquire fences.
+    void* lock(buffer_handle_t& buf, uint64_t cpuUsage, const IMapper::Rect& accessRegion);
+
+    // Assumes caller has waited for acquire fences.
     YCbCrLayout lockYCbCr(buffer_handle_t& buf, uint64_t cpuUsage,
                           const IMapper::Rect& accessRegion);
 
diff --git a/camera/device/1.0/Android.bp b/camera/device/1.0/Android.bp
index 668884d..f2125af 100644
--- a/camera/device/1.0/Android.bp
+++ b/camera/device/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.camera.device@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ICameraDevice.hal",
diff --git a/camera/device/1.0/default/Android.bp b/camera/device/1.0/default/Android.bp
index e6e6485..da70577 100644
--- a/camera/device/1.0/default/Android.bp
+++ b/camera/device/1.0/default/Android.bp
@@ -20,15 +20,15 @@
         "android.hidl.memory@1.0",
         "libcutils",
         "liblog",
+        "libgralloctypes",
         "libhardware",
         "libcamera_metadata",
     ],
     static_libs: [
-        "android.hardware.camera.common@1.0-helper"
+        "android.hardware.camera.common@1.0-helper",
     ],
     header_libs: [
         "media_plugin_headers",
     ],
-    export_include_dirs: ["."]
+    export_include_dirs: ["."],
 }
-
diff --git a/camera/device/1.0/default/CameraDevice.cpp b/camera/device/1.0/default/CameraDevice.cpp
index 2dd6094..80733d1 100644
--- a/camera/device/1.0/default/CameraDevice.cpp
+++ b/camera/device/1.0/default/CameraDevice.cpp
@@ -15,6 +15,9 @@
  */
 
 #define LOG_TAG "CamDev@1.0-impl"
+
+#include <fcntl.h>
+
 #include <hardware/camera.h>
 #include <hardware/gralloc1.h>
 #include <hidlmemory/mapping.h>
diff --git a/camera/device/3.2/Android.bp b/camera/device/3.2/Android.bp
index 2e5349f..93d1e75 100644
--- a/camera/device/3.2/Android.bp
+++ b/camera/device/3.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.camera.device@3.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ICameraDevice.hal",
diff --git a/camera/device/3.2/ICameraDeviceCallback.hal b/camera/device/3.2/ICameraDeviceCallback.hal
index dec3bd8..206a649 100644
--- a/camera/device/3.2/ICameraDeviceCallback.hal
+++ b/camera/device/3.2/ICameraDeviceCallback.hal
@@ -87,15 +87,19 @@
      * ERROR_RESULT message.
      *
      * If an output buffer cannot be filled, its status field must be set to
-     * STATUS_ERROR. In addition, notify() must be called with a ERROR_BUFFER
-     * message.
+     * STATUS_ERROR. In this case, notify() isn't required to be called with
+     * an ERROR_BUFFER message. The framework will simply treat the notify()
+     * call with ERROR_BUFFER as a no-op, and derive whether and when to notify
+     * the application of buffer loss based on the buffer status and whether or not
+     * the entire capture has failed.
      *
      * If the entire capture has failed, then this method still needs to be
      * called to return the output buffers to the framework. All the buffer
      * statuses must be STATUS_ERROR, and the result metadata must be an
      * empty buffer. In addition, notify() must be called with a ERROR_REQUEST
      * message. In this case, individual ERROR_RESULT/ERROR_BUFFER messages
-     * must not be sent.
+     * must not be sent. Note that valid partial results are still allowed
+     * as long as the final result metadata fails to be generated.
      *
      * Performance requirements:
      *
diff --git a/camera/device/3.2/default/Android.bp b/camera/device/3.2/default/Android.bp
index 878878d..be2de07 100644
--- a/camera/device/3.2/default/Android.bp
+++ b/camera/device/3.2/default/Android.bp
@@ -2,9 +2,11 @@
     name: "camera.device@3.2-impl",
     defaults: ["hidl_defaults"],
     proprietary: true,
-    srcs: ["CameraDevice.cpp",
-           "CameraDeviceSession.cpp",
-           "convert.cpp"],
+    srcs: [
+        "CameraDevice.cpp",
+        "CameraDeviceSession.cpp",
+        "convert.cpp",
+    ],
     shared_libs: [
         "libhidlbase",
         "libutils",
@@ -15,15 +17,16 @@
         "android.hardware.graphics.mapper@3.0",
         "android.hardware.graphics.mapper@4.0",
         "liblog",
+        "libgralloctypes",
         "libhardware",
         "libcamera_metadata",
-        "libfmq"
+        "libfmq",
     ],
     static_libs: [
-        "android.hardware.camera.common@1.0-helper"
+        "android.hardware.camera.common@1.0-helper",
     ],
     export_include_dirs: ["."],
     export_shared_lib_headers: [
         "libfmq",
-    ]
+    ],
 }
diff --git a/camera/device/3.2/default/CameraDeviceSession.cpp b/camera/device/3.2/default/CameraDeviceSession.cpp
index 99cdccb..769991c 100644
--- a/camera/device/3.2/default/CameraDeviceSession.cpp
+++ b/camera/device/3.2/default/CameraDeviceSession.cpp
@@ -790,8 +790,9 @@
             auto it = batch->mBatchBufs.find(buffer.streamId);
             if (it != batch->mBatchBufs.end()) {
                 InflightBatch::BufferBatch& bb = it->second;
+                auto id = buffer.streamId;
                 pushStreamBuffer(std::move(buffer), bb.mBuffers);
-                filledStreams.push_back(buffer.streamId);
+                filledStreams.push_back(id);
             } else {
                 pushStreamBuffer(std::move(buffer), nonBatchedBuffers);
             }
diff --git a/camera/device/3.2/default/convert.cpp b/camera/device/3.2/default/convert.cpp
index d878deb..06ad7e9 100644
--- a/camera/device/3.2/default/convert.cpp
+++ b/camera/device/3.2/default/convert.cpp
@@ -38,7 +38,7 @@
     }
 
     const uint8_t* data = src.data();
-    // sanity check the size of CameraMetadata match underlying camera_metadata_t
+    // check that the size of CameraMetadata match underlying camera_metadata_t
     if (get_camera_metadata_size((camera_metadata_t*)data) != src.size()) {
         ALOGE("%s: input CameraMetadata is corrupt!", __FUNCTION__);
         return false;
diff --git a/camera/device/3.3/Android.bp b/camera/device/3.3/Android.bp
index 679fad6..0f8502b 100644
--- a/camera/device/3.3/Android.bp
+++ b/camera/device/3.3/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.camera.device@3.3",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ICameraDeviceSession.hal",
diff --git a/camera/device/3.3/default/Android.bp b/camera/device/3.3/default/Android.bp
index 7d51434..0aa0dd7 100644
--- a/camera/device/3.3/default/Android.bp
+++ b/camera/device/3.3/default/Android.bp
@@ -2,9 +2,11 @@
     name: "camera.device@3.3-impl",
     defaults: ["hidl_defaults"],
     proprietary: true,
-    srcs: ["CameraDevice.cpp",
-           "CameraDeviceSession.cpp",
-           "convert.cpp"],
+    srcs: [
+        "CameraDevice.cpp",
+        "CameraDeviceSession.cpp",
+        "convert.cpp",
+    ],
     shared_libs: [
         "libhidlbase",
         "libutils",
@@ -17,15 +19,16 @@
         "android.hardware.graphics.mapper@3.0",
         "android.hardware.graphics.mapper@4.0",
         "liblog",
+        "libgralloctypes",
         "libhardware",
         "libcamera_metadata",
-        "libfmq"
+        "libfmq",
     ],
     static_libs: [
-        "android.hardware.camera.common@1.0-helper"
+        "android.hardware.camera.common@1.0-helper",
     ],
     export_include_dirs: ["."],
     export_shared_lib_headers: [
         "libfmq",
-    ]
+    ],
 }
diff --git a/camera/device/3.4/Android.bp b/camera/device/3.4/Android.bp
index e6f42d6..5575366 100644
--- a/camera/device/3.4/Android.bp
+++ b/camera/device/3.4/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.camera.device@3.4",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ICameraDeviceCallback.hal",
diff --git a/camera/device/3.4/default/Android.bp b/camera/device/3.4/default/Android.bp
index 59e8329..982dce1 100644
--- a/camera/device/3.4/default/Android.bp
+++ b/camera/device/3.4/default/Android.bp
@@ -17,13 +17,13 @@
 cc_library_headers {
     name: "camera.device@3.4-impl_headers",
     vendor: true,
-    export_include_dirs: ["include/device_v3_4_impl"]
+    export_include_dirs: ["include/device_v3_4_impl"],
 }
 
 cc_library_headers {
     name: "camera.device@3.4-external-impl_headers",
     vendor: true,
-    export_include_dirs: ["include/ext_device_v3_4_impl"]
+    export_include_dirs: ["include/ext_device_v3_4_impl"],
 }
 
 cc_library_shared {
@@ -34,7 +34,7 @@
     srcs: [
         "CameraDevice.cpp",
         "CameraDeviceSession.cpp",
-        "convert.cpp"
+        "convert.cpp",
     ],
     shared_libs: [
         "libhidlbase",
@@ -50,6 +50,7 @@
         "android.hardware.graphics.mapper@3.0",
         "android.hardware.graphics.mapper@4.0",
         "liblog",
+        "libgralloctypes",
         "libhardware",
         "libcamera_metadata",
         "libfmq",
@@ -87,6 +88,7 @@
         "android.hardware.graphics.mapper@3.0",
         "android.hardware.graphics.mapper@4.0",
         "liblog",
+        "libgralloctypes",
         "libhardware",
         "libcamera_metadata",
         "libfmq",
@@ -94,7 +96,7 @@
         "libyuv",
         "libjpeg",
         "libexif",
-        "libtinyxml2"
+        "libtinyxml2",
     ],
     static_libs: [
         "android.hardware.camera.common@1.0-helper",
diff --git a/camera/device/3.4/default/CameraDeviceSession.cpp b/camera/device/3.4/default/CameraDeviceSession.cpp
index b4ebe22..3f088a3 100644
--- a/camera/device/3.4/default/CameraDeviceSession.cpp
+++ b/camera/device/3.4/default/CameraDeviceSession.cpp
@@ -656,8 +656,9 @@
             auto it = batch->mBatchBufs.find(buffer.streamId);
             if (it != batch->mBatchBufs.end()) {
                 InflightBatch::BufferBatch& bb = it->second;
+                auto id = buffer.streamId;
                 pushStreamBuffer(std::move(buffer), bb.mBuffers);
-                filledStreams.push_back(buffer.streamId);
+                filledStreams.push_back(id);
             } else {
                 pushStreamBuffer(std::move(buffer), nonBatchedBuffers);
             }
diff --git a/camera/device/3.5/Android.bp b/camera/device/3.5/Android.bp
index 362a5e6..9496216 100644
--- a/camera/device/3.5/Android.bp
+++ b/camera/device/3.5/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.camera.device@3.5",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ICameraDevice.hal",
diff --git a/camera/device/3.5/default/Android.bp b/camera/device/3.5/default/Android.bp
index 1c307ee..d106b4b 100644
--- a/camera/device/3.5/default/Android.bp
+++ b/camera/device/3.5/default/Android.bp
@@ -17,13 +17,13 @@
 cc_library_headers {
     name: "camera.device@3.5-impl_headers",
     vendor: true,
-    export_include_dirs: ["include/device_v3_5_impl"]
+    export_include_dirs: ["include/device_v3_5_impl"],
 }
 
 cc_library_headers {
     name: "camera.device@3.5-external-impl_headers",
     vendor: true,
-    export_include_dirs: ["include/ext_device_v3_5_impl"]
+    export_include_dirs: ["include/ext_device_v3_5_impl"],
 }
 
 cc_library_shared {
@@ -51,6 +51,7 @@
         "android.hardware.graphics.mapper@3.0",
         "android.hardware.graphics.mapper@4.0",
         "liblog",
+        "libgralloctypes",
         "libhardware",
         "libcamera_metadata",
     ],
@@ -85,6 +86,7 @@
         "android.hardware.graphics.mapper@3.0",
         "android.hardware.graphics.mapper@4.0",
         "liblog",
+        "libgralloctypes",
         "libhardware",
         "libcamera_metadata",
         "libfmq",
@@ -92,7 +94,7 @@
         "libyuv",
         "libjpeg",
         "libexif",
-        "libtinyxml2"
+        "libtinyxml2",
     ],
     static_libs: [
         "android.hardware.camera.common@1.0-helper",
diff --git a/camera/device/3.6/Android.bp b/camera/device/3.6/Android.bp
index 19adb34..e6f458c 100644
--- a/camera/device/3.6/Android.bp
+++ b/camera/device/3.6/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.camera.device@3.6",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ICameraDevice.hal",
diff --git a/camera/device/3.6/default/Android.bp b/camera/device/3.6/default/Android.bp
index a2ddebd..2871e2a 100644
--- a/camera/device/3.6/default/Android.bp
+++ b/camera/device/3.6/default/Android.bp
@@ -17,7 +17,7 @@
 cc_library_headers {
     name: "camera.device@3.6-external-impl_headers",
     vendor: true,
-    export_include_dirs: ["include/ext_device_v3_6_impl"]
+    export_include_dirs: ["include/ext_device_v3_6_impl"],
 }
 
 cc_library_shared {
@@ -48,6 +48,7 @@
         "android.hardware.graphics.mapper@3.0",
         "android.hardware.graphics.mapper@4.0",
         "liblog",
+        "libgralloctypes",
         "libhardware",
         "libcamera_metadata",
         "libfmq",
@@ -55,7 +56,7 @@
         "libyuv",
         "libjpeg",
         "libexif",
-        "libtinyxml2"
+        "libtinyxml2",
     ],
     static_libs: [
         "android.hardware.camera.common@1.0-helper",
diff --git a/camera/metadata/3.2/Android.bp b/camera/metadata/3.2/Android.bp
index f58fb28..6e55139 100644
--- a/camera/metadata/3.2/Android.bp
+++ b/camera/metadata/3.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.camera.metadata@3.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
     ],
diff --git a/camera/metadata/3.2/types.hal b/camera/metadata/3.2/types.hal
index f5034cc..ad671d9 100644
--- a/camera/metadata/3.2/types.hal
+++ b/camera/metadata/3.2/types.hal
@@ -1343,8 +1343,8 @@
 
     /** android.sensor.rollingShutterSkew [dynamic, int64, public]
      *
-     * <p>Duration between the start of first row exposure
-     * and the start of last row exposure.</p>
+     * <p>Duration between the start of exposure for the first row of the image sensor,
+     * and the start of exposure for one past the last row of the image sensor.</p>
      */
     ANDROID_SENSOR_ROLLING_SHUTTER_SKEW,
 
diff --git a/camera/metadata/3.3/Android.bp b/camera/metadata/3.3/Android.bp
index 885f4f9..f11fe2b 100644
--- a/camera/metadata/3.3/Android.bp
+++ b/camera/metadata/3.3/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.camera.metadata@3.3",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
     ],
diff --git a/camera/metadata/3.4/Android.bp b/camera/metadata/3.4/Android.bp
index 6a92458..31218be 100644
--- a/camera/metadata/3.4/Android.bp
+++ b/camera/metadata/3.4/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.camera.metadata@3.4",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
     ],
diff --git a/camera/metadata/3.5/Android.bp b/camera/metadata/3.5/Android.bp
index 224c369..a28ba43 100644
--- a/camera/metadata/3.5/Android.bp
+++ b/camera/metadata/3.5/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.camera.metadata@3.5",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
     ],
diff --git a/camera/provider/2.4/Android.bp b/camera/provider/2.4/Android.bp
index 876814d..8b67f3f 100644
--- a/camera/provider/2.4/Android.bp
+++ b/camera/provider/2.4/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.camera.provider@2.4",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "ICameraProvider.hal",
         "ICameraProviderCallback.hal",
diff --git a/camera/provider/2.4/vts/functional/AndroidTest.xml b/camera/provider/2.4/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..3000c0e
--- /dev/null
+++ b/camera/provider/2.4/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalCameraProviderV2_4TargetTest.">
+    <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="VtsHalCameraProviderV2_4TargetTest->/data/local/tmp/VtsHalCameraProviderV2_4TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalCameraProviderV2_4TargetTest" />
+        <option name="native-test-timeout" value="1800000"/> <!-- 30 min -->
+    </test>
+</configuration>
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index bf5fbfe..f235235 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -575,7 +575,10 @@
  }
  virtual void TearDown() override {}
 
- hidl_vec<hidl_string> getCameraDeviceNames(sp<ICameraProvider> provider);
+ hidl_vec<hidl_string> getCameraDeviceNames(sp<ICameraProvider> provider,
+                                            bool addSecureOnly = false);
+
+ bool isSecureOnly(sp<ICameraProvider> provider, const hidl_string& name);
 
  std::map<hidl_string, hidl_string> getCameraDeviceIdToNameMap(sp<ICameraProvider> provider);
 
@@ -799,6 +802,16 @@
             bool *useHalBufManager /*out*/,
             sp<DeviceCb> *cb /*out*/,
             uint32_t streamConfigCounter = 0);
+    void configureSingleStream(const std::string& name, int32_t deviceVersion,
+            sp<ICameraProvider> provider,
+            const AvailableStream* previewThreshold, uint64_t bufferUsage,
+            RequestTemplate reqTemplate,
+            sp<ICameraDeviceSession>* session /*out*/,
+            V3_2::Stream* previewStream /*out*/,
+            HalStreamConfiguration* halStreamConfig /*out*/,
+            bool* supportsPartialResults /*out*/,
+            uint32_t* partialResultCount /*out*/, bool* useHalBufManager /*out*/,
+            sp<DeviceCb>* cb /*out*/, uint32_t streamConfigCounter = 0);
 
     void verifyLogicalCameraMetadata(const std::string& cameraName,
             const ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice>& device,
@@ -830,7 +843,7 @@
 
     void verifyRequestTemplate(const camera_metadata_t* metadata, RequestTemplate requestTemplate);
 
-    bool isDepthOnly(camera_metadata_t* staticMeta);
+    static bool isDepthOnly(const camera_metadata_t* staticMeta);
 
     static Status getAvailableOutputStreams(const camera_metadata_t *staticMeta,
             std::vector<AvailableStream> &outputStreams,
@@ -875,6 +888,9 @@
     static Status getSystemCameraKind(const camera_metadata_t* staticMeta,
                                       SystemCameraKind* systemCameraKind);
 
+    void processCaptureRequestInternal(uint64_t bufferusage, RequestTemplate reqTemplate,
+                                       bool useSecureOnlyCameras);
+
     // Used by switchToOffline where a new result queue is created for offline reqs
     void updateInflightResultQueue(std::shared_ptr<ResultMetadataQueue> resultQueue);
 
@@ -1585,7 +1601,8 @@
     return idToNameMap;
 }
 
-hidl_vec<hidl_string> CameraHidlTest::getCameraDeviceNames(sp<ICameraProvider> provider) {
+hidl_vec<hidl_string> CameraHidlTest::getCameraDeviceNames(sp<ICameraProvider> provider,
+                                                           bool addSecureOnly) {
     std::vector<std::string> cameraDeviceNames;
     Return<void> ret;
     ret = provider->getCameraIdList(
@@ -1634,11 +1651,51 @@
         }
     }
 
-    hidl_vec<hidl_string> retList(cameraDeviceNames.size());
+    std::vector<hidl_string> retList;
     for (size_t i = 0; i < cameraDeviceNames.size(); i++) {
-        retList[i] = cameraDeviceNames[i];
+        bool isSecureOnlyCamera = isSecureOnly(mProvider, cameraDeviceNames[i]);
+        if (addSecureOnly) {
+            if (isSecureOnlyCamera) {
+                retList.emplace_back(cameraDeviceNames[i]);
+            }
+        } else if (!isSecureOnlyCamera) {
+            retList.emplace_back(cameraDeviceNames[i]);
+        }
     }
-    return retList;
+    hidl_vec<hidl_string> finalRetList = std::move(retList);
+    return finalRetList;
+}
+
+bool CameraHidlTest::isSecureOnly(sp<ICameraProvider> provider, const hidl_string& name) {
+    Return<void> ret;
+    ::android::sp<ICameraDevice> device3_x;
+    bool retVal = false;
+    if (getCameraDeviceVersion(mProviderType, name) == CAMERA_DEVICE_API_VERSION_1_0) {
+        return false;
+    }
+    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;
+    }
+    ret = device3_x->getCameraCharacteristics([&](Status s, CameraMetadata metadata) {
+        ASSERT_EQ(Status::OK, s);
+        camera_metadata_t* chars = (camera_metadata_t*)metadata.data();
+        SystemCameraKind systemCameraKind = SystemCameraKind::PUBLIC;
+        Status status = getSystemCameraKind(chars, &systemCameraKind);
+        ASSERT_EQ(status, Status::OK);
+        if (systemCameraKind == SystemCameraKind::HIDDEN_SECURE_CAMERA) {
+            retVal = true;
+        }
+    });
+    if (!ret.isOk()) {
+        ADD_FAILURE() << "Failed to get camera characteristics for device " << name;
+    }
+    return retVal;
 }
 
 hidl_vec<hidl_vec<hidl_string>> CameraHidlTest::getConcurrentDeviceCombinations(
@@ -1837,7 +1894,7 @@
 }
 
 // Verify that the device resource cost can be retrieved and the values are
-// sane.
+// correct.
 TEST_P(CameraHidlTest, getResourceCost) {
     hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
@@ -2487,7 +2544,7 @@
     }
 }
 
-// Basic sanity tests related to camera parameters.
+// Basic correctness tests related to camera parameters.
 TEST_P(CameraHidlTest, getSetParameters) {
     hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
 
@@ -4316,8 +4373,21 @@
 
 // Generate and verify a camera capture request
 TEST_P(CameraHidlTest, processCaptureRequestPreview) {
-    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
-    AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+    processCaptureRequestInternal(GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, RequestTemplate::PREVIEW,
+                                  false /*secureOnlyCameras*/);
+}
+
+// Generate and verify a secure camera capture request
+TEST_P(CameraHidlTest, processSecureCaptureRequest) {
+    processCaptureRequestInternal(GRALLOC1_PRODUCER_USAGE_PROTECTED, RequestTemplate::STILL_CAPTURE,
+                                  true /*secureOnlyCameras*/);
+}
+
+void CameraHidlTest::processCaptureRequestInternal(uint64_t bufferUsage,
+                                                   RequestTemplate reqTemplate,
+                                                   bool useSecureOnlyCameras) {
+    hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider, useSecureOnlyCameras);
+    AvailableStream streamThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
                                         static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
     uint64_t bufferId = 1;
     uint32_t frameNumber = 1;
@@ -4333,17 +4403,17 @@
             return;
         }
 
-        V3_2::Stream previewStream;
+        V3_2::Stream testStream;
         HalStreamConfiguration halStreamConfig;
         sp<ICameraDeviceSession> session;
         sp<DeviceCb> cb;
         bool supportsPartialResults = false;
         bool useHalBufManager = false;
         uint32_t partialResultCount = 0;
-        configurePreviewStream(name, deviceVersion, mProvider, &previewThreshold, &session /*out*/,
-                &previewStream /*out*/, &halStreamConfig /*out*/,
-                &supportsPartialResults /*out*/,
-                &partialResultCount /*out*/, &useHalBufManager /*out*/, &cb /*out*/);
+        configureSingleStream(name, deviceVersion, mProvider, &streamThreshold, bufferUsage,
+                              reqTemplate, &session /*out*/, &testStream /*out*/,
+                              &halStreamConfig /*out*/, &supportsPartialResults /*out*/,
+                              &partialResultCount /*out*/, &useHalBufManager /*out*/, &cb /*out*/);
 
         std::shared_ptr<ResultMetadataQueue> resultQueue;
         auto resultQueueRet =
@@ -4364,7 +4434,6 @@
         InFlightRequest inflightReq = {1, false, supportsPartialResults,
                                        partialResultCount, resultQueue};
 
-        RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
         Return<void> ret;
         ret = session->constructDefaultRequestSettings(reqTemplate,
                                                        [&](auto status, const auto& req) {
@@ -4383,7 +4452,7 @@
                             nullptr,
                             nullptr};
         } else {
-            allocateGraphicBuffer(previewStream.width, previewStream.height,
+            allocateGraphicBuffer(testStream.width, testStream.height,
                     android_convertGralloc1To0Usage(halStreamConfig.streams[0].producerUsage,
                         halStreamConfig.streams[0].consumerUsage),
                     halStreamConfig.streams[0].overrideFormat, &buffer_handle);
@@ -4432,7 +4501,7 @@
 
             ASSERT_FALSE(inflightReq.errorCodeValid);
             ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
-            ASSERT_EQ(previewStream.id, inflightReq.resultOutputBuffers[0].streamId);
+            ASSERT_EQ(testStream.id, inflightReq.resultOutputBuffers[0].streamId);
 
             request.frameNumber++;
             // Empty settings should be supported after the first call
@@ -4470,11 +4539,11 @@
 
             ASSERT_FALSE(inflightReq.errorCodeValid);
             ASSERT_NE(inflightReq.resultOutputBuffers.size(), 0u);
-            ASSERT_EQ(previewStream.id, inflightReq.resultOutputBuffers[0].streamId);
+            ASSERT_EQ(testStream.id, inflightReq.resultOutputBuffers[0].streamId);
         }
 
         if (useHalBufManager) {
-            verifyBuffersReturned(session, deviceVersion, previewStream.id, cb);
+            verifyBuffersReturned(session, deviceVersion, testStream.id, cb);
         }
 
         ret = session->close();
@@ -5468,9 +5537,22 @@
 // TODO: Add more combinations
 Status CameraHidlTest::getMandatoryConcurrentStreams(const camera_metadata_t* staticMeta,
                                                      std::vector<AvailableStream>* outputStreams) {
-    if (nullptr == staticMeta) {
+    if (nullptr == staticMeta || nullptr == outputStreams) {
         return Status::ILLEGAL_ARGUMENT;
     }
+
+    if (isDepthOnly(staticMeta)) {
+        Size y16MaxSize(640, 480);
+        Size maxAvailableY16Size;
+        getMaxOutputSizeForFormat(staticMeta, PixelFormat::Y16, &maxAvailableY16Size);
+        Size y16ChosenSize = getMinSize(y16MaxSize, maxAvailableY16Size);
+        AvailableStream y16Stream = {.width = y16ChosenSize.width,
+                                     .height = y16ChosenSize.height,
+                                     .format = static_cast<int32_t>(PixelFormat::Y16)};
+        outputStreams->push_back(y16Stream);
+        return Status::OK;
+    }
+
     Size yuvMaxSize(1280, 720);
     Size jpegMaxSize(1920, 1440);
     Size maxAvailableYuvSize;
@@ -6227,7 +6309,7 @@
     ASSERT_TRUE(ret.isOk());
 }
 
-bool CameraHidlTest::isDepthOnly(camera_metadata_t* staticMeta) {
+bool CameraHidlTest::isDepthOnly(const camera_metadata_t* staticMeta) {
     camera_metadata_ro_entry scalarEntry;
     camera_metadata_ro_entry depthEntry;
 
@@ -6278,6 +6360,19 @@
         bool *useHalBufManager /*out*/,
         sp<DeviceCb> *outCb /*out*/,
         uint32_t streamConfigCounter) {
+    configureSingleStream(name, deviceVersion, provider, previewThreshold,
+                          GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, RequestTemplate::PREVIEW, session,
+                          previewStream, halStreamConfig, supportsPartialResults,
+                          partialResultCount, useHalBufManager, outCb, streamConfigCounter);
+}
+// Open a device session and configure a preview stream.
+void CameraHidlTest::configureSingleStream(
+        const std::string& name, int32_t deviceVersion, sp<ICameraProvider> provider,
+        const AvailableStream* previewThreshold, uint64_t bufferUsage, RequestTemplate reqTemplate,
+        sp<ICameraDeviceSession>* session /*out*/, V3_2::Stream* previewStream /*out*/,
+        HalStreamConfiguration* halStreamConfig /*out*/, bool* supportsPartialResults /*out*/,
+        uint32_t* partialResultCount /*out*/, bool* useHalBufManager /*out*/,
+        sp<DeviceCb>* outCb /*out*/, uint32_t streamConfigCounter) {
     ASSERT_NE(nullptr, session);
     ASSERT_NE(nullptr, previewStream);
     ASSERT_NE(nullptr, halStreamConfig);
@@ -6366,11 +6461,14 @@
             dataspaceFlag = static_cast<V3_2::DataspaceFlags>(Dataspace::UNKNOWN);
     }
 
-    V3_2::Stream stream3_2 = {0, StreamType::OUTPUT,
-            static_cast<uint32_t> (outputPreviewStreams[0].width),
-            static_cast<uint32_t> (outputPreviewStreams[0].height),
-            static_cast<PixelFormat> (outputPreviewStreams[0].format),
-            GRALLOC1_CONSUMER_USAGE_HWCOMPOSER, dataspaceFlag, StreamRotation::ROTATION_0};
+    V3_2::Stream stream3_2 = {0,
+                              StreamType::OUTPUT,
+                              static_cast<uint32_t>(outputPreviewStreams[0].width),
+                              static_cast<uint32_t>(outputPreviewStreams[0].height),
+                              static_cast<PixelFormat>(outputPreviewStreams[0].format),
+                              bufferUsage,
+                              dataspaceFlag,
+                              StreamRotation::ROTATION_0};
     ::android::hardware::hidl_vec<V3_2::Stream> streams3_2 = {stream3_2};
     ::android::hardware::camera::device::V3_2::StreamConfiguration config3_2;
     ::android::hardware::camera::device::V3_4::StreamConfiguration config3_4;
@@ -6378,7 +6476,6 @@
     createStreamConfiguration(streams3_2, StreamConfigurationMode::NORMAL_MODE,
                               &config3_2, &config3_4, &config3_5, jpegBufferSize);
     if (session3_5 != nullptr) {
-        RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
         ret = session3_5->constructDefaultRequestSettings(reqTemplate,
                                                        [&config3_5](auto status, const auto& req) {
                                                            ASSERT_EQ(Status::OK, status);
@@ -6401,7 +6498,6 @@
                     }
                 });
     } else if (session3_4 != nullptr) {
-        RequestTemplate reqTemplate = RequestTemplate::PREVIEW;
         ret = session3_4->constructDefaultRequestSettings(reqTemplate,
                                                        [&config3_4](auto status, const auto& req) {
                                                            ASSERT_EQ(Status::OK, status);
@@ -6942,8 +7038,11 @@
 
     float minZoomRatio = entry.data.f[0];
     float maxZoomRatio = entry.data.f[1];
-    if (maxDigitalZoom != maxZoomRatio) {
-        ADD_FAILURE() << "Maximum zoom ratio is different than maximum digital zoom!";
+    constexpr float FLOATING_POINT_THRESHOLD = 0.00001f;
+    if (maxDigitalZoom > maxZoomRatio + FLOATING_POINT_THRESHOLD) {
+        ADD_FAILURE() << "Maximum digital zoom " << maxDigitalZoom
+                      << " is larger than maximum zoom ratio " << maxZoomRatio << " + threshold "
+                      << FLOATING_POINT_THRESHOLD << "!";
     }
     if (minZoomRatio > maxZoomRatio) {
         ADD_FAILURE() << "Maximum zoom ratio is less than minimum zoom ratio!";
diff --git a/camera/provider/2.5/Android.bp b/camera/provider/2.5/Android.bp
index 4ca1efb..be71806 100644
--- a/camera/provider/2.5/Android.bp
+++ b/camera/provider/2.5/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.camera.provider@2.5",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ICameraProvider.hal",
diff --git a/camera/provider/2.6/Android.bp b/camera/provider/2.6/Android.bp
index e69819c..6934c17 100644
--- a/camera/provider/2.6/Android.bp
+++ b/camera/provider/2.6/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.camera.provider@2.6",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ICameraProvider.hal",
diff --git a/camera/provider/2.6/ICameraProvider.hal b/camera/provider/2.6/ICameraProvider.hal
index ed1d31d..d720b26 100644
--- a/camera/provider/2.6/ICameraProvider.hal
+++ b/camera/provider/2.6/ICameraProvider.hal
@@ -61,6 +61,12 @@
      * outputs, stream combinations mentioned above, where YUV is substituted by
      * Y8 must be also supported.
      *
+     * Devices whose capabilities do not include
+     * ANDROID_REQUEST_AVAILABLE_CAPABILITIES_BACKWARD_COMPATIBLE, must support
+     * at least a single Y16 stream, Dataspace::DEPTH with sVGA resolution,
+     * during concurrent operation.
+     * Where sVGA -  min (max output resolution for the given format, 640 X 480)
+     *
      * The camera framework must call this method whenever it gets a
      * cameraDeviceStatusChange callback adding a new camera device or removing
      * a camera device known to it. This is so that the camera framework can get new combinations
@@ -76,12 +82,16 @@
      * configuration settings exposed through camera metadata), should the sum
      * of resource costs for the combination be <= 100.
      *
-     * The lists of camera id combinations returned by this method may contain
-     * hidden physical camera ids. If a combination does contain hidden physical
-     * camera ids, the camera framework must be able to open any logical cameras
-     * that contain these hidden physical camera ids in their
-     * ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS list, in addition to the other
-     * camera ids advertised in the combination, for concurrent operation.
+     * For guaranteed concurrent camera operation, the camera framework must call
+     * ICameraDevice.open() on all devices (intended for concurrent operation), before configuring
+     * any streams on them. This gives the camera HAL process an opportunity to potentially
+     * distribute hardware resources better before stream configuration.
+     *
+     * Due to potential hardware constraints around internal switching of physical camera devices,
+     * a device's complete ZOOM_RATIO_RANGE(if supported), may not apply during concurrent
+     * operation. If ZOOM_RATIO is supported, camera HALs must ensure ZOOM_RATIO_RANGE of
+     * [1.0, ANDROID_SCALER_AVAILABLE_MAX_DIGITAL_ZOOM] is supported by that device, during
+     * concurrent operation.
      *
      * @return status Status code for the operation
      * @return cameraIds a list of camera id combinations that support
diff --git a/cas/1.0/Android.bp b/cas/1.0/Android.bp
index 4982e20..9f289a1 100644
--- a/cas/1.0/Android.bp
+++ b/cas/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.cas@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ICas.hal",
diff --git a/cas/1.0/default/DescramblerImpl.cpp b/cas/1.0/default/DescramblerImpl.cpp
index 9b09751..f79b32d 100644
--- a/cas/1.0/default/DescramblerImpl.cpp
+++ b/cas/1.0/default/DescramblerImpl.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "android.hardware.cas@1.0-DescramblerImpl"
 
 #include <hidlmemory/mapping.h>
+#include <inttypes.h>
 #include <media/cas/DescramblerAPI.h>
 #include <media/hardware/CryptoAPI.h>
 #include <media/stagefright/foundation/AString.h>
@@ -101,7 +102,7 @@
     // size in size_t. If size is over SIZE_MAX, mapMemory mapMemory could succeed
     // but the mapped memory's actual size will be smaller than the reported size.
     if (srcBuffer.heapBase.size() > SIZE_MAX) {
-        ALOGE("Invalid hidl_memory size: %llu", srcBuffer.heapBase.size());
+        ALOGE("Invalid hidl_memory size: %" PRIu64 "", srcBuffer.heapBase.size());
         android_errorWriteLog(0x534e4554, "79376389");
         _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
         return Void();
@@ -118,8 +119,8 @@
     }
     if (!validateRangeForSize(
             srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize())) {
-        ALOGE("Invalid src buffer range: offset %llu, size %llu, srcMem size %llu",
-                srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize());
+        ALOGE("Invalid src buffer range: offset %" PRIu64 ", size %" PRIu64 ", srcMem"
+              "size %" PRIu64 "", srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize());
         android_errorWriteLog(0x534e4554, "67962232");
         _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
         return Void();
@@ -135,8 +136,8 @@
     // is consistent with the source shared buffer size.
     if (!validateRangeForSize(srcOffset, totalBytesInSubSamples, srcBuffer.size)) {
         ALOGE("Invalid srcOffset and subsample size: "
-                "srcOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
-                srcOffset, totalBytesInSubSamples, srcBuffer.size);
+                "srcOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64 ", srcBuffer"
+                "size %" PRIu64 "", srcOffset, totalBytesInSubSamples, srcBuffer.size);
         android_errorWriteLog(0x534e4554, "67962232");
         _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
         return Void();
@@ -153,8 +154,8 @@
         // dstOffset against the buffer size too.
         if (!validateRangeForSize(dstOffset, totalBytesInSubSamples, srcBuffer.size)) {
             ALOGE("Invalid dstOffset and subsample size: "
-                    "dstOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
-                    dstOffset, totalBytesInSubSamples, srcBuffer.size);
+                    "dstOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64 ", srcBuffer"
+                    "size %" PRIu64 "", dstOffset, totalBytesInSubSamples, srcBuffer.size);
             android_errorWriteLog(0x534e4554, "67962232");
             _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
             return Void();
diff --git a/cas/1.1/Android.bp b/cas/1.1/Android.bp
index 13217b6..e20298b 100644
--- a/cas/1.1/Android.bp
+++ b/cas/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.cas@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "ICas.hal",
         "ICasListener.hal",
diff --git a/cas/1.1/default/DescramblerImpl.cpp b/cas/1.1/default/DescramblerImpl.cpp
index 36dc1a5..309cd3c 100644
--- a/cas/1.1/default/DescramblerImpl.cpp
+++ b/cas/1.1/default/DescramblerImpl.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "android.hardware.cas@1.1-DescramblerImpl"
 
 #include <hidlmemory/mapping.h>
+#include <inttypes.h>
 #include <media/cas/DescramblerAPI.h>
 #include <media/hardware/CryptoAPI.h>
 #include <media/stagefright/foundation/AUtils.h>
@@ -92,7 +93,7 @@
     // size in size_t. If size is over SIZE_MAX, mapMemory mapMemory could succeed
     // but the mapped memory's actual size will be smaller than the reported size.
     if (srcBuffer.heapBase.size() > SIZE_MAX) {
-        ALOGE("Invalid hidl_memory size: %llu", srcBuffer.heapBase.size());
+        ALOGE("Invalid hidl_memory size: %" PRIu64 "", srcBuffer.heapBase.size());
         android_errorWriteLog(0x534e4554, "79376389");
         _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
         return Void();
@@ -108,8 +109,8 @@
         return Void();
     }
     if (!validateRangeForSize(srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize())) {
-        ALOGE("Invalid src buffer range: offset %llu, size %llu, srcMem size %llu",
-              srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize());
+        ALOGE("Invalid src buffer range: offset %" PRIu64 ", size %" PRIu64 ", srcMem"
+              "size %" PRIu64 "", srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize());
         android_errorWriteLog(0x534e4554, "67962232");
         _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
         return Void();
@@ -125,8 +126,8 @@
     // is consistent with the source shared buffer size.
     if (!validateRangeForSize(srcOffset, totalBytesInSubSamples, srcBuffer.size)) {
         ALOGE("Invalid srcOffset and subsample size: "
-              "srcOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
-              srcOffset, totalBytesInSubSamples, srcBuffer.size);
+              "srcOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64 ", srcBuffer"
+              "size %" PRIu64 "", srcOffset, totalBytesInSubSamples, srcBuffer.size);
         android_errorWriteLog(0x534e4554, "67962232");
         _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
         return Void();
@@ -143,8 +144,8 @@
         // dstOffset against the buffer size too.
         if (!validateRangeForSize(dstOffset, totalBytesInSubSamples, srcBuffer.size)) {
             ALOGE("Invalid dstOffset and subsample size: "
-                  "dstOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
-                  dstOffset, totalBytesInSubSamples, srcBuffer.size);
+                  "dstOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64 ", srcBuffer"
+                  "size %" PRIu64 "", dstOffset, totalBytesInSubSamples, srcBuffer.size);
             android_errorWriteLog(0x534e4554, "67962232");
             _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
             return Void();
diff --git a/cas/1.2/Android.bp b/cas/1.2/Android.bp
index fbb38b0..f03b6b7 100644
--- a/cas/1.2/Android.bp
+++ b/cas/1.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.cas@1.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ICas.hal",
diff --git a/cas/1.2/default/DescramblerImpl.cpp b/cas/1.2/default/DescramblerImpl.cpp
index 36dc1a5..309cd3c 100644
--- a/cas/1.2/default/DescramblerImpl.cpp
+++ b/cas/1.2/default/DescramblerImpl.cpp
@@ -18,6 +18,7 @@
 #define LOG_TAG "android.hardware.cas@1.1-DescramblerImpl"
 
 #include <hidlmemory/mapping.h>
+#include <inttypes.h>
 #include <media/cas/DescramblerAPI.h>
 #include <media/hardware/CryptoAPI.h>
 #include <media/stagefright/foundation/AUtils.h>
@@ -92,7 +93,7 @@
     // size in size_t. If size is over SIZE_MAX, mapMemory mapMemory could succeed
     // but the mapped memory's actual size will be smaller than the reported size.
     if (srcBuffer.heapBase.size() > SIZE_MAX) {
-        ALOGE("Invalid hidl_memory size: %llu", srcBuffer.heapBase.size());
+        ALOGE("Invalid hidl_memory size: %" PRIu64 "", srcBuffer.heapBase.size());
         android_errorWriteLog(0x534e4554, "79376389");
         _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
         return Void();
@@ -108,8 +109,8 @@
         return Void();
     }
     if (!validateRangeForSize(srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize())) {
-        ALOGE("Invalid src buffer range: offset %llu, size %llu, srcMem size %llu",
-              srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize());
+        ALOGE("Invalid src buffer range: offset %" PRIu64 ", size %" PRIu64 ", srcMem"
+              "size %" PRIu64 "", srcBuffer.offset, srcBuffer.size, (uint64_t)srcMem->getSize());
         android_errorWriteLog(0x534e4554, "67962232");
         _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
         return Void();
@@ -125,8 +126,8 @@
     // is consistent with the source shared buffer size.
     if (!validateRangeForSize(srcOffset, totalBytesInSubSamples, srcBuffer.size)) {
         ALOGE("Invalid srcOffset and subsample size: "
-              "srcOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
-              srcOffset, totalBytesInSubSamples, srcBuffer.size);
+              "srcOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64 ", srcBuffer"
+              "size %" PRIu64 "", srcOffset, totalBytesInSubSamples, srcBuffer.size);
         android_errorWriteLog(0x534e4554, "67962232");
         _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
         return Void();
@@ -143,8 +144,8 @@
         // dstOffset against the buffer size too.
         if (!validateRangeForSize(dstOffset, totalBytesInSubSamples, srcBuffer.size)) {
             ALOGE("Invalid dstOffset and subsample size: "
-                  "dstOffset %llu, totalBytesInSubSamples %llu, srcBuffer size %llu",
-                  dstOffset, totalBytesInSubSamples, srcBuffer.size);
+                  "dstOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64 ", srcBuffer"
+                  "size %" PRIu64 "", dstOffset, totalBytesInSubSamples, srcBuffer.size);
             android_errorWriteLog(0x534e4554, "67962232");
             _hidl_cb(toStatus(BAD_VALUE), 0, NULL);
             return Void();
diff --git a/cas/native/1.0/Android.bp b/cas/native/1.0/Android.bp
index 633ceb9..6aa4204 100644
--- a/cas/native/1.0/Android.bp
+++ b/cas/native/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.cas.native@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IDescrambler.hal",
diff --git a/common/aidl/Android.bp b/common/aidl/Android.bp
index 0731230..9ea4cdf 100644
--- a/common/aidl/Android.bp
+++ b/common/aidl/Android.bp
@@ -17,6 +17,13 @@
         cpp: {
             enabled: false,
         },
+        ndk: {
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.media.swcodec",
+            ],
+            min_sdk_version: "29",
+        },
     },
     versions: ["1"],
 }
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index ba56832..9d4e55c 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -90,3 +90,16 @@
         "kernel_config_r_5.4",
     ],
 }
+
+vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.current.xml",
+    stem: "compatibility_matrix.current.xml",
+    srcs: [
+        "compatibility_matrix.current.xml",
+    ],
+    kernel_configs: [
+        "kernel_config_current_4.14",
+        "kernel_config_current_4.19",
+        "kernel_config_current_5.4",
+    ],
+}
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index e69fc8d..96191c8 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -98,6 +98,7 @@
     framework_compatibility_matrix.3.xml \
     framework_compatibility_matrix.4.xml \
     framework_compatibility_matrix.5.xml \
+    framework_compatibility_matrix.current.xml \
     framework_compatibility_matrix.device.xml \
 
 my_framework_matrix_deps += \
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
new file mode 100644
index 0000000..9463924
--- /dev/null
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -0,0 +1,554 @@
+<compatibility-matrix version="1.0" type="framework" level="6">
+    <hal format="hidl" optional="true">
+        <name>android.hardware.atrace</name>
+        <version>1.0</version>
+        <interface>
+            <name>IAtraceDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.audio</name>
+        <version>6.0</version>
+        <interface>
+            <name>IDevicesFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.audio.effect</name>
+        <version>6.0</version>
+        <interface>
+            <name>IEffectsFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.authsecret</name>
+        <version>1.0</version>
+        <interface>
+            <name>IAuthSecret</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.audiocontrol</name>
+        <version>1.0</version>
+        <version>2.0</version>
+        <interface>
+            <name>IAudioControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.can</name>
+        <version>1.0</version>
+        <interface>
+            <name>ICanBus</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+        <interface>
+            <name>ICanController</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.evs</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IEvsEnumerator</name>
+            <instance>default</instance>
+            <regex-instance>[a-z]+/[0-9]+</regex-instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.automotive.occupant_awareness</name>
+        <interface>
+            <name>IOccupantAwareness</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.sv</name>
+        <version>1.0</version>
+        <interface>
+            <name>ISurroundView</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.vehicle</name>
+        <version>2.0</version>
+        <interface>
+            <name>IVehicle</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.biometrics.face</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IBiometricsFace</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.biometrics.fingerprint</name>
+        <version>2.1-2</version>
+        <interface>
+            <name>IBiometricsFingerprint</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.bluetooth</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IBluetoothHci</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.bluetooth.audio</name>
+        <version>2.0</version>
+        <interface>
+            <name>IBluetoothAudioProvidersFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.boot</name>
+        <version>1.1</version>
+        <interface>
+            <name>IBootControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.broadcastradio</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IBroadcastRadioFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.broadcastradio</name>
+        <version>2.0</version>
+        <interface>
+            <name>IBroadcastRadio</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.camera.provider</name>
+        <version>2.4-6</version>
+        <interface>
+            <name>ICameraProvider</name>
+            <regex-instance>[^/]+/[0-9]+</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.cas</name>
+        <version>1.1-2</version>
+        <interface>
+            <name>IMediaCasService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.confirmationui</name>
+        <version>1.0</version>
+        <interface>
+            <name>IConfirmationUI</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.contexthub</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IContexthub</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.drm</name>
+        <version>1.3</version>
+        <interface>
+            <name>ICryptoFactory</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+        <interface>
+            <name>IDrmFactory</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.dumpstate</name>
+        <version>1.1</version>
+        <interface>
+            <name>IDumpstateDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.gatekeeper</name>
+        <version>1.0</version>
+        <interface>
+            <name>IGatekeeper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.gnss</name>
+        <version>2.0-1</version>
+        <version>3.0</version>
+        <interface>
+            <name>IGnss</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.allocator</name>
+        <!-- New, non-Go devices should use 4.0, tested in vts_treble_vintf_vendor_test -->
+        <version>2.0</version>
+        <version>3.0</version>
+        <version>4.0</version>
+        <interface>
+            <name>IAllocator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.composer</name>
+        <version>2.1-4</version>
+        <interface>
+            <name>IComposer</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.mapper</name>
+        <!-- New, non-Go devices should use 4.0, tested in vts_treble_vintf_vendor_test -->
+        <version>2.1</version>
+        <version>3.0</version>
+        <version>4.0</version>
+        <interface>
+            <name>IMapper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.health</name>
+        <version>2.1</version>
+        <interface>
+            <name>IHealth</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.health.storage</name>
+        <version>1.0</version>
+        <interface>
+            <name>IStorage</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.identity</name>
+        <interface>
+            <name>IIdentityCredentialStore</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.ir</name>
+        <version>1.0</version>
+        <interface>
+            <name>IConsumerIr</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.input.classifier</name>
+        <version>1.0</version>
+        <interface>
+            <name>IInputClassifier</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.keymaster</name>
+        <version>3.0</version>
+        <version>4.0-1</version>
+        <interface>
+            <name>IKeymasterDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.keymaster</name>
+        <version>4.0-1</version>
+        <interface>
+            <name>IKeymasterDevice</name>
+            <instance>strongbox</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.light</name>
+        <interface>
+            <name>ILights</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.media.c2</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IComponentStore</name>
+            <regex-instance>default[0-9]*</regex-instance>
+            <regex-instance>vendor[0-9]*_software</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.media.omx</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOmx</name>
+            <instance>default</instance>
+        </interface>
+        <interface>
+            <name>IOmxStore</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.memtrack</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMemtrack</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.neuralnetworks</name>
+        <version>1.0-3</version>
+        <interface>
+            <name>IDevice</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.nfc</name>
+        <version>1.2</version>
+        <interface>
+            <name>INfc</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.oemlock</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="false">
+        <name>android.hardware.power</name>
+        <interface>
+            <name>IPower</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.power.stats</name>
+        <version>1.0</version>
+        <interface>
+            <name>IPowerStats</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.radio</name>
+        <version>1.6</version>
+        <interface>
+            <name>IRadio</name>
+            <instance>slot1</instance>
+            <instance>slot2</instance>
+            <instance>slot3</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.radio</name>
+        <version>1.2</version>
+        <interface>
+            <name>ISap</name>
+            <instance>slot1</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.radio.config</name>
+        <!--
+        See compatibility_matrix.4.xml on versioning of radio config HAL.
+        -->
+        <version>1.1</version>
+        <interface>
+            <name>IRadioConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.renderscript</name>
+        <version>1.0</version>
+        <interface>
+            <name>IDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.rebootescrow</name>
+        <interface>
+            <name>IRebootEscrow</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.secure_element</name>
+        <version>1.0-2</version>
+        <interface>
+            <name>ISecureElement</name>
+            <regex-instance>eSE[1-9][0-9]*</regex-instance>
+            <regex-instance>SIM[1-9][0-9]*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.sensors</name>
+        <version>1.0</version>
+        <version>2.0-1</version>
+        <interface>
+            <name>ISensors</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.soundtrigger</name>
+        <version>2.0-3</version>
+        <interface>
+            <name>ISoundTriggerHw</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.config</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.control</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.thermal</name>
+        <version>2.0</version>
+        <interface>
+            <name>IThermal</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tv.cec</name>
+        <version>1.0</version>
+        <interface>
+            <name>IHdmiCec</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tv.input</name>
+        <version>1.0</version>
+        <interface>
+            <name>ITvInput</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tv.tuner</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>ITuner</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.usb</name>
+        <version>1.0-2</version>
+        <interface>
+            <name>IUsb</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.usb.gadget</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IUsbGadget</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.vibrator</name>
+        <interface>
+            <name>IVibrator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.vr</name>
+        <version>1.0</version>
+        <interface>
+            <name>IVr</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.weaver</name>
+        <version>1.0</version>
+        <interface>
+            <name>IWeaver</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi</name>
+        <version>1.0-5</version>
+        <interface>
+            <name>IWifi</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.hostapd</name>
+        <version>1.0-2</version>
+        <interface>
+            <name>IHostapd</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.supplicant</name>
+        <version>1.0-3</version>
+        <interface>
+            <name>ISupplicant</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</compatibility-matrix>
diff --git a/confirmationui/1.0/Android.bp b/confirmationui/1.0/Android.bp
index a22067a..15c4f18 100644
--- a/confirmationui/1.0/Android.bp
+++ b/confirmationui/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.confirmationui@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IConfirmationResultCallback.hal",
diff --git a/contexthub/1.0/Android.bp b/contexthub/1.0/Android.bp
index 71dd978..be30d61 100644
--- a/contexthub/1.0/Android.bp
+++ b/contexthub/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.contexthub@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IContexthub.hal",
diff --git a/contexthub/1.1/Android.bp b/contexthub/1.1/Android.bp
index 649f1db..9ee8e76 100644
--- a/contexthub/1.1/Android.bp
+++ b/contexthub/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.contexthub@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IContexthub.hal",
diff --git a/current.txt b/current.txt
index d2b7206..6f5e559 100644
--- a/current.txt
+++ b/current.txt
@@ -588,8 +588,10 @@
 578f640c653726d58f99c84a7e1bb63862e21ef7cbb4f7d95c3cc62de00dca35 android.hardware.automotive.evs@1.0::IEvsDisplay
 f5bc6aa840db933cb9fd36668b06d3e2021cf5384bb70e459f22e2f2f921fba5 android.hardware.automotive.evs@1.0::IEvsEnumerator
 d3a344b7bd4c0d2658ae7209f55a979b8f53f361fd00f4fca29d5baa56d11fd2 android.hardware.automotive.evs@1.0::types
+2924c3e43858190ee3e2da4c2fb93bba8ae065fe314451f035a7ec52cb80c94a android.hardware.camera.device@3.2::ICameraDeviceCallback # b/155353799
 2410dd02d67786a732d36e80b0f8ccf55086604ef37f9838e2013ff2c571e404 android.hardware.camera.device@3.5::types
 cd06a7911b9acd4a653bbf7133888878fbcb3f84be177c7a3f1becaae3d8618f android.hardware.camera.metadata@3.2::types
+5cf81b1001296fbb3c5b3d275a859244f61cec5fa858d7be9cca46c5b7dfa733 android.hardware.camera.metadata@3.2::types # b/150331548
 a05277065c28ebecd58118bd240fb8c55757361e8648c01f7c4dacdb7f2a95dc android.hardware.camera.metadata@3.3::types
 9cb3df2bde2c6cd5fd96b7c41555420cacd7e276a556c684af91b7461c86460f android.hardware.gnss@1.0::IGnssCallback
 dd6cd9dba4fde99a1bc3cb1728d82309f509a6e6e1993e5042dfa5ffe4af5442 android.hardware.gnss@2.0::IGnssMeasurementCallback
@@ -601,9 +603,11 @@
 eb2fa0c883c2185d514be0b84c179b283753ef0c1b77b45b4f359bd23bba8b75 android.hardware.neuralnetworks@1.0::IPreparedModel
 92e101b30e47bdf526a01c52cecfbe730def5997b8260ab497eb949eb2a6dcdf android.hardware.neuralnetworks@1.0::types
 5f6d3097ba84cb63c430787123f4de1b31c11f90b531b98eae9a8623a5ae962a android.hardware.neuralnetworks@1.1::types
+c2711d8748ccbcc858d5d5ec1abf145d9ab4c0b27db8ca215d7c39665a9b6652 android.hardware.neuralnetworks@1.1::types # b/155508675, b/155662254, b/155238914
 fb382e986c10b8fbb797a8546e8f9ea6d1107bfe6f3fb7e57f6bbbf1f807a906 android.hardware.neuralnetworks@1.2::IDevice
 40e71cd693de5b832325c5d8f081f2ff20a7ba2b89d401cee5b4b3eb0e241681 android.hardware.neuralnetworks@1.2::IPreparedModel
 ee1a0dee5be00a6fe2d4d3270068c78016dcb194d768fe07ed894ea20904037f android.hardware.neuralnetworks@1.2::types
+9c53b727cfa9efde38ebe3914e1e95939cff29c072a1b8c8f419d24853b98831 android.hardware.neuralnetworks@1.2::types # b/155508675, b/155662254, b/155238914, b/155660285
 a785a57447a81e9c130eef6904c3a5c256076c6a04588c40620ebd6fa2660d77 android.hardware.radio@1.2::types
 1a6e2bd289f22931c526b21916910f1d4c436b7acb9556e4243de4ce8e6cc2e4 android.hardware.soundtrigger@2.0::ISoundTriggerHwCallback
 fd65298e1e09e0e3c781ab18305920d757dbe55a3b459ce17814ec5cf6dfee99 android.hardware.wifi@1.0::IWifiP2pIface
@@ -619,6 +623,7 @@
 164826a380f4c1700183003f62d7532e367b67381c30ea44f946c0cf00008f85 android.hardware.audio@6.0::IStreamOut
 997fdaad7a9d17ee7e01feb7031a753e2365e72ad30b11d950e9183fabdf3844 android.hardware.audio@6.0::IStreamOutCallback
 e7ca0db9a1098210f327a9b152fa6afe6bf019c41e5264c64829d04d50c0a526 android.hardware.audio@6.0::IStreamOutEventCallback
+aa2211abd803e03d05ea11c18749db068f785fe026f8d99bce64bd764f63d194 android.hardware.audio@6.0::IStreamOutEventCallback  # b/150175043
 822369cf4dc16a6f6b9622bcf86cbdc0b692dc82193fc15e967767175cbfdd8f android.hardware.audio@6.0::types
 bee662c62d997d8065e2bcb5c1e7a9578931f22ce28fd02c219fdb4d0630abf7 android.hardware.audio.common@6.0::types
 525bec6b44f1103869c269a128d51b8dccd73af5340ba863c8886c68357c7faf android.hardware.audio.effect@6.0::IAcousticEchoCancelerEffect
@@ -653,7 +658,7 @@
 87958d728d7c0ee9b9391ab4a072b097914921a7b38f7dc3df427f933a5b528e android.hardware.automotive.evs@1.1::IEvsEnumerator
 f53b4e8de6209c6d0fa9036005671b34a2f98328b51423d3a5137a43bf42c84d android.hardware.automotive.evs@1.1::IEvsUltrasonicsArray
 0460bacbde906a846a3d71b2b7b33d6927cac3ff072e523ffac7853577464406 android.hardware.automotive.evs@1.1::IEvsUltrasonicsArrayStream
-3e374b5c4777f959f62a320abb3b9edca8874e24e383dbb19c66d224f151b363 android.hardware.automotive.evs@1.1::types
+f27cf8283e7b953d33dd258734749d2fca9cc63502ea41353060ffa78d8ce9f6 android.hardware.automotive.evs@1.1::types
 4e4904c4067dadae974ddf90351f362331dcd04bba1d890d313cc8ba91f68c15 android.hardware.automotive.sv@1.0::ISurroundView2dSession
 63336e9d03f545020ff2982ff76d9d8c44fa76ad476293b5ef6732cbbd71e61b android.hardware.automotive.sv@1.0::ISurroundView3dSession
 b7015428cd52ce8192d13bfcbf2c4455cda3727d57f2aac80d65a1747104f5ac android.hardware.automotive.sv@1.0::ISurroundViewService
@@ -672,7 +677,7 @@
 a718c8a3acaa938de5a57923e8c4625ed7ca051e05a1d930ba6998557d7b57c8 android.hardware.camera.device@3.6::ICameraOfflineSession
 a35d5151b48505f06a775b38c0e2e265f80a845d92802324c643565807f81c53 android.hardware.camera.device@3.6::types
 02bdf82dba7dce273a554b4474468a8fb1fb4f61ab65da95eb16e080df63fff6 android.hardware.camera.metadata@3.5::types
-21086e1c7a2acc0ebe0ff8561b11f3c2009be687a92d79b608a5f00b16c5f598 android.hardware.camera.provider@2.6::ICameraProvider
+93cd94e47b22007bbf436c2f5c2703bb7b2859d1b714d6ae15520db55667ba6c android.hardware.camera.provider@2.6::ICameraProvider
 8f8d9463508ff9cae88eb35c429fd0e2dbca0ca8f5de7fdf836cc0c4370becb6 android.hardware.camera.provider@2.6::ICameraProviderCallback
 1edf7aef68ef3bd577a1175b1462fb82e3e39f01c6915dda61fba121028df283 android.hardware.camera.provider@2.6::types
 c1aa508d00b66ed5feefea398fd5edf28fa651ac89773adad7dfda4e0a73a952 android.hardware.cas@1.2::ICas
@@ -716,6 +721,8 @@
 ee9dc34b9925b8367b1111c72bd6d9d375432735e451572ca5a665d8516a7744 android.hardware.neuralnetworks@1.3::IPreparedModel
 eee3430cc86c97c7b407495863d8fb61da6f1a64b7721e77b9b4909b11b174e9 android.hardware.neuralnetworks@1.3::IPreparedModelCallback
 acf84925f8ee0a651f2ec547ac334034de266479b93af5434f6c1f25e66aba96 android.hardware.neuralnetworks@1.3::types
+e9080d04218e98512b63aace9ff3da52f0130238391f15cbbf7df396a3ec9072 android.hardware.neuralnetworks@1.3::types # b/155508675, b/155662254, b/155238914, b/155660285
+583dc88b41e702e940fd954edda1beb8b4151eab55a5c6d7e69e2781bce84b59 android.hardware.neuralnetworks@1.3::types # b/156918813
 b454df853441c12f6e425e8a60dd29fda20f5e6e39b93d1103e4b37495db38aa android.hardware.radio@1.5::IRadio
 fcbb0742a88215ee7a6d7ce0825d253eb2b50391fc6c8c48667f9fd7f6d4549e android.hardware.radio@1.5::IRadioIndication
 b809193970a91ca637a4b0184767315601d32e3ef3d5992ffbc7a8d14a14f015 android.hardware.radio@1.5::IRadioResponse
@@ -758,3 +765,14 @@
 2ce1f7fb52e49f80b13a9b153d491bce530552f02357ea729acae922a8659f93 android.hardware.wifi.supplicant@1.3::ISupplicantStaIfaceCallback
 77531c8d048f8f8ae532babd0ca86332a865ec9aace1b051226ef2b21123e645 android.hardware.wifi.supplicant@1.3::ISupplicantStaNetwork
 98592d193a717066facf91428426e5abe211e3bd718bc372e29fb944ddbe6e7c android.hardware.wifi.supplicant@1.3::types
+
+# ABI preserving changes to HALs during Android S
+cd84ab19c590e0e73dd2307b591a3093ee18147ef95e6d5418644463a6620076 android.hardware.neuralnetworks@1.2::IDevice
+9625e85f56515ad2cf87b6a1847906db669f746ea4ab02cd3d4ca25abc9b0109 android.hardware.neuralnetworks@1.2::types
+9e758e208d14f7256e0885d6d8ad0b61121b21d8c313864f981727ae55bffd16 android.hardware.neuralnetworks@1.3::types
+38d65fb20c60a5b823298560fc0825457ecdc49603a4b4e94bf81511790737da android.hardware.radio@1.4::types
+954c334efd80e8869b66d1ce5fe2755712d96ba4b3c38d415739c330af5fb4cb android.hardware.radio@1.5::types
+
+# HALs released in Android S
+# NOTE: waiting to freeze HALs until later in the release
+# NOTE: new HALs are recommended to be in AIDL
diff --git a/drm/1.0/Android.bp b/drm/1.0/Android.bp
index 9049af2..44fb837 100644
--- a/drm/1.0/Android.bp
+++ b/drm/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.drm@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ICryptoFactory.hal",
diff --git a/drm/1.0/default/Android.bp b/drm/1.0/default/Android.bp
index ed6bcde..93b3278 100644
--- a/drm/1.0/default/Android.bp
+++ b/drm/1.0/default/Android.bp
@@ -1,3 +1,17 @@
+// Copyright (C) 2016-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.
+
 cc_library_static {
     name: "android.hardware.drm@1.0-helper",
     vendor_available: true,
@@ -21,3 +35,111 @@
     ],
     export_include_dirs : ["include"]
 }
+
+soong_config_module_type {
+    name: "android_hardware_drm_1_0_multilib",
+    module_type: "cc_defaults",
+    config_namespace: "ANDROID",
+    bool_variables: ["TARGET_ENABLE_MEDIADRM_64"],
+    properties: ["compile_multilib"],
+}
+
+android_hardware_drm_1_0_multilib {
+    name: "android.hardware.drm@1.0-multilib-lib",
+    compile_multilib: "32",
+    soong_config_variables: {
+        TARGET_ENABLE_MEDIADRM_64: {
+            compile_multilib: "both",
+        }
+    }
+}
+
+android_hardware_drm_1_0_multilib {
+    name: "android.hardware.drm@1.0-multilib-exe",
+    compile_multilib: "32",
+    soong_config_variables: {
+        TARGET_ENABLE_MEDIADRM_64: {
+            compile_multilib: "first",
+        }
+    }
+}
+
+cc_defaults {
+    name: "android.hardware.drm@1.0-service-defaults",
+    proprietary: true,
+    relative_install_path: "hw",
+    include_dirs: ["hardware/interfaces/drm"],
+    header_libs: ["media_plugin_headers"],
+    static_libs: ["android.hardware.drm@1.0-helper"],
+
+    shared_libs: [
+        "android.hardware.drm@1.0",
+        "android.hidl.memory@1.0",
+        "libhidlbase",
+        "libhardware",
+        "liblog",
+        "libutils",
+        "libbinder",
+    ],
+}
+
+//############ Build legacy drm service ############
+
+cc_binary {
+    name: "android.hardware.drm@1.0-service",
+    defaults: [
+        "android.hardware.drm@1.0-multilib-exe",
+        "android.hardware.drm@1.0-service-defaults"
+    ],
+    init_rc: ["android.hardware.drm@1.0-service.rc"],
+    srcs: ["service.cpp"],
+}
+
+//############ Build legacy drm lazy service ############
+
+cc_binary {
+    name: "android.hardware.drm@1.0-service-lazy",
+    defaults: [
+        "android.hardware.drm@1.0-multilib-exe",
+        "android.hardware.drm@1.0-service-defaults"
+    ],
+    overrides: ["android.hardware.drm@1.0-service"],
+    init_rc: ["android.hardware.drm@1.0-service-lazy.rc"],
+    srcs: ["serviceLazy.cpp"],
+}
+
+//############ Build legacy drm impl library ############
+
+cc_library_shared {
+    name: "android.hardware.drm@1.0-impl",
+    defaults: ["android.hardware.drm@1.0-multilib-lib"],
+    proprietary: true,
+    relative_install_path: "hw",
+
+    include_dirs: [
+        "frameworks/native/include",
+        "frameworks/av/include",
+    ],
+
+    shared_libs: [
+        "android.hardware.drm@1.0",
+        "android.hidl.memory@1.0",
+        "libcutils",
+        "libhidlbase",
+        "libhidlmemory",
+        "liblog",
+        "libstagefright_foundation",
+        "libutils",
+    ],
+
+    static_libs: ["android.hardware.drm@1.0-helper"],
+
+    srcs: [
+        "DrmFactory.cpp",
+        "DrmPlugin.cpp",
+        "CryptoFactory.cpp",
+        "CryptoPlugin.cpp",
+        "LegacyPluginPath.cpp",
+        "TypeConvert.cpp",
+    ],
+}
diff --git a/drm/1.0/default/Android.mk b/drm/1.0/default/Android.mk
deleted file mode 100644
index 9016dc3..0000000
--- a/drm/1.0/default/Android.mk
+++ /dev/null
@@ -1,81 +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.
-
-
-############# Build legacy drm service ############
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-include $(LOCAL_PATH)/common_default_service.mk
-LOCAL_MODULE := android.hardware.drm@1.0-service
-LOCAL_INIT_RC := android.hardware.drm@1.0-service.rc
-LOCAL_SRC_FILES := service.cpp
-
-include $(BUILD_EXECUTABLE)
-
-############# Build legacy drm lazy service ############
-
-include $(CLEAR_VARS)
-
-include $(LOCAL_PATH)/common_default_service.mk
-LOCAL_MODULE := android.hardware.drm@1.0-service-lazy
-LOCAL_OVERRIDES_MODULES := android.hardware.drm@1.0-service
-LOCAL_INIT_RC := android.hardware.drm@1.0-service-lazy.rc
-LOCAL_SRC_FILES := serviceLazy.cpp
-
-include $(BUILD_EXECUTABLE)
-
-############# Build legacy drm impl library ############
-
-include $(CLEAR_VARS)
-LOCAL_MODULE := android.hardware.drm@1.0-impl
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-LOCAL_SRC_FILES := \
-    DrmFactory.cpp \
-    DrmPlugin.cpp \
-    CryptoFactory.cpp \
-    CryptoPlugin.cpp \
-    LegacyPluginPath.cpp \
-    TypeConvert.cpp \
-
-LOCAL_SHARED_LIBRARIES := \
-    android.hardware.drm@1.0 \
-    android.hidl.memory@1.0 \
-    libcutils \
-    libhidlbase \
-    libhidlmemory \
-    liblog \
-    libstagefright_foundation \
-    libutils \
-
-LOCAL_STATIC_LIBRARIES := \
-    android.hardware.drm@1.0-helper \
-
-LOCAL_C_INCLUDES := \
-    frameworks/native/include \
-    frameworks/av/include
-
-# TODO: Some legacy DRM plugins only support 32-bit. They need to be migrated to
-# 64-bit. (b/18948909) Once all of a device's legacy DRM plugins support 64-bit,
-# that device can turn on TARGET_ENABLE_MEDIADRM_64 to build this impl as
-# 64-bit.
-ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
-LOCAL_32_BIT_ONLY := true
-endif
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/drm/1.0/default/common_default_service.mk b/drm/1.0/default/common_default_service.mk
deleted file mode 100644
index 1b5a975..0000000
--- a/drm/1.0/default/common_default_service.mk
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-include $(CLEAR_VARS)
-LOCAL_PROPRIETARY_MODULE := true
-LOCAL_MODULE_RELATIVE_PATH := hw
-
-LOCAL_SHARED_LIBRARIES := \
-  android.hardware.drm@1.0 \
-  android.hidl.memory@1.0 \
-  libhidlbase \
-  libhardware \
-  liblog \
-  libutils \
-  libbinder \
-
-LOCAL_STATIC_LIBRARIES := \
-  android.hardware.drm@1.0-helper \
-
-LOCAL_C_INCLUDES := \
-  hardware/interfaces/drm
-
-LOCAL_HEADER_LIBRARIES := \
-  media_plugin_headers
-
-# TODO(b/18948909) Some legacy DRM plugins only support 32-bit. They need to be
-# migrated to 64-bit. Once all of a device's legacy DRM plugins support 64-bit,
-# that device can turn on TARGET_ENABLE_MEDIADRM_64 to build this service as
-# 64-bit.
-ifneq ($(TARGET_ENABLE_MEDIADRM_64), true)
-LOCAL_32_BIT_ONLY := true
-endif
diff --git a/drm/1.0/vts/functional/Android.bp b/drm/1.0/vts/functional/Android.bp
index 8fd258a..0545c70 100644
--- a/drm/1.0/vts/functional/Android.bp
+++ b/drm/1.0/vts/functional/Android.bp
@@ -43,12 +43,12 @@
         "android.hardware.drm@1.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
+        "libcrypto",
         "libhidlmemory",
         "libnativehelper",
     ],
     static_libs: [
         "android.hardware.drm@1.0-helper",
-        "libcrypto_static",
         "libdrmvtshelper",
     ],
     export_shared_lib_headers: [
@@ -76,12 +76,12 @@
         "android.hardware.drm@1.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
+        "libcrypto",
         "libhidlmemory",
         "libnativehelper",
     ],
     static_libs: [
         "android.hardware.drm@1.0-helper",
-        "libcrypto_static",
         "libdrmvtshelper",
     ],
     arch: {
diff --git a/drm/1.1/Android.bp b/drm/1.1/Android.bp
index 16010a6..0af4cf4 100644
--- a/drm/1.1/Android.bp
+++ b/drm/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.drm@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ICryptoFactory.hal",
diff --git a/drm/1.1/vts/functional/AndroidTest.xml b/drm/1.1/vts/functional/AndroidTest.xml
index 65c45ac..24eeb72 100644
--- a/drm/1.1/vts/functional/AndroidTest.xml
+++ b/drm/1.1/vts/functional/AndroidTest.xml
@@ -19,6 +19,10 @@
 
     <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
 
+    <target_preparer class="com.android.tradefed.targetprep.WifiPreparer" >
+        <option name="verify-only" value="true" />
+    </target_preparer>
+
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push-file" key="VtsHalDrmV1_1TargetTest" value="/data/local/tmp/VtsHalDrmV1_1TargetTest" />
diff --git a/drm/1.2/Android.bp b/drm/1.2/Android.bp
index 9104aa9..f1c60de 100644
--- a/drm/1.2/Android.bp
+++ b/drm/1.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.drm@1.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ICryptoFactory.hal",
diff --git a/drm/1.2/vts/functional/Android.bp b/drm/1.2/vts/functional/Android.bp
index 9aed4ee..271cc04 100644
--- a/drm/1.2/vts/functional/Android.bp
+++ b/drm/1.2/vts/functional/Android.bp
@@ -31,12 +31,12 @@
         "android.hardware.drm@1.2",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
+        "libcrypto",
         "libhidlmemory",
         "libnativehelper",
     ],
     static_libs: [
         "android.hardware.drm@1.0-helper",
-        "libcrypto_static",
         "libdrmvtshelper",
     ],
     export_shared_lib_headers: [
@@ -63,11 +63,11 @@
         "android.hardware.drm@1.0",
         "android.hardware.drm@1.2",
         "android.hidl.allocator@1.0",
+        "libcrypto",
         "libhidlmemory",
     ],
     static_libs: [
         "android.hardware.drm@1.0-helper",
-        "libcrypto_static",
         "libdrmvtshelper",
     ],
     arch: {
diff --git a/drm/1.2/vts/functional/AndroidTest.xml b/drm/1.2/vts/functional/AndroidTest.xml
index 5da38ae..3285c37 100644
--- a/drm/1.2/vts/functional/AndroidTest.xml
+++ b/drm/1.2/vts/functional/AndroidTest.xml
@@ -19,6 +19,10 @@
 
     <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
 
+    <target_preparer class="com.android.tradefed.targetprep.WifiPreparer" >
+        <option name="verify-only" value="true" />
+    </target_preparer>
+
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push-file" key="VtsHalDrmV1_2TargetTest" value="/data/local/tmp/VtsHalDrmV1_2TargetTest" />
diff --git a/drm/1.3/Android.bp b/drm/1.3/Android.bp
index b0ffcb9..9a2b9e1 100644
--- a/drm/1.3/Android.bp
+++ b/drm/1.3/Android.bp
@@ -3,12 +3,9 @@
 hidl_interface {
     name: "android.hardware.drm@1.3",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
-        "IDrmFactory.hal",
         "ICryptoFactory.hal",
+        "IDrmFactory.hal",
     ],
     interfaces: [
         "android.hardware.drm@1.0",
diff --git a/drm/1.3/vts/functional/AndroidTest.xml b/drm/1.3/vts/functional/AndroidTest.xml
index 338430f..9cc8e0c 100644
--- a/drm/1.3/vts/functional/AndroidTest.xml
+++ b/drm/1.3/vts/functional/AndroidTest.xml
@@ -19,6 +19,10 @@
 
     <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
 
+    <target_preparer class="com.android.tradefed.targetprep.WifiPreparer" >
+        <option name="verify-only" value="true" />
+    </target_preparer>
+
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push-file" key="VtsHalDrmV1_3TargetTest" value="/data/local/tmp/VtsHalDrmV1_3TargetTest" />
diff --git a/dumpstate/1.0/Android.bp b/dumpstate/1.0/Android.bp
index 3d47550..5d9eefc 100644
--- a/dumpstate/1.0/Android.bp
+++ b/dumpstate/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.dumpstate@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "IDumpstateDevice.hal",
     ],
diff --git a/dumpstate/1.1/Android.bp b/dumpstate/1.1/Android.bp
index 2aa8c82..75805df 100644
--- a/dumpstate/1.1/Android.bp
+++ b/dumpstate/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.dumpstate@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IDumpstateDevice.hal",
diff --git a/dumpstate/1.1/default/main.cpp b/dumpstate/1.1/default/main.cpp
index 3c17e18..4510f63 100644
--- a/dumpstate/1.1/default/main.cpp
+++ b/dumpstate/1.1/default/main.cpp
@@ -116,7 +116,7 @@
 
     configureRpcThreadpool(1, true);
 
-    sp<DumpstateDevice> dumpstate(new DumpstateDevice);
+    auto dumpstate = sp<DumpstateDevice>::make();
     auto serviceRegistrar = LazyServiceRegistrar::getInstance();
 
     if (serviceRegistrar.registerService(dumpstate) != ::android::OK) {
diff --git a/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp b/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp
index cbdd87b..1bef663 100644
--- a/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp
+++ b/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp
@@ -20,6 +20,7 @@
 #include <unistd.h>
 
 #include <functional>
+#include <tuple>
 #include <vector>
 
 #include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
@@ -27,6 +28,7 @@
 #include <cutils/native_handle.h>
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
+#include <hidl/HidlSupport.h>
 #include <hidl/ServiceManagement.h>
 #include <log/log.h>
 
@@ -39,13 +41,18 @@
 using ::android::hardware::dumpstate::V1_1::IDumpstateDevice;
 using ::android::hardware::dumpstate::V1_1::toString;
 
-class DumpstateHidl1_1Test : public ::testing::TestWithParam<std::string> {
+// Base class common to all dumpstate HAL v1.1 tests.
+template <typename T>
+class DumpstateHidl1_1TestBase : public ::testing::TestWithParam<T> {
   protected:
     virtual void SetUp() override { GetService(); }
 
+    virtual std::string GetInstanceName() = 0;
+
     void GetService() {
-        dumpstate = IDumpstateDevice::getService(GetParam());
-        ASSERT_NE(dumpstate, nullptr) << "Could not get HIDL instance";
+        const std::string instance_name = GetInstanceName();
+        dumpstate = IDumpstateDevice::getService(instance_name);
+        ASSERT_NE(dumpstate, nullptr) << "Could not get HIDL instance " << instance_name;
     }
 
     void ToggleVerboseLogging(bool enable) {
@@ -78,77 +85,76 @@
     sp<IDumpstateDevice> dumpstate;
 };
 
-#define TEST_FOR_DUMPSTATE_MODE(name, body, mode) \
-    TEST_P(DumpstateHidl1_1Test, name##_##mode) { body(DumpstateMode::mode); }
+// Tests that don't need to iterate every single DumpstateMode value for dumpstateBoard_1_1.
+class DumpstateHidl1_1GeneralTest : public DumpstateHidl1_1TestBase<std::string> {
+  protected:
+    virtual std::string GetInstanceName() override { return GetParam(); }
+};
 
-// We use a macro to define individual test cases instead of hidl_enum_range<> because some HAL
-// implementations are lazy and may call exit() at the end of dumpstateBoard(), which would cause
-// DEAD_OBJECT errors after the first iteration. Separate cases re-get the service each time as part
-// of SetUp(), and also provide better separation of concerns when specific modes are problematic.
-#define TEST_FOR_ALL_DUMPSTATE_MODES(name, body)       \
-    TEST_FOR_DUMPSTATE_MODE(name, body, FULL);         \
-    TEST_FOR_DUMPSTATE_MODE(name, body, INTERACTIVE);  \
-    TEST_FOR_DUMPSTATE_MODE(name, body, REMOTE);       \
-    TEST_FOR_DUMPSTATE_MODE(name, body, WEAR);         \
-    TEST_FOR_DUMPSTATE_MODE(name, body, CONNECTIVITY); \
-    TEST_FOR_DUMPSTATE_MODE(name, body, WIFI);         \
-    TEST_FOR_DUMPSTATE_MODE(name, body, DEFAULT);      \
-    TEST_FOR_DUMPSTATE_MODE(name, body, PROTO);
+// Tests that iterate every single DumpstateMode value for dumpstateBoard_1_1.
+class DumpstateHidl1_1PerModeTest
+    : public DumpstateHidl1_1TestBase<std::tuple<std::string, DumpstateMode>> {
+  protected:
+    virtual std::string GetInstanceName() override { return std::get<0>(GetParam()); }
+
+    DumpstateMode GetMode() { return std::get<1>(GetParam()); }
+
+    // Will only execute additional_assertions when status == expected.
+    void AssertStatusForMode(const Return<DumpstateStatus>& status, const DumpstateStatus expected,
+                             std::function<void()> additional_assertions = nullptr) {
+        ASSERT_TRUE(status.isOk())
+                << "Status should be ok and return a more specific DumpstateStatus: "
+                << status.description();
+        if (GetMode() == DumpstateMode::DEFAULT) {
+            ASSERT_EQ(expected, status)
+                    << "Required mode (DumpstateMode::" << toString(GetMode())
+                    << "): status should be DumpstateStatus::" << toString(expected)
+                    << ", but got DumpstateStatus::" << toString(status);
+        } else {
+            // The rest of the modes are optional to support, but they MUST return either the
+            // expected value or UNSUPPORTED_MODE.
+            ASSERT_TRUE(status == expected || status == DumpstateStatus::UNSUPPORTED_MODE)
+                    << "Optional mode (DumpstateMode::" << toString(GetMode())
+                    << "): status should be DumpstateStatus::" << toString(expected)
+                    << " or DumpstateStatus::UNSUPPORTED_MODE, but got DumpstateStatus::"
+                    << toString(status);
+        }
+        if (status == expected && additional_assertions != nullptr) {
+            additional_assertions();
+        }
+    }
+};
 
 constexpr uint64_t kDefaultTimeoutMillis = 30 * 1000;  // 30 seconds
 
-// Will only execute additional_assertions when status == expected.
-void AssertStatusForMode(const DumpstateMode mode, const Return<DumpstateStatus>& status,
-                         const DumpstateStatus expected,
-                         std::function<void()> additional_assertions = nullptr) {
-    ASSERT_TRUE(status.isOk()) << "Status should be ok and return a more specific DumpstateStatus: "
-                               << status.description();
-    if (mode == DumpstateMode::DEFAULT) {
-        ASSERT_EQ(expected, status) << "Required mode (DumpstateMode::" << toString(mode)
-                                    << "): status should be DumpstateStatus::" << toString(expected)
-                                    << ", but got DumpstateStatus::" << toString(status);
-    } else {
-        // The rest of the modes are optional to support, but they MUST return either the expected
-        // value or UNSUPPORTED_MODE.
-        ASSERT_TRUE(status == expected || status == DumpstateStatus::UNSUPPORTED_MODE)
-                << "Optional mode (DumpstateMode::" << toString(mode)
-                << "): status should be DumpstateStatus::" << toString(expected)
-                << " or DumpstateStatus::UNSUPPORTED_MODE, but got DumpstateStatus::"
-                << toString(status);
-    }
-    if (status == expected && additional_assertions != nullptr) {
-        additional_assertions();
-    }
-}
-
 // Negative test: make sure dumpstateBoard() doesn't crash when passed a null pointer.
-TEST_FOR_ALL_DUMPSTATE_MODES(TestNullHandle, [this](DumpstateMode mode) {
+TEST_P(DumpstateHidl1_1PerModeTest, TestNullHandle) {
     EnableVerboseLogging();
 
     Return<DumpstateStatus> status =
-            dumpstate->dumpstateBoard_1_1(nullptr, mode, kDefaultTimeoutMillis);
+            dumpstate->dumpstateBoard_1_1(nullptr, GetMode(), kDefaultTimeoutMillis);
 
-    AssertStatusForMode(mode, status, DumpstateStatus::ILLEGAL_ARGUMENT);
-});
+    AssertStatusForMode(status, DumpstateStatus::ILLEGAL_ARGUMENT);
+}
 
 // Negative test: make sure dumpstateBoard() ignores a handle with no FD.
-TEST_FOR_ALL_DUMPSTATE_MODES(TestHandleWithNoFd, [this](DumpstateMode mode) {
+TEST_P(DumpstateHidl1_1PerModeTest, TestHandleWithNoFd) {
     EnableVerboseLogging();
 
     native_handle_t* handle = native_handle_create(0, 0);
     ASSERT_NE(handle, nullptr) << "Could not create native_handle";
 
     Return<DumpstateStatus> status =
-            dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
+            dumpstate->dumpstateBoard_1_1(handle, GetMode(), kDefaultTimeoutMillis);
 
-    AssertStatusForMode(mode, status, DumpstateStatus::ILLEGAL_ARGUMENT);
+    AssertStatusForMode(status, DumpstateStatus::ILLEGAL_ARGUMENT);
 
     native_handle_close(handle);
     native_handle_delete(handle);
-});
+}
 
 // Positive test: make sure dumpstateBoard() writes something to the FD.
-TEST_FOR_ALL_DUMPSTATE_MODES(TestOk, [this](DumpstateMode mode) {
+TEST_P(DumpstateHidl1_1PerModeTest, TestOk) {
     EnableVerboseLogging();
 
     // Index 0 corresponds to the read end of the pipe; 1 to the write end.
@@ -160,9 +166,9 @@
     handle->data[0] = fds[1];
 
     Return<DumpstateStatus> status =
-            dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
+            dumpstate->dumpstateBoard_1_1(handle, GetMode(), kDefaultTimeoutMillis);
 
-    AssertStatusForMode(mode, status, DumpstateStatus::OK, [&fds]() {
+    AssertStatusForMode(status, DumpstateStatus::OK, [&fds]() {
         // Check that at least one byte was written.
         char buff;
         ASSERT_EQ(1, read(fds[0], &buff, 1)) << "Dumped nothing";
@@ -170,10 +176,10 @@
 
     native_handle_close(handle);
     native_handle_delete(handle);
-});
+}
 
 // Positive test: make sure dumpstateBoard() doesn't crash with two FDs.
-TEST_FOR_ALL_DUMPSTATE_MODES(TestHandleWithTwoFds, [this](DumpstateMode mode) {
+TEST_P(DumpstateHidl1_1PerModeTest, TestHandleWithTwoFds) {
     EnableVerboseLogging();
 
     int fds1[2];
@@ -187,9 +193,9 @@
     handle->data[1] = fds2[1];
 
     Return<DumpstateStatus> status =
-            dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
+            dumpstate->dumpstateBoard_1_1(handle, GetMode(), kDefaultTimeoutMillis);
 
-    AssertStatusForMode(mode, status, DumpstateStatus::OK, [&fds1, &fds2]() {
+    AssertStatusForMode(status, DumpstateStatus::OK, [&fds1, &fds2]() {
         // Check that at least one byte was written to one of the FDs.
         char buff;
         size_t read1 = read(fds1[0], &buff, 1);
@@ -200,10 +206,10 @@
 
     native_handle_close(handle);
     native_handle_delete(handle);
-});
+}
 
 // Make sure dumpstateBoard_1_1 actually validates its arguments.
-TEST_P(DumpstateHidl1_1Test, TestInvalidModeArgument_Negative) {
+TEST_P(DumpstateHidl1_1GeneralTest, TestInvalidModeArgument_Negative) {
     EnableVerboseLogging();
 
     int fds[2];
@@ -225,7 +231,7 @@
     native_handle_delete(handle);
 }
 
-TEST_P(DumpstateHidl1_1Test, TestInvalidModeArgument_Undefined) {
+TEST_P(DumpstateHidl1_1GeneralTest, TestInvalidModeArgument_Undefined) {
     EnableVerboseLogging();
 
     int fds[2];
@@ -248,7 +254,7 @@
 }
 
 // Positive test: make sure dumpstateBoard() from 1.0 doesn't fail.
-TEST_P(DumpstateHidl1_1Test, Test1_0MethodOk) {
+TEST_P(DumpstateHidl1_1GeneralTest, Test1_0MethodOk) {
     EnableVerboseLogging();
 
     int fds[2];
@@ -272,7 +278,7 @@
 
 // Make sure disabling verbose logging behaves correctly. Some info is still allowed to be emitted,
 // but it can't have privacy/storage/battery impacts.
-TEST_FOR_ALL_DUMPSTATE_MODES(TestVerboseLoggingDisabled, [this](DumpstateMode mode) {
+TEST_P(DumpstateHidl1_1PerModeTest, TestDeviceLoggingDisabled) {
     DisableVerboseLogging();
 
     // Index 0 corresponds to the read end of the pipe; 1 to the write end.
@@ -284,31 +290,31 @@
     handle->data[0] = fds[1];
 
     Return<DumpstateStatus> status =
-            dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
+            dumpstate->dumpstateBoard_1_1(handle, GetMode(), kDefaultTimeoutMillis);
 
     // We don't include additional assertions here about the file passed in. If verbose logging is
     // disabled, the OEM may choose to include nothing at all, but it is allowed to include some
     // essential information based on the mode as long as it isn't private user information.
-    AssertStatusForMode(mode, status, DumpstateStatus::OK);
+    AssertStatusForMode(status, DumpstateStatus::OK);
 
     native_handle_close(handle);
     native_handle_delete(handle);
-});
+}
 
 // Double-enable is perfectly valid, but the second call shouldn't do anything.
-TEST_P(DumpstateHidl1_1Test, TestRepeatedEnable) {
+TEST_P(DumpstateHidl1_1GeneralTest, TestRepeatedEnable) {
     EnableVerboseLogging();
     EnableVerboseLogging();
 }
 
 // Double-disable is perfectly valid, but the second call shouldn't do anything.
-TEST_P(DumpstateHidl1_1Test, TestRepeatedDisable) {
+TEST_P(DumpstateHidl1_1GeneralTest, TestRepeatedDisable) {
     DisableVerboseLogging();
     DisableVerboseLogging();
 }
 
 // Toggling in short order is perfectly valid.
-TEST_P(DumpstateHidl1_1Test, TestRepeatedToggle) {
+TEST_P(DumpstateHidl1_1GeneralTest, TestRepeatedToggle) {
     EnableVerboseLogging();
     DisableVerboseLogging();
     EnableVerboseLogging();
@@ -316,8 +322,23 @@
 }
 
 INSTANTIATE_TEST_SUITE_P(
-        PerInstance, DumpstateHidl1_1Test,
+        PerInstance, DumpstateHidl1_1GeneralTest,
         testing::ValuesIn(android::hardware::getAllHalInstanceNames(IDumpstateDevice::descriptor)),
         android::hardware::PrintInstanceNameToString);
 
+// Includes the mode's name as part of the description string.
+static inline std::string PrintInstanceNameToStringWithMode(
+        const testing::TestParamInfo<std::tuple<std::string, DumpstateMode>>& info) {
+    return android::hardware::PrintInstanceNameToString(
+                   testing::TestParamInfo(std::get<0>(info.param), info.index)) +
+           "_" + toString(std::get<1>(info.param));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstanceAndMode, DumpstateHidl1_1PerModeTest,
+        testing::Combine(testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+                                 IDumpstateDevice::descriptor)),
+                         testing::ValuesIn(android::hardware::hidl_enum_range<DumpstateMode>())),
+        PrintInstanceNameToStringWithMode);
+
 }  // namespace
diff --git a/fastboot/1.0/Android.bp b/fastboot/1.0/Android.bp
index ec447b8..60dfb2d 100644
--- a/fastboot/1.0/Android.bp
+++ b/fastboot/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.fastboot@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IFastboot.hal",
diff --git a/gatekeeper/1.0/Android.bp b/gatekeeper/1.0/Android.bp
index 5d63eaf..28fd5b6 100644
--- a/gatekeeper/1.0/Android.bp
+++ b/gatekeeper/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.gatekeeper@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IGatekeeper.hal",
diff --git a/gnss/1.0/Android.bp b/gnss/1.0/Android.bp
index d97588c..22f47e8 100644
--- a/gnss/1.0/Android.bp
+++ b/gnss/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.gnss@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IAGnss.hal",
diff --git a/gnss/1.1/Android.bp b/gnss/1.1/Android.bp
index 5294a6b..1c38e97 100644
--- a/gnss/1.1/Android.bp
+++ b/gnss/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.gnss@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "IGnss.hal",
         "IGnssCallback.hal",
diff --git a/gnss/1.1/vts/functional/Android.bp b/gnss/1.1/vts/functional/Android.bp
index 0d540b7..94bfb89 100644
--- a/gnss/1.1/vts/functional/Android.bp
+++ b/gnss/1.1/vts/functional/Android.bp
@@ -25,6 +25,7 @@
     static_libs: [
         "android.hardware.gnss@1.0",
         "android.hardware.gnss@1.1",
+        "android.hardware.gnss@2.0",
         "android.hardware.gnss@common-vts-lib",
     ],
     shared_libs: [
diff --git a/gnss/2.0/Android.bp b/gnss/2.0/Android.bp
index db5075f..b7a98b7 100644
--- a/gnss/2.0/Android.bp
+++ b/gnss/2.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.gnss@2.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IAGnss.hal",
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.cpp b/gnss/2.0/vts/functional/gnss_hal_test.cpp
index 59e18f3..1cb44c5 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test.cpp
@@ -247,3 +247,46 @@
     capabilities_cbq_.store(capabilities);
     return Void();
 }
+
+GnssConstellationType_1_0 GnssHalTest::startLocationAndGetNonGpsConstellation() {
+    const int kLocationsToAwait = 3;
+
+    gnss_cb_->location_cbq_.reset();
+    StartAndCheckLocations(kLocationsToAwait);
+    const int location_called_count = gnss_cb_->location_cbq_.calledCount();
+
+    // Tolerate 1 less sv status to handle edge cases in reporting.
+    int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+    EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+    ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
+          sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
+
+    // Find first non-GPS constellation to blacklist. Exclude IRNSS in GnssConstellationType_2_0
+    // as blacklisting of this constellation is not supported in gnss@2.0.
+    const int kGnssSvStatusTimeout = 2;
+    GnssConstellationType_1_0 constellation_to_blacklist = GnssConstellationType_1_0::UNKNOWN;
+    for (int i = 0; i < sv_info_list_cbq_size; ++i) {
+        hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
+        gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
+        for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
+            if ((sv_info.v1_0.svFlag & IGnssCallback_2_0::GnssSvFlags::USED_IN_FIX) &&
+                (sv_info.constellation != GnssConstellationType_2_0::UNKNOWN) &&
+                (sv_info.constellation != GnssConstellationType_2_0::IRNSS) &&
+                (sv_info.constellation != GnssConstellationType_2_0::GPS)) {
+                // found a non-GPS V1_0 constellation
+                constellation_to_blacklist = Utils::mapConstellationType(sv_info.constellation);
+                break;
+            }
+        }
+        if (constellation_to_blacklist != GnssConstellationType_1_0::UNKNOWN) {
+            break;
+        }
+    }
+
+    if (constellation_to_blacklist == GnssConstellationType_1_0::UNKNOWN) {
+        ALOGI("No non-GPS constellations found, constellation blacklist test less effective.");
+        // Proceed functionally to blacklist something.
+        constellation_to_blacklist = GnssConstellationType_1_0::GLONASS;
+    }
+    return constellation_to_blacklist;
+}
diff --git a/gnss/2.0/vts/functional/gnss_hal_test.h b/gnss/2.0/vts/functional/gnss_hal_test.h
index a02a9ff..7fbd735 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test.h
+++ b/gnss/2.0/vts/functional/gnss_hal_test.h
@@ -31,6 +31,9 @@
 using android::hardware::gnss::V1_0::GnssLocationFlags;
 using android::hardware::gnss::V2_0::IGnss;
 
+using GnssConstellationType_1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
+using GnssConstellationType_2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
+
 using GnssLocation_1_0 = android::hardware::gnss::V1_0::GnssLocation;
 using GnssLocation_2_0 = android::hardware::gnss::V2_0::GnssLocation;
 
@@ -194,6 +197,16 @@
      */
     void SetPositionMode(const int min_interval_msec, const bool low_power_mode);
 
+    /*
+     * startLocationAndGetNonGpsConstellation:
+     * 1. Start location
+     * 2. Find and return first non-GPS constellation
+     *
+     * Note that location is not stopped in this method. The client should call
+     * StopAndClearLocations() after the call.
+     */
+    GnssConstellationType_1_0 startLocationAndGetNonGpsConstellation();
+
     sp<IGnss> gnss_hal_;         // GNSS HAL to call into
     sp<GnssCallback> gnss_cb_;   // Primary callback interface
 };
diff --git a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
index c93e89b..51dcf0d 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
@@ -24,8 +24,6 @@
 using android::hardware::hidl_string;
 using android::hardware::hidl_vec;
 
-using GnssConstellationType_2_0 = android::hardware::gnss::V2_0::GnssConstellationType;
-using GnssConstellationType_1_0 = android::hardware::gnss::V1_0::GnssConstellationType;
 using IGnssConfiguration_2_0 = android::hardware::gnss::V2_0::IGnssConfiguration;
 using IGnssConfiguration_1_1 = android::hardware::gnss::V1_1::IGnssConfiguration;
 using IAGnssRil_2_0 = android::hardware::gnss::V2_0::IAGnssRil;
@@ -223,9 +221,10 @@
                 static_cast<uint32_t>(measurement.state) >=
                         static_cast<uint32_t>(IGnssMeasurementCallback_2_0::GnssMeasurementState::
                                                       STATE_UNKNOWN) &&
-                static_cast<uint32_t>(measurement.state) <=
-                        static_cast<uint32_t>(IGnssMeasurementCallback_2_0::GnssMeasurementState::
-                                                      STATE_2ND_CODE_LOCK));
+                static_cast<uint32_t>(measurement.state) <
+                        (static_cast<uint32_t>(IGnssMeasurementCallback_2_0::GnssMeasurementState::
+                                                       STATE_2ND_CODE_LOCK)
+                         << 1));
     }
 
     iGnssMeasurement->close();
@@ -491,31 +490,6 @@
 }
 
 /*
- * MapConstellationType:
- * Given a GnssConstellationType_2_0 type constellation, maps to its equivalent
- * GnssConstellationType_1_0 type constellation. For constellations that do not have
- * an equivalent value, maps to GnssConstellationType_1_0::UNKNOWN
- */
-GnssConstellationType_1_0 MapConstellationType(GnssConstellationType_2_0 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;
-        default:
-            return GnssConstellationType_1_0::UNKNOWN;
-    }
-}
-
-/*
  * FindStrongFrequentNonGpsSource:
  *
  * Search through a GnssSvStatus list for the strongest non-GPS satellite observed enough times
@@ -554,7 +528,7 @@
                 (sv_info.constellation != GnssConstellationType_2_0::GPS)) {
                 ComparableBlacklistedSource source;
                 source.id.svid = sv_info.v1_0.svid;
-                source.id.constellation = MapConstellationType(sv_info.constellation);
+                source.id.constellation = Utils::mapConstellationType(sv_info.constellation);
 
                 const auto& itSignal = mapSignals.find(source);
                 if (itSignal == mapSignals.end()) {
@@ -693,7 +667,7 @@
         hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
         gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
         for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
-            auto constellation = MapConstellationType(sv_info.constellation);
+            auto constellation = Utils::mapConstellationType(sv_info.constellation);
             EXPECT_FALSE((sv_info.v1_0.svid == source_to_blacklist.svid) &&
                          (constellation == source_to_blacklist.constellation) &&
                          (sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
@@ -735,7 +709,7 @@
             hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
             gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
             for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
-                auto constellation = MapConstellationType(sv_info.constellation);
+                auto constellation = Utils::mapConstellationType(sv_info.constellation);
                 if ((sv_info.v1_0.svid == source_to_blacklist.svid) &&
                     (constellation == source_to_blacklist.constellation) &&
                     (sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX)) {
@@ -751,7 +725,7 @@
 }
 
 /*
- * BlacklistConstellation:
+ * BlacklistConstellationWithLocationOff:
  *
  * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
  * GnssStatus for any non-GPS constellations.
@@ -760,12 +734,11 @@
  * GnssStatus does not use any constellation but GPS.
  * 4a & b) Clean up by turning off location, and send in empty blacklist.
  */
-TEST_P(GnssHalTest, BlacklistConstellation) {
+TEST_P(GnssHalTest, BlacklistConstellationWithLocationOff) {
     if (!IsGnssHalVersion_2_0()) {
         ALOGI("Test BlacklistConstellation skipped. GNSS HAL version is greater than 2.0.");
         return;
     }
-
     if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) {
         ALOGI("Test BlacklistConstellation skipped. SATELLITE_BLACKLIST capability not supported.");
         return;
@@ -773,43 +746,12 @@
 
     const int kLocationsToAwait = 3;
 
-    gnss_cb_->location_cbq_.reset();
-    StartAndCheckLocations(kLocationsToAwait);
-    const int location_called_count = gnss_cb_->location_cbq_.calledCount();
+    // Find first non-GPS constellation to blacklist
+    GnssConstellationType_1_0 constellation_to_blacklist = startLocationAndGetNonGpsConstellation();
 
-    // Tolerate 1 less sv status to handle edge cases in reporting.
-    int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
-    EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
-    ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
-          sv_info_list_cbq_size, kLocationsToAwait, location_called_count);
+    // Turns off location
+    StopAndClearLocations();
 
-    // Find first non-GPS constellation to blacklist. Exclude IRNSS in GnssConstellationType_2_0
-    // as blacklisting of this constellation is not supported in gnss@2.0.
-    const int kGnssSvStatusTimeout = 2;
-    GnssConstellationType_1_0 constellation_to_blacklist = GnssConstellationType_1_0::UNKNOWN;
-    for (int i = 0; i < sv_info_list_cbq_size; ++i) {
-        hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
-        gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
-        for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
-            if ((sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX) &&
-                (sv_info.constellation != GnssConstellationType_2_0::UNKNOWN) &&
-                (sv_info.constellation != GnssConstellationType_2_0::IRNSS) &&
-                (sv_info.constellation != GnssConstellationType_2_0::GPS)) {
-                // found a non-GPS V1_0 constellation
-                constellation_to_blacklist = MapConstellationType(sv_info.constellation);
-                break;
-            }
-        }
-        if (constellation_to_blacklist != GnssConstellationType_1_0::UNKNOWN) {
-            break;
-        }
-    }
-
-    if (constellation_to_blacklist == GnssConstellationType_1_0::UNKNOWN) {
-        ALOGI("No non-GPS constellations found, constellation blacklist test less effective.");
-        // Proceed functionally to blacklist something.
-        constellation_to_blacklist = GnssConstellationType_1_0::GLONASS;
-    }
     IGnssConfiguration_1_1::BlacklistedSource source_to_blacklist;
     source_to_blacklist.constellation = constellation_to_blacklist;
     source_to_blacklist.svid = 0;  // documented wildcard for all satellites in this constellation
@@ -823,6 +765,7 @@
     sources.resize(1);
     sources[0] = source_to_blacklist;
 
+    // setBlacklist when location is off.
     auto result = gnss_configuration_hal->setBlacklist(sources);
     ASSERT_TRUE(result.isOk());
     EXPECT_TRUE(result);
@@ -834,15 +777,93 @@
     StartAndCheckLocations(kLocationsToAwait);
 
     // Tolerate 1 less sv status to handle edge cases in reporting.
-    sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+    int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
     EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
     ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations", sv_info_list_cbq_size,
           kLocationsToAwait);
+    const int kGnssSvStatusTimeout = 2;
     for (int i = 0; i < sv_info_list_cbq_size; ++i) {
         hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
         gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
         for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
-            auto constellation = MapConstellationType(sv_info.constellation);
+            auto constellation = Utils::mapConstellationType(sv_info.constellation);
+            EXPECT_FALSE((constellation == source_to_blacklist.constellation) &&
+                         (sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
+        }
+    }
+
+    // clean up
+    StopAndClearLocations();
+    sources.resize(0);
+    result = gnss_configuration_hal->setBlacklist(sources);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+}
+
+/*
+ * BlacklistConstellationWithLocationOn:
+ *
+ * 1) Turns on location, waits for 3 locations, ensuring they are valid, and checks corresponding
+ * GnssStatus for any non-GPS constellations.
+ * 2a & b) Blacklist first non-GPS constellations, and turns off location.
+ * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
+ * GnssStatus does not use any constellation but GPS.
+ * 4a & b) Clean up by turning off location, and send in empty blacklist.
+ */
+TEST_P(GnssHalTest, BlacklistConstellationWithLocationOn) {
+    if (!IsGnssHalVersion_2_0()) {
+        ALOGI("Test BlacklistConstellation skipped. GNSS HAL version is greater than 2.0.");
+        return;
+    }
+
+    if (!(gnss_cb_->last_capabilities_ & IGnssCallback::Capabilities::SATELLITE_BLACKLIST)) {
+        ALOGI("Test BlacklistConstellation skipped. SATELLITE_BLACKLIST capability not supported.");
+        return;
+    }
+
+    const int kLocationsToAwait = 3;
+
+    // Find first non-GPS constellation to blacklist
+    GnssConstellationType_1_0 constellation_to_blacklist = startLocationAndGetNonGpsConstellation();
+
+    IGnssConfiguration_1_1::BlacklistedSource source_to_blacklist;
+    source_to_blacklist.constellation = constellation_to_blacklist;
+    source_to_blacklist.svid = 0;  // documented wildcard for all satellites in this constellation
+
+    auto gnss_configuration_hal_return = gnss_hal_->getExtensionGnssConfiguration_1_1();
+    ASSERT_TRUE(gnss_configuration_hal_return.isOk());
+    sp<IGnssConfiguration_1_1> gnss_configuration_hal = gnss_configuration_hal_return;
+    ASSERT_NE(gnss_configuration_hal, nullptr);
+
+    hidl_vec<IGnssConfiguration_1_1::BlacklistedSource> sources;
+    sources.resize(1);
+    sources[0] = source_to_blacklist;
+
+    // setBlacklist when location is on.
+    auto result = gnss_configuration_hal->setBlacklist(sources);
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+
+    // Turns off location
+    StopAndClearLocations();
+
+    // retry and ensure constellation not used
+    gnss_cb_->sv_info_list_cbq_.reset();
+
+    gnss_cb_->location_cbq_.reset();
+    StartAndCheckLocations(kLocationsToAwait);
+
+    // Tolerate 1 less sv status to handle edge cases in reporting.
+    int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+    EXPECT_GE(sv_info_list_cbq_size + 1, kLocationsToAwait);
+    ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations", sv_info_list_cbq_size,
+          kLocationsToAwait);
+    const int kGnssSvStatusTimeout = 2;
+    for (int i = 0; i < sv_info_list_cbq_size; ++i) {
+        hidl_vec<IGnssCallback_2_0::GnssSvInfo> sv_info_list;
+        gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_list, kGnssSvStatusTimeout);
+        for (IGnssCallback_2_0::GnssSvInfo sv_info : sv_info_list) {
+            auto constellation = Utils::mapConstellationType(sv_info.constellation);
             EXPECT_FALSE((constellation == source_to_blacklist.constellation) &&
                          (sv_info.v1_0.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX));
         }
diff --git a/gnss/2.1/Android.bp b/gnss/2.1/Android.bp
index 2122399..affbeae 100644
--- a/gnss/2.1/Android.bp
+++ b/gnss/2.1/Android.bp
@@ -3,22 +3,19 @@
 hidl_interface {
     name: "android.hardware.gnss@2.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IGnss.hal",
         "IGnssAntennaInfo.hal",
         "IGnssAntennaInfoCallback.hal",
         "IGnssCallback.hal",
+        "IGnssConfiguration.hal",
         "IGnssMeasurement.hal",
         "IGnssMeasurementCallback.hal",
-        "IGnssConfiguration.hal",
     ],
     interfaces: [
-        "android.hardware.gnss.measurement_corrections@1.1",
         "android.hardware.gnss.measurement_corrections@1.0",
+        "android.hardware.gnss.measurement_corrections@1.1",
         "android.hardware.gnss.visibility_control@1.0",
         "android.hardware.gnss@1.0",
         "android.hardware.gnss@1.1",
@@ -26,4 +23,5 @@
         "android.hidl.base@1.0",
     ],
     gen_java: true,
+    gen_java_constants: true,
 }
diff --git a/gnss/2.1/default/Android.bp b/gnss/2.1/default/Android.bp
index c4dc8fd..7739f90 100644
--- a/gnss/2.1/default/Android.bp
+++ b/gnss/2.1/default/Android.bp
@@ -21,12 +21,6 @@
     vendor: true,
     vintf_fragments: ["android.hardware.gnss@2.1-service.xml"],
     srcs: [
-        "Gnss.cpp",
-        "GnssAntennaInfo.cpp",
-        "GnssDebug.cpp",
-        "GnssMeasurement.cpp",
-        "GnssMeasurementCorrections.cpp",
-        "GnssConfiguration.cpp",
         "service.cpp",
     ],
     shared_libs: [
diff --git a/gnss/2.1/default/Gnss.cpp b/gnss/2.1/default/Gnss.cpp
deleted file mode 100644
index 2b327a9..0000000
--- a/gnss/2.1/default/Gnss.cpp
+++ /dev/null
@@ -1,439 +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 "Gnss"
-
-#include "Gnss.h"
-#include "GnssAntennaInfo.h"
-#include "GnssDebug.h"
-#include "GnssMeasurement.h"
-#include "GnssMeasurementCorrections.h"
-#include "Utils.h"
-
-#include <log/log.h>
-
-using ::android::hardware::gnss::common::Utils;
-using ::android::hardware::gnss::measurement_corrections::V1_1::implementation::
-        GnssMeasurementCorrections;
-
-namespace android {
-namespace hardware {
-namespace gnss {
-namespace V2_1 {
-namespace implementation {
-
-sp<V2_1::IGnssCallback> Gnss::sGnssCallback_2_1 = nullptr;
-sp<V2_0::IGnssCallback> Gnss::sGnssCallback_2_0 = nullptr;
-sp<V1_1::IGnssCallback> Gnss::sGnssCallback_1_1 = nullptr;
-sp<V1_0::IGnssCallback> Gnss::sGnssCallback_1_0 = nullptr;
-
-Gnss::Gnss() : mMinIntervalMs(1000), mGnssConfiguration{new GnssConfiguration()} {}
-
-Gnss::~Gnss() {
-    stop();
-}
-
-Return<bool> Gnss::start() {
-    ALOGD("start");
-    if (mIsActive) {
-        ALOGW("Gnss has started. Restarting...");
-        stop();
-    }
-
-    mIsActive = true;
-    mThread = std::thread([this]() {
-        while (mIsActive == true) {
-            auto svStatus = filterBlacklistedSatellitesV2_1(Utils::getMockSvInfoListV2_1());
-            this->reportSvStatus(svStatus);
-
-            if (sGnssCallback_2_1 != nullptr || sGnssCallback_2_0 != nullptr) {
-                const auto location = Utils::getMockLocationV2_0();
-                this->reportLocation(location);
-            } else {
-                const auto location = Utils::getMockLocationV1_0();
-                this->reportLocation(location);
-            }
-
-            std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
-        }
-    });
-    return true;
-}
-
-hidl_vec<GnssSvInfo> Gnss::filterBlacklistedSatellitesV2_1(hidl_vec<GnssSvInfo> gnssSvInfoList) {
-    for (uint32_t i = 0; i < gnssSvInfoList.size(); i++) {
-        if (mGnssConfiguration->isBlacklistedV2_1(gnssSvInfoList[i])) {
-            gnssSvInfoList[i].v2_0.v1_0.svFlag &=
-                    ~static_cast<uint8_t>(V1_0::IGnssCallback::GnssSvFlags::USED_IN_FIX);
-        }
-    }
-    return gnssSvInfoList;
-}
-
-Return<bool> Gnss::stop() {
-    ALOGD("stop");
-    mIsActive = false;
-    if (mThread.joinable()) {
-        mThread.join();
-    }
-    return true;
-}
-
-// Methods from V1_0::IGnss follow.
-Return<bool> Gnss::setCallback(const sp<V1_0::IGnssCallback>& callback) {
-    if (callback == nullptr) {
-        ALOGE("%s: Null callback ignored", __func__);
-        return false;
-    }
-
-    sGnssCallback_1_0 = callback;
-
-    uint32_t capabilities = 0x0 | V1_0::IGnssCallback::Capabilities::MEASUREMENTS |
-                            V1_0::IGnssCallback::Capabilities::SCHEDULING;
-    auto ret = sGnssCallback_1_0->gnssSetCapabilitesCb(capabilities);
-    if (!ret.isOk()) {
-        ALOGE("%s: Unable to invoke callback", __func__);
-    }
-
-    IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2018};
-
-    ret = sGnssCallback_1_0->gnssSetSystemInfoCb(gnssInfo);
-    if (!ret.isOk()) {
-        ALOGE("%s: Unable to invoke callback", __func__);
-    }
-
-    return true;
-}
-
-Return<void> Gnss::cleanup() {
-    sGnssCallback_2_1 = nullptr;
-    sGnssCallback_2_0 = nullptr;
-    return Void();
-}
-
-Return<bool> Gnss::injectTime(int64_t, int64_t, int32_t) {
-    return true;
-}
-
-Return<bool> Gnss::injectLocation(double, double, float) {
-    return true;
-}
-
-Return<void> Gnss::deleteAidingData(V1_0::IGnss::GnssAidingData) {
-    // TODO implement
-    return Void();
-}
-
-Return<bool> Gnss::setPositionMode(V1_0::IGnss::GnssPositionMode,
-                                   V1_0::IGnss::GnssPositionRecurrence, uint32_t minIntervalMs,
-                                   uint32_t, uint32_t) {
-    mMinIntervalMs = minIntervalMs;
-    return true;
-}
-
-Return<sp<V1_0::IAGnssRil>> Gnss::getExtensionAGnssRil() {
-    // TODO implement
-    return ::android::sp<V1_0::IAGnssRil>{};
-}
-
-Return<sp<V1_0::IGnssGeofencing>> Gnss::getExtensionGnssGeofencing() {
-    // TODO implement
-    return ::android::sp<V1_0::IGnssGeofencing>{};
-}
-
-Return<sp<V1_0::IAGnss>> Gnss::getExtensionAGnss() {
-    // TODO implement
-    return ::android::sp<V1_0::IAGnss>{};
-}
-
-Return<sp<V1_0::IGnssNi>> Gnss::getExtensionGnssNi() {
-    // TODO implement
-    return ::android::sp<V1_0::IGnssNi>{};
-}
-
-Return<sp<V1_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement() {
-    ALOGD("Gnss::getExtensionGnssMeasurement");
-    return new GnssMeasurement();
-}
-
-Return<sp<V1_0::IGnssNavigationMessage>> Gnss::getExtensionGnssNavigationMessage() {
-    // TODO implement
-    return ::android::sp<V1_0::IGnssNavigationMessage>{};
-}
-
-Return<sp<V1_0::IGnssXtra>> Gnss::getExtensionXtra() {
-    // TODO implement
-    return ::android::sp<V1_0::IGnssXtra>{};
-}
-
-Return<sp<V1_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration() {
-    // TODO implement
-    return ::android::sp<V1_0::IGnssConfiguration>{};
-}
-
-Return<sp<V1_0::IGnssDebug>> Gnss::getExtensionGnssDebug() {
-    return new V1_1::implementation::GnssDebug();
-}
-
-Return<sp<V1_0::IGnssBatching>> Gnss::getExtensionGnssBatching() {
-    // TODO implement
-    return ::android::sp<V1_0::IGnssBatching>{};
-}
-
-// Methods from V1_1::IGnss follow.
-Return<bool> Gnss::setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) {
-    if (callback == nullptr) {
-        ALOGE("%s: Null callback ignored", __func__);
-        return false;
-    }
-
-    sGnssCallback_1_1 = callback;
-
-    uint32_t capabilities = 0x0;
-    auto ret = sGnssCallback_1_1->gnssSetCapabilitesCb(capabilities);
-    if (!ret.isOk()) {
-        ALOGE("%s: Unable to invoke callback", __func__);
-    }
-
-    IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2018};
-
-    ret = sGnssCallback_1_1->gnssSetSystemInfoCb(gnssInfo);
-    if (!ret.isOk()) {
-        ALOGE("%s: Unable to invoke callback", __func__);
-    }
-
-    auto gnssName = "Google Mock GNSS Implementation v2.1";
-    ret = sGnssCallback_1_1->gnssNameCb(gnssName);
-    if (!ret.isOk()) {
-        ALOGE("%s: Unable to invoke callback", __func__);
-    }
-
-    return true;
-}
-
-Return<bool> Gnss::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode,
-                                       V1_0::IGnss::GnssPositionRecurrence, uint32_t minIntervalMs,
-                                       uint32_t, uint32_t, bool) {
-    mMinIntervalMs = minIntervalMs;
-    return true;
-}
-
-Return<sp<V1_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_1_1() {
-    // TODO implement
-    return ::android::sp<V1_1::IGnssConfiguration>{};
-}
-
-Return<sp<V1_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_1_1() {
-    // TODO implement
-    return ::android::sp<V1_1::IGnssMeasurement>{};
-}
-
-Return<bool> Gnss::injectBestLocation(const V1_0::GnssLocation&) {
-    return true;
-}
-
-// Methods from V2_0::IGnss follow.
-Return<bool> Gnss::setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) {
-    ALOGD("Gnss::setCallback_2_0");
-    if (callback == nullptr) {
-        ALOGE("%s: Null callback ignored", __func__);
-        return false;
-    }
-
-    sGnssCallback_2_0 = callback;
-
-    using Capabilities = V2_0::IGnssCallback::Capabilities;
-    const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS |
-                              Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST;
-    auto ret = sGnssCallback_2_0->gnssSetCapabilitiesCb_2_0(capabilities);
-    if (!ret.isOk()) {
-        ALOGE("%s: Unable to invoke callback", __func__);
-    }
-
-    V1_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2019};
-
-    ret = sGnssCallback_2_0->gnssSetSystemInfoCb(gnssInfo);
-    if (!ret.isOk()) {
-        ALOGE("%s: Unable to invoke callback", __func__);
-    }
-
-    auto gnssName = "Google Mock GNSS Implementation v2.1";
-    ret = sGnssCallback_2_0->gnssNameCb(gnssName);
-    if (!ret.isOk()) {
-        ALOGE("%s: Unable to invoke callback", __func__);
-    }
-
-    return true;
-}
-
-Return<sp<V2_0::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_0() {
-    ALOGD("Gnss::getExtensionGnssConfiguration_2_0");
-    return mGnssConfiguration;
-}
-
-Return<sp<V2_0::IGnssDebug>> Gnss::getExtensionGnssDebug_2_0() {
-    // TODO implement
-    return ::android::sp<V2_0::IGnssDebug>{};
-}
-
-Return<sp<V2_0::IAGnss>> Gnss::getExtensionAGnss_2_0() {
-    // TODO implement
-    return ::android::sp<V2_0::IAGnss>{};
-}
-
-Return<sp<V2_0::IAGnssRil>> Gnss::getExtensionAGnssRil_2_0() {
-    // TODO implement
-    return ::android::sp<V2_0::IAGnssRil>{};
-}
-
-Return<sp<V2_0::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_0() {
-    ALOGD("Gnss::getExtensionGnssMeasurement_2_0");
-    return new GnssMeasurement();
-}
-
-Return<sp<measurement_corrections::V1_0::IMeasurementCorrections>>
-Gnss::getExtensionMeasurementCorrections() {
-    ALOGD("Gnss::getExtensionMeasurementCorrections()");
-    return new GnssMeasurementCorrections();
-}
-
-Return<sp<visibility_control::V1_0::IGnssVisibilityControl>> Gnss::getExtensionVisibilityControl() {
-    // TODO implement
-    return ::android::sp<visibility_control::V1_0::IGnssVisibilityControl>{};
-}
-
-Return<sp<V2_0::IGnssBatching>> Gnss::getExtensionGnssBatching_2_0() {
-    // TODO implement
-    return ::android::sp<V2_0::IGnssBatching>{};
-}
-
-Return<bool> Gnss::injectBestLocation_2_0(const V2_0::GnssLocation&) {
-    // TODO(b/124012850): Implement function.
-    return bool{};
-}
-
-// Methods from V2_1::IGnss follow.
-Return<bool> Gnss::setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) {
-    ALOGD("Gnss::setCallback_2_1");
-    if (callback == nullptr) {
-        ALOGE("%s: Null callback ignored", __func__);
-        return false;
-    }
-
-    sGnssCallback_2_1 = callback;
-
-    using Capabilities = V2_1::IGnssCallback::Capabilities;
-    const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS |
-                              Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST |
-                              Capabilities::ANTENNA_INFO;
-    auto ret = sGnssCallback_2_1->gnssSetCapabilitiesCb_2_1(capabilities);
-    if (!ret.isOk()) {
-        ALOGE("%s: Unable to invoke callback", __func__);
-    }
-
-    V1_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2020};
-
-    ret = sGnssCallback_2_1->gnssSetSystemInfoCb(gnssInfo);
-    if (!ret.isOk()) {
-        ALOGE("%s: Unable to invoke callback", __func__);
-    }
-
-    auto gnssName = "Android Mock GNSS Implementation v2.1";
-    ret = sGnssCallback_2_1->gnssNameCb(gnssName);
-    if (!ret.isOk()) {
-        ALOGE("%s: Unable to invoke callback", __func__);
-    }
-
-    return true;
-}
-
-Return<sp<V2_1::IGnssMeasurement>> Gnss::getExtensionGnssMeasurement_2_1() {
-    ALOGD("Gnss::getExtensionGnssMeasurement_2_1");
-    return new GnssMeasurement();
-}
-
-Return<sp<V2_1::IGnssConfiguration>> Gnss::getExtensionGnssConfiguration_2_1() {
-    ALOGD("Gnss::getExtensionGnssConfiguration_2_1");
-    return mGnssConfiguration;
-}
-
-Return<sp<measurement_corrections::V1_1::IMeasurementCorrections>>
-Gnss::getExtensionMeasurementCorrections_1_1() {
-    ALOGD("Gnss::getExtensionMeasurementCorrections_1_1()");
-    return new GnssMeasurementCorrections();
-}
-
-Return<sp<V2_1::IGnssAntennaInfo>> Gnss::getExtensionGnssAntennaInfo() {
-    ALOGD("Gnss::getExtensionGnssAntennaInfo");
-    return new GnssAntennaInfo();
-}
-
-void Gnss::reportSvStatus(const hidl_vec<GnssSvInfo>& svInfoList) const {
-    std::unique_lock<std::mutex> lock(mMutex);
-    // TODO(skz): update this to call 2_0 callback if non-null
-    if (sGnssCallback_2_1 == nullptr) {
-        ALOGE("%s: sGnssCallback v2.1 is null.", __func__);
-        return;
-    }
-    auto ret = sGnssCallback_2_1->gnssSvStatusCb_2_1(svInfoList);
-    if (!ret.isOk()) {
-        ALOGE("%s: Unable to invoke callback", __func__);
-    }
-}
-
-void Gnss::reportLocation(const V1_0::GnssLocation& location) const {
-    std::unique_lock<std::mutex> lock(mMutex);
-    if (sGnssCallback_1_1 != nullptr) {
-        auto ret = sGnssCallback_1_1->gnssLocationCb(location);
-        if (!ret.isOk()) {
-            ALOGE("%s: Unable to invoke callback v1.1", __func__);
-        }
-        return;
-    }
-    if (sGnssCallback_1_0 == nullptr) {
-        ALOGE("%s: No non-null callback", __func__);
-        return;
-    }
-    auto ret = sGnssCallback_1_0->gnssLocationCb(location);
-    if (!ret.isOk()) {
-        ALOGE("%s: Unable to invoke callback v1.0", __func__);
-    }
-}
-
-void Gnss::reportLocation(const V2_0::GnssLocation& location) const {
-    std::unique_lock<std::mutex> lock(mMutex);
-    if (sGnssCallback_2_1 != nullptr) {
-        auto ret = sGnssCallback_2_1->gnssLocationCb_2_0(location);
-        if (!ret.isOk()) {
-            ALOGE("%s: Unable to invoke callback v2.1", __func__);
-        }
-        return;
-    }
-    if (sGnssCallback_2_0 == nullptr) {
-        ALOGE("%s: No non-null callback", __func__);
-        return;
-    }
-    auto ret = sGnssCallback_2_0->gnssLocationCb_2_0(location);
-    if (!ret.isOk()) {
-        ALOGE("%s: Unable to invoke callback v2.0", __func__);
-    }
-}
-
-}  // namespace implementation
-}  // namespace V2_1
-}  // namespace gnss
-}  // namespace hardware
-}  // namespace android
diff --git a/gnss/2.1/default/Gnss.h b/gnss/2.1/default/Gnss.h
deleted file mode 100644
index bd5e6e8..0000000
--- a/gnss/2.1/default/Gnss.h
+++ /dev/null
@@ -1,118 +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.
- */
-
-#pragma once
-
-#include <android/hardware/gnss/2.1/IGnss.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-#include <atomic>
-#include <mutex>
-#include <thread>
-#include "GnssAntennaInfo.h"
-#include "GnssConfiguration.h"
-
-namespace android {
-namespace hardware {
-namespace gnss {
-namespace V2_1 {
-
-using GnssSvInfo = IGnssCallback::GnssSvInfo;
-
-namespace implementation {
-
-struct Gnss : public IGnss {
-    Gnss();
-    ~Gnss();
-    // Methods from V1_0::IGnss follow.
-    Return<bool> setCallback(const sp<V1_0::IGnssCallback>& callback) override;
-    Return<bool> start() override;
-    Return<bool> stop() override;
-    Return<void> cleanup() override;
-    Return<bool> injectTime(int64_t timeMs, int64_t timeReferenceMs,
-                            int32_t uncertaintyMs) override;
-    Return<bool> injectLocation(double latitudeDegrees, double longitudeDegrees,
-                                float accuracyMeters) override;
-    Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override;
-    Return<bool> setPositionMode(V1_0::IGnss::GnssPositionMode mode,
-                                 V1_0::IGnss::GnssPositionRecurrence recurrence,
-                                 uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
-                                 uint32_t preferredTimeMs) override;
-    Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override;
-    Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override;
-    Return<sp<V1_0::IAGnss>> getExtensionAGnss() override;
-    Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override;
-    Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override;
-    Return<sp<V1_0::IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override;
-    Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override;
-    Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override;
-    Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override;
-    Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override;
-
-    // Methods from V1_1::IGnss follow.
-    Return<bool> setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) override;
-    Return<bool> setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
-                                     V1_0::IGnss::GnssPositionRecurrence recurrence,
-                                     uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
-                                     uint32_t preferredTimeMs, bool lowPowerMode) override;
-    Return<sp<V1_1::IGnssConfiguration>> getExtensionGnssConfiguration_1_1() override;
-    Return<sp<V1_1::IGnssMeasurement>> getExtensionGnssMeasurement_1_1() override;
-    Return<bool> injectBestLocation(const V1_0::GnssLocation& location) override;
-
-    // Methods from V2_0::IGnss follow.
-    Return<bool> setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) override;
-    Return<sp<V2_0::IGnssConfiguration>> getExtensionGnssConfiguration_2_0() override;
-    Return<sp<V2_0::IGnssDebug>> getExtensionGnssDebug_2_0() override;
-    Return<sp<V2_0::IAGnss>> getExtensionAGnss_2_0() override;
-    Return<sp<V2_0::IAGnssRil>> getExtensionAGnssRil_2_0() override;
-    Return<sp<V2_0::IGnssMeasurement>> getExtensionGnssMeasurement_2_0() override;
-    Return<sp<measurement_corrections::V1_0::IMeasurementCorrections>>
-    getExtensionMeasurementCorrections() override;
-    Return<sp<visibility_control::V1_0::IGnssVisibilityControl>> getExtensionVisibilityControl()
-            override;
-    Return<sp<V2_0::IGnssBatching>> getExtensionGnssBatching_2_0() override;
-    Return<bool> injectBestLocation_2_0(const V2_0::GnssLocation& location) override;
-
-    // Methods from V2_1::IGnss follow.
-    Return<bool> setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) override;
-    Return<sp<V2_1::IGnssMeasurement>> getExtensionGnssMeasurement_2_1() override;
-    Return<sp<V2_1::IGnssConfiguration>> getExtensionGnssConfiguration_2_1() override;
-    Return<sp<measurement_corrections::V1_1::IMeasurementCorrections>>
-    getExtensionMeasurementCorrections_1_1() override;
-    Return<sp<V2_1::IGnssAntennaInfo>> getExtensionGnssAntennaInfo() override;
-
-  private:
-    void reportLocation(const V2_0::GnssLocation&) const;
-    void reportLocation(const V1_0::GnssLocation&) const;
-    void reportSvStatus(const hidl_vec<GnssSvInfo>&) const;
-
-    static sp<V2_1::IGnssCallback> sGnssCallback_2_1;
-    static sp<V2_0::IGnssCallback> sGnssCallback_2_0;
-    static sp<V1_1::IGnssCallback> sGnssCallback_1_1;
-    static sp<V1_0::IGnssCallback> sGnssCallback_1_0;
-    std::atomic<long> mMinIntervalMs;
-    sp<GnssConfiguration> mGnssConfiguration;
-    std::atomic<bool> mIsActive;
-    std::thread mThread;
-    mutable std::mutex mMutex;
-    hidl_vec<GnssSvInfo> filterBlacklistedSatellitesV2_1(hidl_vec<GnssSvInfo> gnssSvInfoList);
-};
-
-}  // namespace implementation
-}  // namespace V2_1
-}  // namespace gnss
-}  // namespace hardware
-}  // namespace android
diff --git a/gnss/2.1/default/service.cpp b/gnss/2.1/default/service.cpp
index 5e004d5..4f282cf 100644
--- a/gnss/2.1/default/service.cpp
+++ b/gnss/2.1/default/service.cpp
@@ -18,17 +18,17 @@
 
 #include <hidl/HidlSupport.h>
 #include <hidl/HidlTransportSupport.h>
-#include "Gnss.h"
+#include "v2_1/GnssTemplate.h"
 
 using ::android::OK;
 using ::android::sp;
 using ::android::hardware::configureRpcThreadpool;
 using ::android::hardware::joinRpcThreadpool;
+using ::android::hardware::gnss::common::implementation::GnssTemplate;
 using ::android::hardware::gnss::V2_1::IGnss;
-using ::android::hardware::gnss::V2_1::implementation::Gnss;
 
 int main(int /* argc */, char* /* argv */[]) {
-    sp<IGnss> gnss = new Gnss();
+    sp<IGnss> gnss = new GnssTemplate<IGnss>();
     configureRpcThreadpool(1, true /* will join */);
     if (gnss->registerAsService() != OK) {
         ALOGE("Could not register gnss 2.1 service.");
diff --git a/gnss/2.1/vts/functional/Android.bp b/gnss/2.1/vts/functional/Android.bp
index b3051d4..175bc75 100644
--- a/gnss/2.1/vts/functional/Android.bp
+++ b/gnss/2.1/vts/functional/Android.bp
@@ -18,7 +18,6 @@
     name: "VtsHalGnssV2_1TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
-        "gnss_hal_test.cpp",
         "gnss_hal_test_cases.cpp",
         "VtsHalGnssV2_1TargetTest.cpp",
     ],
diff --git a/gnss/2.1/vts/functional/gnss_hal_test.cpp b/gnss/2.1/vts/functional/gnss_hal_test.cpp
deleted file mode 100644
index da7a62b..0000000
--- a/gnss/2.1/vts/functional/gnss_hal_test.cpp
+++ /dev/null
@@ -1,278 +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 "GnssHalTest"
-
-#include <gnss_hal_test.h>
-#include <chrono>
-#include "Utils.h"
-
-#include <gtest/gtest.h>
-
-using ::android::hardware::gnss::common::Utils;
-
-// Implementations for the main test class for GNSS HAL
-void GnssHalTest::SetUp() {
-    gnss_hal_ = IGnss::getService(GetParam());
-    ASSERT_NE(gnss_hal_, nullptr);
-
-    SetUpGnssCallback();
-}
-
-void GnssHalTest::TearDown() {
-    if (gnss_hal_ != nullptr) {
-        gnss_hal_->cleanup();
-        gnss_hal_ = nullptr;
-    }
-
-    // Set to nullptr to destruct the callback event queues and warn of any unprocessed events.
-    gnss_cb_ = nullptr;
-}
-
-void GnssHalTest::SetUpGnssCallback() {
-    gnss_cb_ = new GnssCallback();
-    ASSERT_NE(gnss_cb_, nullptr);
-
-    auto result = gnss_hal_->setCallback_2_1(gnss_cb_);
-    if (!result.isOk()) {
-        ALOGE("result of failed setCallback %s", result.description().c_str());
-    }
-
-    ASSERT_TRUE(result.isOk());
-    ASSERT_TRUE(result);
-
-    /*
-     * All capabilities, name and systemInfo callbacks should trigger
-     */
-    EXPECT_TRUE(gnss_cb_->capabilities_cbq_.retrieve(gnss_cb_->last_capabilities_, TIMEOUT_SEC));
-    EXPECT_TRUE(gnss_cb_->info_cbq_.retrieve(gnss_cb_->last_info_, TIMEOUT_SEC));
-    EXPECT_TRUE(gnss_cb_->name_cbq_.retrieve(gnss_cb_->last_name_, TIMEOUT_SEC));
-
-    EXPECT_EQ(gnss_cb_->capabilities_cbq_.calledCount(), 1);
-    EXPECT_EQ(gnss_cb_->info_cbq_.calledCount(), 1);
-    EXPECT_EQ(gnss_cb_->name_cbq_.calledCount(), 1);
-}
-
-void GnssHalTest::StopAndClearLocations() {
-    const auto result = gnss_hal_->stop();
-
-    EXPECT_TRUE(result.isOk());
-    EXPECT_TRUE(result);
-
-    /*
-     * Clear notify/waiting counter, allowing up till the timeout after
-     * the last reply for final startup messages to arrive (esp. system
-     * info.)
-     */
-    while (gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, TIMEOUT_SEC)) {
-    }
-    gnss_cb_->location_cbq_.reset();
-}
-
-void GnssHalTest::SetPositionMode(const int min_interval_msec, const bool low_power_mode) {
-    const int kPreferredAccuracy = 0;  // Ideally perfect (matches GnssLocationProvider)
-    const int kPreferredTimeMsec = 0;  // Ideally immediate
-
-    const auto result = gnss_hal_->setPositionMode_1_1(
-            IGnss::GnssPositionMode::MS_BASED, IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC,
-            min_interval_msec, kPreferredAccuracy, kPreferredTimeMsec, low_power_mode);
-
-    ASSERT_TRUE(result.isOk());
-    EXPECT_TRUE(result);
-}
-
-bool GnssHalTest::StartAndCheckFirstLocation() {
-    const auto result = gnss_hal_->start();
-
-    EXPECT_TRUE(result.isOk());
-    EXPECT_TRUE(result);
-
-    /*
-     * GnssLocationProvider support of AGPS SUPL & XtraDownloader is not available in VTS,
-     * so allow time to demodulate ephemeris over the air.
-     */
-    const int kFirstGnssLocationTimeoutSeconds = 75;
-
-    EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_,
-                                                 kFirstGnssLocationTimeoutSeconds));
-    int locationCalledCount = gnss_cb_->location_cbq_.calledCount();
-    EXPECT_EQ(locationCalledCount, 1);
-
-    if (locationCalledCount > 0) {
-        // don't require speed on first fix
-        CheckLocation(gnss_cb_->last_location_, false);
-        return true;
-    }
-    return false;
-}
-
-void GnssHalTest::CheckLocation(const GnssLocation_2_0& location, bool check_speed) {
-    const bool check_more_accuracies =
-            (gnss_cb_->info_cbq_.calledCount() > 0 && gnss_cb_->last_info_.yearOfHw >= 2017);
-
-    Utils::checkLocation(location.v1_0, check_speed, check_more_accuracies);
-}
-
-void GnssHalTest::StartAndCheckLocations(int count) {
-    const int kMinIntervalMsec = 500;
-    const int kLocationTimeoutSubsequentSec = 2;
-    const bool kLowPowerMode = false;
-
-    SetPositionMode(kMinIntervalMsec, kLowPowerMode);
-
-    EXPECT_TRUE(StartAndCheckFirstLocation());
-
-    for (int i = 1; i < count; i++) {
-        EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_,
-                                                     kLocationTimeoutSubsequentSec));
-        int locationCalledCount = gnss_cb_->location_cbq_.calledCount();
-        EXPECT_EQ(locationCalledCount, i + 1);
-        // Don't cause confusion by checking details if no location yet
-        if (locationCalledCount > 0) {
-            // Should be more than 1 location by now, but if not, still don't check first fix speed
-            CheckLocation(gnss_cb_->last_location_, locationCalledCount > 1);
-        }
-    }
-}
-
-GnssConstellationType GnssHalTest::startLocationAndGetNonGpsConstellation(
-        const int locations_to_await, const int gnss_sv_info_list_timeout) {
-    gnss_cb_->location_cbq_.reset();
-    StartAndCheckLocations(locations_to_await);
-    const int location_called_count = gnss_cb_->location_cbq_.calledCount();
-
-    // Tolerate 1 less sv status to handle edge cases in reporting.
-    int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
-    EXPECT_GE(sv_info_list_cbq_size + 1, locations_to_await);
-    ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
-          sv_info_list_cbq_size, locations_to_await, location_called_count);
-
-    // Find first non-GPS constellation to blacklist
-    GnssConstellationType constellation_to_blacklist = GnssConstellationType::UNKNOWN;
-    for (int i = 0; i < sv_info_list_cbq_size; ++i) {
-        hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
-        gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, gnss_sv_info_list_timeout);
-        for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
-            const auto& gnss_sv = sv_info_vec[iSv];
-            if ((gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX) &&
-                (gnss_sv.v2_0.constellation != GnssConstellationType::UNKNOWN) &&
-                (gnss_sv.v2_0.constellation != GnssConstellationType::GPS)) {
-                // found a non-GPS constellation
-                constellation_to_blacklist = gnss_sv.v2_0.constellation;
-                break;
-            }
-        }
-        if (constellation_to_blacklist != GnssConstellationType::UNKNOWN) {
-            break;
-        }
-    }
-
-    if (constellation_to_blacklist == GnssConstellationType::UNKNOWN) {
-        ALOGI("No non-GPS constellations found, constellation blacklist test less effective.");
-        // Proceed functionally to blacklist something.
-        constellation_to_blacklist = GnssConstellationType::GLONASS;
-    }
-
-    return constellation_to_blacklist;
-}
-
-GnssHalTest::GnssCallback::GnssCallback()
-    : info_cbq_("system_info"),
-      name_cbq_("name"),
-      capabilities_cbq_("capabilities"),
-      location_cbq_("location"),
-      sv_info_list_cbq_("sv_info") {}
-
-Return<void> GnssHalTest::GnssCallback::gnssSetSystemInfoCb(
-        const IGnssCallback_1_0::GnssSystemInfo& info) {
-    ALOGI("Info received, year %d", info.yearOfHw);
-    info_cbq_.store(info);
-    return Void();
-}
-
-Return<void> GnssHalTest::GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) {
-    ALOGI("Capabilities received %d", capabilities);
-    capabilities_cbq_.store(capabilities);
-    return Void();
-}
-
-Return<void> GnssHalTest::GnssCallback::gnssSetCapabilitiesCb_2_0(uint32_t capabilities) {
-    ALOGI("Capabilities (v2.0) received %d", capabilities);
-    capabilities_cbq_.store(capabilities);
-    return Void();
-}
-
-Return<void> GnssHalTest::GnssCallback::gnssSetCapabilitiesCb_2_1(uint32_t capabilities) {
-    ALOGI("Capabilities (v2.1) received %d", capabilities);
-    capabilities_cbq_.store(capabilities);
-    return Void();
-}
-
-Return<void> GnssHalTest::GnssCallback::gnssNameCb(const android::hardware::hidl_string& name) {
-    ALOGI("Name received: %s", name.c_str());
-    name_cbq_.store(name);
-    return Void();
-}
-
-Return<void> GnssHalTest::GnssCallback::gnssLocationCb(const GnssLocation_1_0& location) {
-    ALOGI("Location received");
-    GnssLocation_2_0 location_v2_0;
-    location_v2_0.v1_0 = location;
-    return gnssLocationCbImpl(location_v2_0);
-}
-
-Return<void> GnssHalTest::GnssCallback::gnssLocationCb_2_0(const GnssLocation_2_0& location) {
-    ALOGI("Location (v2.0) received");
-    return gnssLocationCbImpl(location);
-}
-
-Return<void> GnssHalTest::GnssCallback::gnssLocationCbImpl(const GnssLocation_2_0& location) {
-    location_cbq_.store(location);
-    return Void();
-}
-
-Return<void> GnssHalTest::GnssCallback::gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus&) {
-    ALOGI("gnssSvStatusCb");
-    return Void();
-}
-
-Return<void> GnssHalTest::GnssCallback::gnssSvStatusCb_2_1(
-        const hidl_vec<IGnssCallback_2_1::GnssSvInfo>& svInfoList) {
-    ALOGI("gnssSvStatusCb_2_1. Size = %d", (int)svInfoList.size());
-    sv_info_list_cbq_.store(svInfoList);
-    return Void();
-}
-
-Return<void> GnssHalTest::GnssMeasurementCallback::gnssMeasurementCb_2_1(
-        const IGnssMeasurementCallback_2_1::GnssData& data) {
-    ALOGD("GnssMeasurement v2.1 received. Size = %d", (int)data.measurements.size());
-    measurement_cbq_.store(data);
-    return Void();
-}
-
-Return<void> GnssHalTest::GnssMeasurementCorrectionsCallback::setCapabilitiesCb(
-        uint32_t capabilities) {
-    ALOGI("GnssMeasurementCorrectionsCallback capabilities received %d", capabilities);
-    capabilities_cbq_.store(capabilities);
-    return Void();
-}
-
-Return<void> GnssHalTest::GnssAntennaInfoCallback::gnssAntennaInfoCb(
-        const hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos) {
-    ALOGD("GnssAntennaInfo v2.1 received. Size = %d", (int)gnssAntennaInfos.size());
-    antenna_info_cbq_.store(gnssAntennaInfos);
-    return Void();
-}
\ No newline at end of file
diff --git a/gnss/2.1/vts/functional/gnss_hal_test.h b/gnss/2.1/vts/functional/gnss_hal_test.h
index 9e6e162..c28e248 100644
--- a/gnss/2.1/vts/functional/gnss_hal_test.h
+++ b/gnss/2.1/vts/functional/gnss_hal_test.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,221 +14,12 @@
  * limitations under the License.
  */
 
-#ifndef GNSS_HAL_TEST_H_
-#define GNSS_HAL_TEST_H_
+#pragma once
 
 #include <android/hardware/gnss/2.1/IGnss.h>
-#include "GnssCallbackEventQueue.h"
+#include "v2_1/gnss_hal_test_template.h"
 
-#include <gtest/gtest.h>
-
-using android::hardware::hidl_vec;
-using android::hardware::Return;
-using android::hardware::Void;
-
-using android::hardware::gnss::common::GnssCallbackEventQueue;
-using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback;
-using android::hardware::gnss::V1_0::GnssLocationFlags;
-using android::hardware::gnss::V2_0::GnssConstellationType;
 using android::hardware::gnss::V2_1::IGnss;
-using android::hardware::gnss::V2_1::IGnssAntennaInfo;
-using android::hardware::gnss::V2_1::IGnssAntennaInfoCallback;
-
-using GnssLocation_1_0 = android::hardware::gnss::V1_0::GnssLocation;
-using GnssLocation_2_0 = android::hardware::gnss::V2_0::GnssLocation;
-
-using IGnssCallback_1_0 = android::hardware::gnss::V1_0::IGnssCallback;
-using IGnssCallback_2_0 = android::hardware::gnss::V2_0::IGnssCallback;
-using IGnssCallback_2_1 = android::hardware::gnss::V2_1::IGnssCallback;
-
-using IGnssMeasurementCallback_1_0 = android::hardware::gnss::V1_0::IGnssMeasurementCallback;
-using IGnssMeasurementCallback_1_1 = android::hardware::gnss::V1_1::IGnssMeasurementCallback;
-using IGnssMeasurementCallback_2_0 = android::hardware::gnss::V2_0::IGnssMeasurementCallback;
-using IGnssMeasurementCallback_2_1 = android::hardware::gnss::V2_1::IGnssMeasurementCallback;
-
-using android::sp;
-
-#define TIMEOUT_SEC 2  // for basic commands/responses
 
 // The main test class for GNSS HAL.
-class GnssHalTest : public testing::TestWithParam<std::string> {
-  public:
-    virtual void SetUp() override;
-
-    virtual void TearDown() override;
-
-    /* Callback class for data & Event. */
-    class GnssCallback : public IGnssCallback_2_1 {
-      public:
-        IGnssCallback_1_0::GnssSystemInfo last_info_;
-        android::hardware::hidl_string last_name_;
-        uint32_t last_capabilities_;
-        GnssLocation_2_0 last_location_;
-
-        GnssCallbackEventQueue<IGnssCallback_1_0::GnssSystemInfo> info_cbq_;
-        GnssCallbackEventQueue<android::hardware::hidl_string> name_cbq_;
-        GnssCallbackEventQueue<uint32_t> capabilities_cbq_;
-        GnssCallbackEventQueue<GnssLocation_2_0> location_cbq_;
-        GnssCallbackEventQueue<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list_cbq_;
-
-        GnssCallback();
-        virtual ~GnssCallback() = default;
-
-        // Dummy callback handlers
-        Return<void> gnssStatusCb(const IGnssCallback_1_0::GnssStatusValue /* status */) override {
-            return Void();
-        }
-        Return<void> gnssNmeaCb(int64_t /* timestamp */,
-                                const android::hardware::hidl_string& /* nmea */) override {
-            return Void();
-        }
-        Return<void> gnssAcquireWakelockCb() override { return Void(); }
-        Return<void> gnssReleaseWakelockCb() override { return Void(); }
-        Return<void> gnssRequestLocationCb(bool /* independentFromGnss */) override {
-            return Void();
-        }
-        Return<void> gnssRequestTimeCb() override { return Void(); }
-        // Actual (test) callback handlers
-        Return<void> gnssNameCb(const android::hardware::hidl_string& name) override;
-        Return<void> gnssLocationCb(const GnssLocation_1_0& location) override;
-        Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
-        Return<void> gnssSetSystemInfoCb(const IGnssCallback_1_0::GnssSystemInfo& info) override;
-        Return<void> gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus& svStatus) override;
-
-        // New in v2.0
-        Return<void> gnssLocationCb_2_0(const GnssLocation_2_0& location) override;
-        Return<void> gnssRequestLocationCb_2_0(bool /* independentFromGnss */,
-                                               bool /* isUserEmergency */) override {
-            return Void();
-        }
-        Return<void> gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override;
-        Return<void> gnssSvStatusCb_2_0(const hidl_vec<IGnssCallback_2_0::GnssSvInfo>&) override {
-            return Void();
-        }
-
-        // New in v2.1
-        Return<void> gnssSvStatusCb_2_1(
-                const hidl_vec<IGnssCallback_2_1::GnssSvInfo>& svInfoList) override;
-        Return<void> gnssSetCapabilitiesCb_2_1(uint32_t capabilities) override;
-
-      private:
-        Return<void> gnssLocationCbImpl(const GnssLocation_2_0& location);
-    };
-
-    /* Callback class for GnssMeasurement. */
-    class GnssMeasurementCallback : public IGnssMeasurementCallback_2_1 {
-      public:
-        GnssCallbackEventQueue<IGnssMeasurementCallback_2_1::GnssData> measurement_cbq_;
-
-        GnssMeasurementCallback() : measurement_cbq_("measurement"){};
-        virtual ~GnssMeasurementCallback() = default;
-
-        // Methods from V1_0::IGnssMeasurementCallback follow.
-        Return<void> GnssMeasurementCb(const IGnssMeasurementCallback_1_0::GnssData&) override {
-            return Void();
-        }
-
-        // Methods from V1_1::IGnssMeasurementCallback follow.
-        Return<void> gnssMeasurementCb(const IGnssMeasurementCallback_1_1::GnssData&) override {
-            return Void();
-        }
-
-        // Methods from V2_0::IGnssMeasurementCallback follow.
-        Return<void> gnssMeasurementCb_2_0(const IGnssMeasurementCallback_2_0::GnssData&) override {
-            return Void();
-        }
-
-        // Methods from V2_1::IGnssMeasurementCallback follow.
-        Return<void> gnssMeasurementCb_2_1(const IGnssMeasurementCallback_2_1::GnssData&) override;
-    };
-
-    /* Callback class for GnssMeasurementCorrections. */
-    class GnssMeasurementCorrectionsCallback : public IMeasurementCorrectionsCallback {
-      public:
-        uint32_t last_capabilities_;
-        GnssCallbackEventQueue<uint32_t> capabilities_cbq_;
-
-        GnssMeasurementCorrectionsCallback() : capabilities_cbq_("capabilities"){};
-        virtual ~GnssMeasurementCorrectionsCallback() = default;
-
-        // Methods from V1_0::IMeasurementCorrectionsCallback follow.
-        Return<void> setCapabilitiesCb(uint32_t capabilities) override;
-    };
-
-    /* Callback class for GnssAntennaInfo. */
-    class GnssAntennaInfoCallback : public IGnssAntennaInfoCallback {
-      public:
-        GnssCallbackEventQueue<hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>>
-                antenna_info_cbq_;
-
-        GnssAntennaInfoCallback() : antenna_info_cbq_("info"){};
-        virtual ~GnssAntennaInfoCallback() = default;
-
-        // Methods from V2_1::GnssAntennaInfoCallback follow.
-        Return<void> gnssAntennaInfoCb(
-                const hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos);
-    };
-
-    /*
-     * SetUpGnssCallback:
-     *   Set GnssCallback and verify the result.
-     */
-    void SetUpGnssCallback();
-
-    /*
-     * StartAndCheckFirstLocation:
-     *   Helper function to start location, and check the first one.
-     *
-     *   <p> Note this leaves the Location request active, to enable Stop call vs. other call
-     *   reordering tests.
-     *
-     * returns  true if a location was successfully generated
-     */
-    bool StartAndCheckFirstLocation();
-
-    /*
-     * CheckLocation:
-     *   Helper function to vet Location fields
-     *
-     *   check_speed: true if speed related fields are also verified.
-     */
-    void CheckLocation(const GnssLocation_2_0& location, const bool check_speed);
-
-    /*
-     * StartAndCheckLocations:
-     *   Helper function to collect, and check a number of
-     *   normal ~1Hz locations.
-     *
-     *   Note this leaves the Location request active, to enable Stop call vs. other call
-     *   reordering tests.
-     */
-    void StartAndCheckLocations(int count);
-
-    /*
-     * StopAndClearLocations:
-     * Helper function to stop locations, and clear any remaining notifications
-     */
-    void StopAndClearLocations();
-
-    /*
-     * SetPositionMode:
-     * Helper function to set positioning mode and verify output
-     */
-    void SetPositionMode(const int min_interval_msec, const bool low_power_mode);
-
-    /*
-     * startLocationAndGetNonGpsConstellation:
-     * 1. Start location
-     * 2. Find and return first non-GPS constellation
-     *
-     * Note that location is not stopped in this method. The client should call
-     * StopAndClearLocations() after the call.
-     */
-    GnssConstellationType startLocationAndGetNonGpsConstellation(
-            const int locations_to_await, const int gnss_sv_info_list_timeout);
-
-    sp<IGnss> gnss_hal_;        // GNSS HAL to call into
-    sp<GnssCallback> gnss_cb_;  // Primary callback interface
-};
-
-#endif  // GNSS_HAL_TEST_H_
+class GnssHalTest : public GnssHalTestTemplate<IGnss> {};
diff --git a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
index 33feb5e..a3d2956 100644
--- a/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.1/vts/functional/gnss_hal_test_cases.cpp
@@ -247,8 +247,10 @@
     ALOGD("Observed %d GnssSvStatus, while awaiting one location (%d received)",
           sv_info_list_cbq_size, location_called_count);
 
-    hidl_vec<IGnssCallback_2_1::GnssSvInfo> last_sv_info_list;
-    ASSERT_TRUE(gnss_cb_->sv_info_list_cbq_.retrieve(last_sv_info_list, 1));
+    // Get the last sv_info_list
+    std::list<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_vec_list;
+    gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec_list, sv_info_list_cbq_size, 1);
+    hidl_vec<IGnssCallback_2_1::GnssSvInfo> last_sv_info_list = sv_info_vec_list.back();
 
     bool nonZeroCn0Found = false;
     for (auto sv_info : last_sv_info_list) {
@@ -673,4 +675,4 @@
             iMeasurementCorrections->setCorrections_1_1(Utils::getMockMeasurementCorrections_1_1());
     ASSERT_TRUE(result.isOk());
     EXPECT_TRUE(result);
-}
\ No newline at end of file
+}
diff --git a/gnss/3.0/Android.bp b/gnss/3.0/Android.bp
new file mode 100644
index 0000000..dada17c
--- /dev/null
+++ b/gnss/3.0/Android.bp
@@ -0,0 +1,22 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.gnss@3.0",
+    root: "android.hardware",
+    srcs: [
+        "IGnss.hal",
+        "IGnssPsds.hal",
+        "IGnssPsdsCallback.hal",
+    ],
+    interfaces: [
+        "android.hardware.gnss.measurement_corrections@1.0",
+        "android.hardware.gnss.measurement_corrections@1.1",
+        "android.hardware.gnss.visibility_control@1.0",
+        "android.hardware.gnss@1.0",
+        "android.hardware.gnss@1.1",
+        "android.hardware.gnss@2.0",
+        "android.hardware.gnss@2.1",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/gnss/3.0/IGnss.hal
similarity index 60%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to gnss/3.0/IGnss.hal
index 7edec47..18e5a9d 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/gnss/3.0/IGnss.hal
@@ -14,13 +14,19 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+package android.hardware.gnss@3.0;
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+import @2.1::IGnss;
+import IGnssPsds;
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+/**
+ * Represents the standard GNSS (Global Navigation Satellite System) interface.
+ */
+interface IGnss extends @2.1::IGnss {
+    /**
+     * This method returns the IGnssPsds interface.
+     *
+     * @return psdsIface Handle to the IGnssPsds interface.
+     */
+    getExtensionPsds() generates (IGnssPsds psdsIface);
+};
diff --git a/gnss/3.0/IGnssPsds.hal b/gnss/3.0/IGnssPsds.hal
new file mode 100644
index 0000000..5004570
--- /dev/null
+++ b/gnss/3.0/IGnssPsds.hal
@@ -0,0 +1,48 @@
+/*
+ * 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 android.hardware.gnss@3.0;
+
+import @1.0::IGnssXtra;
+import IGnssPsdsCallback;
+
+/**
+ * This interface is used by the GNSS HAL to request the framework to download Predicted Satellite
+ * Data Service data.
+ */
+interface IGnssPsds extends @1.0::IGnssXtra {
+    /**
+     * Opens the PSDS interface and provides the callback routines to the implementation of this
+     * interface.
+     *
+     * @param callback Handle to the IGnssPsdsCallback interface.
+     *
+     * @return success True if the operation is successful.
+     */
+    setCallback_3_0(IGnssPsdsCallback callback) generates (bool success);
+
+    /**
+     * Inject the downloaded PSDS data into the GNSS receiver.
+     *
+     * @param psdsType Type of PSDS as defined in IGnssPsdsCallback.hal
+     * @param psdsData GNSS PSDS data. Framework must not parse the data since the data format is
+     *                 opaque to framework.
+     *
+     * @return success True if the operation is successful.
+     */
+    injectPsdsData_3_0(int32_t psdsType, string psdsData) generates (bool success);
+};
+
diff --git a/gnss/3.0/IGnssPsdsCallback.hal b/gnss/3.0/IGnssPsdsCallback.hal
new file mode 100644
index 0000000..d91385f
--- /dev/null
+++ b/gnss/3.0/IGnssPsdsCallback.hal
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.gnss@3.0;
+
+import @1.0::IGnssXtraCallback;
+
+/**
+ * This interface is used by the GNSS HAL to request download data from Predicted Satellite Data
+ * Service (PSDS).
+ */
+interface IGnssPsdsCallback extends @1.0::IGnssXtraCallback {
+   /**
+    * Callback to request the client to download PSDS data. The client should
+    * download PSDS data and inject it by calling injectPsdsData().
+    *
+    * psdsType represents the type of PSDS data requested.
+    * - Value 1 represents the Long-Term type PSDS data, which lasts for many hours to several days
+    *   and often provides satellite orbit and clock accuracy of 2 - 20 meters.
+    * - Value 2 represents the Normal type PSDS data, which is similar to broadcast ephemeris in
+    *   longevity - lasting for hours and providings satellite orbit and clock accuracy of 1 - 2
+    *   meters.
+    * - Value 3 represents the Real-Time type PSDS data, which lasts for minutes and provides brief
+    *   satellite status information such as temporary malfunction, but does not include satellite
+    *   orbit or clock information.
+    */
+   downloadRequestCb_3_0(int32_t psdsType);
+};
diff --git a/gnss/3.0/default/Android.bp b/gnss/3.0/default/Android.bp
new file mode 100644
index 0000000..2b33b32
--- /dev/null
+++ b/gnss/3.0/default/Android.bp
@@ -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.
+ */
+
+cc_binary {
+    name: "android.hardware.gnss@3.0-service",
+    init_rc: ["android.hardware.gnss@3.0-service.rc"],
+    relative_install_path: "hw",
+    vendor: true,
+    vintf_fragments: ["android.hardware.gnss@3.0-service.xml"],
+    srcs: [
+        "Gnss.cpp",
+        "GnssPsds.cpp",
+        "service.cpp",
+    ],
+    shared_libs: [
+        "libhidlbase",
+        "libutils",
+        "liblog",
+        "android.hardware.gnss@1.0",
+        "android.hardware.gnss@1.1",
+        "android.hardware.gnss@2.0",
+        "android.hardware.gnss@2.1",
+        "android.hardware.gnss@3.0",
+        "android.hardware.gnss.measurement_corrections@1.1",
+        "android.hardware.gnss.measurement_corrections@1.0",
+    ],
+    static_libs: [
+        "android.hardware.gnss@common-default-lib",
+    ],
+}
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/gnss/3.0/default/Gnss.cpp
similarity index 61%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to gnss/3.0/default/Gnss.cpp
index 7edec47..5f2ca4f 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/gnss/3.0/default/Gnss.cpp
@@ -14,13 +14,19 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#define LOG_TAG "Gnss"
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+#include "Gnss.h"
+#include <log/log.h>
+#include "GnssPsds.h"
+#include "Utils.h"
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
+namespace android::hardware::gnss::V3_0::implementation {
+
+// Methods from V3_0::IGnss follow.
+Return<sp<V3_0::IGnssPsds>> Gnss::getExtensionPsds() {
+    ALOGD("Gnss::getExtensionPsds");
+    return new GnssPsds();
 }
+
+}  // namespace android::hardware::gnss::V3_0::implementation
diff --git a/gnss/3.0/default/Gnss.h b/gnss/3.0/default/Gnss.h
new file mode 100644
index 0000000..7ae562a
--- /dev/null
+++ b/gnss/3.0/default/Gnss.h
@@ -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.
+ */
+
+#pragma once
+
+#include <android/hardware/gnss/3.0/IGnss.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <atomic>
+#include <mutex>
+#include <thread>
+#include "v2_1/GnssTemplate.h"
+
+namespace android::hardware::gnss::V3_0::implementation {
+
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::gnss::common::implementation::GnssTemplate;
+
+struct Gnss : public GnssTemplate<IGnss> {
+    Gnss(){};
+    ~Gnss(){};
+
+    // Methods from V3_0::IGnss follow.
+    Return<sp<V3_0::IGnssPsds>> getExtensionPsds() override;
+};
+
+}  // namespace android::hardware::gnss::V3_0::implementation
diff --git a/gnss/3.0/default/GnssPsds.cpp b/gnss/3.0/default/GnssPsds.cpp
new file mode 100644
index 0000000..44e096e
--- /dev/null
+++ b/gnss/3.0/default/GnssPsds.cpp
@@ -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.
+ */
+
+#define LOG_TAG "GnssPsds"
+
+#include "GnssPsds.h"
+
+#include <log/log.h>
+
+namespace android::hardware::gnss::V3_0::implementation {
+
+sp<V3_0::IGnssPsdsCallback> GnssPsds::sCallback_3_0 = nullptr;
+
+// Methods from V1_0::IGnssXtra follow.
+Return<bool> GnssPsds::setCallback(const sp<V1_0::IGnssXtraCallback>&) {
+    // TODO implement
+    return bool{};
+}
+
+Return<bool> GnssPsds::injectXtraData(const hidl_string&) {
+    // TODO implement
+    return bool{};
+}
+
+// Methods from V3_0::IGnssPsds follow.
+Return<bool> GnssPsds::setCallback_3_0(const sp<V3_0::IGnssPsdsCallback>& callback) {
+    ALOGD("setCallback_3_0");
+    std::unique_lock<std::mutex> lock(mMutex);
+    sCallback_3_0 = callback;
+    return true;
+}
+
+Return<bool> GnssPsds::injectPsdsData_3_0(int32_t psdsType, const hidl_string& psdsData) {
+    ALOGD("injectPsdsData_3_0. psdsType: %d, psdsData: %s", psdsType, psdsData.c_str());
+    return true;
+}
+}  // namespace android::hardware::gnss::V3_0::implementation
diff --git a/gnss/3.0/default/GnssPsds.h b/gnss/3.0/default/GnssPsds.h
new file mode 100644
index 0000000..4053bf1
--- /dev/null
+++ b/gnss/3.0/default/GnssPsds.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/hardware/gnss/3.0/IGnssPsds.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android::hardware::gnss::V3_0::implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+struct GnssPsds : public V3_0::IGnssPsds {
+    // Methods from V1_0::IGnssXtra follow.
+    Return<bool> setCallback(const sp<V1_0::IGnssXtraCallback>& callback) override;
+    Return<bool> injectXtraData(const hidl_string& xtraData) override;
+
+    // Methods from V3_0::IGnssPsds follow.
+    Return<bool> setCallback_3_0(const sp<V3_0::IGnssPsdsCallback>& callback) override;
+    Return<bool> injectPsdsData_3_0(int32_t psdsType, const hidl_string& psdsData) override;
+
+  private:
+    // Guarded by mMutex
+    static sp<V3_0::IGnssPsdsCallback> sCallback_3_0;
+
+    // Synchronization lock for sCallback_3_0
+    mutable std::mutex mMutex;
+};
+
+}  // namespace android::hardware::gnss::V3_0::implementation
diff --git a/gnss/3.0/default/OWNERS b/gnss/3.0/default/OWNERS
new file mode 100644
index 0000000..b7b4a2e
--- /dev/null
+++ b/gnss/3.0/default/OWNERS
@@ -0,0 +1,4 @@
+gomo@google.com
+smalkos@google.com
+wyattriley@google.com
+yuhany@google.com
diff --git a/gnss/3.0/default/android.hardware.gnss@3.0-service.rc b/gnss/3.0/default/android.hardware.gnss@3.0-service.rc
new file mode 100644
index 0000000..c2bfb91
--- /dev/null
+++ b/gnss/3.0/default/android.hardware.gnss@3.0-service.rc
@@ -0,0 +1,4 @@
+service vendor.gnss-3-0 /vendor/bin/hw/android.hardware.gnss@3.0-service
+    class hal
+    user system
+    group system
diff --git a/gnss/3.0/default/android.hardware.gnss@3.0-service.xml b/gnss/3.0/default/android.hardware.gnss@3.0-service.xml
new file mode 100644
index 0000000..6709e0c
--- /dev/null
+++ b/gnss/3.0/default/android.hardware.gnss@3.0-service.xml
@@ -0,0 +1,13 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.gnss</name>
+        <transport>hwbinder</transport>
+        <version>3.0</version>
+        <version>2.1</version>
+        <version>1.1</version>
+        <interface>
+            <name>IGnss</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/gnss/3.0/default/service.cpp b/gnss/3.0/default/service.cpp
new file mode 100644
index 0000000..87b4580
--- /dev/null
+++ b/gnss/3.0/default/service.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.gnss@3.0-service"
+
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include "Gnss.h"
+
+using ::android::OK;
+using ::android::sp;
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::joinRpcThreadpool;
+using ::android::hardware::gnss::V3_0::IGnss;
+using ::android::hardware::gnss::V3_0::implementation::Gnss;
+
+int main(int /* argc */, char* /* argv */[]) {
+    sp<IGnss> gnss = new Gnss();
+    configureRpcThreadpool(1, true /* will join */);
+    if (gnss->registerAsService() != OK) {
+        ALOGE("Could not register gnss 3.0 service.");
+        return 1;
+    }
+    joinRpcThreadpool();
+
+    ALOGE("Service exited!");
+    return 1;
+}
\ No newline at end of file
diff --git a/gnss/3.0/vts/OWNERS b/gnss/3.0/vts/OWNERS
new file mode 100644
index 0000000..b7b4a2e
--- /dev/null
+++ b/gnss/3.0/vts/OWNERS
@@ -0,0 +1,4 @@
+gomo@google.com
+smalkos@google.com
+wyattriley@google.com
+yuhany@google.com
diff --git a/gnss/3.0/vts/functional/Android.bp b/gnss/3.0/vts/functional/Android.bp
new file mode 100644
index 0000000..584424c
--- /dev/null
+++ b/gnss/3.0/vts/functional/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.
+//
+
+cc_test {
+    name: "VtsHalGnssV3_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "gnss_hal_test_cases.cpp",
+        "VtsHalGnssV3_0TargetTest.cpp",
+    ],
+    static_libs: [
+        "android.hardware.gnss.measurement_corrections@1.0",
+        "android.hardware.gnss.measurement_corrections@1.1",
+        "android.hardware.gnss.visibility_control@1.0",
+        "android.hardware.gnss@1.0",
+        "android.hardware.gnss@1.1",
+        "android.hardware.gnss@2.0",
+        "android.hardware.gnss@2.1",
+        "android.hardware.gnss@3.0",
+        "android.hardware.gnss@common-vts-lib",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
diff --git a/gnss/3.0/vts/functional/VtsHalGnssV3_0TargetTest.cpp b/gnss/3.0/vts/functional/VtsHalGnssV3_0TargetTest.cpp
new file mode 100644
index 0000000..9eca7b0
--- /dev/null
+++ b/gnss/3.0/vts/functional/VtsHalGnssV3_0TargetTest.cpp
@@ -0,0 +1,29 @@
+/*
+ * 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 "VtsHalGnssV3_0TargetTest"
+
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include "gnss_hal_test.h"
+
+using android::hardware::gnss::V3_0::IGnss;
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, GnssHalTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IGnss::descriptor)),
+        android::hardware::PrintInstanceNameToString);
\ No newline at end of file
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/gnss/3.0/vts/functional/gnss_hal_test.h
similarity index 69%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to gnss/3.0/vts/functional/gnss_hal_test.h
index 7edec47..387214e 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/gnss/3.0/vts/functional/gnss_hal_test.h
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#pragma once
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+#include <android/hardware/gnss/3.0/IGnss.h>
+#include "v2_1/gnss_hal_test_template.h"
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+using android::hardware::gnss::V3_0::IGnss;
+
+// The main test class for GNSS HAL.
+class GnssHalTest : public GnssHalTestTemplate<IGnss> {};
\ No newline at end of file
diff --git a/gnss/3.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/3.0/vts/functional/gnss_hal_test_cases.cpp
new file mode 100644
index 0000000..cc5341c
--- /dev/null
+++ b/gnss/3.0/vts/functional/gnss_hal_test_cases.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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 "GnssHalTestCases"
+
+#include <gnss_hal_test.h>
+#include <cmath>
+#include "Utils.h"
+
+#include <gtest/gtest.h>
+
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+
+using android::hardware::gnss::common::Utils;
+
+using android::hardware::gnss::V3_0::IGnssPsds;
+
+/*
+ * SetupTeardownCreateCleanup:
+ * Requests the gnss HAL then calls cleanup
+ *
+ * Empty test fixture to verify basic Setup & Teardown
+ */
+TEST_P(GnssHalTest, SetupTeardownCreateCleanup) {}
+
+/*
+ * TestPsdsExtension:
+ * Gets the PsdsExtension and verifies that it returns a non-null extension.
+ */
+TEST_P(GnssHalTest, TestPsdsExtension) {
+    auto psds = gnss_hal_->getExtensionPsds();
+    ASSERT_TRUE(psds.isOk());
+    sp<IGnssPsds> iPsds = psds;
+    ASSERT_TRUE(iPsds != nullptr);
+}
diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp
index 577f6ae..8d9d4d4 100644
--- a/gnss/common/utils/default/Android.bp
+++ b/gnss/common/utils/default/Android.bp
@@ -24,7 +24,13 @@
         "-Werror",
     ],
     srcs: [
+        "v2_1/GnssAntennaInfo.cpp",
+        "v2_1/GnssConfiguration.cpp",
+        "v2_1/GnssDebug.cpp",
+        "v2_1/GnssMeasurement.cpp",
+        "v2_1/GnssMeasurementCorrections.cpp",
         "Utils.cpp",
+        "NmeaFixInfo.cpp",
     ],
     export_include_dirs: ["include"],
     shared_libs: [
@@ -33,5 +39,7 @@
         "android.hardware.gnss@1.0",
         "android.hardware.gnss@2.0",
         "android.hardware.gnss@2.1",
+        "android.hardware.gnss.measurement_corrections@1.1",
+        "android.hardware.gnss.measurement_corrections@1.0",
     ],
 }
diff --git a/gnss/common/utils/default/NmeaFixInfo.cpp b/gnss/common/utils/default/NmeaFixInfo.cpp
new file mode 100644
index 0000000..43e008b
--- /dev/null
+++ b/gnss/common/utils/default/NmeaFixInfo.cpp
@@ -0,0 +1,266 @@
+/*
+ * 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 "NmeaFixInfo"
+
+#include <Constants.h>
+#include <NmeaFixInfo.h>
+#include <Utils.h>
+#include <log/log.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <utils/SystemClock.h>
+#include <limits>
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+
+NmeaFixInfo::NmeaFixInfo() : hasGMCRecord(false), hasGGARecord(false) {}
+
+float NmeaFixInfo::getAltitudeMeters() const {
+    return altitudeMeters;
+}
+
+float NmeaFixInfo::checkAndConvertToFloat(const std::string& sentence) {
+    if (sentence.empty()) {
+        return std::numeric_limits<float>::quiet_NaN();
+    }
+    return std::stof(sentence);
+}
+
+float NmeaFixInfo::getBearingAccuracyDegrees() const {
+    // Current NMEA doesn't contains beaing accuracy inforamtion
+    return kMockBearingAccuracyDegrees;
+}
+float NmeaFixInfo::getBearingDegrees() const {
+    return bearingDegrees;
+}
+
+float NmeaFixInfo::getHorizontalAccuracyMeters() const {
+    // Current NMEA doesn't contains horizontal accuracy inforamtion
+    return kMockHorizontalAccuracyMeters;
+}
+
+float NmeaFixInfo::getLatDeg() const {
+    return latDeg;
+}
+
+float NmeaFixInfo::getLngDeg() const {
+    return lngDeg;
+}
+
+float NmeaFixInfo::getSpeedAccuracyMetersPerSecond() const {
+    // Current NMEA doesn't contains speed accuracy inforamtion
+    return kMockSpeedAccuracyMetersPerSecond;
+}
+
+float NmeaFixInfo::getSpeedMetersPerSec() const {
+    return speedMetersPerSec;
+}
+
+int64_t NmeaFixInfo::getTimestamp() const {
+    return timestamp;
+}
+
+float NmeaFixInfo::getVerticalAccuracyMeters() const {
+    // Current NMEA doesn't contains vertical accuracy inforamtion
+    return kMockVerticalAccuracyMeters;
+}
+
+int64_t NmeaFixInfo::nmeaPartsToTimestamp(const std::string& timeStr, const std::string& dateStr) {
+    /**
+     * In NMEA format, the full time can only get from the $GPRMC record, see
+     * the following example:
+     * $GPRMC,213204.00,A,3725.371240,N,12205.589239,W,000.0,000.0,290819,,,A*49
+     * the datetime is stored in two parts, 213204 and 290819, which means
+     * 2019/08/29 21:32:04, however for in unix the year starts from 1900, we
+     * need to add the offset.
+     */
+    struct tm tm;
+    const int32_t unixYearOffset = 100;
+    tm.tm_mday = std::stoi(dateStr.substr(0, 2).c_str());
+    tm.tm_mon = std::stoi(dateStr.substr(2, 2).c_str()) - 1;
+    tm.tm_year = std::stoi(dateStr.substr(4, 2).c_str()) + unixYearOffset;
+    tm.tm_hour = std::stoi(timeStr.substr(0, 2).c_str());
+    tm.tm_min = std::stoi(timeStr.substr(2, 2).c_str());
+    tm.tm_sec = std::stoi(timeStr.substr(4, 2).c_str());
+    return static_cast<int64_t>(mktime(&tm) - timezone);
+}
+
+bool NmeaFixInfo::isValidFix() const {
+    return hasGMCRecord && hasGGARecord;
+}
+
+void NmeaFixInfo::parseGGALine(const std::vector<std::string>& sentenceValues) {
+    if (sentenceValues.size() == 0 || sentenceValues[0].compare(GPGA_RECORD_TAG) != 0) {
+        return;
+    }
+    // LatDeg, need covert to degree, if it is 'N', should be negative value
+    this->latDeg = std::stof(sentenceValues[2].substr(0, 2)) +
+                   (std::stof(sentenceValues[2].substr(2)) / 60.0);
+    if (sentenceValues[3].compare("N") != 0) {
+        this->latDeg *= -1;
+    }
+
+    // LngDeg, need covert to degree, if it is 'E', should be negative value
+    this->lngDeg = std::stof(sentenceValues[4].substr(0, 3)) +
+                   std::stof(sentenceValues[4].substr(3)) / 60.0;
+    if (sentenceValues[5].compare("E") != 0) {
+        this->lngDeg *= -1;
+    }
+
+    this->altitudeMeters = std::stof(sentenceValues[9]);
+
+    this->hDop = sentenceValues[8].empty() ? std::numeric_limits<float>::quiet_NaN()
+                                           : std::stof(sentenceValues[8]);
+    this->hasGGARecord = true;
+}
+
+void NmeaFixInfo::parseRMCLine(const std::vector<std::string>& sentenceValues) {
+    if (sentenceValues.size() == 0 || sentenceValues[0].compare(GPRMC_RECORD_TAG) != 0) {
+        return;
+    }
+    this->speedMetersPerSec = checkAndConvertToFloat(sentenceValues[7]);
+    this->bearingDegrees = checkAndConvertToFloat(sentenceValues[8]);
+    this->timestamp = nmeaPartsToTimestamp(sentenceValues[1], sentenceValues[9]);
+    this->hasGMCRecord = true;
+}
+
+/** invalid the current NmeaFixInfo */
+void NmeaFixInfo::reset() {
+    this->altitudeMeters = 0;
+    this->bearingDegrees = 0;
+    this->fixId = 0;
+    this->hasGMCRecord = false;
+    this->hasGGARecord = false;
+    this->latDeg = 0;
+    this->lngDeg = 0;
+    this->hDop = 0;
+    this->vDop = 0;
+    this->satelliteCount = 0;
+    this->speedMetersPerSec = 0;
+    this->timestamp = 0;
+}
+
+void NmeaFixInfo::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);
+    }
+}
+
+NmeaFixInfo& NmeaFixInfo::operator=(const NmeaFixInfo& rhs) {
+    if (this == &rhs) return *this;
+    this->altitudeMeters = rhs.altitudeMeters;
+    this->bearingDegrees = rhs.bearingDegrees;
+    this->fixId = rhs.fixId;
+    this->hasGMCRecord = rhs.hasGMCRecord;
+    this->hasGGARecord = rhs.hasGGARecord;
+    this->hDop = rhs.hDop;
+    this->vDop = rhs.vDop;
+    this->latDeg = rhs.latDeg;
+    this->lngDeg = rhs.lngDeg;
+    this->satelliteCount = rhs.satelliteCount;
+    this->speedMetersPerSec = rhs.speedMetersPerSec;
+    this->timestamp = rhs.timestamp;
+
+    return *this;
+}
+
+/**
+ * Parses the input string in NMEA format and convert to GnssLocation.
+ * Currently version only cares about $GPGGA and $GPRMC records. but we
+ * can easily extend to other types supported by NMEA if needed.
+ */
+std::unique_ptr<V2_0::GnssLocation> NmeaFixInfo::getLocationFromInputStr(
+        const std::string& inputStr) {
+    std::vector<std::string> nmeaRecords;
+    splitStr(inputStr, LINE_SEPARATOR, nmeaRecords);
+    NmeaFixInfo nmeaFixInfo;
+    NmeaFixInfo candidateFixInfo;
+    uint32_t fixId = 0;
+    double lastTimeStamp = 0;
+    for (const auto& line : nmeaRecords) {
+        std::vector<std::string> sentenceValues;
+        splitStr(line, COMMA_SEPARATOR, sentenceValues);
+        double currentTimeStamp = std::stof(sentenceValues[1]);
+        // If see a new timestamp, report correct location.
+        if ((currentTimeStamp - lastTimeStamp) > TIMESTAMP_EPSILON &&
+            candidateFixInfo.isValidFix()) {
+            nmeaFixInfo = candidateFixInfo;
+            candidateFixInfo.reset();
+            fixId++;
+        }
+        if (line.compare(0, strlen(GPGA_RECORD_TAG), GPGA_RECORD_TAG) == 0) {
+            candidateFixInfo.fixId = fixId;
+            candidateFixInfo.parseGGALine(sentenceValues);
+        } else if (line.compare(0, strlen(GPRMC_RECORD_TAG), GPRMC_RECORD_TAG) == 0) {
+            candidateFixInfo.parseRMCLine(sentenceValues);
+        }
+    }
+    if (candidateFixInfo.isValidFix()) {
+        nmeaFixInfo = candidateFixInfo;
+        candidateFixInfo.reset();
+    }
+    if (!nmeaFixInfo.isValidFix()) {
+        return nullptr;
+    }
+    return nmeaFixInfo.toGnssLocation();
+}
+
+/**
+ * Parses the input string in NMEA format and convert to GnssLocation.
+ */
+std::unique_ptr<V2_0::GnssLocation> NmeaFixInfo::toGnssLocation() const {
+    const V2_0::ElapsedRealtime currentOsTimestamp = {
+            .flags = V2_0::ElapsedRealtimeFlags::HAS_TIMESTAMP_NS |
+                     V2_0::ElapsedRealtimeFlags::HAS_TIME_UNCERTAINTY_NS,
+            .timestampNs = static_cast<uint64_t>(::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 = 1000000};
+
+    V1_0::GnssLocation locationV1 = {
+            .gnssLocationFlags = 0xFF,
+            .latitudeDegrees = this->getLatDeg(),
+            .longitudeDegrees = this->getLngDeg(),
+            .altitudeMeters = this->getAltitudeMeters(),
+            .speedMetersPerSec = this->getSpeedMetersPerSec(),
+            .bearingDegrees = this->getBearingDegrees(),
+            .horizontalAccuracyMeters = this->getHorizontalAccuracyMeters(),
+            .verticalAccuracyMeters = this->getVerticalAccuracyMeters(),
+            .speedAccuracyMetersPerSecond = this->getSpeedAccuracyMetersPerSecond(),
+            .bearingAccuracyDegrees = this->getBearingAccuracyDegrees(),
+            .timestamp = this->getTimestamp()};
+
+    V2_0::GnssLocation locationV2 = {.v1_0 = locationV1, .elapsedRealtime = currentOsTimestamp};
+
+    return std::make_unique<V2_0::GnssLocation>(locationV2);
+}
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
\ No newline at end of file
diff --git a/gnss/common/utils/default/include/NmeaFixInfo.h b/gnss/common/utils/default/include/NmeaFixInfo.h
new file mode 100644
index 0000000..fb2c1a4
--- /dev/null
+++ b/gnss/common/utils/default/include/NmeaFixInfo.h
@@ -0,0 +1,92 @@
+/*
+ * 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 <Constants.h>
+#include <android/hardware/gnss/1.0/IGnss.h>
+#include <android/hardware/gnss/2.0/IGnss.h>
+#include <hidl/Status.h>
+#include <ctime>
+#include <string>
+namespace android {
+namespace hardware {
+namespace gnss {
+namespace common {
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+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;
+
+/** Helper class to parse and store the GNSS fix details information. */
+class NmeaFixInfo {
+  private:
+    float altitudeMeters;
+    float bearingDegrees;
+    uint32_t fixId;
+    bool hasGMCRecord;
+    bool hasGGARecord;
+    float hDop;
+    float vDop;
+    float latDeg;
+    float lngDeg;
+    uint32_t satelliteCount;
+    float speedMetersPerSec;
+    int64_t timestamp;
+
+  public:
+    static std::unique_ptr<V2_0::GnssLocation> getLocationFromInputStr(const std::string& inputStr);
+
+  private:
+    static void splitStr(const std::string& line, const char& delimiter,
+                         std::vector<std::string>& out);
+    static float checkAndConvertToFloat(const std::string& sentence);
+    static int64_t nmeaPartsToTimestamp(const std::string& timeStr, const std::string& dateStr);
+
+    NmeaFixInfo();
+    void parseGGALine(const std::vector<std::string>& sentenceValues);
+    void parseRMCLine(const std::vector<std::string>& sentenceValues);
+    std::unique_ptr<V2_0::GnssLocation> toGnssLocation() const;
+
+    // Getters
+    float getAltitudeMeters() const;
+    float getBearingAccuracyDegrees() const;
+    float getBearingDegrees() const;
+    uint32_t getFixId() const;
+    float getHorizontalAccuracyMeters() const;
+    float getLatDeg() const;
+    float getLngDeg() const;
+    float getSpeedAccuracyMetersPerSecond() const;
+    float getSpeedMetersPerSec() const;
+    int64_t getTimestamp() const;
+    float getVerticalAccuracyMeters() const;
+
+    bool isValidFix() const;
+    void reset();
+    NmeaFixInfo& operator=(const NmeaFixInfo& rhs);
+};
+
+}  // namespace common
+}  // namespace gnss
+}  // namespace hardware
+}  // namespace android
\ No newline at end of file
diff --git a/gnss/2.1/default/GnssAntennaInfo.h b/gnss/common/utils/default/include/v2_1/GnssAntennaInfo.h
similarity index 79%
rename from gnss/2.1/default/GnssAntennaInfo.h
rename to gnss/common/utils/default/include/v2_1/GnssAntennaInfo.h
index 94b2111..e74ff54 100644
--- a/gnss/2.1/default/GnssAntennaInfo.h
+++ b/gnss/common/utils/default/include/v2_1/GnssAntennaInfo.h
@@ -14,23 +14,20 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H
-#define ANDROID_HARDWARE_GNSS_V2_1_GNSSANTENNAINFO_H
+#pragma once
 
 #include <android/hardware/gnss/2.1/IGnssAntennaInfo.h>
 
 #include <mutex>
 #include <thread>
 
-namespace android {
-namespace hardware {
-namespace gnss {
-namespace V2_1 {
-namespace implementation {
+namespace android::hardware::gnss::V2_1::implementation {
 
 using ::android::sp;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
+using IGnssAntennaInfo = ::android::hardware::gnss::V2_1::IGnssAntennaInfo;
+using IGnssAntennaInfoCallback = ::android::hardware::gnss::V2_1::IGnssAntennaInfoCallback;
 
 struct GnssAntennaInfo : public IGnssAntennaInfo {
     GnssAntennaInfo();
@@ -58,10 +55,4 @@
     mutable std::mutex mMutex;
 };
 
-}  // namespace implementation
-}  // namespace V2_1
-}  // namespace gnss
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
+}  // namespace android::hardware::gnss::V2_1::implementation
diff --git a/gnss/2.1/default/GnssConfiguration.h b/gnss/common/utils/default/include/v2_1/GnssConfiguration.h
similarity index 89%
rename from gnss/2.1/default/GnssConfiguration.h
rename to gnss/common/utils/default/include/v2_1/GnssConfiguration.h
index 662d61d..8463a5c 100644
--- a/gnss/2.1/default/GnssConfiguration.h
+++ b/gnss/common/utils/default/include/v2_1/GnssConfiguration.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
-#define ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
+#pragma once
 
 #include <android/hardware/gnss/2.1/IGnssCallback.h>
 #include <android/hardware/gnss/2.1/IGnssConfiguration.h>
@@ -24,11 +23,7 @@
 #include <mutex>
 #include <unordered_set>
 
-namespace android {
-namespace hardware {
-namespace gnss {
-namespace V2_1 {
-namespace implementation {
+namespace android::hardware::gnss::V2_1::implementation {
 
 using ::android::sp;
 using ::android::hardware::hidl_array;
@@ -92,10 +87,4 @@
     BlacklistedConstellationSetV2_1 mBlacklistedConstellationSet;
 };
 
-}  // namespace implementation
-}  // namespace V2_1
-}  // namespace gnss
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_GNSS_V2_1_GNSSCONFIGURATION_H
\ No newline at end of file
+}  // namespace android::hardware::gnss::V2_1::implementation
diff --git a/gnss/2.1/default/GnssDebug.h b/gnss/common/utils/default/include/v2_1/GnssDebug.h
similarity index 76%
rename from gnss/2.1/default/GnssDebug.h
rename to gnss/common/utils/default/include/v2_1/GnssDebug.h
index 969d337..8580989 100644
--- a/gnss/2.1/default/GnssDebug.h
+++ b/gnss/common/utils/default/include/v2_1/GnssDebug.h
@@ -14,17 +14,12 @@
  * limitations under the License.
  */
 
-#ifndef android_hardware_gnss_V1_1_GnssDebug_H_
-#define android_hardware_gnss_V1_1_GnssDebug_H_
+#pragma once
 
 #include <android/hardware/gnss/1.0/IGnssDebug.h>
 #include <hidl/Status.h>
 
-namespace android {
-namespace hardware {
-namespace gnss {
-namespace V1_1 {
-namespace implementation {
+namespace android::hardware::gnss::V1_1::implementation {
 
 using ::android::sp;
 using ::android::hardware::hidl_string;
@@ -42,10 +37,4 @@
     Return<void> getDebugData(V1_0::IGnssDebug::getDebugData_cb _hidl_cb) override;
 };
 
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace gnss
-}  // namespace hardware
-}  // namespace android
-
-#endif  // android_hardware_gnss_V1_1_GnssDebug_H_
+}  // namespace android::hardware::gnss::V1_1::implementation
diff --git a/gnss/2.1/default/GnssMeasurement.h b/gnss/common/utils/default/include/v2_1/GnssMeasurement.h
similarity index 91%
rename from gnss/2.1/default/GnssMeasurement.h
rename to gnss/common/utils/default/include/v2_1/GnssMeasurement.h
index d446419..1d1fc9d 100644
--- a/gnss/2.1/default/GnssMeasurement.h
+++ b/gnss/common/utils/default/include/v2_1/GnssMeasurement.h
@@ -23,11 +23,7 @@
 #include <mutex>
 #include <thread>
 
-namespace android {
-namespace hardware {
-namespace gnss {
-namespace V2_1 {
-namespace implementation {
+namespace android::hardware::gnss::V2_1::implementation {
 
 using GnssDataV2_1 = V2_1::IGnssMeasurementCallback::GnssData;
 using GnssDataV2_0 = V2_0::IGnssMeasurementCallback::GnssData;
@@ -80,8 +76,4 @@
     mutable std::mutex mMutex;
 };
 
-}  // namespace implementation
-}  // namespace V2_1
-}  // namespace gnss
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::gnss::V2_1::implementation
diff --git a/gnss/2.1/default/GnssMeasurementCorrections.h b/gnss/common/utils/default/include/v2_1/GnssMeasurementCorrections.h
similarity index 72%
rename from gnss/2.1/default/GnssMeasurementCorrections.h
rename to gnss/common/utils/default/include/v2_1/GnssMeasurementCorrections.h
index 036e855..eaa7659 100644
--- a/gnss/2.1/default/GnssMeasurementCorrections.h
+++ b/gnss/common/utils/default/include/v2_1/GnssMeasurementCorrections.h
@@ -20,22 +20,15 @@
 #include <hidl/MQDescriptor.h>
 #include <hidl/Status.h>
 
-namespace android {
-namespace hardware {
-namespace gnss {
-namespace measurement_corrections {
-namespace V1_1 {
-namespace implementation {
+namespace android::hardware::gnss::measurement_corrections::V1_1::implementation {
 
 using ::android::sp;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
 using ::android::hardware::Return;
-using ::android::hardware::Void;
 
 struct GnssMeasurementCorrections : public IMeasurementCorrections {
+    GnssMeasurementCorrections();
+    ~GnssMeasurementCorrections();
+
     // Methods from V1_0::IMeasurementCorrections follow.
     Return<bool> setCorrections(const V1_0::MeasurementCorrections& corrections) override;
     Return<bool> setCallback(const sp<V1_0::IMeasurementCorrectionsCallback>& callback) override;
@@ -44,9 +37,4 @@
     Return<bool> setCorrections_1_1(const V1_1::MeasurementCorrections& corrections) override;
 };
 
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace measurement_corrections
-}  // namespace gnss
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::gnss::measurement_corrections::V1_1::implementation
diff --git a/gnss/common/utils/default/include/v2_1/GnssTemplate.h b/gnss/common/utils/default/include/v2_1/GnssTemplate.h
new file mode 100644
index 0000000..d16a67b
--- /dev/null
+++ b/gnss/common/utils/default/include/v2_1/GnssTemplate.h
@@ -0,0 +1,641 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <android/hardware/gnss/2.1/IGnss.h>
+#include <fcntl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <log/log.h>
+#include <sys/epoll.h>
+#include <atomic>
+#include <mutex>
+#include <string>
+#include <thread>
+
+#include "GnssAntennaInfo.h"
+#include "GnssConfiguration.h"
+#include "GnssDebug.h"
+#include "GnssMeasurement.h"
+#include "GnssMeasurementCorrections.h"
+#include "NmeaFixInfo.h"
+#include "Utils.h"
+
+namespace android::hardware::gnss::common::implementation {
+
+using GnssSvInfo = V2_1::IGnssCallback::GnssSvInfo;
+
+using common::NmeaFixInfo;
+using common::Utils;
+using measurement_corrections::V1_1::implementation::GnssMeasurementCorrections;
+
+using V2_1::implementation::GnssAntennaInfo;
+using V2_1::implementation::GnssConfiguration;
+using V2_1::implementation::GnssMeasurement;
+
+constexpr int INPUT_BUFFER_SIZE = 128;
+constexpr char CMD_GET_LOCATION[] = "CMD_GET_LOCATION";
+constexpr char GNSS_PATH[] = "/dev/gnss0";
+
+template <class T_IGnss>
+struct GnssTemplate : public T_IGnss {
+    GnssTemplate();
+    ~GnssTemplate();
+    // Methods from V1_0::IGnss follow.
+    Return<bool> setCallback(const sp<V1_0::IGnssCallback>& callback) override;
+    Return<bool> start() override;
+    Return<bool> stop() override;
+    Return<void> cleanup() override;
+    Return<bool> injectTime(int64_t timeMs, int64_t timeReferenceMs,
+                            int32_t uncertaintyMs) override;
+    Return<bool> injectLocation(double latitudeDegrees, double longitudeDegrees,
+                                float accuracyMeters) override;
+    Return<void> deleteAidingData(V1_0::IGnss::GnssAidingData aidingDataFlags) override;
+    Return<bool> setPositionMode(V1_0::IGnss::GnssPositionMode mode,
+                                 V1_0::IGnss::GnssPositionRecurrence recurrence,
+                                 uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
+                                 uint32_t preferredTimeMs) override;
+    Return<sp<V1_0::IAGnssRil>> getExtensionAGnssRil() override;
+    Return<sp<V1_0::IGnssGeofencing>> getExtensionGnssGeofencing() override;
+    Return<sp<V1_0::IAGnss>> getExtensionAGnss() override;
+    Return<sp<V1_0::IGnssNi>> getExtensionGnssNi() override;
+    Return<sp<V1_0::IGnssMeasurement>> getExtensionGnssMeasurement() override;
+    Return<sp<V1_0::IGnssNavigationMessage>> getExtensionGnssNavigationMessage() override;
+    Return<sp<V1_0::IGnssXtra>> getExtensionXtra() override;
+    Return<sp<V1_0::IGnssConfiguration>> getExtensionGnssConfiguration() override;
+    Return<sp<V1_0::IGnssDebug>> getExtensionGnssDebug() override;
+    Return<sp<V1_0::IGnssBatching>> getExtensionGnssBatching() override;
+
+    // Methods from V1_1::IGnss follow.
+    Return<bool> setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) override;
+    Return<bool> setPositionMode_1_1(V1_0::IGnss::GnssPositionMode mode,
+                                     V1_0::IGnss::GnssPositionRecurrence recurrence,
+                                     uint32_t minIntervalMs, uint32_t preferredAccuracyMeters,
+                                     uint32_t preferredTimeMs, bool lowPowerMode) override;
+    Return<sp<V1_1::IGnssConfiguration>> getExtensionGnssConfiguration_1_1() override;
+    Return<sp<V1_1::IGnssMeasurement>> getExtensionGnssMeasurement_1_1() override;
+    Return<bool> injectBestLocation(const V1_0::GnssLocation& location) override;
+
+    // Methods from V2_0::IGnss follow.
+    Return<bool> setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) override;
+    Return<sp<V2_0::IGnssConfiguration>> getExtensionGnssConfiguration_2_0() override;
+    Return<sp<V2_0::IGnssDebug>> getExtensionGnssDebug_2_0() override;
+    Return<sp<V2_0::IAGnss>> getExtensionAGnss_2_0() override;
+    Return<sp<V2_0::IAGnssRil>> getExtensionAGnssRil_2_0() override;
+    Return<sp<V2_0::IGnssMeasurement>> getExtensionGnssMeasurement_2_0() override;
+    Return<sp<measurement_corrections::V1_0::IMeasurementCorrections>>
+    getExtensionMeasurementCorrections() override;
+    Return<sp<visibility_control::V1_0::IGnssVisibilityControl>> getExtensionVisibilityControl()
+            override;
+    Return<sp<V2_0::IGnssBatching>> getExtensionGnssBatching_2_0() override;
+    Return<bool> injectBestLocation_2_0(const V2_0::GnssLocation& location) override;
+
+    // Methods from V2_1::IGnss follow.
+    Return<bool> setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) override;
+    Return<sp<V2_1::IGnssMeasurement>> getExtensionGnssMeasurement_2_1() override;
+    Return<sp<V2_1::IGnssConfiguration>> getExtensionGnssConfiguration_2_1() override;
+    Return<sp<measurement_corrections::V1_1::IMeasurementCorrections>>
+    getExtensionMeasurementCorrections_1_1() override;
+    Return<sp<V2_1::IGnssAntennaInfo>> getExtensionGnssAntennaInfo() override;
+
+  private:
+    std::unique_ptr<V2_0::GnssLocation> getLocationFromHW();
+    void reportLocation(const V2_0::GnssLocation&) const;
+    void reportLocation(const V1_0::GnssLocation&) const;
+    void reportSvStatus(const hidl_vec<GnssSvInfo>&) const;
+
+    static sp<V2_1::IGnssCallback> sGnssCallback_2_1;
+    static sp<V2_0::IGnssCallback> sGnssCallback_2_0;
+    static sp<V1_1::IGnssCallback> sGnssCallback_1_1;
+    static sp<V1_0::IGnssCallback> sGnssCallback_1_0;
+
+    std::atomic<long> mMinIntervalMs;
+    sp<GnssConfiguration> mGnssConfiguration;
+    std::atomic<bool> mIsActive;
+    std::atomic<bool> mHardwareModeOn;
+    std::atomic<int> mGnssFd;
+    std::thread mThread;
+
+    mutable std::mutex mMutex;
+    hidl_vec<GnssSvInfo> filterBlacklistedSatellitesV2_1(hidl_vec<GnssSvInfo> gnssSvInfoList);
+};
+
+template <class T_IGnss>
+sp<V2_1::IGnssCallback> GnssTemplate<T_IGnss>::sGnssCallback_2_1 = nullptr;
+template <class T_IGnss>
+sp<V2_0::IGnssCallback> GnssTemplate<T_IGnss>::sGnssCallback_2_0 = nullptr;
+template <class T_IGnss>
+sp<V1_1::IGnssCallback> GnssTemplate<T_IGnss>::sGnssCallback_1_1 = nullptr;
+template <class T_IGnss>
+sp<V1_0::IGnssCallback> GnssTemplate<T_IGnss>::sGnssCallback_1_0 = nullptr;
+
+template <class T_IGnss>
+GnssTemplate<T_IGnss>::GnssTemplate()
+    : mMinIntervalMs(1000),
+      mGnssConfiguration{new GnssConfiguration()},
+      mHardwareModeOn(false),
+      mGnssFd(-1) {}
+
+template <class T_IGnss>
+GnssTemplate<T_IGnss>::~GnssTemplate() {
+    stop();
+}
+
+template <class T_IGnss>
+std::unique_ptr<V2_0::GnssLocation> GnssTemplate<T_IGnss>::getLocationFromHW() {
+    char inputBuffer[INPUT_BUFFER_SIZE];
+    mHardwareModeOn = false;
+    if (mGnssFd == -1) {
+        mGnssFd = open(GNSS_PATH, O_RDWR | O_NONBLOCK);
+    }
+    if (mGnssFd == -1) {
+        return nullptr;
+    }
+    // Send control message to device
+    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);
+    // Indicates it is a hardwareMode, don't need to wait outside.
+    mHardwareModeOn = true;
+    if (epoll_ret == -1) {
+        return nullptr;
+    }
+    while (true) {
+        bytes_read = read(mGnssFd, &inputBuffer, INPUT_BUFFER_SIZE);
+        if (bytes_read <= 0) {
+            break;
+        }
+        inputStr += std::string(inputBuffer, bytes_read);
+    }
+    return NmeaFixInfo::getLocationFromInputStr(inputStr);
+}
+
+template <class T_IGnss>
+Return<bool> GnssTemplate<T_IGnss>::start() {
+    if (mIsActive) {
+        ALOGW("Gnss has started. Restarting...");
+        stop();
+    }
+
+    mIsActive = true;
+    mThread = std::thread([this]() {
+        while (mIsActive == true) {
+            auto svStatus = filterBlacklistedSatellitesV2_1(Utils::getMockSvInfoListV2_1());
+            this->reportSvStatus(svStatus);
+
+            auto currentLocation = getLocationFromHW();
+            if (currentLocation != nullptr) {
+                this->reportLocation(*currentLocation);
+            } else {
+                if (sGnssCallback_2_1 != nullptr || sGnssCallback_2_0 != nullptr) {
+                    const auto location = Utils::getMockLocationV2_0();
+                    this->reportLocation(location);
+                } else {
+                    const auto location = Utils::getMockLocationV1_0();
+                    this->reportLocation(location);
+                }
+
+                // Only need do the sleep in the static location mode, which mocks the "wait
+                // for" hardware behavior.
+                if (!mHardwareModeOn) {
+                    std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
+                }
+            }
+        }
+    });
+    return true;
+}
+
+template <class T_IGnss>
+hidl_vec<GnssSvInfo> GnssTemplate<T_IGnss>::filterBlacklistedSatellitesV2_1(
+        hidl_vec<GnssSvInfo> gnssSvInfoList) {
+    for (uint32_t i = 0; i < gnssSvInfoList.size(); i++) {
+        if (mGnssConfiguration->isBlacklistedV2_1(gnssSvInfoList[i])) {
+            gnssSvInfoList[i].v2_0.v1_0.svFlag &=
+                    ~static_cast<uint8_t>(V1_0::IGnssCallback::GnssSvFlags::USED_IN_FIX);
+        }
+    }
+    return gnssSvInfoList;
+}
+
+template <class T_IGnss>
+Return<bool> GnssTemplate<T_IGnss>::stop() {
+    ALOGD("stop");
+    mIsActive = false;
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+    if (mGnssFd != -1) {
+        close(mGnssFd);
+        mGnssFd = -1;
+    }
+    return true;
+}
+
+// Methods from V1_0::IGnss follow.
+template <class T_IGnss>
+Return<bool> GnssTemplate<T_IGnss>::setCallback(const sp<V1_0::IGnssCallback>& callback) {
+    if (callback == nullptr) {
+        ALOGE("%s: Null callback ignored", __func__);
+        return false;
+    }
+
+    sGnssCallback_1_0 = callback;
+
+    uint32_t capabilities = 0x0 | V1_0::IGnssCallback::Capabilities::MEASUREMENTS |
+                            V1_0::IGnssCallback::Capabilities::SCHEDULING;
+    auto ret = sGnssCallback_1_0->gnssSetCapabilitesCb(capabilities);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    V2_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2018};
+
+    ret = sGnssCallback_1_0->gnssSetSystemInfoCb(gnssInfo);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    return true;
+}
+
+template <class T_IGnss>
+Return<void> GnssTemplate<T_IGnss>::cleanup() {
+    sGnssCallback_2_1 = nullptr;
+    sGnssCallback_2_0 = nullptr;
+    return Void();
+}
+
+template <class T_IGnss>
+Return<bool> GnssTemplate<T_IGnss>::injectTime(int64_t, int64_t, int32_t) {
+    return true;
+}
+
+template <class T_IGnss>
+Return<bool> GnssTemplate<T_IGnss>::injectLocation(double, double, float) {
+    return true;
+}
+
+template <class T_IGnss>
+Return<void> GnssTemplate<T_IGnss>::deleteAidingData(V1_0::IGnss::GnssAidingData) {
+    // TODO implement
+    return Void();
+}
+
+template <class T_IGnss>
+Return<bool> GnssTemplate<T_IGnss>::setPositionMode(V1_0::IGnss::GnssPositionMode,
+                                                    V1_0::IGnss::GnssPositionRecurrence,
+                                                    uint32_t minIntervalMs, uint32_t, uint32_t) {
+    mMinIntervalMs = minIntervalMs;
+    return true;
+}
+
+template <class T_IGnss>
+Return<sp<V1_0::IAGnssRil>> GnssTemplate<T_IGnss>::getExtensionAGnssRil() {
+    // TODO implement
+    return ::android::sp<V1_0::IAGnssRil>{};
+}
+
+template <class T_IGnss>
+Return<sp<V1_0::IGnssGeofencing>> GnssTemplate<T_IGnss>::getExtensionGnssGeofencing() {
+    // TODO implement
+    return ::android::sp<V1_0::IGnssGeofencing>{};
+}
+
+template <class T_IGnss>
+Return<sp<V1_0::IAGnss>> GnssTemplate<T_IGnss>::getExtensionAGnss() {
+    // TODO implement
+    return ::android::sp<V1_0::IAGnss>{};
+}
+
+template <class T_IGnss>
+Return<sp<V1_0::IGnssNi>> GnssTemplate<T_IGnss>::getExtensionGnssNi() {
+    // TODO implement
+    return ::android::sp<V1_0::IGnssNi>{};
+}
+
+template <class T_IGnss>
+Return<sp<V1_0::IGnssMeasurement>> GnssTemplate<T_IGnss>::getExtensionGnssMeasurement() {
+    ALOGD("Gnss::getExtensionGnssMeasurement");
+    return new GnssMeasurement();
+}
+
+template <class T_IGnss>
+Return<sp<V1_0::IGnssNavigationMessage>>
+GnssTemplate<T_IGnss>::getExtensionGnssNavigationMessage() {
+    // TODO implement
+    return ::android::sp<V1_0::IGnssNavigationMessage>{};
+}
+
+template <class T_IGnss>
+Return<sp<V1_0::IGnssXtra>> GnssTemplate<T_IGnss>::getExtensionXtra() {
+    // TODO implement
+    return ::android::sp<V1_0::IGnssXtra>{};
+}
+
+template <class T_IGnss>
+Return<sp<V1_0::IGnssConfiguration>> GnssTemplate<T_IGnss>::getExtensionGnssConfiguration() {
+    // TODO implement
+    return ::android::sp<V1_0::IGnssConfiguration>{};
+}
+
+template <class T_IGnss>
+Return<sp<V1_0::IGnssDebug>> GnssTemplate<T_IGnss>::getExtensionGnssDebug() {
+    return new V1_1::implementation::GnssDebug();
+}
+
+template <class T_IGnss>
+Return<sp<V1_0::IGnssBatching>> GnssTemplate<T_IGnss>::getExtensionGnssBatching() {
+    // TODO implement
+    return ::android::sp<V1_0::IGnssBatching>{};
+}
+
+// Methods from V1_1::IGnss follow.
+template <class T_IGnss>
+Return<bool> GnssTemplate<T_IGnss>::setCallback_1_1(const sp<V1_1::IGnssCallback>& callback) {
+    if (callback == nullptr) {
+        ALOGE("%s: Null callback ignored", __func__);
+        return false;
+    }
+
+    sGnssCallback_1_1 = callback;
+
+    uint32_t capabilities = 0x0;
+    auto ret = sGnssCallback_1_1->gnssSetCapabilitesCb(capabilities);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    V2_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2018};
+
+    ret = sGnssCallback_1_1->gnssSetSystemInfoCb(gnssInfo);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    auto gnssName = "Google Mock GNSS Implementation v2.1";
+    ret = sGnssCallback_1_1->gnssNameCb(gnssName);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    return true;
+}
+
+template <class T_IGnss>
+Return<bool> GnssTemplate<T_IGnss>::setPositionMode_1_1(V1_0::IGnss::GnssPositionMode,
+                                                        V1_0::IGnss::GnssPositionRecurrence,
+                                                        uint32_t minIntervalMs, uint32_t, uint32_t,
+                                                        bool) {
+    mMinIntervalMs = minIntervalMs;
+    return true;
+}
+
+template <class T_IGnss>
+Return<sp<V1_1::IGnssConfiguration>> GnssTemplate<T_IGnss>::getExtensionGnssConfiguration_1_1() {
+    // TODO implement
+    return ::android::sp<V1_1::IGnssConfiguration>{};
+}
+
+template <class T_IGnss>
+Return<sp<V1_1::IGnssMeasurement>> GnssTemplate<T_IGnss>::getExtensionGnssMeasurement_1_1() {
+    // TODO implement
+    return ::android::sp<V1_1::IGnssMeasurement>{};
+}
+
+template <class T_IGnss>
+Return<bool> GnssTemplate<T_IGnss>::injectBestLocation(const V1_0::GnssLocation&) {
+    return true;
+}
+
+// Methods from V2_0::IGnss follow.
+template <class T_IGnss>
+Return<bool> GnssTemplate<T_IGnss>::setCallback_2_0(const sp<V2_0::IGnssCallback>& callback) {
+    ALOGD("Gnss::setCallback_2_0");
+    if (callback == nullptr) {
+        ALOGE("%s: Null callback ignored", __func__);
+        return false;
+    }
+
+    sGnssCallback_2_0 = callback;
+
+    using Capabilities = V2_0::IGnssCallback::Capabilities;
+    const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS |
+                              Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST;
+    auto ret = sGnssCallback_2_0->gnssSetCapabilitiesCb_2_0(capabilities);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    V1_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2019};
+
+    ret = sGnssCallback_2_0->gnssSetSystemInfoCb(gnssInfo);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    auto gnssName = "Google Mock GNSS Implementation v2.1";
+    ret = sGnssCallback_2_0->gnssNameCb(gnssName);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    return true;
+}
+
+template <class T_IGnss>
+Return<sp<V2_0::IGnssConfiguration>> GnssTemplate<T_IGnss>::getExtensionGnssConfiguration_2_0() {
+    ALOGD("Gnss::getExtensionGnssConfiguration_2_0");
+    return mGnssConfiguration;
+}
+
+template <class T_IGnss>
+Return<sp<V2_0::IGnssDebug>> GnssTemplate<T_IGnss>::getExtensionGnssDebug_2_0() {
+    // TODO implement
+    return ::android::sp<V2_0::IGnssDebug>{};
+}
+
+template <class T_IGnss>
+Return<sp<V2_0::IAGnss>> GnssTemplate<T_IGnss>::getExtensionAGnss_2_0() {
+    // TODO implement
+    return ::android::sp<V2_0::IAGnss>{};
+}
+
+template <class T_IGnss>
+Return<sp<V2_0::IAGnssRil>> GnssTemplate<T_IGnss>::getExtensionAGnssRil_2_0() {
+    // TODO implement
+    return ::android::sp<V2_0::IAGnssRil>{};
+}
+
+template <class T_IGnss>
+Return<sp<V2_0::IGnssMeasurement>> GnssTemplate<T_IGnss>::getExtensionGnssMeasurement_2_0() {
+    ALOGD("Gnss::getExtensionGnssMeasurement_2_0");
+    return new GnssMeasurement();
+}
+
+template <class T_IGnss>
+Return<sp<measurement_corrections::V1_0::IMeasurementCorrections>>
+GnssTemplate<T_IGnss>::getExtensionMeasurementCorrections() {
+    ALOGD("Gnss::getExtensionMeasurementCorrections()");
+    return new GnssMeasurementCorrections();
+}
+
+template <class T_IGnss>
+Return<sp<visibility_control::V1_0::IGnssVisibilityControl>>
+GnssTemplate<T_IGnss>::getExtensionVisibilityControl() {
+    // TODO implement
+    return ::android::sp<visibility_control::V1_0::IGnssVisibilityControl>{};
+}
+
+template <class T_IGnss>
+Return<sp<V2_0::IGnssBatching>> GnssTemplate<T_IGnss>::getExtensionGnssBatching_2_0() {
+    // TODO implement
+    return ::android::sp<V2_0::IGnssBatching>{};
+}
+
+template <class T_IGnss>
+Return<bool> GnssTemplate<T_IGnss>::injectBestLocation_2_0(const V2_0::GnssLocation&) {
+    // TODO(b/124012850): Implement function.
+    return bool{};
+}
+
+// Methods from V2_1::IGnss follow.
+template <class T_IGnss>
+Return<bool> GnssTemplate<T_IGnss>::setCallback_2_1(const sp<V2_1::IGnssCallback>& callback) {
+    ALOGD("Gnss::setCallback_2_1");
+    if (callback == nullptr) {
+        ALOGE("%s: Null callback ignored", __func__);
+        return false;
+    }
+
+    sGnssCallback_2_1 = callback;
+
+    using Capabilities = V2_1::IGnssCallback::Capabilities;
+    const auto capabilities = Capabilities::MEASUREMENTS | Capabilities::MEASUREMENT_CORRECTIONS |
+                              Capabilities::LOW_POWER_MODE | Capabilities::SATELLITE_BLACKLIST |
+                              Capabilities::ANTENNA_INFO;
+    auto ret = sGnssCallback_2_1->gnssSetCapabilitiesCb_2_1(capabilities);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    V1_1::IGnssCallback::GnssSystemInfo gnssInfo = {.yearOfHw = 2020};
+
+    ret = sGnssCallback_2_1->gnssSetSystemInfoCb(gnssInfo);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    auto gnssName = "Android Mock GNSS Implementation v2.1";
+    ret = sGnssCallback_2_1->gnssNameCb(gnssName);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+
+    return true;
+}
+
+template <class T_IGnss>
+Return<sp<V2_1::IGnssMeasurement>> GnssTemplate<T_IGnss>::getExtensionGnssMeasurement_2_1() {
+    ALOGD("Gnss::getExtensionGnssMeasurement_2_1");
+    return new GnssMeasurement();
+}
+
+template <class T_IGnss>
+Return<sp<V2_1::IGnssConfiguration>> GnssTemplate<T_IGnss>::getExtensionGnssConfiguration_2_1() {
+    ALOGD("Gnss::getExtensionGnssConfiguration_2_1");
+    return mGnssConfiguration;
+}
+
+template <class T_IGnss>
+Return<sp<measurement_corrections::V1_1::IMeasurementCorrections>>
+GnssTemplate<T_IGnss>::getExtensionMeasurementCorrections_1_1() {
+    ALOGD("Gnss::getExtensionMeasurementCorrections_1_1()");
+    return new GnssMeasurementCorrections();
+}
+
+template <class T_IGnss>
+Return<sp<V2_1::IGnssAntennaInfo>> GnssTemplate<T_IGnss>::getExtensionGnssAntennaInfo() {
+    ALOGD("Gnss::getExtensionGnssAntennaInfo");
+    return new GnssAntennaInfo();
+}
+
+template <class T_IGnss>
+void GnssTemplate<T_IGnss>::reportSvStatus(const hidl_vec<GnssSvInfo>& svInfoList) const {
+    std::unique_lock<std::mutex> lock(mMutex);
+    // TODO(skz): update this to call 2_0 callback if non-null
+    if (sGnssCallback_2_1 == nullptr) {
+        ALOGE("%s: sGnssCallback v2.1 is null.", __func__);
+        return;
+    }
+    auto ret = sGnssCallback_2_1->gnssSvStatusCb_2_1(svInfoList);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+template <class T_IGnss>
+void GnssTemplate<T_IGnss>::reportLocation(const V1_0::GnssLocation& location) const {
+    std::unique_lock<std::mutex> lock(mMutex);
+    if (sGnssCallback_1_1 != nullptr) {
+        auto ret = sGnssCallback_1_1->gnssLocationCb(location);
+        if (!ret.isOk()) {
+            ALOGE("%s: Unable to invoke callback v1.1", __func__);
+        }
+        return;
+    }
+    if (sGnssCallback_1_0 == nullptr) {
+        ALOGE("%s: No non-null callback", __func__);
+        return;
+    }
+    auto ret = sGnssCallback_1_0->gnssLocationCb(location);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback v1.0", __func__);
+    }
+}
+
+template <class T_IGnss>
+void GnssTemplate<T_IGnss>::reportLocation(const V2_0::GnssLocation& location) const {
+    std::unique_lock<std::mutex> lock(mMutex);
+    if (sGnssCallback_2_1 != nullptr) {
+        auto ret = sGnssCallback_2_1->gnssLocationCb_2_0(location);
+        if (!ret.isOk()) {
+            ALOGE("%s: Unable to invoke callback v2.1", __func__);
+        }
+        return;
+    }
+    if (sGnssCallback_2_0 == nullptr) {
+        ALOGE("%s: No non-null callback", __func__);
+        return;
+    }
+    auto ret = sGnssCallback_2_0->gnssLocationCb_2_0(location);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback v2.0", __func__);
+    }
+}
+
+}  // namespace android::hardware::gnss::common::implementation
diff --git a/gnss/2.1/default/GnssAntennaInfo.cpp b/gnss/common/utils/default/v2_1/GnssAntennaInfo.cpp
similarity index 91%
rename from gnss/2.1/default/GnssAntennaInfo.cpp
rename to gnss/common/utils/default/v2_1/GnssAntennaInfo.cpp
index ed183a9..962451c 100644
--- a/gnss/2.1/default/GnssAntennaInfo.cpp
+++ b/gnss/common/utils/default/v2_1/GnssAntennaInfo.cpp
@@ -16,18 +16,14 @@
 
 #define LOG_TAG "GnssAntennaInfo"
 
-#include "GnssAntennaInfo.h"
+#include "v2_1/GnssAntennaInfo.h"
 #include "Utils.h"
 
 #include <log/log.h>
 
 using ::android::hardware::gnss::common::Utils;
 
-namespace android {
-namespace hardware {
-namespace gnss {
-namespace V2_1 {
-namespace implementation {
+namespace android::hardware::gnss::V2_1::implementation {
 
 sp<IGnssAntennaInfoCallback> GnssAntennaInfo::sCallback = nullptr;
 
@@ -102,8 +98,4 @@
     }
 }
 
-}  // namespace implementation
-}  // namespace V2_1
-}  // namespace gnss
-}  // namespace hardware
-}  // namespace android
\ No newline at end of file
+}  // namespace android::hardware::gnss::V2_1::implementation
diff --git a/gnss/2.1/default/GnssConfiguration.cpp b/gnss/common/utils/default/v2_1/GnssConfiguration.cpp
similarity index 92%
rename from gnss/2.1/default/GnssConfiguration.cpp
rename to gnss/common/utils/default/v2_1/GnssConfiguration.cpp
index cd8f07f..8b30701 100644
--- a/gnss/2.1/default/GnssConfiguration.cpp
+++ b/gnss/common/utils/default/v2_1/GnssConfiguration.cpp
@@ -16,14 +16,10 @@
 
 #define LOG_TAG "GnssConfiguration"
 
-#include "GnssConfiguration.h"
+#include "v2_1/GnssConfiguration.h"
 #include <log/log.h>
 
-namespace android {
-namespace hardware {
-namespace gnss {
-namespace V2_1 {
-namespace implementation {
+namespace android::hardware::gnss::V2_1::implementation {
 
 // Methods from ::android::hardware::gnss::V1_0::IGnssConfiguration follow.
 Return<bool> GnssConfiguration::setSuplEs(bool enable) {
@@ -99,8 +95,4 @@
     return (mBlacklistedSourceSet.find(source) != mBlacklistedSourceSet.end());
 }
 
-}  // namespace implementation
-}  // namespace V2_1
-}  // namespace gnss
-}  // namespace hardware
-}  // namespace android
\ No newline at end of file
+}  // namespace android::hardware::gnss::V2_1::implementation
diff --git a/gnss/2.1/default/GnssDebug.cpp b/gnss/common/utils/default/v2_1/GnssDebug.cpp
similarity index 87%
rename from gnss/2.1/default/GnssDebug.cpp
rename to gnss/common/utils/default/v2_1/GnssDebug.cpp
index a9f7ded..492b970 100644
--- a/gnss/2.1/default/GnssDebug.cpp
+++ b/gnss/common/utils/default/v2_1/GnssDebug.cpp
@@ -19,15 +19,11 @@
 #include <log/log.h>
 
 #include "Constants.h"
-#include "GnssDebug.h"
+#include "v2_1/GnssDebug.h"
 
 using namespace ::android::hardware::gnss::common;
 
-namespace android {
-namespace hardware {
-namespace gnss {
-namespace V1_1 {
-namespace implementation {
+namespace android::hardware::gnss::V1_1::implementation {
 
 // Methods from ::android::hardware::gnss::V1_0::IGnssDebug follow.
 Return<void> GnssDebug::getDebugData(V1_0::IGnssDebug::getDebugData_cb _hidl_cb) {
@@ -55,8 +51,4 @@
     return Void();
 }
 
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace gnss
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::gnss::V1_1::implementation
diff --git a/gnss/2.1/default/GnssMeasurement.cpp b/gnss/common/utils/default/v2_1/GnssMeasurement.cpp
similarity index 94%
rename from gnss/2.1/default/GnssMeasurement.cpp
rename to gnss/common/utils/default/v2_1/GnssMeasurement.cpp
index 63bbc0a..7d3a002 100644
--- a/gnss/2.1/default/GnssMeasurement.cpp
+++ b/gnss/common/utils/default/v2_1/GnssMeasurement.cpp
@@ -16,19 +16,14 @@
 
 #define LOG_TAG "GnssMeasurement"
 
-#include "GnssMeasurement.h"
+#include "v2_1/GnssMeasurement.h"
 #include <log/log.h>
 #include "Utils.h"
 
-namespace android {
-namespace hardware {
-namespace gnss {
+namespace android::hardware::gnss::V2_1::implementation {
 
 using common::Utils;
 
-namespace V2_1 {
-namespace implementation {
-
 sp<V2_1::IGnssMeasurementCallback> GnssMeasurement::sCallback_2_1 = nullptr;
 sp<V2_0::IGnssMeasurementCallback> GnssMeasurement::sCallback_2_0 = nullptr;
 
@@ -145,8 +140,4 @@
     }
 }
 
-}  // namespace implementation
-}  // namespace V2_1
-}  // namespace gnss
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::gnss::V2_1::implementation
diff --git a/gnss/2.1/default/GnssMeasurementCorrections.cpp b/gnss/common/utils/default/v2_1/GnssMeasurementCorrections.cpp
similarity index 93%
rename from gnss/2.1/default/GnssMeasurementCorrections.cpp
rename to gnss/common/utils/default/v2_1/GnssMeasurementCorrections.cpp
index accf62b..9be7e23 100644
--- a/gnss/2.1/default/GnssMeasurementCorrections.cpp
+++ b/gnss/common/utils/default/v2_1/GnssMeasurementCorrections.cpp
@@ -16,15 +16,14 @@
 
 #define LOG_TAG "GnssMeasurementCorrections"
 
-#include "GnssMeasurementCorrections.h"
+#include "v2_1/GnssMeasurementCorrections.h"
 #include <log/log.h>
 
-namespace android {
-namespace hardware {
-namespace gnss {
-namespace measurement_corrections {
-namespace V1_1 {
-namespace implementation {
+namespace android::hardware::gnss::measurement_corrections::V1_1::implementation {
+
+GnssMeasurementCorrections::GnssMeasurementCorrections() {}
+
+GnssMeasurementCorrections::~GnssMeasurementCorrections() {}
 
 // Methods from V1_0::IMeasurementCorrections follow.
 Return<bool> GnssMeasurementCorrections::setCorrections(
@@ -101,9 +100,4 @@
     return true;
 }
 
-}  // namespace implementation
-}  // namespace V1_1
-}  // namespace measurement_corrections
-}  // namespace gnss
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::gnss::measurement_corrections::V1_1::implementation
diff --git a/gnss/common/utils/vts/Android.bp b/gnss/common/utils/vts/Android.bp
index fd9613b..e36b656 100644
--- a/gnss/common/utils/vts/Android.bp
+++ b/gnss/common/utils/vts/Android.bp
@@ -25,10 +25,14 @@
     ],
     srcs: [
         "Utils.cpp",
+        "v2_1/GnssCallback.cpp",
     ],
     export_include_dirs: ["include"],
     shared_libs: [
         "android.hardware.gnss@1.0",
+        "android.hardware.gnss@1.1",
+        "android.hardware.gnss@2.0",
+        "android.hardware.gnss@2.1",
         "android.hardware.gnss.measurement_corrections@1.0",
         "android.hardware.gnss.measurement_corrections@1.1",
     ],
diff --git a/gnss/common/utils/vts/Utils.cpp b/gnss/common/utils/vts/Utils.cpp
index 4b5a50f..9bf68e6 100644
--- a/gnss/common/utils/vts/Utils.cpp
+++ b/gnss/common/utils/vts/Utils.cpp
@@ -169,6 +169,31 @@
     return mockCorrections_1_1;
 }
 
+/*
+ * MapConstellationType:
+ * Given a GnssConstellationType_2_0 type constellation, maps to its equivalent
+ * 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) {
+    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;
+        default:
+            return GnssConstellationType_1_0::UNKNOWN;
+    }
+}
+
 }  // namespace common
 }  // namespace gnss
 }  // namespace hardware
diff --git a/gnss/common/utils/vts/include/Utils.h b/gnss/common/utils/vts/include/Utils.h
index c3cdd18..9c838b2 100644
--- a/gnss/common/utils/vts/include/Utils.h
+++ b/gnss/common/utils/vts/include/Utils.h
@@ -18,9 +18,12 @@
 #define android_hardware_gnss_common_vts_Utils_H_
 
 #include <android/hardware/gnss/1.0/IGnss.h>
+#include <android/hardware/gnss/2.0/IGnss.h>
 #include <android/hardware/gnss/measurement_corrections/1.0/IMeasurementCorrections.h>
 #include <android/hardware/gnss/measurement_corrections/1.1/IMeasurementCorrections.h>
 
+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;
 
@@ -44,6 +47,8 @@
                               bool check_more_accuracies);
     static const MeasurementCorrections_1_0 getMockMeasurementCorrections();
     static const MeasurementCorrections_1_1 getMockMeasurementCorrections_1_1();
+
+    static GnssConstellationType_1_0 mapConstellationType(GnssConstellationType_2_0 constellation);
 };
 
 }  // namespace common
diff --git a/gnss/common/utils/vts/include/v2_1/GnssCallback.h b/gnss/common/utils/vts/include/v2_1/GnssCallback.h
new file mode 100644
index 0000000..ab1375d
--- /dev/null
+++ b/gnss/common/utils/vts/include/v2_1/GnssCallback.h
@@ -0,0 +1,107 @@
+/*
+ * 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/gnss/2.1/IGnss.h>
+#include "GnssCallbackEventQueue.h"
+
+#include <gtest/gtest.h>
+
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+
+using android::hardware::gnss::common::GnssCallbackEventQueue;
+using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback;
+using android::hardware::gnss::V1_0::GnssLocationFlags;
+using android::hardware::gnss::V2_0::GnssConstellationType;
+
+using GnssLocation_1_0 = android::hardware::gnss::V1_0::GnssLocation;
+using GnssLocation_2_0 = android::hardware::gnss::V2_0::GnssLocation;
+
+using IGnssCallback_1_0 = android::hardware::gnss::V1_0::IGnssCallback;
+using IGnssCallback_2_0 = android::hardware::gnss::V2_0::IGnssCallback;
+using IGnssCallback_2_1 = android::hardware::gnss::V2_1::IGnssCallback;
+
+using IGnssMeasurementCallback_1_0 = android::hardware::gnss::V1_0::IGnssMeasurementCallback;
+using IGnssMeasurementCallback_1_1 = android::hardware::gnss::V1_1::IGnssMeasurementCallback;
+using IGnssMeasurementCallback_2_0 = android::hardware::gnss::V2_0::IGnssMeasurementCallback;
+using IGnssMeasurementCallback_2_1 = android::hardware::gnss::V2_1::IGnssMeasurementCallback;
+
+using android::sp;
+
+#define TIMEOUT_SEC 2  // for basic commands/responses
+
+namespace android::hardware::gnss::common {
+
+/* Callback class for data & Event. */
+class GnssCallback : public IGnssCallback_2_1 {
+  public:
+    IGnssCallback_1_0::GnssSystemInfo last_info_;
+    android::hardware::hidl_string last_name_;
+    uint32_t last_capabilities_;
+    GnssLocation_2_0 last_location_;
+
+    GnssCallbackEventQueue<IGnssCallback_1_0::GnssSystemInfo> info_cbq_;
+    GnssCallbackEventQueue<android::hardware::hidl_string> name_cbq_;
+    GnssCallbackEventQueue<uint32_t> capabilities_cbq_;
+    GnssCallbackEventQueue<GnssLocation_2_0> location_cbq_;
+    GnssCallbackEventQueue<hidl_vec<IGnssCallback_2_1::GnssSvInfo>> sv_info_list_cbq_;
+
+    GnssCallback();
+    virtual ~GnssCallback() = default;
+
+    // Dummy callback handlers
+    Return<void> gnssStatusCb(const IGnssCallback_1_0::GnssStatusValue /* status */) override {
+        return Void();
+    }
+    Return<void> gnssNmeaCb(int64_t /* timestamp */,
+                            const android::hardware::hidl_string& /* nmea */) override {
+        return Void();
+    }
+    Return<void> gnssAcquireWakelockCb() override { return Void(); }
+    Return<void> gnssReleaseWakelockCb() override { return Void(); }
+    Return<void> gnssRequestLocationCb(bool /* independentFromGnss */) override { return Void(); }
+    Return<void> gnssRequestTimeCb() override { return Void(); }
+    // Actual (test) callback handlers
+    Return<void> gnssNameCb(const android::hardware::hidl_string& name) override;
+    Return<void> gnssLocationCb(const GnssLocation_1_0& location) override;
+    Return<void> gnssSetCapabilitesCb(uint32_t capabilities) override;
+    Return<void> gnssSetSystemInfoCb(const IGnssCallback_1_0::GnssSystemInfo& info) override;
+    Return<void> gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus& svStatus) override;
+
+    // New in v2.0
+    Return<void> gnssLocationCb_2_0(const GnssLocation_2_0& location) override;
+    Return<void> gnssRequestLocationCb_2_0(bool /* independentFromGnss */,
+                                           bool /* isUserEmergency */) override {
+        return Void();
+    }
+    Return<void> gnssSetCapabilitiesCb_2_0(uint32_t capabilities) override;
+    Return<void> gnssSvStatusCb_2_0(const hidl_vec<IGnssCallback_2_0::GnssSvInfo>&) override {
+        return Void();
+    }
+
+    // New in v2.1
+    Return<void> gnssSvStatusCb_2_1(
+            const hidl_vec<IGnssCallback_2_1::GnssSvInfo>& svInfoList) override;
+    Return<void> gnssSetCapabilitiesCb_2_1(uint32_t capabilities) override;
+
+  private:
+    Return<void> gnssLocationCbImpl(const GnssLocation_2_0& location);
+};
+
+}  // namespace android::hardware::gnss::common
diff --git a/gnss/common/utils/vts/include/v2_1/gnss_hal_test_template.h b/gnss/common/utils/vts/include/v2_1/gnss_hal_test_template.h
new file mode 100644
index 0000000..d057c61
--- /dev/null
+++ b/gnss/common/utils/vts/include/v2_1/gnss_hal_test_template.h
@@ -0,0 +1,381 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "GnssCallbackEventQueue.h"
+#include "Utils.h"
+#include "v2_1/GnssCallback.h"
+
+#include <gtest/gtest.h>
+#include <chrono>
+
+using ::android::hardware::gnss::common::Utils;
+
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+
+using android::hardware::gnss::common::GnssCallback;
+using android::hardware::gnss::common::GnssCallbackEventQueue;
+using android::hardware::gnss::measurement_corrections::V1_0::IMeasurementCorrectionsCallback;
+using android::hardware::gnss::V1_0::GnssLocationFlags;
+using android::hardware::gnss::V2_0::GnssConstellationType;
+using android::hardware::gnss::V2_1::IGnssAntennaInfo;
+using android::hardware::gnss::V2_1::IGnssAntennaInfoCallback;
+
+using GnssLocation_1_0 = android::hardware::gnss::V1_0::GnssLocation;
+using GnssLocation_2_0 = android::hardware::gnss::V2_0::GnssLocation;
+
+using IGnssCallback_1_0 = android::hardware::gnss::V1_0::IGnssCallback;
+using IGnssCallback_2_0 = android::hardware::gnss::V2_0::IGnssCallback;
+using IGnssCallback_2_1 = android::hardware::gnss::V2_1::IGnssCallback;
+
+using IGnssMeasurementCallback_1_0 = android::hardware::gnss::V1_0::IGnssMeasurementCallback;
+using IGnssMeasurementCallback_1_1 = android::hardware::gnss::V1_1::IGnssMeasurementCallback;
+using IGnssMeasurementCallback_2_0 = android::hardware::gnss::V2_0::IGnssMeasurementCallback;
+using IGnssMeasurementCallback_2_1 = android::hardware::gnss::V2_1::IGnssMeasurementCallback;
+
+using android::sp;
+
+#define TIMEOUT_SEC 2  // for basic commands/responses
+
+// The main test class for GNSS HAL.
+template <class T_IGnss>
+class GnssHalTestTemplate : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override;
+
+    virtual void TearDown() override;
+
+    /* Callback class for GnssMeasurement. */
+    class GnssMeasurementCallback : public IGnssMeasurementCallback_2_1 {
+      public:
+        GnssCallbackEventQueue<IGnssMeasurementCallback_2_1::GnssData> measurement_cbq_;
+
+        GnssMeasurementCallback() : measurement_cbq_("measurement"){};
+        virtual ~GnssMeasurementCallback() = default;
+
+        // Methods from V1_0::IGnssMeasurementCallback follow.
+        Return<void> GnssMeasurementCb(const IGnssMeasurementCallback_1_0::GnssData&) override {
+            return Void();
+        }
+
+        // Methods from V1_1::IGnssMeasurementCallback follow.
+        Return<void> gnssMeasurementCb(const IGnssMeasurementCallback_1_1::GnssData&) override {
+            return Void();
+        }
+
+        // Methods from V2_0::IGnssMeasurementCallback follow.
+        Return<void> gnssMeasurementCb_2_0(const IGnssMeasurementCallback_2_0::GnssData&) override {
+            return Void();
+        }
+
+        // Methods from V2_1::IGnssMeasurementCallback follow.
+        Return<void> gnssMeasurementCb_2_1(const IGnssMeasurementCallback_2_1::GnssData&) override;
+    };
+
+    /* Callback class for GnssMeasurementCorrections. */
+    class GnssMeasurementCorrectionsCallback : public IMeasurementCorrectionsCallback {
+      public:
+        uint32_t last_capabilities_;
+        GnssCallbackEventQueue<uint32_t> capabilities_cbq_;
+
+        GnssMeasurementCorrectionsCallback() : capabilities_cbq_("capabilities"){};
+        virtual ~GnssMeasurementCorrectionsCallback() = default;
+
+        // Methods from V1_0::IMeasurementCorrectionsCallback follow.
+        Return<void> setCapabilitiesCb(uint32_t capabilities) override;
+    };
+
+    /* Callback class for GnssAntennaInfo. */
+    class GnssAntennaInfoCallback : public IGnssAntennaInfoCallback {
+      public:
+        GnssCallbackEventQueue<hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>>
+                antenna_info_cbq_;
+
+        GnssAntennaInfoCallback() : antenna_info_cbq_("info"){};
+        virtual ~GnssAntennaInfoCallback() = default;
+
+        // Methods from V2_1::GnssAntennaInfoCallback follow.
+        Return<void> gnssAntennaInfoCb(
+                const hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos);
+    };
+
+    /*
+     * SetUpGnssCallback:
+     *   Set GnssCallback and verify the result.
+     */
+    void SetUpGnssCallback();
+
+    /*
+     * StartAndCheckFirstLocation:
+     *   Helper function to start location, and check the first one.
+     *
+     *   <p> Note this leaves the Location request active, to enable Stop call vs. other call
+     *   reordering tests.
+     *
+     * returns  true if a location was successfully generated
+     */
+    bool StartAndCheckFirstLocation();
+
+    /*
+     * CheckLocation:
+     *   Helper function to vet Location fields
+     *
+     *   check_speed: true if speed related fields are also verified.
+     */
+    void CheckLocation(const GnssLocation_2_0& location, const bool check_speed);
+
+    /*
+     * StartAndCheckLocations:
+     *   Helper function to collect, and check a number of
+     *   normal ~1Hz locations.
+     *
+     *   Note this leaves the Location request active, to enable Stop call vs. other call
+     *   reordering tests.
+     */
+    void StartAndCheckLocations(int count);
+
+    /*
+     * StopAndClearLocations:
+     * Helper function to stop locations, and clear any remaining notifications
+     */
+    void StopAndClearLocations();
+
+    /*
+     * SetPositionMode:
+     * Helper function to set positioning mode and verify output
+     */
+    void SetPositionMode(const int min_interval_msec, const bool low_power_mode);
+
+    /*
+     * startLocationAndGetNonGpsConstellation:
+     * 1. Start location
+     * 2. Find and return first non-GPS constellation
+     *
+     * Note that location is not stopped in this method. The client should call
+     * StopAndClearLocations() after the call.
+     */
+    GnssConstellationType startLocationAndGetNonGpsConstellation(
+            const int locations_to_await, const int gnss_sv_info_list_timeout);
+
+    sp<T_IGnss> gnss_hal_;      // GNSS HAL to call into
+    sp<GnssCallback> gnss_cb_;  // Primary callback interface
+};
+
+using ::android::hardware::gnss::common::Utils;
+
+// Implementations for the main test class for GNSS HAL
+template <class T_IGnss>
+void GnssHalTestTemplate<T_IGnss>::SetUp() {
+    gnss_hal_ = T_IGnss::getService(GetParam());
+    ASSERT_NE(gnss_hal_, nullptr);
+
+    SetUpGnssCallback();
+}
+
+template <class T_IGnss>
+void GnssHalTestTemplate<T_IGnss>::TearDown() {
+    if (gnss_hal_ != nullptr) {
+        gnss_hal_->cleanup();
+        gnss_hal_ = nullptr;
+    }
+
+    // Set to nullptr to destruct the callback event queues and warn of any unprocessed events.
+    gnss_cb_ = nullptr;
+}
+
+template <class T_IGnss>
+void GnssHalTestTemplate<T_IGnss>::SetUpGnssCallback() {
+    gnss_cb_ = new GnssCallback();
+    ASSERT_NE(gnss_cb_, nullptr);
+
+    auto result = gnss_hal_->setCallback_2_1(gnss_cb_);
+    if (!result.isOk()) {
+        ALOGE("result of failed setCallback %s", result.description().c_str());
+    }
+
+    ASSERT_TRUE(result.isOk());
+    ASSERT_TRUE(result);
+
+    /*
+     * All capabilities, name and systemInfo callbacks should trigger
+     */
+    EXPECT_TRUE(gnss_cb_->capabilities_cbq_.retrieve(gnss_cb_->last_capabilities_, TIMEOUT_SEC));
+    EXPECT_TRUE(gnss_cb_->info_cbq_.retrieve(gnss_cb_->last_info_, TIMEOUT_SEC));
+    EXPECT_TRUE(gnss_cb_->name_cbq_.retrieve(gnss_cb_->last_name_, TIMEOUT_SEC));
+
+    EXPECT_EQ(gnss_cb_->capabilities_cbq_.calledCount(), 1);
+    EXPECT_EQ(gnss_cb_->info_cbq_.calledCount(), 1);
+    EXPECT_EQ(gnss_cb_->name_cbq_.calledCount(), 1);
+}
+
+template <class T_IGnss>
+void GnssHalTestTemplate<T_IGnss>::StopAndClearLocations() {
+    const auto result = gnss_hal_->stop();
+
+    EXPECT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+
+    /*
+     * Clear notify/waiting counter, allowing up till the timeout after
+     * the last reply for final startup messages to arrive (esp. system
+     * info.)
+     */
+    while (gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_, TIMEOUT_SEC)) {
+    }
+    gnss_cb_->location_cbq_.reset();
+}
+
+template <class T_IGnss>
+void GnssHalTestTemplate<T_IGnss>::SetPositionMode(const int min_interval_msec,
+                                                   const bool low_power_mode) {
+    const int kPreferredAccuracy = 0;  // Ideally perfect (matches GnssLocationProvider)
+    const int kPreferredTimeMsec = 0;  // Ideally immediate
+
+    const auto result = gnss_hal_->setPositionMode_1_1(
+            T_IGnss::GnssPositionMode::MS_BASED,
+            T_IGnss::GnssPositionRecurrence::RECURRENCE_PERIODIC, min_interval_msec,
+            kPreferredAccuracy, kPreferredTimeMsec, low_power_mode);
+
+    ASSERT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+}
+
+template <class T_IGnss>
+bool GnssHalTestTemplate<T_IGnss>::StartAndCheckFirstLocation() {
+    const auto result = gnss_hal_->start();
+
+    EXPECT_TRUE(result.isOk());
+    EXPECT_TRUE(result);
+
+    /*
+     * GnssLocationProvider support of AGPS SUPL & XtraDownloader is not available in VTS,
+     * so allow time to demodulate ephemeris over the air.
+     */
+    const int kFirstGnssLocationTimeoutSeconds = 75;
+
+    EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_,
+                                                 kFirstGnssLocationTimeoutSeconds));
+    int locationCalledCount = gnss_cb_->location_cbq_.calledCount();
+    EXPECT_EQ(locationCalledCount, 1);
+
+    if (locationCalledCount > 0) {
+        // don't require speed on first fix
+        CheckLocation(gnss_cb_->last_location_, false);
+        return true;
+    }
+    return false;
+}
+
+template <class T_IGnss>
+void GnssHalTestTemplate<T_IGnss>::CheckLocation(const GnssLocation_2_0& location,
+                                                 bool check_speed) {
+    const bool check_more_accuracies =
+            (gnss_cb_->info_cbq_.calledCount() > 0 && gnss_cb_->last_info_.yearOfHw >= 2017);
+
+    Utils::checkLocation(location.v1_0, check_speed, check_more_accuracies);
+}
+
+template <class T_IGnss>
+void GnssHalTestTemplate<T_IGnss>::StartAndCheckLocations(int count) {
+    const int kMinIntervalMsec = 500;
+    const int kLocationTimeoutSubsequentSec = 2;
+    const bool kLowPowerMode = false;
+
+    SetPositionMode(kMinIntervalMsec, kLowPowerMode);
+
+    EXPECT_TRUE(StartAndCheckFirstLocation());
+
+    for (int i = 1; i < count; i++) {
+        EXPECT_TRUE(gnss_cb_->location_cbq_.retrieve(gnss_cb_->last_location_,
+                                                     kLocationTimeoutSubsequentSec));
+        int locationCalledCount = gnss_cb_->location_cbq_.calledCount();
+        EXPECT_EQ(locationCalledCount, i + 1);
+        // Don't cause confusion by checking details if no location yet
+        if (locationCalledCount > 0) {
+            // Should be more than 1 location by now, but if not, still don't check first fix speed
+            CheckLocation(gnss_cb_->last_location_, locationCalledCount > 1);
+        }
+    }
+}
+
+template <class T_IGnss>
+GnssConstellationType GnssHalTestTemplate<T_IGnss>::startLocationAndGetNonGpsConstellation(
+        const int locations_to_await, const int gnss_sv_info_list_timeout) {
+    gnss_cb_->location_cbq_.reset();
+    StartAndCheckLocations(locations_to_await);
+    const int location_called_count = gnss_cb_->location_cbq_.calledCount();
+
+    // Tolerate 1 less sv status to handle edge cases in reporting.
+    int sv_info_list_cbq_size = gnss_cb_->sv_info_list_cbq_.size();
+    EXPECT_GE(sv_info_list_cbq_size + 1, locations_to_await);
+    ALOGD("Observed %d GnssSvInfo, while awaiting %d Locations (%d received)",
+          sv_info_list_cbq_size, locations_to_await, location_called_count);
+
+    // Find first non-GPS constellation to blacklist
+    GnssConstellationType constellation_to_blacklist = GnssConstellationType::UNKNOWN;
+    for (int i = 0; i < sv_info_list_cbq_size; ++i) {
+        hidl_vec<IGnssCallback_2_1::GnssSvInfo> sv_info_vec;
+        gnss_cb_->sv_info_list_cbq_.retrieve(sv_info_vec, gnss_sv_info_list_timeout);
+        for (uint32_t iSv = 0; iSv < sv_info_vec.size(); iSv++) {
+            const auto& gnss_sv = sv_info_vec[iSv];
+            if ((gnss_sv.v2_0.v1_0.svFlag & IGnssCallback_1_0::GnssSvFlags::USED_IN_FIX) &&
+                (gnss_sv.v2_0.constellation != GnssConstellationType::UNKNOWN) &&
+                (gnss_sv.v2_0.constellation != GnssConstellationType::GPS)) {
+                // found a non-GPS constellation
+                constellation_to_blacklist = gnss_sv.v2_0.constellation;
+                break;
+            }
+        }
+        if (constellation_to_blacklist != GnssConstellationType::UNKNOWN) {
+            break;
+        }
+    }
+
+    if (constellation_to_blacklist == GnssConstellationType::UNKNOWN) {
+        ALOGI("No non-GPS constellations found, constellation blacklist test less effective.");
+        // Proceed functionally to blacklist something.
+        constellation_to_blacklist = GnssConstellationType::GLONASS;
+    }
+
+    return constellation_to_blacklist;
+}
+
+template <class T_IGnss>
+Return<void> GnssHalTestTemplate<T_IGnss>::GnssMeasurementCallback::gnssMeasurementCb_2_1(
+        const IGnssMeasurementCallback_2_1::GnssData& data) {
+    ALOGD("GnssMeasurement v2.1 received. Size = %d", (int)data.measurements.size());
+    measurement_cbq_.store(data);
+    return Void();
+}
+
+template <class T_IGnss>
+Return<void> GnssHalTestTemplate<T_IGnss>::GnssMeasurementCorrectionsCallback::setCapabilitiesCb(
+        uint32_t capabilities) {
+    ALOGI("GnssMeasurementCorrectionsCallback capabilities received %d", capabilities);
+    capabilities_cbq_.store(capabilities);
+    return Void();
+}
+
+template <class T_IGnss>
+Return<void> GnssHalTestTemplate<T_IGnss>::GnssAntennaInfoCallback::gnssAntennaInfoCb(
+        const hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos) {
+    ALOGD("GnssAntennaInfo v2.1 received. Size = %d", (int)gnssAntennaInfos.size());
+    antenna_info_cbq_.store(gnssAntennaInfos);
+    return Void();
+}
diff --git a/gnss/common/utils/vts/v2_1/GnssCallback.cpp b/gnss/common/utils/vts/v2_1/GnssCallback.cpp
new file mode 100644
index 0000000..3b96fb8
--- /dev/null
+++ b/gnss/common/utils/vts/v2_1/GnssCallback.cpp
@@ -0,0 +1,95 @@
+/*
+ * 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 "GnssCallback"
+
+#include "v2_1/GnssCallback.h"
+#include <chrono>
+#include "Utils.h"
+
+#include <gtest/gtest.h>
+
+using ::android::hardware::gnss::common::Utils;
+
+namespace android::hardware::gnss::common {
+
+GnssCallback::GnssCallback()
+    : info_cbq_("system_info"),
+      name_cbq_("name"),
+      capabilities_cbq_("capabilities"),
+      location_cbq_("location"),
+      sv_info_list_cbq_("sv_info") {}
+
+Return<void> GnssCallback::gnssSetSystemInfoCb(const IGnssCallback_1_0::GnssSystemInfo& info) {
+    ALOGI("Info received, year %d", info.yearOfHw);
+    info_cbq_.store(info);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssSetCapabilitesCb(uint32_t capabilities) {
+    ALOGI("Capabilities received %d", capabilities);
+    capabilities_cbq_.store(capabilities);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssSetCapabilitiesCb_2_0(uint32_t capabilities) {
+    ALOGI("Capabilities (v2.0) received %d", capabilities);
+    capabilities_cbq_.store(capabilities);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssSetCapabilitiesCb_2_1(uint32_t capabilities) {
+    ALOGI("Capabilities (v2.1) received %d", capabilities);
+    capabilities_cbq_.store(capabilities);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssNameCb(const android::hardware::hidl_string& name) {
+    ALOGI("Name received: %s", name.c_str());
+    name_cbq_.store(name);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssLocationCb(const GnssLocation_1_0& location) {
+    ALOGI("Location received");
+    GnssLocation_2_0 location_v2_0;
+    location_v2_0.v1_0 = location;
+    return gnssLocationCbImpl(location_v2_0);
+}
+
+Return<void> GnssCallback::gnssLocationCb_2_0(const GnssLocation_2_0& location) {
+    ALOGI("Location (v2.0) received");
+    return gnssLocationCbImpl(location);
+}
+
+Return<void> GnssCallback::gnssLocationCbImpl(const GnssLocation_2_0& location) {
+    location_cbq_.store(location);
+    return Void();
+}
+
+Return<void> GnssCallback::gnssSvStatusCb(const IGnssCallback_1_0::GnssSvStatus&) {
+    ALOGI("gnssSvStatusCb");
+    return Void();
+}
+
+Return<void> GnssCallback::gnssSvStatusCb_2_1(
+        const hidl_vec<IGnssCallback::GnssSvInfo>& svInfoList) {
+    ALOGI("gnssSvStatusCb_2_1. Size = %d", (int)svInfoList.size());
+    sv_info_list_cbq_.store(svInfoList);
+    return Void();
+}
+
+}  // namespace android::hardware::gnss::common
diff --git a/gnss/measurement_corrections/1.0/Android.bp b/gnss/measurement_corrections/1.0/Android.bp
index 837cc7a..a140674 100644
--- a/gnss/measurement_corrections/1.0/Android.bp
+++ b/gnss/measurement_corrections/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.gnss.measurement_corrections@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IMeasurementCorrections.hal",
diff --git a/gnss/measurement_corrections/1.1/Android.bp b/gnss/measurement_corrections/1.1/Android.bp
index d279af6..9363848 100644
--- a/gnss/measurement_corrections/1.1/Android.bp
+++ b/gnss/measurement_corrections/1.1/Android.bp
@@ -3,17 +3,14 @@
 hidl_interface {
     name: "android.hardware.gnss.measurement_corrections@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IMeasurementCorrections.hal",
     ],
     interfaces: [
         "android.hardware.gnss.measurement_corrections@1.0",
-        "android.hardware.gnss@2.0",
         "android.hardware.gnss@1.0",
+        "android.hardware.gnss@2.0",
         "android.hidl.base@1.0",
     ],
     gen_java: true,
diff --git a/gnss/visibility_control/1.0/Android.bp b/gnss/visibility_control/1.0/Android.bp
index e58e932..975da78 100644
--- a/gnss/visibility_control/1.0/Android.bp
+++ b/gnss/visibility_control/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.gnss.visibility_control@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "IGnssVisibilityControl.hal",
         "IGnssVisibilityControlCallback.hal",
diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp
index c089a76..e594233 100644
--- a/graphics/common/aidl/Android.bp
+++ b/graphics/common/aidl/Android.bp
@@ -20,6 +20,13 @@
         cpp: {
             enabled: false,
         },
+        ndk: {
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.media.swcodec",
+            ],
+            min_sdk_version: "29",
+        },
     },
     versions: ["1"],
 }
diff --git a/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl b/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl
index ccb0690..b329cb2 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/PlaneLayout.aidl
@@ -100,10 +100,11 @@
     long totalSizeInBytes;
 
     /**
-     * Horizontal and vertical subsampling. Must be a positive power of 2.
+     * Horizontal and vertical subsampling. Must be a positive power of 2. A value of 1
+     * indicates no subsampling.
      *
      * These fields indicate the number of horizontally or vertically adjacent pixels that use
-     * the same pixel data. A value of 1 indicates no subsampling.
+     * the same pixel data.
      */
     long horizontalSubsampling;
     long verticalSubsampling;
diff --git a/graphics/composer/2.1/Android.bp b/graphics/composer/2.1/Android.bp
index 4e4b81c..2358a8f 100644
--- a/graphics/composer/2.1/Android.bp
+++ b/graphics/composer/2.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.graphics.composer@2.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IComposer.hal",
diff --git a/graphics/composer/2.1/vts/functional/Android.bp b/graphics/composer/2.1/vts/functional/Android.bp
index dafbbf9..e137afb 100644
--- a/graphics/composer/2.1/vts/functional/Android.bp
+++ b/graphics/composer/2.1/vts/functional/Android.bp
@@ -23,6 +23,10 @@
     shared_libs: [
         "libfmq",
         "libsync",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@2.1",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.mapper@4.0",
     ],
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
@@ -30,13 +34,9 @@
         "android.hardware.graphics.allocator@4.0",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.1-vts",
-        "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.0-vts",
-        "android.hardware.graphics.mapper@2.1",
         "android.hardware.graphics.mapper@2.1-vts",
-        "android.hardware.graphics.mapper@3.0",
         "android.hardware.graphics.mapper@3.0-vts",
-        "android.hardware.graphics.mapper@4.0",
         "android.hardware.graphics.mapper@4.0-vts",
     ],
     header_libs: [
diff --git a/graphics/composer/2.2/Android.bp b/graphics/composer/2.2/Android.bp
index 930cadc..234b9ac 100644
--- a/graphics/composer/2.2/Android.bp
+++ b/graphics/composer/2.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.graphics.composer@2.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "IComposer.hal",
         "IComposerClient.hal",
diff --git a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
index c78c358..3becace 100644
--- a/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
+++ b/graphics/composer/2.2/utils/vts/RenderEngineVts.cpp
@@ -69,9 +69,8 @@
                    [](renderengine::LayerSettings& settings) -> renderengine::LayerSettings* {
                        return &settings;
                    });
-    mRenderEngine->drawLayers(mDisplaySettings, compositionLayerPointers,
-                              mGraphicBuffer->getNativeBuffer(), true, std::move(bufferFence),
-                              &readyFence);
+    mRenderEngine->drawLayers(mDisplaySettings, compositionLayerPointers, mGraphicBuffer, true,
+                              std::move(bufferFence), &readyFence);
     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 e1a254d..d80845f 100644
--- a/graphics/composer/2.2/vts/functional/Android.bp
+++ b/graphics/composer/2.2/vts/functional/Android.bp
@@ -33,6 +33,10 @@
         "libprocessgroup",
         "libsync",
         "libui",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@2.1",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.mapper@4.0",
     ],
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
@@ -43,13 +47,9 @@
         "android.hardware.graphics.composer@2.1-vts",
         "android.hardware.graphics.composer@2.2",
         "android.hardware.graphics.composer@2.2-vts",
-        "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.0-vts",
-        "android.hardware.graphics.mapper@2.1",
         "android.hardware.graphics.mapper@2.1-vts",
-        "android.hardware.graphics.mapper@3.0",
         "android.hardware.graphics.mapper@3.0-vts",
-        "android.hardware.graphics.mapper@4.0",
         "android.hardware.graphics.mapper@4.0-vts",
         "libgtest",
         "librenderengine",
diff --git a/graphics/composer/2.3/Android.bp b/graphics/composer/2.3/Android.bp
index a777556..96f301c 100644
--- a/graphics/composer/2.3/Android.bp
+++ b/graphics/composer/2.3/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.graphics.composer@2.3",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "IComposer.hal",
         "IComposerClient.hal",
diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp
index 18ea2aa..1ab6b3b 100644
--- a/graphics/composer/2.3/vts/functional/Android.bp
+++ b/graphics/composer/2.3/vts/functional/Android.bp
@@ -24,6 +24,10 @@
         "libfmq",
         "libhidlbase",
         "libsync",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@2.1",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.mapper@4.0",
     ],
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
@@ -35,13 +39,9 @@
         "android.hardware.graphics.composer@2.2-vts",
         "android.hardware.graphics.composer@2.3",
         "android.hardware.graphics.composer@2.3-vts",
-        "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.0-vts",
-        "android.hardware.graphics.mapper@2.1",
         "android.hardware.graphics.mapper@2.1-vts",
-        "android.hardware.graphics.mapper@3.0",
         "android.hardware.graphics.mapper@3.0-vts",
-        "android.hardware.graphics.mapper@4.0",
         "android.hardware.graphics.mapper@4.0-vts",
     ],
     header_libs: [
diff --git a/graphics/composer/2.4/Android.bp b/graphics/composer/2.4/Android.bp
index 5f700be..2bbe751 100644
--- a/graphics/composer/2.4/Android.bp
+++ b/graphics/composer/2.4/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.graphics.composer@2.4",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IComposer.hal",
diff --git a/graphics/composer/2.4/vts/functional/Android.bp b/graphics/composer/2.4/vts/functional/Android.bp
index 9e7cc46..d0209b7 100644
--- a/graphics/composer/2.4/vts/functional/Android.bp
+++ b/graphics/composer/2.4/vts/functional/Android.bp
@@ -23,6 +23,10 @@
     shared_libs: [
         "libfmq",
         "libsync",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@2.1",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.mapper@4.0",
     ],
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
@@ -36,13 +40,9 @@
         "android.hardware.graphics.composer@2.3-vts",
         "android.hardware.graphics.composer@2.4",
         "android.hardware.graphics.composer@2.4-vts",
-        "android.hardware.graphics.mapper@2.0",
         "android.hardware.graphics.mapper@2.0-vts",
-        "android.hardware.graphics.mapper@2.1",
         "android.hardware.graphics.mapper@2.1-vts",
-        "android.hardware.graphics.mapper@3.0",
         "android.hardware.graphics.mapper@3.0-vts",
-        "android.hardware.graphics.mapper@4.0",
         "android.hardware.graphics.mapper@4.0-vts",
     ],
     header_libs: [
diff --git a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
index 27b633a..f0de4f7 100644
--- a/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
+++ b/graphics/composer/2.4/vts/functional/VtsHalGraphicsComposerV2_4TargetTest.cpp
@@ -201,8 +201,12 @@
 
     void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
 
-    void Test_setActiveConfigWithConstraints(
-            const IComposerClient::VsyncPeriodChangeConstraints& constraints, bool refreshMiss);
+    struct TestParameters {
+        nsecs_t delayForChange;
+        bool refreshMiss;
+    };
+
+    void Test_setActiveConfigWithConstraints(const TestParameters& params);
 
     void sendRefreshFrame(const VsyncPeriodChangeTimeline*);
 
@@ -414,12 +418,9 @@
 
     mWriter->validateDisplay();
     execute();
-    if (mReader->mCompositionChanges.size() != 0) {
-        GTEST_SUCCEED() << "Composition change requested, skipping test";
-        return;
-    }
-
     ASSERT_EQ(0, mReader->mErrors.size());
+    mReader->mCompositionChanges.clear();
+
     mWriter->presentDisplay();
     execute();
     ASSERT_EQ(0, mReader->mErrors.size());
@@ -427,8 +428,14 @@
     mWriter->selectLayer(layer);
     auto handle2 = allocate();
     ASSERT_NE(nullptr, handle2);
+
     mWriter->setLayerBuffer(0, handle2, -1);
     mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, {0, 0, 10, 10}));
+    mWriter->validateDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mReader->mCompositionChanges.clear();
+
     mWriter->presentDisplay();
     execute();
 }
@@ -450,9 +457,7 @@
 }
 
 void GraphicsComposerHidlCommandTest::Test_setActiveConfigWithConstraints(
-        const IComposerClient::VsyncPeriodChangeConstraints& constraints, bool refreshMiss) {
-    VsyncPeriodChangeTimeline timeline = {};
-
+        const TestParameters& params) {
     for (Display display : mComposerCallback->getDisplays()) {
         forEachTwoConfigs(display, [&](Config config1, Config config2) {
             mComposerClient->setActiveConfig(display, config1);
@@ -467,6 +472,10 @@
                 return;  // continue
             }
 
+            VsyncPeriodChangeTimeline timeline;
+            IComposerClient::VsyncPeriodChangeConstraints constraints = {
+                    .desiredTimeNanos = systemTime() + params.delayForChange,
+                    .seamlessRequired = false};
             EXPECT_EQ(Error::NONE, mComposerClient->setActiveConfigWithConstraints(
                                            display, config2, constraints, &timeline));
 
@@ -477,7 +486,7 @@
                         kReasonableTimeForChange.count());
 
             if (timeline.refreshRequired) {
-                if (refreshMiss) {
+                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);
@@ -490,16 +499,16 @@
             // 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 newTimelime = mComposerCallback->takeLastVsyncPeriodChangeTimeline();
-            if (timeline.refreshRequired && refreshMiss) {
-                EXPECT_TRUE(newTimelime.has_value());
+            auto newTimeline = mComposerCallback->takeLastVsyncPeriodChangeTimeline();
+            if (timeline.refreshRequired && params.refreshMiss) {
+                EXPECT_TRUE(newTimeline.has_value());
             }
 
-            if (newTimelime.has_value()) {
-                if (timeline.refreshRequired) {
-                    sendRefreshFrame(&newTimelime.value());
+            if (newTimeline.has_value()) {
+                if (newTimeline->refreshRequired) {
+                    sendRefreshFrame(&newTimeline.value());
                 }
-                waitForVsyncPeriodChange(display, newTimelime.value(), constraints.desiredTimeNanos,
+                waitForVsyncPeriodChange(display, newTimeline.value(), constraints.desiredTimeNanos,
                                          vsyncPeriod1, vsyncPeriod2);
             }
 
@@ -512,28 +521,16 @@
 }
 
 TEST_P(GraphicsComposerHidlCommandTest, setActiveConfigWithConstraints) {
-    IComposerClient::VsyncPeriodChangeConstraints constraints;
-
-    constraints.seamlessRequired = false;
-    constraints.desiredTimeNanos = systemTime();
-    Test_setActiveConfigWithConstraints(constraints, false);
+    Test_setActiveConfigWithConstraints({.delayForChange = 0, .refreshMiss = false});
 }
 
 TEST_P(GraphicsComposerHidlCommandTest, setActiveConfigWithConstraints_Delayed) {
-    IComposerClient::VsyncPeriodChangeConstraints constraints;
-
-    constexpr nsecs_t kDelayForChange = 300'000'000;  // 300ms
-    constraints.seamlessRequired = false;
-    constraints.desiredTimeNanos = systemTime() + kDelayForChange;
-    Test_setActiveConfigWithConstraints(constraints, false);
+    Test_setActiveConfigWithConstraints({.delayForChange = 300'000'000,  // 300ms
+                                         .refreshMiss = false});
 }
 
 TEST_P(GraphicsComposerHidlCommandTest, setActiveConfigWithConstraints_MissRefresh) {
-    IComposerClient::VsyncPeriodChangeConstraints constraints;
-
-    constraints.seamlessRequired = false;
-    constraints.desiredTimeNanos = systemTime();
-    Test_setActiveConfigWithConstraints(constraints, true);
+    Test_setActiveConfigWithConstraints({.delayForChange = 0, .refreshMiss = true});
 }
 
 TEST_P(GraphicsComposerHidlTest, setAutoLowLatencyModeBadDisplay) {
diff --git a/graphics/mapper/4.0/utils/vts/MapperVts.cpp b/graphics/mapper/4.0/utils/vts/MapperVts.cpp
index cb90fa0..5b2a94e 100644
--- a/graphics/mapper/4.0/utils/vts/MapperVts.cpp
+++ b/graphics/mapper/4.0/utils/vts/MapperVts.cpp
@@ -71,7 +71,8 @@
     return mAllocator;
 }
 
-const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle) {
+const native_handle_t* Gralloc::cloneBuffer(const hidl_handle& rawHandle,
+                                            enum Tolerance /*tolerance*/) {
     const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
     EXPECT_NE(nullptr, bufferHandle);
 
@@ -84,39 +85,37 @@
 
 std::vector<const native_handle_t*> Gralloc::allocate(const BufferDescriptor& descriptor,
                                                       uint32_t count, bool import,
-                                                      bool allowFailure, uint32_t* outStride) {
+                                                      enum Tolerance tolerance,
+                                                      uint32_t* outStride) {
     std::vector<const native_handle_t*> bufferHandles;
     bufferHandles.reserve(count);
-    mAllocator->allocate(
-            descriptor, count,
-            [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
-                ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers";
-                ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array";
+    mAllocator->allocate(descriptor, count,
+                         [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
+                             if (canTolerate(tolerance, tmpError)) {
+                                 return;
+                             }
 
-                for (uint32_t i = 0; i < count; i++) {
-                    const native_handle_t* bufferHandle = nullptr;
-                    if (import) {
-                        if (allowFailure) {
-                            bufferHandle = importBuffer(tmpBuffers[i]);
-                        } else {
-                            ASSERT_NO_FATAL_FAILURE(bufferHandle = importBuffer(tmpBuffers[i]));
-                        }
-                    } else {
-                        if (allowFailure) {
-                            bufferHandle = cloneBuffer(tmpBuffers[i]);
-                        } else {
-                            ASSERT_NO_FATAL_FAILURE(bufferHandle = cloneBuffer(tmpBuffers[i]));
-                        }
-                    }
-                    if (bufferHandle) {
-                        bufferHandles.push_back(bufferHandle);
-                    }
-                }
+                             ASSERT_EQ(Error::NONE, tmpError) << "failed to allocate buffers";
+                             ASSERT_EQ(count, tmpBuffers.size()) << "invalid buffer array";
 
-                if (outStride) {
-                    *outStride = tmpStride;
-                }
-            });
+                             for (uint32_t i = 0; i < count; i++) {
+                                 const native_handle_t* bufferHandle = nullptr;
+                                 if (import) {
+                                     ASSERT_NO_FATAL_FAILURE(
+                                             bufferHandle = importBuffer(tmpBuffers[i], tolerance));
+                                 } else {
+                                     ASSERT_NO_FATAL_FAILURE(
+                                             bufferHandle = cloneBuffer(tmpBuffers[i], tolerance));
+                                 }
+                                 if (bufferHandle) {
+                                     bufferHandles.push_back(bufferHandle);
+                                 }
+                             }
+
+                             if (outStride) {
+                                 *outStride = tmpStride;
+                             }
+                         });
 
     if (::testing::Test::HasFatalFailure()) {
         bufferHandles.clear();
@@ -126,13 +125,14 @@
 }
 
 const native_handle_t* Gralloc::allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
-                                         bool import, bool allowFailure, uint32_t* outStride) {
+                                         bool import, enum Tolerance tolerance,
+                                         uint32_t* outStride) {
     BufferDescriptor descriptor = createDescriptor(descriptorInfo);
     if (::testing::Test::HasFatalFailure()) {
         return nullptr;
     }
 
-    auto buffers = allocate(descriptor, 1, import, allowFailure, outStride);
+    auto buffers = allocate(descriptor, 1, import, tolerance, outStride);
     if (::testing::Test::HasFatalFailure()) {
         return nullptr;
     }
@@ -157,11 +157,14 @@
     return descriptor;
 }
 
-const native_handle_t* Gralloc::importBuffer(const hidl_handle& rawHandle) {
+const native_handle_t* Gralloc::importBuffer(const hidl_handle& rawHandle,
+                                             enum Tolerance tolerance) {
     const native_handle_t* bufferHandle = nullptr;
     mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
-        ASSERT_EQ(Error::NONE, tmpError)
-                << "failed to import buffer %p" << rawHandle.getNativeHandle();
+        if (!canTolerate(tolerance, tmpError)) {
+            ASSERT_EQ(Error::NONE, tmpError)
+                    << "failed to import buffer %p" << rawHandle.getNativeHandle();
+        }
         bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
     });
 
diff --git a/graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h b/graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h
index cd40aa4..22a935f 100644
--- a/graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h
+++ b/graphics/mapper/4.0/utils/vts/include/mapper-vts/4.0/MapperVts.h
@@ -37,6 +37,16 @@
 // A wrapper to IAllocator and IMapper.
 class Gralloc {
   public:
+    enum class Tolerance : uint32_t {
+        kToleranceStrict = 0x0U,
+        kToleranceBadDescriptor = 0x1U << std::underlying_type_t<Error>(Error::BAD_DESCRIPTOR),
+        kToleranceBadBuffer = 0x1U << std::underlying_type_t<Error>(Error::BAD_BUFFER),
+        kToleranceBadValue = 0x1U << std::underlying_type_t<Error>(Error::BAD_VALUE),
+        kToleranceNoResource = 0x1U << std::underlying_type_t<Error>(Error::NO_RESOURCES),
+        kToleranceUnSupported = 0x1U << std::underlying_type_t<Error>(Error::UNSUPPORTED),
+        kToleranceAllErrors = ~0x0U,
+    };
+
     Gralloc(const std::string& allocatorServiceName = "default",
             const std::string& mapperServiceName = "default", bool errOnFailure = true);
     ~Gralloc();
@@ -49,12 +59,27 @@
     // is true, the returned buffers are also imported into the mapper.
     //
     // Either case, the returned buffers must be freed with freeBuffer.
-    std::vector<const native_handle_t*> allocate(const BufferDescriptor& descriptor, uint32_t count,
-                                                 bool import = true, bool allowFailure = false,
-                                                 uint32_t* outStride = nullptr);
+    std::vector<const native_handle_t*> allocate(
+            const BufferDescriptor& descriptor, uint32_t count, bool import = true,
+            enum Tolerance tolerance = Tolerance::kToleranceStrict, uint32_t* outStride = nullptr);
+
     const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
-                                    bool import = true, bool allowFailure = false,
-                                    uint32_t* outStride = nullptr);
+                                    bool import, enum Tolerance tolerance, uint32_t* outStride);
+
+    const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                    bool import) {
+        return allocate(descriptorInfo, import, Tolerance::kToleranceStrict);
+    }
+
+    const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                    bool import, enum Tolerance tolerance) {
+        return allocate(descriptorInfo, import, tolerance, nullptr);
+    }
+
+    const native_handle_t* allocate(const IMapper::BufferDescriptorInfo& descriptorInfo,
+                                    bool import, uint32_t* outStride) {
+        return allocate(descriptorInfo, import, Tolerance::kToleranceStrict, outStride);
+    }
 
     // IMapper methods
 
@@ -62,7 +87,11 @@
 
     BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo);
 
-    const native_handle_t* importBuffer(const hidl_handle& rawHandle);
+    const native_handle_t* importBuffer(const hidl_handle& rawHandle, enum Tolerance tolerance);
+    const native_handle_t* importBuffer(const hidl_handle& rawHandle) {
+        return importBuffer(rawHandle, Tolerance::kToleranceStrict);
+    }
+
     void freeBuffer(const native_handle_t* bufferHandle);
 
     // We use fd instead of hidl_handle in these functions to pass fences
@@ -96,11 +125,19 @@
                             uint64_t* outReservedSize);
 
   private:
+    bool canTolerate(Tolerance tolerance, Error error) {
+        return (std::underlying_type_t<Tolerance>(tolerance) &
+                0x1U << std::underlying_type_t<Error>(error)) != 0;
+    }
+
     void init(const std::string& allocatorServiceName, const std::string& mapperServiceName);
 
     // initialize without checking for failure to get service
     void initNoErr(const std::string& allocatorServiceName, const std::string& mapperServiceName);
-    const native_handle_t* cloneBuffer(const hidl_handle& rawHandle);
+    const native_handle_t* cloneBuffer(const hidl_handle& rawHandle, enum Tolerance tolerance);
+    const native_handle_t* cloneBuffer(const hidl_handle& rawHandle) {
+        return cloneBuffer(rawHandle, Tolerance::kToleranceStrict);
+    }
 
     sp<IAllocator> mAllocator;
     sp<IMapper> mMapper;
diff --git a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index 8247ded..bb775dc 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -24,6 +24,7 @@
 #include <aidl/android/hardware/graphics/common/PlaneLayoutComponentType.h>
 
 #include <android-base/logging.h>
+#include <android-base/unique_fd.h>
 #include <android/sync.h>
 #include <gralloctypes/Gralloc4.h>
 #include <gtest/gtest.h>
@@ -40,8 +41,10 @@
 namespace vts {
 namespace {
 
+using ::android::base::unique_fd;
 using android::hardware::graphics::common::V1_2::BufferUsage;
 using android::hardware::graphics::common::V1_2::PixelFormat;
+using Tolerance = ::android::hardware::graphics::mapper::V4_0::vts::Gralloc::Tolerance;
 using MetadataType = android::hardware::graphics::mapper::V4_0::IMapper::MetadataType;
 using aidl::android::hardware::graphics::common::BlendMode;
 using aidl::android::hardware::graphics::common::Cta861_3;
@@ -276,7 +279,7 @@
         }
     }
 
-    void verifyRGBA8888(const native_handle_t* bufferHandle, uint8_t* data, uint32_t height,
+    void verifyRGBA8888(const native_handle_t* bufferHandle, const uint8_t* data, uint32_t height,
                         size_t strideInBytes, size_t widthInBytes, uint32_t seed = 0) {
         hidl_vec<uint8_t> vec;
         ASSERT_EQ(Error::NONE,
@@ -294,6 +297,49 @@
         }
     }
 
+    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) {
+        auto yData = static_cast<uint8_t*>(yCbCr.y);
+        auto cbData = static_cast<uint8_t*>(yCbCr.cb);
+        auto crData = static_cast<uint8_t*>(yCbCr.cr);
+        auto yStride = yCbCr.ystride;
+        auto cStride = yCbCr.cstride;
+        auto chromaStep = yCbCr.chroma_step;
+
+        for (uint32_t y = 0; y < height; y++) {
+            for (uint32_t x = 0; x < width; x++) {
+                auto val = static_cast<uint8_t>(height * y + x);
+
+                traverseFuncion(yData + yStride * y + x, val);
+
+                if (y % vSubsampling == 0 && x % hSubsampling == 0) {
+                    uint32_t subSampleX = x / hSubsampling;
+                    uint32_t subSampleY = y / vSubsampling;
+                    const auto subSampleOffset = cStride * subSampleY + chromaStep * subSampleX;
+                    const auto subSampleVal =
+                            static_cast<uint8_t>(height * subSampleY + subSampleX);
+
+                    traverseFuncion(cbData + subSampleOffset, subSampleVal);
+                    traverseFuncion(crData + subSampleOffset, subSampleVal + 1);
+                }
+            }
+        }
+    }
+
+    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 verifyYCbCr888Data(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 expectedData) { EXPECT_EQ(*address, expectedData); });
+    }
+
     bool isEqual(float a, float b) { return abs(a - b) < 0.0001; }
 
     std::unique_ptr<Gralloc> mGralloc;
@@ -331,8 +377,9 @@
     for (uint32_t count = 0; count < 5; count++) {
         std::vector<const native_handle_t*> bufferHandles;
         uint32_t stride;
-        ASSERT_NO_FATAL_FAILURE(
-                bufferHandles = mGralloc->allocate(descriptor, count, false, false, &stride));
+        ASSERT_NO_FATAL_FAILURE(bufferHandles =
+                                        mGralloc->allocate(descriptor, count, false,
+                                                           Tolerance::kToleranceStrict, &stride));
 
         if (count >= 1) {
             EXPECT_LE(mDummyDescriptorInfo.width, stride) << "invalid buffer stride";
@@ -532,50 +579,56 @@
 
     const native_handle_t* bufferHandle;
     uint32_t stride;
-    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, false, &stride));
+    ASSERT_NO_FATAL_FAILURE(
+            bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceStrict, &stride));
 
     // lock buffer for writing
     const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
                                static_cast<int32_t>(info.height)};
-    int fence = -1;
+    unique_fd fence;
     uint8_t* data;
-    ASSERT_NO_FATAL_FAILURE(
-            data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
+    ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage,
+                                                                        region, fence.release())));
 
     // RGBA_8888
     fillRGBA8888(data, info.height, stride * 4, info.width * 4);
 
-    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
+    ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
 
     // lock again for reading
-    ASSERT_NO_FATAL_FAILURE(
-            data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
+    ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage,
+                                                                        region, fence.release())));
 
     ASSERT_NO_FATAL_FAILURE(
             verifyRGBA8888(bufferHandle, data, info.height, stride * 4, info.width * 4));
 
-    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
-    if (fence >= 0) {
-        close(fence);
-    }
+    ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
 }
 
+/**
+ *  Test multiple operations associated with different color formats
+ */
 TEST_P(GraphicsMapperHidlTest, Lock_YCRCB_420_SP) {
     auto info = mDummyDescriptorInfo;
     info.format = PixelFormat::YCRCB_420_SP;
 
     const native_handle_t* bufferHandle;
     uint32_t stride;
-    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(info, true, false, &stride));
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(
+                                    info, true, Tolerance::kToleranceUnSupported, &stride));
+    if (bufferHandle == nullptr) {
+        GTEST_SUCCEED() << "YCRCB_420_SP format is unsupported";
+        return;
+    }
 
     // lock buffer for writing
     const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
                                static_cast<int32_t>(info.height)};
-    int fence = -1;
+    unique_fd fence;
     uint8_t* data;
 
-    ASSERT_NO_FATAL_FAILURE(
-            data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
+    ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage,
+                                                                        region, fence.release())));
 
     android_ycbcr yCbCr;
     int64_t hSubsampling = 0;
@@ -583,74 +636,256 @@
     ASSERT_NO_FATAL_FAILURE(
             getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling));
 
-    auto yData = static_cast<uint8_t*>(yCbCr.y);
-    auto cbData = static_cast<uint8_t*>(yCbCr.cb);
-    auto crData = static_cast<uint8_t*>(yCbCr.cr);
-    auto yStride = yCbCr.ystride;
-    auto cStride = yCbCr.cstride;
-    auto chromaStep = yCbCr.chroma_step;
-
     constexpr uint32_t kCbCrSubSampleFactor = 2;
-    ASSERT_EQ(crData + 1, cbData);
-    ASSERT_EQ(2, chromaStep);
     ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling);
     ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling);
 
-    for (uint32_t y = 0; y < info.height; y++) {
-        for (uint32_t x = 0; x < info.width; x++) {
-            auto val = static_cast<uint8_t>(info.height * y + x);
+    auto cbData = static_cast<uint8_t*>(yCbCr.cb);
+    auto crData = static_cast<uint8_t*>(yCbCr.cr);
+    ASSERT_EQ(crData + 1, cbData);
+    ASSERT_EQ(2, yCbCr.chroma_step);
 
-            yData[yStride * y + x] = val;
+    fillYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
 
-            if (y % vSubsampling == 0 && x % hSubsampling == 0) {
-                uint32_t subSampleX = x / hSubsampling;
-                uint32_t subSampleY = y / vSubsampling;
-                const auto subSampleOffset = cStride * subSampleY + chromaStep * subSampleX;
-                const auto subSampleVal =
-                        static_cast<uint8_t>(info.height * subSampleY + subSampleX);
-
-                cbData[subSampleOffset] = subSampleVal;
-                crData[subSampleOffset] = subSampleVal + 1;
-            }
-        }
-    }
-
-    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
+    ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
 
     // lock again for reading
-    ASSERT_NO_FATAL_FAILURE(
-            data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage, region, fence)));
+    ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage,
+                                                                        region, fence.release())));
 
     ASSERT_NO_FATAL_FAILURE(
             getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling));
 
-    yData = static_cast<uint8_t*>(yCbCr.y);
-    cbData = static_cast<uint8_t*>(yCbCr.cb);
-    crData = static_cast<uint8_t*>(yCbCr.cr);
+    verifyYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
 
-    for (uint32_t y = 0; y < info.height; y++) {
-        for (uint32_t x = 0; x < info.width; x++) {
-            auto val = static_cast<uint8_t>(info.height * y + x);
+    ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
+}
 
-            EXPECT_EQ(val, yData[yStride * y + x]);
+TEST_P(GraphicsMapperHidlTest, YV12SubsampleMetadata) {
+    auto info = mDummyDescriptorInfo;
+    info.format = PixelFormat::YV12;
 
-            if (y % vSubsampling == 0 && x % hSubsampling == 0) {
-                uint32_t subSampleX = x / hSubsampling;
-                uint32_t subSampleY = y / vSubsampling;
-                const auto subSampleOffset = cStride * subSampleY + chromaStep * subSampleX;
-                const auto subSampleVal =
-                        static_cast<uint8_t>(info.height * subSampleY + subSampleX);
+    const native_handle_t* bufferHandle;
+    uint32_t stride;
+    ASSERT_NO_FATAL_FAILURE(
+            bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceStrict, &stride));
 
-                EXPECT_EQ(subSampleVal, cbData[subSampleOffset]);
-                EXPECT_EQ(subSampleVal + 1, crData[subSampleOffset]);
-            }
-        }
+    const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+                               static_cast<int32_t>(info.height)};
+    unique_fd fence;
+    ASSERT_NO_FATAL_FAILURE(mGralloc->lock(bufferHandle, info.usage, region, fence.release()));
+
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec));
+    std::vector<PlaneLayout> planeLayouts;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts));
+
+    ASSERT_EQ(3, planeLayouts.size());
+
+    auto yPlane = planeLayouts[0];
+    auto crPlane = planeLayouts[1];
+    auto cbPlane = planeLayouts[2];
+
+    constexpr uint32_t kCbCrSubSampleFactor = 2;
+    EXPECT_EQ(kCbCrSubSampleFactor, crPlane.horizontalSubsampling);
+    EXPECT_EQ(kCbCrSubSampleFactor, crPlane.verticalSubsampling);
+
+    EXPECT_EQ(kCbCrSubSampleFactor, cbPlane.horizontalSubsampling);
+    EXPECT_EQ(kCbCrSubSampleFactor, cbPlane.verticalSubsampling);
+
+    const long chromaSampleWidth = info.width / kCbCrSubSampleFactor;
+    const long chromaSampleHeight = info.height / kCbCrSubSampleFactor;
+
+    EXPECT_EQ(info.width, yPlane.widthInSamples);
+    EXPECT_EQ(info.height, yPlane.heightInSamples);
+
+    EXPECT_EQ(chromaSampleWidth, crPlane.widthInSamples);
+    EXPECT_EQ(chromaSampleHeight, crPlane.heightInSamples);
+
+    EXPECT_EQ(chromaSampleWidth, cbPlane.widthInSamples);
+    EXPECT_EQ(chromaSampleHeight, cbPlane.heightInSamples);
+
+    EXPECT_LE(crPlane.widthInSamples, crPlane.strideInBytes);
+    EXPECT_LE(cbPlane.widthInSamples, cbPlane.strideInBytes);
+
+    ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
+}
+
+TEST_P(GraphicsMapperHidlTest, Lock_YV12) {
+    auto info = mDummyDescriptorInfo;
+    info.format = PixelFormat::YV12;
+
+    const native_handle_t* bufferHandle;
+    uint32_t stride;
+    ASSERT_NO_FATAL_FAILURE(
+            bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceStrict, &stride));
+
+    // lock buffer for writing
+    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())));
+
+    android_ycbcr yCbCr;
+    int64_t hSubsampling = 0;
+    int64_t vSubsampling = 0;
+    ASSERT_NO_FATAL_FAILURE(
+            getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling));
+
+    constexpr uint32_t kCbCrSubSampleFactor = 2;
+    ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling);
+    ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling);
+
+    auto cbData = static_cast<uint8_t*>(yCbCr.cb);
+    auto crData = static_cast<uint8_t*>(yCbCr.cr);
+    ASSERT_EQ(crData + yCbCr.cstride * info.height / vSubsampling, cbData);
+    ASSERT_EQ(1, yCbCr.chroma_step);
+
+    fillYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+
+    ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
+
+    // lock again for reading
+    ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage,
+                                                                        region, fence.release())));
+
+    ASSERT_NO_FATAL_FAILURE(
+            getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling));
+
+    verifyYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+
+    ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
+}
+
+TEST_P(GraphicsMapperHidlTest, Lock_YCBCR_420_888) {
+    auto info = mDummyDescriptorInfo;
+    info.format = PixelFormat::YCBCR_420_888;
+
+    const native_handle_t* bufferHandle;
+    uint32_t stride;
+    ASSERT_NO_FATAL_FAILURE(
+            bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceStrict, &stride));
+
+    // lock buffer for writing
+    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())));
+
+    android_ycbcr yCbCr;
+    int64_t hSubsampling = 0;
+    int64_t vSubsampling = 0;
+    ASSERT_NO_FATAL_FAILURE(
+            getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling));
+
+    constexpr uint32_t kCbCrSubSampleFactor = 2;
+    ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling);
+    ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling);
+
+    fillYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+
+    ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
+
+    // lock again for reading
+    ASSERT_NO_FATAL_FAILURE(data = static_cast<uint8_t*>(mGralloc->lock(bufferHandle, info.usage,
+                                                                        region, fence.release())));
+
+    ASSERT_NO_FATAL_FAILURE(
+            getAndroidYCbCr(bufferHandle, data, &yCbCr, &hSubsampling, &vSubsampling));
+
+    verifyYCbCr888Data(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+
+    ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
+}
+
+TEST_P(GraphicsMapperHidlTest, Lock_RAW10) {
+    auto info = mDummyDescriptorInfo;
+    info.format = PixelFormat::RAW10;
+
+    const native_handle_t* bufferHandle;
+    uint32_t stride;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(
+                                    info, true, Tolerance::kToleranceUnSupported, &stride));
+    if (bufferHandle == nullptr) {
+        GTEST_SUCCEED() << "RAW10 format is unsupported";
+        return;
     }
 
-    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(bufferHandle));
-    if (fence >= 0) {
-        close(fence);
+    const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+                               static_cast<int32_t>(info.height)};
+    unique_fd fence;
+
+    ASSERT_NO_FATAL_FAILURE(mGralloc->lock(bufferHandle, info.usage, region, fence.release()));
+
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec));
+    std::vector<PlaneLayout> planeLayouts;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts));
+
+    ASSERT_EQ(1, planeLayouts.size());
+    auto planeLayout = planeLayouts[0];
+
+    EXPECT_EQ(0, planeLayout.sampleIncrementInBits);
+    EXPECT_EQ(1, planeLayout.horizontalSubsampling);
+    EXPECT_EQ(1, planeLayout.verticalSubsampling);
+
+    ASSERT_EQ(1, planeLayout.components.size());
+    auto planeLayoutComponent = planeLayout.components[0];
+
+    EXPECT_EQ(PlaneLayoutComponentType::RAW,
+              static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value));
+    EXPECT_EQ(0, planeLayoutComponent.offsetInBits % 8);
+    EXPECT_EQ(-1, planeLayoutComponent.sizeInBits);
+
+    ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
+}
+
+TEST_P(GraphicsMapperHidlTest, Lock_RAW12) {
+    auto info = mDummyDescriptorInfo;
+    info.format = PixelFormat::RAW12;
+
+    const native_handle_t* bufferHandle;
+    uint32_t stride;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(
+                                    info, true, Tolerance::kToleranceUnSupported, &stride));
+    if (bufferHandle == nullptr) {
+        GTEST_SUCCEED() << "RAW12 format is unsupported";
+        return;
     }
+
+    const IMapper::Rect region{0, 0, static_cast<int32_t>(info.width),
+                               static_cast<int32_t>(info.height)};
+    unique_fd fence;
+
+    ASSERT_NO_FATAL_FAILURE(mGralloc->lock(bufferHandle, info.usage, region, fence.release()));
+
+    hidl_vec<uint8_t> vec;
+    ASSERT_EQ(Error::NONE, mGralloc->get(bufferHandle, gralloc4::MetadataType_PlaneLayouts, &vec));
+    std::vector<PlaneLayout> planeLayouts;
+    ASSERT_EQ(NO_ERROR, gralloc4::decodePlaneLayouts(vec, &planeLayouts));
+
+    ASSERT_EQ(1, planeLayouts.size());
+    auto planeLayout = planeLayouts[0];
+
+    EXPECT_EQ(0, planeLayout.sampleIncrementInBits);
+    EXPECT_EQ(1, planeLayout.horizontalSubsampling);
+    EXPECT_EQ(1, planeLayout.verticalSubsampling);
+
+    ASSERT_EQ(1, planeLayout.components.size());
+    auto planeLayoutComponent = planeLayout.components[0];
+
+    EXPECT_EQ(PlaneLayoutComponentType::RAW,
+              static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value));
+    EXPECT_EQ(0, planeLayoutComponent.offsetInBits % 8);
+    EXPECT_EQ(-1, planeLayoutComponent.sizeInBits);
+
+    ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(bufferHandle)));
 }
 
 /**
@@ -741,8 +976,8 @@
 
     const native_handle_t* rawHandle;
     uint32_t stride;
-    ASSERT_NO_FATAL_FAILURE(
-            rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false, false, &stride));
+    ASSERT_NO_FATAL_FAILURE(rawHandle = mGralloc->allocate(mDummyDescriptorInfo, false,
+                                                           Tolerance::kToleranceStrict, &stride));
 
     const native_handle_t* writeBufferHandle;
     const native_handle_t* readBufferHandle;
@@ -766,11 +1001,10 @@
 
     fillRGBA8888(writeData, info.height, stride * 4, info.width * 4);
 
-    int fence;
-    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->flushLockedBuffer(writeBufferHandle));
+    unique_fd fence;
+    ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->flushLockedBuffer(writeBufferHandle)));
     if (fence >= 0) {
         ASSERT_EQ(0, sync_wait(fence, 3500));
-        close(fence);
     }
 
     ASSERT_NO_FATAL_FAILURE(mGralloc->rereadLockedBuffer(readBufferHandle));
@@ -778,14 +1012,9 @@
     ASSERT_NO_FATAL_FAILURE(
             verifyRGBA8888(readBufferHandle, readData, info.height, stride * 4, info.width * 4));
 
-    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(readBufferHandle));
-    if (fence >= 0) {
-        close(fence);
-    }
-    ASSERT_NO_FATAL_FAILURE(fence = mGralloc->unlock(writeBufferHandle));
-    if (fence >= 0) {
-        close(fence);
-    }
+    ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(readBufferHandle)));
+
+    ASSERT_NO_FATAL_FAILURE(fence.reset(mGralloc->unlock(writeBufferHandle)));
 }
 
 /**
@@ -964,8 +1193,8 @@
     info.usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY;
 
     const native_handle_t* bufferHandle = nullptr;
-    bufferHandle = mGralloc->allocate(info, true, true);
-    if (bufferHandle) {
+    bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceAllErrors);
+    if (!bufferHandle) {
         GTEST_SUCCEED() << "unable to allocate protected content";
         return;
     }
@@ -1267,8 +1496,8 @@
     auto info = mDummyDescriptorInfo;
     info.usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY;
 
-    bufferHandle = mGralloc->allocate(info, true, true);
-    if (bufferHandle) {
+    bufferHandle = mGralloc->allocate(info, true, Tolerance::kToleranceAllErrors);
+    if (!bufferHandle) {
         GTEST_SUCCEED() << "unable to allocate protected content";
         return;
     }
@@ -1615,6 +1844,84 @@
 }
 
 /**
+ * Test get::metadata with cloned native_handle
+ */
+TEST_P(GraphicsMapperHidlTest, GetMetadataClonedHandle) {
+    const native_handle_t* bufferHandle = nullptr;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
+
+    const auto dataspace = Dataspace::SRGB_LINEAR;
+    {
+        hidl_vec<uint8_t> metadata;
+        ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(dataspace, &metadata));
+
+        Error err = mGralloc->set(bufferHandle, gralloc4::MetadataType_Dataspace, metadata);
+        if (err == Error::UNSUPPORTED) {
+            GTEST_SUCCEED() << "setting this metadata is unsupported";
+            return;
+        }
+        ASSERT_EQ(Error::NONE, err);
+    }
+
+    const native_handle_t* importedHandle;
+    {
+        auto clonedHandle = native_handle_clone(bufferHandle);
+        ASSERT_NO_FATAL_FAILURE(importedHandle = mGralloc->importBuffer(clonedHandle));
+        native_handle_close(clonedHandle);
+        native_handle_delete(clonedHandle);
+    }
+
+    Dataspace realSpace = Dataspace::UNKNOWN;
+    {
+        hidl_vec<uint8_t> metadata;
+        ASSERT_EQ(Error::NONE,
+                  mGralloc->get(importedHandle, gralloc4::MetadataType_Dataspace, &metadata));
+        ASSERT_NO_FATAL_FAILURE(gralloc4::decodeDataspace(metadata, &realSpace));
+    }
+
+    EXPECT_EQ(dataspace, realSpace);
+}
+
+/**
+ * Test set::metadata with cloned native_handle
+ */
+TEST_P(GraphicsMapperHidlTest, SetMetadataClonedHandle) {
+    const native_handle_t* bufferHandle = nullptr;
+    ASSERT_NO_FATAL_FAILURE(bufferHandle = mGralloc->allocate(mDummyDescriptorInfo, true));
+
+    const native_handle_t* importedHandle;
+    {
+        auto clonedHandle = native_handle_clone(bufferHandle);
+        ASSERT_NO_FATAL_FAILURE(importedHandle = mGralloc->importBuffer(clonedHandle));
+        native_handle_close(clonedHandle);
+        native_handle_delete(clonedHandle);
+    }
+
+    const auto dataspace = Dataspace::SRGB_LINEAR;
+    {
+        hidl_vec<uint8_t> metadata;
+        ASSERT_EQ(NO_ERROR, gralloc4::encodeDataspace(dataspace, &metadata));
+
+        Error err = mGralloc->set(importedHandle, gralloc4::MetadataType_Dataspace, metadata);
+        if (err == Error::UNSUPPORTED) {
+            GTEST_SUCCEED() << "setting this metadata is unsupported";
+            return;
+        }
+        ASSERT_EQ(Error::NONE, err);
+    }
+
+    Dataspace realSpace = Dataspace::UNKNOWN;
+    {
+        hidl_vec<uint8_t> metadata;
+        ASSERT_EQ(Error::NONE,
+                  mGralloc->get(bufferHandle, gralloc4::MetadataType_Dataspace, &metadata));
+        ASSERT_NO_FATAL_FAILURE(gralloc4::decodeDataspace(metadata, &realSpace));
+    }
+
+    EXPECT_EQ(dataspace, realSpace);
+}
+
+/**
  * Test IMapper::set(metadata) for constant metadata
  */
 TEST_P(GraphicsMapperHidlTest, SetConstantMetadata) {
@@ -1835,8 +2142,13 @@
     info.usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY;
 
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
-                                   info, gralloc4::MetadataType_ProtectedContent, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(info, gralloc4::MetadataType_ProtectedContent,
+                                                     &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     uint64_t protectedContent = 0;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeProtectedContent(vec, &protectedContent));
@@ -1851,8 +2163,13 @@
     info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
 
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
-                                   info, gralloc4::MetadataType_Compression, &vec));
+    auto err =
+            mGralloc->getFromBufferDescriptorInfo(info, gralloc4::MetadataType_Compression, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     ExtendableType compression = gralloc4::Compression_DisplayStreamCompression;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeCompression(vec, &compression));
@@ -1866,8 +2183,13 @@
  */
 TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoInterlaced) {
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
-                                   mDummyDescriptorInfo, gralloc4::MetadataType_Interlaced, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                     gralloc4::MetadataType_Interlaced, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     ExtendableType interlaced = gralloc4::Interlaced_TopBottom;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeInterlaced(vec, &interlaced));
@@ -1881,9 +2203,13 @@
  */
 TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoChromaSiting) {
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE,
-              mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
-                                                    gralloc4::MetadataType_ChromaSiting, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                     gralloc4::MetadataType_ChromaSiting, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     ExtendableType chromaSiting = gralloc4::ChromaSiting_CositedHorizontal;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeChromaSiting(vec, &chromaSiting));
@@ -1917,8 +2243,12 @@
     info.usage = static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
 
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE,
-              mGralloc->getFromBufferDescriptorInfo(info, gralloc4::MetadataType_Crop, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(info, gralloc4::MetadataType_Crop, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     std::vector<aidl::android::hardware::graphics::common::Rect> crops;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeCrop(vec, &crops));
@@ -1930,8 +2260,13 @@
  */
 TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoDataspace) {
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
-                                   mDummyDescriptorInfo, gralloc4::MetadataType_Dataspace, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                     gralloc4::MetadataType_Dataspace, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     Dataspace dataspace = Dataspace::DISPLAY_P3;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeDataspace(vec, &dataspace));
@@ -1943,8 +2278,13 @@
  */
 TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoBlendMode) {
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
-                                   mDummyDescriptorInfo, gralloc4::MetadataType_BlendMode, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                     gralloc4::MetadataType_BlendMode, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     BlendMode blendMode = BlendMode::COVERAGE;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeBlendMode(vec, &blendMode));
@@ -1956,8 +2296,13 @@
  */
 TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoSmpte2086) {
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
-                                   mDummyDescriptorInfo, gralloc4::MetadataType_Smpte2086, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                     gralloc4::MetadataType_Smpte2086, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     std::optional<Smpte2086> smpte2086;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2086(vec, &smpte2086));
@@ -1969,8 +2314,13 @@
  */
 TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoCta861_3) {
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE, mGralloc->getFromBufferDescriptorInfo(
-                                   mDummyDescriptorInfo, gralloc4::MetadataType_Cta861_3, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                     gralloc4::MetadataType_Cta861_3, &vec);
+    if (err == Error::UNSUPPORTED) {
+        GTEST_SUCCEED() << "setting this metadata is unsupported";
+        return;
+    }
+    ASSERT_EQ(err, Error::NONE);
 
     std::optional<Cta861_3> cta861_3;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeCta861_3(vec, &cta861_3));
@@ -1982,9 +2332,14 @@
  */
 TEST_P(GraphicsMapperHidlTest, GetFromBufferDescriptorInfoSmpte2094_40) {
     hidl_vec<uint8_t> vec;
-    ASSERT_EQ(Error::NONE,
-              mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
-                                                    gralloc4::MetadataType_Smpte2094_40, &vec));
+    auto err = mGralloc->getFromBufferDescriptorInfo(mDummyDescriptorInfo,
+                                                     gralloc4::MetadataType_Smpte2094_40, &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_40;
     ASSERT_EQ(NO_ERROR, gralloc4::decodeSmpte2094_40(vec, &smpte2094_40));
     EXPECT_FALSE(smpte2094_40.has_value());
diff --git a/health/1.0/Android.bp b/health/1.0/Android.bp
index ea6b0c8..7845871 100644
--- a/health/1.0/Android.bp
+++ b/health/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.health@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IHealth.hal",
diff --git a/health/1.0/default/Android.bp b/health/1.0/default/Android.bp
index 7581335..b815eae 100644
--- a/health/1.0/default/Android.bp
+++ b/health/1.0/default/Android.bp
@@ -51,6 +51,12 @@
         "android.hardware.health@1.0-convert",
         "libhealthd.default",
     ],
+
+    shared_libs: [
+        "libhidlbase",
+        "libutils",
+        "android.hardware.health@1.0",
+    ],
 }
 
 cc_binary {
diff --git a/health/1.0/default/convert.cpp b/health/1.0/default/convert.cpp
index 7f1e3c4..3680d4d 100644
--- a/health/1.0/default/convert.cpp
+++ b/health/1.0/default/convert.cpp
@@ -79,7 +79,7 @@
 
     hc->batteryCurrentAvgPath =
         android::String8(c.batteryCurrentAvgPath.c_str(),
-                         c.batteryCurrentNowPath.size());
+                         c.batteryCurrentAvgPath.size());
 
     hc->batteryChargeCounterPath =
         android::String8(c.batteryChargeCounterPath.c_str(),
diff --git a/health/2.0/Android.bp b/health/2.0/Android.bp
index b8323b6..420586e 100644
--- a/health/2.0/Android.bp
+++ b/health/2.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.health@2.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IHealth.hal",
diff --git a/health/2.1/Android.bp b/health/2.1/Android.bp
index 254bfc0..80a6501 100644
--- a/health/2.1/Android.bp
+++ b/health/2.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.health@2.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IHealth.hal",
diff --git a/health/storage/1.0/Android.bp b/health/storage/1.0/Android.bp
index e4620f8..b9d892d 100644
--- a/health/storage/1.0/Android.bp
+++ b/health/storage/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.health.storage@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IGarbageCollectCallback.hal",
diff --git a/health/utils/libhealth2impl/include/health2impl/HalHealthLoop.h b/health/utils/libhealth2impl/include/health2impl/HalHealthLoop.h
index d9b5580..362581e 100644
--- a/health/utils/libhealth2impl/include/health2impl/HalHealthLoop.h
+++ b/health/utils/libhealth2impl/include/health2impl/HalHealthLoop.h
@@ -55,7 +55,7 @@
     void set_charger_online(const HealthInfo& health_info);
 
   private:
-    const std::string& instance_name_;
+    std::string instance_name_;
     sp<IHealth> service_;
     bool charger_online_ = false;
 };
diff --git a/identity/aidl/Android.bp b/identity/aidl/Android.bp
index 7298c7d..14aef8e 100644
--- a/identity/aidl/Android.bp
+++ b/identity/aidl/Android.bp
@@ -18,5 +18,8 @@
             },
         },
     },
-    versions: ["1"],
+    versions: [
+        "1",
+        "2",
+    ],
 }
diff --git a/identity/aidl/aidl_api/android.hardware.identity/2/.hash b/identity/aidl/aidl_api/android.hardware.identity/2/.hash
new file mode 100644
index 0000000..036ce84
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/2/.hash
@@ -0,0 +1 @@
+194e04be642728623d65ec8321a3764fdea52ae0
diff --git a/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/Certificate.aidl b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/Certificate.aidl
new file mode 100644
index 0000000..7e3002d
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/Certificate.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+parcelable Certificate {
+  byte[] encodedCertificate;
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/CipherSuite.aidl b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/CipherSuite.aidl
new file mode 100644
index 0000000..447203f
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/CipherSuite.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@Backing(type="int") @VintfStability
+enum CipherSuite {
+  CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 = 1,
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/HardwareInformation.aidl b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/HardwareInformation.aidl
new file mode 100644
index 0000000..e1296e0
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/HardwareInformation.aidl
@@ -0,0 +1,26 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+parcelable HardwareInformation {
+  @utf8InCpp String credentialStoreName;
+  @utf8InCpp String credentialStoreAuthorName;
+  int dataChunkSize;
+  boolean isDirectAccess;
+  @utf8InCpp String[] supportedDocTypes;
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/IIdentityCredential.aidl
new file mode 100644
index 0000000..88104d9
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/IIdentityCredential.aidl
@@ -0,0 +1,32 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+interface IIdentityCredential {
+  byte[] deleteCredential();
+  byte[] createEphemeralKeyPair();
+  void setReaderEphemeralPublicKey(in byte[] publicKey);
+  long createAuthChallenge();
+  void startRetrieval(in android.hardware.identity.SecureAccessControlProfile[] accessControlProfiles, in android.hardware.keymaster.HardwareAuthToken authToken, in byte[] itemsRequest, in byte[] signingKeyBlob, in byte[] sessionTranscript, in byte[] readerSignature, in int[] requestCounts);
+  void startRetrieveEntryValue(in @utf8InCpp String nameSpace, in @utf8InCpp String name, in int entrySize, in int[] accessControlProfileIds);
+  byte[] retrieveEntryValue(in byte[] encryptedContent);
+  void finishRetrieval(out byte[] mac, out byte[] deviceNameSpaces);
+  android.hardware.identity.Certificate generateSigningKeyPair(out byte[] signingKeyBlob);
+  void setRequestedNamespaces(in android.hardware.identity.RequestNamespace[] requestNamespaces);
+  void setVerificationToken(in android.hardware.keymaster.VerificationToken verificationToken);
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/IIdentityCredentialStore.aidl b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/IIdentityCredentialStore.aidl
new file mode 100644
index 0000000..5dafb76
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/IIdentityCredentialStore.aidl
@@ -0,0 +1,37 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+interface IIdentityCredentialStore {
+  android.hardware.identity.HardwareInformation getHardwareInformation();
+  android.hardware.identity.IWritableIdentityCredential createCredential(in @utf8InCpp String docType, in boolean testCredential);
+  android.hardware.identity.IIdentityCredential getCredential(in android.hardware.identity.CipherSuite cipherSuite, in byte[] credentialData);
+  const int STATUS_OK = 0;
+  const int STATUS_FAILED = 1;
+  const int STATUS_CIPHER_SUITE_NOT_SUPPORTED = 2;
+  const int STATUS_INVALID_DATA = 3;
+  const int STATUS_INVALID_AUTH_TOKEN = 4;
+  const int STATUS_INVALID_ITEMS_REQUEST_MESSAGE = 5;
+  const int STATUS_READER_SIGNATURE_CHECK_FAILED = 6;
+  const int STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND = 7;
+  const int STATUS_USER_AUTHENTICATION_FAILED = 8;
+  const int STATUS_READER_AUTHENTICATION_FAILED = 9;
+  const int STATUS_NO_ACCESS_CONTROL_PROFILES = 10;
+  const int STATUS_NOT_IN_REQUEST_MESSAGE = 11;
+  const int STATUS_SESSION_TRANSCRIPT_MISMATCH = 12;
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/IWritableIdentityCredential.aidl b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/IWritableIdentityCredential.aidl
new file mode 100644
index 0000000..c5ac9d6
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/IWritableIdentityCredential.aidl
@@ -0,0 +1,28 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+interface IWritableIdentityCredential {
+  android.hardware.identity.Certificate[] getAttestationCertificate(in byte[] attestationApplicationId, in byte[] attestationChallenge);
+  void startPersonalization(in int accessControlProfileCount, in int[] entryCounts);
+  android.hardware.identity.SecureAccessControlProfile addAccessControlProfile(in int id, in android.hardware.identity.Certificate readerCertificate, in boolean userAuthenticationRequired, in long timeoutMillis, in long secureUserId);
+  void beginAddEntry(in int[] accessControlProfileIds, in @utf8InCpp String nameSpace, in @utf8InCpp String name, in int entrySize);
+  byte[] addEntryValue(in byte[] content);
+  void finishAddingEntries(out byte[] credentialData, out byte[] proofOfProvisioningSignature);
+  void setExpectedProofOfProvisioningSize(in int expectedProofOfProvisioningSize);
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/RequestDataItem.aidl b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/RequestDataItem.aidl
new file mode 100644
index 0000000..24ec26a
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/RequestDataItem.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+parcelable RequestDataItem {
+  @utf8InCpp String name;
+  long size;
+  int[] accessControlProfileIds;
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/RequestNamespace.aidl b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/RequestNamespace.aidl
new file mode 100644
index 0000000..af00f3b
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/RequestNamespace.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+parcelable RequestNamespace {
+  @utf8InCpp String namespaceName;
+  android.hardware.identity.RequestDataItem[] items;
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/SecureAccessControlProfile.aidl b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/SecureAccessControlProfile.aidl
new file mode 100644
index 0000000..dfc1ad0
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/2/android/hardware/identity/SecureAccessControlProfile.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+parcelable SecureAccessControlProfile {
+  int id;
+  android.hardware.identity.Certificate readerCertificate;
+  boolean userAuthenticationRequired;
+  long timeoutMillis;
+  long secureUserId;
+  byte[] mac;
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl
index 58b90b5..88104d9 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IIdentityCredential.aidl
@@ -27,4 +27,6 @@
   byte[] retrieveEntryValue(in byte[] encryptedContent);
   void finishRetrieval(out byte[] mac, out byte[] deviceNameSpaces);
   android.hardware.identity.Certificate generateSigningKeyPair(out byte[] signingKeyBlob);
+  void setRequestedNamespaces(in android.hardware.identity.RequestNamespace[] requestNamespaces);
+  void setVerificationToken(in android.hardware.keymaster.VerificationToken verificationToken);
 }
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IWritableIdentityCredential.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IWritableIdentityCredential.aidl
index 32f283c..c5ac9d6 100644
--- a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IWritableIdentityCredential.aidl
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/IWritableIdentityCredential.aidl
@@ -24,4 +24,5 @@
   void beginAddEntry(in int[] accessControlProfileIds, in @utf8InCpp String nameSpace, in @utf8InCpp String name, in int entrySize);
   byte[] addEntryValue(in byte[] content);
   void finishAddingEntries(out byte[] credentialData, out byte[] proofOfProvisioningSignature);
+  void setExpectedProofOfProvisioningSize(in int expectedProofOfProvisioningSize);
 }
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestDataItem.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestDataItem.aidl
new file mode 100644
index 0000000..24ec26a
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestDataItem.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+parcelable RequestDataItem {
+  @utf8InCpp String name;
+  long size;
+  int[] accessControlProfileIds;
+}
diff --git a/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestNamespace.aidl b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestNamespace.aidl
new file mode 100644
index 0000000..af00f3b
--- /dev/null
+++ b/identity/aidl/aidl_api/android.hardware.identity/current/android/hardware/identity/RequestNamespace.aidl
@@ -0,0 +1,23 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.identity;
+@VintfStability
+parcelable RequestNamespace {
+  @utf8InCpp String namespaceName;
+  android.hardware.identity.RequestDataItem[] items;
+}
diff --git a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
index 7d14f03..730b601 100644
--- a/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
@@ -17,8 +17,10 @@
 package android.hardware.identity;
 
 import android.hardware.identity.Certificate;
+import android.hardware.identity.RequestNamespace;
 import android.hardware.identity.SecureAccessControlProfile;
 import android.hardware.keymaster.HardwareAuthToken;
+import android.hardware.keymaster.VerificationToken;
 
 @VintfStability
 interface IIdentityCredential {
@@ -70,10 +72,11 @@
 
     /**
      * Creates a challenge value to be used for proving successful user authentication. This
-     * is included in the authToken passed to the startRetrieval() method.
+     * is included in the authToken passed to the startRetrieval() method and the
+     * verificationToken passed to the setVerificationToken() method.
      *
      * This method may only be called once per instance. If called more than once, STATUS_FAILED
-     * will be returned.
+     * will be returned. If user authentication is not needed, this method may not be called.
      *
      * @return challenge, a non-zero number.
      */
@@ -82,6 +85,9 @@
     /**
      * Start an entry retrieval process.
      *
+     * The setRequestedNamespaces() and setVerificationToken() methods will be called before
+     * this method is called.
+     *
      * This method be called after createEphemeralKeyPair(), setReaderEphemeralPublicKey(),
      * createAuthChallenge() and before startRetrieveEntry(). This method call is followed by
      * multiple calls of startRetrieveEntryValue(), retrieveEntryValue(), and finally
@@ -93,7 +99,19 @@
      * must be identical for each startRetrieval() invocation. If this is not the case, this call
      * fails with the STATUS_SESSION_TRANSCRIPT_MISMATCH error.
      *
-     * If the provided authToken is not valid this method fails with STATUS_INVALID_AUTH_TOKEN.
+     * If either authToken or verificationToken (as passed with setVerificationToken())
+     * is not valid this method fails with STATUS_INVALID_AUTH_TOKEN. Note that valid tokens
+     * are only passed if they are actually needed and available (this can be detected by
+     * the timestamp being set to zero). For example, if no data items with access control
+     * profiles using user authentication are requested, the tokens are not filled in.
+     * It's also possible that no usable auth token is actually available (it could be the user
+     * never unlocked the device within the timeouts in the access control profiles) and
+     * in this case the tokens aren't filled in either.
+     *
+     * For test credentials (identified by the testCredential boolean in the CredentialData
+     * CBOR created at provisioning time), the |mac| field in both the authToken and
+     * verificationToken should not be checked against the shared HMAC key (see IKeyMasterDevice
+     * for details). This is to enable VTS tests to check for correct behavior.
      *
      * Each of the provided accessControlProfiles is checked in this call. If they are not
      * all valid, the call fails with STATUS_INVALID_DATA.
@@ -133,8 +151,8 @@
      *   IntentToRetain = bool
      *
      * For the readerSignature parameter, this can either be empty or if non-empty it
-     * must be a COSE_Sign1 structure with an ECDSA signature over the content of the
-     * CBOR conforming to the following CDDL:
+     * must be a COSE_Sign1 where the payload is the bytes of the
+     * ReaderAuthenticationBytes CBOR defined below:
      *
      *     ReaderAuthentication = [
      *       "ReaderAuthentication",
@@ -142,16 +160,11 @@
      *       ItemsRequestBytes
      *     ]
      *
-     *     SessionTranscript = [
-     *       DeviceEngagementBytes,
-     *       EReaderKeyBytes
-     *     ]
+     *     SessionTranscript = any
      *
-     *     DeviceEngagementBytes = #6.24(bstr .cbor DeviceEngagement)
-     *     EReaderKeyBytes = #6.24(bstr .cbor EReaderKey.Pub)
      *     ItemsRequestBytes = #6.24(bstr .cbor ItemsRequest)
      *
-     *     EReaderKey.Pub = COSE_Key    ; Ephemeral public key provided by reader
+     *     ReaderAuthenticationBytes = #6.24(bstr .cbor ReaderAuthentication)
      *
      * The public key corresponding to the key used to made signature, can be found in the
      * 'x5chain' unprotected header element of the COSE_Sign1 structure (as as described
@@ -166,8 +179,12 @@
      *
      * If the SessionTranscript CBOR is not empty, the X and Y coordinates of the public
      * part of the key-pair previously generated by createEphemeralKeyPair() must appear
-     * somewhere in the bytes of DeviceEngagement structure. Both X and Y should be in
-     * uncompressed form. If this is not satisfied, the call fails with
+     * somewhere in the bytes of the CBOR. Each of these coordinates must appear encoded
+     * with the most significant bits first and use the exact amount of bits indicated by
+     * the key size of the ephemeral keys. For example, if the ephemeral key is using the
+     * P-256 curve then the 32 bytes for the X coordinate encoded with the most significant
+     * bits first must appear somewhere in the CBOR and ditto for the 32 bytes for the Y
+     * coordinate. If this is not satisfied, the call fails with
      * STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND.
      *
      * @param accessControlProfiles
@@ -176,7 +193,8 @@
      *
      * @param authToken
      *   The authentication token that proves the user was authenticated, as required
-     *   by one or more of the provided accessControlProfiles. See above.
+     *   by one or more of the provided accessControlProfiles. This token is only valid
+     *   if the timestamp field is non-zero. See above.
      *
      * @param itemsRequest
      *   If non-empty, contains request data that is signed by the reader. See above.
@@ -262,7 +280,7 @@
      *
      * @param out mac is empty if signingKeyBlob or the sessionTranscript passed to
      *    startRetrieval() is empty. Otherwise it is a COSE_Mac0 with empty payload
-     *    and the detached content is set to DeviceAuthentication as defined below.
+     *    and the detached content is set to DeviceAuthenticationBytes as defined below.
      *    This code is produced by using the key agreement and key derivation function
      *    from the ciphersuite with the authentication private key and the reader
      *    ephemeral public key to compute a shared message authentication code (MAC)
@@ -274,20 +292,17 @@
      *            "DeviceAuthentication",
      *            SessionTranscript,
      *            DocType,
-     *            DeviceNameSpaceBytes,
+     *            DeviceNameSpacesBytes,
      *        ]
      *
      *        DocType = tstr
      *
-     *        SessionTranscript = [
-     *            DeviceEngagementBytes,
-     *            EReaderKeyBytes
-     *        ]
+     *        SessionTranscript = any
      *
-     *        DeviceEngagementBytes = #6.24(bstr .cbor DeviceEngagement)
-     *        EReaderKeyBytes = #6.24(bstr .cbor EReaderKey.Pub)
      *        DeviceNameSpacesBytes = #6.24(bstr .cbor DeviceNameSpaces)
      *
+     *        DeviceAuthenticationBytes = #6.24(bstr .cbor DeviceAuthentication)
+     *
      *    where
      *
      *        DeviceNameSpaces = {
@@ -337,10 +352,32 @@
      *
      *  - subjectPublicKeyInfo: must contain attested public key.
      *
-     * @param out signingKeyBlob contains an encrypted copy of the newly-generated private
-     *     signing key.
+     * @param out signingKeyBlob contains an AES-GCM-ENC(storageKey, R, signingKey, docType)
+     *     where signingKey is an EC private key in uncompressed form. That is, the returned
+     *     blob is an encrypted copy of the newly-generated private signing key.
      *
      * @return an X.509 certificate for the new signing key, signed by the credential key.
      */
     Certificate generateSigningKeyPair(out byte[] signingKeyBlob);
+
+    /**
+     * Sets the namespaces and data items (including their size and access control profiles)
+     * which will be requested. This method must be called before startRetrieval() is called.
+     *
+     * This information is provided to make it possible for a HAL implementation to
+     * incrementally build up cryptographically authenticated data which includes the
+     * DeviceNameSpaces CBOR.
+     *
+     * @param requestNamespaces Namespaces and data items which will be requested.
+     */
+    void setRequestedNamespaces(in RequestNamespace[] requestNamespaces);
+
+   /**
+    * Sets the VerificationToken. This method must be called before startRetrieval() is
+    * called. This token uses the same challenge as returned by createAuthChallenge().
+    *
+    * @param verificationToken
+    *   The verification token. This token is only valid if the timestamp field is non-zero.
+    */
+    void setVerificationToken(in VerificationToken verificationToken);
 }
diff --git a/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl b/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
index bd664e8..33e25b1 100644
--- a/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
+++ b/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
@@ -99,7 +99,7 @@
  * Various fields need to be encoded as precisely-specified byte arrays.  Where existing standards
  * define appropriate encodings, those are used.  For example, X.509 certificates.  Where new
  * encodings are needed, CBOR is used.  CBOR maps are described in CDDL notation
- * (https://tools.ietf.org/html/draft-ietf-cbor-cddl-06).
+ * (https://tools.ietf.org/html/rfc8610).
  *
  * All binder calls in the HAL may return a ServiceSpecificException with statuses from the
  * STATUS_* integers defined in this interface. Each method states which status can be returned
diff --git a/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
index 07486e6..297fd1d 100644
--- a/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
@@ -29,9 +29,27 @@
      * Gets the certificate chain for credentialKey which can be used to prove the hardware
      * characteristics to an issuing authority.  Must not be called more than once.
      *
+     * The following non-optional fields for the X.509 certificate shall be set as follows:
+     *
+     *  - version: INTEGER 2 (means v3 certificate).
+     *
+     *  - serialNumber: INTEGER 1 (fixed value: same on all certs).
+     *
+     *  - signature: must be set to ECDSA.
+     *
+     *  - subject: CN shall be set to "Android Identity Credential Key".
+     *
+     *  - issuer: shall be set to "credentialStoreName (credentialStoreAuthorName)" using the
+     *    values returned in HardwareInformation.
+     *
+     *  - validity: should be from current time and expire at the same time as the
+     *    attestation batch certificate used.
+     *
+     *  - subjectPublicKeyInfo: must contain attested public key.
+     *
      * The certificate chain must be generated using Keymaster Attestation
      * (see https://source.android.com/security/keystore/attestation) with the
-     * following additional requirements:
+     * following additional requirements on the data in the attestation extension:
      *
      *  - The attestationVersion field in the attestation extension must be at least 3.
      *
@@ -109,7 +127,8 @@
      *     in Tag::ATTESTATION_APPLICATION_ID. This schema is described in
      *     https://developer.android.com/training/articles/security-key-attestation#certificate_schema_attestationid
      *
-     * @param attestationChallenge a challenge set by the issuer to ensure freshness.
+     * @param attestationChallenge a challenge set by the issuer to ensure freshness. If
+     *    this is empty, the call fails with STATUS_INVALID_DATA.
      *
      * @return the X.509 certificate chain for the credentialKey
      */
@@ -120,6 +139,8 @@
      *
      * startPersonalization must not be called more than once.
      *
+     * The setExpectedProofOfProvisioningSize() method will be called before this method.
+     *
      * @param accessControlProfileCount specifies the number of access control profiles that will
      *     be provisioned with addAccessControlProfile().
      *
@@ -248,6 +269,7 @@
      *         CredentialKeys = [
      *              bstr,   ; storageKey, a 128-bit AES key
      *              bstr    ; credentialPrivKey, the private key for credentialKey
+     *                      ; in uncompressed form
      *         ]
      *
      * @param out proofOfProvisioningSignature proves to the IA that the credential was imported
@@ -288,4 +310,16 @@
      */
     void finishAddingEntries(out byte[] credentialData,
         out byte[] proofOfProvisioningSignature);
+
+    /**
+     * Sets the expected size of the ProofOfProvisioning returned by finishAddingEntries(). This
+     * method must be called before startPersonalization() is called.
+     *
+     * This information is provided to make it possible for a HAL implementation to
+     * incrementally build up cryptographically authenticated data which includes the
+     * ProofOfProvisioning CBOR.
+     *
+     * @param expectedProofOfProvisioningSize the expected size of ProofOfProvisioning.
+     */
+    void setExpectedProofOfProvisioningSize(in int expectedProofOfProvisioningSize);
 }
diff --git a/identity/aidl/android/hardware/identity/RequestDataItem.aidl b/identity/aidl/android/hardware/identity/RequestDataItem.aidl
new file mode 100644
index 0000000..05bc762
--- /dev/null
+++ b/identity/aidl/android/hardware/identity/RequestDataItem.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.identity;
+
+@VintfStability
+parcelable RequestDataItem {
+    /**
+     * The data item name being requested, for example "driving_privileges".
+     */
+    @utf8InCpp String name;
+
+    /**
+     * The size of the data item value.
+     *
+     * Data item values are always encoded as CBOR so this is the length of
+     * the CBOR encoding of the value.
+     */
+    long size;
+
+    /**
+     * The access control profile ids this data item is configured with.
+     */
+    int[] accessControlProfileIds;
+}
diff --git a/identity/aidl/android/hardware/identity/RequestNamespace.aidl b/identity/aidl/android/hardware/identity/RequestNamespace.aidl
new file mode 100644
index 0000000..4d61506
--- /dev/null
+++ b/identity/aidl/android/hardware/identity/RequestNamespace.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.identity;
+
+import android.hardware.identity.RequestDataItem;
+
+@VintfStability
+parcelable RequestNamespace {
+    /**
+     * The name of the namespace that items are being requested from, for
+     * example "org.iso.18013.5.1".
+     */
+    @utf8InCpp String namespaceName;
+
+    /**
+     * The data items requested.
+     */
+    RequestDataItem[] items;
+}
diff --git a/identity/aidl/default/IdentityCredential.cpp b/identity/aidl/default/IdentityCredential.cpp
index 341fae6..87d9a93 100644
--- a/identity/aidl/default/IdentityCredential.cpp
+++ b/identity/aidl/default/IdentityCredential.cpp
@@ -25,6 +25,7 @@
 #include <string.h>
 
 #include <android-base/logging.h>
+#include <android-base/stringprintf.h>
 
 #include <cppbor.h>
 #include <cppbor_parse.h>
@@ -32,11 +33,16 @@
 namespace aidl::android::hardware::identity {
 
 using ::aidl::android::hardware::keymaster::Timestamp;
+using ::android::base::StringPrintf;
 using ::std::optional;
 
 using namespace ::android::hardware::identity;
 
 int IdentityCredential::initialize() {
+    if (credentialData_.size() == 0) {
+        LOG(ERROR) << "CredentialData is empty";
+        return IIdentityCredentialStore::STATUS_INVALID_DATA;
+    }
     auto [item, _, message] = cppbor::parse(credentialData_);
     if (item == nullptr) {
         LOG(ERROR) << "CredentialData is not valid CBOR: " << message;
@@ -102,7 +108,7 @@
 }
 
 ndk::ScopedAStatus IdentityCredential::deleteCredential(
-        vector<int8_t>* outProofOfDeletionSignature) {
+        vector<uint8_t>* outProofOfDeletionSignature) {
     cppbor::Array array = {"ProofOfDeletion", docType_, testCredential_};
     vector<uint8_t> proofOfDeletion = array.encode();
 
@@ -115,11 +121,11 @@
                 IIdentityCredentialStore::STATUS_FAILED, "Error signing data"));
     }
 
-    *outProofOfDeletionSignature = byteStringToSigned(signature.value());
+    *outProofOfDeletionSignature = signature.value();
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus IdentityCredential::createEphemeralKeyPair(vector<int8_t>* outKeyPair) {
+ndk::ScopedAStatus IdentityCredential::createEphemeralKeyPair(vector<uint8_t>* outKeyPair) {
     optional<vector<uint8_t>> kp = support::createEcKeyPair();
     if (!kp) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -135,13 +141,13 @@
     }
     ephemeralPublicKey_ = publicKey.value();
 
-    *outKeyPair = byteStringToSigned(kp.value());
+    *outKeyPair = kp.value();
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus IdentityCredential::setReaderEphemeralPublicKey(
-        const vector<int8_t>& publicKey) {
-    readerPublicKey_ = byteStringToUnsigned(publicKey);
+        const vector<uint8_t>& publicKey) {
+    readerPublicKey_ = publicKey;
     return ndk::ScopedAStatus::ok();
 }
 
@@ -162,6 +168,7 @@
     }
 
     *outChallenge = challenge;
+    authChallenge_ = challenge;
     return ndk::ScopedAStatus::ok();
 }
 
@@ -169,8 +176,8 @@
 // ahead of time.
 bool checkReaderAuthentication(const SecureAccessControlProfile& profile,
                                const vector<uint8_t>& readerCertificateChain) {
-    optional<vector<uint8_t>> acpPubKey = support::certificateChainGetTopMostKey(
-            byteStringToUnsigned(profile.readerCertificate.encodedCertificate));
+    optional<vector<uint8_t>> acpPubKey =
+            support::certificateChainGetTopMostKey(profile.readerCertificate.encodedCertificate);
     if (!acpPubKey) {
         LOG(ERROR) << "Error extracting public key from readerCertificate in profile";
         return false;
@@ -196,15 +203,8 @@
     return false;
 }
 
-Timestamp clockGetTime() {
-    struct timespec time;
-    clock_gettime(CLOCK_MONOTONIC, &time);
-    Timestamp ts;
-    ts.milliSeconds = time.tv_sec * 1000 + time.tv_nsec / 1000000;
-    return ts;
-}
-
 bool checkUserAuthentication(const SecureAccessControlProfile& profile,
+                             const VerificationToken& verificationToken,
                              const HardwareAuthToken& authToken, uint64_t authChallenge) {
     if (profile.secureUserId != authToken.userId) {
         LOG(ERROR) << "secureUserId in profile (" << profile.secureUserId
@@ -212,6 +212,15 @@
         return false;
     }
 
+    if (verificationToken.timestamp.milliSeconds == 0) {
+        LOG(ERROR) << "VerificationToken is not set";
+        return false;
+    }
+    if (authToken.timestamp.milliSeconds == 0) {
+        LOG(ERROR) << "AuthToken is not set";
+        return false;
+    }
+
     if (profile.timeoutMillis == 0) {
         if (authToken.challenge == 0) {
             LOG(ERROR) << "No challenge in authToken";
@@ -219,25 +228,18 @@
         }
 
         if (authToken.challenge != int64_t(authChallenge)) {
-            LOG(ERROR) << "Challenge in authToken doesn't match the challenge we created";
+            LOG(ERROR) << "Challenge in authToken (" << uint64_t(authToken.challenge) << ") "
+                       << "doesn't match the challenge we created (" << authChallenge << ")";
             return false;
         }
         return true;
     }
 
-    // Note that the Epoch for timestamps in HardwareAuthToken is at the
-    // discretion of the vendor:
+    // Timeout-based user auth follows. The verification token conveys what the
+    // time is right now in the environment which generated the auth token. This
+    // is what makes it possible to do timeout-based checks.
     //
-    //   "[...] since some starting point (generally the most recent device
-    //    boot) which all of the applications within one secure environment
-    //    must agree upon."
-    //
-    // Therefore, if this software implementation is used on a device which isn't
-    // the emulator then the assumption that the epoch is the same as used in
-    // clockGetTime above will not hold. This is OK as this software
-    // implementation should never be used on a real device.
-    //
-    Timestamp now = clockGetTime();
+    const Timestamp now = verificationToken.timestamp;
     if (authToken.timestamp.milliSeconds > now.milliSeconds) {
         LOG(ERROR) << "Timestamp in authToken (" << authToken.timestamp.milliSeconds
                    << ") is in the future (now: " << now.milliSeconds << ")";
@@ -253,15 +255,23 @@
     return true;
 }
 
+ndk::ScopedAStatus IdentityCredential::setRequestedNamespaces(
+        const vector<RequestNamespace>& requestNamespaces) {
+    requestNamespaces_ = requestNamespaces;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus IdentityCredential::setVerificationToken(
+        const VerificationToken& verificationToken) {
+    verificationToken_ = verificationToken;
+    return ndk::ScopedAStatus::ok();
+}
+
 ndk::ScopedAStatus IdentityCredential::startRetrieval(
         const vector<SecureAccessControlProfile>& accessControlProfiles,
-        const HardwareAuthToken& authToken, const vector<int8_t>& itemsRequestS,
-        const vector<int8_t>& signingKeyBlobS, const vector<int8_t>& sessionTranscriptS,
-        const vector<int8_t>& readerSignatureS, const vector<int32_t>& requestCounts) {
-    auto sessionTranscript = byteStringToUnsigned(sessionTranscriptS);
-    auto itemsRequest = byteStringToUnsigned(itemsRequestS);
-    auto readerSignature = byteStringToUnsigned(readerSignatureS);
-
+        const HardwareAuthToken& authToken, const vector<uint8_t>& itemsRequest,
+        const vector<uint8_t>& signingKeyBlob, const vector<uint8_t>& sessionTranscript,
+        const vector<uint8_t>& readerSignature, const vector<int32_t>& requestCounts) {
     if (sessionTranscript.size() > 0) {
         auto [item, _, message] = cppbor::parse(sessionTranscript);
         if (item == nullptr) {
@@ -306,13 +316,16 @@
         }
 
         const vector<uint8_t>& itemsRequestBytes = itemsRequest;
-        vector<uint8_t> dataThatWasSigned = cppbor::Array()
-                                                    .add("ReaderAuthentication")
-                                                    .add(sessionTranscriptItem_->clone())
-                                                    .add(cppbor::Semantic(24, itemsRequestBytes))
-                                                    .encode();
+        vector<uint8_t> encodedReaderAuthentication =
+                cppbor::Array()
+                        .add("ReaderAuthentication")
+                        .add(sessionTranscriptItem_->clone())
+                        .add(cppbor::Semantic(24, itemsRequestBytes))
+                        .encode();
+        vector<uint8_t> encodedReaderAuthenticationBytes =
+                cppbor::Semantic(24, encodedReaderAuthentication).encode();
         if (!support::coseCheckEcDsaSignature(readerSignature,
-                                              dataThatWasSigned,  // detached content
+                                              encodedReaderAuthenticationBytes,  // detached content
                                               readerPublicKey.value())) {
             return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                     IIdentityCredentialStore::STATUS_READER_SIGNATURE_CHECK_FAILED,
@@ -333,28 +346,6 @@
     //
     // We do this by just searching for the X and Y coordinates.
     if (sessionTranscript.size() > 0) {
-        const cppbor::Array* array = sessionTranscriptItem_->asArray();
-        if (array == nullptr || array->size() != 2) {
-            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
-                    IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
-                    "SessionTranscript is not an array with two items"));
-        }
-        const cppbor::Semantic* taggedEncodedDE = (*array)[0]->asSemantic();
-        if (taggedEncodedDE == nullptr || taggedEncodedDE->value() != 24) {
-            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
-                    IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
-                    "First item in SessionTranscript array is not a "
-                    "semantic with value 24"));
-        }
-        const cppbor::Bstr* encodedDE = (taggedEncodedDE->child())->asBstr();
-        if (encodedDE == nullptr) {
-            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
-                    IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
-                    "Child of semantic in first item in SessionTranscript "
-                    "array is not a bstr"));
-        }
-        const vector<uint8_t>& bytesDE = encodedDE->value();
-
         auto [getXYSuccess, ePubX, ePubY] = support::ecPublicKeyGetXandY(ephemeralPublicKey_);
         if (!getXYSuccess) {
             return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
@@ -362,8 +353,10 @@
                     "Error extracting X and Y from ePub"));
         }
         if (sessionTranscript.size() > 0 &&
-            !(memmem(bytesDE.data(), bytesDE.size(), ePubX.data(), ePubX.size()) != nullptr &&
-              memmem(bytesDE.data(), bytesDE.size(), ePubY.data(), ePubY.size()) != nullptr)) {
+            !(memmem(sessionTranscript.data(), sessionTranscript.size(), ePubX.data(),
+                     ePubX.size()) != nullptr &&
+              memmem(sessionTranscript.data(), sessionTranscript.size(), ePubY.data(),
+                     ePubY.size()) != nullptr)) {
             return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                     IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
                     "Did not find ephemeral public key's X and Y coordinates in "
@@ -451,7 +444,7 @@
                         "Type mismatch in nameSpaces map"));
             }
             string requestedNamespace = nsKey->value();
-            vector<string> requestedKeys;
+            set<string> requestedKeys;
             for (size_t m = 0; m < nsInnerMap->size(); m++) {
                 const auto& [innerMapKeyItem, innerMapValueItem] = (*nsInnerMap)[m];
                 const cppbor::Tstr* nameItem = innerMapKeyItem->asTstr();
@@ -463,23 +456,25 @@
                             IIdentityCredentialStore::STATUS_INVALID_ITEMS_REQUEST_MESSAGE,
                             "Type mismatch in value in nameSpaces map"));
                 }
-                requestedKeys.push_back(nameItem->value());
+                requestedKeys.insert(nameItem->value());
             }
             requestedNameSpacesAndNames_[requestedNamespace] = requestedKeys;
         }
     }
 
-    // Finally, validate all the access control profiles in the requestData.
-    bool haveAuthToken = (authToken.mac.size() > 0);
+    // Validate all the access control profiles in the requestData.
+    bool haveAuthToken = (authToken.timestamp.milliSeconds != int64_t(0));
     for (const auto& profile : accessControlProfiles) {
         if (!secureAccessControlProfileCheckMac(profile, storageKey_)) {
+            LOG(ERROR) << "Error checking MAC for profile";
             return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                     IIdentityCredentialStore::STATUS_INVALID_DATA,
                     "Error checking MAC for profile"));
         }
         int accessControlCheck = IIdentityCredentialStore::STATUS_OK;
         if (profile.userAuthenticationRequired) {
-            if (!haveAuthToken || !checkUserAuthentication(profile, authToken, authChallenge_)) {
+            if (!haveAuthToken ||
+                !checkUserAuthentication(profile, verificationToken_, authToken, authChallenge_)) {
                 accessControlCheck = IIdentityCredentialStore::STATUS_USER_AUTHENTICATION_FAILED;
             }
         } else if (profile.readerCertificate.encodedCertificate.size() > 0) {
@@ -498,12 +493,120 @@
     currentNameSpace_ = "";
 
     itemsRequest_ = itemsRequest;
-    signingKeyBlob_ = byteStringToUnsigned(signingKeyBlobS);
+    signingKeyBlob_ = signingKeyBlob;
+
+    // Finally, calculate the size of DeviceNameSpaces. We need to know it ahead of time.
+    expectedDeviceNameSpacesSize_ = calcDeviceNameSpacesSize();
 
     numStartRetrievalCalls_ += 1;
     return ndk::ScopedAStatus::ok();
 }
 
+size_t cborNumBytesForLength(size_t length) {
+    if (length < 24) {
+        return 0;
+    } else if (length <= 0xff) {
+        return 1;
+    } else if (length <= 0xffff) {
+        return 2;
+    } else if (length <= 0xffffffff) {
+        return 4;
+    }
+    return 8;
+}
+
+size_t cborNumBytesForTstr(const string& value) {
+    return 1 + cborNumBytesForLength(value.size()) + value.size();
+}
+
+size_t IdentityCredential::calcDeviceNameSpacesSize() {
+    /*
+     * This is how DeviceNameSpaces is defined:
+     *
+     *        DeviceNameSpaces = {
+     *            * NameSpace => DeviceSignedItems
+     *        }
+     *        DeviceSignedItems = {
+     *            + DataItemName => DataItemValue
+     *        }
+     *
+     *        Namespace = tstr
+     *        DataItemName = tstr
+     *        DataItemValue = any
+     *
+     * This function will calculate its length using knowledge of how CBOR is
+     * encoded.
+     */
+    size_t ret = 0;
+    size_t numNamespacesWithValues = 0;
+    for (const RequestNamespace& rns : requestNamespaces_) {
+        vector<RequestDataItem> itemsToInclude;
+
+        for (const RequestDataItem& rdi : rns.items) {
+            // If we have a CBOR request message, skip if item isn't in it
+            if (itemsRequest_.size() > 0) {
+                const auto& it = requestedNameSpacesAndNames_.find(rns.namespaceName);
+                if (it == requestedNameSpacesAndNames_.end()) {
+                    continue;
+                }
+                const set<string>& dataItemNames = it->second;
+                if (dataItemNames.find(rdi.name) == dataItemNames.end()) {
+                    continue;
+                }
+            }
+
+            // Access is granted if at least one of the profiles grants access.
+            //
+            // If an item is configured without any profiles, access is denied.
+            //
+            bool authorized = false;
+            for (auto id : rdi.accessControlProfileIds) {
+                auto it = profileIdToAccessCheckResult_.find(id);
+                if (it != profileIdToAccessCheckResult_.end()) {
+                    int accessControlForProfile = it->second;
+                    if (accessControlForProfile == IIdentityCredentialStore::STATUS_OK) {
+                        authorized = true;
+                        break;
+                    }
+                }
+            }
+            if (!authorized) {
+                continue;
+            }
+
+            itemsToInclude.push_back(rdi);
+        }
+
+        // If no entries are to be in the namespace, we don't include it...
+        if (itemsToInclude.size() == 0) {
+            continue;
+        }
+
+        // Key: NameSpace
+        ret += cborNumBytesForTstr(rns.namespaceName);
+
+        // Value: Open the DeviceSignedItems map
+        ret += 1 + cborNumBytesForLength(itemsToInclude.size());
+
+        for (const RequestDataItem& item : itemsToInclude) {
+            // Key: DataItemName
+            ret += cborNumBytesForTstr(item.name);
+
+            // Value: DataItemValue - entryData.size is the length of serialized CBOR so we use
+            // that.
+            ret += item.size;
+        }
+
+        numNamespacesWithValues++;
+    }
+
+    // Now that we now the nunber of namespaces with values, we know how many
+    // bytes the DeviceNamespaces map in the beginning is going to take up.
+    ret += 1 + cborNumBytesForLength(numNamespacesWithValues);
+
+    return ret;
+}
+
 ndk::ScopedAStatus IdentityCredential::startRetrieveEntryValue(
         const string& nameSpace, const string& name, int32_t entrySize,
         const vector<int32_t>& accessControlProfileIds) {
@@ -562,8 +665,8 @@
                     IIdentityCredentialStore::STATUS_NOT_IN_REQUEST_MESSAGE,
                     "Name space was not requested in startRetrieval"));
         }
-        const auto& dataItemNames = it->second;
-        if (std::find(dataItemNames.begin(), dataItemNames.end(), name) == dataItemNames.end()) {
+        const set<string>& dataItemNames = it->second;
+        if (dataItemNames.find(name) == dataItemNames.end()) {
             return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                     IIdentityCredentialStore::STATUS_NOT_IN_REQUEST_MESSAGE,
                     "Data item name in name space was not requested in startRetrieval"));
@@ -605,10 +708,8 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus IdentityCredential::retrieveEntryValue(const vector<int8_t>& encryptedContentS,
-                                                          vector<int8_t>* outContent) {
-    auto encryptedContent = byteStringToUnsigned(encryptedContentS);
-
+ndk::ScopedAStatus IdentityCredential::retrieveEntryValue(const vector<uint8_t>& encryptedContent,
+                                                          vector<uint8_t>* outContent) {
     optional<vector<uint8_t>> content =
             support::decryptAes128Gcm(storageKey_, encryptedContent, entryAdditionalData_);
     if (!content) {
@@ -647,18 +748,29 @@
         currentNameSpaceDeviceNameSpacesMap_.add(currentName_, std::move(entryValueItem));
     }
 
-    *outContent = byteStringToSigned(content.value());
+    *outContent = content.value();
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<int8_t>* outMac,
-                                                       vector<int8_t>* outDeviceNameSpaces) {
+ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<uint8_t>* outMac,
+                                                       vector<uint8_t>* outDeviceNameSpaces) {
     if (currentNameSpaceDeviceNameSpacesMap_.size() > 0) {
         deviceNameSpacesMap_.add(currentNameSpace_,
                                  std::move(currentNameSpaceDeviceNameSpacesMap_));
     }
     vector<uint8_t> encodedDeviceNameSpaces = deviceNameSpacesMap_.encode();
 
+    if (encodedDeviceNameSpaces.size() != expectedDeviceNameSpacesSize_) {
+        LOG(ERROR) << "encodedDeviceNameSpaces is " << encodedDeviceNameSpaces.size() << " bytes, "
+                   << "was expecting " << expectedDeviceNameSpacesSize_;
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA,
+                StringPrintf(
+                        "Unexpected CBOR size %zd for encodedDeviceNameSpaces, was expecting %zd",
+                        encodedDeviceNameSpaces.size(), expectedDeviceNameSpacesSize_)
+                        .c_str()));
+    }
+
     // If there's no signing key or no sessionTranscript or no reader ephemeral
     // public key, we return the empty MAC.
     optional<vector<uint8_t>> mac;
@@ -669,7 +781,7 @@
         array.add(sessionTranscriptItem_->clone());
         array.add(docType_);
         array.add(cppbor::Semantic(24, encodedDeviceNameSpaces));
-        vector<uint8_t> encodedDeviceAuthentication = array.encode();
+        vector<uint8_t> deviceAuthenticationBytes = cppbor::Semantic(24, array.encode()).encode();
 
         vector<uint8_t> docTypeAsBlob(docType_.begin(), docType_.end());
         optional<vector<uint8_t>> signingKey =
@@ -687,30 +799,37 @@
                     IIdentityCredentialStore::STATUS_FAILED, "Error doing ECDH"));
         }
 
+        // Mix-in SessionTranscriptBytes
+        vector<uint8_t> sessionTranscriptBytes = cppbor::Semantic(24, sessionTranscript_).encode();
+        vector<uint8_t> sharedSecretWithSessionTranscriptBytes = sharedSecret.value();
+        std::copy(sessionTranscriptBytes.begin(), sessionTranscriptBytes.end(),
+                  std::back_inserter(sharedSecretWithSessionTranscriptBytes));
+
         vector<uint8_t> salt = {0x00};
         vector<uint8_t> info = {};
-        optional<vector<uint8_t>> derivedKey = support::hkdf(sharedSecret.value(), salt, info, 32);
+        optional<vector<uint8_t>> derivedKey =
+                support::hkdf(sharedSecretWithSessionTranscriptBytes, salt, info, 32);
         if (!derivedKey) {
             return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                     IIdentityCredentialStore::STATUS_FAILED,
                     "Error deriving key from shared secret"));
         }
 
-        mac = support::coseMac0(derivedKey.value(), {},        // payload
-                                encodedDeviceAuthentication);  // additionalData
+        mac = support::coseMac0(derivedKey.value(), {},      // payload
+                                deviceAuthenticationBytes);  // detached content
         if (!mac) {
             return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                     IIdentityCredentialStore::STATUS_FAILED, "Error MACing data"));
         }
     }
 
-    *outMac = byteStringToSigned(mac.value_or(vector<uint8_t>({})));
-    *outDeviceNameSpaces = byteStringToSigned(encodedDeviceNameSpaces);
+    *outMac = mac.value_or(vector<uint8_t>({}));
+    *outDeviceNameSpaces = encodedDeviceNameSpaces;
     return ndk::ScopedAStatus::ok();
 }
 
 ndk::ScopedAStatus IdentityCredential::generateSigningKeyPair(
-        vector<int8_t>* outSigningKeyBlob, Certificate* outSigningKeyCertificate) {
+        vector<uint8_t>* outSigningKeyBlob, Certificate* outSigningKeyCertificate) {
     string serialDecimal = "0";  // TODO: set serial to something unique
     string issuer = "Android Open Source Project";
     string subject = "Android IdentityCredential Reference Implementation";
@@ -758,9 +877,9 @@
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                 IIdentityCredentialStore::STATUS_FAILED, "Error encrypting signingKey"));
     }
-    *outSigningKeyBlob = byteStringToSigned(encryptedSigningKey.value());
+    *outSigningKeyBlob = encryptedSigningKey.value();
     *outSigningKeyCertificate = Certificate();
-    outSigningKeyCertificate->encodedCertificate = byteStringToSigned(certificate.value());
+    outSigningKeyCertificate->encodedCertificate = certificate.value();
     return ndk::ScopedAStatus::ok();
 }
 
diff --git a/identity/aidl/default/IdentityCredential.h b/identity/aidl/default/IdentityCredential.h
index fc29254..a82531d 100644
--- a/identity/aidl/default/IdentityCredential.h
+++ b/identity/aidl/default/IdentityCredential.h
@@ -19,6 +19,7 @@
 
 #include <aidl/android/hardware/identity/BnIdentityCredential.h>
 #include <aidl/android/hardware/keymaster/HardwareAuthToken.h>
+#include <aidl/android/hardware/keymaster/VerificationToken.h>
 #include <android/hardware/identity/support/IdentityCredentialSupport.h>
 
 #include <map>
@@ -31,39 +32,45 @@
 namespace aidl::android::hardware::identity {
 
 using ::aidl::android::hardware::keymaster::HardwareAuthToken;
+using ::aidl::android::hardware::keymaster::VerificationToken;
 using ::std::map;
+using ::std::set;
 using ::std::string;
 using ::std::vector;
 
-using MapStringToVectorOfStrings = map<string, vector<string>>;
-
 class IdentityCredential : public BnIdentityCredential {
   public:
     IdentityCredential(const vector<uint8_t>& credentialData)
-        : credentialData_(credentialData), numStartRetrievalCalls_(0), authChallenge_(0) {}
+        : credentialData_(credentialData),
+          numStartRetrievalCalls_(0),
+          authChallenge_(0),
+          expectedDeviceNameSpacesSize_(0) {}
 
     // Parses and decrypts credentialData_, return a status code from
     // IIdentityCredentialStore. Must be called right after construction.
     int initialize();
 
     // Methods from IIdentityCredential follow.
-    ndk::ScopedAStatus deleteCredential(vector<int8_t>* outProofOfDeletionSignature) override;
-    ndk::ScopedAStatus createEphemeralKeyPair(vector<int8_t>* outKeyPair) override;
-    ndk::ScopedAStatus setReaderEphemeralPublicKey(const vector<int8_t>& publicKey) override;
+    ndk::ScopedAStatus deleteCredential(vector<uint8_t>* outProofOfDeletionSignature) override;
+    ndk::ScopedAStatus createEphemeralKeyPair(vector<uint8_t>* outKeyPair) override;
+    ndk::ScopedAStatus setReaderEphemeralPublicKey(const vector<uint8_t>& publicKey) override;
     ndk::ScopedAStatus createAuthChallenge(int64_t* outChallenge) override;
+    ndk::ScopedAStatus setRequestedNamespaces(
+            const vector<RequestNamespace>& requestNamespaces) override;
+    ndk::ScopedAStatus setVerificationToken(const VerificationToken& verificationToken) override;
     ndk::ScopedAStatus startRetrieval(
             const vector<SecureAccessControlProfile>& accessControlProfiles,
-            const HardwareAuthToken& authToken, const vector<int8_t>& itemsRequest,
-            const vector<int8_t>& signingKeyBlob, const vector<int8_t>& sessionTranscript,
-            const vector<int8_t>& readerSignature, const vector<int32_t>& requestCounts) override;
+            const HardwareAuthToken& authToken, const vector<uint8_t>& itemsRequest,
+            const vector<uint8_t>& signingKeyBlob, const vector<uint8_t>& sessionTranscript,
+            const vector<uint8_t>& readerSignature, const vector<int32_t>& requestCounts) override;
     ndk::ScopedAStatus startRetrieveEntryValue(
             const string& nameSpace, const string& name, int32_t entrySize,
             const vector<int32_t>& accessControlProfileIds) override;
-    ndk::ScopedAStatus retrieveEntryValue(const vector<int8_t>& encryptedContent,
-                                          vector<int8_t>* outContent) override;
-    ndk::ScopedAStatus finishRetrieval(vector<int8_t>* outMac,
-                                       vector<int8_t>* outDeviceNameSpaces) override;
-    ndk::ScopedAStatus generateSigningKeyPair(vector<int8_t>* outSigningKeyBlob,
+    ndk::ScopedAStatus retrieveEntryValue(const vector<uint8_t>& encryptedContent,
+                                          vector<uint8_t>* outContent) override;
+    ndk::ScopedAStatus finishRetrieval(vector<uint8_t>* outMac,
+                                       vector<uint8_t>* outDeviceNameSpaces) override;
+    ndk::ScopedAStatus generateSigningKeyPair(vector<uint8_t>* outSigningKeyBlob,
                                               Certificate* outSigningKeyCertificate) override;
 
   private:
@@ -86,6 +93,12 @@
     // Set by createAuthChallenge()
     uint64_t authChallenge_;
 
+    // Set by setRequestedNamespaces()
+    vector<RequestNamespace> requestNamespaces_;
+
+    // Set by setVerificationToken().
+    VerificationToken verificationToken_;
+
     // Set at startRetrieval() time.
     map<int32_t, int> profileIdToAccessCheckResult_;
     vector<uint8_t> signingKeyBlob_;
@@ -93,16 +106,21 @@
     std::unique_ptr<cppbor::Item> sessionTranscriptItem_;
     vector<uint8_t> itemsRequest_;
     vector<int32_t> requestCountsRemaining_;
-    MapStringToVectorOfStrings requestedNameSpacesAndNames_;
+    map<string, set<string>> requestedNameSpacesAndNames_;
     cppbor::Map deviceNameSpacesMap_;
     cppbor::Map currentNameSpaceDeviceNameSpacesMap_;
 
+    // Calculated at startRetrieval() time.
+    size_t expectedDeviceNameSpacesSize_;
+
     // Set at startRetrieveEntryValue() time.
     string currentNameSpace_;
     string currentName_;
     size_t entryRemainingBytes_;
     vector<uint8_t> entryValue_;
     vector<uint8_t> entryAdditionalData_;
+
+    size_t calcDeviceNameSpacesSize();
 };
 
 }  // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/IdentityCredentialStore.cpp b/identity/aidl/default/IdentityCredentialStore.cpp
index 1efb4b4..30dc6f3 100644
--- a/identity/aidl/default/IdentityCredentialStore.cpp
+++ b/identity/aidl/default/IdentityCredentialStore.cpp
@@ -51,7 +51,7 @@
 }
 
 ndk::ScopedAStatus IdentityCredentialStore::getCredential(
-        CipherSuite cipherSuite, const vector<int8_t>& credentialData,
+        CipherSuite cipherSuite, const vector<uint8_t>& credentialData,
         shared_ptr<IIdentityCredential>* outCredential) {
     // We only support CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 right now.
     if (cipherSuite != CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256) {
@@ -60,8 +60,8 @@
                 "Unsupported cipher suite"));
     }
 
-    vector<uint8_t> data = vector<uint8_t>(credentialData.begin(), credentialData.end());
-    shared_ptr<IdentityCredential> credential = ndk::SharedRefBase::make<IdentityCredential>(data);
+    shared_ptr<IdentityCredential> credential =
+            ndk::SharedRefBase::make<IdentityCredential>(credentialData);
     auto ret = credential->initialize();
     if (ret != IIdentityCredentialStore::STATUS_OK) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
diff --git a/identity/aidl/default/IdentityCredentialStore.h b/identity/aidl/default/IdentityCredentialStore.h
index a205113..4f3a421 100644
--- a/identity/aidl/default/IdentityCredentialStore.h
+++ b/identity/aidl/default/IdentityCredentialStore.h
@@ -39,7 +39,7 @@
             const string& docType, bool testCredential,
             shared_ptr<IWritableIdentityCredential>* outWritableCredential) override;
 
-    ndk::ScopedAStatus getCredential(CipherSuite cipherSuite, const vector<int8_t>& credentialData,
+    ndk::ScopedAStatus getCredential(CipherSuite cipherSuite, const vector<uint8_t>& credentialData,
                                      shared_ptr<IIdentityCredential>* outCredential) override;
 };
 
diff --git a/identity/aidl/default/Util.cpp b/identity/aidl/default/Util.cpp
index a0f86be..66b9f13 100644
--- a/identity/aidl/default/Util.cpp
+++ b/identity/aidl/default/Util.cpp
@@ -39,21 +39,12 @@
     return hardwareBoundKey;
 }
 
-vector<uint8_t> byteStringToUnsigned(const vector<int8_t>& value) {
-    return vector<uint8_t>(value.begin(), value.end());
-}
-
-vector<int8_t> byteStringToSigned(const vector<uint8_t>& value) {
-    return vector<int8_t>(value.begin(), value.end());
-}
-
 vector<uint8_t> secureAccessControlProfileEncodeCbor(const SecureAccessControlProfile& profile) {
     cppbor::Map map;
     map.add("id", profile.id);
 
     if (profile.readerCertificate.encodedCertificate.size() > 0) {
-        map.add("readerCertificate",
-                cppbor::Bstr(byteStringToUnsigned(profile.readerCertificate.encodedCertificate)));
+        map.add("readerCertificate", cppbor::Bstr(profile.readerCertificate.encodedCertificate));
     }
 
     if (profile.userAuthenticationRequired) {
@@ -94,7 +85,7 @@
     if (!mac) {
         return false;
     }
-    if (mac.value() != byteStringToUnsigned(profile.mac)) {
+    if (mac.value() != profile.mac) {
         return false;
     }
     return true;
diff --git a/identity/aidl/default/Util.h b/identity/aidl/default/Util.h
index ee41ad1..9fccba2 100644
--- a/identity/aidl/default/Util.h
+++ b/identity/aidl/default/Util.h
@@ -49,10 +49,6 @@
 vector<uint8_t> entryCreateAdditionalData(const string& nameSpace, const string& name,
                                           const vector<int32_t> accessControlProfileIds);
 
-vector<uint8_t> byteStringToUnsigned(const vector<int8_t>& value);
-
-vector<int8_t> byteStringToSigned(const vector<uint8_t>& value);
-
 }  // namespace aidl::android::hardware::identity
 
 #endif  // ANDROID_HARDWARE_IDENTITY_UTIL_H
diff --git a/identity/aidl/default/WritableIdentityCredential.cpp b/identity/aidl/default/WritableIdentityCredential.cpp
index 52cd496..fea289b 100644
--- a/identity/aidl/default/WritableIdentityCredential.cpp
+++ b/identity/aidl/default/WritableIdentityCredential.cpp
@@ -22,6 +22,7 @@
 #include <android/hardware/identity/support/IdentityCredentialSupport.h>
 
 #include <android-base/logging.h>
+#include <android-base/stringprintf.h>
 
 #include <cppbor/cppbor.h>
 #include <cppbor/cppbor_parse.h>
@@ -34,6 +35,7 @@
 
 namespace aidl::android::hardware::identity {
 
+using ::android::base::StringPrintf;
 using ::std::optional;
 using namespace ::android::hardware::identity;
 
@@ -55,14 +57,18 @@
 // attestation certificate with current time and expires one year from now.  The
 // certificate shall contain all values as specified in hal.
 ndk::ScopedAStatus WritableIdentityCredential::getAttestationCertificate(
-        const vector<int8_t>& attestationApplicationId,  //
-        const vector<int8_t>& attestationChallenge,      //
+        const vector<uint8_t>& attestationApplicationId,  //
+        const vector<uint8_t>& attestationChallenge,      //
         vector<Certificate>* outCertificateChain) {
     if (!credentialPrivKey_.empty() || !credentialPubKey_.empty() || !certificateChain_.empty()) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                 IIdentityCredentialStore::STATUS_FAILED,
                 "Error attestation certificate previously generated"));
     }
+    if (attestationChallenge.empty()) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA, "Challenge can not be empty"));
+    }
 
     vector<uint8_t> challenge(attestationChallenge.begin(), attestationChallenge.end());
     vector<uint8_t> appId(attestationApplicationId.begin(), attestationApplicationId.end());
@@ -99,12 +105,18 @@
     *outCertificateChain = vector<Certificate>();
     for (const vector<uint8_t>& cert : certificateChain_) {
         Certificate c = Certificate();
-        c.encodedCertificate = byteStringToSigned(cert);
+        c.encodedCertificate = cert;
         outCertificateChain->push_back(std::move(c));
     }
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus WritableIdentityCredential::setExpectedProofOfProvisioningSize(
+        int32_t expectedProofOfProvisioningSize) {
+    expectedProofOfProvisioningSize_ = expectedProofOfProvisioningSize;
+    return ndk::ScopedAStatus::ok();
+}
+
 ndk::ScopedAStatus WritableIdentityCredential::startPersonalization(
         int32_t accessControlProfileCount, const vector<int32_t>& entryCounts) {
     if (startPersonalizationCalled_) {
@@ -157,6 +169,13 @@
                 "userAuthenticationRequired is false but timeout is non-zero"));
     }
 
+    // If |userAuthenticationRequired| is true, then |secureUserId| must be non-zero.
+    if (userAuthenticationRequired && secureUserId == 0) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA,
+                "userAuthenticationRequired is true but secureUserId is zero"));
+    }
+
     profile.id = id;
     profile.readerCertificate = readerCertificate;
     profile.userAuthenticationRequired = userAuthenticationRequired;
@@ -167,14 +186,13 @@
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                 IIdentityCredentialStore::STATUS_FAILED, "Error calculating MAC for profile"));
     }
-    profile.mac = byteStringToSigned(mac.value());
+    profile.mac = mac.value();
 
     cppbor::Map profileMap;
     profileMap.add("id", profile.id);
     if (profile.readerCertificate.encodedCertificate.size() > 0) {
-        profileMap.add(
-                "readerCertificate",
-                cppbor::Bstr(byteStringToUnsigned(profile.readerCertificate.encodedCertificate)));
+        profileMap.add("readerCertificate",
+                       cppbor::Bstr(profile.readerCertificate.encodedCertificate));
     }
     if (profile.userAuthenticationRequired) {
         profileMap.add("userAuthenticationRequired", profile.userAuthenticationRequired);
@@ -254,9 +272,8 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus WritableIdentityCredential::addEntryValue(const vector<int8_t>& contentS,
-                                                             vector<int8_t>* outEncryptedContent) {
-    auto content = byteStringToUnsigned(contentS);
+ndk::ScopedAStatus WritableIdentityCredential::addEntryValue(const vector<uint8_t>& content,
+                                                             vector<uint8_t>* outEncryptedContent) {
     size_t contentSize = content.size();
 
     if (contentSize > IdentityCredentialStore::kGcmChunkSize) {
@@ -311,7 +328,7 @@
         signedDataCurrentNamespace_.add(std::move(entryMap));
     }
 
-    *outEncryptedContent = byteStringToSigned(encryptedContent.value());
+    *outEncryptedContent = encryptedContent.value();
     return ndk::ScopedAStatus::ok();
 }
 
@@ -360,7 +377,7 @@
 }
 
 ndk::ScopedAStatus WritableIdentityCredential::finishAddingEntries(
-        vector<int8_t>* outCredentialData, vector<int8_t>* outProofOfProvisioningSignature) {
+        vector<uint8_t>* outCredentialData, vector<uint8_t>* outProofOfProvisioningSignature) {
     if (numAccessControlProfileRemaining_ != 0) {
         return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
                 IIdentityCredentialStore::STATUS_INVALID_DATA,
@@ -384,6 +401,16 @@
             .add(testCredential_);
     vector<uint8_t> encodedCbor = popArray.encode();
 
+    if (encodedCbor.size() != expectedProofOfProvisioningSize_) {
+        LOG(ERROR) << "CBOR for proofOfProvisioning is " << encodedCbor.size() << " bytes, "
+                   << "was expecting " << expectedProofOfProvisioningSize_;
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA,
+                StringPrintf("Unexpected CBOR size %zd for proofOfProvisioning, was expecting %zd",
+                             encodedCbor.size(), expectedProofOfProvisioningSize_)
+                        .c_str()));
+    }
+
     optional<vector<uint8_t>> signature = support::coseSignEcDsa(credentialPrivKey_,
                                                                  encodedCbor,  // payload
                                                                  {},           // additionalData
@@ -407,8 +434,8 @@
                 IIdentityCredentialStore::STATUS_FAILED, "Error generating CredentialData"));
     }
 
-    *outCredentialData = byteStringToSigned(credentialData);
-    *outProofOfProvisioningSignature = byteStringToSigned(signature.value());
+    *outCredentialData = credentialData;
+    *outProofOfProvisioningSignature = signature.value();
     return ndk::ScopedAStatus::ok();
 }
 
diff --git a/identity/aidl/default/WritableIdentityCredential.h b/identity/aidl/default/WritableIdentityCredential.h
index cb91f7b..5645852 100644
--- a/identity/aidl/default/WritableIdentityCredential.h
+++ b/identity/aidl/default/WritableIdentityCredential.h
@@ -39,10 +39,13 @@
     bool initialize();
 
     // Methods from IWritableIdentityCredential follow.
-    ndk::ScopedAStatus getAttestationCertificate(const vector<int8_t>& attestationApplicationId,
-                                                 const vector<int8_t>& attestationChallenge,
+    ndk::ScopedAStatus getAttestationCertificate(const vector<uint8_t>& attestationApplicationId,
+                                                 const vector<uint8_t>& attestationChallenge,
                                                  vector<Certificate>* outCertificateChain) override;
 
+    ndk::ScopedAStatus setExpectedProofOfProvisioningSize(
+            int32_t expectedProofOfProvisioningSize) override;
+
     ndk::ScopedAStatus startPersonalization(int32_t accessControlProfileCount,
                                             const vector<int32_t>& entryCounts) override;
 
@@ -55,14 +58,14 @@
                                      const string& nameSpace, const string& name,
                                      int32_t entrySize) override;
 
-    ndk::ScopedAStatus addEntryValue(const vector<int8_t>& content,
-                                     vector<int8_t>* outEncryptedContent) override;
+    ndk::ScopedAStatus addEntryValue(const vector<uint8_t>& content,
+                                     vector<uint8_t>* outEncryptedContent) override;
 
     ndk::ScopedAStatus finishAddingEntries(
-            vector<int8_t>* outCredentialData,
-            vector<int8_t>* outProofOfProvisioningSignature) override;
+            vector<uint8_t>* outCredentialData,
+            vector<uint8_t>* outProofOfProvisioningSignature) override;
 
-    // private:
+  private:
     string docType_;
     bool testCredential_;
 
@@ -82,6 +85,7 @@
     cppbor::Array signedDataAccessControlProfiles_;
     cppbor::Map signedDataNamespaces_;
     cppbor::Array signedDataCurrentNamespace_;
+    size_t expectedProofOfProvisioningSize_;
 
     // This field is initialized in addAccessControlProfile
     set<int32_t> accessControlProfileIds_;
diff --git a/identity/aidl/default/service.cpp b/identity/aidl/default/service.cpp
index f05c615..bf95df5 100644
--- a/identity/aidl/default/service.cpp
+++ b/identity/aidl/default/service.cpp
@@ -22,9 +22,14 @@
 
 #include "IdentityCredentialStore.h"
 
+using ::android::base::InitLogging;
+using ::android::base::StderrLogger;
+
 using aidl::android::hardware::identity::IdentityCredentialStore;
 
-int main() {
+int main(int /*argc*/, char* argv[]) {
+    InitLogging(argv, StderrLogger);
+
     ABinderProcess_setThreadPoolMaxThreadCount(0);
     std::shared_ptr<IdentityCredentialStore> store =
             ndk::SharedRefBase::make<IdentityCredentialStore>();
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index e4780bf..c1f44e7 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -8,6 +8,10 @@
         "VtsHalIdentityEndToEndTest.cpp",
         "VtsIWritableIdentityCredentialTests.cpp",
         "VtsIdentityTestUtils.cpp",
+        "VtsAttestationTests.cpp",
+        "VtsAttestationParserSupport.cpp",
+        "UserAuthTests.cpp",
+        "ReaderAuthTests.cpp",
     ],
     shared_libs: [
         "libbinder",
@@ -15,9 +19,14 @@
     ],
     static_libs: [
         "libcppbor",
+        "libkeymaster_portable",
+        "libsoft_attestation_cert",
+        "libpuresoftkeymasterdevice",
+        "android.hardware.keymaster@4.0",
         "android.hardware.identity-support-lib",
         "android.hardware.identity-cpp",
         "android.hardware.keymaster-cpp",
+        "android.hardware.keymaster-ndk_platform",
     ],
     test_suites: [
         "general-tests",
diff --git a/identity/aidl/vts/ReaderAuthTests.cpp b/identity/aidl/vts/ReaderAuthTests.cpp
new file mode 100644
index 0000000..b11f6c5
--- /dev/null
+++ b/identity/aidl/vts/ReaderAuthTests.cpp
@@ -0,0 +1,602 @@
+/*
+ * 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 "ReaderAuthTests"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/keymaster/HardwareAuthToken.h>
+#include <aidl/android/hardware/keymaster/VerificationToken.h>
+#include <android-base/logging.h>
+#include <android/hardware/identity/IIdentityCredentialStore.h>
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <cppbor.h>
+#include <cppbor_parse.h>
+#include <gtest/gtest.h>
+#include <future>
+#include <map>
+#include <utility>
+
+#include "VtsIdentityTestUtils.h"
+
+namespace android::hardware::identity {
+
+using std::endl;
+using std::make_pair;
+using std::map;
+using std::optional;
+using std::pair;
+using std::string;
+using std::tie;
+using std::vector;
+
+using ::android::sp;
+using ::android::String16;
+using ::android::binder::Status;
+
+using ::android::hardware::keymaster::HardwareAuthToken;
+using ::android::hardware::keymaster::VerificationToken;
+
+class ReaderAuthTests : public testing::TestWithParam<string> {
+  public:
+    virtual void SetUp() override {
+        credentialStore_ = android::waitForDeclaredService<IIdentityCredentialStore>(
+                String16(GetParam().c_str()));
+        ASSERT_NE(credentialStore_, nullptr);
+    }
+
+    void provisionData();
+    void retrieveData(const vector<uint8_t>& readerPrivateKey,
+                      const vector<vector<uint8_t>>& readerCertChain, bool expectSuccess,
+                      bool leaveOutAccessibleToAllFromRequestMessage);
+
+    // Set by provisionData
+    vector<uint8_t> readerPublicKey_;
+    vector<uint8_t> readerPrivateKey_;
+    vector<uint8_t> intermediateAPublicKey_;
+    vector<uint8_t> intermediateAPrivateKey_;
+    vector<uint8_t> intermediateBPublicKey_;
+    vector<uint8_t> intermediateBPrivateKey_;
+    vector<uint8_t> intermediateCPublicKey_;
+    vector<uint8_t> intermediateCPrivateKey_;
+
+    vector<uint8_t> cert_A_SelfSigned_;
+
+    vector<uint8_t> cert_B_SelfSigned_;
+
+    vector<uint8_t> cert_B_SignedBy_C_;
+
+    vector<uint8_t> cert_C_SelfSigned_;
+
+    vector<uint8_t> cert_reader_SelfSigned_;
+    vector<uint8_t> cert_reader_SignedBy_A_;
+    vector<uint8_t> cert_reader_SignedBy_B_;
+
+    SecureAccessControlProfile sacp0_;
+    SecureAccessControlProfile sacp1_;
+    SecureAccessControlProfile sacp2_;
+    SecureAccessControlProfile sacp3_;
+
+    vector<uint8_t> encContentAccessibleByA_;
+    vector<uint8_t> encContentAccessibleByAorB_;
+    vector<uint8_t> encContentAccessibleByB_;
+    vector<uint8_t> encContentAccessibleByC_;
+    vector<uint8_t> encContentAccessibleByAll_;
+    vector<uint8_t> encContentAccessibleByNone_;
+
+    vector<uint8_t> credentialData_;
+
+    // Set by retrieveData()
+    bool canGetAccessibleByA_;
+    bool canGetAccessibleByAorB_;
+    bool canGetAccessibleByB_;
+    bool canGetAccessibleByC_;
+    bool canGetAccessibleByAll_;
+    bool canGetAccessibleByNone_;
+
+    sp<IIdentityCredentialStore> credentialStore_;
+};
+
+pair<vector<uint8_t>, vector<uint8_t>> generateReaderKey() {
+    optional<vector<uint8_t>> keyPKCS8 = support::createEcKeyPair();
+    optional<vector<uint8_t>> publicKey = support::ecKeyPairGetPublicKey(keyPKCS8.value());
+    optional<vector<uint8_t>> privateKey = support::ecKeyPairGetPrivateKey(keyPKCS8.value());
+    return make_pair(publicKey.value(), privateKey.value());
+}
+
+vector<uint8_t> generateReaderCert(const vector<uint8_t>& publicKey,
+                                   const vector<uint8_t>& signingKey) {
+    time_t validityNotBefore = 0;
+    time_t validityNotAfter = 0xffffffff;
+    optional<vector<uint8_t>> cert =
+            support::ecPublicKeyGenerateCertificate(publicKey, signingKey, "24601", "Issuer",
+                                                    "Subject", validityNotBefore, validityNotAfter);
+    return cert.value();
+}
+
+void ReaderAuthTests::provisionData() {
+    // Keys and certificates for intermediates.
+    tie(intermediateAPublicKey_, intermediateAPrivateKey_) = generateReaderKey();
+    tie(intermediateBPublicKey_, intermediateBPrivateKey_) = generateReaderKey();
+    tie(intermediateCPublicKey_, intermediateCPrivateKey_) = generateReaderKey();
+
+    cert_A_SelfSigned_ = generateReaderCert(intermediateAPublicKey_, intermediateAPrivateKey_);
+
+    cert_B_SelfSigned_ = generateReaderCert(intermediateBPublicKey_, intermediateBPrivateKey_);
+
+    cert_B_SignedBy_C_ = generateReaderCert(intermediateBPublicKey_, intermediateCPrivateKey_);
+
+    cert_C_SelfSigned_ = generateReaderCert(intermediateCPublicKey_, intermediateCPrivateKey_);
+
+    // Key and self-signed certificate reader
+    tie(readerPublicKey_, readerPrivateKey_) = generateReaderKey();
+    cert_reader_SelfSigned_ = generateReaderCert(readerPublicKey_, readerPrivateKey_);
+
+    // Certificate for reader signed by intermediates
+    cert_reader_SignedBy_A_ = generateReaderCert(readerPublicKey_, intermediateAPrivateKey_);
+    cert_reader_SignedBy_B_ = generateReaderCert(readerPublicKey_, intermediateBPrivateKey_);
+
+    string docType = "org.iso.18013-5.2019.mdl";
+    bool testCredential = true;
+    sp<IWritableIdentityCredential> wc;
+    ASSERT_TRUE(credentialStore_->createCredential(docType, testCredential, &wc).isOk());
+
+    vector<uint8_t> attestationApplicationId = {};
+    vector<uint8_t> attestationChallenge = {1};
+    vector<Certificate> certChain;
+    ASSERT_TRUE(wc->getAttestationCertificate(attestationApplicationId, attestationChallenge,
+                                              &certChain)
+                        .isOk());
+
+    size_t proofOfProvisioningSize =
+            465 + cert_A_SelfSigned_.size() + cert_B_SelfSigned_.size() + cert_C_SelfSigned_.size();
+    ASSERT_TRUE(wc->setExpectedProofOfProvisioningSize(proofOfProvisioningSize).isOk());
+
+    // Not in v1 HAL, may fail
+    wc->startPersonalization(4 /* numAccessControlProfiles */,
+                             {6} /* numDataElementsPerNamespace */);
+
+    // AIDL expects certificates wrapped in the Certificate type...
+    Certificate cert_A;
+    Certificate cert_B;
+    Certificate cert_C;
+    cert_A.encodedCertificate = cert_A_SelfSigned_;
+    cert_B.encodedCertificate = cert_B_SelfSigned_;
+    cert_C.encodedCertificate = cert_C_SelfSigned_;
+
+    // Access control profile 0: accessible by A
+    ASSERT_TRUE(wc->addAccessControlProfile(0, cert_A, false, 0, 0, &sacp0_).isOk());
+
+    // Access control profile 1: accessible by B
+    ASSERT_TRUE(wc->addAccessControlProfile(1, cert_B, false, 0, 0, &sacp1_).isOk());
+
+    // Access control profile 2: accessible by C
+    ASSERT_TRUE(wc->addAccessControlProfile(2, cert_C, false, 0, 0, &sacp2_).isOk());
+
+    // Access control profile 3: open access
+    ASSERT_TRUE(wc->addAccessControlProfile(3, {}, false, 0, 0, &sacp3_).isOk());
+
+    // Data Element: "Accessible by A"
+    ASSERT_TRUE(wc->beginAddEntry({0}, "ns", "Accessible by A", 1).isOk());
+    ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByA_).isOk());
+
+    // Data Element: "Accessible by A or B"
+    ASSERT_TRUE(wc->beginAddEntry({0, 1}, "ns", "Accessible by A or B", 1).isOk());
+    ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByAorB_).isOk());
+
+    // Data Element: "Accessible by B"
+    ASSERT_TRUE(wc->beginAddEntry({1}, "ns", "Accessible by B", 1).isOk());
+    ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByB_).isOk());
+
+    // Data Element: "Accessible by C"
+    ASSERT_TRUE(wc->beginAddEntry({2}, "ns", "Accessible by C", 1).isOk());
+    ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByC_).isOk());
+
+    // Data Element: "Accessible by All"
+    ASSERT_TRUE(wc->beginAddEntry({3}, "ns", "Accessible by All", 1).isOk());
+    ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByAll_).isOk());
+
+    // Data Element: "Accessible by None"
+    ASSERT_TRUE(wc->beginAddEntry({}, "ns", "Accessible by None", 1).isOk());
+    ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByNone_).isOk());
+
+    vector<uint8_t> proofOfProvisioningSignature;
+    ASSERT_TRUE(wc->finishAddingEntries(&credentialData_, &proofOfProvisioningSignature).isOk());
+}
+
+RequestDataItem buildRequestDataItem(const string& name, size_t size,
+                                     vector<int32_t> accessControlProfileIds) {
+    RequestDataItem item;
+    item.name = name;
+    item.size = size;
+    item.accessControlProfileIds = accessControlProfileIds;
+    return item;
+}
+
+void ReaderAuthTests::retrieveData(const vector<uint8_t>& readerPrivateKey,
+                                   const vector<vector<uint8_t>>& readerCertChain,
+                                   bool expectSuccess,
+                                   bool leaveOutAccessibleToAllFromRequestMessage) {
+    canGetAccessibleByA_ = false;
+    canGetAccessibleByAorB_ = false;
+    canGetAccessibleByB_ = false;
+    canGetAccessibleByC_ = false;
+    canGetAccessibleByAll_ = false;
+    canGetAccessibleByNone_ = false;
+
+    sp<IIdentityCredential> c;
+    ASSERT_TRUE(credentialStore_
+                        ->getCredential(
+                                CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256,
+                                credentialData_, &c)
+                        .isOk());
+
+    optional<vector<uint8_t>> readerEKeyPair = support::createEcKeyPair();
+    optional<vector<uint8_t>> readerEPublicKey =
+            support::ecKeyPairGetPublicKey(readerEKeyPair.value());
+    ASSERT_TRUE(c->setReaderEphemeralPublicKey(readerEPublicKey.value()).isOk());
+
+    vector<uint8_t> eKeyPair;
+    ASSERT_TRUE(c->createEphemeralKeyPair(&eKeyPair).isOk());
+    optional<vector<uint8_t>> ePublicKey = support::ecKeyPairGetPublicKey(eKeyPair);
+
+    // Calculate requestData field and sign it with the reader key.
+    auto [getXYSuccess, ephX, ephY] = support::ecPublicKeyGetXandY(ePublicKey.value());
+    ASSERT_TRUE(getXYSuccess);
+    cppbor::Map deviceEngagement = cppbor::Map().add("ephX", ephX).add("ephY", ephY);
+    vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
+    vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
+    cppbor::Array sessionTranscript = cppbor::Array()
+                                              .add(cppbor::Semantic(24, deviceEngagementBytes))
+                                              .add(cppbor::Semantic(24, eReaderPubBytes));
+    vector<uint8_t> sessionTranscriptBytes = sessionTranscript.encode();
+
+    vector<uint8_t> itemsRequestBytes;
+    if (leaveOutAccessibleToAllFromRequestMessage) {
+        itemsRequestBytes =
+                cppbor::Map("nameSpaces",
+                            cppbor::Map().add("ns", cppbor::Map()
+                                                            .add("Accessible by A", false)
+                                                            .add("Accessible by A or B", false)
+                                                            .add("Accessible by B", false)
+                                                            .add("Accessible by C", false)
+                                                            .add("Accessible by None", false)))
+                        .encode();
+    } else {
+        itemsRequestBytes =
+                cppbor::Map("nameSpaces",
+                            cppbor::Map().add("ns", cppbor::Map()
+                                                            .add("Accessible by A", false)
+                                                            .add("Accessible by A or B", false)
+                                                            .add("Accessible by B", false)
+                                                            .add("Accessible by C", false)
+                                                            .add("Accessible by All", false)
+                                                            .add("Accessible by None", false)))
+                        .encode();
+    }
+    vector<uint8_t> encodedReaderAuthentication =
+            cppbor::Array()
+                    .add("ReaderAuthentication")
+                    .add(sessionTranscript.clone())
+                    .add(cppbor::Semantic(24, itemsRequestBytes))
+                    .encode();
+    vector<uint8_t> encodedReaderAuthenticationBytes =
+            cppbor::Semantic(24, encodedReaderAuthentication).encode();
+
+    optional<vector<uint8_t>> readerSignature =
+            support::coseSignEcDsa(readerPrivateKey,                  // private key for reader
+                                   {},                                // content
+                                   encodedReaderAuthenticationBytes,  // detached content
+                                   support::certificateChainJoin(readerCertChain));
+    ASSERT_TRUE(readerSignature);
+
+    // Generate the key that will be used to sign AuthenticatedData.
+    vector<uint8_t> signingKeyBlob;
+    Certificate signingKeyCertificate;
+    ASSERT_TRUE(c->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
+
+    RequestNamespace rns;
+    rns.namespaceName = "ns";
+    rns.items.push_back(buildRequestDataItem("Accessible by A", 1, {0}));
+    rns.items.push_back(buildRequestDataItem("Accessible by A or B", 1, {0, 1}));
+    rns.items.push_back(buildRequestDataItem("Accessible by B", 1, {1}));
+    rns.items.push_back(buildRequestDataItem("Accessible by C", 1, {2}));
+    rns.items.push_back(buildRequestDataItem("Accessible by All", 1, {3}));
+    rns.items.push_back(buildRequestDataItem("Accessible by None", 1, {}));
+    // OK to fail, not available in v1 HAL
+    c->setRequestedNamespaces({rns}).isOk();
+
+    // It doesn't matter since no user auth is needed in this particular test,
+    // but for good measure, clear out the tokens we pass to the HAL.
+    HardwareAuthToken authToken;
+    VerificationToken verificationToken;
+    authToken.challenge = 0;
+    authToken.userId = 0;
+    authToken.authenticatorId = 0;
+    authToken.authenticatorType = ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
+    authToken.timestamp.milliSeconds = 0;
+    authToken.mac.clear();
+    verificationToken.challenge = 0;
+    verificationToken.timestamp.milliSeconds = 0;
+    verificationToken.securityLevel = ::android::hardware::keymaster::SecurityLevel::SOFTWARE;
+    verificationToken.mac.clear();
+    // OK to fail, not available in v1 HAL
+    c->setVerificationToken(verificationToken);
+
+    Status status = c->startRetrieval(
+            {sacp0_, sacp1_, sacp2_, sacp3_}, authToken, itemsRequestBytes, signingKeyBlob,
+            sessionTranscriptBytes, readerSignature.value(), {6 /* numDataElementsPerNamespace */});
+    if (expectSuccess) {
+        ASSERT_TRUE(status.isOk());
+    } else {
+        ASSERT_FALSE(status.isOk());
+        return;
+    }
+
+    vector<uint8_t> decrypted;
+
+    status = c->startRetrieveEntryValue("ns", "Accessible by A", 1, {0});
+    if (status.isOk()) {
+        canGetAccessibleByA_ = true;
+        ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByA_, &decrypted).isOk());
+    }
+
+    status = c->startRetrieveEntryValue("ns", "Accessible by A or B", 1, {0, 1});
+    if (status.isOk()) {
+        canGetAccessibleByAorB_ = true;
+        ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByAorB_, &decrypted).isOk());
+    }
+
+    status = c->startRetrieveEntryValue("ns", "Accessible by B", 1, {1});
+    if (status.isOk()) {
+        canGetAccessibleByB_ = true;
+        ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByB_, &decrypted).isOk());
+    }
+
+    status = c->startRetrieveEntryValue("ns", "Accessible by C", 1, {2});
+    if (status.isOk()) {
+        canGetAccessibleByC_ = true;
+        ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByC_, &decrypted).isOk());
+    }
+
+    status = c->startRetrieveEntryValue("ns", "Accessible by All", 1, {3});
+    if (status.isOk()) {
+        canGetAccessibleByAll_ = true;
+        ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByAll_, &decrypted).isOk());
+    }
+
+    status = c->startRetrieveEntryValue("ns", "Accessible by None", 1, {});
+    if (status.isOk()) {
+        canGetAccessibleByNone_ = true;
+        ASSERT_TRUE(c->retrieveEntryValue(encContentAccessibleByNone_, &decrypted).isOk());
+    }
+
+    vector<uint8_t> mac;
+    vector<uint8_t> deviceNameSpaces;
+    ASSERT_TRUE(c->finishRetrieval(&mac, &deviceNameSpaces).isOk());
+}
+
+TEST_P(ReaderAuthTests, presentingChain_Reader) {
+    provisionData();
+    retrieveData(readerPrivateKey_, {cert_reader_SelfSigned_}, true /* expectSuccess */,
+                 false /* leaveOutAccessibleToAllFromRequestMessage */);
+    EXPECT_FALSE(canGetAccessibleByA_);
+    EXPECT_FALSE(canGetAccessibleByAorB_);
+    EXPECT_FALSE(canGetAccessibleByB_);
+    EXPECT_FALSE(canGetAccessibleByC_);
+    EXPECT_TRUE(canGetAccessibleByAll_);
+    EXPECT_FALSE(canGetAccessibleByNone_);
+}
+
+TEST_P(ReaderAuthTests, presentingChain_Reader_A) {
+    provisionData();
+    retrieveData(readerPrivateKey_, {cert_reader_SignedBy_A_, cert_A_SelfSigned_},
+                 true /* expectSuccess */, false /* leaveOutAccessibleToAllFromRequestMessage */);
+    EXPECT_TRUE(canGetAccessibleByA_);
+    EXPECT_TRUE(canGetAccessibleByAorB_);
+    EXPECT_FALSE(canGetAccessibleByB_);
+    EXPECT_FALSE(canGetAccessibleByC_);
+    EXPECT_TRUE(canGetAccessibleByAll_);
+    EXPECT_FALSE(canGetAccessibleByNone_);
+}
+
+TEST_P(ReaderAuthTests, presentingChain_Reader_B) {
+    provisionData();
+    retrieveData(readerPrivateKey_, {cert_reader_SignedBy_B_, cert_B_SelfSigned_},
+                 true /* expectSuccess */, false /* leaveOutAccessibleToAllFromRequestMessage */);
+    EXPECT_FALSE(canGetAccessibleByA_);
+    EXPECT_TRUE(canGetAccessibleByAorB_);
+    EXPECT_TRUE(canGetAccessibleByB_);
+    EXPECT_FALSE(canGetAccessibleByC_);
+    EXPECT_TRUE(canGetAccessibleByAll_);
+    EXPECT_FALSE(canGetAccessibleByNone_);
+}
+
+// This test proves that for the purpose of determining inclusion of an ACP certificate
+// in a presented reader chain, certificate equality is done by comparing public keys,
+// not bitwise comparison of the certificates.
+//
+// Specifically for this test, the ACP is configured with cert_B_SelfSigned_ and the
+// reader is presenting cert_B_SignedBy_C_. Both certificates have the same public
+// key - intermediateBPublicKey_ - but they are signed by different keys.
+//
+TEST_P(ReaderAuthTests, presentingChain_Reader_B_C) {
+    provisionData();
+    retrieveData(readerPrivateKey_,
+                 {cert_reader_SignedBy_B_, cert_B_SignedBy_C_, cert_C_SelfSigned_},
+                 true /* expectSuccess */, false /* leaveOutAccessibleToAllFromRequestMessage */);
+    EXPECT_FALSE(canGetAccessibleByA_);
+    EXPECT_TRUE(canGetAccessibleByAorB_);
+    EXPECT_TRUE(canGetAccessibleByB_);
+    EXPECT_TRUE(canGetAccessibleByC_);
+    EXPECT_TRUE(canGetAccessibleByAll_);
+    EXPECT_FALSE(canGetAccessibleByNone_);
+}
+
+// This test presents a reader chain where the chain is invalid because
+// the 2nd certificate in the chain isn't signed by the 3rd one.
+//
+TEST_P(ReaderAuthTests, presentingInvalidChain) {
+    provisionData();
+    retrieveData(readerPrivateKey_,
+                 {cert_reader_SignedBy_B_, cert_B_SelfSigned_, cert_C_SelfSigned_},
+                 false /* expectSuccess */, false /* leaveOutAccessibleToAllFromRequestMessage */);
+}
+
+// This tests presents a valid reader chain but where requestMessage isn't
+// signed by the private key corresponding to the public key in the top-level
+// certificate.
+//
+TEST_P(ReaderAuthTests, presentingMessageSignedNotByTopLevel) {
+    provisionData();
+    retrieveData(intermediateBPrivateKey_,
+                 {cert_reader_SignedBy_B_, cert_B_SignedBy_C_, cert_C_SelfSigned_},
+                 false /* expectSuccess */, false /* leaveOutAccessibleToAllFromRequestMessage */);
+}
+
+// This test leaves out "Accessible by All" data element from the signed request
+// message (the CBOR from the reader) while still including this data element at
+// the API level. The call on the API level for said element will fail with
+// STATUS_NOT_IN_REQUEST_MESSAGE but this doesn't prevent the other elements
+// from being returned (if authorized, of course).
+//
+// This test verifies that.
+//
+TEST_P(ReaderAuthTests, limitedMessage) {
+    provisionData();
+    retrieveData(readerPrivateKey_, {cert_reader_SelfSigned_}, true /* expectSuccess */,
+                 true /* leaveOutAccessibleToAllFromRequestMessage */);
+    EXPECT_FALSE(canGetAccessibleByA_);
+    EXPECT_FALSE(canGetAccessibleByAorB_);
+    EXPECT_FALSE(canGetAccessibleByB_);
+    EXPECT_FALSE(canGetAccessibleByC_);
+    EXPECT_FALSE(canGetAccessibleByAll_);
+    EXPECT_FALSE(canGetAccessibleByNone_);
+}
+
+TEST_P(ReaderAuthTests, ephemeralKeyNotInSessionTranscript) {
+    provisionData();
+
+    sp<IIdentityCredential> c;
+    ASSERT_TRUE(credentialStore_
+                        ->getCredential(
+                                CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256,
+                                credentialData_, &c)
+                        .isOk());
+
+    optional<vector<uint8_t>> readerEKeyPair = support::createEcKeyPair();
+    optional<vector<uint8_t>> readerEPublicKey =
+            support::ecKeyPairGetPublicKey(readerEKeyPair.value());
+    ASSERT_TRUE(c->setReaderEphemeralPublicKey(readerEPublicKey.value()).isOk());
+
+    vector<uint8_t> eKeyPair;
+    ASSERT_TRUE(c->createEphemeralKeyPair(&eKeyPair).isOk());
+    optional<vector<uint8_t>> ePublicKey = support::ecKeyPairGetPublicKey(eKeyPair);
+
+    // Calculate requestData field and sign it with the reader key.
+    auto [getXYSuccess, ephX, ephY] = support::ecPublicKeyGetXandY(ePublicKey.value());
+    ASSERT_TRUE(getXYSuccess);
+    // Instead of include the X and Y coordinates (|ephX| and |ephY|), add NUL bytes instead.
+    vector<uint8_t> nulls(32);
+    cppbor::Map deviceEngagement = cppbor::Map().add("ephX", nulls).add("ephY", nulls);
+    vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
+    vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
+    cppbor::Array sessionTranscript = cppbor::Array()
+                                              .add(cppbor::Semantic(24, deviceEngagementBytes))
+                                              .add(cppbor::Semantic(24, eReaderPubBytes));
+    vector<uint8_t> sessionTranscriptBytes = sessionTranscript.encode();
+
+    vector<uint8_t> itemsRequestBytes;
+    itemsRequestBytes =
+            cppbor::Map("nameSpaces",
+                        cppbor::Map().add("ns", cppbor::Map()
+                                                        .add("Accessible by A", false)
+                                                        .add("Accessible by A or B", false)
+                                                        .add("Accessible by B", false)
+                                                        .add("Accessible by C", false)
+                                                        .add("Accessible by None", false)))
+                    .encode();
+    vector<uint8_t> encodedReaderAuthentication =
+            cppbor::Array()
+                    .add("ReaderAuthentication")
+                    .add(sessionTranscript.clone())
+                    .add(cppbor::Semantic(24, itemsRequestBytes))
+                    .encode();
+    vector<uint8_t> encodedReaderAuthenticationBytes =
+            cppbor::Semantic(24, encodedReaderAuthentication).encode();
+
+    vector<vector<uint8_t>> readerCertChain = {cert_reader_SelfSigned_};
+    optional<vector<uint8_t>> readerSignature =
+            support::coseSignEcDsa(readerPrivateKey_,                 // private key for reader
+                                   {},                                // content
+                                   encodedReaderAuthenticationBytes,  // detached content
+                                   support::certificateChainJoin(readerCertChain));
+    ASSERT_TRUE(readerSignature);
+
+    // Generate the key that will be used to sign AuthenticatedData.
+    vector<uint8_t> signingKeyBlob;
+    Certificate signingKeyCertificate;
+    ASSERT_TRUE(c->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
+
+    RequestNamespace rns;
+    rns.namespaceName = "ns";
+    rns.items.push_back(buildRequestDataItem("Accessible by A", 1, {0}));
+    rns.items.push_back(buildRequestDataItem("Accessible by A or B", 1, {0, 1}));
+    rns.items.push_back(buildRequestDataItem("Accessible by B", 1, {1}));
+    rns.items.push_back(buildRequestDataItem("Accessible by C", 1, {2}));
+    rns.items.push_back(buildRequestDataItem("Accessible by All", 1, {3}));
+    rns.items.push_back(buildRequestDataItem("Accessible by None", 1, {}));
+    // OK to fail, not available in v1 HAL
+    c->setRequestedNamespaces({rns}).isOk();
+
+    // It doesn't matter since no user auth is needed in this particular test,
+    // but for good measure, clear out the tokens we pass to the HAL.
+    HardwareAuthToken authToken;
+    VerificationToken verificationToken;
+    authToken.challenge = 0;
+    authToken.userId = 0;
+    authToken.authenticatorId = 0;
+    authToken.authenticatorType = ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
+    authToken.timestamp.milliSeconds = 0;
+    authToken.mac.clear();
+    verificationToken.challenge = 0;
+    verificationToken.timestamp.milliSeconds = 0;
+    verificationToken.securityLevel =
+            ::android::hardware::keymaster::SecurityLevel::TRUSTED_ENVIRONMENT;
+    verificationToken.mac.clear();
+    // OK to fail, not available in v1 HAL
+    c->setVerificationToken(verificationToken);
+
+    // Finally check that STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND is returned.
+    // This proves that the TA checked for X and Y coordinatets and didn't find
+    // them.
+    Status status = c->startRetrieval(
+            {sacp0_, sacp1_, sacp2_, sacp3_}, authToken, itemsRequestBytes, signingKeyBlob,
+            sessionTranscriptBytes, readerSignature.value(), {6 /* numDataElementsPerNamespace */});
+    ASSERT_FALSE(status.isOk());
+    ASSERT_EQ(binder::Status::EX_SERVICE_SPECIFIC, status.exceptionCode());
+    ASSERT_EQ(IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
+              status.serviceSpecificErrorCode());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        Identity, ReaderAuthTests,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
+        android::PrintInstanceNameToString);
+
+}  // namespace android::hardware::identity
diff --git a/identity/aidl/vts/UserAuthTests.cpp b/identity/aidl/vts/UserAuthTests.cpp
new file mode 100644
index 0000000..5b4c8f1
--- /dev/null
+++ b/identity/aidl/vts/UserAuthTests.cpp
@@ -0,0 +1,473 @@
+/*
+ * 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 "UserAuthTests"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/keymaster/HardwareAuthToken.h>
+#include <aidl/android/hardware/keymaster/VerificationToken.h>
+#include <android-base/logging.h>
+#include <android/hardware/identity/IIdentityCredentialStore.h>
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <cppbor.h>
+#include <cppbor_parse.h>
+#include <gtest/gtest.h>
+#include <future>
+#include <map>
+#include <utility>
+
+#include "VtsIdentityTestUtils.h"
+
+namespace android::hardware::identity {
+
+using std::endl;
+using std::make_pair;
+using std::map;
+using std::optional;
+using std::pair;
+using std::string;
+using std::tie;
+using std::vector;
+
+using ::android::sp;
+using ::android::String16;
+using ::android::binder::Status;
+
+using ::android::hardware::keymaster::HardwareAuthToken;
+using ::android::hardware::keymaster::VerificationToken;
+
+class UserAuthTests : public testing::TestWithParam<string> {
+  public:
+    virtual void SetUp() override {
+        credentialStore_ = android::waitForDeclaredService<IIdentityCredentialStore>(
+                String16(GetParam().c_str()));
+        ASSERT_NE(credentialStore_, nullptr);
+    }
+
+    void provisionData();
+    void setupRetrieveData();
+    pair<HardwareAuthToken, VerificationToken> mintTokens(uint64_t challengeForAuthToken,
+                                                          int64_t ageOfAuthTokenMilliSeconds);
+    void retrieveData(HardwareAuthToken authToken, VerificationToken verificationToken,
+                      bool expectSuccess, bool useSessionTranscript);
+
+    // Set by provisionData
+    SecureAccessControlProfile sacp0_;
+    SecureAccessControlProfile sacp1_;
+    SecureAccessControlProfile sacp2_;
+
+    vector<uint8_t> encContentUserAuthPerSession_;
+    vector<uint8_t> encContentUserAuthTimeout_;
+    vector<uint8_t> encContentAccessibleByAll_;
+    vector<uint8_t> encContentAccessibleByNone_;
+
+    vector<uint8_t> credentialData_;
+
+    // Set by setupRetrieveData().
+    int64_t authChallenge_;
+    cppbor::Map sessionTranscript_;
+    sp<IIdentityCredential> credential_;
+
+    // Set by retrieveData()
+    bool canGetUserAuthPerSession_;
+    bool canGetUserAuthTimeout_;
+    bool canGetAccessibleByAll_;
+    bool canGetAccessibleByNone_;
+
+    sp<IIdentityCredentialStore> credentialStore_;
+};
+
+void UserAuthTests::provisionData() {
+    string docType = "org.iso.18013-5.2019.mdl";
+    bool testCredential = true;
+    sp<IWritableIdentityCredential> wc;
+    ASSERT_TRUE(credentialStore_->createCredential(docType, testCredential, &wc).isOk());
+
+    vector<uint8_t> attestationApplicationId = {};
+    vector<uint8_t> attestationChallenge = {1};
+    vector<Certificate> certChain;
+    ASSERT_TRUE(wc->getAttestationCertificate(attestationApplicationId, attestationChallenge,
+                                              &certChain)
+                        .isOk());
+
+    size_t proofOfProvisioningSize = 381;
+    // Not in v1 HAL, may fail
+    wc->setExpectedProofOfProvisioningSize(proofOfProvisioningSize);
+
+    ASSERT_TRUE(wc->startPersonalization(3 /* numAccessControlProfiles */,
+                                         {4} /* numDataElementsPerNamespace */)
+                        .isOk());
+
+    // Access control profile 0: user auth every session (timeout = 0)
+    ASSERT_TRUE(wc->addAccessControlProfile(0, {}, true, 0, 65 /* secureUserId */, &sacp0_).isOk());
+
+    // Access control profile 1: user auth, 60 seconds timeout
+    ASSERT_TRUE(
+            wc->addAccessControlProfile(1, {}, true, 60000, 65 /* secureUserId */, &sacp1_).isOk());
+
+    // Access control profile 2: open access
+    ASSERT_TRUE(wc->addAccessControlProfile(2, {}, false, 0, 0, &sacp2_).isOk());
+
+    // Data Element: "UserAuth Per Session"
+    ASSERT_TRUE(wc->beginAddEntry({0}, "ns", "UserAuth Per Session", 1).isOk());
+    ASSERT_TRUE(wc->addEntryValue({9}, &encContentUserAuthPerSession_).isOk());
+
+    // Data Element: "UserAuth Timeout"
+    ASSERT_TRUE(wc->beginAddEntry({1}, "ns", "UserAuth Timeout", 1).isOk());
+    ASSERT_TRUE(wc->addEntryValue({9}, &encContentUserAuthTimeout_).isOk());
+
+    // Data Element: "Accessible by All"
+    ASSERT_TRUE(wc->beginAddEntry({2}, "ns", "Accessible by All", 1).isOk());
+    ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByAll_).isOk());
+
+    // Data Element: "Accessible by None"
+    ASSERT_TRUE(wc->beginAddEntry({}, "ns", "Accessible by None", 1).isOk());
+    ASSERT_TRUE(wc->addEntryValue({9}, &encContentAccessibleByNone_).isOk());
+
+    vector<uint8_t> proofOfProvisioningSignature;
+    Status status = wc->finishAddingEntries(&credentialData_, &proofOfProvisioningSignature);
+    EXPECT_TRUE(status.isOk()) << status.exceptionCode() << ": " << status.exceptionMessage();
+}
+
+// From ReaderAuthTest.cpp - TODO: consolidate with VtsIdentityTestUtils.h
+pair<vector<uint8_t>, vector<uint8_t>> generateReaderKey();
+vector<uint8_t> generateReaderCert(const vector<uint8_t>& publicKey,
+                                   const vector<uint8_t>& signingKey);
+RequestDataItem buildRequestDataItem(const string& name, size_t size,
+                                     vector<int32_t> accessControlProfileIds);
+
+cppbor::Map calcSessionTranscript(const vector<uint8_t>& ePublicKey) {
+    auto [getXYSuccess, ephX, ephY] = support::ecPublicKeyGetXandY(ePublicKey);
+    cppbor::Map deviceEngagement = cppbor::Map().add("ephX", ephX).add("ephY", ephY);
+    vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
+    vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
+    // Let SessionTranscript be a map here (it's an array in EndToEndTest) just
+    // to check that the implementation can deal with either.
+    cppbor::Map sessionTranscript;
+    sessionTranscript.add(42, cppbor::Semantic(24, deviceEngagementBytes));
+    sessionTranscript.add(43, cppbor::Semantic(24, eReaderPubBytes));
+    return sessionTranscript;
+}
+
+void UserAuthTests::setupRetrieveData() {
+    ASSERT_TRUE(credentialStore_
+                        ->getCredential(
+                                CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256,
+                                credentialData_, &credential_)
+                        .isOk());
+
+    optional<vector<uint8_t>> readerEKeyPair = support::createEcKeyPair();
+    optional<vector<uint8_t>> readerEPublicKey =
+            support::ecKeyPairGetPublicKey(readerEKeyPair.value());
+    ASSERT_TRUE(credential_->setReaderEphemeralPublicKey(readerEPublicKey.value()).isOk());
+
+    vector<uint8_t> eKeyPair;
+    ASSERT_TRUE(credential_->createEphemeralKeyPair(&eKeyPair).isOk());
+    optional<vector<uint8_t>> ePublicKey = support::ecKeyPairGetPublicKey(eKeyPair);
+    sessionTranscript_ = calcSessionTranscript(ePublicKey.value());
+
+    Status status = credential_->createAuthChallenge(&authChallenge_);
+    EXPECT_TRUE(status.isOk()) << status.exceptionCode() << ": " << status.exceptionMessage();
+}
+
+void UserAuthTests::retrieveData(HardwareAuthToken authToken, VerificationToken verificationToken,
+                                 bool expectSuccess, bool useSessionTranscript) {
+    canGetUserAuthPerSession_ = false;
+    canGetUserAuthTimeout_ = false;
+    canGetAccessibleByAll_ = false;
+    canGetAccessibleByNone_ = false;
+
+    vector<uint8_t> itemsRequestBytes;
+    vector<uint8_t> sessionTranscriptBytes;
+    if (useSessionTranscript) {
+        sessionTranscriptBytes = sessionTranscript_.encode();
+
+        itemsRequestBytes =
+                cppbor::Map("nameSpaces",
+                            cppbor::Map().add("ns", cppbor::Map()
+                                                            .add("UserAuth Per Session", false)
+                                                            .add("UserAuth Timeout", false)
+                                                            .add("Accessible by All", false)
+                                                            .add("Accessible by None", false)))
+                        .encode();
+        vector<uint8_t> dataToSign = cppbor::Array()
+                                             .add("ReaderAuthentication")
+                                             .add(sessionTranscript_.clone())
+                                             .add(cppbor::Semantic(24, itemsRequestBytes))
+                                             .encode();
+    }
+
+    // Generate the key that will be used to sign AuthenticatedData.
+    vector<uint8_t> signingKeyBlob;
+    Certificate signingKeyCertificate;
+    ASSERT_TRUE(
+            credential_->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
+
+    RequestNamespace rns;
+    rns.namespaceName = "ns";
+    rns.items.push_back(buildRequestDataItem("UserAuth Per Session", 1, {0}));
+    rns.items.push_back(buildRequestDataItem("UserAuth Timeout", 1, {1}));
+    rns.items.push_back(buildRequestDataItem("Accessible by All", 1, {2}));
+    rns.items.push_back(buildRequestDataItem("Accessible by None", 1, {}));
+    // OK to fail, not available in v1 HAL
+    credential_->setRequestedNamespaces({rns}).isOk();
+
+    // OK to fail, not available in v1 HAL
+    credential_->setVerificationToken(verificationToken);
+
+    Status status = credential_->startRetrieval({sacp0_, sacp1_, sacp2_}, authToken,
+                                                itemsRequestBytes, signingKeyBlob,
+                                                sessionTranscriptBytes, {} /* readerSignature */,
+                                                {4 /* numDataElementsPerNamespace */});
+    if (expectSuccess) {
+        ASSERT_TRUE(status.isOk());
+    } else {
+        ASSERT_FALSE(status.isOk());
+        return;
+    }
+
+    vector<uint8_t> decrypted;
+
+    status = credential_->startRetrieveEntryValue("ns", "UserAuth Per Session", 1, {0});
+    if (status.isOk()) {
+        canGetUserAuthPerSession_ = true;
+        ASSERT_TRUE(
+                credential_->retrieveEntryValue(encContentUserAuthPerSession_, &decrypted).isOk());
+    }
+
+    status = credential_->startRetrieveEntryValue("ns", "UserAuth Timeout", 1, {1});
+    if (status.isOk()) {
+        canGetUserAuthTimeout_ = true;
+        ASSERT_TRUE(credential_->retrieveEntryValue(encContentUserAuthTimeout_, &decrypted).isOk());
+    }
+
+    status = credential_->startRetrieveEntryValue("ns", "Accessible by All", 1, {2});
+    if (status.isOk()) {
+        canGetAccessibleByAll_ = true;
+        ASSERT_TRUE(credential_->retrieveEntryValue(encContentAccessibleByAll_, &decrypted).isOk());
+    }
+
+    status = credential_->startRetrieveEntryValue("ns", "Accessible by None", 1, {});
+    if (status.isOk()) {
+        canGetAccessibleByNone_ = true;
+        ASSERT_TRUE(
+                credential_->retrieveEntryValue(encContentAccessibleByNone_, &decrypted).isOk());
+    }
+
+    vector<uint8_t> mac;
+    vector<uint8_t> deviceNameSpaces;
+    ASSERT_TRUE(credential_->finishRetrieval(&mac, &deviceNameSpaces).isOk());
+}
+
+pair<HardwareAuthToken, VerificationToken> UserAuthTests::mintTokens(
+        uint64_t challengeForAuthToken, int64_t ageOfAuthTokenMilliSeconds) {
+    HardwareAuthToken authToken;
+    VerificationToken verificationToken;
+
+    uint64_t epochMilliseconds = 1000ULL * 1000ULL * 1000ULL * 1000ULL;
+
+    authToken.challenge = challengeForAuthToken;
+    authToken.userId = 65;
+    authToken.authenticatorId = 0;
+    authToken.authenticatorType = ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
+    authToken.timestamp.milliSeconds = epochMilliseconds - ageOfAuthTokenMilliSeconds;
+    authToken.mac.clear();
+    verificationToken.challenge = authChallenge_;
+    verificationToken.timestamp.milliSeconds = epochMilliseconds;
+    verificationToken.securityLevel =
+            ::android::hardware::keymaster::SecurityLevel::TRUSTED_ENVIRONMENT;
+    verificationToken.mac.clear();
+    return make_pair(authToken, verificationToken);
+}
+
+TEST_P(UserAuthTests, GoodChallenge) {
+    provisionData();
+    setupRetrieveData();
+    auto [authToken, verificationToken] = mintTokens(authChallenge_,  // challengeForAuthToken
+                                                     0);              // ageOfAuthTokenMilliSeconds
+    retrieveData(authToken, verificationToken, true /* expectSuccess */,
+                 true /* useSessionTranscript */);
+    EXPECT_TRUE(canGetUserAuthPerSession_);
+    EXPECT_TRUE(canGetUserAuthTimeout_);
+    EXPECT_TRUE(canGetAccessibleByAll_);
+    EXPECT_FALSE(canGetAccessibleByNone_);
+}
+
+TEST_P(UserAuthTests, OtherChallenge) {
+    provisionData();
+    setupRetrieveData();
+    uint64_t otherChallenge = authChallenge_ ^ 0x12345678;
+    auto [authToken, verificationToken] = mintTokens(otherChallenge,  // challengeForAuthToken
+                                                     0);              // ageOfAuthTokenMilliSeconds
+    retrieveData(authToken, verificationToken, true /* expectSuccess */,
+                 true /* useSessionTranscript */);
+    EXPECT_FALSE(canGetUserAuthPerSession_);
+    EXPECT_TRUE(canGetUserAuthTimeout_);
+    EXPECT_TRUE(canGetAccessibleByAll_);
+    EXPECT_FALSE(canGetAccessibleByNone_);
+}
+
+TEST_P(UserAuthTests, NoChallenge) {
+    provisionData();
+    setupRetrieveData();
+    auto [authToken, verificationToken] = mintTokens(0,   // challengeForAuthToken
+                                                     0);  // ageOfAuthTokenMilliSeconds
+    retrieveData(authToken, verificationToken, true /* expectSuccess */,
+                 true /* useSessionTranscript */);
+    EXPECT_FALSE(canGetUserAuthPerSession_);
+    EXPECT_TRUE(canGetUserAuthTimeout_);
+    EXPECT_TRUE(canGetAccessibleByAll_);
+    EXPECT_FALSE(canGetAccessibleByNone_);
+}
+
+TEST_P(UserAuthTests, AuthTokenAgeZero) {
+    provisionData();
+    setupRetrieveData();
+    auto [authToken, verificationToken] = mintTokens(0,   // challengeForAuthToken
+                                                     0);  // ageOfAuthTokenMilliSeconds
+    retrieveData(authToken, verificationToken, true /* expectSuccess */,
+                 true /* useSessionTranscript */);
+    EXPECT_FALSE(canGetUserAuthPerSession_);
+    EXPECT_TRUE(canGetUserAuthTimeout_);
+    EXPECT_TRUE(canGetAccessibleByAll_);
+    EXPECT_FALSE(canGetAccessibleByNone_);
+}
+
+TEST_P(UserAuthTests, AuthTokenFromTheFuture) {
+    provisionData();
+    setupRetrieveData();
+    auto [authToken, verificationToken] = mintTokens(0,           // challengeForAuthToken
+                                                     -1 * 1000);  // ageOfAuthTokenMilliSeconds
+    retrieveData(authToken, verificationToken, true /* expectSuccess */,
+                 true /* useSessionTranscript */);
+    EXPECT_FALSE(canGetUserAuthPerSession_);
+    EXPECT_FALSE(canGetUserAuthTimeout_);
+    EXPECT_TRUE(canGetAccessibleByAll_);
+    EXPECT_FALSE(canGetAccessibleByNone_);
+}
+
+TEST_P(UserAuthTests, AuthTokenInsideTimeout) {
+    provisionData();
+    setupRetrieveData();
+    auto [authToken, verificationToken] = mintTokens(0,           // challengeForAuthToken
+                                                     30 * 1000);  // ageOfAuthTokenMilliSeconds
+    retrieveData(authToken, verificationToken, true /* expectSuccess */,
+                 true /* useSessionTranscript */);
+    EXPECT_FALSE(canGetUserAuthPerSession_);
+    EXPECT_TRUE(canGetUserAuthTimeout_);
+    EXPECT_TRUE(canGetAccessibleByAll_);
+    EXPECT_FALSE(canGetAccessibleByNone_);
+}
+
+TEST_P(UserAuthTests, AuthTokenOutsideTimeout) {
+    provisionData();
+    setupRetrieveData();
+    auto [authToken, verificationToken] = mintTokens(0,           // challengeForAuthToken
+                                                     61 * 1000);  // ageOfAuthTokenMilliSeconds
+    retrieveData(authToken, verificationToken, true /* expectSuccess */,
+                 true /* useSessionTranscript */);
+    EXPECT_FALSE(canGetUserAuthPerSession_);
+    EXPECT_FALSE(canGetUserAuthTimeout_);
+    EXPECT_TRUE(canGetAccessibleByAll_);
+    EXPECT_FALSE(canGetAccessibleByNone_);
+}
+
+// The API works even when there's no SessionTranscript / itemsRequest.
+// Verify that.
+TEST_P(UserAuthTests, NoSessionTranscript) {
+    provisionData();
+    setupRetrieveData();
+    auto [authToken, verificationToken] = mintTokens(0,          // challengeForAuthToken
+                                                     1 * 1000);  // ageOfAuthTokenMilliSeconds
+    retrieveData(authToken, verificationToken, true /* expectSuccess */,
+                 false /* useSessionTranscript */);
+    EXPECT_FALSE(canGetUserAuthPerSession_);
+    EXPECT_TRUE(canGetUserAuthTimeout_);
+    EXPECT_TRUE(canGetAccessibleByAll_);
+    EXPECT_FALSE(canGetAccessibleByNone_);
+}
+
+// This test verifies that it's possible to do multiple requests as long
+// as the sessionTranscript doesn't change.
+//
+TEST_P(UserAuthTests, MultipleRequestsSameSessionTranscript) {
+    provisionData();
+    setupRetrieveData();
+
+    // First we try with a stale authToken
+    //
+    auto [authToken, verificationToken] = mintTokens(0,           // challengeForAuthToken
+                                                     61 * 1000);  // ageOfAuthTokenMilliSeconds
+    retrieveData(authToken, verificationToken, true /* expectSuccess */,
+                 true /* useSessionTranscript */);
+    EXPECT_FALSE(canGetUserAuthPerSession_);
+    EXPECT_FALSE(canGetUserAuthTimeout_);
+    EXPECT_TRUE(canGetAccessibleByAll_);
+    EXPECT_FALSE(canGetAccessibleByNone_);
+
+    // Then we get a new authToken and try again.
+    tie(authToken, verificationToken) = mintTokens(0,          // challengeForAuthToken
+                                                   5 * 1000);  // ageOfAuthTokenMilliSeconds
+    retrieveData(authToken, verificationToken, true /* expectSuccess */,
+                 true /* useSessionTranscript */);
+    EXPECT_FALSE(canGetUserAuthPerSession_);
+    EXPECT_TRUE(canGetUserAuthTimeout_);
+    EXPECT_TRUE(canGetAccessibleByAll_);
+    EXPECT_FALSE(canGetAccessibleByNone_);
+}
+
+// Like MultipleRequestsSameSessionTranscript but we change the sessionTranscript
+// between the two calls. This test verifies that change is detected and the
+// second request fails.
+//
+TEST_P(UserAuthTests, MultipleRequestsSessionTranscriptChanges) {
+    provisionData();
+    setupRetrieveData();
+
+    // First we try with a stale authToken
+    //
+    auto [authToken, verificationToken] = mintTokens(0,           // challengeForAuthToken
+                                                     61 * 1000);  // ageOfAuthTokenMilliSeconds
+    retrieveData(authToken, verificationToken, true /* expectSuccess */,
+                 true /* useSessionTranscript */);
+    EXPECT_FALSE(canGetUserAuthPerSession_);
+    EXPECT_FALSE(canGetUserAuthTimeout_);
+    EXPECT_TRUE(canGetAccessibleByAll_);
+    EXPECT_FALSE(canGetAccessibleByNone_);
+
+    // Then we get a new authToken and try again.
+    tie(authToken, verificationToken) = mintTokens(0,          // challengeForAuthToken
+                                                   5 * 1000);  // ageOfAuthTokenMilliSeconds
+
+    // Change sessionTranscript...
+    optional<vector<uint8_t>> eKeyPairNew = support::createEcKeyPair();
+    optional<vector<uint8_t>> ePublicKeyNew = support::ecKeyPairGetPublicKey(eKeyPairNew.value());
+    sessionTranscript_ = calcSessionTranscript(ePublicKeyNew.value());
+
+    // ... and expect failure.
+    retrieveData(authToken, verificationToken, false /* expectSuccess */,
+                 true /* useSessionTranscript */);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        Identity, UserAuthTests,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
+        android::PrintInstanceNameToString);
+
+}  // namespace android::hardware::identity
diff --git a/identity/aidl/vts/VtsAttestationParserSupport.cpp b/identity/aidl/vts/VtsAttestationParserSupport.cpp
new file mode 100644
index 0000000..71fe733
--- /dev/null
+++ b/identity/aidl/vts/VtsAttestationParserSupport.cpp
@@ -0,0 +1,187 @@
+/*
+ * 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.
+ */
+
+#include "VtsAttestationParserSupport.h"
+
+#include <aidl/Gtest.h>
+#include <map>
+
+namespace android::hardware::identity::test_utils {
+
+using std::endl;
+using std::map;
+using std::optional;
+using std::string;
+using std::vector;
+
+using ::android::sp;
+using ::android::String16;
+using ::android::binder::Status;
+
+using ::keymaster::ASN1_OBJECT_Ptr;
+using ::keymaster::AuthorizationSet;
+using ::keymaster::EVP_PKEY_Ptr;
+using ::keymaster::kAttestionRecordOid;
+using ::keymaster::TAG_ATTESTATION_APPLICATION_ID;
+using ::keymaster::TAG_IDENTITY_CREDENTIAL_KEY;
+using ::keymaster::TAG_INCLUDE_UNIQUE_ID;
+using ::keymaster::TypedTag;
+using ::keymaster::X509_Ptr;
+
+using support::certificateChainSplit;
+
+optional<keymaster_cert_chain_t> AttestationCertificateParser::certificateChainToKeymasterChain(
+        const vector<Certificate>& certificates) {
+    if (certificates.size() <= 0) {
+        return {};
+    }
+
+    keymaster_cert_chain_t kCert;
+    kCert.entry_count = certificates.size();
+    kCert.entries = (keymaster_blob_t*)malloc(sizeof(keymaster_blob_t) * kCert.entry_count);
+
+    int index = 0;
+    for (const auto& c : certificates) {
+        kCert.entries[index].data_length = c.encodedCertificate.size();
+        uint8_t* data = (uint8_t*)malloc(c.encodedCertificate.size());
+
+        memcpy(data, c.encodedCertificate.data(), c.encodedCertificate.size());
+        kCert.entries[index].data = (const uint8_t*)data;
+        index++;
+    }
+
+    return kCert;
+}
+
+bool AttestationCertificateParser::parse() {
+    optional<keymaster_cert_chain_t> cert_chain = certificateChainToKeymasterChain(origCertChain_);
+    if (!cert_chain) {
+        return false;
+    }
+
+    if (cert_chain.value().entry_count < 3) {
+        return false;
+    }
+
+    if (!verifyChain(cert_chain.value())) {
+        return false;
+    }
+
+    if (!verifyAttestationRecord(cert_chain.value().entries[0])) {
+        return false;
+    }
+
+    keymaster_free_cert_chain(&cert_chain.value());
+    return true;
+}
+
+ASN1_OCTET_STRING* AttestationCertificateParser::getAttestationRecord(X509* certificate) {
+    ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1));
+    if (!oid.get()) return nullptr;
+
+    int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1);
+    if (location == -1) return nullptr;
+
+    X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location);
+    if (!attest_rec_ext) return nullptr;
+
+    ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext);
+    return attest_rec;
+}
+
+X509* AttestationCertificateParser::parseCertBlob(const keymaster_blob_t& blob) {
+    const uint8_t* p = blob.data;
+    return d2i_X509(nullptr, &p, blob.data_length);
+}
+
+bool AttestationCertificateParser::verifyAttestationRecord(
+        const keymaster_blob_t& attestation_cert) {
+    X509_Ptr cert(parseCertBlob(attestation_cert));
+    if (!cert.get()) {
+        return false;
+    }
+
+    ASN1_OCTET_STRING* attest_rec = getAttestationRecord(cert.get());
+    if (!attest_rec) {
+        return false;
+    }
+
+    keymaster_blob_t att_unique_id = {};
+    keymaster_blob_t att_challenge;
+    keymaster_error_t ret = parse_attestation_record(
+            attest_rec->data, attest_rec->length, &att_attestation_version_,
+            &att_attestation_security_level_, &att_keymaster_version_,
+            &att_keymaster_security_level_, &att_challenge, &att_sw_enforced_, &att_hw_enforced_,
+            &att_unique_id);
+    if (ret) {
+        return false;
+    }
+
+    att_challenge_.assign(att_challenge.data, att_challenge.data + att_challenge.data_length);
+    return true;
+}
+
+uint32_t AttestationCertificateParser::getKeymasterVersion() {
+    return att_keymaster_version_;
+}
+
+uint32_t AttestationCertificateParser::getAttestationVersion() {
+    return att_attestation_version_;
+}
+
+vector<uint8_t> AttestationCertificateParser::getAttestationChallenge() {
+    return att_challenge_;
+}
+
+keymaster_security_level_t AttestationCertificateParser::getKeymasterSecurityLevel() {
+    return att_keymaster_security_level_;
+}
+
+keymaster_security_level_t AttestationCertificateParser::getAttestationSecurityLevel() {
+    return att_attestation_security_level_;
+}
+
+// Verify the Attestation certificates are correctly chained.
+bool AttestationCertificateParser::verifyChain(const keymaster_cert_chain_t& chain) {
+    for (size_t i = 0; i < chain.entry_count - 1; ++i) {
+        keymaster_blob_t& key_cert_blob = chain.entries[i];
+        keymaster_blob_t& signing_cert_blob = chain.entries[i + 1];
+
+        X509_Ptr key_cert(parseCertBlob(key_cert_blob));
+        X509_Ptr signing_cert(parseCertBlob(signing_cert_blob));
+        if (!key_cert.get() || !signing_cert.get()) {
+            return false;
+        }
+
+        EVP_PKEY_Ptr signing_pubkey(X509_get_pubkey(signing_cert.get()));
+        if (!signing_pubkey.get()) return false;
+
+        if (X509_verify(key_cert.get(), signing_pubkey.get()) != 1) {
+            return false;
+        }
+
+        if (i + 1 == chain.entry_count - 1) {
+            // Last entry is self-signed.
+            if (X509_verify(signing_cert.get(), signing_pubkey.get()) != 1) {
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+}  // namespace android::hardware::identity::test_utils
diff --git a/identity/aidl/vts/VtsAttestationParserSupport.h b/identity/aidl/vts/VtsAttestationParserSupport.h
new file mode 100644
index 0000000..7c7e1b6
--- /dev/null
+++ b/identity/aidl/vts/VtsAttestationParserSupport.h
@@ -0,0 +1,122 @@
+
+/*
+ * 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.
+ */
+
+#ifndef VTS_ATTESTATION_PARSER_SUPPORT_H
+#define VTS_ATTESTATION_PARSER_SUPPORT_H
+
+//#include <aidl/Gtest.h>
+#include <android/hardware/identity/IIdentityCredentialStore.h>
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+#include <android/hardware/keymaster/4.0/types.h>
+#include <hardware/keymaster_defs.h>
+#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/authorization_set.h>
+#include <keymaster/contexts/pure_soft_keymaster_context.h>
+#include <keymaster/contexts/soft_attestation_cert.h>
+#include <keymaster/keymaster_tags.h>
+#include <keymaster/km_openssl/attestation_utils.h>
+#include <vector>
+
+namespace android::hardware::identity::test_utils {
+
+using ::std::optional;
+using ::std::string;
+using ::std::vector;
+
+using ::keymaster::AuthorizationSet;
+using ::keymaster::TypedTag;
+
+class AttestationCertificateParser {
+  public:
+    AttestationCertificateParser(const vector<Certificate>& certChain)
+        : origCertChain_(certChain) {}
+
+    bool parse();
+
+    uint32_t getKeymasterVersion();
+    uint32_t getAttestationVersion();
+    vector<uint8_t> getAttestationChallenge();
+    keymaster_security_level_t getKeymasterSecurityLevel();
+    keymaster_security_level_t getAttestationSecurityLevel();
+
+    template <keymaster_tag_t Tag>
+    bool getSwEnforcedBool(TypedTag<KM_BOOL, Tag> tag) {
+        if (att_sw_enforced_.GetTagValue(tag)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    template <keymaster_tag_t Tag>
+    bool getHwEnforcedBool(TypedTag<KM_BOOL, Tag> tag) {
+        if (att_hw_enforced_.GetTagValue(tag)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    template <keymaster_tag_t Tag>
+    optional<vector<uint8_t>> getHwEnforcedBlob(TypedTag<KM_BYTES, Tag> tag) {
+        keymaster_blob_t blob;
+        if (att_hw_enforced_.GetTagValue(tag, &blob)) {
+            return {};
+        }
+
+        vector<uint8_t> ret(blob.data, blob.data + blob.data_length);
+        return ret;
+    }
+
+    template <keymaster_tag_t Tag>
+    optional<vector<uint8_t>> getSwEnforcedBlob(TypedTag<KM_BYTES, Tag> tag) {
+        keymaster_blob_t blob;
+        if (!att_sw_enforced_.GetTagValue(tag, &blob)) {
+            return {};
+        }
+
+        vector<uint8_t> ret(blob.data, blob.data + blob.data_length);
+        return ret;
+    }
+
+  private:
+    // Helper functions.
+    bool verifyChain(const keymaster_cert_chain_t& chain);
+
+    ASN1_OCTET_STRING* getAttestationRecord(X509* certificate);
+
+    X509* parseCertBlob(const keymaster_blob_t& blob);
+
+    bool verifyAttestationRecord(const keymaster_blob_t& attestation_cert);
+
+    optional<keymaster_cert_chain_t> certificateChainToKeymasterChain(
+            const vector<Certificate>& certificates);
+
+    // Private variables.
+    vector<Certificate> origCertChain_;
+    AuthorizationSet att_sw_enforced_;
+    AuthorizationSet att_hw_enforced_;
+    uint32_t att_attestation_version_;
+    uint32_t att_keymaster_version_;
+    keymaster_security_level_t att_attestation_security_level_;
+    keymaster_security_level_t att_keymaster_security_level_;
+    vector<uint8_t> att_challenge_;
+};
+
+}  // namespace android::hardware::identity::test_utils
+
+#endif  // VTS_ATTESTATION_PARSER_SUPPORT_H
diff --git a/identity/aidl/vts/VtsAttestationTests.cpp b/identity/aidl/vts/VtsAttestationTests.cpp
new file mode 100644
index 0000000..c7cdfc7
--- /dev/null
+++ b/identity/aidl/vts/VtsAttestationTests.cpp
@@ -0,0 +1,143 @@
+/*
+ * 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 "VtsAttestationTests"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <android-base/logging.h>
+#include <android/hardware/identity/IIdentityCredentialStore.h>
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <cppbor.h>
+#include <cppbor_parse.h>
+#include <gtest/gtest.h>
+#include <future>
+#include <map>
+
+#include "VtsAttestationParserSupport.h"
+#include "VtsIdentityTestUtils.h"
+
+namespace android::hardware::identity {
+
+using std::endl;
+using std::map;
+using std::optional;
+using std::string;
+using std::vector;
+
+using ::android::sp;
+using ::android::String16;
+using ::android::binder::Status;
+
+using test_utils::AttestationCertificateParser;
+using test_utils::setupWritableCredential;
+using test_utils::validateAttestationCertificate;
+
+// This file verifies the Identity Credential VTS Attestation Certificate
+// generated.
+class VtsAttestationTests : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        credentialStore_ = android::waitForDeclaredService<IIdentityCredentialStore>(
+                String16(GetParam().c_str()));
+        ASSERT_NE(credentialStore_, nullptr);
+    }
+
+    sp<IIdentityCredentialStore> credentialStore_;
+};
+
+TEST_P(VtsAttestationTests, verifyAttestationWithNonemptyChallengeEmptyId) {
+    Status result;
+
+    HardwareInformation hwInfo;
+    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
+    sp<IWritableIdentityCredential> writableCredential;
+    ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_));
+
+    string challenge = "NotSoRandomChallenge";
+    vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
+    vector<Certificate> attestationCertificate;
+    vector<uint8_t> attestationApplicationId = {};
+
+    result = writableCredential->getAttestationCertificate(
+            attestationApplicationId, attestationChallenge, &attestationCertificate);
+
+    ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+                               << endl;
+
+    EXPECT_TRUE(validateAttestationCertificate(attestationCertificate, attestationChallenge,
+                                               attestationApplicationId, hwInfo));
+}
+
+TEST_P(VtsAttestationTests, verifyAttestationWithNonemptyChallengeNonemptyId) {
+    Status result;
+
+    HardwareInformation hwInfo;
+    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
+    sp<IWritableIdentityCredential> writableCredential;
+    ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_));
+
+    string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
+    vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
+    vector<Certificate> attestationCertificate;
+    string applicationId = "Attestation Verification";
+    vector<uint8_t> attestationApplicationId = {applicationId.begin(), applicationId.end()};
+
+    result = writableCredential->getAttestationCertificate(
+            attestationApplicationId, attestationChallenge, &attestationCertificate);
+
+    ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+                               << endl;
+
+    EXPECT_TRUE(validateAttestationCertificate(attestationCertificate, attestationChallenge,
+                                               attestationApplicationId, hwInfo));
+}
+
+TEST_P(VtsAttestationTests, verifyAttestationWithVeryShortChallengeAndId) {
+    Status result;
+
+    HardwareInformation hwInfo;
+    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
+    sp<IWritableIdentityCredential> writableCredential;
+    ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_));
+
+    string challenge = "c";
+    vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
+    vector<Certificate> attestationCertificate;
+    string applicationId = "i";
+    vector<uint8_t> attestationApplicationId = {applicationId.begin(), applicationId.end()};
+
+    result = writableCredential->getAttestationCertificate(
+            attestationApplicationId, attestationChallenge, &attestationCertificate);
+
+    ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+                               << endl;
+
+    EXPECT_TRUE(validateAttestationCertificate(attestationCertificate, attestationChallenge,
+                                               attestationApplicationId, hwInfo));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        Identity, VtsAttestationTests,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
+        android::PrintInstanceNameToString);
+
+}  // namespace android::hardware::identity
diff --git a/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
index 8a4e8a7..e347654 100644
--- a/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
+++ b/identity/aidl/vts/VtsHalIdentityEndToEndTest.cpp
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#define LOG_TAG "VtsHalIdentityTargetTest"
+#define LOG_TAG "VtsHalIdentityEndToEndTest"
 
 #include <aidl/Gtest.h>
 #include <aidl/Vintf.h>
@@ -27,15 +27,18 @@
 #include <gtest/gtest.h>
 #include <future>
 #include <map>
+#include <tuple>
 
 #include "VtsIdentityTestUtils.h"
 
 namespace android::hardware::identity {
 
 using std::endl;
+using std::make_tuple;
 using std::map;
 using std::optional;
 using std::string;
+using std::tuple;
 using std::vector;
 
 using ::android::sp;
@@ -43,6 +46,9 @@
 using ::android::binder::Status;
 
 using ::android::hardware::keymaster::HardwareAuthToken;
+using ::android::hardware::keymaster::VerificationToken;
+
+using test_utils::validateAttestationCertificate;
 
 class IdentityAidl : public testing::TestWithParam<std::string> {
   public:
@@ -63,18 +69,73 @@
     ASSERT_GE(info.dataChunkSize, 256);
 }
 
+tuple<bool, string, vector<uint8_t>, vector<uint8_t>> extractFromTestCredentialData(
+        const vector<uint8_t>& credentialData) {
+    string docType;
+    vector<uint8_t> storageKey;
+    vector<uint8_t> credentialPrivKey;
+
+    auto [item, _, message] = cppbor::parse(credentialData);
+    if (item == nullptr) {
+        return make_tuple(false, docType, storageKey, credentialPrivKey);
+    }
+
+    const cppbor::Array* arrayItem = item->asArray();
+    if (arrayItem == nullptr || arrayItem->size() != 3) {
+        return make_tuple(false, docType, storageKey, credentialPrivKey);
+    }
+
+    const cppbor::Tstr* docTypeItem = (*arrayItem)[0]->asTstr();
+    const cppbor::Bool* testCredentialItem =
+            ((*arrayItem)[1]->asSimple() != nullptr ? ((*arrayItem)[1]->asSimple()->asBool())
+                                                    : nullptr);
+    const cppbor::Bstr* encryptedCredentialKeysItem = (*arrayItem)[2]->asBstr();
+    if (docTypeItem == nullptr || testCredentialItem == nullptr ||
+        encryptedCredentialKeysItem == nullptr) {
+        return make_tuple(false, docType, storageKey, credentialPrivKey);
+    }
+
+    docType = docTypeItem->value();
+
+    vector<uint8_t> hardwareBoundKey = support::getTestHardwareBoundKey();
+    const vector<uint8_t>& encryptedCredentialKeys = encryptedCredentialKeysItem->value();
+    const vector<uint8_t> docTypeVec(docType.begin(), docType.end());
+    optional<vector<uint8_t>> decryptedCredentialKeys =
+            support::decryptAes128Gcm(hardwareBoundKey, encryptedCredentialKeys, docTypeVec);
+    if (!decryptedCredentialKeys) {
+        return make_tuple(false, docType, storageKey, credentialPrivKey);
+    }
+
+    auto [dckItem, dckPos, dckMessage] = cppbor::parse(decryptedCredentialKeys.value());
+    if (dckItem == nullptr) {
+        return make_tuple(false, docType, storageKey, credentialPrivKey);
+    }
+    const cppbor::Array* dckArrayItem = dckItem->asArray();
+    if (dckArrayItem == nullptr || dckArrayItem->size() != 2) {
+        return make_tuple(false, docType, storageKey, credentialPrivKey);
+    }
+    const cppbor::Bstr* storageKeyItem = (*dckArrayItem)[0]->asBstr();
+    const cppbor::Bstr* credentialPrivKeyItem = (*dckArrayItem)[1]->asBstr();
+    if (storageKeyItem == nullptr || credentialPrivKeyItem == nullptr) {
+        return make_tuple(false, docType, storageKey, credentialPrivKey);
+    }
+    storageKey = storageKeyItem->value();
+    credentialPrivKey = credentialPrivKeyItem->value();
+    return make_tuple(true, docType, storageKey, credentialPrivKey);
+}
+
 TEST_P(IdentityAidl, createAndRetrieveCredential) {
     // First, generate a key-pair for the reader since its public key will be
     // part of the request data.
     vector<uint8_t> readerKey;
     optional<vector<uint8_t>> readerCertificate =
-            test_utils::GenerateReaderCertificate("1234", readerKey);
+            test_utils::generateReaderCertificate("1234", &readerKey);
     ASSERT_TRUE(readerCertificate);
 
     // Make the portrait image really big (just shy of 256 KiB) to ensure that
     // the chunking code gets exercised.
     vector<uint8_t> portraitImage;
-    test_utils::SetImageData(portraitImage);
+    test_utils::setImageData(portraitImage);
 
     // Access control profiles:
     const vector<test_utils::TestProfile> testProfiles = {// Profile 0 (reader authentication)
@@ -82,7 +143,20 @@
                                                           // Profile 1 (no authentication)
                                                           {1, {}, false, 0}};
 
+    // It doesn't matter since no user auth is needed in this particular test,
+    // but for good measure, clear out the tokens we pass to the HAL.
     HardwareAuthToken authToken;
+    VerificationToken verificationToken;
+    authToken.challenge = 0;
+    authToken.userId = 0;
+    authToken.authenticatorId = 0;
+    authToken.authenticatorType = ::android::hardware::keymaster::HardwareAuthenticatorType::NONE;
+    authToken.timestamp.milliSeconds = 0;
+    authToken.mac.clear();
+    verificationToken.challenge = 0;
+    verificationToken.timestamp.milliSeconds = 0;
+    verificationToken.securityLevel = ::android::hardware::keymaster::SecurityLevel::SOFTWARE;
+    verificationToken.mac.clear();
 
     // Here's the actual test data:
     const vector<test_utils::TestEntryData> testEntries = {
@@ -100,24 +174,28 @@
 
     string cborPretty;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     string challenge = "attestationChallenge";
     test_utils::AttestationData attData(writableCredential, challenge, {});
     ASSERT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
-    ASSERT_EQ(binder::Status::EX_NONE, attData.result.exceptionCode());
-    ASSERT_EQ(IIdentityCredentialStore::STATUS_OK, attData.result.serviceSpecificErrorCode());
 
-    // TODO: set it to something random and check it's in the cert chain
-    ASSERT_GE(attData.attestationCertificate.size(), 2);
+    EXPECT_TRUE(validateAttestationCertificate(attData.attestationCertificate,
+                                               attData.attestationChallenge,
+                                               attData.attestationApplicationId, hwInfo));
 
+    // This is kinda of a hack but we need to give the size of
+    // ProofOfProvisioning that we'll expect to receive.
+    const int32_t expectedProofOfProvisioningSize = 262861 - 326 + readerCertificate.value().size();
+    // OK to fail, not available in v1 HAL
+    writableCredential->setExpectedProofOfProvisioningSize(expectedProofOfProvisioningSize);
     ASSERT_TRUE(
             writableCredential->startPersonalization(testProfiles.size(), testEntriesEntryCounts)
                     .isOk());
 
     optional<vector<SecureAccessControlProfile>> secureProfiles =
-            test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+            test_utils::addAccessControlProfiles(writableCredential, testProfiles);
     ASSERT_TRUE(secureProfiles);
 
     // Uses TestEntryData* pointer as key and values are the encrypted blobs. This
@@ -125,7 +203,7 @@
     map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
 
     for (const auto& entry : testEntries) {
-        ASSERT_TRUE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+        ASSERT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
                                          encryptedBlobs, true));
     }
 
@@ -135,6 +213,7 @@
             writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature)
                     .isOk());
 
+    // Validate the proofOfProvisioning which was returned
     optional<vector<uint8_t>> proofOfProvisioning =
             support::coseSignGetPayload(proofOfProvisioningSignature);
     ASSERT_TRUE(proofOfProvisioning);
@@ -195,6 +274,22 @@
                                                  credentialPubKey.value()));
     writableCredential = nullptr;
 
+    // Extract doctype, storage key, and credentialPrivKey from credentialData... this works
+    // only because we asked for a test-credential meaning that the HBK is all zeroes.
+    auto [exSuccess, exDocType, exStorageKey, exCredentialPrivKey] =
+            extractFromTestCredentialData(credentialData);
+    ASSERT_TRUE(exSuccess);
+    ASSERT_EQ(exDocType, "org.iso.18013-5.2019.mdl");
+    // ... check that the public key derived from the private key matches what was
+    // in the certificate.
+    optional<vector<uint8_t>> exCredentialKeyPair =
+            support::ecPrivateKeyToKeyPair(exCredentialPrivKey);
+    ASSERT_TRUE(exCredentialKeyPair);
+    optional<vector<uint8_t>> exCredentialPubKey =
+            support::ecKeyPairGetPublicKey(exCredentialKeyPair.value());
+    ASSERT_TRUE(exCredentialPubKey);
+    ASSERT_EQ(exCredentialPubKey.value(), credentialPubKey.value());
+
     // Now that the credential has been provisioned, read it back and check the
     // correct data is returned.
     sp<IIdentityCredential> credential;
@@ -224,7 +319,7 @@
     cppbor::Array sessionTranscript = cppbor::Array()
                                               .add(cppbor::Semantic(24, deviceEngagementBytes))
                                               .add(cppbor::Semantic(24, eReaderPubBytes));
-    vector<uint8_t> sessionTranscriptBytes = sessionTranscript.encode();
+    vector<uint8_t> sessionTranscriptEncoded = sessionTranscript.encode();
 
     vector<uint8_t> itemsRequestBytes =
             cppbor::Map("nameSpaces",
@@ -252,14 +347,17 @@
             "  },\n"
             "}",
             cborPretty);
-    vector<uint8_t> dataToSign = cppbor::Array()
-                                         .add("ReaderAuthentication")
-                                         .add(sessionTranscript.clone())
-                                         .add(cppbor::Semantic(24, itemsRequestBytes))
-                                         .encode();
+    vector<uint8_t> encodedReaderAuthentication =
+            cppbor::Array()
+                    .add("ReaderAuthentication")
+                    .add(sessionTranscript.clone())
+                    .add(cppbor::Semantic(24, itemsRequestBytes))
+                    .encode();
+    vector<uint8_t> encodedReaderAuthenticationBytes =
+            cppbor::Semantic(24, encodedReaderAuthentication).encode();
     optional<vector<uint8_t>> readerSignature =
-            support::coseSignEcDsa(readerKey, {},  // content
-                                   dataToSign,     // detached content
+            support::coseSignEcDsa(readerKey, {},                     // content
+                                   encodedReaderAuthenticationBytes,  // detached content
                                    readerCertificate.value());
     ASSERT_TRUE(readerSignature);
 
@@ -267,10 +365,33 @@
     vector<uint8_t> signingKeyBlob;
     Certificate signingKeyCertificate;
     ASSERT_TRUE(credential->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
+    optional<vector<uint8_t>> signingPubKey =
+            support::certificateChainGetTopMostKey(signingKeyCertificate.encodedCertificate);
+    EXPECT_TRUE(signingPubKey);
 
+    // Since we're using a test-credential we know storageKey meaning we can get the
+    // private key. Do this, derive the public key from it, and check this matches what
+    // is in the certificate...
+    const vector<uint8_t> exDocTypeVec(exDocType.begin(), exDocType.end());
+    optional<vector<uint8_t>> exSigningPrivKey =
+            support::decryptAes128Gcm(exStorageKey, signingKeyBlob, exDocTypeVec);
+    ASSERT_TRUE(exSigningPrivKey);
+    optional<vector<uint8_t>> exSigningKeyPair =
+            support::ecPrivateKeyToKeyPair(exSigningPrivKey.value());
+    ASSERT_TRUE(exSigningKeyPair);
+    optional<vector<uint8_t>> exSigningPubKey =
+            support::ecKeyPairGetPublicKey(exSigningKeyPair.value());
+    ASSERT_TRUE(exSigningPubKey);
+    ASSERT_EQ(exSigningPubKey.value(), signingPubKey.value());
+
+    vector<RequestNamespace> requestedNamespaces = test_utils::buildRequestNamespaces(testEntries);
+    // OK to fail, not available in v1 HAL
+    credential->setRequestedNamespaces(requestedNamespaces);
+    // OK to fail, not available in v1 HAL
+    credential->setVerificationToken(verificationToken);
     ASSERT_TRUE(credential
                         ->startRetrieval(secureProfiles.value(), authToken, itemsRequestBytes,
-                                         signingKeyBlob, sessionTranscriptBytes,
+                                         signingKeyBlob, sessionTranscriptEncoded,
                                          readerSignature.value(), testEntriesEntryCounts)
                         .isOk());
 
@@ -291,6 +412,9 @@
             content.insert(content.end(), chunk.begin(), chunk.end());
         }
         EXPECT_EQ(content, entry.valueCbor);
+
+        // TODO: also use |exStorageKey| to decrypt data and check it's the same as whatt
+        // the HAL returns...
     }
 
     vector<uint8_t> mac;
@@ -311,7 +435,7 @@
             "  },\n"
             "}",
             cborPretty);
-    // The data that is MACed is ["DeviceAuthentication", sessionTranscriptBytes, docType,
+    // The data that is MACed is ["DeviceAuthentication", sessionTranscript, docType,
     // deviceNameSpacesBytes] so build up that structure
     cppbor::Array deviceAuthentication;
     deviceAuthentication.add("DeviceAuthentication");
@@ -320,24 +444,80 @@
     string docType = "org.iso.18013-5.2019.mdl";
     deviceAuthentication.add(docType);
     deviceAuthentication.add(cppbor::Semantic(24, deviceNameSpacesBytes));
-    vector<uint8_t> encodedDeviceAuthentication = deviceAuthentication.encode();
-    optional<vector<uint8_t>> signingPublicKey =
-            support::certificateChainGetTopMostKey(signingKeyCertificate.encodedCertificate);
-    EXPECT_TRUE(signingPublicKey);
-
+    vector<uint8_t> deviceAuthenticationBytes =
+            cppbor::Semantic(24, deviceAuthentication.encode()).encode();
     // Derive the key used for MACing.
     optional<vector<uint8_t>> readerEphemeralPrivateKey =
             support::ecKeyPairGetPrivateKey(readerEphemeralKeyPair.value());
     optional<vector<uint8_t>> sharedSecret =
-            support::ecdh(signingPublicKey.value(), readerEphemeralPrivateKey.value());
+            support::ecdh(signingPubKey.value(), readerEphemeralPrivateKey.value());
     ASSERT_TRUE(sharedSecret);
+    // Mix-in SessionTranscriptBytes
+    vector<uint8_t> sessionTranscriptBytes =
+            cppbor::Semantic(24, sessionTranscript.encode()).encode();
+    vector<uint8_t> sharedSecretWithSessionTranscriptBytes = sharedSecret.value();
+    std::copy(sessionTranscriptBytes.begin(), sessionTranscriptBytes.end(),
+              std::back_inserter(sharedSecretWithSessionTranscriptBytes));
     vector<uint8_t> salt = {0x00};
     vector<uint8_t> info = {};
-    optional<vector<uint8_t>> derivedKey = support::hkdf(sharedSecret.value(), salt, info, 32);
+    optional<vector<uint8_t>> derivedKey =
+            support::hkdf(sharedSecretWithSessionTranscriptBytes, salt, info, 32);
     ASSERT_TRUE(derivedKey);
     optional<vector<uint8_t>> calculatedMac =
-            support::coseMac0(derivedKey.value(), {},        // payload
-                              encodedDeviceAuthentication);  // detached content
+            support::coseMac0(derivedKey.value(), {},      // payload
+                              deviceAuthenticationBytes);  // detached content
+    ASSERT_TRUE(calculatedMac);
+    EXPECT_EQ(mac, calculatedMac);
+
+    // Also perform an additional empty request. This is what mDL applications
+    // are envisioned to do - one call to get the data elements, another to get
+    // an empty DeviceSignedItems and corresponding MAC.
+    //
+    credential->setRequestedNamespaces({});  // OK to fail, not available in v1 HAL
+    ASSERT_TRUE(credential
+                        ->startRetrieval(
+                                secureProfiles.value(), authToken, {},         // itemsRequestBytes
+                                signingKeyBlob, sessionTranscriptEncoded, {},  // readerSignature,
+                                testEntriesEntryCounts)
+                        .isOk());
+    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
+    cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 32, {});
+    ASSERT_EQ("{}", cborPretty);
+    // Calculate DeviceAuthentication and MAC (MACing key hasn't changed)
+    deviceAuthentication = cppbor::Array();
+    deviceAuthentication.add("DeviceAuthentication");
+    deviceAuthentication.add(sessionTranscript.clone());
+    deviceAuthentication.add(docType);
+    deviceAuthentication.add(cppbor::Semantic(24, deviceNameSpacesBytes));
+    deviceAuthenticationBytes = cppbor::Semantic(24, deviceAuthentication.encode()).encode();
+    calculatedMac = support::coseMac0(derivedKey.value(), {},      // payload
+                                      deviceAuthenticationBytes);  // detached content
+    ASSERT_TRUE(calculatedMac);
+    EXPECT_EQ(mac, calculatedMac);
+
+    // Some mDL apps might send a request but with a single empty
+    // namespace. Check that too.
+    RequestNamespace emptyRequestNS;
+    emptyRequestNS.namespaceName = "PersonalData";
+    credential->setRequestedNamespaces({emptyRequestNS});  // OK to fail, not available in v1 HAL
+    ASSERT_TRUE(credential
+                        ->startRetrieval(
+                                secureProfiles.value(), authToken, {},         // itemsRequestBytes
+                                signingKeyBlob, sessionTranscriptEncoded, {},  // readerSignature,
+                                testEntriesEntryCounts)
+                        .isOk());
+    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
+    cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 32, {});
+    ASSERT_EQ("{}", cborPretty);
+    // Calculate DeviceAuthentication and MAC (MACing key hasn't changed)
+    deviceAuthentication = cppbor::Array();
+    deviceAuthentication.add("DeviceAuthentication");
+    deviceAuthentication.add(sessionTranscript.clone());
+    deviceAuthentication.add(docType);
+    deviceAuthentication.add(cppbor::Semantic(24, deviceNameSpacesBytes));
+    deviceAuthenticationBytes = cppbor::Semantic(24, deviceAuthentication.encode()).encode();
+    calculatedMac = support::coseMac0(derivedKey.value(), {},      // payload
+                                      deviceAuthenticationBytes);  // detached content
     ASSERT_TRUE(calculatedMac);
     EXPECT_EQ(mac, calculatedMac);
 }
diff --git a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
index b68fbb5..b572b0f 100644
--- a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
+++ b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
@@ -56,8 +56,12 @@
 
 TEST_P(IdentityCredentialTests, verifyAttestationWithEmptyChallenge) {
     Status result;
+
+    HardwareInformation hwInfo;
+    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     vector<uint8_t> attestationChallenge;
     vector<Certificate> attestationCertificate;
@@ -65,16 +69,20 @@
     result = writableCredential->getAttestationCertificate(
             attestationApplicationId, attestationChallenge, &attestationCertificate);
 
-    EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
-                               << endl;
-
-    EXPECT_TRUE(test_utils::ValidateAttestationCertificate(attestationCertificate));
+    EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+                                << endl;
+    EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
+    EXPECT_EQ(IIdentityCredentialStore::STATUS_INVALID_DATA, result.serviceSpecificErrorCode());
 }
 
 TEST_P(IdentityCredentialTests, verifyAttestationSuccessWithChallenge) {
     Status result;
+
+    HardwareInformation hwInfo;
+    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     string challenge = "NotSoRandomChallenge1NotSoRandomChallenge1NotSoRandomChallenge1";
     vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
@@ -87,17 +95,24 @@
     EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 
-    EXPECT_TRUE(test_utils::ValidateAttestationCertificate(attestationCertificate));
+    EXPECT_TRUE(test_utils::validateAttestationCertificate(
+            attestationCertificate, attestationChallenge, attestationApplicationId, hwInfo));
 }
 
 TEST_P(IdentityCredentialTests, verifyAttestationDoubleCallFails) {
     Status result;
+
+    HardwareInformation hwInfo;
+    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     string challenge = "NotSoRandomChallenge1";
     test_utils::AttestationData attData(writableCredential, challenge, {});
-    ASSERT_TRUE(test_utils::ValidateAttestationCertificate(attData.attestationCertificate));
+    ASSERT_TRUE(test_utils::validateAttestationCertificate(
+            attData.attestationCertificate, attData.attestationChallenge,
+            attData.attestationApplicationId, hwInfo));
 
     string challenge2 = "NotSoRandomChallenge2";
     test_utils::AttestationData attData2(writableCredential, challenge2, {});
@@ -110,10 +125,11 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalization) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     // First call should go through
     const vector<int32_t> entryCounts = {2, 4};
+    writableCredential->setExpectedProofOfProvisioningSize(123456);
     result = writableCredential->startPersonalization(5, entryCounts);
     ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
@@ -131,22 +147,12 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalizationMin) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     // Verify minimal number of profile count and entry count
     const vector<int32_t> entryCounts = {1, 1};
-    writableCredential->startPersonalization(1, entryCounts);
-    EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
-                               << endl;
-}
-
-TEST_P(IdentityCredentialTests, verifyStartPersonalizationZero) {
-    Status result;
-    sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
-
-    const vector<int32_t> entryCounts = {0};
-    writableCredential->startPersonalization(0, entryCounts);
+    writableCredential->setExpectedProofOfProvisioningSize(123456);
+    result = writableCredential->startPersonalization(1, entryCounts);
     EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 }
@@ -154,11 +160,12 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalizationOne) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     // Verify minimal number of profile count and entry count
     const vector<int32_t> entryCounts = {1};
-    writableCredential->startPersonalization(1, entryCounts);
+    writableCredential->setExpectedProofOfProvisioningSize(123456);
+    result = writableCredential->startPersonalization(1, entryCounts);
     EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 }
@@ -166,11 +173,12 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalizationLarge) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     // Verify set a large number of profile count and entry count is ok
     const vector<int32_t> entryCounts = {3000};
-    writableCredential->startPersonalization(3500, entryCounts);
+    writableCredential->setExpectedProofOfProvisioningSize(123456);
+    result = writableCredential->startPersonalization(25, entryCounts);
     EXPECT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 }
@@ -178,15 +186,16 @@
 TEST_P(IdentityCredentialTests, verifyProfileNumberMismatchShouldFail) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     // Enter mismatched entry and profile numbers
     const vector<int32_t> entryCounts = {5, 6};
-    writableCredential->startPersonalization(5, entryCounts);
+    writableCredential->setExpectedProofOfProvisioningSize(123456);
+    result = writableCredential->startPersonalization(5, entryCounts);
     ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 
-    optional<vector<uint8_t>> readerCertificate = test_utils::GenerateReaderCertificate("12345");
+    optional<vector<uint8_t>> readerCertificate = test_utils::generateReaderCertificate("12345");
     ASSERT_TRUE(readerCertificate);
 
     const vector<test_utils::TestProfile> testProfiles = {// Profile 0 (reader authentication)
@@ -196,7 +205,7 @@
                                                           {4, {}, false, 0}};
 
     optional<vector<SecureAccessControlProfile>> secureProfiles =
-            test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+            test_utils::addAccessControlProfiles(writableCredential, testProfiles);
     ASSERT_TRUE(secureProfiles);
 
     vector<uint8_t> credentialData;
@@ -205,7 +214,7 @@
             writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
 
     // finishAddingEntries should fail because the number of addAccessControlProfile mismatched with
-    // startPersonalization, and begintest_utils::AddEntry was not called.
+    // startPersonalization, and begintest_utils::addEntry was not called.
     EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                 << endl;
     EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
@@ -215,10 +224,11 @@
 TEST_P(IdentityCredentialTests, verifyDuplicateProfileId) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     const vector<int32_t> entryCounts = {3, 6};
-    writableCredential->startPersonalization(3, entryCounts);
+    writableCredential->setExpectedProofOfProvisioningSize(123456);
+    result = writableCredential->startPersonalization(3, entryCounts);
     ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 
@@ -235,9 +245,10 @@
         SecureAccessControlProfile profile;
         Certificate cert;
         cert.encodedCertificate = testProfile.readerCertificate;
+        int64_t secureUserId = testProfile.userAuthenticationRequired ? 66 : 0;
         result = writableCredential->addAccessControlProfile(
                 testProfile.id, cert, testProfile.userAuthenticationRequired,
-                testProfile.timeoutMillis, 0, &profile);
+                testProfile.timeoutMillis, secureUserId, &profile);
 
         if (expectOk) {
             expectOk = false;
@@ -272,25 +283,28 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     string challenge = "NotSoRandomChallenge1";
     test_utils::AttestationData attData(writableCredential, challenge, {});
     EXPECT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
 
+    optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
+    ASSERT_TRUE(readerCertificate1);
+
     const vector<int32_t> entryCounts = {1u};
-    writableCredential->startPersonalization(1, entryCounts);
+    size_t expectedPoPSize = 186 + readerCertificate1.value().size();
+    // OK to fail, not available in v1 HAL
+    writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
+    result = writableCredential->startPersonalization(1, entryCounts);
     ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 
-    optional<vector<uint8_t>> readerCertificate1 = test_utils::GenerateReaderCertificate("123456");
-    ASSERT_TRUE(readerCertificate1);
-
     const vector<test_utils::TestProfile> testProfiles = {{1, readerCertificate1.value(), true, 1}};
 
     optional<vector<SecureAccessControlProfile>> secureProfiles =
-            test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+            test_utils::addAccessControlProfiles(writableCredential, testProfiles);
     ASSERT_TRUE(secureProfiles);
 
     const vector<test_utils::TestEntryData> testEntries1 = {
@@ -299,7 +313,7 @@
 
     map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
     for (const auto& entry : testEntries1) {
-        ASSERT_TRUE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+        ASSERT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
                                          encryptedBlobs, true));
     }
 
@@ -356,17 +370,17 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     string challenge = "NotSoRandomChallenge";
     test_utils::AttestationData attData(writableCredential, challenge, {});
     EXPECT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
 
-    optional<vector<uint8_t>> readerCertificate1 = test_utils::GenerateReaderCertificate("123456");
+    optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
     ASSERT_TRUE(readerCertificate1);
 
-    optional<vector<uint8_t>> readerCertificate2 = test_utils::GenerateReaderCertificate("1256");
+    optional<vector<uint8_t>> readerCertificate2 = test_utils::generateReaderCertificate("1256");
     ASSERT_TRUE(readerCertificate2);
 
     const vector<test_utils::TestProfile> testProfiles = {
@@ -374,19 +388,23 @@
             {2, readerCertificate2.value(), true, 2},
     };
     const vector<int32_t> entryCounts = {1u, 3u, 1u, 1u, 2u};
-    writableCredential->startPersonalization(testProfiles.size(), entryCounts);
+    size_t expectedPoPSize =
+            525021 + readerCertificate1.value().size() + readerCertificate2.value().size();
+    // OK to fail, not available in v1 HAL
+    writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
+    result = writableCredential->startPersonalization(testProfiles.size(), entryCounts);
     ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 
     optional<vector<SecureAccessControlProfile>> secureProfiles =
-            test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+            test_utils::addAccessControlProfiles(writableCredential, testProfiles);
     ASSERT_TRUE(secureProfiles);
 
     vector<uint8_t> portraitImage1;
-    test_utils::SetImageData(portraitImage1);
+    test_utils::setImageData(portraitImage1);
 
     vector<uint8_t> portraitImage2;
-    test_utils::SetImageData(portraitImage2);
+    test_utils::setImageData(portraitImage2);
 
     const vector<test_utils::TestEntryData> testEntries1 = {
             {"Name Space 1", "Last name", string("Turing"), vector<int32_t>{1, 2}},
@@ -404,7 +422,7 @@
 
     map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
     for (const auto& entry : testEntries1) {
-        EXPECT_TRUE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+        EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
                                          encryptedBlobs, true));
     }
 
@@ -511,31 +529,36 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     string challenge = "NotSoRandomChallenge";
     test_utils::AttestationData attData(writableCredential, challenge, {});
     ASSERT_TRUE(attData.result.isOk())
             << attData.result.exceptionCode() << "; " << attData.result.exceptionMessage() << endl;
 
-    const vector<int32_t> entryCounts = {2u, 2u};
-    writableCredential->startPersonalization(3, entryCounts);
-    ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
-                               << endl;
-
-    optional<vector<uint8_t>> readerCertificate1 = test_utils::GenerateReaderCertificate("123456");
+    optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
     ASSERT_TRUE(readerCertificate1);
 
     optional<vector<uint8_t>> readerCertificate2 =
-            test_utils::GenerateReaderCertificate("123456987987987987987987");
+            test_utils::generateReaderCertificate("123456987987987987987987");
     ASSERT_TRUE(readerCertificate2);
 
+    const vector<int32_t> entryCounts = {2u, 2u};
+    size_t expectedPoPSize =
+            377 + readerCertificate1.value().size() + readerCertificate2.value().size();
+    ;
+    // OK to fail, not available in v1 HAL
+    writableCredential->setExpectedProofOfProvisioningSize(expectedPoPSize);
+    result = writableCredential->startPersonalization(3, entryCounts);
+    ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
+                               << endl;
+
     const vector<test_utils::TestProfile> testProfiles = {{0, readerCertificate1.value(), false, 0},
                                                           {1, readerCertificate2.value(), true, 1},
                                                           {2, {}, false, 0}};
 
     optional<vector<SecureAccessControlProfile>> secureProfiles =
-            test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+            test_utils::addAccessControlProfiles(writableCredential, testProfiles);
     ASSERT_TRUE(secureProfiles);
 
     const vector<test_utils::TestEntryData> testEntries1 = {
@@ -548,7 +571,7 @@
 
     map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
     for (const auto& entry : testEntries1) {
-        EXPECT_TRUE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+        EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
                                          encryptedBlobs, true));
     }
 
@@ -568,7 +591,7 @@
     ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
 
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     string challenge = "NotSoRandomChallenge";
     test_utils::AttestationData attData(writableCredential, challenge, {});
@@ -580,15 +603,16 @@
     // before "Image" and 2 after image, which is not correct.  All of same name
     // space should occur together.  Let's see if this fails.
     const vector<int32_t> entryCounts = {2u, 1u, 2u};
-    writableCredential->startPersonalization(3, entryCounts);
+    writableCredential->setExpectedProofOfProvisioningSize(123456);
+    result = writableCredential->startPersonalization(3, entryCounts);
     ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
 
-    optional<vector<uint8_t>> readerCertificate1 = test_utils::GenerateReaderCertificate("123456");
+    optional<vector<uint8_t>> readerCertificate1 = test_utils::generateReaderCertificate("123456");
     ASSERT_TRUE(readerCertificate1);
 
     optional<vector<uint8_t>> readerCertificate2 =
-            test_utils::GenerateReaderCertificate("123456987987987987987987");
+            test_utils::generateReaderCertificate("123456987987987987987987");
     ASSERT_TRUE(readerCertificate2);
 
     const vector<test_utils::TestProfile> testProfiles = {{0, readerCertificate1.value(), false, 0},
@@ -596,7 +620,7 @@
                                                           {2, {}, false, 0}};
 
     optional<vector<SecureAccessControlProfile>> secureProfiles =
-            test_utils::AddAccessControlProfiles(writableCredential, testProfiles);
+            test_utils::addAccessControlProfiles(writableCredential, testProfiles);
     ASSERT_TRUE(secureProfiles);
 
     const vector<test_utils::TestEntryData> testEntries1 = {
@@ -607,13 +631,13 @@
 
     map<const test_utils::TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
     for (const auto& entry : testEntries1) {
-        EXPECT_TRUE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+        EXPECT_TRUE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
                                          encryptedBlobs, true));
     }
     const test_utils::TestEntryData testEntry2 = {"Image", "Portrait image", string("asdfs"),
                                                   vector<int32_t>{0, 1}};
 
-    EXPECT_TRUE(test_utils::AddEntry(writableCredential, testEntry2, hwInfo.dataChunkSize,
+    EXPECT_TRUE(test_utils::addEntry(writableCredential, testEntry2, hwInfo.dataChunkSize,
                                      encryptedBlobs, true));
 
     // We expect this to fail because the namespace is out of order, all "Name Space"
@@ -625,7 +649,7 @@
     };
 
     for (const auto& entry : testEntries3) {
-        EXPECT_FALSE(test_utils::AddEntry(writableCredential, entry, hwInfo.dataChunkSize,
+        EXPECT_FALSE(test_utils::addEntry(writableCredential, entry, hwInfo.dataChunkSize,
                                           encryptedBlobs, false));
     }
 
@@ -634,7 +658,7 @@
     result =
             writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature);
 
-    // should fail because test_utils::AddEntry should have failed earlier.
+    // should fail because test_utils::addEntry should have failed earlier.
     EXPECT_FALSE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                 << endl;
     EXPECT_EQ(binder::Status::EX_SERVICE_SPECIFIC, result.exceptionCode());
@@ -643,9 +667,10 @@
 
 TEST_P(IdentityCredentialTests, verifyAccessControlProfileIdOutOfRange) {
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     const vector<int32_t> entryCounts = {1};
+    writableCredential->setExpectedProofOfProvisioningSize(123456);
     Status result = writableCredential->startPersonalization(1, entryCounts);
     ASSERT_TRUE(result.isOk()) << result.exceptionCode() << "; " << result.exceptionMessage()
                                << endl;
diff --git a/identity/aidl/vts/VtsIdentityTestUtils.cpp b/identity/aidl/vts/VtsIdentityTestUtils.cpp
index 3aeebc6..b6ed80f 100644
--- a/identity/aidl/vts/VtsIdentityTestUtils.cpp
+++ b/identity/aidl/vts/VtsIdentityTestUtils.cpp
@@ -19,6 +19,8 @@
 #include <aidl/Gtest.h>
 #include <map>
 
+#include "VtsAttestationParserSupport.h"
+
 namespace android::hardware::identity::test_utils {
 
 using std::endl;
@@ -31,7 +33,7 @@
 using ::android::String16;
 using ::android::binder::Status;
 
-bool SetupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
+bool setupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
                              sp<IIdentityCredentialStore>& credentialStore) {
     if (credentialStore == nullptr) {
         return false;
@@ -48,13 +50,13 @@
     }
 }
 
-optional<vector<uint8_t>> GenerateReaderCertificate(string serialDecimal) {
+optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal) {
     vector<uint8_t> privKey;
-    return GenerateReaderCertificate(serialDecimal, privKey);
+    return generateReaderCertificate(serialDecimal, &privKey);
 }
 
-optional<vector<uint8_t>> GenerateReaderCertificate(string serialDecimal,
-                                                    vector<uint8_t>& readerPrivateKey) {
+optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal,
+                                                    vector<uint8_t>* outReaderPrivateKey) {
     optional<vector<uint8_t>> readerKeyPKCS8 = support::createEcKeyPair();
     if (!readerKeyPKCS8) {
         return {};
@@ -67,7 +69,11 @@
         return {};
     }
 
-    readerPrivateKey = readerKey.value();
+    if (outReaderPrivateKey == nullptr) {
+        return {};
+    }
+
+    *outReaderPrivateKey = readerKey.value();
 
     string issuer = "Android Open Source Project";
     string subject = "Android IdentityCredential VTS Test";
@@ -79,7 +85,7 @@
                                                    validityNotBefore, validityNotAfter);
 }
 
-optional<vector<SecureAccessControlProfile>> AddAccessControlProfiles(
+optional<vector<SecureAccessControlProfile>> addAccessControlProfiles(
         sp<IWritableIdentityCredential>& writableCredential,
         const vector<TestProfile>& testProfiles) {
     Status result;
@@ -90,9 +96,10 @@
         SecureAccessControlProfile profile;
         Certificate cert;
         cert.encodedCertificate = testProfile.readerCertificate;
+        int64_t secureUserId = testProfile.userAuthenticationRequired ? 66 : 0;
         result = writableCredential->addAccessControlProfile(
                 testProfile.id, cert, testProfile.userAuthenticationRequired,
-                testProfile.timeoutMillis, 0, &profile);
+                testProfile.timeoutMillis, secureUserId, &profile);
 
         // Don't use assert so all errors can be outputed.  Then return
         // instead of exit even on errors so caller can decide.
@@ -120,7 +127,7 @@
 
 // Most test expects this function to pass. So we will print out additional
 // value if failed so more debug data can be provided.
-bool AddEntry(sp<IWritableIdentityCredential>& writableCredential, const TestEntryData& entry,
+bool addEntry(sp<IWritableIdentityCredential>& writableCredential, const TestEntryData& entry,
               int dataChunkSize, map<const TestEntryData*, vector<vector<uint8_t>>>& encryptedBlobs,
               bool expectSuccess) {
     Status result;
@@ -164,16 +171,92 @@
     return true;
 }
 
-bool ValidateAttestationCertificate(vector<Certificate>& inputCertificates) {
-    return (inputCertificates.size() >= 2);
-    // TODO: add parsing of the certificate and make sure it is genuine.
-}
-
-void SetImageData(vector<uint8_t>& image) {
+void setImageData(vector<uint8_t>& image) {
     image.resize(256 * 1024 - 10);
     for (size_t n = 0; n < image.size(); n++) {
         image[n] = (uint8_t)n;
     }
 }
 
+bool validateAttestationCertificate(const vector<Certificate>& inputCertificates,
+                                    const vector<uint8_t>& expectedChallenge,
+                                    const vector<uint8_t>& expectedAppId,
+                                    const HardwareInformation& hwInfo) {
+    AttestationCertificateParser certParser_(inputCertificates);
+    bool ret = certParser_.parse();
+    EXPECT_TRUE(ret);
+    if (!ret) {
+        return false;
+    }
+
+    // As per the IC HAL, the version of the Identity
+    // Credential HAL is 1.0 - and this is encoded as major*10 + minor. This field is used by
+    // Keymaster which is known to report integers less than or equal to 4 (for KM up to 4.0)
+    // and integers greater or equal than 41 (for KM starting with 4.1).
+    //
+    // Since we won't get to version 4.0 of the IC HAL for a while, let's also check that a KM
+    // version isn't errornously returned.
+    EXPECT_LE(10, certParser_.getKeymasterVersion());
+    EXPECT_GT(40, certParser_.getKeymasterVersion());
+    EXPECT_LE(3, certParser_.getAttestationVersion());
+
+    // Verify the app id matches to whatever we set it to be.
+    optional<vector<uint8_t>> appId =
+            certParser_.getSwEnforcedBlob(::keymaster::TAG_ATTESTATION_APPLICATION_ID);
+    if (appId) {
+        EXPECT_EQ(expectedAppId.size(), appId.value().size());
+        EXPECT_EQ(0, memcmp(expectedAppId.data(), appId.value().data(), expectedAppId.size()));
+    } else {
+        // app id not found
+        EXPECT_EQ(0, expectedAppId.size());
+    }
+
+    EXPECT_TRUE(certParser_.getHwEnforcedBool(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY));
+    EXPECT_FALSE(certParser_.getHwEnforcedBool(::keymaster::TAG_INCLUDE_UNIQUE_ID));
+
+    // Verify the challenge always matches in size and data of what is passed
+    // in.
+    vector<uint8_t> attChallenge = certParser_.getAttestationChallenge();
+    EXPECT_EQ(expectedChallenge.size(), attChallenge.size());
+    EXPECT_EQ(0, memcmp(expectedChallenge.data(), attChallenge.data(), expectedChallenge.size()));
+
+    // Ensure the attestation conveys that it's implemented in secure hardware (with carve-out
+    // for the reference implementation which cannot be implemented in secure hardware).
+    if (hwInfo.credentialStoreName == "Identity Credential Reference Implementation" &&
+        hwInfo.credentialStoreAuthorName == "Google") {
+        EXPECT_LE(KM_SECURITY_LEVEL_SOFTWARE, certParser_.getKeymasterSecurityLevel());
+        EXPECT_LE(KM_SECURITY_LEVEL_SOFTWARE, certParser_.getAttestationSecurityLevel());
+
+    } else {
+        // Actual devices should use TrustedEnvironment or StrongBox.
+        EXPECT_LE(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT, certParser_.getKeymasterSecurityLevel());
+        EXPECT_LE(KM_SECURITY_LEVEL_TRUSTED_ENVIRONMENT, certParser_.getAttestationSecurityLevel());
+    }
+    return true;
+}
+
+vector<RequestNamespace> buildRequestNamespaces(const vector<TestEntryData> entries) {
+    vector<RequestNamespace> ret;
+    RequestNamespace curNs;
+    for (const TestEntryData& testEntry : entries) {
+        if (testEntry.nameSpace != curNs.namespaceName) {
+            if (curNs.namespaceName.size() > 0) {
+                ret.push_back(curNs);
+            }
+            curNs.namespaceName = testEntry.nameSpace;
+            curNs.items.clear();
+        }
+
+        RequestDataItem item;
+        item.name = testEntry.name;
+        item.size = testEntry.valueCbor.size();
+        item.accessControlProfileIds = testEntry.profileIds;
+        curNs.items.push_back(item);
+    }
+    if (curNs.namespaceName.size() > 0) {
+        ret.push_back(curNs);
+    }
+    return ret;
+}
+
 }  // namespace android::hardware::identity::test_utils
diff --git a/identity/aidl/vts/VtsIdentityTestUtils.h b/identity/aidl/vts/VtsIdentityTestUtils.h
index 043ccd6..673b736 100644
--- a/identity/aidl/vts/VtsIdentityTestUtils.h
+++ b/identity/aidl/vts/VtsIdentityTestUtils.h
@@ -93,25 +93,30 @@
     uint64_t timeoutMillis;
 };
 
-bool SetupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
+bool setupWritableCredential(sp<IWritableIdentityCredential>& writableCredential,
                              sp<IIdentityCredentialStore>& credentialStore);
 
-optional<vector<uint8_t>> GenerateReaderCertificate(string serialDecimal);
+optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal);
 
-optional<vector<uint8_t>> GenerateReaderCertificate(string serialDecimal,
-                                                    vector<uint8_t>& readerPrivateKey);
+optional<vector<uint8_t>> generateReaderCertificate(string serialDecimal,
+                                                    vector<uint8_t>* outReaderPrivateKey);
 
-optional<vector<SecureAccessControlProfile>> AddAccessControlProfiles(
+optional<vector<SecureAccessControlProfile>> addAccessControlProfiles(
         sp<IWritableIdentityCredential>& writableCredential,
         const vector<TestProfile>& testProfiles);
 
-bool AddEntry(sp<IWritableIdentityCredential>& writableCredential, const TestEntryData& entry,
+bool addEntry(sp<IWritableIdentityCredential>& writableCredential, const TestEntryData& entry,
               int dataChunkSize, map<const TestEntryData*, vector<vector<uint8_t>>>& encryptedBlobs,
               bool expectSuccess);
 
-bool ValidateAttestationCertificate(vector<Certificate>& inputCertificates);
+void setImageData(vector<uint8_t>& image);
 
-void SetImageData(vector<uint8_t>& image);
+bool validateAttestationCertificate(const vector<Certificate>& inputCertificates,
+                                    const vector<uint8_t>& expectedChallenge,
+                                    const vector<uint8_t>& expectedAppId,
+                                    const HardwareInformation& hwInfo);
+
+vector<RequestNamespace> buildRequestNamespaces(const vector<TestEntryData> entries);
 
 }  // namespace android::hardware::identity::test_utils
 
diff --git a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
index 507e914..f7ec7c5 100644
--- a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
+++ b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
@@ -33,6 +33,7 @@
 using ::std::string;
 using ::std::tuple;
 using ::std::vector;
+using ::std::pair;
 
 // ---------------------------------------------------------------------------
 // Miscellaneous utilities.
@@ -119,6 +120,12 @@
 optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAndAttestation(
         const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId);
 
+// Like createEcKeyPairAndAttestation() but allows you to choose the public key.
+//
+optional<vector<vector<uint8_t>>> createAttestationForEcPublicKey(
+        const vector<uint8_t>& publicKey, const vector<uint8_t>& challenge,
+        const vector<uint8_t>& applicationId);
+
 // Creates an 256-bit EC key using the NID_X9_62_prime256v1 curve, returns the
 // PKCS#8 encoded key-pair.
 //
@@ -134,6 +141,11 @@
 //
 optional<vector<uint8_t>> ecKeyPairGetPrivateKey(const vector<uint8_t>& keyPair);
 
+// Creates a PKCS#8 encoded key-pair from a private key (which must be uncompressed,
+// e.g. 32 bytes). The public key is derived from the given private key..
+//
+optional<vector<uint8_t>> ecPrivateKeyToKeyPair(const vector<uint8_t>& privateKey);
+
 // For an EC key |keyPair| encoded in PKCS#8 format, creates a PKCS#12 structure
 // with the key-pair (not using a password to encrypt the data). The public key
 // in the created structure is included as a certificate, using the given fields
@@ -150,6 +162,12 @@
 //
 optional<vector<uint8_t>> signEcDsa(const vector<uint8_t>& key, const vector<uint8_t>& data);
 
+// Like signEcDsa() but instead of taking the data to be signed, takes a digest
+// of it instead.
+//
+optional<vector<uint8_t>> signEcDsaDigest(const vector<uint8_t>& key,
+                                          const vector<uint8_t>& dataDigest);
+
 // Calculates the HMAC with SHA-256 for |data| using |key|. The calculated HMAC
 // is returned and will be 32 bytes.
 //
@@ -170,6 +188,27 @@
 //
 optional<vector<uint8_t>> certificateChainGetTopMostKey(const vector<uint8_t>& certificateChain);
 
+// Extracts the public-key from the top-most certificate in |certificateChain|
+// (which should be a concatenated chain of DER-encoded X.509 certificates).
+//
+// Return offset and size of the public-key
+//
+optional<pair<size_t, size_t>> certificateFindPublicKey(const vector<uint8_t>& x509Certificate);
+
+// Extracts the TbsCertificate from the top-most certificate in |certificateChain|
+// (which should be a concatenated chain of DER-encoded X.509 certificates).
+//
+// Return offset and size of the TbsCertificate
+//
+optional<pair<size_t, size_t>> certificateTbsCertificate(const vector<uint8_t>& x509Certificate);
+
+// Extracts the Signature from the top-most certificate in |certificateChain|
+// (which should be a concatenated chain of DER-encoded X.509 certificates).
+//
+// Return offset and size of the Signature
+//
+optional<pair<size_t, size_t>> certificateFindSignature(const vector<uint8_t>& x509Certificate);
+
 // Generates a X.509 certificate for |publicKey| (which must be in the format
 // returned by ecKeyPairGetPublicKey()).
 //
@@ -226,6 +265,11 @@
 //
 bool certificateChainValidate(const vector<uint8_t>& certificateChain);
 
+// Returns true if |certificate| is signed by |publicKey|.
+//
+bool certificateSignedByPublicKey(const vector<uint8_t>& certificate,
+                                  const vector<uint8_t>& publicKey);
+
 // Signs |data| and |detachedContent| with |key| (which must be in the format
 // returned by ecKeyPairGetPrivateKey()).
 //
@@ -238,6 +282,21 @@
                                         const vector<uint8_t>& detachedContent,
                                         const vector<uint8_t>& certificateChain);
 
+// Creates a COSE_Signature1 where |signatureToBeSigned| is the ECDSA signature
+// of the ToBeSigned CBOR from RFC 8051 "4.4. Signing and Verification Process".
+//
+// The |signatureToBeSigned| is expected to be 64 bytes and contain the R value,
+// then the S value.
+//
+// The |data| parameter will be included in the COSE_Sign1 CBOR.
+//
+// If |certificateChain| is non-empty it's included in the 'x5chain'
+// protected header element (as as described in'draft-ietf-cose-x509-04').
+//
+optional<vector<uint8_t>> coseSignEcDsaWithSignature(const vector<uint8_t>& signatureToBeSigned,
+                                                     const vector<uint8_t>& data,
+                                                     const vector<uint8_t>& certificateChain);
+
 // Checks that |signatureCoseSign1| (in COSE_Sign1 format) is a valid signature
 // made with |public_key| (which must be in the format returned by
 // ecKeyPairGetPublicKey()) where |detachedContent| is the detached content.
@@ -246,9 +305,23 @@
                              const vector<uint8_t>& detachedContent,
                              const vector<uint8_t>& publicKey);
 
+// Converts a DER-encoded signature to the format used in 'signature' bstr in COSE_Sign1.
+bool ecdsaSignatureDerToCose(const vector<uint8_t>& ecdsaDerSignature,
+                             vector<uint8_t>& ecdsaCoseSignature);
+
+// Converts from the format in in 'signature' bstr in COSE_Sign1 to DER encoding.
+bool ecdsaSignatureCoseToDer(const vector<uint8_t>& ecdsaCoseSignature,
+                             vector<uint8_t>& ecdsaDerSignature);
+
 // Extracts the payload from a COSE_Sign1.
 optional<vector<uint8_t>> coseSignGetPayload(const vector<uint8_t>& signatureCoseSign1);
 
+// Extracts the signature (of the ToBeSigned CBOR) from a COSE_Sign1.
+optional<vector<uint8_t>> coseSignGetSignature(const vector<uint8_t>& signatureCoseSign1);
+
+// Extracts the signature algorithm from a COSE_Sign1.
+optional<int> coseSignGetAlg(const vector<uint8_t>& signatureCoseSign1);
+
 // Extracts the X.509 certificate chain, if present. Returns the data as a
 // concatenated chain of DER-encoded X.509 certificates
 //
@@ -264,6 +337,16 @@
 optional<vector<uint8_t>> coseMac0(const vector<uint8_t>& key, const vector<uint8_t>& data,
                                    const vector<uint8_t>& detachedContent);
 
+// Creates a COSE_Mac0 where |digestToBeMaced| is the HMAC-SHA256
+// of the ToBeMaced CBOR from RFC 8051 "6.3. How to Compute and Verify a MAC".
+//
+// The |digestToBeMaced| is expected to be 32 bytes.
+//
+// The |data| parameter will be included in the COSE_Mac0 CBOR.
+//
+optional<vector<uint8_t>> coseMacWithDigest(const vector<uint8_t>& digestToBeMaced,
+                                            const vector<uint8_t>& data);
+
 // ---------------------------------------------------------------------------
 // Utility functions specific to IdentityCredential.
 // ---------------------------------------------------------------------------
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index dc49ddc..8e099e7 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -24,6 +24,7 @@
 #include <stdarg.h>
 #include <stdio.h>
 #include <time.h>
+#include <chrono>
 #include <iomanip>
 
 #include <openssl/aes.h>
@@ -684,6 +685,48 @@
     return true;
 }
 
+bool certificateSignedByPublicKey(const vector<uint8_t>& certificate,
+                                  const vector<uint8_t>& publicKey) {
+    const unsigned char* p = certificate.data();
+    auto x509 = X509_Ptr(d2i_X509(nullptr, &p, certificate.size()));
+    if (x509 == nullptr) {
+        LOG(ERROR) << "Error parsing X509 certificate";
+        return false;
+    }
+
+    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+    auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
+    if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
+        1) {
+        LOG(ERROR) << "Error decoding publicKey";
+        return false;
+    }
+    auto ecKey = EC_KEY_Ptr(EC_KEY_new());
+    auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
+    if (ecKey.get() == nullptr || pkey.get() == nullptr) {
+        LOG(ERROR) << "Memory allocation failed";
+        return false;
+    }
+    if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
+        LOG(ERROR) << "Error setting group";
+        return false;
+    }
+    if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
+        LOG(ERROR) << "Error setting point";
+        return false;
+    }
+    if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
+        LOG(ERROR) << "Error setting key";
+        return false;
+    }
+
+    if (X509_verify(x509.get(), pkey.get()) != 1) {
+        return false;
+    }
+
+    return true;
+}
+
 // TODO: Right now the only check we perform is to check that each certificate
 //       is signed by its successor. We should - but currently don't - also check
 //       things like valid dates etc.
@@ -770,7 +813,8 @@
     return ret;
 }
 
-optional<vector<uint8_t>> signEcDsa(const vector<uint8_t>& key, const vector<uint8_t>& data) {
+optional<vector<uint8_t>> signEcDsaDigest(const vector<uint8_t>& key,
+                                          const vector<uint8_t>& dataDigest) {
     auto bn = BIGNUM_Ptr(BN_bin2bn(key.data(), key.size(), nullptr));
     if (bn.get() == nullptr) {
         LOG(ERROR) << "Error creating BIGNUM";
@@ -783,8 +827,7 @@
         return {};
     }
 
-    auto digest = sha256(data);
-    ECDSA_SIG* sig = ECDSA_do_sign(digest.data(), digest.size(), ec_key.get());
+    ECDSA_SIG* sig = ECDSA_do_sign(dataDigest.data(), dataDigest.size(), ec_key.get());
     if (sig == nullptr) {
         LOG(ERROR) << "Error signing digest";
         return {};
@@ -798,6 +841,10 @@
     return signature;
 }
 
+optional<vector<uint8_t>> signEcDsa(const vector<uint8_t>& key, const vector<uint8_t>& data) {
+    return signEcDsaDigest(key, sha256(data));
+}
+
 optional<vector<uint8_t>> hmacSha256(const vector<uint8_t>& key, const vector<uint8_t>& data) {
     HMAC_CTX ctx;
     HMAC_CTX_init(&ctx);
@@ -955,6 +1002,51 @@
     return make_pair(keyPair, attestationCert.value());
 }
 
+optional<vector<vector<uint8_t>>> createAttestationForEcPublicKey(
+        const vector<uint8_t>& publicKey, const vector<uint8_t>& challenge,
+        const vector<uint8_t>& applicationId) {
+    auto group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+    auto point = EC_POINT_Ptr(EC_POINT_new(group.get()));
+    if (EC_POINT_oct2point(group.get(), point.get(), publicKey.data(), publicKey.size(), nullptr) !=
+        1) {
+        LOG(ERROR) << "Error decoding publicKey";
+        return {};
+    }
+    auto ecKey = EC_KEY_Ptr(EC_KEY_new());
+    auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
+    if (ecKey.get() == nullptr || pkey.get() == nullptr) {
+        LOG(ERROR) << "Memory allocation failed";
+        return {};
+    }
+    if (EC_KEY_set_group(ecKey.get(), group.get()) != 1) {
+        LOG(ERROR) << "Error setting group";
+        return {};
+    }
+    if (EC_KEY_set_public_key(ecKey.get(), point.get()) != 1) {
+        LOG(ERROR) << "Error setting point";
+        return {};
+    }
+    if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
+        LOG(ERROR) << "Error setting key";
+        return {};
+    }
+
+    uint64_t now = (std::chrono::duration_cast<std::chrono::nanoseconds>(
+                    std::chrono::system_clock::now().time_since_epoch()).
+                    count()/ 1000000000);
+    uint64_t secondsInOneYear = 365 * 24 * 60 * 60;
+    uint64_t expireTimeMs = (now + secondsInOneYear) * 1000;
+
+    optional<vector<vector<uint8_t>>> attestationCert =
+            createAttestation(pkey.get(), applicationId, challenge, now * 1000, expireTimeMs);
+    if (!attestationCert) {
+        LOG(ERROR) << "Error create attestation from key and challenge";
+        return {};
+    }
+
+    return attestationCert.value();
+}
+
 optional<vector<uint8_t>> createEcKeyPair() {
     auto ec_key = EC_KEY_Ptr(EC_KEY_new());
     auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
@@ -1047,6 +1139,42 @@
     return privateKey;
 }
 
+optional<vector<uint8_t>> ecPrivateKeyToKeyPair(const vector<uint8_t>& privateKey) {
+    auto bn = BIGNUM_Ptr(BN_bin2bn(privateKey.data(), privateKey.size(), nullptr));
+    if (bn.get() == nullptr) {
+        LOG(ERROR) << "Error creating BIGNUM";
+        return {};
+    }
+
+    auto ecKey = EC_KEY_Ptr(EC_KEY_new_by_curve_name(NID_X9_62_prime256v1));
+    if (EC_KEY_set_private_key(ecKey.get(), bn.get()) != 1) {
+        LOG(ERROR) << "Error setting private key from BIGNUM";
+        return {};
+    }
+
+    auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
+    if (pkey.get() == nullptr) {
+        LOG(ERROR) << "Memory allocation failed";
+        return {};
+    }
+
+    if (EVP_PKEY_set1_EC_KEY(pkey.get(), ecKey.get()) != 1) {
+        LOG(ERROR) << "Error getting private key";
+        return {};
+    }
+
+    int size = i2d_PrivateKey(pkey.get(), nullptr);
+    if (size == 0) {
+        LOG(ERROR) << "Error generating public key encoding";
+        return {};
+    }
+    vector<uint8_t> keyPair;
+    keyPair.resize(size);
+    unsigned char* p = keyPair.data();
+    i2d_PrivateKey(pkey.get(), &p);
+    return keyPair;
+}
+
 optional<vector<uint8_t>> ecKeyPairGetPkcs12(const vector<uint8_t>& keyPair, const string& name,
                                              const string& serialDecimal, const string& issuer,
                                              const string& subject, time_t validityNotBefore,
@@ -1441,6 +1569,120 @@
     return publicKey;
 }
 
+optional<pair<size_t, size_t>> certificateFindPublicKey(const vector<uint8_t>& x509Certificate) {
+    vector<X509_Ptr> certs;
+    if (!parseX509Certificates(x509Certificate, certs)) {
+        return {};
+    }
+    if (certs.size() < 1) {
+        LOG(ERROR) << "No certificates in chain";
+        return {};
+    }
+
+    auto pkey = EVP_PKEY_Ptr(X509_get_pubkey(certs[0].get()));
+    if (pkey.get() == nullptr) {
+        LOG(ERROR) << "No public key";
+        return {};
+    }
+
+    auto ecKey = EC_KEY_Ptr(EVP_PKEY_get1_EC_KEY(pkey.get()));
+    if (ecKey.get() == nullptr) {
+        LOG(ERROR) << "Failed getting EC key";
+        return {};
+    }
+
+    auto ecGroup = EC_KEY_get0_group(ecKey.get());
+    auto ecPoint = EC_KEY_get0_public_key(ecKey.get());
+    int size = EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, nullptr, 0,
+                                  nullptr);
+    if (size == 0) {
+        LOG(ERROR) << "Error generating public key encoding";
+        return {};
+    }
+    vector<uint8_t> publicKey;
+    publicKey.resize(size);
+    EC_POINT_point2oct(ecGroup, ecPoint, POINT_CONVERSION_UNCOMPRESSED, publicKey.data(),
+                       publicKey.size(), nullptr);
+
+    size_t publicKeyOffset = 0;
+    size_t publicKeySize = (size_t)size;
+    void* location = memmem((const void*)x509Certificate.data(), x509Certificate.size(),
+                            (const void*)publicKey.data(), publicKey.size());
+
+    if (location == NULL) {
+        LOG(ERROR) << "Error finding publicKey from x509Certificate";
+        return {};
+    }
+    publicKeyOffset = (size_t)((const char*)location - (const char*)x509Certificate.data());
+
+    return std::make_pair(publicKeyOffset, publicKeySize);
+}
+
+optional<pair<size_t, size_t>> certificateTbsCertificate(const vector<uint8_t>& x509Certificate) {
+    vector<X509_Ptr> certs;
+    if (!parseX509Certificates(x509Certificate, certs)) {
+        return {};
+    }
+    if (certs.size() < 1) {
+        LOG(ERROR) << "No certificates in chain";
+        return {};
+    }
+
+    unsigned char* buf = NULL;
+    int len = i2d_re_X509_tbs(certs[0].get(), &buf);
+    if ((len < 0) || (buf == NULL)) {
+        LOG(ERROR) << "fail to extract tbsCertificate in x509Certificate";
+        return {};
+    }
+
+    vector<uint8_t> tbsCertificate(len);
+    memcpy(tbsCertificate.data(), buf, len);
+
+    size_t tbsCertificateOffset = 0;
+    size_t tbsCertificateSize = (size_t)len;
+    void* location = memmem((const void*)x509Certificate.data(), x509Certificate.size(),
+                            (const void*)tbsCertificate.data(), tbsCertificate.size());
+
+    if (location == NULL) {
+        LOG(ERROR) << "Error finding tbsCertificate from x509Certificate";
+        return {};
+    }
+    tbsCertificateOffset = (size_t)((const char*)location - (const char*)x509Certificate.data());
+
+    return std::make_pair(tbsCertificateOffset, tbsCertificateSize);
+}
+
+optional<pair<size_t, size_t>> certificateFindSignature(const vector<uint8_t>& x509Certificate) {
+    vector<X509_Ptr> certs;
+    if (!parseX509Certificates(x509Certificate, certs)) {
+        return {};
+    }
+    if (certs.size() < 1) {
+        LOG(ERROR) << "No certificates in chain";
+        return {};
+    }
+
+    ASN1_BIT_STRING* psig;
+    X509_ALGOR* palg;
+    X509_get0_signature((const ASN1_BIT_STRING**)&psig, (const X509_ALGOR**)&palg, certs[0].get());
+
+    vector<char> signature(psig->length);
+    memcpy(signature.data(), psig->data, psig->length);
+
+    size_t signatureOffset = 0;
+    size_t signatureSize = (size_t)psig->length;
+    void* location = memmem((const void*)x509Certificate.data(), x509Certificate.size(),
+                            (const void*)signature.data(), signature.size());
+
+    if (location == NULL) {
+        LOG(ERROR) << "Error finding signature from x509Certificate";
+        return {};
+    }
+    signatureOffset = (size_t)((const char*)location - (const char*)x509Certificate.data());
+
+    return std::make_pair(signatureOffset, signatureSize);
+}
+
 // ---------------------------------------------------------------------------
 // COSE Utility Functions
 // ---------------------------------------------------------------------------
@@ -1538,6 +1780,55 @@
     return true;
 }
 
+optional<vector<uint8_t>> coseSignEcDsaWithSignature(const vector<uint8_t>& signatureToBeSigned,
+                                                     const vector<uint8_t>& data,
+                                                     const vector<uint8_t>& certificateChain) {
+    if (signatureToBeSigned.size() != 64) {
+        LOG(ERROR) << "Invalid size for signatureToBeSigned, expected 64 got "
+                   << signatureToBeSigned.size();
+        return {};
+    }
+
+    cppbor::Map unprotectedHeaders;
+    cppbor::Map protectedHeaders;
+
+    protectedHeaders.add(COSE_LABEL_ALG, COSE_ALG_ECDSA_256);
+
+    if (certificateChain.size() != 0) {
+        optional<vector<vector<uint8_t>>> certs = support::certificateChainSplit(certificateChain);
+        if (!certs) {
+            LOG(ERROR) << "Error splitting certificate chain";
+            return {};
+        }
+        if (certs.value().size() == 1) {
+            unprotectedHeaders.add(COSE_LABEL_X5CHAIN, certs.value()[0]);
+        } else {
+            cppbor::Array certArray;
+            for (const vector<uint8_t>& cert : certs.value()) {
+                certArray.add(cert);
+            }
+            unprotectedHeaders.add(COSE_LABEL_X5CHAIN, std::move(certArray));
+        }
+    }
+
+    vector<uint8_t> encodedProtectedHeaders = coseEncodeHeaders(protectedHeaders);
+
+    cppbor::Array coseSign1;
+    coseSign1.add(encodedProtectedHeaders);
+    coseSign1.add(std::move(unprotectedHeaders));
+    if (data.size() == 0) {
+        cppbor::Null nullValue;
+        coseSign1.add(std::move(nullValue));
+    } else {
+        coseSign1.add(data);
+    }
+    coseSign1.add(signatureToBeSigned);
+    vector<uint8_t> signatureCoseSign1;
+    signatureCoseSign1 = coseSign1.encode();
+
+    return signatureCoseSign1;
+}
+
 optional<vector<uint8_t>> coseSignEcDsa(const vector<uint8_t>& key, const vector<uint8_t>& data,
                                         const vector<uint8_t>& detachedContent,
                                         const vector<uint8_t>& certificateChain) {
@@ -1673,6 +1964,35 @@
     return true;
 }
 
+// Extracts the signature (of the ToBeSigned CBOR) from a COSE_Sign1.
+optional<vector<uint8_t>> coseSignGetSignature(const vector<uint8_t>& signatureCoseSign1) {
+    auto [item, _, message] = cppbor::parse(signatureCoseSign1);
+    if (item == nullptr) {
+        LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
+        return {};
+    }
+    const cppbor::Array* array = item->asArray();
+    if (array == nullptr) {
+        LOG(ERROR) << "Value for COSE_Sign1 is not an array";
+        return {};
+    }
+    if (array->size() != 4) {
+        LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
+        return {};
+    }
+
+    vector<uint8_t> signature;
+    const cppbor::Bstr* signatureAsBstr = (*array)[3]->asBstr();
+    if (signatureAsBstr == nullptr) {
+        LOG(ERROR) << "Value for signature is not a bstr";
+        return {};
+    }
+    // Copy payload into |data|
+    signature = signatureAsBstr->value();
+
+    return signature;
+}
+
 optional<vector<uint8_t>> coseSignGetPayload(const vector<uint8_t>& signatureCoseSign1) {
     auto [item, _, message] = cppbor::parse(signatureCoseSign1);
     if (item == nullptr) {
@@ -1710,6 +2030,59 @@
     return data;
 }
 
+optional<int> coseSignGetAlg(const vector<uint8_t>& signatureCoseSign1) {
+    auto [item, _, message] = cppbor::parse(signatureCoseSign1);
+    if (item == nullptr) {
+        LOG(ERROR) << "Passed-in COSE_Sign1 is not valid CBOR: " << message;
+        return {};
+    }
+    const cppbor::Array* array = item->asArray();
+    if (array == nullptr) {
+        LOG(ERROR) << "Value for COSE_Sign1 is not an array";
+        return {};
+    }
+    if (array->size() != 4) {
+        LOG(ERROR) << "Value for COSE_Sign1 is not an array of size 4";
+        return {};
+    }
+
+    const cppbor::Bstr* protectedHeadersBytes = (*array)[0]->asBstr();
+    if (protectedHeadersBytes == nullptr) {
+        LOG(ERROR) << "Value for protectedHeaders is not a bstr";
+        return {};
+    }
+    auto [item2, _2, message2] = cppbor::parse(protectedHeadersBytes->value());
+    if (item2 == nullptr) {
+        LOG(ERROR) << "Error parsing protectedHeaders: " << message2;
+        return {};
+    }
+    const cppbor::Map* protectedHeaders = item2->asMap();
+    if (protectedHeaders == nullptr) {
+        LOG(ERROR) << "Decoded CBOR for protectedHeaders is not a map";
+        return {};
+    }
+
+    for (size_t n = 0; n < protectedHeaders->size(); n++) {
+        auto [keyItem, valueItem] = (*protectedHeaders)[n];
+        const cppbor::Int* number = keyItem->asInt();
+        if (number == nullptr) {
+            LOG(ERROR) << "Key item in top-level map is not a number";
+            return {};
+        }
+        int label = number->value();
+        if (label == COSE_LABEL_ALG) {
+            const cppbor::Int* number = valueItem->asInt();
+            if (number != nullptr) {
+                return number->value();
+            }
+            LOG(ERROR) << "Value for COSE_LABEL_ALG label is not a number";
+            return {};
+        }
+    }
+    LOG(ERROR) << "Did not find COSE_LABEL_ALG label in protected headers";
+    return {};
+}
+
 optional<vector<uint8_t>> coseSignGetX5Chain(const vector<uint8_t>& signatureCoseSign1) {
     auto [item, _, message] = cppbor::parse(signatureCoseSign1);
     if (item == nullptr) {
@@ -1825,6 +2198,28 @@
     return array.encode();
 }
 
+optional<vector<uint8_t>> coseMacWithDigest(const vector<uint8_t>& digestToBeMaced,
+                                            const vector<uint8_t>& data) {
+    cppbor::Map unprotectedHeaders;
+    cppbor::Map protectedHeaders;
+
+    protectedHeaders.add(COSE_LABEL_ALG, COSE_ALG_HMAC_256_256);
+
+    vector<uint8_t> encodedProtectedHeaders = coseEncodeHeaders(protectedHeaders);
+
+    cppbor::Array array;
+    array.add(encodedProtectedHeaders);
+    array.add(std::move(unprotectedHeaders));
+    if (data.size() == 0) {
+        cppbor::Null nullValue;
+        array.add(std::move(nullValue));
+    } else {
+        array.add(data);
+    }
+    array.add(digestToBeMaced);
+    return array.encode();
+}
+
 // ---------------------------------------------------------------------------
 // Utility functions specific to IdentityCredential.
 // ---------------------------------------------------------------------------
diff --git a/input/classifier/1.0/Android.bp b/input/classifier/1.0/Android.bp
index 11e0f52..b6e54ca 100644
--- a/input/classifier/1.0/Android.bp
+++ b/input/classifier/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.input.classifier@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "IInputClassifier.hal",
     ],
diff --git a/input/classifier/1.0/vts/functional/Android.bp b/input/classifier/1.0/vts/functional/Android.bp
index 4d6c9c3..fc1f585 100644
--- a/input/classifier/1.0/vts/functional/Android.bp
+++ b/input/classifier/1.0/vts/functional/Android.bp
@@ -18,9 +18,11 @@
     name: "VtsHalInputClassifierV1_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["VtsHalInputClassifierV1_0TargetTest.cpp"],
+    header_libs: ["jni_headers"],
     static_libs: [
         "android.hardware.input.classifier@1.0",
         "android.hardware.input.common@1.0",
+        "libui-types",
     ],
     test_suites: [
         "general-tests",
diff --git a/input/common/1.0/Android.bp b/input/common/1.0/Android.bp
index 2c7c517..07ced7a 100644
--- a/input/common/1.0/Android.bp
+++ b/input/common/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.input.common@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
     ],
diff --git a/ir/1.0/Android.bp b/ir/1.0/Android.bp
index 5fca96d..6a521f7 100644
--- a/ir/1.0/Android.bp
+++ b/ir/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.ir@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IConsumerIr.hal",
diff --git a/keymaster/3.0/Android.bp b/keymaster/3.0/Android.bp
index 0fdc32c..d0c7a7c 100644
--- a/keymaster/3.0/Android.bp
+++ b/keymaster/3.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.keymaster@3.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IKeymasterDevice.hal",
diff --git a/keymaster/4.0/Android.bp b/keymaster/4.0/Android.bp
index ea328f4..5774718 100644
--- a/keymaster/4.0/Android.bp
+++ b/keymaster/4.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.keymaster@4.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IKeymasterDevice.hal",
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
index bc7f311..8d6e74a 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
@@ -112,6 +112,11 @@
 DECLARE_TYPED_TAG(ASSOCIATED_DATA);
 DECLARE_TYPED_TAG(ATTESTATION_APPLICATION_ID);
 DECLARE_TYPED_TAG(ATTESTATION_CHALLENGE);
+DECLARE_TYPED_TAG(ATTESTATION_ID_BRAND);
+DECLARE_TYPED_TAG(ATTESTATION_ID_DEVICE);
+DECLARE_TYPED_TAG(ATTESTATION_ID_PRODUCT);
+DECLARE_TYPED_TAG(ATTESTATION_ID_MANUFACTURER);
+DECLARE_TYPED_TAG(ATTESTATION_ID_MODEL);
 DECLARE_TYPED_TAG(AUTH_TIMEOUT);
 DECLARE_TYPED_TAG(BLOB_USAGE_REQUIREMENTS);
 DECLARE_TYPED_TAG(BLOCK_MODE);
@@ -155,21 +160,22 @@
 template <typename... Elems>
 struct MetaList {};
 
-using all_tags_t =
-    MetaList<TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t,
-             TAG_MIN_MAC_LENGTH_t, TAG_RSA_PUBLIC_EXPONENT_t, TAG_INCLUDE_UNIQUE_ID_t,
-             TAG_ACTIVE_DATETIME_t, TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t,
-             TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_USER_ID_t,
-             TAG_USER_SECURE_ID_t, TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t,
-             TAG_ALLOW_WHILE_ON_BODY_t, TAG_UNLOCKED_DEVICE_REQUIRED_t, TAG_APPLICATION_ID_t,
-             TAG_APPLICATION_DATA_t, TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t,
-             TAG_HARDWARE_TYPE_t, TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t,
-             TAG_BOOTLOADER_ONLY_t, TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t,
-             TAG_ATTESTATION_CHALLENGE_t, TAG_ATTESTATION_APPLICATION_ID_t,
-             TAG_RESET_SINCE_ID_ROTATION_t, TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t,
-             TAG_DIGEST_t, TAG_PADDING_t, TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t,
-             TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t, TAG_BOOT_PATCHLEVEL_t, TAG_VENDOR_PATCHLEVEL_t,
-             TAG_TRUSTED_CONFIRMATION_REQUIRED_t, TAG_TRUSTED_USER_PRESENCE_REQUIRED_t>;
+using all_tags_t = MetaList<
+        TAG_INVALID_t, TAG_KEY_SIZE_t, TAG_MAC_LENGTH_t, TAG_CALLER_NONCE_t, TAG_MIN_MAC_LENGTH_t,
+        TAG_RSA_PUBLIC_EXPONENT_t, TAG_INCLUDE_UNIQUE_ID_t, TAG_ACTIVE_DATETIME_t,
+        TAG_ORIGINATION_EXPIRE_DATETIME_t, TAG_USAGE_EXPIRE_DATETIME_t,
+        TAG_MIN_SECONDS_BETWEEN_OPS_t, TAG_MAX_USES_PER_BOOT_t, TAG_USER_ID_t, TAG_USER_SECURE_ID_t,
+        TAG_NO_AUTH_REQUIRED_t, TAG_AUTH_TIMEOUT_t, TAG_ALLOW_WHILE_ON_BODY_t,
+        TAG_UNLOCKED_DEVICE_REQUIRED_t, TAG_APPLICATION_ID_t, TAG_APPLICATION_DATA_t,
+        TAG_CREATION_DATETIME_t, TAG_ROLLBACK_RESISTANCE_t, TAG_HARDWARE_TYPE_t,
+        TAG_ROOT_OF_TRUST_t, TAG_ASSOCIATED_DATA_t, TAG_NONCE_t, TAG_BOOTLOADER_ONLY_t,
+        TAG_OS_VERSION_t, TAG_OS_PATCHLEVEL_t, TAG_UNIQUE_ID_t, TAG_ATTESTATION_CHALLENGE_t,
+        TAG_ATTESTATION_APPLICATION_ID_t, TAG_ATTESTATION_ID_BRAND_t, TAG_ATTESTATION_ID_DEVICE_t,
+        TAG_ATTESTATION_ID_PRODUCT_t, TAG_ATTESTATION_ID_MANUFACTURER_t, TAG_ATTESTATION_ID_MODEL_t,
+        TAG_RESET_SINCE_ID_ROTATION_t, TAG_PURPOSE_t, TAG_ALGORITHM_t, TAG_BLOCK_MODE_t,
+        TAG_DIGEST_t, TAG_PADDING_t, TAG_BLOB_USAGE_REQUIREMENTS_t, TAG_ORIGIN_t,
+        TAG_USER_AUTH_TYPE_t, TAG_EC_CURVE_t, TAG_BOOT_PATCHLEVEL_t, TAG_VENDOR_PATCHLEVEL_t,
+        TAG_TRUSTED_CONFIRMATION_REQUIRED_t, TAG_TRUSTED_USER_PRESENCE_REQUIRED_t>;
 
 template <typename TypedTagType>
 struct TypedTag2ValueType;
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h
index 61645f8..f585d62 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h
@@ -18,6 +18,8 @@
 #define HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_UTILS_H_
 
 #include <android/hardware/keymaster/4.0/types.h>
+#include <optional>
+#include <vector>
 
 namespace android {
 namespace hardware {
@@ -52,6 +54,15 @@
 HardwareAuthToken hidlVec2AuthToken(const hidl_vec<uint8_t>& buffer);
 hidl_vec<uint8_t> authToken2HidlVec(const HardwareAuthToken& token);
 
+// Serializes and deserializes a verification token. This format is private and
+// not stable between releases and should not be persisted to disk.
+//
+// Currently doesn't support the |parametersVerified| field, will fail if set.
+//
+std::optional<VerificationToken> deserializeVerificationToken(
+        const std::vector<uint8_t>& serializedToken);
+std::optional<std::vector<uint8_t>> serializeVerificationToken(const VerificationToken& token);
+
 uint32_t getOsVersion();
 uint32_t getOsPatchlevel();
 
diff --git a/keymaster/4.0/support/keymaster_utils.cpp b/keymaster/4.0/support/keymaster_utils.cpp
index 850a776..bcfa757 100644
--- a/keymaster/4.0/support/keymaster_utils.cpp
+++ b/keymaster/4.0/support/keymaster_utils.cpp
@@ -16,6 +16,7 @@
 
 #include <regex.h>
 
+#include <android-base/logging.h>
 #include <android-base/properties.h>
 #include <hardware/hw_auth_token.h>
 #include <keymasterV4_0/keymaster_utils.h>
@@ -110,6 +111,80 @@
     return token;
 }
 
+void appendUint64(std::vector<uint8_t>& vec, uint64_t value) {
+    for (size_t n = 0; n < sizeof(uint64_t); n++) {
+        uint8_t byte = (value >> (n * 8)) & 0xff;
+        vec.push_back(byte);
+    }
+}
+
+uint64_t extractUint64(const std::vector<uint8_t>& data, size_t offset) {
+    uint64_t value = 0;
+    for (size_t n = 0; n < sizeof(uint64_t); n++) {
+        uint64_t tmp = data[offset + n];
+        value |= (tmp << (n * 8));
+    }
+    return value;
+}
+
+void appendUint32(std::vector<uint8_t>& vec, uint32_t value) {
+    for (size_t n = 0; n < sizeof(uint32_t); n++) {
+        uint8_t byte = (value >> (n * 8)) & 0xff;
+        vec.push_back(byte);
+    }
+}
+
+uint32_t extractUint32(const std::vector<uint8_t>& data, size_t offset) {
+    uint32_t value = 0;
+    for (size_t n = 0; n < sizeof(uint32_t); n++) {
+        uint32_t tmp = data[offset + n];
+        value |= (tmp << (n * 8));
+    }
+    return value;
+}
+
+std::optional<std::vector<uint8_t>> serializeVerificationToken(const VerificationToken& token) {
+    if (token.parametersVerified.size() > 0) {
+        LOG(ERROR) << "Serializing verification tokens with parametersVerified is not supported";
+        return {};
+    }
+    if (!(token.mac.size() == 0 || token.mac.size() == 32)) {
+        LOG(ERROR) << "Unexpected MAC size " << token.mac.size() << ", expected 0 or 32";
+        return {};
+    }
+    std::vector<uint8_t> serializedToken;
+    appendUint64(serializedToken, token.challenge);
+    appendUint64(serializedToken, token.timestamp);
+    appendUint32(serializedToken, uint32_t(token.securityLevel));
+    appendUint32(serializedToken, token.mac.size());
+    serializedToken.insert(serializedToken.end(), token.mac.begin(), token.mac.end());
+    return serializedToken;
+}
+
+std::optional<VerificationToken> deserializeVerificationToken(
+        const std::vector<uint8_t>& serializedToken) {
+    if (serializedToken.size() < 24) {
+        LOG(ERROR) << "Unexpected serialized VerificationToken size " << serializedToken.size()
+                   << ", expected at least 24 bytes";
+        return {};
+    }
+    VerificationToken token;
+    token.challenge = extractUint64(serializedToken, 0);
+    token.timestamp = extractUint64(serializedToken, 8);
+    token.securityLevel = SecurityLevel(extractUint32(serializedToken, 16));
+    size_t macSize = extractUint32(serializedToken, 20);
+    size_t expectedSerializedSize = 24 + macSize;
+    if (serializedToken.size() != expectedSerializedSize) {
+        LOG(ERROR) << "Unexpected serialized VerificationToken size " << serializedToken.size()
+                   << ", expected " << expectedSerializedSize;
+        return {};
+    }
+    if (macSize > 0) {
+        token.mac = std::vector<uint8_t>(serializedToken.begin() + 24, serializedToken.end());
+    }
+    return token;
+}
+
 namespace {
 
 constexpr char kPlatformVersionProp[] = "ro.build.version.release";
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 6cbe4da..aa2de2a 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -438,10 +438,10 @@
             EXPECT_TRUE(device_locked);
         }
 
-        // Check that the expected result from VBMeta matches the build type. Only a user build
-        // should have AVB reporting the device is locked.
-        EXPECT_NE(property_get("ro.build.type", property_value, ""), 0);
-        if (!strcmp(property_value, "user")) {
+        // Check that the device is locked if not debuggable, e.g., user build
+        // images in CTS. For VTS, debuggable images are used to allow adb root
+        // and the device is unlocked.
+        if (!property_get_bool("ro.debuggable", false)) {
             EXPECT_TRUE(device_locked);
         } else {
             EXPECT_FALSE(device_locked);
diff --git a/keymaster/4.1/Android.bp b/keymaster/4.1/Android.bp
index f6ac6f8..4e7e944 100644
--- a/keymaster/4.1/Android.bp
+++ b/keymaster/4.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.keymaster@4.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IKeymasterDevice.hal",
diff --git a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
index 495de0f..728a523 100644
--- a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -212,9 +212,11 @@
     EXPECT_EQ(ErrorCode::UNIMPLEMENTED,
               convert(AttestKey(
                       AuthorizationSetBuilder()
+                              .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
                               .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
                               .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")),
                       &cert_chain)));
+    CheckedDeleteKey();
 }
 
 TEST_P(DeviceUniqueAttestationTest, Rsa) {
diff --git a/keymaster/aidl/Android.bp b/keymaster/aidl/Android.bp
index 3011da6..5206721 100644
--- a/keymaster/aidl/Android.bp
+++ b/keymaster/aidl/Android.bp
@@ -15,5 +15,17 @@
             },
         },
     },
-    versions: ["1"],
+    versions: [
+        "1",
+        "2",
+    ],
+}
+
+// This is a reminder that the next version of keymaster should be frozen at
+// version "5" to avoid confusion with other versions of this interface.
+cc_library {
+    name: "android.hardware.keymaster-V3-java",
+}
+cc_library {
+    name: "android.hardware.keymaster-V4-java",
 }
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/2/.hash b/keymaster/aidl/aidl_api/android.hardware.keymaster/2/.hash
new file mode 100644
index 0000000..9d5974e
--- /dev/null
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/2/.hash
@@ -0,0 +1 @@
+91ab0be1887410935f564e3938ff12c5f5f8c59d
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/2/android/hardware/keymaster/HardwareAuthToken.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/2/android/hardware/keymaster/HardwareAuthToken.aidl
new file mode 100644
index 0000000..db1df2b
--- /dev/null
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/2/android/hardware/keymaster/HardwareAuthToken.aidl
@@ -0,0 +1,27 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.keymaster;
+@VintfStability
+parcelable HardwareAuthToken {
+  long challenge;
+  long userId;
+  long authenticatorId;
+  android.hardware.keymaster.HardwareAuthenticatorType authenticatorType;
+  android.hardware.keymaster.Timestamp timestamp;
+  byte[] mac;
+}
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/2/android/hardware/keymaster/HardwareAuthenticatorType.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/2/android/hardware/keymaster/HardwareAuthenticatorType.aidl
new file mode 100644
index 0000000..924567f
--- /dev/null
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/2/android/hardware/keymaster/HardwareAuthenticatorType.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.keymaster;
+@Backing(type="int") @VintfStability
+enum HardwareAuthenticatorType {
+  NONE = 0,
+  PASSWORD = 1,
+  FINGERPRINT = 2,
+  ANY = -1,
+}
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/2/android/hardware/keymaster/SecurityLevel.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/2/android/hardware/keymaster/SecurityLevel.aidl
new file mode 100644
index 0000000..127c1bf
--- /dev/null
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/2/android/hardware/keymaster/SecurityLevel.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.keymaster;
+@Backing(type="int") @VintfStability
+enum SecurityLevel {
+  SOFTWARE = 0,
+  TRUSTED_ENVIRONMENT = 1,
+  STRONGBOX = 2,
+}
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/2/android/hardware/keymaster/Timestamp.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/2/android/hardware/keymaster/Timestamp.aidl
new file mode 100644
index 0000000..45fa1ae
--- /dev/null
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/2/android/hardware/keymaster/Timestamp.aidl
@@ -0,0 +1,22 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.keymaster;
+@VintfStability
+parcelable Timestamp {
+  long milliSeconds;
+}
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/2/android/hardware/keymaster/VerificationToken.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/2/android/hardware/keymaster/VerificationToken.aidl
new file mode 100644
index 0000000..0633765
--- /dev/null
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/2/android/hardware/keymaster/VerificationToken.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.keymaster;
+@VintfStability
+parcelable VerificationToken {
+  long challenge;
+  android.hardware.keymaster.Timestamp timestamp;
+  android.hardware.keymaster.SecurityLevel securityLevel;
+  byte[] mac;
+}
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/SecurityLevel.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/SecurityLevel.aidl
new file mode 100644
index 0000000..127c1bf
--- /dev/null
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/SecurityLevel.aidl
@@ -0,0 +1,24 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.keymaster;
+@Backing(type="int") @VintfStability
+enum SecurityLevel {
+  SOFTWARE = 0,
+  TRUSTED_ENVIRONMENT = 1,
+  STRONGBOX = 2,
+}
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/VerificationToken.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/VerificationToken.aidl
new file mode 100644
index 0000000..0633765
--- /dev/null
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/VerificationToken.aidl
@@ -0,0 +1,25 @@
+///////////////////////////////////////////////////////////////////////////////
+// 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.
+//
+// You must not make a backward incompatible changes to the AIDL files built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.keymaster;
+@VintfStability
+parcelable VerificationToken {
+  long challenge;
+  android.hardware.keymaster.Timestamp timestamp;
+  android.hardware.keymaster.SecurityLevel securityLevel;
+  byte[] mac;
+}
diff --git a/keymaster/aidl/android/hardware/keymaster/SecurityLevel.aidl b/keymaster/aidl/android/hardware/keymaster/SecurityLevel.aidl
new file mode 100644
index 0000000..f129783
--- /dev/null
+++ b/keymaster/aidl/android/hardware/keymaster/SecurityLevel.aidl
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymaster;
+
+/**
+ * Device security levels.
+ */
+@VintfStability
+@Backing(type="int")
+enum SecurityLevel {
+    SOFTWARE = 0,
+    TRUSTED_ENVIRONMENT = 1,
+    /**
+     * STRONGBOX specifies that the secure hardware satisfies the requirements specified in CDD
+     * 9.11.2.
+     */
+    STRONGBOX = 2,
+}
diff --git a/keymaster/aidl/android/hardware/keymaster/VerificationToken.aidl b/keymaster/aidl/android/hardware/keymaster/VerificationToken.aidl
new file mode 100644
index 0000000..eff9ca6
--- /dev/null
+++ b/keymaster/aidl/android/hardware/keymaster/VerificationToken.aidl
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.keymaster;
+
+import android.hardware.keymaster.SecurityLevel;
+import android.hardware.keymaster.Timestamp;
+import android.hardware.keymaster.HardwareAuthenticatorType;
+
+/**
+ * VerificationToken instances are used for secure environments to authenticate one another.
+ *
+ * This version of the parcelable currently don't use the parametersVerified field since it's not
+ * needed for time-based verification. This can be added in a later version, if needed.
+ */
+@VintfStability
+parcelable VerificationToken {
+    /**
+     * The operation handle, used to ensure freshness.
+     */
+    long challenge;
+
+    /**
+     * The current time of the secure environment that generates the VerificationToken.  This can be
+     * checked against auth tokens generated by the same secure environment, which avoids needing to
+     * synchronize clocks.
+     */
+    Timestamp timestamp;
+
+    /**
+     * SecurityLevel of the secure environment that generated the token.
+     */
+    SecurityLevel securityLevel;
+
+    /**
+     * 32-byte HMAC-SHA256 of the above values, computed as:
+     *
+     *    HMAC(H,
+     *         "Auth Verification" || challenge || timestamp || securityLevel || parametersVerified)
+     *
+     * where:
+     *
+     *   ``HMAC'' is the shared HMAC key (see computeSharedHmac() in IKeymaster).
+     *
+     *   ``||'' represents concatenation
+     *
+     * The representation of challenge and timestamp is as 64-bit unsigned integers in big-endian
+     * order.  securityLevel is represented as a 32-bit unsigned integer in big-endian order.
+     *
+     * If parametersVerified is non-empty, the representation of parametersVerified is an ASN.1 DER
+     * encoded representation of the values.  The ASN.1 schema used is the AuthorizationList schema
+     * from the Keystore attestation documentation.  If parametersVerified is empty, it is simply
+     * omitted from the HMAC computation.
+     */
+    byte[] mac;
+}
diff --git a/light/2.0/Android.bp b/light/2.0/Android.bp
index d51f10d..ae6d37c 100644
--- a/light/2.0/Android.bp
+++ b/light/2.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.light@2.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ILight.hal",
diff --git a/media/bufferpool/1.0/Android.bp b/media/bufferpool/1.0/Android.bp
index 079e47f..5dbbadd 100644
--- a/media/bufferpool/1.0/Android.bp
+++ b/media/bufferpool/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.media.bufferpool@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IAccessor.hal",
diff --git a/media/c2/1.0/Android.bp b/media/c2/1.0/Android.bp
index 391e6c4..089ce98 100644
--- a/media/c2/1.0/Android.bp
+++ b/media/c2/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.media.c2@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IComponent.hal",
diff --git a/media/c2/1.1/Android.bp b/media/c2/1.1/Android.bp
index c3e30b2..a3d31df 100644
--- a/media/c2/1.1/Android.bp
+++ b/media/c2/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.media.c2@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "IComponent.hal",
         "IComponentStore.hal",
diff --git a/media/omx/1.0/vts/functional/common/Android.bp b/media/omx/1.0/vts/functional/common/Android.bp
index 2c024a0..3845b9f 100644
--- a/media/omx/1.0/vts/functional/common/Android.bp
+++ b/media/omx/1.0/vts/functional/common/Android.bp
@@ -68,11 +68,12 @@
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
         "libhidlmemory",
-        "libnativehelper",
     ],
 
     // TODO(b/64437680): Assume these libs are always available on the device.
     shared_libs: [
+        "libnativehelper",
         "libstagefright_foundation",
+        "libstagefright_omx_utils",
     ],
 }
diff --git a/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp b/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
index 9b4722e..68ee900 100644
--- a/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
+++ b/media/omx/1.0/vts/functional/master/VtsHalMediaOmxV1_0TargetMasterTest.cpp
@@ -33,6 +33,7 @@
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
+#include <media/stagefright/omx/OMXUtils.h>
 
 using ::android::sp;
 using ::android::base::Join;
@@ -87,71 +88,6 @@
     }
 }
 
-/*
- * Returns the role based on is_encoder and mime.
- *
- * The mapping from a pair (is_encoder, mime) to a role string is
- * defined in frameworks/av/media/libmedia/MediaDefs.cpp and
- * frameworks/av/media/libstagefright/omx/OMXUtils.cpp. This function
- * does essentially the same work as GetComponentRole() in
- * OMXUtils.cpp.
- *
- * Args:
- *   is_encoder: A boolean indicating whether the role is for an
- *       encoder or a decoder.
- *   mime: A string of the desired mime type.
- *
- * Returns:
- *   A const string for the requested role name, empty if mime is not
- *   recognized.
- */
-const std::string getComponentRole(bool isEncoder, const std::string mime) {
-    // Mapping from mime types to roles.
-    // These values come from MediaDefs.cpp and OMXUtils.cpp
-    const std::map<const std::string, const std::string> audioMimeToRole = {
-            {"3gpp", "amrnb"},         {"ac3", "ac3"},     {"amr-wb", "amrwb"},
-            {"eac3", "eac3"},          {"flac", "flac"},   {"g711-alaw", "g711alaw"},
-            {"g711-mlaw", "g711mlaw"}, {"gsm", "gsm"},     {"mp4a-latm", "aac"},
-            {"mpeg", "mp3"},           {"mpeg-L1", "mp1"}, {"mpeg-L2", "mp2"},
-            {"opus", "opus"},          {"raw", "raw"},     {"vorbis", "vorbis"},
-    };
-    const std::map<const std::string, const std::string> videoMimeToRole = {
-            {"3gpp", "h263"},         {"avc", "avc"},           {"dolby-vision", "dolby-vision"},
-            {"hevc", "hevc"},         {"mp4v-es", "mpeg4"},     {"mpeg2", "mpeg2"},
-            {"x-vnd.on2.vp8", "vp8"}, {"x-vnd.on2.vp9", "vp9"},
-    };
-    const std::map<const std::string, const std::string> imageMimeToRole = {
-            {"vnd.android.heic", "heic"},
-    };
-
-    // Suffix begins after the mime prefix.
-    const size_t prefixEnd = mime.find("/");
-    if (prefixEnd == std::string::npos || prefixEnd == mime.size()) return "";
-    const std::string mime_suffix = mime.substr(prefixEnd + 1, mime.size() - 1);
-    const std::string middle = isEncoder ? "encoder." : "decoder.";
-    std::string prefix;
-    std::string suffix;
-    if (mime.rfind("audio/", 0) != std::string::npos) {
-        const auto it = audioMimeToRole.find(mime_suffix);
-        if (it == audioMimeToRole.end()) return "";
-        prefix = "audio_";
-        suffix = it->second;
-    } else if (mime.rfind("video/", 0) != std::string::npos) {
-        const auto it = videoMimeToRole.find(mime_suffix);
-        if (it == videoMimeToRole.end()) return "";
-        prefix = "video_";
-        suffix = it->second;
-    } else if (mime.rfind("image/", 0) != std::string::npos) {
-        const auto it = imageMimeToRole.find(mime_suffix);
-        if (it == imageMimeToRole.end()) return "";
-        prefix = "image_";
-        suffix = it->second;
-    } else {
-        return "";
-    }
-    return prefix + middle + suffix;
-}
-
 void validateAttributes(
         const std::map<const std::string, const testing::internal::RE>& knownPatterns,
         const std::vector<const struct AttributePattern>& unknownPatterns,
@@ -315,7 +251,7 @@
     };
 
     // Matching rules for node names and owners
-    const testing::internal::RE nodeNamePattern = "[a-zA-Z0-9.-]+";
+    const testing::internal::RE nodeNamePattern = "[a-zA-Z0-9._-]+";
     const testing::internal::RE nodeOwnerPattern = "[a-zA-Z0-9._-]+";
 
     std::set<const std::string> roleKeys;
@@ -328,7 +264,8 @@
 
         // Make sure role name follows expected format based on type and
         // isEncoder
-        const std::string role_name = getComponentRole(role.isEncoder, role.type);
+        const std::string role_name(
+                ::android::GetComponentRole(role.isEncoder, role.type.c_str()));
         EXPECT_EQ(role_name, role.role) << "Role \"" << role.role << "\" does not match "
                                         << (role.isEncoder ? "an encoder " : "a decoder ")
                                         << "for mime type \"" << role.type << ".";
diff --git a/neuralnetworks/1.0/Android.bp b/neuralnetworks/1.0/Android.bp
index 3e740c4..20de9d5 100644
--- a/neuralnetworks/1.0/Android.bp
+++ b/neuralnetworks/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.neuralnetworks@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IDevice.hal",
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index 87e8519..d802911 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -62,11 +62,12 @@
     defaults: ["neuralnetworks_vts_functional_defaults"],
     srcs: [
         "BasicTests.cpp",
+        "GeneratedTestHarness.cpp",
         "TestAssertions.cpp",
+        "TestMain.cpp",
         "ValidateModel.cpp",
         "ValidateRequest.cpp",
         "VtsHalNeuralnetworks.cpp",
-        "GeneratedTestHarness.cpp",
     ],
     shared_libs: [
         "libfmq",
diff --git a/neuralnetworks/1.0/vts/functional/AndroidTest.xml b/neuralnetworks/1.0/vts/functional/AndroidTest.xml
index 54e6e91..13671f9 100644
--- a/neuralnetworks/1.0/vts/functional/AndroidTest.xml
+++ b/neuralnetworks/1.0/vts/functional/AndroidTest.xml
@@ -26,10 +26,6 @@
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
-        <!-- b/155577050, temporarily disable the failing tests.
-             Must be deleted after corresponding driver issues are fixed.
-        -->
-        <option name="native-test-flag" value="--gtest_filter=-*Validation*:*CycleTest*:*sample_float_fast*:*sample_float_slow*:*sample_minimal*:*sample_quant*" />
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="VtsHalNeuralnetworksV1_0TargetTest" />
     </test>
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/neuralnetworks/1.0/vts/functional/TestMain.cpp
similarity index 73%
rename from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
rename to neuralnetworks/1.0/vts/functional/TestMain.cpp
index 7edec47..6bf4e5f 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/neuralnetworks/1.0/vts/functional/TestMain.cpp
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#include <gtest/gtest.h>
+#include "1.0/LogTestCaseToLogcat.h"
 
 int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
-
-    ::testing::InitGoogleTest(&argc, argv);
+    testing::InitGoogleTest(&argc, argv);
+    testing::UnitTest::GetInstance()->listeners().Append(
+            new android::hardware::neuralnetworks::LogTestCaseToLogcat());
     return RUN_ALL_TESTS();
 }
diff --git a/neuralnetworks/1.0/vts/functional/include/1.0/LogTestCaseToLogcat.h b/neuralnetworks/1.0/vts/functional/include/1.0/LogTestCaseToLogcat.h
new file mode 100644
index 0000000..f1413ef
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/include/1.0/LogTestCaseToLogcat.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_0_LOG_TEST_CASE_TO_LOGCAT_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_0_LOG_TEST_CASE_TO_LOGCAT_H
+
+#include <android-base/logging.h>
+#include <gtest/gtest.h>
+
+namespace android::hardware::neuralnetworks {
+
+class LogTestCaseToLogcat : public ::testing::EmptyTestEventListener {
+  public:
+    void OnTestStart(const ::testing::TestInfo& test_info) override {
+        LOG(INFO) << "[Test Case] " << test_info.test_suite_name() << "." << test_info.name()
+                  << " BEGIN";
+    }
+
+    void OnTestEnd(const ::testing::TestInfo& test_info) override {
+        LOG(INFO) << "[Test Case] " << test_info.test_suite_name() << "." << test_info.name()
+                  << " END";
+    }
+};
+
+}  // namespace android::hardware::neuralnetworks
+
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_0_LOG_TEST_CASE_TO_LOGCAT_H
diff --git a/neuralnetworks/1.1/Android.bp b/neuralnetworks/1.1/Android.bp
index bef21c0..52d866f 100644
--- a/neuralnetworks/1.1/Android.bp
+++ b/neuralnetworks/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.neuralnetworks@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IDevice.hal",
diff --git a/neuralnetworks/1.1/types.hal b/neuralnetworks/1.1/types.hal
index da7ba78..c8cdd59 100644
--- a/neuralnetworks/1.1/types.hal
+++ b/neuralnetworks/1.1/types.hal
@@ -126,6 +126,8 @@
      * * 0: A tensor of the same {@link OperandType} as input0.
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
      *      the scale and zeroPoint must be the same as input0.
+     *      If all dimensions are reduced and keep_dims is false, the output
+     *      shape is [1].
      */
     MEAN = 31,
 
@@ -232,6 +234,8 @@
      *      removed.
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
      *      the scale and zeroPoint must be the same as input0.
+     *      If all input dimensions are equal to 1 and are to be squeezed, the
+     *      output shape is [1].
      */
     SQUEEZE = 34,
 
@@ -278,6 +282,8 @@
      *      where k is the number of bits set in shrink_axis_mask.
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
      *      the scale and zeroPoint must be the same as input0.
+     *      If shrink_axis_mask is true for all input dimensions, the output
+     *      shape is [1].
      */
     STRIDED_SLICE = 35,
 
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index 9afa0af..405548f 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -20,6 +20,7 @@
     srcs: [
         "BasicTests.cpp",
         "TestAssertions.cpp",
+        "TestMain.cpp",
         "ValidateModel.cpp",
         "ValidateRequest.cpp",
         "VtsHalNeuralnetworks.cpp",
diff --git a/neuralnetworks/1.1/vts/functional/AndroidTest.xml b/neuralnetworks/1.1/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..cfde60c
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalNeuralnetworksV1_1TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+    </target_preparer>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push" value="VtsHalNeuralnetworksV1_1TargetTest->/data/local/tmp/VtsHalNeuralnetworksV1_1TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalNeuralnetworksV1_1TargetTest" />
+    </test>
+</configuration>
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/neuralnetworks/1.1/vts/functional/TestMain.cpp
similarity index 73%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to neuralnetworks/1.1/vts/functional/TestMain.cpp
index 7edec47..6bf4e5f 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/neuralnetworks/1.1/vts/functional/TestMain.cpp
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#include <gtest/gtest.h>
+#include "1.0/LogTestCaseToLogcat.h"
 
 int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
-
-    ::testing::InitGoogleTest(&argc, argv);
+    testing::InitGoogleTest(&argc, argv);
+    testing::UnitTest::GetInstance()->listeners().Append(
+            new android::hardware::neuralnetworks::LogTestCaseToLogcat());
     return RUN_ALL_TESTS();
 }
diff --git a/neuralnetworks/1.2/Android.bp b/neuralnetworks/1.2/Android.bp
index 4aa90aa..9e1db1e 100644
--- a/neuralnetworks/1.2/Android.bp
+++ b/neuralnetworks/1.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.neuralnetworks@1.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IBurstCallback.hal",
diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal
index ff20c12..5fb339f 100644
--- a/neuralnetworks/1.2/IDevice.hal
+++ b/neuralnetworks/1.2/IDevice.hal
@@ -40,7 +40,7 @@
      * NNAPI applications filter devices based on their needs:
      *     - An application demands a certain level of performance, but a specific version of
      *       the driver cannot meet that requirement because of a performance regression.
-     *       The application can blacklist the driver based on the version provided.
+     *       The application can disallow the driver based on the version provided.
      *     - An application has a minimum precision requirement, but certain versions of
      *       the driver cannot meet that requirement because of bugs or certain optimizations.
      *       The application can filter out versions of these drivers.
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index 2c3c599..7441a54 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -1955,6 +1955,8 @@
      * * 0: A tensor of the same {@link OperandType} as input0.
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
      *      the scale and zeroPoint must be the same as input0.
+     *      If all dimensions are reduced and keep_dims is false, the output
+     *      shape is [1].
      */
     MEAN = @1.1::OperationType:MEAN,
 
@@ -2078,6 +2080,8 @@
      *      removed.
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
      *      the scale and zeroPoint must be the same as input0.
+     *      If all input dimensions are equal to 1 and are to be squeezed, the
+     *      output shape is [1].
      */
     SQUEEZE = @1.1::OperationType:SQUEEZE,
 
@@ -2125,6 +2129,8 @@
      *      where k is the number of bits set in shrink_axis_mask.
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
      *      the scale and zeroPoint must be the same as input0.
+     *      If shrink_axis_mask is true for all input dimensions, the output
+     *      shape is [1].
      */
     STRIDED_SLICE = @1.1::OperationType:STRIDED_SLICE,
 
@@ -2239,6 +2245,7 @@
      *
      * Outputs:
      * * 0: An (n - 1)-D {@link OperandType::TENSOR_INT32} tensor.
+     *      If input is 1-dimensional, the output shape is [1].
      */
     // There is no underscore in ARG_MAX to avoid name conflict with
     // the macro defined in libc/kernel/uapi/linux/limits.h.
@@ -2263,6 +2270,7 @@
      *
      * Outputs:
      * * 0: An (n - 1)-D {@link OperandType::TENSOR_INT32} tensor.
+     *      If input is 1-dimensional, the output shape is [1].
      */
     ARGMIN = 40,  // See ARGMAX for naming discussion.
 
@@ -3872,6 +3880,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *      If all dimensions are reduced and keep_dims is false, the output
+     *      shape is [1].
      */
     REDUCE_ALL = 75,
 
@@ -3897,6 +3907,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *      If all dimensions are reduced and keep_dims is false, the output
+     *      shape is [1].
      */
     REDUCE_ANY = 76,
 
@@ -3924,6 +3936,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *      If all dimensions are reduced and keep_dims is false, the output
+     *      shape is [1].
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
      *      the scale and zeroPoint must be the same as input0.
      */
@@ -3953,6 +3967,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *      If all dimensions are reduced and keep_dims is false, the output
+     *      shape is [1].
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
      *      the scale and zeroPoint must be the same as input0.
      */
@@ -3980,6 +3996,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *      If all dimensions are reduced and keep_dims is false, the output
+     *      shape is [1].
      */
     REDUCE_PROD = 79,
 
@@ -4005,6 +4023,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *      If all dimensions are reduced and keep_dims is false, the output
+     *      shape is [1].
      */
     REDUCE_SUM = 80,
 
@@ -4833,15 +4853,18 @@
     /**
      * Quantized scale of the operand.
      *
-     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM or
-     * TENSOR_INT32.
+     * Must be 0 when not applicable to an operand type.
+     *
+     * See {@link OperandType}.
      */
     float scale;
 
     /**
      * Quantized zero-point offset of the operand.
      *
-     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
+     * Must be 0 when not applicable to an operand type.
+     *
+     * See {@link OperandType}.
      */
     int32_t zeroPoint;
 
diff --git a/neuralnetworks/1.2/types.t b/neuralnetworks/1.2/types.t
index d197f6b..21d88ac 100644
--- a/neuralnetworks/1.2/types.t
+++ b/neuralnetworks/1.2/types.t
@@ -251,15 +251,18 @@
     /**
      * Quantized scale of the operand.
      *
-     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM or
-     * TENSOR_INT32.
+     * Must be 0 when not applicable to an operand type.
+     *
+     * See {@link OperandType}.
      */
     float scale;
 
     /**
      * Quantized zero-point offset of the operand.
      *
-     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
+     * Must be 0 when not applicable to an operand type.
+     *
+     * See {@link OperandType}.
      */
     int32_t zeroPoint;
 
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 182f716..93edca6 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -40,6 +40,7 @@
         "CompilationCachingTests.cpp",
         "GeneratedTestHarness.cpp",
         "TestAssertions.cpp",
+        "TestMain.cpp",
         "ValidateBurst.cpp",
         "ValidateModel.cpp",
         "ValidateRequest.cpp",
diff --git a/neuralnetworks/1.2/vts/functional/AndroidTest.xml b/neuralnetworks/1.2/vts/functional/AndroidTest.xml
index d9a09ab..3f91618 100644
--- a/neuralnetworks/1.2/vts/functional/AndroidTest.xml
+++ b/neuralnetworks/1.2/vts/functional/AndroidTest.xml
@@ -26,10 +26,6 @@
     </target_preparer>
 
     <test class="com.android.tradefed.testtype.GTest" >
-        <!-- b/155674368, b/153876253, temporarily disable the test.
-             Must be deleted after corresponding driver issues are fixed.
-        -->
-        <option name="native-test-flag" value="--gtest_filter=-*squeeze*_all*_inputs*:*strided_slice*_all*_inputs*:*transpose*_all*_inputs*:*l2_normalization_axis_corner_case*:*sample_float_fast*:*sample_float_slow*:*sample_minimal*:*sample_quant*" />
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="VtsHalNeuralnetworksV1_2TargetTest" />
     </test>
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/neuralnetworks/1.2/vts/functional/TestMain.cpp
similarity index 73%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to neuralnetworks/1.2/vts/functional/TestMain.cpp
index 7edec47..6bf4e5f 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/neuralnetworks/1.2/vts/functional/TestMain.cpp
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#include <gtest/gtest.h>
+#include "1.0/LogTestCaseToLogcat.h"
 
 int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
-
-    ::testing::InitGoogleTest(&argc, argv);
+    testing::InitGoogleTest(&argc, argv);
+    testing::UnitTest::GetInstance()->listeners().Append(
+            new android::hardware::neuralnetworks::LogTestCaseToLogcat());
     return RUN_ALL_TESTS();
 }
diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
index d01336e..c4e2b15 100644
--- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
@@ -21,6 +21,7 @@
 #include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
 #include <android/hardware/neuralnetworks/1.2/types.h>
 #include <gtest/gtest.h>
+#include <vector>
 #include "1.0/Utils.h"
 #include "1.2/Callbacks.h"
 
diff --git a/neuralnetworks/1.3/Android.bp b/neuralnetworks/1.3/Android.bp
index 7b02cc5..3e02c90 100644
--- a/neuralnetworks/1.3/Android.bp
+++ b/neuralnetworks/1.3/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.neuralnetworks@1.3",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IBuffer.hal",
diff --git a/neuralnetworks/1.3/types.hal b/neuralnetworks/1.3/types.hal
index 56930c2..5f5ee03 100644
--- a/neuralnetworks/1.3/types.hal
+++ b/neuralnetworks/1.3/types.hal
@@ -2012,6 +2012,8 @@
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
      *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint must be the same as input0.
+     *      If all dimensions are reduced and keep_dims is false, the output
+     *      shape is [1].
      */
     MEAN = @1.2::OperationType:MEAN,
 
@@ -2141,6 +2143,8 @@
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
      *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint must be the same as input0.
+     *      If all input dimensions are equal to 1 and are to be squeezed, the
+     *      output shape is [1].
      */
     SQUEEZE = @1.2::OperationType:SQUEEZE,
 
@@ -2190,6 +2194,8 @@
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
      *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint must be the same as input0.
+     *      If shrink_axis_mask is true for all input dimensions, the output
+     *      shape is [1].
      */
     STRIDED_SLICE = @1.2::OperationType:STRIDED_SLICE,
 
@@ -2313,6 +2319,7 @@
      *
      * Outputs:
      * * 0: An (n - 1)-D {@link OperandType::TENSOR_INT32} tensor.
+     *      If input is 1-dimensional, the output shape is [1].
      */
     // There is no underscore in ARG_MAX to avoid name conflict with
     // the macro defined in libc/kernel/uapi/linux/limits.h.
@@ -2338,6 +2345,7 @@
      *
      * Outputs:
      * * 0: An (n - 1)-D {@link OperandType::TENSOR_INT32} tensor.
+     *      If input is 1-dimensional, the output shape is [1].
      */
     ARGMIN = @1.2::OperationType:ARGMIN,  // See ARGMAX for naming discussion.
 
@@ -4096,6 +4104,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *      If all dimensions are reduced and keep_dims is false, the output
+     *      shape is [1].
      */
     REDUCE_ALL = @1.2::OperationType:REDUCE_ALL,
 
@@ -4121,6 +4131,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *      If all dimensions are reduced and keep_dims is false, the output
+     *      shape is [1].
      */
     REDUCE_ANY = @1.2::OperationType:REDUCE_ANY,
 
@@ -4149,6 +4161,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *      If all dimensions are reduced and keep_dims is false, the output
+     *      shape is [1].
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
      *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint must be the same as input0.
@@ -4180,6 +4194,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *      If all dimensions are reduced and keep_dims is false, the output
+     *      shape is [1].
      *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} and
      *      {@link OperandType::TENSOR_QUANT8_ASYMM_SIGNED} tensor,
      *      the scale and zeroPoint must be the same as input0.
@@ -4208,6 +4224,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *      If all dimensions are reduced and keep_dims is false, the output
+     *      shape is [1].
      */
     REDUCE_PROD = @1.2::OperationType:REDUCE_PROD,
 
@@ -4233,6 +4251,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *      If all dimensions are reduced and keep_dims is false, the output
+     *      shape is [1].
      */
     REDUCE_SUM = @1.2::OperationType:REDUCE_SUM,
 
@@ -5082,11 +5102,15 @@
      * The inputs and outputs of the two referenced subgraphs must agree with the
      * signature of this operation. That is, if the operation has (3 + n) inputs
      * and m outputs, both subgraphs must have n inputs and m outputs with the same
-     * types as the corresponding operation inputs and outputs.
+     * types, ranks, dimensions, scales,
+     * zeroPoints, and extraParams as the corresponding operation
+     * inputs and outputs.
+     * All of the operands mentioned must have fully specified dimensions.
      *
      * Inputs:
      * * 0: A value of type {@link OperandType::TENSOR_BOOL8} and shape [1]
      *      that determines which of the two referenced subgraphs to execute.
+     *      The operand must have fully specified dimensions.
      * * 1: A {@link OperandType::SUBGRAPH} reference to the subgraph to be
      *      executed if the condition is true.
      * * 2: A {@link OperandType::SUBGRAPH} reference to the subgraph to be
@@ -5145,13 +5169,17 @@
      * Inputs:
      * * 0: A {@link OperandType::SUBGRAPH} reference to the condition
      *      subgraph. The subgraph must have (m + k + n) inputs with
-     *      the same types as the corresponding inputs of the WHILE operation
-     *      and exactly one output of {@link OperandType::TENSOR_BOOL8}
-     *      and shape [1].
+     *      the same types, ranks, dimensions,
+     *      scales, zeroPoints, and extraParams as the
+     *      corresponding inputs of the WHILE operation and exactly one output
+     *      of {@link OperandType::TENSOR_BOOL8} and shape [1].
+     *      All of the operands mentioned must have fully specified dimensions.
      * * 1: A {@link OperandType::SUBGRAPH} reference to the body subgraph.
      *      The subgraph must have (m + k + n) inputs and (m + k) outputs with
-     *      the same types as the corresponding inputs and outputs of the WHILE
-     *      operation.
+     *      the same types, ranks, dimensions,
+     *      scales, zeroPoints, and extraParams as the
+     *      corresponding inputs and outputs of the WHILE operation.
+     *      All of the operands mentioned must have fully specified dimensions.
      * * (m inputs): Initial values for input-output operands.
      * * (k inputs): Initial values for state-only operands.
      * * (n inputs): Values for input-only operands.
@@ -5471,7 +5499,9 @@
      * If a tensor operand's dimensions are not fully specified, the
      * dimensions of the operand are deduced from the operand
      * dimensions and values of the operation for which that operand
-     * is an output.
+     * is an output or from the corresponding {@link OperationType::IF} or
+     * {@link OperationType::WHILE} operation input operand dimensions in the
+     * case of referenced subgraph input operands.
      *
      * In the following situations, a tensor operand's dimensions must
      * be fully specified:
@@ -5479,8 +5509,8 @@
      *     . The operand has lifetime CONSTANT_COPY or
      *       CONSTANT_REFERENCE.
      *
-     *     . The operand has lifetime SUBGRAPH_INPUT. Fully
-     *       specified dimensions must either be present in the
+     *     . The operand has lifetime SUBGRAPH_INPUT and belongs to the main
+     *       subgraph. Fully specified dimensions must either be present in the
      *       Operand or they must be provided in the corresponding
      *       RequestArgument.
      *       EXCEPTION: If the input is optional and omitted
@@ -5508,15 +5538,18 @@
     /**
      * Quantized scale of the operand.
      *
-     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM or
-     * TENSOR_INT32.
+     * Must be 0 when not applicable to an operand type.
+     *
+     * See {@link OperandType}.
      */
     float scale;
 
     /**
      * Quantized zero-point offset of the operand.
      *
-     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
+     * Must be 0 when not applicable to an operand type.
+     *
+     * See {@link OperandType}.
      */
     int32_t zeroPoint;
 
@@ -5710,8 +5743,8 @@
      * Input data and information to be used in the execution of a prepared
      * model.
      *
-     * The index of the input corresponds to the index in Model.inputIndexes.
-     *   E.g., input[i] corresponds to Model.inputIndexes[i].
+     * The index of the input corresponds to the index in Model.main.inputIndexes.
+     *   E.g., input[i] corresponds to Model.main.inputIndexes[i].
      */
     vec<RequestArgument> inputs;
 
@@ -5719,8 +5752,8 @@
      * Output data and information to be used in the execution of a prepared
      * model.
      *
-     * The index of the output corresponds to the index in Model.outputIndexes.
-     *   E.g., output[i] corresponds to Model.outputIndexes[i].
+     * The index of the output corresponds to the index in Model.main.outputIndexes.
+     *   E.g., output[i] corresponds to Model.main.outputIndexes[i].
      */
     vec<RequestArgument> outputs;
 
diff --git a/neuralnetworks/1.3/types.t b/neuralnetworks/1.3/types.t
index 0a6e45e..2901d18 100644
--- a/neuralnetworks/1.3/types.t
+++ b/neuralnetworks/1.3/types.t
@@ -264,7 +264,9 @@
      * If a tensor operand's dimensions are not fully specified, the
      * dimensions of the operand are deduced from the operand
      * dimensions and values of the operation for which that operand
-     * is an output.
+     * is an output or from the corresponding {@link OperationType::IF} or
+     * {@link OperationType::WHILE} operation input operand dimensions in the
+     * case of referenced subgraph input operands.
      *
      * In the following situations, a tensor operand's dimensions must
      * be fully specified:
@@ -272,8 +274,8 @@
      *     . The operand has lifetime CONSTANT_COPY or
      *       CONSTANT_REFERENCE.
      *
-     *     . The operand has lifetime SUBGRAPH_INPUT. Fully
-     *       specified dimensions must either be present in the
+     *     . The operand has lifetime SUBGRAPH_INPUT and belongs to the main
+     *       subgraph. Fully specified dimensions must either be present in the
      *       Operand or they must be provided in the corresponding
      *       RequestArgument.
      *       EXCEPTION: If the input is optional and omitted
@@ -301,15 +303,18 @@
     /**
      * Quantized scale of the operand.
      *
-     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM or
-     * TENSOR_INT32.
+     * Must be 0 when not applicable to an operand type.
+     *
+     * See {@link OperandType}.
      */
     float scale;
 
     /**
      * Quantized zero-point offset of the operand.
      *
-     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
+     * Must be 0 when not applicable to an operand type.
+     *
+     * See {@link OperandType}.
      */
     int32_t zeroPoint;
 
@@ -503,8 +508,8 @@
      * Input data and information to be used in the execution of a prepared
      * model.
      *
-     * The index of the input corresponds to the index in Model.inputIndexes.
-     *   E.g., input[i] corresponds to Model.inputIndexes[i].
+     * The index of the input corresponds to the index in Model.main.inputIndexes.
+     *   E.g., input[i] corresponds to Model.main.inputIndexes[i].
      */
     vec<RequestArgument> inputs;
 
@@ -512,8 +517,8 @@
      * Output data and information to be used in the execution of a prepared
      * model.
      *
-     * The index of the output corresponds to the index in Model.outputIndexes.
-     *   E.g., output[i] corresponds to Model.outputIndexes[i].
+     * The index of the output corresponds to the index in Model.main.outputIndexes.
+     *   E.g., output[i] corresponds to Model.main.outputIndexes[i].
      */
     vec<RequestArgument> outputs;
 
diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp
index 771fc54..b17d445 100644
--- a/neuralnetworks/1.3/vts/functional/Android.bp
+++ b/neuralnetworks/1.3/vts/functional/Android.bp
@@ -43,6 +43,7 @@
         "MemoryDomainTests.cpp",
         "QualityOfServiceTests.cpp",
         "TestAssertions.cpp",
+        "TestMain.cpp",
         "ValidateBurst.cpp",
         "ValidateModel.cpp",
         "ValidateRequest.cpp",
diff --git a/neuralnetworks/1.3/vts/functional/AndroidTest.xml b/neuralnetworks/1.3/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..e5acd90
--- /dev/null
+++ b/neuralnetworks/1.3/vts/functional/AndroidTest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalNeuralnetworksV1_3TargetTest.">
+    <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="VtsHalNeuralnetworksV1_3TargetTest->/data/local/tmp/VtsHalNeuralnetworksV1_3TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalNeuralnetworksV1_3TargetTest" />
+    </test>
+</configuration>
diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
index 4dbac16..914a01a 100644
--- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
@@ -568,8 +568,10 @@
     }
 
     Request request = std::move(maybeRequest.value());
+
+    constexpr uint32_t kInsufficientOutputIndex = 0;
     if (testConfig.outputType == OutputType::INSUFFICIENT) {
-        makeOutputInsufficientSize(/*outputIndex=*/0, &request);
+        makeOutputInsufficientSize(kInsufficientOutputIndex, &request);
     }
 
     OptionalTimeoutDuration loopTimeoutDuration;
@@ -745,7 +747,21 @@
             }
             ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
             ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
-            ASSERT_FALSE(outputShapes[0].isSufficient);
+            // Check that all returned output dimensions are at least as fully specified as the
+            // union of the information about the corresponding operand in the model and in the
+            // request. In this test, all model outputs have known rank with all dimensions
+            // unspecified, and no dimensional information is provided in the request.
+            for (uint32_t i = 0; i < outputShapes.size(); i++) {
+                ASSERT_EQ(outputShapes[i].isSufficient, i != kInsufficientOutputIndex);
+                const auto& actual = outputShapes[i].dimensions;
+                const auto& golden =
+                        testModel.main.operands[testModel.main.outputIndexes[i]].dimensions;
+                ASSERT_EQ(actual.size(), golden.size());
+                for (uint32_t j = 0; j < actual.size(); j++) {
+                    if (actual[j] == 0) continue;
+                    EXPECT_EQ(actual[j], golden[j]) << "index: " << j;
+                }
+            }
             return;
         case OutputType::MISSED_DEADLINE:
             ASSERT_TRUE(executionStatus == ErrorStatus::MISSED_DEADLINE_TRANSIENT ||
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/neuralnetworks/1.3/vts/functional/TestMain.cpp
similarity index 73%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to neuralnetworks/1.3/vts/functional/TestMain.cpp
index 7edec47..6bf4e5f 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/neuralnetworks/1.3/vts/functional/TestMain.cpp
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#include <gtest/gtest.h>
+#include "1.0/LogTestCaseToLogcat.h"
 
 int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
-
-    ::testing::InitGoogleTest(&argc, argv);
+    testing::InitGoogleTest(&argc, argv);
+    testing::UnitTest::GetInstance()->listeners().Append(
+            new android::hardware::neuralnetworks::LogTestCaseToLogcat());
     return RUN_ALL_TESTS();
 }
diff --git a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h
index de082c3..a2e5071 100644
--- a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.h
@@ -21,6 +21,7 @@
 #include <android/hardware/neuralnetworks/1.3/IPreparedModel.h>
 #include <android/hardware/neuralnetworks/1.3/types.h>
 #include <gtest/gtest.h>
+#include <vector>
 #include "1.0/Utils.h"
 #include "1.3/Callbacks.h"
 
diff --git a/nfc/1.0/Android.bp b/nfc/1.0/Android.bp
index bd64907..667922a 100644
--- a/nfc/1.0/Android.bp
+++ b/nfc/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.nfc@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "INfc.hal",
diff --git a/nfc/1.1/Android.bp b/nfc/1.1/Android.bp
index 1f8789f..a8976b0 100644
--- a/nfc/1.1/Android.bp
+++ b/nfc/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.nfc@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "INfc.hal",
diff --git a/nfc/1.2/Android.bp b/nfc/1.2/Android.bp
index aa68d2f..514d531 100644
--- a/nfc/1.2/Android.bp
+++ b/nfc/1.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.nfc@1.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "INfc.hal",
diff --git a/oemlock/1.0/Android.bp b/oemlock/1.0/Android.bp
index e784be0..8ab2911 100644
--- a/oemlock/1.0/Android.bp
+++ b/oemlock/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.oemlock@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IOemLock.hal",
diff --git a/power/1.0/Android.bp b/power/1.0/Android.bp
index 6ba1d78..7381c70 100644
--- a/power/1.0/Android.bp
+++ b/power/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.power@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IPower.hal",
diff --git a/power/1.1/Android.bp b/power/1.1/Android.bp
index 6b133cc..e026e70 100644
--- a/power/1.1/Android.bp
+++ b/power/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.power@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IPower.hal",
diff --git a/power/1.2/Android.bp b/power/1.2/Android.bp
index 296965b..ccf66dc 100644
--- a/power/1.2/Android.bp
+++ b/power/1.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.power@1.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IPower.hal",
diff --git a/power/1.3/Android.bp b/power/1.3/Android.bp
index 00ca750..15955e5 100644
--- a/power/1.3/Android.bp
+++ b/power/1.3/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.power@1.3",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IPower.hal",
diff --git a/power/stats/1.0/Android.bp b/power/stats/1.0/Android.bp
index c592006..2a71490 100644
--- a/power/stats/1.0/Android.bp
+++ b/power/stats/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.power.stats@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IPowerStats.hal",
diff --git a/prebuilt_hashes/26.txt b/prebuilt_hashes/26.txt
deleted file mode 100644
index f2feb4c..0000000
--- a/prebuilt_hashes/26.txt
+++ /dev/null
@@ -1,186 +0,0 @@
-# Do not change this file except to add new interfaces. Changing
-# pre-existing interfaces will fail VTS and break framework-only OTAs
-
-# HALs released in Android O
-
-f219c3b5b8c6cb1d659d4c7328f67246abfe1a8613f469826fd3b9ad090417a2 android.hardware.audio@2.0::IDevice
-4d579cae1cd87a783fd49233e10ce720ba183cfd1d5ccd80149e69de5c1c7362 android.hardware.audio@2.0::IDevicesFactory
-203e23f18011390b8cd10c303e0c16c4eebc8fa187e80e40d6be4624c2b0848a android.hardware.audio@2.0::IPrimaryDevice
-aaf93123deec336eb247ad8099849469a541ca0cf7c28c5f5336cebe1ee86748 android.hardware.audio@2.0::IStream
-0468c5723b0d44c5b451bdfa06153000c6f352fd3336e0ad2697127b04b766df android.hardware.audio@2.0::IStreamIn
-7296f7064fd3ab24082b43a1da34cc876268065310b785499fba5178d063680a android.hardware.audio@2.0::IStreamOut
-19d241d71c3e1140afba8140dcb57448446025a5fc03739788c4c25e9a98b6c2 android.hardware.audio@2.0::IStreamOutCallback
-c84da9f586087227daa3b96d42b4575326bccfd5bc8a2a5acf86d774f8ea2648 android.hardware.audio@2.0::types
-1305786c06e22b9b24ebde136054cc827b63c86d8bf4a136d6f7f54752b8566b android.hardware.audio.common@2.0::types
-fa8fbae3d1da3c264e4f3110728076abc09b4e65f12af6ae136367328de988ab android.hardware.audio.effect@2.0::IAcousticEchoCancelerEffect
-ca4752545d54547ff069eae161af7550cb5f5a7e8b60316ddd132a30906a68e7 android.hardware.audio.effect@2.0::IAutomaticGainControlEffect
-d2b8af988dc66f514d886bcee44b440d8034bc2a762f7161717ef3c956073067 android.hardware.audio.effect@2.0::IBassBoostEffect
-611bc09c75e796f3512b1ca6be508b0a9ba996759b8a2c60507784ff58076229 android.hardware.audio.effect@2.0::IDownmixEffect
-36a57369dfdc75180e8b64ae80b1970db8f6d9085dbff6ca931715038cc056e1 android.hardware.audio.effect@2.0::IEffect
-d2aa2df6d189c580f5be8460fa0ff4134d9c05a383f3204659baee426a6f0edf android.hardware.audio.effect@2.0::IEffectBufferProviderCallback
-217f9161983a48d3bf3faeb158f868aa8bf0ce25889e4ee3d2bab1a2e8d33e77 android.hardware.audio.effect@2.0::IEffectsFactory
-c2b38bc07991e880c83ca8cb88181411eeef708b8b936aedd2f2e0acade7df69 android.hardware.audio.effect@2.0::IEnvironmentalReverbEffect
-2ff9f9704be5f167745b4de790e9dafc3cc4719e2f6e2e5497085e679853cfe7 android.hardware.audio.effect@2.0::IEqualizerEffect
-c31447fb02dbc8b56c359941dad22f416511860173c5c5fd278d1bf2312b13de android.hardware.audio.effect@2.0::ILoudnessEnhancerEffect
-804831ca258802eb3eb65a0a7b5d5e3d37d4a15ba8c2836b4276eda98b47e1d0 android.hardware.audio.effect@2.0::INoiseSuppressionEffect
-778fd5b9837f481d8e47425b3e2a3bd0c6362a0b6870291518e2d863530fdb61 android.hardware.audio.effect@2.0::IPresetReverbEffect
-c93cb25a1a92d07aa80a617c01e8d22fc97bf8cefd3962b6a5be386ad4704d89 android.hardware.audio.effect@2.0::IVirtualizerEffect
-918f331780c9c7b04f2151a2e563aab088198ede8e6f865302ebaa13905bd9ce android.hardware.audio.effect@2.0::IVisualizerEffect
-4caad099f8fc00262b6c03ba41271808b37cea90ac98b534299bbf4ee823af02 android.hardware.audio.effect@2.0::types
-# android.hardware.automotive.* are unfrozen
-1fbdc1f852f8bd2e4a6c5cb30ac2b78668c98dce118a61762d4034ae859f43d8 android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprint
-aabb5c3c585592d71ee57b77298c14993d77914ddeaa64b2c5109a602b02ea47 android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprintClientCallback
-1ec60d4efddae9a7b2469278a576967b4751e88de5b8d7e9df6eff6bc0da7bc9 android.hardware.biometrics.fingerprint@2.1::types
-347ce746815607567f5f3b53e4800998ca5ab9355141f0880fc0cf0c1fc5c355 android.hardware.bluetooth@1.0::IBluetoothHci
-835f41be2281bfb22f3e33c6fa870bde7bc21e37e5cfbaf9a36fff170632f754 android.hardware.bluetooth@1.0::IBluetoothHciCallbacks
-a8dfd0dbe463a3cdbcf1d985b38a28b3d93ba2ae5a1d1db4aaef4c38a5781b91 android.hardware.bluetooth@1.0::types
-7192d756aeba00aba32f4504981df8172ffca83e210c4838dabf295e53e93590 android.hardware.boot@1.0::IBootControl
-cebaa803b8e33807a0d69f46652b650ccb549e8f9b19d6becbbf26690e828b49 android.hardware.boot@1.0::types
-a98d49f23712a7cc327d1e0602d05f6f3ad32cfb5c74711d009c726611ee1c93 android.hardware.broadcastradio@1.0::IBroadcastRadio
-ed82579c0c165feaa12d0e33c06b3342ab41ec0a439247f202775e8369e46ef6 android.hardware.broadcastradio@1.0::IBroadcastRadioFactory
-da6ab32ee2793d2c86d3b603075d5383852b89d7eaa201861aa0473d418f3c7f android.hardware.broadcastradio@1.0::ITuner
-04d3ca022e25c308d9efd2e7eb77b3a7a206907cdc1b9ea9326340b377868172 android.hardware.broadcastradio@1.0::ITunerCallback
-bd42c8d7838cfed1998b49c39745dec116d2d6edc2c11a4c0399b8f3a1d1655a android.hardware.broadcastradio@1.0::types
-81164323115d6588e259e8319fddf7487adfa1f49ce60f7e80ba74e0783392a4 android.hardware.camera.common@1.0::types
-c1705e9d62438a1d955269965af915ae28e692bd480a3b1ce67056fef992d62f android.hardware.camera.device@1.0::ICameraDevice
-78e9b44cf8660bdc1e98dca07451804153824efcd28db208a62f5ad728f44076 android.hardware.camera.device@1.0::ICameraDeviceCallback
-28f0386ba86ddf41e53a8117b48a0328d7a4d2574213e89f4a1062398a244566 android.hardware.camera.device@1.0::ICameraDevicePreviewCallback
-4db48439ce9dde97f1cfb3d7408f6c737f621ac0f7494aeea35ed599bc2352a3 android.hardware.camera.device@1.0::types
-b32f9aeaf1c442195eb06ffc7600968c919d005b2718874f09c57287fae55918 android.hardware.camera.device@3.2::ICameraDevice
-63bfc3da0f2d2301f7a0508c7c2b9ffc521d4d545ee03718da70e9d6273b3b21 android.hardware.camera.device@3.2::ICameraDeviceCallback
-0fa3e1e64819283b8737fc4e5ab759f0cb4ac1a996e8a51cc4aa8025a457208e android.hardware.camera.device@3.2::ICameraDeviceSession
-030be3d2b159cbde7920485807140f6b6064ef4a5de4a40a6c4bc8d2c72f7cd3 android.hardware.camera.device@3.2::types
-5ba7947cee515d7a2359bfcbfb9678c1c3a768c288471919ac095b96ae6f3d40 android.hardware.camera.metadata@3.2::types
-f7e299d85033ac52d1095a35784fcfeaff43603f58c751e4153c85bbade3b330 android.hardware.camera.provider@2.4::ICameraProvider
-a501ca1aecd09f1b9fd70a9af84205430dbd49a808e8fa395d363b9902e6f58c android.hardware.camera.provider@2.4::ICameraProviderCallback
-7f5fe8f4f8a24037153c504d8b4d3313c2ce33d81c8c69fe5194ddd2d4080e72 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
-87beacc481897cf02fb1628d75e68133de6d74d4cffe582cda2f5e16bdd74516 android.hardware.configstore@1.0::types
-a5ae0fe8667f0b1af09b13e72d29600f4eb3853b257079c45a99b6f4a3360649 android.hardware.contexthub@1.0::IContexthub
-2ab3054c2d9302d8417ee7495353a2887fe338f913276f2eb41e80f11395ec2e android.hardware.contexthub@1.0::IContexthubCallback
-c3b2b37d561d31ea094411f251bf73bea334f4fe849a4390aef5e20bca6cadba android.hardware.contexthub@1.0::types
-df174c1871c864b4c79ca9f64aae7936d24a272eca3191a30458ca2b706dec79 android.hardware.drm@1.0::ICryptoFactory
-83639e90caeb996b0274e420de3cd556779de1ca48464b68eee799bef32b34cd android.hardware.drm@1.0::ICryptoPlugin
-1440cffdfaeb12830ac10ee6ffdb0f1083e701057b806df11fb4787b4c91e718 android.hardware.drm@1.0::IDrmFactory
-78ba33b108f620e6a0eec01ef654547e69a85754578ea4c9ef03ec205f16121c android.hardware.drm@1.0::IDrmPlugin
-701d9e51952172364e4ea70db9c397f08c3b4577ba33051f050a6cdd532de1b4 android.hardware.drm@1.0::IDrmPluginListener
-4238d62ad90df63aa338c6f1b6264c09c5a3706945d5c49d1189c0be1dc9e942 android.hardware.drm@1.0::types
-f07b1ee3ba11a2fc9f200421b2e1afb7c1854ee987000e45c987fb9507795055 android.hardware.dumpstate@1.0::IDumpstateDevice
-c9d318df7922bde3b265927b521ff5a965002826fc0cabfcaef52a56760f2d34 android.hardware.gatekeeper@1.0::IGatekeeper
-da13bd69282fb275767abb18704c57ff8038e6c139ad17157dc702810f70d06a android.hardware.gatekeeper@1.0::types
-37c7da4f823ec958dfa9c960e2d341c48f877e0bfa758f3fa9e2d9c1e1bd66d9 android.hardware.gnss@1.0::IAGnss
-7ec9afdb964bfb8369866913caf018f2636592885bcb558a65de2c5436ab4f60 android.hardware.gnss@1.0::IAGnssCallback
-d16e6a359be6963ea753d7138e84ecf2b93052097938938c4d36d7a47ea2e2ae android.hardware.gnss@1.0::IAGnssRil
-2f907708d74d94b1e121ed27651c9c72af65952d347b58ff07dac5d5d7a7f678 android.hardware.gnss@1.0::IAGnssRilCallback
-5ac7edad06d76064b882be161f3f9d9692a997ec72e9f36addb7fe8918f49992 android.hardware.gnss@1.0::IGnss
-b05c983c87c3376e145223688c3b541b5e11b827f211e38d5a31af1ca3a2e222 android.hardware.gnss@1.0::IGnssBatching
-4981d2d2c4e725c7544be0956099a91fc7bbc8048c563394158083fe924e651e android.hardware.gnss@1.0::IGnssBatchingCallback
-3cd22d92cc1f935150c5048310e84886f14eed2556e8f00636733d204045cc4f android.hardware.gnss@1.0::IGnssCallback
-175185a5eda87476193ca5461df75dd16d36664591e8130530dd8ef0eb2ddf6a android.hardware.gnss@1.0::IGnssConfiguration
-4542122b96fbf27101cb8222bafb76e7c8d032d977dd1058edd8e5881ca5752f android.hardware.gnss@1.0::IGnssDebug
-e6dd0c8416e523ab9cbd14d56ab6f016481a8aef3bc8a750051122d31075f6c7 android.hardware.gnss@1.0::IGnssGeofenceCallback
-f90e4ddc652706299d8e3d8ba18e0745c3bae9bf4d1be6bd06d9c1f50ec8d28a android.hardware.gnss@1.0::IGnssGeofencing
-9ea8987bb1089c8c5d7b67866575b866ef516045021d9efcc37c6352bce072a3 android.hardware.gnss@1.0::IGnssMeasurement
-cf20492673d6a423e4c2e87fdfb5a4c4a602431721978db852e246f258e25edb android.hardware.gnss@1.0::IGnssMeasurementCallback
-af85aa0f48ae99a39f4688c344e4419304f681f9af818a5c8d759286fc4418de android.hardware.gnss@1.0::IGnssNavigationMessage
-76b0874ea4c06b29f66418c59820f4286b3be9629cd872923d0dfbb602cd432d android.hardware.gnss@1.0::IGnssNavigationMessageCallback
-248bcf51da4273d64f367bf6877baef2feeaca365459842fd3c214a2dc6e0224 android.hardware.gnss@1.0::IGnssNi
-c781b7b125f68be5db8a8c3d412d526acdbdf77dcc592a4c0ed70b8ce4fe6c49 android.hardware.gnss@1.0::IGnssNiCallback
-c1142657de16fdb292a502372fe938614d65270ab8359217d6e13604fe4dbca4 android.hardware.gnss@1.0::IGnssXtra
-bd366b83d8d565d0e8bfabff3adfcab0259d75b4e2a9f8e1b91e11d1593a2ffb android.hardware.gnss@1.0::IGnssXtraCallback
-881bc2f94026784d194cffbff166c6e8bf911de4e02abe96fc7d89ec75b0574a android.hardware.gnss@1.0::types
-17971eb8a482893dadcfc16e0583f492d42a034ef95d9b0b709417af30838396 android.hardware.graphics.allocator@2.0::IAllocator
-60bf42a4898e4fb70dbd720b263aeafd7f35f5e1a5effeabb4d5d659878a5f18 android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer
-b8a75617b9ec12bea641f3a73d4025a33e8b9a2f9169dd46094af56adf9249c5 android.hardware.graphics.bufferqueue@1.0::IProducerListener
-4f6dedbcdd21c309dfc650acea81a096d6b242493ffe49c8d61bd3c43aad354e android.hardware.graphics.common@1.0::types
-b3aac6c3817f039964fcd62268274b3039e17bd7d0d5b40b4d1d1c7b19a1f866 android.hardware.graphics.composer@2.1::IComposer
-b19d00eb8a8b3b0034a0321f22e8f32162bf4c2aebbce6da22c025f56e459ea2 android.hardware.graphics.composer@2.1::IComposerCallback
-61ee43ffe6fb6dbe8b22dc17c51ff3d5ba703fc6029cba211f901f3d79c8a72d android.hardware.graphics.composer@2.1::IComposerClient
-1c98c2f5154345312ec054871792a2982ec5f3e2bc2abfb61a10c0b517978e20 android.hardware.graphics.composer@2.1::types
-a695898589e1ef15b2b2510f11edd6aafac9918d9cf8d74b4b6143b309dee542 android.hardware.graphics.mapper@2.0::IMapper
-28507d385a3dd224bf3c32f1bfd9f96092c4701b9c1cc66caa578fc3efc97877 android.hardware.graphics.mapper@2.0::types
-91e2ba3805c923f01fc1231ec9ff838942aee3346f2d7614ecc0caeadbe57ed4 android.hardware.health@1.0::IHealth
-1275aa2e8732909101b26aec49ed2285489e89d97b8610a8908b7868e35a3cc5 android.hardware.health@1.0::types
-3a8d3922e06e6d4f8e0befc6be78d0e9e07aed1585b3da6521bed406d25a9483 android.hardware.ir@1.0::IConsumerIr
-7090bd37912fcf723a12f4bc17783e3527577c4944805a028c296fd7a95bd682 android.hardware.ir@1.0::types
-cc7925a78c0ab022515f48840d3dae76f384ed3a1287abadcb461a5cd5396163 android.hardware.keymaster@3.0::IKeymasterDevice
-822998d7bb76f0cd719a409291434fcb56e6d50bc4780788bb157a3374d63b8c android.hardware.keymaster@3.0::types
-d4ed2f0e14f9e914d0b1275d2e0363192fe30aca9059c84edb5fad15995f9ec4 android.hardware.light@2.0::ILight
-d9584bfcaedd6e62cf337881748246b23e36cbc2bc3aa84c01b6a1e622061400 android.hardware.light@2.0::types
-16c0cf0f73de1e5208a95020c6c6474903e7094f76b2d782651afaca0e5fd86f android.hardware.media@1.0::types
-8bc2f5fdcad68856eb61a62fe4cc043fa064bb7f1dab95a71d1918ec1eef7b55 android.hardware.media.omx@1.0::IGraphicBufferSource
-0d3de9cd89d4718ea3b772f2d8b93be004feb3abb7e7dc5402e37047cc730d05 android.hardware.media.omx@1.0::IOmx
-32002e1c358c64de106c977a6dc6af7da27be4803a5bb66fd6f891a5ba0a1617 android.hardware.media.omx@1.0::IOmxBufferSource
-81ad8d8bb1cf6f41923cf11dd39354a8fe433db284a234cc675de7e75a82224c android.hardware.media.omx@1.0::IOmxNode
-494c0c8bf6065edc82ec127228ed19dd2243dc1c2f7d601c7c6be7b7015c1713 android.hardware.media.omx@1.0::IOmxObserver
-252c2fc50c78fd6de8365e5b60e5115119ace107db0b94b0b26815cbf3d2b64a android.hardware.media.omx@1.0::IOmxStore
-148c1b50b0958988373145ffdf5fa0e1b6534e0a2034a570e74b15c127cf7c5e android.hardware.media.omx@1.0::types
-c66902fe48d687ac6740a3e32ae55fb75532c48c36c6386461c2b4416ad2e0f1 android.hardware.memtrack@1.0::IMemtrack
-860bacd8b11a269c40567542b613fe4ca448d5cb4326d0058899e608e89dfca1 android.hardware.memtrack@1.0::types
-07ac2dc95270321ec7d4c33cd25e5085a057f47fe350d645af6f7a7a11e3cf57 android.hardware.nfc@1.0::INfc
-f2fe54426c07d67388d4774a60641ad4c0538f22eb6e1111722f231772655de6 android.hardware.nfc@1.0::INfcClientCallback
-9626fd18db113d709faf593a70caf19bd0980294d23c468c80c30186f9d298a6 android.hardware.nfc@1.0::types
-deee1dc4948f33af207e1008aba0f6cc07afb7900eab53f33192c8cac137eefc android.hardware.power@1.0::IPower
-efc83df3f962b93c7c0290d691d7d300dabe12683e2cde3591fb3c0beedce20f android.hardware.power@1.0::types
-9b5aa499ec3b4226f15f48f5ed08896e2fc0676f978c9e199c1da21daaf002a6 android.hardware.radio@1.0::IRadio
-5c8efbb9c451a59737ed2c6c20230aae4745839ca01d8088d6dcc9020e52d2c5 android.hardware.radio@1.0::IRadioIndication
-69f6b4b8ec40ca02ccc7bb8227a097135c20c00bd94c822e421cd9af1267252c android.hardware.radio@1.0::IRadioResponse
-de3ab9f73b1073cd677b19d886fb927e9381b30161a704712d2b30f875873f5c android.hardware.radio@1.0::ISap
-d183e406ef0897df2117a9dde384e8e6ea4fa6ab1c7f6f28e65b87011218c9ea android.hardware.radio@1.0::ISapCallback
-96986fbd22f0e6ca752e1fcdc0a64bda213995a81f5f36bc4faf3532d9306b97 android.hardware.radio@1.0::types
-00f70085d6fae1d482fb700a3fd42ed475384c95b51c9269b9ae5037b74ad4dd android.hardware.radio.deprecated@1.0::IOemHook
-06837b6d7e843cfa9cd20fed4070feca7a9b5c81a9ed643bf7d06803455a9816 android.hardware.radio.deprecated@1.0::IOemHookIndication
-6fd4874f0eddd4626a27658fd94fad526c317f3563439e79718bdb1a3a2309d5 android.hardware.radio.deprecated@1.0::IOemHookResponse
-6983a2cafe39d5c57dfdc1743055fb0f757a0df8c78e00423d5e1810836927e1 android.hardware.renderscript@1.0::IContext
-7f9417a0ccf78ea042ec7a8ac8e3750346d4d9d7e5ae01b1b35fde303f47c24d android.hardware.renderscript@1.0::IDevice
-fc6f325b266b32353f7d1534fbe58e0d368265a12b77fa396fb556e8c443f739 android.hardware.renderscript@1.0::types
-89585ff541c319de4091a5a0b687dd526ac81c6382ffd7b979a4164b3d7419a6 android.hardware.sensors@1.0::ISensors
-e04ab978fc28f4c515f4a75617dfda8607733a64f13666beeb0e604a07a39333 android.hardware.sensors@1.0::types
-5befc019cbe94953661e2cdb95e3cf64f5e565c29403e1c2daecc2be44e0a55c android.hardware.soundtrigger@2.0::ISoundTriggerHw
-d7ec5f612a5e0a59ea4f2b61317e208ff56dd50920fd4eb441e0cbc8f97e4f49 android.hardware.soundtrigger@2.0::ISoundTriggerHwCallback
-5bee9e70f7e5ec7ee252883b28f98f12b59960f4c2a0b4cc9a4526e4669ebcd4 android.hardware.soundtrigger@2.0::types
-97f1ec446043bc5a6645b74529a6276496bdb35e0aee41eda55cb92d51eb7802 android.hardware.thermal@1.0::IThermal
-84965a6908bceb4ef51546bf8731f309f1ea9d09a0177dcc7974132e523dd6d2 android.hardware.thermal@1.0::types
-938850621c3c5ef426a4b88e752ba99b3559037e782a3d938604f3aef5cc0f1b android.hardware.tv.cec@1.0::IHdmiCec
-e75b6eea711d36fac678bce072b3cec6544b27fa9f4cd903999404e5c110ca10 android.hardware.tv.cec@1.0::IHdmiCecCallback
-6e25f8dbfadb668e1d4ec80eb9acd95d8bc9e0a240c36d27e662adb440314b95 android.hardware.tv.cec@1.0::types
-0cafa3c8388e9631916d2d800f78decbcec2904f11415b32c71a31d9a51ebf79 android.hardware.tv.input@1.0::ITvInput
-dee83e5c864fbbee8f02448d0800be32f06856386b9f907bc5d952208c9434f9 android.hardware.tv.input@1.0::ITvInputCallback
-07aab30410b612381234dca6d453d4ab96f2e536368715717c6e28101b9851b5 android.hardware.tv.input@1.0::types
-4ef57499273f38bdbdd0c15e56ee7a4bc5f18a5644092170a531df3541d9e015 android.hardware.usb@1.0::IUsb
-4be7881e411ba42784bf5b7354c14ae0cf161004d39433aaecaab0d19ea99354 android.hardware.usb@1.0::IUsbCallback
-f7e6e747910a3cd0a35846141e3b990a6a612a297b2b70ccd5740b646a450a8c android.hardware.usb@1.0::types
-06ea64cc3565777f3b259e400ffa7100d07f3827ad9357b0c5d3c651384e5553 android.hardware.vibrator@1.0::IVibrator
-0fecd34ae64f32eff6aa615fd662349242c0b8b6e303ef05a7cb5776c732f413 android.hardware.vibrator@1.0::types
-4b962968a7df4ab104d1315d66a0a7348a713fecbb5d2c1b23688494458f37ce android.hardware.vr@1.0::IVr
-b9be36719a8ad534000a51ea07be91be94c405bf1e038ae825acf65087ffd378 android.hardware.wifi@1.0::IWifi
-ee0224ee18813506d9d6f13d8c8e4679f053c290a443a52a7c52a5d3c852262b android.hardware.wifi@1.0::IWifiApIface
-f3eecc489deb4c74892f59eb7adb769063bd5c354ac132b626a5f42b363d36bc android.hardware.wifi@1.0::IWifiChip
-a1b988377645a58e5e2542ca2bad4e17c21a4a389213d05de2f0e32d57b7d339 android.hardware.wifi@1.0::IWifiChipEventCallback
-5ed6760ce77e84bc6c49d1acb3f7d8117c9176b3f06514bc44ad3af84c80dcfe android.hardware.wifi@1.0::IWifiEventCallback
-6b9ad43a5efbe6ca214f751e22ce43cf5cd4d5d5f2cba80f24ccd3755a72401c android.hardware.wifi@1.0::IWifiIface
-ba5aa74f1ba714f0093864227923492808795bda6199c4ea0891322d27f8c931 android.hardware.wifi@1.0::IWifiNanIface
-325c94f3e1a565b56bbc74faddbd0ba7cb824f263dccf9dfff2daf62b86ed774 android.hardware.wifi@1.0::IWifiNanIfaceEventCallback
-c2c3f0372b41780fb6dfe83c022296806c2024d7046682fd201de5aa9b791c7a android.hardware.wifi@1.0::IWifiP2pIface
-766e9765f5c9c759b2a763c2288353fb5deff3389c2cc28f81d79c939704ce8b android.hardware.wifi@1.0::IWifiRttController
-72ab6f3e120cbf07aa6f8e87ca89112bdeb36b7fbb96bce5af3712323ab8b8e6 android.hardware.wifi@1.0::IWifiRttControllerEventCallback
-3b8093d39ef1e10e43c5538afbf5ff6e39b8d8168ebbe1998d993e89e25f14a5 android.hardware.wifi@1.0::IWifiStaIface
-7fbfc551c3e23c8b4398c3e16e452b516457e6921424a53474cbf373ca306fa9 android.hardware.wifi@1.0::IWifiStaIfaceEventCallback
-e20d5132d6d23e072c15de065b5e2aa13ff965031246a2c82581732bae56bf6d android.hardware.wifi@1.0::types
-f7e55c08187d8c855068a1ee3d0c8daeee7570292d96509c21a8756d4f5cfb9b android.hardware.wifi.supplicant@1.0::ISupplicant
-56b5c7267cb3d3337f44eb8b0b38ff4c6260dcc70e07687fcab94b1ccea8d159 android.hardware.wifi.supplicant@1.0::ISupplicantCallback
-35ba7bcdf18f24a866a7e5429548f06768bb20a257f75b10a397c4d825ef8438 android.hardware.wifi.supplicant@1.0::ISupplicantIface
-cda01008c06922fa37c1213e9bb831a109b3174532805616fb7161edc403866f android.hardware.wifi.supplicant@1.0::ISupplicantNetwork
-4907410338c5e8dbeec4b5edc2608ea323f5561945f8810af81810c47b019184 android.hardware.wifi.supplicant@1.0::ISupplicantP2pIface
-8b63f5efa2e3be3a7cb8a428760d82285a4ab79bcbdea6ef90aa547555e582d4 android.hardware.wifi.supplicant@1.0::ISupplicantP2pIfaceCallback
-56128f74560571b6777d59453f35c6b35693ee377e2a23c807708906928f09de android.hardware.wifi.supplicant@1.0::ISupplicantP2pNetwork
-2067c22197bca9743dab66a6f561a8a8375c67b4f76aed05f776839499bd4c8f android.hardware.wifi.supplicant@1.0::ISupplicantP2pNetworkCallback
-7752e1de93aaf5fed37011c219ac247069f6af320b0810daa98510584a10e7b4 android.hardware.wifi.supplicant@1.0::ISupplicantStaIface
-d781c8d7e7b3fe5cca8cf6e1d8806e770982ae5358c7816ed51b0f0ec272e70d android.hardware.wifi.supplicant@1.0::ISupplicantStaIfaceCallback
-b12ef0bdd8a4d247a8a6e960b227ed32383f2b0241f55d67fcea6eff6a6737fa android.hardware.wifi.supplicant@1.0::ISupplicantStaNetwork
-d8f0877ae1d321c1d884c7631dfe36cab0ec8a4b2863d4b687f85d3549a63bcc android.hardware.wifi.supplicant@1.0::ISupplicantStaNetworkCallback
-fe3c3c2f572b72f15f8594c538b0577bd5c28722c31879cfe6231330cddb6747 android.hardware.wifi.supplicant@1.0::types
-
-# ABI preserving changes to HALs released in Android O
-
-78589343d8ee2e1b155acad3fbdc7fcbb6af94491aee968b2383c21627264f8b android.hardware.radio@1.0::IRadioResponse
-c2c50ec74c87a583c683b4493f8f9f2e454a8d41c57af5b3eb88823a999f0ea4 android.hardware.radio@1.0::IRadioResponse
diff --git a/prebuilt_hashes/27.txt b/prebuilt_hashes/27.txt
deleted file mode 100644
index 23f2004..0000000
--- a/prebuilt_hashes/27.txt
+++ /dev/null
@@ -1,249 +0,0 @@
-# Do not change this file except to add new interfaces. Changing
-# pre-existing interfaces will fail VTS and break framework-only OTAs
-
-# HALs released in Android O
-
-f219c3b5b8c6cb1d659d4c7328f67246abfe1a8613f469826fd3b9ad090417a2 android.hardware.audio@2.0::IDevice
-4d579cae1cd87a783fd49233e10ce720ba183cfd1d5ccd80149e69de5c1c7362 android.hardware.audio@2.0::IDevicesFactory
-203e23f18011390b8cd10c303e0c16c4eebc8fa187e80e40d6be4624c2b0848a android.hardware.audio@2.0::IPrimaryDevice
-aaf93123deec336eb247ad8099849469a541ca0cf7c28c5f5336cebe1ee86748 android.hardware.audio@2.0::IStream
-0468c5723b0d44c5b451bdfa06153000c6f352fd3336e0ad2697127b04b766df android.hardware.audio@2.0::IStreamIn
-7296f7064fd3ab24082b43a1da34cc876268065310b785499fba5178d063680a android.hardware.audio@2.0::IStreamOut
-19d241d71c3e1140afba8140dcb57448446025a5fc03739788c4c25e9a98b6c2 android.hardware.audio@2.0::IStreamOutCallback
-c84da9f586087227daa3b96d42b4575326bccfd5bc8a2a5acf86d774f8ea2648 android.hardware.audio@2.0::types
-1305786c06e22b9b24ebde136054cc827b63c86d8bf4a136d6f7f54752b8566b android.hardware.audio.common@2.0::types
-fa8fbae3d1da3c264e4f3110728076abc09b4e65f12af6ae136367328de988ab android.hardware.audio.effect@2.0::IAcousticEchoCancelerEffect
-ca4752545d54547ff069eae161af7550cb5f5a7e8b60316ddd132a30906a68e7 android.hardware.audio.effect@2.0::IAutomaticGainControlEffect
-d2b8af988dc66f514d886bcee44b440d8034bc2a762f7161717ef3c956073067 android.hardware.audio.effect@2.0::IBassBoostEffect
-611bc09c75e796f3512b1ca6be508b0a9ba996759b8a2c60507784ff58076229 android.hardware.audio.effect@2.0::IDownmixEffect
-36a57369dfdc75180e8b64ae80b1970db8f6d9085dbff6ca931715038cc056e1 android.hardware.audio.effect@2.0::IEffect
-d2aa2df6d189c580f5be8460fa0ff4134d9c05a383f3204659baee426a6f0edf android.hardware.audio.effect@2.0::IEffectBufferProviderCallback
-217f9161983a48d3bf3faeb158f868aa8bf0ce25889e4ee3d2bab1a2e8d33e77 android.hardware.audio.effect@2.0::IEffectsFactory
-c2b38bc07991e880c83ca8cb88181411eeef708b8b936aedd2f2e0acade7df69 android.hardware.audio.effect@2.0::IEnvironmentalReverbEffect
-2ff9f9704be5f167745b4de790e9dafc3cc4719e2f6e2e5497085e679853cfe7 android.hardware.audio.effect@2.0::IEqualizerEffect
-c31447fb02dbc8b56c359941dad22f416511860173c5c5fd278d1bf2312b13de android.hardware.audio.effect@2.0::ILoudnessEnhancerEffect
-804831ca258802eb3eb65a0a7b5d5e3d37d4a15ba8c2836b4276eda98b47e1d0 android.hardware.audio.effect@2.0::INoiseSuppressionEffect
-778fd5b9837f481d8e47425b3e2a3bd0c6362a0b6870291518e2d863530fdb61 android.hardware.audio.effect@2.0::IPresetReverbEffect
-c93cb25a1a92d07aa80a617c01e8d22fc97bf8cefd3962b6a5be386ad4704d89 android.hardware.audio.effect@2.0::IVirtualizerEffect
-918f331780c9c7b04f2151a2e563aab088198ede8e6f865302ebaa13905bd9ce android.hardware.audio.effect@2.0::IVisualizerEffect
-4caad099f8fc00262b6c03ba41271808b37cea90ac98b534299bbf4ee823af02 android.hardware.audio.effect@2.0::types
-# android.hardware.automotive.* are unfrozen
-1fbdc1f852f8bd2e4a6c5cb30ac2b78668c98dce118a61762d4034ae859f43d8 android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprint
-aabb5c3c585592d71ee57b77298c14993d77914ddeaa64b2c5109a602b02ea47 android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprintClientCallback
-1ec60d4efddae9a7b2469278a576967b4751e88de5b8d7e9df6eff6bc0da7bc9 android.hardware.biometrics.fingerprint@2.1::types
-347ce746815607567f5f3b53e4800998ca5ab9355141f0880fc0cf0c1fc5c355 android.hardware.bluetooth@1.0::IBluetoothHci
-835f41be2281bfb22f3e33c6fa870bde7bc21e37e5cfbaf9a36fff170632f754 android.hardware.bluetooth@1.0::IBluetoothHciCallbacks
-a8dfd0dbe463a3cdbcf1d985b38a28b3d93ba2ae5a1d1db4aaef4c38a5781b91 android.hardware.bluetooth@1.0::types
-7192d756aeba00aba32f4504981df8172ffca83e210c4838dabf295e53e93590 android.hardware.boot@1.0::IBootControl
-cebaa803b8e33807a0d69f46652b650ccb549e8f9b19d6becbbf26690e828b49 android.hardware.boot@1.0::types
-a98d49f23712a7cc327d1e0602d05f6f3ad32cfb5c74711d009c726611ee1c93 android.hardware.broadcastradio@1.0::IBroadcastRadio
-ed82579c0c165feaa12d0e33c06b3342ab41ec0a439247f202775e8369e46ef6 android.hardware.broadcastradio@1.0::IBroadcastRadioFactory
-da6ab32ee2793d2c86d3b603075d5383852b89d7eaa201861aa0473d418f3c7f android.hardware.broadcastradio@1.0::ITuner
-04d3ca022e25c308d9efd2e7eb77b3a7a206907cdc1b9ea9326340b377868172 android.hardware.broadcastradio@1.0::ITunerCallback
-bd42c8d7838cfed1998b49c39745dec116d2d6edc2c11a4c0399b8f3a1d1655a android.hardware.broadcastradio@1.0::types
-81164323115d6588e259e8319fddf7487adfa1f49ce60f7e80ba74e0783392a4 android.hardware.camera.common@1.0::types
-c1705e9d62438a1d955269965af915ae28e692bd480a3b1ce67056fef992d62f android.hardware.camera.device@1.0::ICameraDevice
-78e9b44cf8660bdc1e98dca07451804153824efcd28db208a62f5ad728f44076 android.hardware.camera.device@1.0::ICameraDeviceCallback
-28f0386ba86ddf41e53a8117b48a0328d7a4d2574213e89f4a1062398a244566 android.hardware.camera.device@1.0::ICameraDevicePreviewCallback
-4db48439ce9dde97f1cfb3d7408f6c737f621ac0f7494aeea35ed599bc2352a3 android.hardware.camera.device@1.0::types
-b32f9aeaf1c442195eb06ffc7600968c919d005b2718874f09c57287fae55918 android.hardware.camera.device@3.2::ICameraDevice
-63bfc3da0f2d2301f7a0508c7c2b9ffc521d4d545ee03718da70e9d6273b3b21 android.hardware.camera.device@3.2::ICameraDeviceCallback
-0fa3e1e64819283b8737fc4e5ab759f0cb4ac1a996e8a51cc4aa8025a457208e android.hardware.camera.device@3.2::ICameraDeviceSession
-030be3d2b159cbde7920485807140f6b6064ef4a5de4a40a6c4bc8d2c72f7cd3 android.hardware.camera.device@3.2::types
-5ba7947cee515d7a2359bfcbfb9678c1c3a768c288471919ac095b96ae6f3d40 android.hardware.camera.metadata@3.2::types
-f7e299d85033ac52d1095a35784fcfeaff43603f58c751e4153c85bbade3b330 android.hardware.camera.provider@2.4::ICameraProvider
-a501ca1aecd09f1b9fd70a9af84205430dbd49a808e8fa395d363b9902e6f58c android.hardware.camera.provider@2.4::ICameraProviderCallback
-7f5fe8f4f8a24037153c504d8b4d3313c2ce33d81c8c69fe5194ddd2d4080e72 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
-87beacc481897cf02fb1628d75e68133de6d74d4cffe582cda2f5e16bdd74516 android.hardware.configstore@1.0::types
-a5ae0fe8667f0b1af09b13e72d29600f4eb3853b257079c45a99b6f4a3360649 android.hardware.contexthub@1.0::IContexthub
-2ab3054c2d9302d8417ee7495353a2887fe338f913276f2eb41e80f11395ec2e android.hardware.contexthub@1.0::IContexthubCallback
-c3b2b37d561d31ea094411f251bf73bea334f4fe849a4390aef5e20bca6cadba android.hardware.contexthub@1.0::types
-df174c1871c864b4c79ca9f64aae7936d24a272eca3191a30458ca2b706dec79 android.hardware.drm@1.0::ICryptoFactory
-83639e90caeb996b0274e420de3cd556779de1ca48464b68eee799bef32b34cd android.hardware.drm@1.0::ICryptoPlugin
-1440cffdfaeb12830ac10ee6ffdb0f1083e701057b806df11fb4787b4c91e718 android.hardware.drm@1.0::IDrmFactory
-78ba33b108f620e6a0eec01ef654547e69a85754578ea4c9ef03ec205f16121c android.hardware.drm@1.0::IDrmPlugin
-701d9e51952172364e4ea70db9c397f08c3b4577ba33051f050a6cdd532de1b4 android.hardware.drm@1.0::IDrmPluginListener
-4238d62ad90df63aa338c6f1b6264c09c5a3706945d5c49d1189c0be1dc9e942 android.hardware.drm@1.0::types
-f07b1ee3ba11a2fc9f200421b2e1afb7c1854ee987000e45c987fb9507795055 android.hardware.dumpstate@1.0::IDumpstateDevice
-c9d318df7922bde3b265927b521ff5a965002826fc0cabfcaef52a56760f2d34 android.hardware.gatekeeper@1.0::IGatekeeper
-da13bd69282fb275767abb18704c57ff8038e6c139ad17157dc702810f70d06a android.hardware.gatekeeper@1.0::types
-37c7da4f823ec958dfa9c960e2d341c48f877e0bfa758f3fa9e2d9c1e1bd66d9 android.hardware.gnss@1.0::IAGnss
-7ec9afdb964bfb8369866913caf018f2636592885bcb558a65de2c5436ab4f60 android.hardware.gnss@1.0::IAGnssCallback
-d16e6a359be6963ea753d7138e84ecf2b93052097938938c4d36d7a47ea2e2ae android.hardware.gnss@1.0::IAGnssRil
-2f907708d74d94b1e121ed27651c9c72af65952d347b58ff07dac5d5d7a7f678 android.hardware.gnss@1.0::IAGnssRilCallback
-5ac7edad06d76064b882be161f3f9d9692a997ec72e9f36addb7fe8918f49992 android.hardware.gnss@1.0::IGnss
-b05c983c87c3376e145223688c3b541b5e11b827f211e38d5a31af1ca3a2e222 android.hardware.gnss@1.0::IGnssBatching
-4981d2d2c4e725c7544be0956099a91fc7bbc8048c563394158083fe924e651e android.hardware.gnss@1.0::IGnssBatchingCallback
-3cd22d92cc1f935150c5048310e84886f14eed2556e8f00636733d204045cc4f android.hardware.gnss@1.0::IGnssCallback
-175185a5eda87476193ca5461df75dd16d36664591e8130530dd8ef0eb2ddf6a android.hardware.gnss@1.0::IGnssConfiguration
-4542122b96fbf27101cb8222bafb76e7c8d032d977dd1058edd8e5881ca5752f android.hardware.gnss@1.0::IGnssDebug
-e6dd0c8416e523ab9cbd14d56ab6f016481a8aef3bc8a750051122d31075f6c7 android.hardware.gnss@1.0::IGnssGeofenceCallback
-f90e4ddc652706299d8e3d8ba18e0745c3bae9bf4d1be6bd06d9c1f50ec8d28a android.hardware.gnss@1.0::IGnssGeofencing
-9ea8987bb1089c8c5d7b67866575b866ef516045021d9efcc37c6352bce072a3 android.hardware.gnss@1.0::IGnssMeasurement
-cf20492673d6a423e4c2e87fdfb5a4c4a602431721978db852e246f258e25edb android.hardware.gnss@1.0::IGnssMeasurementCallback
-af85aa0f48ae99a39f4688c344e4419304f681f9af818a5c8d759286fc4418de android.hardware.gnss@1.0::IGnssNavigationMessage
-76b0874ea4c06b29f66418c59820f4286b3be9629cd872923d0dfbb602cd432d android.hardware.gnss@1.0::IGnssNavigationMessageCallback
-248bcf51da4273d64f367bf6877baef2feeaca365459842fd3c214a2dc6e0224 android.hardware.gnss@1.0::IGnssNi
-c781b7b125f68be5db8a8c3d412d526acdbdf77dcc592a4c0ed70b8ce4fe6c49 android.hardware.gnss@1.0::IGnssNiCallback
-c1142657de16fdb292a502372fe938614d65270ab8359217d6e13604fe4dbca4 android.hardware.gnss@1.0::IGnssXtra
-bd366b83d8d565d0e8bfabff3adfcab0259d75b4e2a9f8e1b91e11d1593a2ffb android.hardware.gnss@1.0::IGnssXtraCallback
-881bc2f94026784d194cffbff166c6e8bf911de4e02abe96fc7d89ec75b0574a android.hardware.gnss@1.0::types
-17971eb8a482893dadcfc16e0583f492d42a034ef95d9b0b709417af30838396 android.hardware.graphics.allocator@2.0::IAllocator
-60bf42a4898e4fb70dbd720b263aeafd7f35f5e1a5effeabb4d5d659878a5f18 android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer
-b8a75617b9ec12bea641f3a73d4025a33e8b9a2f9169dd46094af56adf9249c5 android.hardware.graphics.bufferqueue@1.0::IProducerListener
-4f6dedbcdd21c309dfc650acea81a096d6b242493ffe49c8d61bd3c43aad354e android.hardware.graphics.common@1.0::types
-b3aac6c3817f039964fcd62268274b3039e17bd7d0d5b40b4d1d1c7b19a1f866 android.hardware.graphics.composer@2.1::IComposer
-b19d00eb8a8b3b0034a0321f22e8f32162bf4c2aebbce6da22c025f56e459ea2 android.hardware.graphics.composer@2.1::IComposerCallback
-61ee43ffe6fb6dbe8b22dc17c51ff3d5ba703fc6029cba211f901f3d79c8a72d android.hardware.graphics.composer@2.1::IComposerClient
-1c98c2f5154345312ec054871792a2982ec5f3e2bc2abfb61a10c0b517978e20 android.hardware.graphics.composer@2.1::types
-a695898589e1ef15b2b2510f11edd6aafac9918d9cf8d74b4b6143b309dee542 android.hardware.graphics.mapper@2.0::IMapper
-28507d385a3dd224bf3c32f1bfd9f96092c4701b9c1cc66caa578fc3efc97877 android.hardware.graphics.mapper@2.0::types
-91e2ba3805c923f01fc1231ec9ff838942aee3346f2d7614ecc0caeadbe57ed4 android.hardware.health@1.0::IHealth
-1275aa2e8732909101b26aec49ed2285489e89d97b8610a8908b7868e35a3cc5 android.hardware.health@1.0::types
-3a8d3922e06e6d4f8e0befc6be78d0e9e07aed1585b3da6521bed406d25a9483 android.hardware.ir@1.0::IConsumerIr
-7090bd37912fcf723a12f4bc17783e3527577c4944805a028c296fd7a95bd682 android.hardware.ir@1.0::types
-cc7925a78c0ab022515f48840d3dae76f384ed3a1287abadcb461a5cd5396163 android.hardware.keymaster@3.0::IKeymasterDevice
-822998d7bb76f0cd719a409291434fcb56e6d50bc4780788bb157a3374d63b8c android.hardware.keymaster@3.0::types
-d4ed2f0e14f9e914d0b1275d2e0363192fe30aca9059c84edb5fad15995f9ec4 android.hardware.light@2.0::ILight
-d9584bfcaedd6e62cf337881748246b23e36cbc2bc3aa84c01b6a1e622061400 android.hardware.light@2.0::types
-16c0cf0f73de1e5208a95020c6c6474903e7094f76b2d782651afaca0e5fd86f android.hardware.media@1.0::types
-8bc2f5fdcad68856eb61a62fe4cc043fa064bb7f1dab95a71d1918ec1eef7b55 android.hardware.media.omx@1.0::IGraphicBufferSource
-0d3de9cd89d4718ea3b772f2d8b93be004feb3abb7e7dc5402e37047cc730d05 android.hardware.media.omx@1.0::IOmx
-32002e1c358c64de106c977a6dc6af7da27be4803a5bb66fd6f891a5ba0a1617 android.hardware.media.omx@1.0::IOmxBufferSource
-81ad8d8bb1cf6f41923cf11dd39354a8fe433db284a234cc675de7e75a82224c android.hardware.media.omx@1.0::IOmxNode
-494c0c8bf6065edc82ec127228ed19dd2243dc1c2f7d601c7c6be7b7015c1713 android.hardware.media.omx@1.0::IOmxObserver
-252c2fc50c78fd6de8365e5b60e5115119ace107db0b94b0b26815cbf3d2b64a android.hardware.media.omx@1.0::IOmxStore
-148c1b50b0958988373145ffdf5fa0e1b6534e0a2034a570e74b15c127cf7c5e android.hardware.media.omx@1.0::types
-c66902fe48d687ac6740a3e32ae55fb75532c48c36c6386461c2b4416ad2e0f1 android.hardware.memtrack@1.0::IMemtrack
-860bacd8b11a269c40567542b613fe4ca448d5cb4326d0058899e608e89dfca1 android.hardware.memtrack@1.0::types
-07ac2dc95270321ec7d4c33cd25e5085a057f47fe350d645af6f7a7a11e3cf57 android.hardware.nfc@1.0::INfc
-f2fe54426c07d67388d4774a60641ad4c0538f22eb6e1111722f231772655de6 android.hardware.nfc@1.0::INfcClientCallback
-9626fd18db113d709faf593a70caf19bd0980294d23c468c80c30186f9d298a6 android.hardware.nfc@1.0::types
-deee1dc4948f33af207e1008aba0f6cc07afb7900eab53f33192c8cac137eefc android.hardware.power@1.0::IPower
-efc83df3f962b93c7c0290d691d7d300dabe12683e2cde3591fb3c0beedce20f android.hardware.power@1.0::types
-9b5aa499ec3b4226f15f48f5ed08896e2fc0676f978c9e199c1da21daaf002a6 android.hardware.radio@1.0::IRadio
-5c8efbb9c451a59737ed2c6c20230aae4745839ca01d8088d6dcc9020e52d2c5 android.hardware.radio@1.0::IRadioIndication
-69f6b4b8ec40ca02ccc7bb8227a097135c20c00bd94c822e421cd9af1267252c android.hardware.radio@1.0::IRadioResponse
-de3ab9f73b1073cd677b19d886fb927e9381b30161a704712d2b30f875873f5c android.hardware.radio@1.0::ISap
-d183e406ef0897df2117a9dde384e8e6ea4fa6ab1c7f6f28e65b87011218c9ea android.hardware.radio@1.0::ISapCallback
-96986fbd22f0e6ca752e1fcdc0a64bda213995a81f5f36bc4faf3532d9306b97 android.hardware.radio@1.0::types
-00f70085d6fae1d482fb700a3fd42ed475384c95b51c9269b9ae5037b74ad4dd android.hardware.radio.deprecated@1.0::IOemHook
-06837b6d7e843cfa9cd20fed4070feca7a9b5c81a9ed643bf7d06803455a9816 android.hardware.radio.deprecated@1.0::IOemHookIndication
-6fd4874f0eddd4626a27658fd94fad526c317f3563439e79718bdb1a3a2309d5 android.hardware.radio.deprecated@1.0::IOemHookResponse
-6983a2cafe39d5c57dfdc1743055fb0f757a0df8c78e00423d5e1810836927e1 android.hardware.renderscript@1.0::IContext
-7f9417a0ccf78ea042ec7a8ac8e3750346d4d9d7e5ae01b1b35fde303f47c24d android.hardware.renderscript@1.0::IDevice
-fc6f325b266b32353f7d1534fbe58e0d368265a12b77fa396fb556e8c443f739 android.hardware.renderscript@1.0::types
-89585ff541c319de4091a5a0b687dd526ac81c6382ffd7b979a4164b3d7419a6 android.hardware.sensors@1.0::ISensors
-e04ab978fc28f4c515f4a75617dfda8607733a64f13666beeb0e604a07a39333 android.hardware.sensors@1.0::types
-5befc019cbe94953661e2cdb95e3cf64f5e565c29403e1c2daecc2be44e0a55c android.hardware.soundtrigger@2.0::ISoundTriggerHw
-d7ec5f612a5e0a59ea4f2b61317e208ff56dd50920fd4eb441e0cbc8f97e4f49 android.hardware.soundtrigger@2.0::ISoundTriggerHwCallback
-5bee9e70f7e5ec7ee252883b28f98f12b59960f4c2a0b4cc9a4526e4669ebcd4 android.hardware.soundtrigger@2.0::types
-97f1ec446043bc5a6645b74529a6276496bdb35e0aee41eda55cb92d51eb7802 android.hardware.thermal@1.0::IThermal
-84965a6908bceb4ef51546bf8731f309f1ea9d09a0177dcc7974132e523dd6d2 android.hardware.thermal@1.0::types
-938850621c3c5ef426a4b88e752ba99b3559037e782a3d938604f3aef5cc0f1b android.hardware.tv.cec@1.0::IHdmiCec
-e75b6eea711d36fac678bce072b3cec6544b27fa9f4cd903999404e5c110ca10 android.hardware.tv.cec@1.0::IHdmiCecCallback
-6e25f8dbfadb668e1d4ec80eb9acd95d8bc9e0a240c36d27e662adb440314b95 android.hardware.tv.cec@1.0::types
-0cafa3c8388e9631916d2d800f78decbcec2904f11415b32c71a31d9a51ebf79 android.hardware.tv.input@1.0::ITvInput
-dee83e5c864fbbee8f02448d0800be32f06856386b9f907bc5d952208c9434f9 android.hardware.tv.input@1.0::ITvInputCallback
-07aab30410b612381234dca6d453d4ab96f2e536368715717c6e28101b9851b5 android.hardware.tv.input@1.0::types
-4ef57499273f38bdbdd0c15e56ee7a4bc5f18a5644092170a531df3541d9e015 android.hardware.usb@1.0::IUsb
-4be7881e411ba42784bf5b7354c14ae0cf161004d39433aaecaab0d19ea99354 android.hardware.usb@1.0::IUsbCallback
-f7e6e747910a3cd0a35846141e3b990a6a612a297b2b70ccd5740b646a450a8c android.hardware.usb@1.0::types
-06ea64cc3565777f3b259e400ffa7100d07f3827ad9357b0c5d3c651384e5553 android.hardware.vibrator@1.0::IVibrator
-0fecd34ae64f32eff6aa615fd662349242c0b8b6e303ef05a7cb5776c732f413 android.hardware.vibrator@1.0::types
-4b962968a7df4ab104d1315d66a0a7348a713fecbb5d2c1b23688494458f37ce android.hardware.vr@1.0::IVr
-b9be36719a8ad534000a51ea07be91be94c405bf1e038ae825acf65087ffd378 android.hardware.wifi@1.0::IWifi
-ee0224ee18813506d9d6f13d8c8e4679f053c290a443a52a7c52a5d3c852262b android.hardware.wifi@1.0::IWifiApIface
-f3eecc489deb4c74892f59eb7adb769063bd5c354ac132b626a5f42b363d36bc android.hardware.wifi@1.0::IWifiChip
-a1b988377645a58e5e2542ca2bad4e17c21a4a389213d05de2f0e32d57b7d339 android.hardware.wifi@1.0::IWifiChipEventCallback
-5ed6760ce77e84bc6c49d1acb3f7d8117c9176b3f06514bc44ad3af84c80dcfe android.hardware.wifi@1.0::IWifiEventCallback
-6b9ad43a5efbe6ca214f751e22ce43cf5cd4d5d5f2cba80f24ccd3755a72401c android.hardware.wifi@1.0::IWifiIface
-ba5aa74f1ba714f0093864227923492808795bda6199c4ea0891322d27f8c931 android.hardware.wifi@1.0::IWifiNanIface
-325c94f3e1a565b56bbc74faddbd0ba7cb824f263dccf9dfff2daf62b86ed774 android.hardware.wifi@1.0::IWifiNanIfaceEventCallback
-c2c3f0372b41780fb6dfe83c022296806c2024d7046682fd201de5aa9b791c7a android.hardware.wifi@1.0::IWifiP2pIface
-766e9765f5c9c759b2a763c2288353fb5deff3389c2cc28f81d79c939704ce8b android.hardware.wifi@1.0::IWifiRttController
-72ab6f3e120cbf07aa6f8e87ca89112bdeb36b7fbb96bce5af3712323ab8b8e6 android.hardware.wifi@1.0::IWifiRttControllerEventCallback
-3b8093d39ef1e10e43c5538afbf5ff6e39b8d8168ebbe1998d993e89e25f14a5 android.hardware.wifi@1.0::IWifiStaIface
-7fbfc551c3e23c8b4398c3e16e452b516457e6921424a53474cbf373ca306fa9 android.hardware.wifi@1.0::IWifiStaIfaceEventCallback
-e20d5132d6d23e072c15de065b5e2aa13ff965031246a2c82581732bae56bf6d android.hardware.wifi@1.0::types
-f7e55c08187d8c855068a1ee3d0c8daeee7570292d96509c21a8756d4f5cfb9b android.hardware.wifi.supplicant@1.0::ISupplicant
-56b5c7267cb3d3337f44eb8b0b38ff4c6260dcc70e07687fcab94b1ccea8d159 android.hardware.wifi.supplicant@1.0::ISupplicantCallback
-35ba7bcdf18f24a866a7e5429548f06768bb20a257f75b10a397c4d825ef8438 android.hardware.wifi.supplicant@1.0::ISupplicantIface
-cda01008c06922fa37c1213e9bb831a109b3174532805616fb7161edc403866f android.hardware.wifi.supplicant@1.0::ISupplicantNetwork
-4907410338c5e8dbeec4b5edc2608ea323f5561945f8810af81810c47b019184 android.hardware.wifi.supplicant@1.0::ISupplicantP2pIface
-8b63f5efa2e3be3a7cb8a428760d82285a4ab79bcbdea6ef90aa547555e582d4 android.hardware.wifi.supplicant@1.0::ISupplicantP2pIfaceCallback
-56128f74560571b6777d59453f35c6b35693ee377e2a23c807708906928f09de android.hardware.wifi.supplicant@1.0::ISupplicantP2pNetwork
-2067c22197bca9743dab66a6f561a8a8375c67b4f76aed05f776839499bd4c8f android.hardware.wifi.supplicant@1.0::ISupplicantP2pNetworkCallback
-7752e1de93aaf5fed37011c219ac247069f6af320b0810daa98510584a10e7b4 android.hardware.wifi.supplicant@1.0::ISupplicantStaIface
-d781c8d7e7b3fe5cca8cf6e1d8806e770982ae5358c7816ed51b0f0ec272e70d android.hardware.wifi.supplicant@1.0::ISupplicantStaIfaceCallback
-b12ef0bdd8a4d247a8a6e960b227ed32383f2b0241f55d67fcea6eff6a6737fa android.hardware.wifi.supplicant@1.0::ISupplicantStaNetwork
-d8f0877ae1d321c1d884c7631dfe36cab0ec8a4b2863d4b687f85d3549a63bcc android.hardware.wifi.supplicant@1.0::ISupplicantStaNetworkCallback
-fe3c3c2f572b72f15f8594c538b0577bd5c28722c31879cfe6231330cddb6747 android.hardware.wifi.supplicant@1.0::types
-
-# ABI preserving changes to HALs during Android O MR1 (Initial Set)
-
-# android.hardware.automotive.* are unfrozen
-150a338ce11fcec70757c9675d83cf6a5d7b40d0c812741b91671fecce59eac9 android.hardware.broadcastradio@1.0::types
-dc7e6d4f537b9943e27edc4f86c5a03bb643b18f18f866f8c3c71c0ac4ea8cbc android.hardware.broadcastradio@1.0::types
-760485232f6cce07f8bb05e3475509956996b702f77415ee5bff05e2ec5a5bcc android.hardware.dumpstate@1.0::IDumpstateDevice
-e822cb7f4a1bdd45689c5e92ccd19a2201c20b771bd4b2ec1ae627e324591f9d android.hardware.radio@1.0::IRadioResponse
-6e69adb24d7c0b0ca3a54a38c49a5625b161b3f5d5f7d6fda0befdbbfc8e9e06 android.hardware.radio@1.0::IRadioResponse
-28e929b453df3d9f5060af2764e6cdb123ddb893e3e86923c877f6ff7e5f02c9 android.hardware.wifi@1.0::types
-df1d7b27e644bfed0a4f606a8c44d35d45cafce82c7c648494c8a25c7cd4a949 android.hardware.wifi@1.0::types
-
-# HALs released in Android O MR1 (Initial Set)
-
-4b65763663a94a3920134011691f8fbb42ccb7b7795589efddc049a9106047d6 android.hardware.oemlock@1.0::IOemLock
-e02cd3722cb5e8fa51179f5defacb4f7866f903c9c7c51dc01a3148473a71525 android.hardware.oemlock@1.0::types
-224f9d22a367a0016f09b6dc676f53f1446697d9dc747163032329e5da552de5 android.hardware.power@1.1::IPower
-574fd9758b7cab4922c72cc5a9f36d1cd48ffd3425fdd776426653280d3d4138 android.hardware.power@1.1::types
-f79edf50a378a9c9bb737f93f205dab91b4c63ea49723afc6f856c138203ea81 android.hardware.radio@1.1::IRadio
-fcc5c8c88b85a9f63fba67d9e674da466c72a98ca287f343fb5721d098713f86 android.hardware.radio@1.1::IRadioIndication
-50f27e8c7ec009d5d4418b2ce8392b940bbf052ecc1d7251285f332485a5ba4e android.hardware.radio@1.1::IRadioResponse
-be981148c95c0089f3ae92854f0e7ae999d308e927db3e065f12a4fabe07852f android.hardware.radio@1.1::ISap
-d8d6bf7b4d36c04ce587df75953c3f723cfbe71c896c1aa8ab6478eae126723d android.hardware.radio@1.1::types
-d8aae01606bfd34bf2fb9a59cadc016f46f318e56cddb8f15a945c5b3c1222bc android.hardware.tetheroffload.config@1.0::IOffloadConfig
-447b00306bc95a7aafec1d660f6f3e9f76ac8bc0353193435e5579ab833da619 android.hardware.tetheroffload.control@1.0::IOffloadControl
-07658829339d75962016e00ed81b005ad29fca7ac12ad3bc3ccd86b08d94c2d3 android.hardware.tetheroffload.control@1.0::ITetheringOffloadCallback
-0df5b0178af15c53cdce8fcf8ca14035e8e08db4fa76fdc12009ddbe0b53626b android.hardware.tetheroffload.control@1.0::types
-b30ef02ef26ff804e2f6acf1201bc141b59e134e6a0338562284491102cb13e3 android.hardware.usb@1.1::IUsb
-13a580e35af01270a1e9774177c51db51d8672e6139ba00851e654e68a4d7dff android.hardware.usb@1.1::IUsbCallback
-f0ed667288908c08fced570bd1f3c4a0f236aa927938e805f0d9fece525da81e android.hardware.usb@1.1::types
-f95a1e85612f2d0d616eacd2eb63c52d10dfa889f165df57697c30e1f47b4785 android.hardware.vibrator@1.1::IVibrator
-246fb9d9e2b4800aeb0adc3cdbaa15d0321ebab54b7bd1ab87da5b67c7b0b064 android.hardware.vibrator@1.1::types
-9bc43413b80cd0c59a022e93da1448dcb82dd10c6dd31932df4659e4bdcb1368 android.hardware.weaver@1.0::IWeaver
-7728b0393a2ed9796537d4165c7d95407e9d8cb447a647b545fdfe06a28689e7 android.hardware.weaver@1.0::types
-bb7c96762d0aa3ddb874c8815bacdd3cbc8fb87ea2f82b928bc29e24a3593055 android.hardware.wifi.offload@1.0::IOffload
-c3354ab0d381a236c12dc486ad4b6bec28c979d26748b4661f12ede36f392808 android.hardware.wifi.offload@1.0::IOffloadCallback
-b18caefefcc765092412285d776234fcf213b73bdf07ae1b67a5f71b2d2464e3 android.hardware.wifi.offload@1.0::types
-c26473e2e4a00af43e28a0ddf9002e5062a7d0940429e5efb6e5513a8abcb75c android.hardware.wifi@1.1::IWifi
-b056e1defab4071584214584057d0bc73a613081bf1152590549649d4582c13c android.hardware.wifi@1.1::IWifiChip
-
-# ABI preserving changes to HALs during Android O MR1 (Final Set)
-2d833aeed0cd1d59437aca210be590a953cf32bcb6683cd63d089762a643fb49 android.hardware.radio@1.0::IRadioResponse
-05aa3de6130a9788fdb6f4d3cc57c3ea90f067e77a5e09d6a772ec7f6bca33d2 android.hardware.radio@1.1::IRadioResponse
-
-# HALs released in Android O MR1 (Final Set)
-044cb039378b8a0e36f40ff1e6ce04dc0d339da02095f968d5062a051e99d108 android.hardware.broadcastradio@1.1::types
-c9699483f8cefe4f9b39b4b9609b76cab2dd1659a06188056b45797d337d4256 android.hardware.broadcastradio@1.1::IBroadcastRadio
-b5d62dcd663fc4fcc977b252af59b333043bdfe73de2f11fe6d6a8bf438a0f92 android.hardware.broadcastradio@1.1::IBroadcastRadioFactory
-bc7e054a6e93adebedff345aeed44549be89e6b1b6ffe071ff47a61de764b232 android.hardware.broadcastradio@1.1::ITuner
-e9139fc755be578693f17c8cd1e27c75f412cfc722157bab5bf03ee68896e31d android.hardware.broadcastradio@1.1::ITunerCallback
-63929c99e5755d9e09d9e0fd2527391fbb1609dda0508f5933b7943b92ae0fbc android.hardware.camera.device@3.3::types
-bbcfc3f748b078f6a66c4e228084a679d30bd61bfde8bb7a91efd507b91c1bfd android.hardware.camera.device@3.3::ICameraDeviceSession
-4a6998cd6793a3f9f03989c29d662589b1bc9d38826c6698c6c17864f7a814f5 android.hardware.cas@1.0::types
-0e656ba1bac11461a17096ef752b69d24b000d820ef5652f0150a0f9731d54c2 android.hardware.cas@1.0::ICas
-b80e1456b81f80032d0de7cb45652ac15af11e7474d520d757481ecaad796dff android.hardware.cas@1.0::ICasListener
-a432d6d9200248dc2126827bcd6cdea31dd65eff39b939f64585d27d915a5857 android.hardware.cas@1.0::IDescramblerBase
-86ba9c03978b79a742e990420bc5ced0673d25a939f82572996bef92621e2014 android.hardware.cas@1.0::IMediaCasService
-503da837d1a67cbdb7c08a033e927e5430ae1b159d98bf72c6336b4dcc5e76f5 android.hardware.cas.native@1.0::types
-619600109232ed64b827c8a11beed8070b1827ae464547d7aa146cf0473b4bca android.hardware.cas.native@1.0::IDescrambler
-0a159f81359cd4f71bbe00972ee8403ea79351fb7c0cd48be72ebb3e424dbaef android.hardware.radio@1.0::types
-09342041e17c429fce0034b9096d17849122111436a5f0053e7e59500e1cb89c android.hardware.media.omx@1.0::IOmxStore
-246a56d37d57a47224562c9d077b4a2886ce6242b9311bd98a17325944c280d7 android.hardware.neuralnetworks@1.0::types
-93eb3757ceaf21590fa4cd1d4a7dfe3b3794af5396100a6d25630879352abce9 android.hardware.neuralnetworks@1.0::IDevice
-f66f9a38541bf92001d3adcce678cd7e3da2262124befb460b1c9aea9492813b android.hardware.neuralnetworks@1.0::IExecutionCallback
-953607822954435874f4b81686440a604e2a88cdd2d9164c6293f3d5772510d7 android.hardware.neuralnetworks@1.0::IPreparedModel
-73e03573494ba96f0e711ab7f1956c5b2d54c3da690cd7ecf4d6d0f287447730 android.hardware.neuralnetworks@1.0::IPreparedModelCallback
-f4945e397b5dea41bb64518dfde59be71245d8a125fd1e0acffeb57ac7b08fed android.hardware.thermal@1.1::IThermal
-c8bc853546dd55584611def2a9fa1d99f657e3366c976d2f60fe6b8aa6d2cb87 android.hardware.thermal@1.1::IThermalCallback
diff --git a/prebuilt_hashes/28.txt b/prebuilt_hashes/28.txt
deleted file mode 100644
index 8a45ca5..0000000
--- a/prebuilt_hashes/28.txt
+++ /dev/null
@@ -1,384 +0,0 @@
-# Do not change this file except to add new interfaces. Changing
-# pre-existing interfaces will fail VTS and break framework-only OTAs
-
-# HALs released in Android O
-
-f219c3b5b8c6cb1d659d4c7328f67246abfe1a8613f469826fd3b9ad090417a2 android.hardware.audio@2.0::IDevice
-4d579cae1cd87a783fd49233e10ce720ba183cfd1d5ccd80149e69de5c1c7362 android.hardware.audio@2.0::IDevicesFactory
-203e23f18011390b8cd10c303e0c16c4eebc8fa187e80e40d6be4624c2b0848a android.hardware.audio@2.0::IPrimaryDevice
-aaf93123deec336eb247ad8099849469a541ca0cf7c28c5f5336cebe1ee86748 android.hardware.audio@2.0::IStream
-0468c5723b0d44c5b451bdfa06153000c6f352fd3336e0ad2697127b04b766df android.hardware.audio@2.0::IStreamIn
-7296f7064fd3ab24082b43a1da34cc876268065310b785499fba5178d063680a android.hardware.audio@2.0::IStreamOut
-19d241d71c3e1140afba8140dcb57448446025a5fc03739788c4c25e9a98b6c2 android.hardware.audio@2.0::IStreamOutCallback
-c84da9f586087227daa3b96d42b4575326bccfd5bc8a2a5acf86d774f8ea2648 android.hardware.audio@2.0::types
-1305786c06e22b9b24ebde136054cc827b63c86d8bf4a136d6f7f54752b8566b android.hardware.audio.common@2.0::types
-fa8fbae3d1da3c264e4f3110728076abc09b4e65f12af6ae136367328de988ab android.hardware.audio.effect@2.0::IAcousticEchoCancelerEffect
-ca4752545d54547ff069eae161af7550cb5f5a7e8b60316ddd132a30906a68e7 android.hardware.audio.effect@2.0::IAutomaticGainControlEffect
-d2b8af988dc66f514d886bcee44b440d8034bc2a762f7161717ef3c956073067 android.hardware.audio.effect@2.0::IBassBoostEffect
-611bc09c75e796f3512b1ca6be508b0a9ba996759b8a2c60507784ff58076229 android.hardware.audio.effect@2.0::IDownmixEffect
-36a57369dfdc75180e8b64ae80b1970db8f6d9085dbff6ca931715038cc056e1 android.hardware.audio.effect@2.0::IEffect
-d2aa2df6d189c580f5be8460fa0ff4134d9c05a383f3204659baee426a6f0edf android.hardware.audio.effect@2.0::IEffectBufferProviderCallback
-217f9161983a48d3bf3faeb158f868aa8bf0ce25889e4ee3d2bab1a2e8d33e77 android.hardware.audio.effect@2.0::IEffectsFactory
-c2b38bc07991e880c83ca8cb88181411eeef708b8b936aedd2f2e0acade7df69 android.hardware.audio.effect@2.0::IEnvironmentalReverbEffect
-2ff9f9704be5f167745b4de790e9dafc3cc4719e2f6e2e5497085e679853cfe7 android.hardware.audio.effect@2.0::IEqualizerEffect
-c31447fb02dbc8b56c359941dad22f416511860173c5c5fd278d1bf2312b13de android.hardware.audio.effect@2.0::ILoudnessEnhancerEffect
-804831ca258802eb3eb65a0a7b5d5e3d37d4a15ba8c2836b4276eda98b47e1d0 android.hardware.audio.effect@2.0::INoiseSuppressionEffect
-778fd5b9837f481d8e47425b3e2a3bd0c6362a0b6870291518e2d863530fdb61 android.hardware.audio.effect@2.0::IPresetReverbEffect
-c93cb25a1a92d07aa80a617c01e8d22fc97bf8cefd3962b6a5be386ad4704d89 android.hardware.audio.effect@2.0::IVirtualizerEffect
-918f331780c9c7b04f2151a2e563aab088198ede8e6f865302ebaa13905bd9ce android.hardware.audio.effect@2.0::IVisualizerEffect
-4caad099f8fc00262b6c03ba41271808b37cea90ac98b534299bbf4ee823af02 android.hardware.audio.effect@2.0::types
-1fbdc1f852f8bd2e4a6c5cb30ac2b78668c98dce118a61762d4034ae859f43d8 android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprint
-aabb5c3c585592d71ee57b77298c14993d77914ddeaa64b2c5109a602b02ea47 android.hardware.biometrics.fingerprint@2.1::IBiometricsFingerprintClientCallback
-1ec60d4efddae9a7b2469278a576967b4751e88de5b8d7e9df6eff6bc0da7bc9 android.hardware.biometrics.fingerprint@2.1::types
-347ce746815607567f5f3b53e4800998ca5ab9355141f0880fc0cf0c1fc5c355 android.hardware.bluetooth@1.0::IBluetoothHci
-835f41be2281bfb22f3e33c6fa870bde7bc21e37e5cfbaf9a36fff170632f754 android.hardware.bluetooth@1.0::IBluetoothHciCallbacks
-a8dfd0dbe463a3cdbcf1d985b38a28b3d93ba2ae5a1d1db4aaef4c38a5781b91 android.hardware.bluetooth@1.0::types
-7192d756aeba00aba32f4504981df8172ffca83e210c4838dabf295e53e93590 android.hardware.boot@1.0::IBootControl
-cebaa803b8e33807a0d69f46652b650ccb549e8f9b19d6becbbf26690e828b49 android.hardware.boot@1.0::types
-a98d49f23712a7cc327d1e0602d05f6f3ad32cfb5c74711d009c726611ee1c93 android.hardware.broadcastradio@1.0::IBroadcastRadio
-ed82579c0c165feaa12d0e33c06b3342ab41ec0a439247f202775e8369e46ef6 android.hardware.broadcastradio@1.0::IBroadcastRadioFactory
-da6ab32ee2793d2c86d3b603075d5383852b89d7eaa201861aa0473d418f3c7f android.hardware.broadcastradio@1.0::ITuner
-04d3ca022e25c308d9efd2e7eb77b3a7a206907cdc1b9ea9326340b377868172 android.hardware.broadcastradio@1.0::ITunerCallback
-bd42c8d7838cfed1998b49c39745dec116d2d6edc2c11a4c0399b8f3a1d1655a android.hardware.broadcastradio@1.0::types
-81164323115d6588e259e8319fddf7487adfa1f49ce60f7e80ba74e0783392a4 android.hardware.camera.common@1.0::types
-c1705e9d62438a1d955269965af915ae28e692bd480a3b1ce67056fef992d62f android.hardware.camera.device@1.0::ICameraDevice
-78e9b44cf8660bdc1e98dca07451804153824efcd28db208a62f5ad728f44076 android.hardware.camera.device@1.0::ICameraDeviceCallback
-28f0386ba86ddf41e53a8117b48a0328d7a4d2574213e89f4a1062398a244566 android.hardware.camera.device@1.0::ICameraDevicePreviewCallback
-4db48439ce9dde97f1cfb3d7408f6c737f621ac0f7494aeea35ed599bc2352a3 android.hardware.camera.device@1.0::types
-b32f9aeaf1c442195eb06ffc7600968c919d005b2718874f09c57287fae55918 android.hardware.camera.device@3.2::ICameraDevice
-63bfc3da0f2d2301f7a0508c7c2b9ffc521d4d545ee03718da70e9d6273b3b21 android.hardware.camera.device@3.2::ICameraDeviceCallback
-0fa3e1e64819283b8737fc4e5ab759f0cb4ac1a996e8a51cc4aa8025a457208e android.hardware.camera.device@3.2::ICameraDeviceSession
-030be3d2b159cbde7920485807140f6b6064ef4a5de4a40a6c4bc8d2c72f7cd3 android.hardware.camera.device@3.2::types
-5ba7947cee515d7a2359bfcbfb9678c1c3a768c288471919ac095b96ae6f3d40 android.hardware.camera.metadata@3.2::types
-f7e299d85033ac52d1095a35784fcfeaff43603f58c751e4153c85bbade3b330 android.hardware.camera.provider@2.4::ICameraProvider
-a501ca1aecd09f1b9fd70a9af84205430dbd49a808e8fa395d363b9902e6f58c android.hardware.camera.provider@2.4::ICameraProviderCallback
-7f5fe8f4f8a24037153c504d8b4d3313c2ce33d81c8c69fe5194ddd2d4080e72 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
-87beacc481897cf02fb1628d75e68133de6d74d4cffe582cda2f5e16bdd74516 android.hardware.configstore@1.0::types
-a5ae0fe8667f0b1af09b13e72d29600f4eb3853b257079c45a99b6f4a3360649 android.hardware.contexthub@1.0::IContexthub
-2ab3054c2d9302d8417ee7495353a2887fe338f913276f2eb41e80f11395ec2e android.hardware.contexthub@1.0::IContexthubCallback
-c3b2b37d561d31ea094411f251bf73bea334f4fe849a4390aef5e20bca6cadba android.hardware.contexthub@1.0::types
-df174c1871c864b4c79ca9f64aae7936d24a272eca3191a30458ca2b706dec79 android.hardware.drm@1.0::ICryptoFactory
-83639e90caeb996b0274e420de3cd556779de1ca48464b68eee799bef32b34cd android.hardware.drm@1.0::ICryptoPlugin
-1440cffdfaeb12830ac10ee6ffdb0f1083e701057b806df11fb4787b4c91e718 android.hardware.drm@1.0::IDrmFactory
-78ba33b108f620e6a0eec01ef654547e69a85754578ea4c9ef03ec205f16121c android.hardware.drm@1.0::IDrmPlugin
-701d9e51952172364e4ea70db9c397f08c3b4577ba33051f050a6cdd532de1b4 android.hardware.drm@1.0::IDrmPluginListener
-4238d62ad90df63aa338c6f1b6264c09c5a3706945d5c49d1189c0be1dc9e942 android.hardware.drm@1.0::types
-f07b1ee3ba11a2fc9f200421b2e1afb7c1854ee987000e45c987fb9507795055 android.hardware.dumpstate@1.0::IDumpstateDevice
-c9d318df7922bde3b265927b521ff5a965002826fc0cabfcaef52a56760f2d34 android.hardware.gatekeeper@1.0::IGatekeeper
-da13bd69282fb275767abb18704c57ff8038e6c139ad17157dc702810f70d06a android.hardware.gatekeeper@1.0::types
-37c7da4f823ec958dfa9c960e2d341c48f877e0bfa758f3fa9e2d9c1e1bd66d9 android.hardware.gnss@1.0::IAGnss
-7ec9afdb964bfb8369866913caf018f2636592885bcb558a65de2c5436ab4f60 android.hardware.gnss@1.0::IAGnssCallback
-d16e6a359be6963ea753d7138e84ecf2b93052097938938c4d36d7a47ea2e2ae android.hardware.gnss@1.0::IAGnssRil
-2f907708d74d94b1e121ed27651c9c72af65952d347b58ff07dac5d5d7a7f678 android.hardware.gnss@1.0::IAGnssRilCallback
-5ac7edad06d76064b882be161f3f9d9692a997ec72e9f36addb7fe8918f49992 android.hardware.gnss@1.0::IGnss
-b05c983c87c3376e145223688c3b541b5e11b827f211e38d5a31af1ca3a2e222 android.hardware.gnss@1.0::IGnssBatching
-4981d2d2c4e725c7544be0956099a91fc7bbc8048c563394158083fe924e651e android.hardware.gnss@1.0::IGnssBatchingCallback
-3cd22d92cc1f935150c5048310e84886f14eed2556e8f00636733d204045cc4f android.hardware.gnss@1.0::IGnssCallback
-175185a5eda87476193ca5461df75dd16d36664591e8130530dd8ef0eb2ddf6a android.hardware.gnss@1.0::IGnssConfiguration
-4542122b96fbf27101cb8222bafb76e7c8d032d977dd1058edd8e5881ca5752f android.hardware.gnss@1.0::IGnssDebug
-e6dd0c8416e523ab9cbd14d56ab6f016481a8aef3bc8a750051122d31075f6c7 android.hardware.gnss@1.0::IGnssGeofenceCallback
-f90e4ddc652706299d8e3d8ba18e0745c3bae9bf4d1be6bd06d9c1f50ec8d28a android.hardware.gnss@1.0::IGnssGeofencing
-9ea8987bb1089c8c5d7b67866575b866ef516045021d9efcc37c6352bce072a3 android.hardware.gnss@1.0::IGnssMeasurement
-cf20492673d6a423e4c2e87fdfb5a4c4a602431721978db852e246f258e25edb android.hardware.gnss@1.0::IGnssMeasurementCallback
-af85aa0f48ae99a39f4688c344e4419304f681f9af818a5c8d759286fc4418de android.hardware.gnss@1.0::IGnssNavigationMessage
-76b0874ea4c06b29f66418c59820f4286b3be9629cd872923d0dfbb602cd432d android.hardware.gnss@1.0::IGnssNavigationMessageCallback
-248bcf51da4273d64f367bf6877baef2feeaca365459842fd3c214a2dc6e0224 android.hardware.gnss@1.0::IGnssNi
-c781b7b125f68be5db8a8c3d412d526acdbdf77dcc592a4c0ed70b8ce4fe6c49 android.hardware.gnss@1.0::IGnssNiCallback
-c1142657de16fdb292a502372fe938614d65270ab8359217d6e13604fe4dbca4 android.hardware.gnss@1.0::IGnssXtra
-bd366b83d8d565d0e8bfabff3adfcab0259d75b4e2a9f8e1b91e11d1593a2ffb android.hardware.gnss@1.0::IGnssXtraCallback
-881bc2f94026784d194cffbff166c6e8bf911de4e02abe96fc7d89ec75b0574a android.hardware.gnss@1.0::types
-17971eb8a482893dadcfc16e0583f492d42a034ef95d9b0b709417af30838396 android.hardware.graphics.allocator@2.0::IAllocator
-60bf42a4898e4fb70dbd720b263aeafd7f35f5e1a5effeabb4d5d659878a5f18 android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer
-b8a75617b9ec12bea641f3a73d4025a33e8b9a2f9169dd46094af56adf9249c5 android.hardware.graphics.bufferqueue@1.0::IProducerListener
-4f6dedbcdd21c309dfc650acea81a096d6b242493ffe49c8d61bd3c43aad354e android.hardware.graphics.common@1.0::types
-b3aac6c3817f039964fcd62268274b3039e17bd7d0d5b40b4d1d1c7b19a1f866 android.hardware.graphics.composer@2.1::IComposer
-b19d00eb8a8b3b0034a0321f22e8f32162bf4c2aebbce6da22c025f56e459ea2 android.hardware.graphics.composer@2.1::IComposerCallback
-61ee43ffe6fb6dbe8b22dc17c51ff3d5ba703fc6029cba211f901f3d79c8a72d android.hardware.graphics.composer@2.1::IComposerClient
-1c98c2f5154345312ec054871792a2982ec5f3e2bc2abfb61a10c0b517978e20 android.hardware.graphics.composer@2.1::types
-a695898589e1ef15b2b2510f11edd6aafac9918d9cf8d74b4b6143b309dee542 android.hardware.graphics.mapper@2.0::IMapper
-28507d385a3dd224bf3c32f1bfd9f96092c4701b9c1cc66caa578fc3efc97877 android.hardware.graphics.mapper@2.0::types
-91e2ba3805c923f01fc1231ec9ff838942aee3346f2d7614ecc0caeadbe57ed4 android.hardware.health@1.0::IHealth
-1275aa2e8732909101b26aec49ed2285489e89d97b8610a8908b7868e35a3cc5 android.hardware.health@1.0::types
-3a8d3922e06e6d4f8e0befc6be78d0e9e07aed1585b3da6521bed406d25a9483 android.hardware.ir@1.0::IConsumerIr
-7090bd37912fcf723a12f4bc17783e3527577c4944805a028c296fd7a95bd682 android.hardware.ir@1.0::types
-cc7925a78c0ab022515f48840d3dae76f384ed3a1287abadcb461a5cd5396163 android.hardware.keymaster@3.0::IKeymasterDevice
-822998d7bb76f0cd719a409291434fcb56e6d50bc4780788bb157a3374d63b8c android.hardware.keymaster@3.0::types
-d4ed2f0e14f9e914d0b1275d2e0363192fe30aca9059c84edb5fad15995f9ec4 android.hardware.light@2.0::ILight
-d9584bfcaedd6e62cf337881748246b23e36cbc2bc3aa84c01b6a1e622061400 android.hardware.light@2.0::types
-16c0cf0f73de1e5208a95020c6c6474903e7094f76b2d782651afaca0e5fd86f android.hardware.media@1.0::types
-8bc2f5fdcad68856eb61a62fe4cc043fa064bb7f1dab95a71d1918ec1eef7b55 android.hardware.media.omx@1.0::IGraphicBufferSource
-0d3de9cd89d4718ea3b772f2d8b93be004feb3abb7e7dc5402e37047cc730d05 android.hardware.media.omx@1.0::IOmx
-32002e1c358c64de106c977a6dc6af7da27be4803a5bb66fd6f891a5ba0a1617 android.hardware.media.omx@1.0::IOmxBufferSource
-81ad8d8bb1cf6f41923cf11dd39354a8fe433db284a234cc675de7e75a82224c android.hardware.media.omx@1.0::IOmxNode
-494c0c8bf6065edc82ec127228ed19dd2243dc1c2f7d601c7c6be7b7015c1713 android.hardware.media.omx@1.0::IOmxObserver
-252c2fc50c78fd6de8365e5b60e5115119ace107db0b94b0b26815cbf3d2b64a android.hardware.media.omx@1.0::IOmxStore
-148c1b50b0958988373145ffdf5fa0e1b6534e0a2034a570e74b15c127cf7c5e android.hardware.media.omx@1.0::types
-c66902fe48d687ac6740a3e32ae55fb75532c48c36c6386461c2b4416ad2e0f1 android.hardware.memtrack@1.0::IMemtrack
-860bacd8b11a269c40567542b613fe4ca448d5cb4326d0058899e608e89dfca1 android.hardware.memtrack@1.0::types
-07ac2dc95270321ec7d4c33cd25e5085a057f47fe350d645af6f7a7a11e3cf57 android.hardware.nfc@1.0::INfc
-f2fe54426c07d67388d4774a60641ad4c0538f22eb6e1111722f231772655de6 android.hardware.nfc@1.0::INfcClientCallback
-9626fd18db113d709faf593a70caf19bd0980294d23c468c80c30186f9d298a6 android.hardware.nfc@1.0::types
-deee1dc4948f33af207e1008aba0f6cc07afb7900eab53f33192c8cac137eefc android.hardware.power@1.0::IPower
-efc83df3f962b93c7c0290d691d7d300dabe12683e2cde3591fb3c0beedce20f android.hardware.power@1.0::types
-9b5aa499ec3b4226f15f48f5ed08896e2fc0676f978c9e199c1da21daaf002a6 android.hardware.radio@1.0::IRadio
-5c8efbb9c451a59737ed2c6c20230aae4745839ca01d8088d6dcc9020e52d2c5 android.hardware.radio@1.0::IRadioIndication
-69f6b4b8ec40ca02ccc7bb8227a097135c20c00bd94c822e421cd9af1267252c android.hardware.radio@1.0::IRadioResponse
-de3ab9f73b1073cd677b19d886fb927e9381b30161a704712d2b30f875873f5c android.hardware.radio@1.0::ISap
-d183e406ef0897df2117a9dde384e8e6ea4fa6ab1c7f6f28e65b87011218c9ea android.hardware.radio@1.0::ISapCallback
-96986fbd22f0e6ca752e1fcdc0a64bda213995a81f5f36bc4faf3532d9306b97 android.hardware.radio@1.0::types
-00f70085d6fae1d482fb700a3fd42ed475384c95b51c9269b9ae5037b74ad4dd android.hardware.radio.deprecated@1.0::IOemHook
-06837b6d7e843cfa9cd20fed4070feca7a9b5c81a9ed643bf7d06803455a9816 android.hardware.radio.deprecated@1.0::IOemHookIndication
-6fd4874f0eddd4626a27658fd94fad526c317f3563439e79718bdb1a3a2309d5 android.hardware.radio.deprecated@1.0::IOemHookResponse
-6983a2cafe39d5c57dfdc1743055fb0f757a0df8c78e00423d5e1810836927e1 android.hardware.renderscript@1.0::IContext
-7f9417a0ccf78ea042ec7a8ac8e3750346d4d9d7e5ae01b1b35fde303f47c24d android.hardware.renderscript@1.0::IDevice
-fc6f325b266b32353f7d1534fbe58e0d368265a12b77fa396fb556e8c443f739 android.hardware.renderscript@1.0::types
-89585ff541c319de4091a5a0b687dd526ac81c6382ffd7b979a4164b3d7419a6 android.hardware.sensors@1.0::ISensors
-e04ab978fc28f4c515f4a75617dfda8607733a64f13666beeb0e604a07a39333 android.hardware.sensors@1.0::types
-5befc019cbe94953661e2cdb95e3cf64f5e565c29403e1c2daecc2be44e0a55c android.hardware.soundtrigger@2.0::ISoundTriggerHw
-d7ec5f612a5e0a59ea4f2b61317e208ff56dd50920fd4eb441e0cbc8f97e4f49 android.hardware.soundtrigger@2.0::ISoundTriggerHwCallback
-5bee9e70f7e5ec7ee252883b28f98f12b59960f4c2a0b4cc9a4526e4669ebcd4 android.hardware.soundtrigger@2.0::types
-97f1ec446043bc5a6645b74529a6276496bdb35e0aee41eda55cb92d51eb7802 android.hardware.thermal@1.0::IThermal
-84965a6908bceb4ef51546bf8731f309f1ea9d09a0177dcc7974132e523dd6d2 android.hardware.thermal@1.0::types
-938850621c3c5ef426a4b88e752ba99b3559037e782a3d938604f3aef5cc0f1b android.hardware.tv.cec@1.0::IHdmiCec
-e75b6eea711d36fac678bce072b3cec6544b27fa9f4cd903999404e5c110ca10 android.hardware.tv.cec@1.0::IHdmiCecCallback
-6e25f8dbfadb668e1d4ec80eb9acd95d8bc9e0a240c36d27e662adb440314b95 android.hardware.tv.cec@1.0::types
-0cafa3c8388e9631916d2d800f78decbcec2904f11415b32c71a31d9a51ebf79 android.hardware.tv.input@1.0::ITvInput
-dee83e5c864fbbee8f02448d0800be32f06856386b9f907bc5d952208c9434f9 android.hardware.tv.input@1.0::ITvInputCallback
-07aab30410b612381234dca6d453d4ab96f2e536368715717c6e28101b9851b5 android.hardware.tv.input@1.0::types
-4ef57499273f38bdbdd0c15e56ee7a4bc5f18a5644092170a531df3541d9e015 android.hardware.usb@1.0::IUsb
-4be7881e411ba42784bf5b7354c14ae0cf161004d39433aaecaab0d19ea99354 android.hardware.usb@1.0::IUsbCallback
-f7e6e747910a3cd0a35846141e3b990a6a612a297b2b70ccd5740b646a450a8c android.hardware.usb@1.0::types
-06ea64cc3565777f3b259e400ffa7100d07f3827ad9357b0c5d3c651384e5553 android.hardware.vibrator@1.0::IVibrator
-0fecd34ae64f32eff6aa615fd662349242c0b8b6e303ef05a7cb5776c732f413 android.hardware.vibrator@1.0::types
-4b962968a7df4ab104d1315d66a0a7348a713fecbb5d2c1b23688494458f37ce android.hardware.vr@1.0::IVr
-b9be36719a8ad534000a51ea07be91be94c405bf1e038ae825acf65087ffd378 android.hardware.wifi@1.0::IWifi
-ee0224ee18813506d9d6f13d8c8e4679f053c290a443a52a7c52a5d3c852262b android.hardware.wifi@1.0::IWifiApIface
-f3eecc489deb4c74892f59eb7adb769063bd5c354ac132b626a5f42b363d36bc android.hardware.wifi@1.0::IWifiChip
-a1b988377645a58e5e2542ca2bad4e17c21a4a389213d05de2f0e32d57b7d339 android.hardware.wifi@1.0::IWifiChipEventCallback
-5ed6760ce77e84bc6c49d1acb3f7d8117c9176b3f06514bc44ad3af84c80dcfe android.hardware.wifi@1.0::IWifiEventCallback
-6b9ad43a5efbe6ca214f751e22ce43cf5cd4d5d5f2cba80f24ccd3755a72401c android.hardware.wifi@1.0::IWifiIface
-ba5aa74f1ba714f0093864227923492808795bda6199c4ea0891322d27f8c931 android.hardware.wifi@1.0::IWifiNanIface
-325c94f3e1a565b56bbc74faddbd0ba7cb824f263dccf9dfff2daf62b86ed774 android.hardware.wifi@1.0::IWifiNanIfaceEventCallback
-c2c3f0372b41780fb6dfe83c022296806c2024d7046682fd201de5aa9b791c7a android.hardware.wifi@1.0::IWifiP2pIface
-766e9765f5c9c759b2a763c2288353fb5deff3389c2cc28f81d79c939704ce8b android.hardware.wifi@1.0::IWifiRttController
-72ab6f3e120cbf07aa6f8e87ca89112bdeb36b7fbb96bce5af3712323ab8b8e6 android.hardware.wifi@1.0::IWifiRttControllerEventCallback
-3b8093d39ef1e10e43c5538afbf5ff6e39b8d8168ebbe1998d993e89e25f14a5 android.hardware.wifi@1.0::IWifiStaIface
-7fbfc551c3e23c8b4398c3e16e452b516457e6921424a53474cbf373ca306fa9 android.hardware.wifi@1.0::IWifiStaIfaceEventCallback
-e20d5132d6d23e072c15de065b5e2aa13ff965031246a2c82581732bae56bf6d android.hardware.wifi@1.0::types
-f7e55c08187d8c855068a1ee3d0c8daeee7570292d96509c21a8756d4f5cfb9b android.hardware.wifi.supplicant@1.0::ISupplicant
-56b5c7267cb3d3337f44eb8b0b38ff4c6260dcc70e07687fcab94b1ccea8d159 android.hardware.wifi.supplicant@1.0::ISupplicantCallback
-35ba7bcdf18f24a866a7e5429548f06768bb20a257f75b10a397c4d825ef8438 android.hardware.wifi.supplicant@1.0::ISupplicantIface
-cda01008c06922fa37c1213e9bb831a109b3174532805616fb7161edc403866f android.hardware.wifi.supplicant@1.0::ISupplicantNetwork
-4907410338c5e8dbeec4b5edc2608ea323f5561945f8810af81810c47b019184 android.hardware.wifi.supplicant@1.0::ISupplicantP2pIface
-8b63f5efa2e3be3a7cb8a428760d82285a4ab79bcbdea6ef90aa547555e582d4 android.hardware.wifi.supplicant@1.0::ISupplicantP2pIfaceCallback
-56128f74560571b6777d59453f35c6b35693ee377e2a23c807708906928f09de android.hardware.wifi.supplicant@1.0::ISupplicantP2pNetwork
-2067c22197bca9743dab66a6f561a8a8375c67b4f76aed05f776839499bd4c8f android.hardware.wifi.supplicant@1.0::ISupplicantP2pNetworkCallback
-7752e1de93aaf5fed37011c219ac247069f6af320b0810daa98510584a10e7b4 android.hardware.wifi.supplicant@1.0::ISupplicantStaIface
-d781c8d7e7b3fe5cca8cf6e1d8806e770982ae5358c7816ed51b0f0ec272e70d android.hardware.wifi.supplicant@1.0::ISupplicantStaIfaceCallback
-b12ef0bdd8a4d247a8a6e960b227ed32383f2b0241f55d67fcea6eff6a6737fa android.hardware.wifi.supplicant@1.0::ISupplicantStaNetwork
-d8f0877ae1d321c1d884c7631dfe36cab0ec8a4b2863d4b687f85d3549a63bcc android.hardware.wifi.supplicant@1.0::ISupplicantStaNetworkCallback
-fe3c3c2f572b72f15f8594c538b0577bd5c28722c31879cfe6231330cddb6747 android.hardware.wifi.supplicant@1.0::types
-
-# ABI preserving changes to HALs during Android O MR1 (Initial Set)
-
-150a338ce11fcec70757c9675d83cf6a5d7b40d0c812741b91671fecce59eac9 android.hardware.broadcastradio@1.0::types
-dc7e6d4f537b9943e27edc4f86c5a03bb643b18f18f866f8c3c71c0ac4ea8cbc android.hardware.broadcastradio@1.0::types
-760485232f6cce07f8bb05e3475509956996b702f77415ee5bff05e2ec5a5bcc android.hardware.dumpstate@1.0::IDumpstateDevice
-78589343d8ee2e1b155acad3fbdc7fcbb6af94491aee968b2383c21627264f8b android.hardware.radio@1.0::IRadioResponse # Available in Android O, b/68061860
-e822cb7f4a1bdd45689c5e92ccd19a2201c20b771bd4b2ec1ae627e324591f9d android.hardware.radio@1.0::IRadioResponse
-6e69adb24d7c0b0ca3a54a38c49a5625b161b3f5d5f7d6fda0befdbbfc8e9e06 android.hardware.radio@1.0::IRadioResponse
-c2c50ec74c87a583c683b4493f8f9f2e454a8d41c57af5b3eb88823a999f0ea4 android.hardware.radio@1.0::IRadioResponse # Added for b/65230472 for Android O
-4922dd58e89a03181ed1c48a6e118e47633b73b11090bdfed5aa920d25a7592b android.hardware.radio@1.0::IRadioResponse # Added for b/65230472 for Android O DR
-28e929b453df3d9f5060af2764e6cdb123ddb893e3e86923c877f6ff7e5f02c9 android.hardware.wifi@1.0::types
-df1d7b27e644bfed0a4f606a8c44d35d45cafce82c7c648494c8a25c7cd4a949 android.hardware.wifi@1.0::types
-
-# HALs released in Android O MR1 (Initial Set)
-
-4b65763663a94a3920134011691f8fbb42ccb7b7795589efddc049a9106047d6 android.hardware.oemlock@1.0::IOemLock
-e02cd3722cb5e8fa51179f5defacb4f7866f903c9c7c51dc01a3148473a71525 android.hardware.oemlock@1.0::types
-224f9d22a367a0016f09b6dc676f53f1446697d9dc747163032329e5da552de5 android.hardware.power@1.1::IPower
-574fd9758b7cab4922c72cc5a9f36d1cd48ffd3425fdd776426653280d3d4138 android.hardware.power@1.1::types
-f79edf50a378a9c9bb737f93f205dab91b4c63ea49723afc6f856c138203ea81 android.hardware.radio@1.1::IRadio
-fcc5c8c88b85a9f63fba67d9e674da466c72a98ca287f343fb5721d098713f86 android.hardware.radio@1.1::IRadioIndication
-50f27e8c7ec009d5d4418b2ce8392b940bbf052ecc1d7251285f332485a5ba4e android.hardware.radio@1.1::IRadioResponse
-be981148c95c0089f3ae92854f0e7ae999d308e927db3e065f12a4fabe07852f android.hardware.radio@1.1::ISap
-d8d6bf7b4d36c04ce587df75953c3f723cfbe71c896c1aa8ab6478eae126723d android.hardware.radio@1.1::types
-d8aae01606bfd34bf2fb9a59cadc016f46f318e56cddb8f15a945c5b3c1222bc android.hardware.tetheroffload.config@1.0::IOffloadConfig
-447b00306bc95a7aafec1d660f6f3e9f76ac8bc0353193435e5579ab833da619 android.hardware.tetheroffload.control@1.0::IOffloadControl
-07658829339d75962016e00ed81b005ad29fca7ac12ad3bc3ccd86b08d94c2d3 android.hardware.tetheroffload.control@1.0::ITetheringOffloadCallback
-0df5b0178af15c53cdce8fcf8ca14035e8e08db4fa76fdc12009ddbe0b53626b android.hardware.tetheroffload.control@1.0::types
-b30ef02ef26ff804e2f6acf1201bc141b59e134e6a0338562284491102cb13e3 android.hardware.usb@1.1::IUsb
-13a580e35af01270a1e9774177c51db51d8672e6139ba00851e654e68a4d7dff android.hardware.usb@1.1::IUsbCallback
-f0ed667288908c08fced570bd1f3c4a0f236aa927938e805f0d9fece525da81e android.hardware.usb@1.1::types
-f95a1e85612f2d0d616eacd2eb63c52d10dfa889f165df57697c30e1f47b4785 android.hardware.vibrator@1.1::IVibrator
-246fb9d9e2b4800aeb0adc3cdbaa15d0321ebab54b7bd1ab87da5b67c7b0b064 android.hardware.vibrator@1.1::types
-9bc43413b80cd0c59a022e93da1448dcb82dd10c6dd31932df4659e4bdcb1368 android.hardware.weaver@1.0::IWeaver
-7728b0393a2ed9796537d4165c7d95407e9d8cb447a647b545fdfe06a28689e7 android.hardware.weaver@1.0::types
-bb7c96762d0aa3ddb874c8815bacdd3cbc8fb87ea2f82b928bc29e24a3593055 android.hardware.wifi.offload@1.0::IOffload
-c3354ab0d381a236c12dc486ad4b6bec28c979d26748b4661f12ede36f392808 android.hardware.wifi.offload@1.0::IOffloadCallback
-b18caefefcc765092412285d776234fcf213b73bdf07ae1b67a5f71b2d2464e3 android.hardware.wifi.offload@1.0::types
-c26473e2e4a00af43e28a0ddf9002e5062a7d0940429e5efb6e5513a8abcb75c android.hardware.wifi@1.1::IWifi
-b056e1defab4071584214584057d0bc73a613081bf1152590549649d4582c13c android.hardware.wifi@1.1::IWifiChip
-
-# ABI preserving changes to HALs during Android O MR1 (Final Set)
-09342041e17c429fce0034b9096d17849122111436a5f0053e7e59500e1cb89c android.hardware.media.omx@1.0::IOmxStore
-2d833aeed0cd1d59437aca210be590a953cf32bcb6683cd63d089762a643fb49 android.hardware.radio@1.0::IRadioResponse
-0a159f81359cd4f71bbe00972ee8403ea79351fb7c0cd48be72ebb3e424dbaef android.hardware.radio@1.0::types
-05aa3de6130a9788fdb6f4d3cc57c3ea90f067e77a5e09d6a772ec7f6bca33d2 android.hardware.radio@1.1::IRadioResponse
-
-# HALs released in Android O MR1 (Final Set)
-044cb039378b8a0e36f40ff1e6ce04dc0d339da02095f968d5062a051e99d108 android.hardware.broadcastradio@1.1::types
-c9699483f8cefe4f9b39b4b9609b76cab2dd1659a06188056b45797d337d4256 android.hardware.broadcastradio@1.1::IBroadcastRadio
-b5d62dcd663fc4fcc977b252af59b333043bdfe73de2f11fe6d6a8bf438a0f92 android.hardware.broadcastradio@1.1::IBroadcastRadioFactory
-bc7e054a6e93adebedff345aeed44549be89e6b1b6ffe071ff47a61de764b232 android.hardware.broadcastradio@1.1::ITuner
-e9139fc755be578693f17c8cd1e27c75f412cfc722157bab5bf03ee68896e31d android.hardware.broadcastradio@1.1::ITunerCallback
-63929c99e5755d9e09d9e0fd2527391fbb1609dda0508f5933b7943b92ae0fbc android.hardware.camera.device@3.3::types
-bbcfc3f748b078f6a66c4e228084a679d30bd61bfde8bb7a91efd507b91c1bfd android.hardware.camera.device@3.3::ICameraDeviceSession
-4a6998cd6793a3f9f03989c29d662589b1bc9d38826c6698c6c17864f7a814f5 android.hardware.cas@1.0::types
-0e656ba1bac11461a17096ef752b69d24b000d820ef5652f0150a0f9731d54c2 android.hardware.cas@1.0::ICas
-b80e1456b81f80032d0de7cb45652ac15af11e7474d520d757481ecaad796dff android.hardware.cas@1.0::ICasListener
-a432d6d9200248dc2126827bcd6cdea31dd65eff39b939f64585d27d915a5857 android.hardware.cas@1.0::IDescramblerBase
-86ba9c03978b79a742e990420bc5ced0673d25a939f82572996bef92621e2014 android.hardware.cas@1.0::IMediaCasService
-503da837d1a67cbdb7c08a033e927e5430ae1b159d98bf72c6336b4dcc5e76f5 android.hardware.cas.native@1.0::types
-619600109232ed64b827c8a11beed8070b1827ae464547d7aa146cf0473b4bca android.hardware.cas.native@1.0::IDescrambler
-93eb3757ceaf21590fa4cd1d4a7dfe3b3794af5396100a6d25630879352abce9 android.hardware.neuralnetworks@1.0::IDevice
-f66f9a38541bf92001d3adcce678cd7e3da2262124befb460b1c9aea9492813b android.hardware.neuralnetworks@1.0::IExecutionCallback
-953607822954435874f4b81686440a604e2a88cdd2d9164c6293f3d5772510d7 android.hardware.neuralnetworks@1.0::IPreparedModel
-73e03573494ba96f0e711ab7f1956c5b2d54c3da690cd7ecf4d6d0f287447730 android.hardware.neuralnetworks@1.0::IPreparedModelCallback
-246a56d37d57a47224562c9d077b4a2886ce6242b9311bd98a17325944c280d7 android.hardware.neuralnetworks@1.0::types
-f4945e397b5dea41bb64518dfde59be71245d8a125fd1e0acffeb57ac7b08fed android.hardware.thermal@1.1::IThermal
-c8bc853546dd55584611def2a9fa1d99f657e3366c976d2f60fe6b8aa6d2cb87 android.hardware.thermal@1.1::IThermalCallback
-
-# ABI preserving changes to HALs during Android P
-9e7a0b650d0e461ece2cfec0e1072abf8676f592b41a7fb48f01e88fc3c8f780 android.hardware.broadcastradio@1.0::types
-cf72ff5a52bfa4d08e9e1000cf3ab5952a2d280c7f13cdad5ab7905c08050766 android.hardware.camera.metadata@3.2::types
-3902efc42097cba55f0655aa389e052ea70164e99ced1a6d1ef53dafc13f7650 android.hardware.camera.provider@2.4::ICameraProvider
-6fa9804a17a8bb7923a56bd10493a5483c20007e4c9026fd04287bee7c945a8c android.hardware.gnss@1.0::IGnssCallback
-fb92e2b40f8e9d494e8fd3b4ac18499a3216342e7cff160714c3bbf3660b6e79 android.hardware.gnss@1.0::IGnssConfiguration
-251594ea9b27447bfa005ebd806e58fb0ae4aad84a69938129c9800ec0c64eda android.hardware.gnss@1.0::IGnssMeasurementCallback
-4e7169919d24fbe5573e5bcd683d0bd7abf553a4e6c34c41f9dfc1e12050db07 android.hardware.gnss@1.0::IGnssNavigationMessageCallback
-190ea4898809de6cf379afe318f5fa9564686157b24d9a2d7f5698b0c977d8b2 android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer
-25892789b50eb673506b6c5a2cdab5d9aa428d41608aab10280cc898538b524a android.hardware.graphics.composer@2.1::IComposerClient
-e205dd30f5ff99445b706a901de8ebc46c379e9d7c1921d6a327ed2082cfa83d android.hardware.graphics.composer@2.1::types
-a46251718abfada458dc64c41ce94915757bf6c87cfa2d9e99cfb01fa8e32331 android.hardware.graphics.mapper@2.0::IMapper
-bd33ac23c57b4a07632691d2191bc2c93930f57e62f4ccf459748fdaa5c0f480 android.hardware.graphics.mapper@2.0::types
-ad8a28ca3a5549fb9bc24cf5f80ac8f660cc27be885210d76266780aa52ddb8d android.hardware.keymaster@3.0::types
-5804ca86611d72e5481f022b3a0c1b334217f2e4988dad25730c42af2d1f4d1c android.hardware.neuralnetworks@1.0::IDevice
-12e8dca4ab7d8aadd0ef8f1b438021938e2396139e85db2ed65783b08800aa52 android.hardware.neuralnetworks@1.0::IExecutionCallback
-86b77e06da756a76aa3685be88765852dd982a86d8c90b8b4fc1130ed4184c8f android.hardware.neuralnetworks@1.0::types
-d4840db8efabdf1e4b344fc981cd36e5fe81a39aff6e199f6d06c1c8da413efd android.hardware.radio@1.0::types
-f96cbc59dfe16c8d0c2a7e06db24d8738a6328b6e90f7b8e1640ea2b4600debd android.hardware.radio@1.1::ISap
-2d86929794795e5c70f4fdb5073485fd05835c9c6f496116687c3d9f32e6df3e android.hardware.radio@1.2::ISap
-905a4af79c8329b39d8b11b08f015137216bb078b427b6986f32884a04bc1bec android.hardware.tv.cec@1.0::types
-aebcd9ff2da05c9d4c439916f40dfd219ba7629919007cb981ebf150064b4f82 android.hardware.usb@1.1::IUsb
-e29fb1941b40a990676f8e9c676a38761defd890b81a9c034608eb7ba6496023 android.hardware.wifi@1.0::IWifiP2pIface
-b280c4704dfcc548a9bf127b59b7c3578f460c50cce70a06b66fe0df8b27cff0 android.hardware.wifi@1.0::types
-
-# HALs released in Android P
-5860cf040a3d5d771967ecf648b00d06876a7120da985ee2b3e95d01f634dd20 android.hardware.audio@4.0::IDevice
-cf82a0249e918fdc657e189895e92d60af0491868477e82cdc30f6cab0ca2c65 android.hardware.audio@4.0::IDevicesFactory
-be3dc9baed45a0d330152eca3ca24fa419b375b20a41644c88d4fb46b72784d2 android.hardware.audio@4.0::IPrimaryDevice
-3e3acb70c4e6c7d578f511f4a44ee764ab9126f887a3bf65d523c42e40012bf6 android.hardware.audio@4.0::IStream
-d5de64e66b95f135dd42492250a309134b8227203ef3524440798c66b6f5a392 android.hardware.audio@4.0::IStreamIn
-888ac906461327fa0bd93854d5109be8c292a33afdb467164826970a8bd5b789 android.hardware.audio@4.0::IStreamOut
-15f6ae78e73344c8e7d68847ef03caec64fcd9f951bbcf59957d1712c247fcff android.hardware.audio@4.0::IStreamOutCallback
-61f0eaa4d08547d039e9b1dd7c82abe2c004286d1b9b8153c2491ff46a8a63ca android.hardware.audio@4.0::types
-5d47a2ad2c136b8aba067dd45bb10d0ad390dd76340764154f580658f98f4fe6 android.hardware.audio.common@4.0::types
-b04b6b364938b80008e61fa2e318bc299622433e57c2e1f6cfba332a3f6e3f15 android.hardware.audio.effect@4.0::IAcousticEchoCancelerEffect
-1c17d4ece5c8ba3f7a646a305ee0dd109b0d51372e1bd585812e513cd40e1852 android.hardware.audio.effect@4.0::IAutomaticGainControlEffect
-34174259fe6fbb1bb14e7103e097f2f25529271a676687845b2f55d6d0d9d617 android.hardware.audio.effect@4.0::IBassBoostEffect
-7a18e9bd0163f3784448f6e24be0db75f877e2f0f9bd0d7ec427f1c34b382c0b android.hardware.audio.effect@4.0::IDownmixEffect
-bac81bffbe2661d5b6839087d2dd3a27eded66e60c6c76d35c68d54014cd5c06 android.hardware.audio.effect@4.0::IEffect
-65f0bcf9e498b26f3266ad10cf513a6c2b5906cc49f9db4bc5c7d3ba11a72e05 android.hardware.audio.effect@4.0::IEffectBufferProviderCallback
-5a746e81175489eb2371b88864c36c9bb63bc64ef799fae74cd96003b013c0d1 android.hardware.audio.effect@4.0::IEffectsFactory
-839980c7c5be79da6b95fdb9354a62b04407b4b084749b7a21d2c340773d7638 android.hardware.audio.effect@4.0::IEnvironmentalReverbEffect
-2805fbdac7cff050a1c095b9276bb41ac02a3b7b354336817487eb9a4b6bb462 android.hardware.audio.effect@4.0::IEqualizerEffect
-a91b547f5922f39fe4231d97fac1c3825c1c1b0c8ef7a5136689ceed37e8bfe9 android.hardware.audio.effect@4.0::ILoudnessEnhancerEffect
-1145f5b921ddec184fda5bdc87487b46f2a89cd9f42cc882bbb3a54f4ac80466 android.hardware.audio.effect@4.0::INoiseSuppressionEffect
-3661fa0623056922fdc4235ac5a9c91a2d066ab6f1ab4297e3b240fe302ba500 android.hardware.audio.effect@4.0::IPresetReverbEffect
-e88e520f8c98a62fccd8d5316c6687808f775de145d1405a7a9a66587ee6a001 android.hardware.audio.effect@4.0::IVirtualizerEffect
-fe28829dab10d171783b79ac9cc45412739f8ff275e90228d7c6370ef189b859 android.hardware.audio.effect@4.0::IVisualizerEffect
-21c8a702579356480236c6851b5b2c16b9bd369ce12bdd6ffdc4626a89f34f73  android.hardware.audio.effect@4.0::types
-42a06dc288f61b0690580f3d37b30b663c31d74d50bb58d0772386b550d5faab android.hardware.authsecret@1.0::IAuthSecret
-32cc50cc2a7658ec613c0c2dd2accbf6a05113b749852879e818b8b7b438db19 android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioHost
-ff4be64d7992f8bec97dff37f35450e79b3430c61f85f54322ce45bef229dc3b android.hardware.bluetooth.a2dp@1.0::IBluetoothAudioOffload
-27f22d2e873e6201f9620cf4d8e2facb25bd0dd30a2b911e441b4600d560fa62 android.hardware.bluetooth.a2dp@1.0::types
-3d8ed67d807e9f15d0708390a416bee00920f6a22196c104cc9e443c8d217df8 android.hardware.broadcastradio@2.0::IAnnouncementListener
-44017c42e6f4d8cb30f07eb1da04540a98736a336ac28c7e0ed2e69e1589f8d1 android.hardware.broadcastradio@2.0::IBroadcastRadio
-e5f4960290b4f3089163dd43251e1a032c81e9bdb796e75a87fc7c5810c262b3 android.hardware.broadcastradio@2.0::ICloseHandle
-af24b87ca8b8f02fcde205e47db6a9609fc7e9d77d73e694ec8f9c508ca19575 android.hardware.broadcastradio@2.0::ITunerCallback
-d70464c517a4a1b5167730843775a97f455102919e945b04f717b9da390c0f39 android.hardware.broadcastradio@2.0::ITunerSession
-2afa59ebf8145e7fbc090cf49605c27280c07d4178d47cd7f9d82b3b95a47af0 android.hardware.broadcastradio@2.0::types
-4fb0725c36ed4f77a42b42e3f18d8b5f7919cb62b90098b23143a555aa7dd96d android.hardware.camera.device@3.4::ICameraDeviceCallback
-812fa66aa10ba0cba27cfddc2fd7f0ee27a8ab65a1f15aa79fdad97d403e6a14 android.hardware.camera.device@3.4::ICameraDeviceSession
-cc288f1f78d1e643eb3d3dbc16e1401d44033d8e6856761f5156814a29986ec7 android.hardware.camera.device@3.4::types
-f9278c8beb9d42d96e26d73ecabe1dff1d7e2fb301ab7f737d93e5ffae8d3312 android.hardware.camera.metadata@3.3::types
-f858091b10f7d5927be60573c06df4805275d37226bbb41a732190bfb81457ec android.hardware.configstore@1.1::ISurfaceFlingerConfigs
-5b0fb9842f8b0eb3730b93c30a7925290ab44763ab86bb493bfa58d0f2eeb369 android.hardware.configstore@1.1::types
-1a46aeae45b7a0e47f79b7207300532986f9d9cd7060779afc7a529f54d712ab android.hardware.confirmationui@1.0::IConfirmationResultCallback
-6d8347ff3cd7de471065ac3e8e68385073630cdeebe9f8fa58cb91cf44436c95 android.hardware.confirmationui@1.0::IConfirmationUI
-a3ff916784dce87a56c757ab5c86433f0cdf562280999a5f978a6e8a0f3f19e7 android.hardware.confirmationui@1.0::types
-1fbf2d7e383632216aaaa1d972a21a618f55659263d2e6f0b309e3cb323b4b63 android.hardware.drm@1.1::ICryptoFactory
-7877ff8e4c1e48b825e6e5e66d050288e5656ed535c61cc7830a92ed4a9e1990 android.hardware.drm@1.1::IDrmFactory
-fef2f0ebde7704548fb203df46673ceb342272fc4fa9d0af25a980d2584a36e7 android.hardware.drm@1.1::IDrmPlugin
-5047a346ecce239404b9020959f60dd467318e9c17b290a6386bc3894df62c3c android.hardware.drm@1.1::types
-a830336ac8627d6432cfafb1b884343ad9f885dee0a5323e380e6d3c519156b8 android.hardware.gnss@1.1::IGnss
-8ad55bc35bb3a83e65c018bdfde7ae5ebc749ff2bf6b79412ded0bc6c89b97d8 android.hardware.gnss@1.1::IGnssCallback
-3c5183d7506010be57e0f748e3640fc2ded1ba955784b6256ba427f4c399591c android.hardware.gnss@1.1::IGnssConfiguration
-1a07d1383e847c3deb696ec7a2c9e33b9683772945660448a010b18063da67a4 android.hardware.gnss@1.1::IGnssMeasurement
-83e7a10ff3702147bd7ffa04567b20d407a3b16bbb7705644af44d919afe9103 android.hardware.gnss@1.1::IGnssMeasurementCallback
-0b96e0254e2168cfecb30c1ed5fb42681652cc00faa68c6e07568fafe64d1d50 android.hardware.graphics.common@1.1::types
-7d2cef99c838fb58038de8bbfd3cdb76ff4797241987077721715297f8d45e34 android.hardware.graphics.common@1.1::types # b/78135149
-d9b40a5b09962a5a0780b10fe33a4e607e69e2e088fc83de88a584115b7cb1c0 android.hardware.graphics.composer@2.2::IComposer
-a2f183f7fcc79aabedaef11095ab223aac0ed5ef984d850893872515e7f560c7 android.hardware.graphics.composer@2.2::IComposerClient
-dd83be076b6b3f10ed62ab34d8c8b95f2415961fb785200eb842e7bfb2b0ee92 android.hardware.graphics.mapper@2.1::IMapper
-675682dd3007805c985eaaec91612abc88f4c25b3431fb84070b7584a1a741fb android.hardware.health@2.0::IHealth
-434c4c32c00b0e54bb05e40c79503208b40f786a318029a2a4f66e34f10f2a76 android.hardware.health@2.0::IHealthInfoCallback
-c9e498f1ade5e26f00d290b4763a9671ec6720f915e7d592844b62e8cb1f9b5c android.hardware.health@2.0::types
-201f9723353fdbd40bf3705537fb7e015e4c399879425e68688fe0f43606ea4d android.hardware.keymaster@4.0::IKeymasterDevice
-1b7d2090c0a28b229d37c4b96160796b1f0d703950ac6ccc163fccd280830503 android.hardware.keymaster@4.0::types
-6d5c646a83538f0f9d8438c259932509f4353410c6c76e56db0d6ca98b69c3bb android.hardware.media.bufferpool@1.0::IAccessor
-b8c7ed58aa8740361e63d0ce9e7c94227572a629f356958840b34809d2393a7c android.hardware.media.bufferpool@1.0::IClientManager
-4a2c0dc82780e6c90731725a103feab8ab6ecf85a64e049b9cbd2b2c61620fe1 android.hardware.media.bufferpool@1.0::IConnection
-6aef1218e5949f867b0104752ac536c1b707222a403341720de90141df129e3e android.hardware.media.bufferpool@1.0::types
-7698dc2382a2eeb43541840e3ee624f34108efdfb976b2bfa7c13ef15fb8c4c4 android.hardware.neuralnetworks@1.1::IDevice
-72cc6126632456e8fbb8776fe50150c3c4dd5d09145653193affb70785211dfa android.hardware.neuralnetworks@1.1::types
-8d3d86da0bfa4bf070970d8303c659f67f35d670c287d45a3f542e4fedadd578 android.hardware.nfc@1.1::INfc
-e85f566698d2a2c28100e264fcf2c691a066756ddf8dd341d009ff50cfe10614 android.hardware.nfc@1.1::INfcClientCallback
-5e278fcaa3287d397d8eebe1c22aaa28150f5caae1cf9381cd6dc32cb37899c5 android.hardware.nfc@1.1::types
-163e115e833fc1d77cdd4a8cf0c833bb8b8d74fe35c880fe693101d17774926f android.hardware.power@1.2::IPower
-7899b9305587b2d5cd74a3cc87e9090f58bf4ae74256ce3ee36e7ec011822840 android.hardware.power@1.2::types
-5a464e6db53fad223986d655028a18185b73db8e2bfa9663f9042c9623eb0aa0 android.hardware.power@1.3::IPower
-a54a28d39b892d27a3cb06829181c038edcdd9e8eef359543b01e4313ae59aa0 android.hardware.power@1.3::types
-ab132c990a62f0aca35871c092c22fb9c85d478e22124ef6a4d0a2302da76a9f android.hardware.radio@1.2::IRadio
-cda752aeabaabc20486a82ac57a3dd107785c006094a349bc5e224e8aa22a17c android.hardware.radio@1.2::IRadioIndication
-da8c6ae991c6a4b284cc6e445332e064e28ee8a09482ed5afff9d159ec6694b7 android.hardware.radio@1.2::IRadioResponse
-b65332996eb39ba63300a1011404141fa59ce5c252bc17afae637be6eeca5f55 android.hardware.radio@1.2::ISap
-a9361522cc97ef66209d39ba324095b2f08344054bb4d3481e803eee0480623a android.hardware.radio@1.2::types
-87385469cf4409f0f33b01508e7a477cf71f2a11e466dd7e3ab5971a1baaa72b android.hardware.radio.config@1.0::IRadioConfig
-228b2ee3c8c276c9f0afad2dc313ca3d6bbd9e482ddf313c7204c60ad9b636ab android.hardware.radio.config@1.0::IRadioConfigIndication
-a2e9b7aa09f79426f765838174e04b6f9a3e6c8b76b923fc1705632207bad44b android.hardware.radio.config@1.0::IRadioConfigResponse
-4307696b64ded9bd8de06887f9dfc533e875c4e0d83b8008df4d705164bde0b1 android.hardware.radio.config@1.0::types
-bd7699f07ba5392310fefd33ea964e01f4f4a66015146845c85055004823cc81 android.hardware.secure_element@1.0::ISecureElement
-a65aa82bbe48d81a9ae9e86247bb1b89fd2d3138d4053d7a5b716c71149b7dee android.hardware.secure_element@1.0::ISecureElementHalCallback
-2984c069f48ba35cd1bf49b0e17daad0d418fef52cb7a4a84dba0043114063d4 android.hardware.secure_element@1.0::types
-b4f507b4dc9b5cd5f0e4445926acb7d94525ae60dc307b3951142283632207b6 android.hardware.soundtrigger@2.1::ISoundTriggerHw
-92c2cc0f06ef744c5bda21f1d660258f7937203109b493eee22c3f3e2dbb0d3e android.hardware.soundtrigger@2.1::ISoundTriggerHwCallback
-8ddfa7542772cc7bca19972b2d856264efa31914bfd098aeb7c2079d950194cb android.hardware.usb.gadget@1.0::IUsbGadget
-ad0a620cda08f01b151c30cb7afa23b0637cc84340cf8dec00ac8e32cf54a8db android.hardware.usb.gadget@1.0::IUsbGadgetCallback
-51fc20f223561ac3a32ace3217837ef3860265bd91c8b7ae3859532caef9bc39 android.hardware.usb.gadget@1.0::types
-1bfc9fd9536ed09f04bcaf222a332bc919f1565d4d08bddccdebe1bfca8f01b5 android.hardware.vibrator@1.2::IVibrator
-a0aefa29881235c21e4761d15c55edc35ef85c2e0d9e01d0966176d1dbf5f811 android.hardware.vibrator@1.2::types
-8bc75a0dfac15c6f87ffec950b76c7d7de30d516b54e8e0b1f3c0ff9c7c6873b android.hardware.wifi@1.2::IWifi
-780c16fdeda13b779d993953a67f7ca578c938a172a9424c1c715ae81bc40fd7 android.hardware.wifi@1.2::IWifiChip
-167af870fdb87e1cbbaa0fa62ef35e1031caad20dd1ba695983dedb1e9993486 android.hardware.wifi@1.2::IWifiChipEventCallback
-8c7ef32fc78d5ec6e6956de3784cc2c6f42614b5272d2e461f6d60534ba38ec2 android.hardware.wifi@1.2::IWifiNanIface
-1e6074efad9da333803fb7c1acdb719d51c30b2e1e92087b0420341631c30b60 android.hardware.wifi@1.2::IWifiNanIfaceEventCallback
-f5682dbf19f712bef9cc3faa5fe3dc670b6ffbcb62a147a1d86b9d43574cd83f android.hardware.wifi@1.2::IWifiStaIface
-6db2e7d274be2dca9bf3087afd1f774a68c99d2b4dc7eeaf41690e5cebcbef7a android.hardware.wifi@1.2::types
-ee08280de21cb41e3ec26d6ed636c701b7f70516e71fb22f4fe60a13e603f406 android.hardware.wifi.hostapd@1.0::IHostapd
-b2479cd7a417a1cf4f3a22db4e4579e21bac38fdcaf381e2bf10176d05397e01 android.hardware.wifi.hostapd@1.0::types
-e362203b941f18bd4cba29a62adfa02453ed00d6be5b72cdb6c4d7e0bf394a40 android.hardware.wifi.supplicant@1.1::ISupplicant
-21757d0e5dd4b7e4bd981a4a20531bca3c32271ad9777b17b74eb5a1ea508384 android.hardware.wifi.supplicant@1.1::ISupplicantStaIface
-cd4330c3196bda1d642a32abfe23a7d64ebfbda721940643af6867af3b3f0aa9 android.hardware.wifi.supplicant@1.1::ISupplicantStaIfaceCallback
-10ff2fae516346b86121368ce5790d5accdfcb73983246b813f3d488b66db45a android.hardware.wifi.supplicant@1.1::ISupplicantStaNetwork
diff --git a/prebuilt_hashes/Android.bp b/prebuilt_hashes/Android.bp
deleted file mode 100644
index 4692b76..0000000
--- a/prebuilt_hashes/Android.bp
+++ /dev/null
@@ -1,30 +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.
-
-python_binary_host {
-    name: "dump_hals_for_release",
-
-    srcs: [
-        "dump_hals_for_release.py",
-    ],
-
-    version: {
-        py2: {
-            enabled: true,
-        },
-        py3: {
-            enabled: false,
-        },
-    },
-}
diff --git a/prebuilt_hashes/dump_hals_for_release.py b/prebuilt_hashes/dump_hals_for_release.py
deleted file mode 100755
index e9ed4c2..0000000
--- a/prebuilt_hashes/dump_hals_for_release.py
+++ /dev/null
@@ -1,136 +0,0 @@
-#!/usr/bin/env python
-#
-# 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.
-#
-
-"""
-Dump new HIDL types that are introduced in each dessert release.
-"""
-
-from __future__ import print_function
-
-import argparse
-import collections
-import json
-import os
-import re
-
-class Globals:
-    pass
-
-class Constants:
-    CURRENT = 'current'
-    HAL_PATH_PATTERN = r'/((?:[a-zA-Z_][a-zA-Z0-9_]*/)*)(\d+\.\d+)/([a-zA-Z_][a-zA-Z0-9_]*).hal'
-    CURRENT_TXT_PATTERN = r'(?:.*/)?([0-9]+|current).txt'
-
-def trim_trailing_comments(line):
-    idx = line.find('#')
-    if idx < 0: return line
-    return line[0:idx]
-
-def strip_begin(s, prefix):
-    if s.startswith(prefix):
-        return strip_begin(s[len(prefix):], prefix)
-    return s
-
-def strip_end(s, suffix):
-    if s.endswith(suffix):
-        return strip_end(s[0:-len(suffix)], suffix)
-    return s
-
-def get_interfaces(file_name):
-    with open(file_name) as file:
-        for line in file:
-            line_tokens = trim_trailing_comments(line).strip().split()
-            if not line_tokens:
-                continue
-            assert len(line_tokens) == 2, \
-                "Unrecognized line in file {}:\n{}".format(file_name, line)
-            yield line_tokens[1]
-
-def api_level_to_int(api_level):
-    try:
-        if api_level == Constants.CURRENT: return float('inf')
-        return int(api_level)
-    except ValueError:
-        return None
-
-def get_interfaces_from_package_root(package, root):
-    root = strip_end(root, '/')
-    for dirpath, _, filenames in os.walk(root, topdown=False):
-        dirpath = strip_begin(dirpath, root)
-        for filename in filenames:
-            filepath = os.path.join(dirpath, filename)
-            mo = re.match(Constants.HAL_PATH_PATTERN, filepath)
-            if not mo:
-                continue
-            yield '{}.{}@{}::{}'.format(
-                package, mo.group(1).strip('/').replace('/', '.'), mo.group(2), mo.group(3))
-
-def filter_out(iterable):
-    return iterable if not Globals.filter_out else filter(
-        lambda s: all(re.search(pattern, s) is None for pattern in Globals.filter_out),
-        iterable)
-
-def main():
-    parser = argparse.ArgumentParser(description=__doc__)
-    parser.add_argument('--pretty', help='Print pretty JSON', action='store_true')
-    parser.add_argument('--package-root', metavar='PACKAGE:PATH', nargs='*',
-        help='package root of current directory, e.g. android.hardware:hardware/interfaces')
-    parser.add_argument('--filter-out', metavar='REGEX', nargs='*',
-        help='A regular expression that filters out interfaces.')
-    parser.add_argument('hashes', metavar='FILE', nargs='*',
-        help='Locations of current.txt for each release.')
-    parser.parse_args(namespace=Globals)
-
-    interfaces_for_level = dict()
-
-    for filename in Globals.hashes or tuple():
-        mo = re.match(Constants.CURRENT_TXT_PATTERN, filename)
-        assert mo is not None, \
-            'Input hash file names must have the format {} but is {}'.format(Constants.CURRENT_TXT_PATTERN, filename)
-
-        api_level = mo.group(1)
-        assert api_level_to_int(api_level) is not None
-
-        if api_level not in interfaces_for_level:
-            interfaces_for_level[api_level] = set()
-        interfaces_for_level[api_level].update(filter_out(get_interfaces(filename)))
-
-    for package_root in Globals.package_root or tuple():
-        tup = package_root.split(':')
-        assert len(tup) == 2, \
-            '--package-root must have the format PACKAGE:PATH, but is {}'.format(package_root)
-        if Constants.CURRENT not in interfaces_for_level:
-            interfaces_for_level[Constants.CURRENT] = set()
-        interfaces_for_level[Constants.CURRENT].update(filter_out(get_interfaces_from_package_root(*tup)))
-
-    seen_interfaces = set()
-    new_interfaces_for_level = collections.OrderedDict()
-    for level, interfaces in sorted(interfaces_for_level.items(), key=lambda tup: api_level_to_int(tup[0])):
-        if level != Constants.CURRENT:
-            removed_interfaces = seen_interfaces - interfaces
-            assert not removed_interfaces, \
-                "The following interfaces are removed from API level {}:\n{}".format(
-                    level, removed_interfaces)
-        new_interfaces_for_level[level] = sorted(interfaces - seen_interfaces)
-        seen_interfaces.update(interfaces)
-
-    print(json.dumps(new_interfaces_for_level,
-        separators=None if Globals.pretty else (',',':'),
-        indent=4 if Globals.pretty else None))
-
-if __name__ == '__main__':
-    main()
diff --git a/radio/1.0/Android.bp b/radio/1.0/Android.bp
index 6765b4d..f3cc2e0 100644
--- a/radio/1.0/Android.bp
+++ b/radio/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.radio@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IRadio.hal",
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_cell_broadcast.cpp b/radio/1.0/vts/functional/radio_hidl_hal_cell_broadcast.cpp
index 125ea0c..8e6cf86 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_cell_broadcast.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_cell_broadcast.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <android-base/logging.h>
 #include <radio_hidl_hal_utils_v1_0.h>
 
 using namespace ::android::hardware::radio::V1_0;
@@ -22,6 +23,7 @@
  * Test IRadio.setGsmBroadcastConfig() for the response returned.
  */
 TEST_P(RadioHidlTest, setGsmBroadcastConfig) {
+    LOG(DEBUG) << "setGsmBroadcastConfig";
     serial = GetRandomSerialNumber();
 
     // Create GsmBroadcastSmsConfigInfo #1
@@ -79,12 +81,14 @@
                                       RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "setGsmBroadcastConfig finished";
 }
 
 /*
  * Test IRadio.getGsmBroadcastConfig() for the response returned.
  */
 TEST_P(RadioHidlTest, getGsmBroadcastConfig) {
+    LOG(DEBUG) << "getGsmBroadcastConfig";
     serial = GetRandomSerialNumber();
 
     radio->getGsmBroadcastConfig(serial);
@@ -99,12 +103,14 @@
             {RadioError::NONE, RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "getGsmBroadcastConfig finished";
 }
 
 /*
  * Test IRadio.setCdmaBroadcastConfig() for the response returned.
  */
 TEST_P(RadioHidlTest, setCdmaBroadcastConfig) {
+    LOG(DEBUG) << "setCdmaBroadcastConfig";
     serial = GetRandomSerialNumber();
 
     CdmaBroadcastSmsConfigInfo cbSmsConfig;
@@ -126,12 +132,14 @@
                                      {RadioError::NONE, RadioError::INVALID_MODEM_STATE},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "setCdmaBroadcastConfig finished";
 }
 
 /*
  * Test IRadio.getCdmaBroadcastConfig() for the response returned.
  */
 TEST_P(RadioHidlTest, getCdmaBroadcastConfig) {
+    LOG(DEBUG) << "getCdmaBroadcastConfig";
     serial = GetRandomSerialNumber();
 
     radio->getCdmaBroadcastConfig(serial);
@@ -144,12 +152,14 @@
         ASSERT_TRUE(
             CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "getCdmaBroadcastConfig finished";
 }
 
 /*
  * Test IRadio.setCdmaBroadcastActivation() for the response returned.
  */
 TEST_P(RadioHidlTest, setCdmaBroadcastActivation) {
+    LOG(DEBUG) << "setCdmaBroadcastActivation";
     serial = GetRandomSerialNumber();
     bool activate = false;
 
@@ -164,12 +174,14 @@
                                      {RadioError::NONE, RadioError::INVALID_ARGUMENTS},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "setCdmaBroadcastActivation finished";
 }
 
 /*
  * Test IRadio.setGsmBroadcastActivation() for the response returned.
  */
 TEST_P(RadioHidlTest, setGsmBroadcastActivation) {
+    LOG(DEBUG) << "setGsmBroadcastActivation";
     serial = GetRandomSerialNumber();
     bool activate = false;
 
@@ -186,4 +198,5 @@
              RadioError::INVALID_STATE, RadioError::OPERATION_NOT_ALLOWED},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "setGsmBroadcastActivation finished";
 }
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_data.cpp b/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
index d937d74..e3ee9d4 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <android-base/logging.h>
 #include <radio_hidl_hal_utils_v1_0.h>
 
 using namespace ::android::hardware::radio::V1_0;
@@ -22,6 +23,7 @@
  * Test IRadio.getDataRegistrationState() for the response returned.
  */
 TEST_P(RadioHidlTest, getDataRegistrationState) {
+    LOG(DEBUG) << "getDataRegistrationState";
     serial = GetRandomSerialNumber();
 
     radio->getDataRegistrationState(serial);
@@ -94,12 +96,14 @@
             }
         }
     }
+    LOG(DEBUG) << "getDataRegistrationState finished";
 }
 
 /*
  * Test IRadio.setupDataCall() for the response returned.
  */
 TEST_P(RadioHidlTest, setupDataCall) {
+    LOG(DEBUG) << "setupDataCall";
     serial = GetRandomSerialNumber();
 
     RadioTechnology radioTechnology = RadioTechnology::LTE;
@@ -142,12 +146,14 @@
                                       RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ABSENT},
                                      CHECK_OEM_ERROR));
     }
+    LOG(DEBUG) << "setupDataCall finished";
 }
 
 /*
  * Test IRadio.deactivateDataCall() for the response returned.
  */
 TEST_P(RadioHidlTest, deactivateDataCall) {
+    LOG(DEBUG) << "deactivateDataCall";
     serial = GetRandomSerialNumber();
     int cid = 1;
     bool reasonRadioShutDown = false;
@@ -164,12 +170,14 @@
                                       RadioError::SIM_ABSENT, RadioError::INVALID_CALL_ID},
                                      CHECK_OEM_ERROR));
     }
+    LOG(DEBUG) << "deactivateDataCall finished";
 }
 
 /*
  * Test IRadio.getDataCallList() for the response returned.
  */
 TEST_P(RadioHidlTest, getDataCallList) {
+    LOG(DEBUG) << "getDataCallList";
     serial = GetRandomSerialNumber();
 
     radio->getDataCallList(serial);
@@ -183,12 +191,14 @@
             radioRsp->rspInfo.error,
             {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ABSENT}));
     }
+    LOG(DEBUG) << "getDataCallList finished";
 }
 
 /*
  * Test IRadio.setInitialAttachApn() for the response returned.
  */
 TEST_P(RadioHidlTest, setInitialAttachApn) {
+    LOG(DEBUG) << "setInitialAttachApn";
     serial = GetRandomSerialNumber();
 
     DataProfileInfo dataProfileInfo;
@@ -226,12 +236,14 @@
                                       RadioError::SUBSCRIPTION_NOT_AVAILABLE},
                                      CHECK_OEM_ERROR));
     }
+    LOG(DEBUG) << "setInitialAttachApn finished";
 }
 
 /*
  * Test IRadio.setDataAllowed() for the response returned.
  */
 TEST_P(RadioHidlTest, setDataAllowed) {
+    LOG(DEBUG) << "setDataAllowed";
     serial = GetRandomSerialNumber();
     bool allow = true;
 
@@ -244,12 +256,14 @@
     if (cardStatus.cardState == CardState::ABSENT) {
         EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
+    LOG(DEBUG) << "setDataAllowed finished";
 }
 
 /*
  * Test IRadio.setDataProfile() for the response returned.
  */
 TEST_P(RadioHidlTest, setDataProfile) {
+    LOG(DEBUG) << "setDataProfile";
     serial = GetRandomSerialNumber();
 
     // Create a dataProfileInfo
@@ -289,4 +303,5 @@
                                      {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
                                       RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED}));
     }
+    LOG(DEBUG) << "setDataProfile finished";
 }
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp b/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp
index 9568524..8a977a9 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_icc.cpp
@@ -14,22 +14,26 @@
  * limitations under the License.
  */
 
+#include <android-base/logging.h>
 #include <radio_hidl_hal_utils_v1_0.h>
 
 /*
  * Test IRadio.getIccCardStatus() for the response returned.
  */
 TEST_P(RadioHidlTest, getIccCardStatus) {
+    LOG(DEBUG) << "getIccCardStatus";
     EXPECT_LE(cardStatus.applications.size(), (unsigned int)RadioConst::CARD_MAX_APPS);
     EXPECT_LT(cardStatus.gsmUmtsSubscriptionAppIndex, (int)RadioConst::CARD_MAX_APPS);
     EXPECT_LT(cardStatus.cdmaSubscriptionAppIndex, (int)RadioConst::CARD_MAX_APPS);
     EXPECT_LT(cardStatus.imsSubscriptionAppIndex, (int)RadioConst::CARD_MAX_APPS);
+    LOG(DEBUG) << "getIccCardStatus finished";
 }
 
 /*
  * Test IRadio.supplyIccPinForApp() for the response returned
  */
 TEST_P(RadioHidlTest, supplyIccPinForApp) {
+    LOG(DEBUG) << "supplyIccPinForApp";
     serial = GetRandomSerialNumber();
 
     // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -49,12 +53,14 @@
                 {RadioError::PASSWORD_INCORRECT, RadioError::REQUEST_NOT_SUPPORTED}));
         }
     }
+    LOG(DEBUG) << "supplyIccPinForApp finished";
 }
 
 /*
  * Test IRadio.supplyIccPukForApp() for the response returned.
  */
 TEST_P(RadioHidlTest, supplyIccPukForApp) {
+    LOG(DEBUG) << "supplyIccPukForApp";
     serial = GetRandomSerialNumber();
 
     // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -73,12 +79,14 @@
                                                                    RadioError::INVALID_SIM_STATE}));
         }
     }
+    LOG(DEBUG) << "supplyIccPukForApp finished";
 }
 
 /*
  * Test IRadio.supplyIccPin2ForApp() for the response returned.
  */
 TEST_P(RadioHidlTest, supplyIccPin2ForApp) {
+    LOG(DEBUG) << "supplyIccPin2ForApp";
     serial = GetRandomSerialNumber();
 
     // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -99,12 +107,14 @@
                                   RadioError::SIM_PUK2}));
         }
     }
+    LOG(DEBUG) << "supplyIccPin2ForApp finished";
 }
 
 /*
  * Test IRadio.supplyIccPuk2ForApp() for the response returned.
  */
 TEST_P(RadioHidlTest, supplyIccPuk2ForApp) {
+    LOG(DEBUG) << "supplyIccPuk2ForApp";
     serial = GetRandomSerialNumber();
 
     // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -123,12 +133,14 @@
                                                                    RadioError::INVALID_SIM_STATE}));
         }
     }
+    LOG(DEBUG) << "supplyIccPuk2ForApp finished";
 }
 
 /*
  * Test IRadio.changeIccPinForApp() for the response returned.
  */
 TEST_P(RadioHidlTest, changeIccPinForApp) {
+    LOG(DEBUG) << "changeIccPinForApp";
     serial = GetRandomSerialNumber();
 
     // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -148,12 +160,14 @@
                 {RadioError::PASSWORD_INCORRECT, RadioError::REQUEST_NOT_SUPPORTED}));
         }
     }
+    LOG(DEBUG) << "changeIccPinForApp finished";
 }
 
 /*
  * Test IRadio.changeIccPin2ForApp() for the response returned.
  */
 TEST_P(RadioHidlTest, changeIccPin2ForApp) {
+    LOG(DEBUG) << "changeIccPin2ForApp";
     serial = GetRandomSerialNumber();
 
     // Pass wrong password and check PASSWORD_INCORRECT returned for 3GPP and
@@ -174,6 +188,7 @@
                                   RadioError::SIM_PUK2}));
         }
     }
+    LOG(DEBUG) << "changeIccPin2ForApp finished";
 }
 
 /*
@@ -182,6 +197,7 @@
  * Test IRadio.getImsiForApp() for the response returned.
  */
 TEST_P(RadioHidlTest, DISABLED_getImsiForApp) {
+    LOG(DEBUG) << "DISABLED_getImsiForApp";
     serial = GetRandomSerialNumber();
 
     // Check success returned while getting imsi for 3GPP and 3GPP2 apps only
@@ -205,12 +221,14 @@
             }
         }
     }
+    LOG(DEBUG) << "DISABLED_getImsiForApp finished";
 }
 
 /*
  * Test IRadio.iccIOForApp() for the response returned.
  */
 TEST_P(RadioHidlTest, iccIOForApp) {
+    LOG(DEBUG) << "iccIOForApp";
     serial = GetRandomSerialNumber();
 
     for (int i = 0; i < (int)cardStatus.applications.size(); i++) {
@@ -230,12 +248,14 @@
         EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
         EXPECT_EQ(serial, radioRsp->rspInfo.serial);
     }
+    LOG(DEBUG) << "iccIOForApp finished";
 }
 
 /*
  * Test IRadio.iccTransmitApduBasicChannel() for the response returned.
  */
 TEST_P(RadioHidlTest, iccTransmitApduBasicChannel) {
+    LOG(DEBUG) << "iccTransmitApduBasicChannel";
     serial = GetRandomSerialNumber();
     SimApdu msg;
     memset(&msg, 0, sizeof(msg));
@@ -247,12 +267,14 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     // TODO(sanketpadawe): Add test for error code
+    LOG(DEBUG) << "iccTransmitApduBasicChannel finished";
 }
 
 /*
  * Test IRadio.iccOpenLogicalChannel() for the response returned.
  */
 TEST_P(RadioHidlTest, iccOpenLogicalChannel) {
+    LOG(DEBUG) << "iccOpenLogicalChannel";
     serial = GetRandomSerialNumber();
     int p2 = 0x04;
     // Specified in ISO 7816-4 clause 7.1.1 0x04 means that FCP template is requested.
@@ -262,12 +284,14 @@
         EXPECT_EQ(serial, radioRsp->rspInfo.serial);
         EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp->rspInfo.type);
     }
+    LOG(DEBUG) << "iccOpenLogicalChannel finished";
 }
 
 /*
  * Test IRadio.iccCloseLogicalChannel() for the response returned.
  */
 TEST_P(RadioHidlTest, iccCloseLogicalChannel) {
+    LOG(DEBUG) << "iccCloseLogicalChannel";
     serial = GetRandomSerialNumber();
     // Try closing invalid channel and check INVALID_ARGUMENTS returned as error
     radio->iccCloseLogicalChannel(serial, 0);
@@ -276,12 +300,14 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     EXPECT_EQ(RadioError::INVALID_ARGUMENTS, radioRsp->rspInfo.error);
+    LOG(DEBUG) << "iccCloseLogicalChannel finished";
 }
 
 /*
  * Test IRadio.iccTransmitApduLogicalChannel() for the response returned.
  */
 TEST_P(RadioHidlTest, iccTransmitApduLogicalChannel) {
+    LOG(DEBUG) << "iccTransmitApduLogicalChannel";
     serial = GetRandomSerialNumber();
     SimApdu msg;
     memset(&msg, 0, sizeof(msg));
@@ -293,12 +319,14 @@
     EXPECT_EQ(serial, radioRsp->rspInfo.serial);
 
     // TODO(sanketpadawe): Add test for error code
+    LOG(DEBUG) << "iccTransmitApduLogicalChannel finished";
 }
 
 /*
  * Test IRadio.requestIccSimAuthentication() for the response returned.
  */
 TEST_P(RadioHidlTest, requestIccSimAuthentication) {
+    LOG(DEBUG) << "requestIccSimAuthentication";
     serial = GetRandomSerialNumber();
 
     // Pass wrong challenge string and check RadioError::INVALID_ARGUMENTS
@@ -312,12 +340,14 @@
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::INVALID_ARGUMENTS,
                                                                RadioError::REQUEST_NOT_SUPPORTED}));
     }
+    LOG(DEBUG) << "requestIccSimAuthentication finished";
 }
 
 /*
  * Test IRadio.supplyNetworkDepersonalization() for the response returned.
  */
 TEST_P(RadioHidlTest, supplyNetworkDepersonalization) {
+    LOG(DEBUG) << "supplyNetworkDepersonalization";
     serial = GetRandomSerialNumber();
 
     radio->supplyNetworkDepersonalization(serial, hidl_string("test"));
@@ -332,4 +362,5 @@
              RadioError::INVALID_SIM_STATE, RadioError::MODEM_ERR, RadioError::NO_MEMORY,
              RadioError::PASSWORD_INCORRECT, RadioError::SIM_ABSENT, RadioError::SYSTEM_ERR}));
     }
+    LOG(DEBUG) << "supplyNetworkDepersonalization finished";
 }
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp b/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
index 7228fb0..3f96473 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_misc.cpp
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
+#include <android-base/logging.h>
 #include <radio_hidl_hal_utils_v1_0.h>
 
 /*
  * Test IRadio.getSignalStrength() for the response returned.
  */
 TEST_P(RadioHidlTest, getSignalStrength) {
+    LOG(DEBUG) << "getSignalStrength";
     serial = GetRandomSerialNumber();
 
     radio->getSignalStrength(serial);
@@ -30,12 +32,14 @@
     if (cardStatus.cardState == CardState::ABSENT) {
         EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
+    LOG(DEBUG) << "getSignalStrength finished";
 }
 
 /*
  * Test IRadio.getVoiceRegistrationState() for the response returned.
  */
 TEST_P(RadioHidlTest, getVoiceRegistrationState) {
+    LOG(DEBUG) << "getVoiceRegistrationState";
     serial = GetRandomSerialNumber();
 
     radio->getVoiceRegistrationState(serial);
@@ -46,12 +50,14 @@
     if (cardStatus.cardState == CardState::ABSENT) {
         EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
+    LOG(DEBUG) << "getVoiceRegistrationState finished";
 }
 
 /*
  * Test IRadio.getOperator() for the response returned.
  */
 TEST_P(RadioHidlTest, getOperator) {
+    LOG(DEBUG) << "getOperator";
     serial = GetRandomSerialNumber();
 
     radio->getOperator(serial);
@@ -62,12 +68,14 @@
     if (cardStatus.cardState == CardState::ABSENT) {
         EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
+    LOG(DEBUG) << "getOperator finished";
 }
 
 /*
  * Test IRadio.setRadioPower() for the response returned.
  */
 TEST_P(RadioHidlTest, setRadioPower) {
+    LOG(DEBUG) << "setRadioPower";
     serial = GetRandomSerialNumber();
 
     radio->setRadioPower(serial, 1);
@@ -78,12 +86,14 @@
     if (cardStatus.cardState == CardState::ABSENT) {
         EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
+    LOG(DEBUG) << "setRadioPower finished";
 }
 
 /*
  * Test IRadio.getNetworkSelectionMode() for the response returned.
  */
 TEST_P(RadioHidlTest, getNetworkSelectionMode) {
+    LOG(DEBUG) << "getNetworkSelectionMode";
     serial = GetRandomSerialNumber();
 
     radio->getNetworkSelectionMode(serial);
@@ -94,12 +104,14 @@
     if (cardStatus.cardState == CardState::ABSENT) {
         EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
+    LOG(DEBUG) << "getNetworkSelectionMode finished";
 }
 
 /*
  * Test IRadio.setNetworkSelectionModeAutomatic() for the response returned.
  */
 TEST_P(RadioHidlTest, setNetworkSelectionModeAutomatic) {
+    LOG(DEBUG) << "setNetworkSelectionModeAutomatic";
     serial = GetRandomSerialNumber();
 
     radio->setNetworkSelectionModeAutomatic(serial);
@@ -113,12 +125,14 @@
             {RadioError::NONE, RadioError::ILLEGAL_SIM_OR_ME, RadioError::OPERATION_NOT_ALLOWED},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "setNetworkSelectionModeAutomatic finished";
 }
 
 /*
  * Test IRadio.setNetworkSelectionModeManual() for the response returned.
  */
 TEST_P(RadioHidlTest, setNetworkSelectionModeManual) {
+    LOG(DEBUG) << "setNetworkSelectionModeManual";
     serial = GetRandomSerialNumber();
 
     radio->setNetworkSelectionModeManual(serial, "123456");
@@ -132,12 +146,14 @@
                                       RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "setNetworkSelectionModeManual finished";
 }
 
 /*
  * Test IRadio.getAvailableNetworks() for the response returned.
  */
 TEST_P(RadioHidlTest, getAvailableNetworks) {
+    LOG(DEBUG) << "getAvailableNetworks";
     serial = GetRandomSerialNumber();
 
     radio->getAvailableNetworks(serial);
@@ -153,12 +169,14 @@
                               RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
                              CHECK_GENERAL_ERROR));
   }
+  LOG(DEBUG) << "getAvailableNetworks finished";
 }
 
 /*
  * Test IRadio.getBasebandVersion() for the response returned.
  */
 TEST_P(RadioHidlTest, getBasebandVersion) {
+    LOG(DEBUG) << "getBasebandVersion";
     serial = GetRandomSerialNumber();
 
     radio->getBasebandVersion(serial);
@@ -169,12 +187,14 @@
     if (cardStatus.cardState == CardState::ABSENT) {
         EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
+    LOG(DEBUG) << "getBasebandVersion finished";
 }
 
 /*
  * Test IRadio.setBandMode() for the response returned.
  */
 TEST_P(RadioHidlTest, setBandMode) {
+    LOG(DEBUG) << "setBandMode";
     serial = GetRandomSerialNumber();
 
     radio->setBandMode(serial, RadioBandMode::BAND_MODE_USA);
@@ -186,12 +206,14 @@
         ASSERT_TRUE(
             CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "setBandMode finished";
 }
 
 /*
  * Test IRadio.getAvailableBandModes() for the response returned.
  */
 TEST_P(RadioHidlTest, getAvailableBandModes) {
+    LOG(DEBUG) << "getAvailableBandModes";
     serial = GetRandomSerialNumber();
 
     radio->getAvailableBandModes(serial);
@@ -202,12 +224,14 @@
     if (cardStatus.cardState == CardState::ABSENT) {
         EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
+    LOG(DEBUG) << "getAvailableBandModes finished";
 }
 
 /*
  * Test IRadio.setPreferredNetworkType() for the response returned.
  */
 TEST_P(RadioHidlTest, setPreferredNetworkType) {
+    LOG(DEBUG) << "setPreferredNetworkType";
     serial = GetRandomSerialNumber();
 
     radio->setPreferredNetworkType(serial, PreferredNetworkType::GSM_ONLY);
@@ -219,12 +243,14 @@
         ASSERT_TRUE(
             CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "setPreferredNetworkType finished";
 }
 
 /*
  * Test IRadio.getPreferredNetworkType() for the response returned.
  */
 TEST_P(RadioHidlTest, getPreferredNetworkType) {
+    LOG(DEBUG) << "getPreferredNetworkType";
     serial = GetRandomSerialNumber();
 
     radio->getPreferredNetworkType(serial);
@@ -235,12 +261,14 @@
     if (cardStatus.cardState == CardState::ABSENT) {
         EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
+    LOG(DEBUG) << "getPreferredNetworkType finished";
 }
 
 /*
  * Test IRadio.getNeighboringCids() for the response returned.
  */
 TEST_P(RadioHidlTest, getNeighboringCids) {
+    LOG(DEBUG) << "getNeighboringCids";
     serial = GetRandomSerialNumber();
 
     radio->getNeighboringCids(serial);
@@ -253,12 +281,14 @@
                                      {RadioError::NONE, RadioError::SIM_ABSENT},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "getNeighboringCids finished";
 }
 
 /*
  * Test IRadio.setLocationUpdates() for the response returned.
  */
 TEST_P(RadioHidlTest, setLocationUpdates) {
+    LOG(DEBUG) << "setLocationUpdates";
     serial = GetRandomSerialNumber();
 
     radio->setLocationUpdates(serial, true);
@@ -270,12 +300,14 @@
         ASSERT_TRUE(
             CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE, RadioError::SIM_ABSENT}));
     }
+    LOG(DEBUG) << "setLocationUpdates finished";
 }
 
 /*
  * Test IRadio.setCdmaRoamingPreference() for the response returned.
  */
 TEST_P(RadioHidlTest, setCdmaRoamingPreference) {
+    LOG(DEBUG) << "setCdmaRoamingPreference";
     serial = GetRandomSerialNumber();
 
     radio->setCdmaRoamingPreference(serial, CdmaRoamingType::HOME_NETWORK);
@@ -288,12 +320,14 @@
             radioRsp->rspInfo.error,
             {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::REQUEST_NOT_SUPPORTED}));
     }
+    LOG(DEBUG) << "setCdmaRoamingPreference finished";
 }
 
 /*
  * Test IRadio.getCdmaRoamingPreference() for the response returned.
  */
 TEST_P(RadioHidlTest, getCdmaRoamingPreference) {
+    LOG(DEBUG) << "getCdmaRoamingPreference";
     serial = GetRandomSerialNumber();
 
     radio->getCdmaRoamingPreference(serial);
@@ -307,12 +341,14 @@
                              {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::MODEM_ERR},
                              CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "getCdmaRoamingPreference finished";
 }
 
 /*
  * Test IRadio.getTTYMode() for the response returned.
  */
 TEST_P(RadioHidlTest, getTTYMode) {
+    LOG(DEBUG) << "getTTYMode";
     serial = GetRandomSerialNumber();
 
     radio->getTTYMode(serial);
@@ -323,12 +359,14 @@
     if (cardStatus.cardState == CardState::ABSENT) {
         EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
+    LOG(DEBUG) << "getTTYMode finished";
 }
 
 /*
  * Test IRadio.setTTYMode() for the response returned.
  */
 TEST_P(RadioHidlTest, setTTYMode) {
+    LOG(DEBUG) << "setTTYMode";
     serial = GetRandomSerialNumber();
 
     radio->setTTYMode(serial, TtyMode::OFF);
@@ -339,12 +377,14 @@
     if (cardStatus.cardState == CardState::ABSENT) {
         EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
+    LOG(DEBUG) << "setTTYMode finished";
 }
 
 /*
  * Test IRadio.setPreferredVoicePrivacy() for the response returned.
  */
 TEST_P(RadioHidlTest, setPreferredVoicePrivacy) {
+    LOG(DEBUG) << "setPreferredVoicePrivacy";
     serial = GetRandomSerialNumber();
 
     radio->setPreferredVoicePrivacy(serial, true);
@@ -356,12 +396,14 @@
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
                                      {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
+    LOG(DEBUG) << "setPreferredVoicePrivacy finished";
 }
 
 /*
  * Test IRadio.getPreferredVoicePrivacy() for the response returned.
  */
 TEST_P(RadioHidlTest, getPreferredVoicePrivacy) {
+    LOG(DEBUG) << "getPreferredVoicePrivacy";
     serial = GetRandomSerialNumber();
 
     radio->getPreferredVoicePrivacy(serial);
@@ -373,12 +415,14 @@
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
                                      {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
+    LOG(DEBUG) << "getPreferredVoicePrivacy finished";
 }
 
 /*
  * Test IRadio.getCDMASubscription() for the response returned.
  */
 TEST_P(RadioHidlTest, getCDMASubscription) {
+    LOG(DEBUG) << "getCDMASubscription";
     serial = GetRandomSerialNumber();
 
     radio->getCDMASubscription(serial);
@@ -391,12 +435,14 @@
             radioRsp->rspInfo.error,
             {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
     }
+    LOG(DEBUG) << "getCDMASubscription finished";
 }
 
 /*
  * Test IRadio.getDeviceIdentity() for the response returned.
  */
 TEST_P(RadioHidlTest, getDeviceIdentity) {
+    LOG(DEBUG) << "getDeviceIdentity";
     serial = GetRandomSerialNumber();
 
     radio->getDeviceIdentity(serial);
@@ -408,12 +454,14 @@
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
                                      {RadioError::NONE, RadioError::EMPTY_RECORD}));
     }
+    LOG(DEBUG) << "getDeviceIdentity finished";
 }
 
 /*
  * Test IRadio.exitEmergencyCallbackMode() for the response returned.
  */
 TEST_P(RadioHidlTest, exitEmergencyCallbackMode) {
+    LOG(DEBUG) << "exitEmergencyCallbackMode";
     serial = GetRandomSerialNumber();
 
     radio->exitEmergencyCallbackMode(serial);
@@ -426,12 +474,14 @@
             radioRsp->rspInfo.error,
             {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
     }
+    LOG(DEBUG) << "exitEmergencyCallbackMode finished";
 }
 
 /*
  * Test IRadio.getCdmaSubscriptionSource() for the response returned.
  */
 TEST_P(RadioHidlTest, getCdmaSubscriptionSource) {
+    LOG(DEBUG) << "getCdmaSubscriptionSource";
     serial = GetRandomSerialNumber();
 
     radio->getCdmaSubscriptionSource(serial);
@@ -444,12 +494,14 @@
             radioRsp->rspInfo.error,
             {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
     }
+    LOG(DEBUG) << "getCdmaSubscriptionSource finished";
 }
 
 /*
  * Test IRadio.setCdmaSubscriptionSource() for the response returned.
  */
 TEST_P(RadioHidlTest, setCdmaSubscriptionSource) {
+    LOG(DEBUG) << "setCdmaSubscriptionSource";
     serial = GetRandomSerialNumber();
 
     radio->setCdmaSubscriptionSource(serial, CdmaSubscriptionSource::RUIM_SIM);
@@ -463,12 +515,14 @@
             {RadioError::NONE, RadioError::SIM_ABSENT, RadioError::SUBSCRIPTION_NOT_AVAILABLE},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "setCdmaSubscriptionSource finished";
 }
 
 /*
  * Test IRadio.getVoiceRadioTechnology() for the response returned.
  */
 TEST_P(RadioHidlTest, getVoiceRadioTechnology) {
+    LOG(DEBUG) << "getVoiceRadioTechnology";
     serial = GetRandomSerialNumber();
 
     radio->getVoiceRadioTechnology(serial);
@@ -479,12 +533,14 @@
     if (cardStatus.cardState == CardState::ABSENT) {
         EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
+    LOG(DEBUG) << "getVoiceRadioTechnology finished";
 }
 
 /*
  * Test IRadio.getCellInfoList() for the response returned.
  */
 TEST_P(RadioHidlTest, getCellInfoList) {
+    LOG(DEBUG) << "getCellInfoList";
     serial = GetRandomSerialNumber();
 
     radio->getCellInfoList(serial);
@@ -497,12 +553,14 @@
                                      {RadioError::NONE, RadioError::NO_NETWORK_FOUND},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "getCellInfoList finished";
 }
 
 /*
  * Test IRadio.setCellInfoListRate() for the response returned.
  */
 TEST_P(RadioHidlTest, setCellInfoListRate) {
+    LOG(DEBUG) << "setCellInfoListRate";
     serial = GetRandomSerialNumber();
 
     // TODO(sanketpadawe): RIL crashes with value of rate = 10
@@ -515,12 +573,14 @@
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
                                      {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
+    LOG(DEBUG) << "setCellInfoListRate finished";
 }
 
 /*
  * Test IRadio.nvReadItem() for the response returned.
  */
 TEST_P(RadioHidlTest, nvReadItem) {
+    LOG(DEBUG) << "nvReadItem";
     serial = GetRandomSerialNumber();
 
     radio->nvReadItem(serial, NvItem::LTE_BAND_ENABLE_25);
@@ -532,12 +592,14 @@
         ASSERT_TRUE(
             CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "nvReadItem finished";
 }
 
 /*
  * Test IRadio.nvWriteItem() for the response returned.
  */
 TEST_P(RadioHidlTest, nvWriteItem) {
+    LOG(DEBUG) << "nvWriteItem";
     serial = GetRandomSerialNumber();
     NvWriteItem item;
     memset(&item, 0, sizeof(item));
@@ -552,12 +614,14 @@
         ASSERT_TRUE(
             CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "nvWriteItem finished";
 }
 
 /*
  * Test IRadio.nvWriteCdmaPrl() for the response returned.
  */
 TEST_P(RadioHidlTest, nvWriteCdmaPrl) {
+    LOG(DEBUG) << "nvWriteCdmaPrl";
     serial = GetRandomSerialNumber();
     std::vector<uint8_t> prl = {1, 2, 3, 4, 5};
 
@@ -570,12 +634,14 @@
         ASSERT_TRUE(
             CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "nvWriteCdmaPrl finished";
 }
 
 /*
  * Test IRadio.nvResetConfig() for the response returned.
  */
 TEST_P(RadioHidlTest, nvResetConfig) {
+    LOG(DEBUG) << "nvResetConfig";
     serial = GetRandomSerialNumber();
 
     radio->nvResetConfig(serial, ResetNvType::FACTORY_RESET);
@@ -587,12 +653,14 @@
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
                                      {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
+    LOG(DEBUG) << "nvResetConfig finished";
 }
 
 /*
  * Test IRadio.setUiccSubscription() for the response returned.
  */
 TEST_P(RadioHidlTest, setUiccSubscription) {
+    LOG(DEBUG) << "setUiccSubscription";
     serial = GetRandomSerialNumber();
     SelectUiccSub item;
     memset(&item, 0, sizeof(item));
@@ -609,12 +677,14 @@
                               RadioError::MODEM_ERR, RadioError::SUBSCRIPTION_NOT_SUPPORTED},
                              CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "setUiccSubscription finished";
 }
 
 /*
  * Test IRadio.getHardwareConfig() for the response returned.
  */
 TEST_P(RadioHidlTest, getHardwareConfig) {
+    LOG(DEBUG) << "getHardwareConfig";
     serial = GetRandomSerialNumber();
 
     radio->getHardwareConfig(serial);
@@ -626,6 +696,7 @@
         ASSERT_TRUE(
             CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "getHardwareConfig finished";
 }
 
 /*
@@ -651,6 +722,7 @@
  * Test IRadio.getRadioCapability() for the response returned.
  */
 TEST_P(RadioHidlTest, getRadioCapability) {
+    LOG(DEBUG) << "getRadioCapability";
     serial = GetRandomSerialNumber();
 
     radio->getRadioCapability(serial);
@@ -661,12 +733,14 @@
     if (cardStatus.cardState == CardState::ABSENT) {
         EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
+    LOG(DEBUG) << "getRadioCapability finished";
 }
 
 /*
  * Test IRadio.setRadioCapability() for the response returned.
  */
 TEST_P(RadioHidlTest, setRadioCapability) {
+    LOG(DEBUG) << "setRadioCapability";
     serial = GetRandomSerialNumber();
     RadioCapability rc;
     memset(&rc, 0, sizeof(rc));
@@ -682,12 +756,14 @@
                                      {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "setRadioCapability finished";
 }
 
 /*
  * Test IRadio.startLceService() for the response returned.
  */
 TEST_P(RadioHidlTest, startLceService) {
+    LOG(DEBUG) << "startLceService";
     serial = GetRandomSerialNumber();
 
     radio->startLceService(serial, 5, true);
@@ -701,12 +777,14 @@
             {RadioError::INTERNAL_ERR, RadioError::LCE_NOT_SUPPORTED,
              RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ABSENT, RadioError::NONE}));
     }
+    LOG(DEBUG) << "startLceService finished";
 }
 
 /*
  * Test IRadio.stopLceService() for the response returned.
  */
 TEST_P(RadioHidlTest, stopLceService) {
+    LOG(DEBUG) << "stopLceService";
     serial = GetRandomSerialNumber();
 
     radio->stopLceService(serial);
@@ -719,12 +797,14 @@
                                      {RadioError::NONE, RadioError::LCE_NOT_SUPPORTED,
                                       RadioError::REQUEST_NOT_SUPPORTED, RadioError::SIM_ABSENT}));
     }
+    LOG(DEBUG) << "stopLceService finished";
 }
 
 /*
  * Test IRadio.pullLceData() for the response returned.
  */
 TEST_P(RadioHidlTest, pullLceData) {
+    LOG(DEBUG) << "pullLceData";
     serial = GetRandomSerialNumber();
 
     radio->pullLceData(serial);
@@ -738,12 +818,14 @@
                                       RadioError::RADIO_NOT_AVAILABLE, RadioError::SIM_ABSENT},
                                      CHECK_OEM_ERROR));
     }
+    LOG(DEBUG) << "pullLceData finished";
 }
 
 /*
  * Test IRadio.getModemActivityInfo() for the response returned.
  */
 TEST_P(RadioHidlTest, getModemActivityInfo) {
+    LOG(DEBUG) << "getModemActivityInfo";
     serial = GetRandomSerialNumber();
 
     radio->getModemActivityInfo(serial);
@@ -755,6 +837,7 @@
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
                                      {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
+    LOG(DEBUG) << "getModemActivityInfo finished";
 }
 
 /*
@@ -840,6 +923,7 @@
  * Test IRadio.getAllowedCarriers() for the response returned.
  */
 TEST_P(RadioHidlTest, getAllowedCarriers) {
+    LOG(DEBUG) << "getAllowedCarriers";
     serial = GetRandomSerialNumber();
 
     radio->getAllowedCarriers(serial);
@@ -851,12 +935,14 @@
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
                                      {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
+    LOG(DEBUG) << "getAllowedCarriers finished";
 }
 
 /*
  * Test IRadio.sendDeviceState() for the response returned.
  */
 TEST_P(RadioHidlTest, sendDeviceState) {
+    LOG(DEBUG) << "sendDeviceState";
     serial = GetRandomSerialNumber();
 
     radio->sendDeviceState(serial, DeviceStateType::POWER_SAVE_MODE, true);
@@ -870,12 +956,14 @@
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
                                      {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
+    LOG(DEBUG) << "sendDeviceState finished";
 }
 
 /*
  * Test IRadio.setIndicationFilter() for the response returned.
  */
 TEST_P(RadioHidlTest, setIndicationFilter) {
+    LOG(DEBUG) << "setIndicationFilter";
     serial = GetRandomSerialNumber();
 
     radio->setIndicationFilter(serial, 1);
@@ -889,12 +977,14 @@
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
                                      {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
+    LOG(DEBUG) << "setIndicationFilter finished";
 }
 
 /*
  * Test IRadio.setSimCardPower() for the response returned.
  */
 TEST_P(RadioHidlTest, setSimCardPower) {
+    LOG(DEBUG) << "setSimCardPower";
     serial = GetRandomSerialNumber();
 
     radio->setSimCardPower(serial, true);
@@ -906,4 +996,5 @@
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error,
                                      {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
     }
+    LOG(DEBUG) << "setSimCardPower finished";
 }
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_sms.cpp b/radio/1.0/vts/functional/radio_hidl_hal_sms.cpp
index 58c3bbd..0807dee 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_sms.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_sms.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <android-base/logging.h>
 #include <radio_hidl_hal_utils_v1_0.h>
 
 using namespace ::android::hardware::radio::V1_0;
@@ -22,6 +23,7 @@
  * Test IRadio.sendSms() for the response returned.
  */
 TEST_P(RadioHidlTest, sendSms) {
+    LOG(DEBUG) << "sendSms";
     serial = GetRandomSerialNumber();
     GsmSmsMessage msg;
     msg.smscPdu = "";
@@ -40,12 +42,14 @@
             CHECK_GENERAL_ERROR));
         EXPECT_EQ(0, radioRsp->sendSmsResult.errorCode);
     }
+    LOG(DEBUG) << "sendSms finished";
 }
 
 /*
  * Test IRadio.sendSMSExpectMore() for the response returned.
  */
 TEST_P(RadioHidlTest, sendSMSExpectMore) {
+    LOG(DEBUG) << "sendSMSExpectMore";
     serial = GetRandomSerialNumber();
     GsmSmsMessage msg;
     msg.smscPdu = "";
@@ -66,12 +70,14 @@
             {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "sendSMSExpectMore finished";
 }
 
 /*
  * Test IRadio.acknowledgeLastIncomingGsmSms() for the response returned.
  */
 TEST_P(RadioHidlTest, acknowledgeLastIncomingGsmSms) {
+    LOG(DEBUG) << "acknowledgeLastIncomingGsmSms";
     serial = GetRandomSerialNumber();
     bool success = true;
 
@@ -87,12 +93,14 @@
                                      {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "acknowledgeLastIncomingGsmSms finished";
 }
 
 /*
  * Test IRadio.acknowledgeIncomingGsmSmsWithPdu() for the response returned.
  */
 TEST_P(RadioHidlTest, acknowledgeIncomingGsmSmsWithPdu) {
+    LOG(DEBUG) << "acknowledgeIncomingGsmSmsWithPdu";
     serial = GetRandomSerialNumber();
     bool success = true;
     std::string ackPdu = "";
@@ -106,12 +114,14 @@
     if (cardStatus.cardState == CardState::ABSENT) {
         // TODO(shuoq): Will add error check when we know the expected error from QC
     }
+    LOG(DEBUG) << "acknowledgeIncomingGsmSmsWithPdu finished";
 }
 
 /*
  * Test IRadio.sendCdmaSms() for the response returned.
  */
 TEST_P(RadioHidlTest, sendCdmaSms) {
+    LOG(DEBUG) << "sendCdmaSms";
     serial = GetRandomSerialNumber();
 
     // Create a CdmaSmsAddress
@@ -150,12 +160,14 @@
             {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "sendCdmaSms finished";
 }
 
 /*
  * Test IRadio.acknowledgeLastIncomingCdmaSms() for the response returned.
  */
 TEST_P(RadioHidlTest, acknowledgeLastIncomingCdmaSms) {
+    LOG(DEBUG) << "acknowledgeLastIncomingCdmaSms";
     serial = GetRandomSerialNumber();
 
     // Create a CdmaSmsAck
@@ -174,12 +186,14 @@
                                      {RadioError::INVALID_ARGUMENTS, RadioError::NO_SMS_TO_ACK},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "acknowledgeLastIncomingCdmaSms finished";
 }
 
 /*
  * Test IRadio.sendImsSms() for the response returned.
  */
 TEST_P(RadioHidlTest, sendImsSms) {
+    LOG(DEBUG) << "sendImsSms";
     serial = GetRandomSerialNumber();
 
     // Create a CdmaSmsAddress
@@ -224,12 +238,14 @@
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::INVALID_ARGUMENTS},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "sendImsSms finished";
 }
 
 /*
  * Test IRadio.getSmscAddress() for the response returned.
  */
 TEST_P(RadioHidlTest, getSmscAddress) {
+    LOG(DEBUG) << "getSmscAddress";
     serial = GetRandomSerialNumber();
 
     radio->getSmscAddress(serial);
@@ -244,12 +260,14 @@
             {RadioError::INVALID_MODEM_STATE, RadioError::INVALID_STATE, RadioError::SIM_ABSENT},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "getSmscAddress finished";
 }
 
 /*
  * Test IRadio.setSmscAddress() for the response returned.
  */
 TEST_P(RadioHidlTest, setSmscAddress) {
+    LOG(DEBUG) << "setSmscAddress";
     serial = GetRandomSerialNumber();
     hidl_string address = hidl_string("smscAddress");
 
@@ -265,12 +283,14 @@
             {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_SMS_FORMAT, RadioError::SIM_ABSENT},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "setSmscAddress finished";
 }
 
 /*
  * Test IRadio.writeSmsToSim() for the response returned.
  */
 TEST_P(RadioHidlTest, writeSmsToSim) {
+    LOG(DEBUG) << "writeSmsToSim";
     serial = GetRandomSerialNumber();
     SmsWriteArgs smsWriteArgs;
     smsWriteArgs.status = SmsWriteArgsStatus::REC_UNREAD;
@@ -291,12 +311,14 @@
              RadioError::NO_RESOURCES, RadioError::SIM_ABSENT},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "writeSmsToSim finished";
 }
 
 /*
  * Test IRadio.deleteSmsOnSim() for the response returned.
  */
 TEST_P(RadioHidlTest, deleteSmsOnSim) {
+    LOG(DEBUG) << "deleteSmsOnSim";
     serial = GetRandomSerialNumber();
     int index = 1;
 
@@ -314,12 +336,14 @@
              RadioError::SIM_ABSENT},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "deleteSmsOnSim finished";
 }
 
 /*
  * Test IRadio.writeSmsToRuim() for the response returned.
  */
 TEST_P(RadioHidlTest, writeSmsToRuim) {
+    LOG(DEBUG) << "writeSmsToRuim";
     serial = GetRandomSerialNumber();
 
     // Create a CdmaSmsAddress
@@ -365,12 +389,14 @@
              RadioError::NO_SUCH_ENTRY, RadioError::SIM_ABSENT},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "writeSmsToRuim finished";
 }
 
 /*
  * Test IRadio.deleteSmsOnRuim() for the response returned.
  */
 TEST_P(RadioHidlTest, deleteSmsOnRuim) {
+    LOG(DEBUG) << "deleteSmsOnRuim";
     serial = GetRandomSerialNumber();
     int index = 1;
 
@@ -416,12 +442,14 @@
              RadioError::MODEM_ERR, RadioError::NO_SUCH_ENTRY, RadioError::SIM_ABSENT},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "deleteSmsOnRuim finished";
 }
 
 /*
  * Test IRadio.reportSmsMemoryStatus() for the response returned.
  */
 TEST_P(RadioHidlTest, reportSmsMemoryStatus) {
+    LOG(DEBUG) << "reportSmsMemoryStatus";
     serial = GetRandomSerialNumber();
     bool available = true;
 
@@ -437,4 +465,5 @@
                                       RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "reportSmsMemoryStatus finished";
 }
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp b/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp
index 1170111..193c25d 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_stk.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <android-base/logging.h>
 #include <radio_hidl_hal_utils_v1_0.h>
 
 using namespace ::android::hardware::radio::V1_0;
@@ -22,6 +23,7 @@
  * Test IRadio.sendEnvelope() for the response returned.
  */
 TEST_P(RadioHidlTest, sendEnvelope) {
+    LOG(DEBUG) << "sendEnvelope";
     serial = GetRandomSerialNumber();
 
     // Test with sending empty string
@@ -39,12 +41,14 @@
                                       RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "sendEnvelope finished";
 }
 
 /*
  * Test IRadio.sendTerminalResponseToSim() for the response returned.
  */
 TEST_P(RadioHidlTest, sendTerminalResponseToSim) {
+    LOG(DEBUG) << "sendTerminalResponseToSim";
     serial = GetRandomSerialNumber();
 
     // Test with sending empty string
@@ -62,12 +66,14 @@
             {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::SIM_ABSENT},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "sendTerminalResponseToSim finished";
 }
 
 /*
  * Test IRadio.handleStkCallSetupRequestFromSim() for the response returned.
  */
 TEST_P(RadioHidlTest, handleStkCallSetupRequestFromSim) {
+    LOG(DEBUG) << "handleStkCallSetupRequestFromSim";
     serial = GetRandomSerialNumber();
     bool accept = false;
 
@@ -83,12 +89,14 @@
                                       RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "handleStkCallSetupRequestFromSim finished";
 }
 
 /*
  * Test IRadio.reportStkServiceIsRunning() for the response returned.
  */
 TEST_P(RadioHidlTest, reportStkServiceIsRunning) {
+    LOG(DEBUG) << "reportStkServiceIsRunning";
     serial = GetRandomSerialNumber();
 
     radio->reportStkServiceIsRunning(serial);
@@ -101,6 +109,7 @@
         ASSERT_TRUE(
             CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "reportStkServiceIsRunning finished";
 }
 
 /*
@@ -108,6 +117,7 @@
  * string.
  */
 TEST_P(RadioHidlTest, sendEnvelopeWithStatus) {
+    LOG(DEBUG) << "sendEnvelopeWithStatus";
     serial = GetRandomSerialNumber();
 
     // Test with sending empty string
@@ -125,4 +135,5 @@
             {RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR, RadioError::SIM_ABSENT},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "sendEnvelopeWithStatus finished";
 }
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_test.cpp b/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
index 3c833c0..3583514 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_test.cpp
@@ -14,11 +14,13 @@
  * limitations under the License.
  */
 
+#include <android-base/logging.h>
 #include <radio_hidl_hal_utils_v1_0.h>
 
 void RadioHidlTest::SetUp() {
     radio = IRadio::getService(GetParam());
     if (radio == NULL) {
+        LOG(DEBUG) << "Radio is NULL, waiting 1 minute to retry";
         sleep(60);
         radio = IRadio::getService(GetParam());
     }
@@ -70,4 +72,4 @@
     serial = GetRandomSerialNumber();
     radio->getIccCardStatus(serial);
     EXPECT_EQ(std::cv_status::no_timeout, wait());
-}
\ No newline at end of file
+}
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp b/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
index a192a33..f6de2f8 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_voice.cpp
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
+#include <android-base/logging.h>
 #include <radio_hidl_hal_utils_v1_0.h>
 
 /*
  * Test IRadio.getCurrentCalls() for the response returned.
  */
 TEST_P(RadioHidlTest, getCurrentCalls) {
+    LOG(DEBUG) << "getCurrentCalls";
     serial = GetRandomSerialNumber();
 
     radio->getCurrentCalls(serial);
@@ -30,12 +32,14 @@
     if (cardStatus.cardState == CardState::ABSENT) {
         EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
+    LOG(DEBUG) << "getCurrentCalls finished";
 }
 
 /*
  * Test IRadio.dial() for the response returned.
  */
 TEST_P(RadioHidlTest, dial) {
+    LOG(DEBUG) << "dial";
     serial = GetRandomSerialNumber();
 
     Dial dialInfo;
@@ -57,12 +61,14 @@
              RadioError::OPERATION_NOT_ALLOWED},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "dial finished";
 }
 
 /*
  * Test IRadio.hangup() for the response returned.
  */
 TEST_P(RadioHidlTest, hangup) {
+    LOG(DEBUG) << "hangup";
     serial = GetRandomSerialNumber();
 
     radio->hangup(serial, 1);
@@ -76,12 +82,14 @@
             {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "hangup finished";
 }
 
 /*
  * Test IRadio.hangupWaitingOrBackground() for the response returned.
  */
 TEST_P(RadioHidlTest, hangupWaitingOrBackground) {
+    LOG(DEBUG) << "hangupWaitingOrBackground";
     serial = GetRandomSerialNumber();
 
     radio->hangupWaitingOrBackground(serial);
@@ -94,12 +102,14 @@
                                      {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "hangupWaitingOrBackground finished";
 }
 
 /*
  * Test IRadio.hangupForegroundResumeBackground() for the response returned.
  */
 TEST_P(RadioHidlTest, hangupForegroundResumeBackground) {
+    LOG(DEBUG) << "hangupForegroundResumeBackground";
     serial = GetRandomSerialNumber();
 
     radio->hangupForegroundResumeBackground(serial);
@@ -112,12 +122,14 @@
                                      {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "hangupForegroundResumeBackground finished";
 }
 
 /*
  * Test IRadio.switchWaitingOrHoldingAndActive() for the response returned.
  */
 TEST_P(RadioHidlTest, switchWaitingOrHoldingAndActive) {
+    LOG(DEBUG) << "switchWaitingOrHoldingAndActive";
     serial = GetRandomSerialNumber();
 
     radio->switchWaitingOrHoldingAndActive(serial);
@@ -130,12 +142,14 @@
                                      {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "switchWaitingOrHoldingAndActive finished";
 }
 
 /*
  * Test IRadio.conference() for the response returned.
  */
 TEST_P(RadioHidlTest, conference) {
+    LOG(DEBUG) << "conference";
     serial = GetRandomSerialNumber();
 
     radio->conference(serial);
@@ -148,12 +162,14 @@
                                      {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "conference finished";
 }
 
 /*
  * Test IRadio.rejectCall() for the response returned.
  */
 TEST_P(RadioHidlTest, rejectCall) {
+    LOG(DEBUG) << "rejectCall";
     serial = GetRandomSerialNumber();
 
     radio->rejectCall(serial);
@@ -166,12 +182,14 @@
                                      {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "rejectCall finished";
 }
 
 /*
  * Test IRadio.getLastCallFailCause() for the response returned.
  */
 TEST_P(RadioHidlTest, getLastCallFailCause) {
+    LOG(DEBUG) << "getLastCallFailCause";
     serial = GetRandomSerialNumber();
 
     radio->getLastCallFailCause(serial);
@@ -183,12 +201,14 @@
         ASSERT_TRUE(
             CheckAnyOfErrors(radioRsp->rspInfo.error, {RadioError::NONE}, CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "getLastCallFailCause finished";
 }
 
 /*
  * Test IRadio.sendUssd() for the response returned.
  */
 TEST_P(RadioHidlTest, sendUssd) {
+    LOG(DEBUG) << "sendUssd";
     serial = GetRandomSerialNumber();
     radio->sendUssd(serial, hidl_string("test"));
     EXPECT_EQ(std::cv_status::no_timeout, wait());
@@ -201,12 +221,14 @@
             {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "sendUssd finished";
 }
 
 /*
  * Test IRadio.cancelPendingUssd() for the response returned.
  */
 TEST_P(RadioHidlTest, cancelPendingUssd) {
+    LOG(DEBUG) << "cancelPendingUssd";
     serial = GetRandomSerialNumber();
 
     radio->cancelPendingUssd(serial);
@@ -220,12 +242,14 @@
                              {RadioError::NONE, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
                              CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "cancelPendingUssd finished";
 }
 
 /*
  * Test IRadio.getCallForwardStatus() for the response returned.
  */
 TEST_P(RadioHidlTest, getCallForwardStatus) {
+    LOG(DEBUG) << "getCallForwardStatus";
     serial = GetRandomSerialNumber();
     CallForwardInfo callInfo;
     memset(&callInfo, 0, sizeof(callInfo));
@@ -242,12 +266,14 @@
             {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "getCallForwardStatus finished";
 }
 
 /*
  * Test IRadio.setCallForward() for the response returned.
  */
 TEST_P(RadioHidlTest, setCallForward) {
+    LOG(DEBUG) << "setCallForward";
     serial = GetRandomSerialNumber();
     CallForwardInfo callInfo;
     memset(&callInfo, 0, sizeof(callInfo));
@@ -264,12 +290,14 @@
             {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "setCallForward finished";
 }
 
 /*
  * Test IRadio.getCallWaiting() for the response returned.
  */
 TEST_P(RadioHidlTest, getCallWaiting) {
+    LOG(DEBUG) << "getCallWaiting";
     serial = GetRandomSerialNumber();
 
     radio->getCallWaiting(serial, 1);
@@ -283,12 +311,14 @@
             {RadioError::NONE, RadioError::INVALID_ARGUMENTS, RadioError::MODEM_ERR},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "getCallWaiting finished";
 }
 
 /*
  * Test IRadio.setCallWaiting() for the response returned.
  */
 TEST_P(RadioHidlTest, setCallWaiting) {
+    LOG(DEBUG) << "setCallWaiting";
     serial = GetRandomSerialNumber();
 
     radio->setCallWaiting(serial, true, 1);
@@ -302,12 +332,14 @@
             {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "setCallWaiting finished";
 }
 
 /*
  * Test IRadio.acceptCall() for the response returned.
  */
 TEST_P(RadioHidlTest, acceptCall) {
+    LOG(DEBUG) << "acceptCall";
     serial = GetRandomSerialNumber();
 
     radio->acceptCall(serial);
@@ -320,12 +352,14 @@
                                      {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "acceptCall finished";
 }
 
 /*
  * Test IRadio.separateConnection() for the response returned.
  */
 TEST_P(RadioHidlTest, separateConnection) {
+    LOG(DEBUG) << "separateConnection";
     serial = GetRandomSerialNumber();
 
     radio->separateConnection(serial, 1);
@@ -339,12 +373,14 @@
             {RadioError::INVALID_ARGUMENTS, RadioError::INVALID_STATE, RadioError::MODEM_ERR},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "separateConnection finished";
 }
 
 /*
  * Test IRadio.explicitCallTransfer() for the response returned.
  */
 TEST_P(RadioHidlTest, explicitCallTransfer) {
+    LOG(DEBUG) << "explicitCallTransfer";
     serial = GetRandomSerialNumber();
 
     radio->explicitCallTransfer(serial);
@@ -357,12 +393,14 @@
                                      {RadioError::INVALID_STATE, RadioError::MODEM_ERR},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "explicitCallTransfer finished";
 }
 
 /*
  * Test IRadio.sendCDMAFeatureCode() for the response returned.
  */
 TEST_P(RadioHidlTest, sendCDMAFeatureCode) {
+    LOG(DEBUG) << "sendCDMAFeatureCode";
     serial = GetRandomSerialNumber();
 
     radio->sendCDMAFeatureCode(serial, hidl_string());
@@ -377,12 +415,14 @@
                                       RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "sendCDMAFeatureCode finished";
 }
 
 /*
  * Test IRadio.sendDtmf() for the response returned.
  */
 TEST_P(RadioHidlTest, sendDtmf) {
+    LOG(DEBUG) << "sendDtmf";
     serial = GetRandomSerialNumber();
 
     radio->sendDtmf(serial, "1");
@@ -397,12 +437,14 @@
              RadioError::INVALID_MODEM_STATE, RadioError::MODEM_ERR},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "sendDtmf finished";
 }
 
 /*
  * Test IRadio.startDtmf() for the response returned.
  */
 TEST_P(RadioHidlTest, startDtmf) {
+    LOG(DEBUG) << "startDtmf";
     serial = GetRandomSerialNumber();
 
     radio->startDtmf(serial, "1");
@@ -417,12 +459,14 @@
              RadioError::INVALID_MODEM_STATE, RadioError::MODEM_ERR},
             CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "startDtmf finished";
 }
 
 /*
  * Test IRadio.stopDtmf() for the response returned.
  */
 TEST_P(RadioHidlTest, stopDtmf) {
+    LOG(DEBUG) << "stopDtmf";
     serial = GetRandomSerialNumber();
 
     radio->stopDtmf(serial);
@@ -436,12 +480,14 @@
                                       RadioError::INVALID_MODEM_STATE, RadioError::MODEM_ERR},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "stopDtmf finished";
 }
 
 /*
  * Test IRadio.setMute() for the response returned.
  */
 TEST_P(RadioHidlTest, setMute) {
+    LOG(DEBUG) << "setMute";
     serial = GetRandomSerialNumber();
 
     radio->setMute(serial, true);
@@ -454,12 +500,14 @@
                                      {RadioError::NONE, RadioError::INVALID_ARGUMENTS},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "setMute finished";
 }
 
 /*
  * Test IRadio.getMute() for the response returned.
  */
 TEST_P(RadioHidlTest, getMute) {
+    LOG(DEBUG) << "getMute";
     serial = GetRandomSerialNumber();
 
     radio->getMute(serial);
@@ -470,12 +518,14 @@
     if (cardStatus.cardState == CardState::ABSENT) {
         EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
     }
+    LOG(DEBUG) << "getMute finished";
 }
 
 /*
  * Test IRadio.sendBurstDtmf() for the response returned.
  */
 TEST_P(RadioHidlTest, sendBurstDtmf) {
+    LOG(DEBUG) << "sendBurstDtmf";
     serial = GetRandomSerialNumber();
 
     radio->sendBurstDtmf(serial, "1", 0, 0);
@@ -489,4 +539,5 @@
                                       RadioError::MODEM_ERR, RadioError::OPERATION_NOT_ALLOWED},
                                      CHECK_GENERAL_ERROR));
     }
+    LOG(DEBUG) << "sendBurstDtmf finished";
 }
diff --git a/radio/1.0/vts/functional/sap_hidl_hal_api.cpp b/radio/1.0/vts/functional/sap_hidl_hal_api.cpp
index 6bd2c88..6c7870d 100644
--- a/radio/1.0/vts/functional/sap_hidl_hal_api.cpp
+++ b/radio/1.0/vts/functional/sap_hidl_hal_api.cpp
@@ -14,12 +14,14 @@
  * limitations under the License.
  */
 
+#include <android-base/logging.h>
 #include <sap_hidl_hal_utils.h>
 
 /*
  * Test ISap.connectReq() for the response returned.
  */
 TEST_P(SapHidlTest, connectReq) {
+    LOG(DEBUG) << "connectReq";
     token = GetRandomSerialNumber();
     int32_t maxMsgSize = 100;
 
@@ -30,23 +32,27 @@
     // Modem side need time for connect to finish. Adding a waiting time to prevent
     // disconnect being requested right after connect request.
     sleep(1);
+    LOG(DEBUG) << "connectReq finished";
 }
 
 /*
  * Test IRadio.disconnectReq() for the response returned
  */
 TEST_P(SapHidlTest, disconnectReq) {
+    LOG(DEBUG) << "disconnectReq";
     token = GetRandomSerialNumber();
 
     sap->disconnectReq(token);
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(sapCb->sapResponseToken, token);
+    LOG(DEBUG) << "disconnectReq finished";
 }
 
 /*
  * Test IRadio.apduReq() for the response returned.
  */
 TEST_P(SapHidlTest, apduReq) {
+    LOG(DEBUG) << "apduReq";
     token = GetRandomSerialNumber();
     SapApduType sapApduType = SapApduType::APDU;
     android::hardware::hidl_vec<uint8_t> command = {};
@@ -59,12 +65,14 @@
         CheckAnyOfErrors(sapCb->sapResultCode,
                          {SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_ALREADY_POWERED_OFF,
                           SapResultCode::CARD_NOT_ACCESSSIBLE, SapResultCode::CARD_REMOVED}));
+    LOG(DEBUG) << "apduReq finished";
 }
 
 /*
  * Test IRadio.transferAtrReq() for the response returned.
  */
 TEST_P(SapHidlTest, transferAtrReq) {
+    LOG(DEBUG) << "transferAtrReq";
     token = GetRandomSerialNumber();
 
     sap->transferAtrReq(token);
@@ -75,12 +83,14 @@
         CheckAnyOfErrors(sapCb->sapResultCode,
                          {SapResultCode::GENERIC_FAILURE, SapResultCode::DATA_NOT_AVAILABLE,
                           SapResultCode::CARD_ALREADY_POWERED_OFF, SapResultCode::CARD_REMOVED}));
+    LOG(DEBUG) << "transferAtrReq finished";
 }
 
 /*
  * Test IRadio.powerReq() for the response returned.
  */
 TEST_P(SapHidlTest, powerReq) {
+    LOG(DEBUG) << "powerReq";
     token = GetRandomSerialNumber();
     bool state = true;
 
@@ -92,12 +102,14 @@
         sapCb->sapResultCode, {SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_NOT_ACCESSSIBLE,
                                SapResultCode::CARD_ALREADY_POWERED_OFF, SapResultCode::CARD_REMOVED,
                                SapResultCode::CARD_ALREADY_POWERED_ON}));
+    LOG(DEBUG) << "powerReq finished";
 }
 
 /*
  * Test IRadio.resetSimReq() for the response returned.
  */
 TEST_P(SapHidlTest, resetSimReq) {
+    LOG(DEBUG) << "resetSimReq";
     token = GetRandomSerialNumber();
 
     sap->resetSimReq(token);
@@ -108,12 +120,14 @@
         CheckAnyOfErrors(sapCb->sapResultCode,
                          {SapResultCode::GENERIC_FAILURE, SapResultCode::CARD_NOT_ACCESSSIBLE,
                           SapResultCode::CARD_ALREADY_POWERED_OFF, SapResultCode::CARD_REMOVED}));
+    LOG(DEBUG) << "resetSimReq finished";
 }
 
 /*
  * Test IRadio.transferCardReaderStatusReq() for the response returned.
  */
 TEST_P(SapHidlTest, transferCardReaderStatusReq) {
+    LOG(DEBUG) << "transferCardReaderStatusReq";
     token = GetRandomSerialNumber();
 
     sap->transferCardReaderStatusReq(token);
@@ -122,12 +136,14 @@
 
     ASSERT_TRUE(CheckAnyOfErrors(
         sapCb->sapResultCode, {SapResultCode::GENERIC_FAILURE, SapResultCode::DATA_NOT_AVAILABLE}));
+    LOG(DEBUG) << "transferCardReaderStatusReq finished";
 }
 
 /*
  * Test IRadio.setTransferProtocolReq() for the response returned.
  */
 TEST_P(SapHidlTest, setTransferProtocolReq) {
+    LOG(DEBUG) << "setTransferProtocolReq";
     token = GetRandomSerialNumber();
     SapTransferProtocol sapTransferProtocol = SapTransferProtocol::T0;
 
@@ -136,4 +152,5 @@
     EXPECT_EQ(sapCb->sapResponseToken, token);
 
     EXPECT_EQ(SapResultCode::NOT_SUPPORTED, sapCb->sapResultCode);
+    LOG(DEBUG) << "setTransferProtocolReq finished";
 }
diff --git a/radio/1.0/vts/functional/vts_hal_radio_target_test.xml b/radio/1.0/vts/functional/vts_hal_radio_target_test.xml
index b91119d..82af2ee 100644
--- a/radio/1.0/vts/functional/vts_hal_radio_target_test.xml
+++ b/radio/1.0/vts/functional/vts_hal_radio_target_test.xml
@@ -30,5 +30,6 @@
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
         <option name="module-name" value="VtsHalRadioV1_0TargetTest" />
+        <option name="native-test-timeout" value="300000" /> <!-- 5 min -->
     </test>
 </configuration>
diff --git a/radio/1.0/vts/functional/vts_hal_sap_target_test.xml b/radio/1.0/vts/functional/vts_hal_sap_target_test.xml
index 876e1fb..d7d4477 100644
--- a/radio/1.0/vts/functional/vts_hal_sap_target_test.xml
+++ b/radio/1.0/vts/functional/vts_hal_sap_target_test.xml
@@ -22,6 +22,8 @@
     <target_preparer class="com.android.tradefed.targetprep.MultiSimPreparer" />
     <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
 
+    <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup"/>
+
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
         <option name="push" value="VtsHalSapV1_0TargetTest->/data/local/tmp/VtsHalSapV1_0TargetTest" />
diff --git a/radio/1.0/vts/functional/vts_test_util.cpp b/radio/1.0/vts/functional/vts_test_util.cpp
index ec96e5f..7a21a40 100644
--- a/radio/1.0/vts/functional/vts_test_util.cpp
+++ b/radio/1.0/vts/functional/vts_test_util.cpp
@@ -13,6 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#define LOG_TAG "RadioTest"
+
 #include <vts_test_util.h>
 #include <iostream>
 
@@ -53,4 +55,27 @@
         }
     }
     return testing::AssertionFailure() << "SapError:" + 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;
 }
\ No newline at end of file
diff --git a/radio/1.0/vts/functional/vts_test_util.h b/radio/1.0/vts/functional/vts_test_util.h
index 05b47c9..df8dd77 100644
--- a/radio/1.0/vts/functional/vts_test_util.h
+++ b/radio/1.0/vts/functional/vts_test_util.h
@@ -17,6 +17,7 @@
 #include <android-base/logging.h>
 
 #include <android/hardware/radio/1.0/types.h>
+#include <android/log.h>
 #include <gtest/gtest.h>
 
 using ::android::hardware::radio::V1_0::RadioError;
@@ -31,6 +32,8 @@
     CHECK_SAP_ERROR = 4,
 };
 
+static constexpr const char* FEATURE_VOICE_CALL = "android.software.connectionservice";
+
 /*
  * Generate random serial number for radio test
  */
@@ -47,3 +50,8 @@
  * vendor/devices implementations.
  */
 ::testing::AssertionResult CheckAnyOfErrors(SapResultCode err, std::vector<SapResultCode> errors);
+
+/*
+ * Check if device supports feature.
+ */
+bool deviceSupportsFeature(const char* feature);
diff --git a/radio/1.1/Android.bp b/radio/1.1/Android.bp
index 28388b0..b325015 100644
--- a/radio/1.1/Android.bp
+++ b/radio/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.radio@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IRadio.hal",
diff --git a/radio/1.1/vts/functional/AndroidTest.xml b/radio/1.1/vts/functional/AndroidTest.xml
index 3699575..f1bc7a8 100644
--- a/radio/1.1/vts/functional/AndroidTest.xml
+++ b/radio/1.1/vts/functional/AndroidTest.xml
@@ -29,6 +29,7 @@
 
     <test class="com.android.tradefed.testtype.GTest" >
         <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="native-test-timeout" value="300000" /> <!-- 5 min -->
         <option name="module-name" value="VtsHalRadioV1_1TargetTest" />
     </test>
 </configuration>
diff --git a/radio/1.1/vts/functional/radio_hidl_hal_api.cpp b/radio/1.1/vts/functional/radio_hidl_hal_api.cpp
index 02dcbab..08121fd 100644
--- a/radio/1.1/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.1/vts/functional/radio_hidl_hal_api.cpp
@@ -49,7 +49,6 @@
         }
         EXPECT_EQ(CardState::ABSENT, cardStatus.cardState);
     }
-#endif
 
     /* Test setSimCardPower power up */
     serial = GetRandomSerialNumber();
@@ -60,6 +59,7 @@
     ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_1->rspInfo.error,
                                  {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED,
                                   RadioError::INVALID_ARGUMENTS, RadioError::RADIO_NOT_AVAILABLE}));
+#endif
 
     /**
      * If the sim card status for the testing environment is PRESENT,
diff --git a/radio/1.2/Android.bp b/radio/1.2/Android.bp
index 28e6b26..0a4caf1 100644
--- a/radio/1.2/Android.bp
+++ b/radio/1.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.radio@1.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IRadio.hal",
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
index c81a8d9..acb1b0e 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
@@ -735,7 +735,7 @@
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_2->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_2->rspInfo.serial);
 
-    ALOGI("getVoiceRegistrationStateResponse_1_2, rspInfo.error = %s\n",
+    ALOGI("getDataRegistrationStateResponse_1_2, rspInfo.error = %s\n",
           toString(radioRsp_v1_2->rspInfo.error).c_str());
     ASSERT_TRUE(CheckAnyOfErrors(
         radioRsp_v1_2->rspInfo.error,
diff --git a/radio/1.3/Android.bp b/radio/1.3/Android.bp
index b6af874..1c8e6c2 100644
--- a/radio/1.3/Android.bp
+++ b/radio/1.3/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.radio@1.3",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IRadio.hal",
diff --git a/radio/1.4/Android.bp b/radio/1.4/Android.bp
index ff2e0d6..6c3a7d2 100644
--- a/radio/1.4/Android.bp
+++ b/radio/1.4/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.radio@1.4",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IRadio.hal",
diff --git a/radio/1.4/types.hal b/radio/1.4/types.hal
index 393716b..a830816 100644
--- a/radio/1.4/types.hal
+++ b/radio/1.4/types.hal
@@ -1847,9 +1847,9 @@
     /**
      * SS reference signal received quality, multipled by -1.
      *
-     * Reference: 3GPP TS 38.215.
+     * Reference: 3GPP TS 38.215, 3GPP TS 38.133 section 10.
      *
-     * Range [3, 20], INT_MAX means invalid/unreported.
+     * Range [-20 dB, 43 dB], INT_MAX means invalid/unreported.
      */
     int32_t ssRsrq;
 
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
index 95136bb..3ba9b9d 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
@@ -18,10 +18,26 @@
 
 #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
 
+namespace {
+const RadioAccessSpecifier GERAN_SPECIFIER_P900 = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
+                                                   .geranBands = {GeranBands::BAND_P900},
+                                                   .channels = {1, 2}};
+const RadioAccessSpecifier GERAN_SPECIFIER_850 = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
+                                                  .geranBands = {GeranBands::BAND_850},
+                                                  .channels = {128, 129}};
+}  // namespace
+
 /*
  * Test IRadio.emergencyDial() for the response returned.
  */
 TEST_P(RadioHidlTest_v1_4, emergencyDial) {
+    if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
+        ALOGI("Skipping emergencyDial because voice call is not supported in device");
+        return;
+    } else {
+        ALOGI("Running emergencyDial because voice call is supported in device");
+    }
+
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_0::Dial dialInfo;
@@ -53,6 +69,13 @@
  * Test IRadio.emergencyDial() with specified service and its response returned.
  */
 TEST_P(RadioHidlTest_v1_4, emergencyDial_withServices) {
+    if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
+        ALOGI("Skipping emergencyDial because voice call is not supported in device");
+        return;
+    } else {
+        ALOGI("Running emergencyDial because voice call is supported in device");
+    }
+
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_0::Dial dialInfo;
@@ -85,6 +108,13 @@
  * Test IRadio.emergencyDial() with known emergency call routing and its response returned.
  */
 TEST_P(RadioHidlTest_v1_4, emergencyDial_withEmergencyRouting) {
+    if (!deviceSupportsFeature(FEATURE_VOICE_CALL)) {
+        ALOGI("Skipping emergencyDial because voice call is not supported in device");
+        return;
+    } else {
+        ALOGI("Running emergencyDial because voice call is supported in device");
+    }
+
     serial = GetRandomSerialNumber();
 
     ::android::hardware::radio::V1_0::Dial dialInfo;
@@ -178,14 +208,10 @@
 TEST_P(RadioHidlTest_v1_4, startNetworkScan) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
-                                      .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-                                      .channels = {1, 2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 60,
-            .specifiers = {specifier},
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
             .maxSearchTime = 60,
             .incrementalResults = false,
             .incrementalResultsPeriodicity = 1};
@@ -213,6 +239,11 @@
                            {RadioError::NONE, RadioError::OPERATION_NOT_ALLOWED,
                             RadioError::REQUEST_NOT_SUPPORTED}));
     }
+
+    if (radioRsp_v1_4->rspInfo.error == RadioError::NONE) {
+        ALOGI("Stop Network Scan");
+        stopNetworkScan();
+    }
 }
 
 /*
@@ -249,14 +280,10 @@
 TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval1) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
-                                      .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-                                      .channels = {1, 2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 4,
-            .specifiers = {specifier},
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
             .maxSearchTime = 60,
             .incrementalResults = false,
             .incrementalResultsPeriodicity = 1};
@@ -286,14 +313,10 @@
 TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidInterval2) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
-                                      .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-                                      .channels = {1, 2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 301,
-            .specifiers = {specifier},
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
             .maxSearchTime = 60,
             .incrementalResults = false,
             .incrementalResultsPeriodicity = 1};
@@ -322,14 +345,10 @@
 TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime1) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
-                                      .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-                                      .channels = {1, 2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 60,
-            .specifiers = {specifier},
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
             .maxSearchTime = 59,
             .incrementalResults = false,
             .incrementalResultsPeriodicity = 1};
@@ -358,14 +377,10 @@
 TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidMaxSearchTime2) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
-                                      .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-                                      .channels = {1, 2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 60,
-            .specifiers = {specifier},
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
             .maxSearchTime = 3601,
             .incrementalResults = false,
             .incrementalResultsPeriodicity = 1};
@@ -394,14 +409,10 @@
 TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity1) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
-                                      .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-                                      .channels = {1, 2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 60,
-            .specifiers = {specifier},
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
             .maxSearchTime = 600,
             .incrementalResults = true,
             .incrementalResultsPeriodicity = 0};
@@ -430,14 +441,10 @@
 TEST_P(RadioHidlTest_v1_4, startNetworkScan_InvalidPeriodicity2) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
-                                      .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-                                      .channels = {1, 2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 60,
-            .specifiers = {specifier},
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
             .maxSearchTime = 600,
             .incrementalResults = true,
             .incrementalResultsPeriodicity = 11};
@@ -466,14 +473,10 @@
 TEST_P(RadioHidlTest_v1_4, startNetworkScan_GoodRequest1) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
-                                      .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-                                      .channels = {1, 2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 60,
-            .specifiers = {specifier},
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
             // Some vendor may not support max search time of 360s.
             // This issue is tracked in b/112205669.
             .maxSearchTime = 300,
@@ -497,6 +500,11 @@
                            {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
                             RadioError::REQUEST_NOT_SUPPORTED}));
     }
+
+    if (radioRsp_v1_4->rspInfo.error == RadioError::NONE) {
+        ALOGI("Stop Network Scan");
+        stopNetworkScan();
+    }
 }
 
 /*
@@ -505,14 +513,10 @@
 TEST_P(RadioHidlTest_v1_4, startNetworkScan_GoodRequest2) {
     serial = GetRandomSerialNumber();
 
-    RadioAccessSpecifier specifier = {.radioAccessNetwork = RadioAccessNetworks::GERAN,
-                                      .geranBands = {GeranBands::BAND_450, GeranBands::BAND_480},
-                                      .channels = {1, 2}};
-
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 60,
-            .specifiers = {specifier},
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
             // Some vendor may not support max search time of 360s.
             // This issue is tracked in b/112205669.
             .maxSearchTime = 300,
@@ -538,6 +542,11 @@
                            {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
                             RadioError::REQUEST_NOT_SUPPORTED}));
     }
+
+    if (radioRsp_v1_4->rspInfo.error == RadioError::NONE) {
+        ALOGI("Stop Network Scan");
+        stopNetworkScan();
+    }
 }
 
 /*
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
index 15a0b24..4ac6cc9 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_test.cpp
@@ -107,3 +107,9 @@
     radio_v1_4->getIccCardStatus(serial);
     EXPECT_EQ(std::cv_status::no_timeout, wait());
 }
+
+void RadioHidlTest_v1_4::stopNetworkScan() {
+    serial = GetRandomSerialNumber();
+    radio_v1_4->stopNetworkScan(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+}
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
index 31b7e13..53a5845 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
+++ b/radio/1.4/vts/functional/radio_hidl_hal_utils_v1_4.h
@@ -721,7 +721,10 @@
     /* Update Sim Card Status */
     void updateSimCardStatus();
 
-   public:
+    /* Stop Network Scan Command */
+    void stopNetworkScan();
+
+  public:
     virtual void SetUp() override;
 
     /* Used as a mechanism to inform the test about data/event callback */
diff --git a/radio/1.5/Android.bp b/radio/1.5/Android.bp
index 06a2a6e..0542924 100644
--- a/radio/1.5/Android.bp
+++ b/radio/1.5/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.radio@1.5",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IRadio.hal",
diff --git a/radio/1.5/types.hal b/radio/1.5/types.hal
index b061bd5..c1f3f03 100644
--- a/radio/1.5/types.hal
+++ b/radio/1.5/types.hal
@@ -107,9 +107,9 @@
     SSRSRP = 6,
     /**
      * 5G SS reference signal received quality.
-     * Range: -20 dB to -3 dB.
+     * Range: -43 dB to 20 dB.
      * Used RAN: NGRAN
-     * Reference: 3GPP TS 38.215.
+     * Reference: 3GPP TS 38.215, 3GPP TS 38.133 section 10
      */
     SSRSRQ = 7,
     /**
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
index 32c02cb..24b7fd5 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <android-base/properties.h>
 #include <radio_hidl_hal_utils_v1_5.h>
 
 #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
@@ -248,7 +249,7 @@
     signalThresholdInfo.signalMeasurement = SignalMeasurementType::SSRSRQ;
     signalThresholdInfo.hysteresisMs = 5000;
     signalThresholdInfo.hysteresisDb = 0;
-    signalThresholdInfo.thresholds = {-15, -10, -5, -4};
+    signalThresholdInfo.thresholds = {-43, -20, 0, 20};
     signalThresholdInfo.isEnabled = true;
 
     Return<void> res = radio_v1_5->setSignalStrengthReportingCriteria_1_5(
@@ -502,15 +503,21 @@
 TEST_P(RadioHidlTest_v1_5, setSystemSelectionChannels_1_5) {
     serial = GetRandomSerialNumber();
 
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
-    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
-
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
+    bandP900.geranBands() = {GeranBands::BAND_P900};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
+    band850.geranBands() = {GeranBands::BAND_850};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
             .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
-            .bands = rasBands,
+            .bands = bandP900,
             .channels = {1, 2}};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = band850,
+            .channels = {128, 129}};
 
-    Return<void> res = radio_v1_5->setSystemSelectionChannels_1_5(serial, true, {specifier});
+    Return<void> res =
+            radio_v1_5->setSystemSelectionChannels_1_5(serial, true, {specifierP900, specifier850});
     ASSERT_OK(res);
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
@@ -523,7 +530,8 @@
 
     if (radioRsp_v1_5->rspInfo.error == RadioError::NONE) {
         serial = GetRandomSerialNumber();
-        Return<void> res = radio_v1_5->setSystemSelectionChannels_1_5(serial, false, {specifier});
+        Return<void> res = radio_v1_5->setSystemSelectionChannels_1_5(
+                serial, false, {specifierP900, specifier850});
         ASSERT_OK(res);
         EXPECT_EQ(std::cv_status::no_timeout, wait());
         EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
@@ -540,18 +548,23 @@
 TEST_P(RadioHidlTest_v1_5, startNetworkScan) {
     serial = GetRandomSerialNumber();
 
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
-    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
-
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
+    bandP900.geranBands() = {GeranBands::BAND_P900};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
+    band850.geranBands() = {GeranBands::BAND_850};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
             .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
-            .bands = rasBands,
+            .bands = bandP900,
             .channels = {1, 2}};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = band850,
+            .channels = {128, 129}};
 
     ::android::hardware::radio::V1_5::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 60,
-            .specifiers = {specifier},
+            .specifiers = {specifierP900, specifier850},
             .maxSearchTime = 60,
             .incrementalResults = false,
             .incrementalResultsPeriodicity = 1};
@@ -573,6 +586,11 @@
         ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
                                      {RadioError::NONE, RadioError::OPERATION_NOT_ALLOWED}));
     }
+
+    if (radioRsp_v1_5->rspInfo.error == RadioError::NONE) {
+        ALOGI("Stop Network Scan");
+        stopNetworkScan();
+    }
 }
 
 /*
@@ -608,18 +626,23 @@
 TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidInterval1) {
     serial = GetRandomSerialNumber();
 
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
-    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
-
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
+    bandP900.geranBands() = {GeranBands::BAND_P900};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
+    band850.geranBands() = {GeranBands::BAND_850};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
             .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
-            .bands = rasBands,
+            .bands = bandP900,
             .channels = {1, 2}};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = band850,
+            .channels = {128, 129}};
 
     ::android::hardware::radio::V1_5::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 4,
-            .specifiers = {specifier},
+            .specifiers = {specifierP900, specifier850},
             .maxSearchTime = 60,
             .incrementalResults = false,
             .incrementalResultsPeriodicity = 1};
@@ -647,18 +670,23 @@
 TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidInterval2) {
     serial = GetRandomSerialNumber();
 
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
-    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
-
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
+    bandP900.geranBands() = {GeranBands::BAND_P900};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
+    band850.geranBands() = {GeranBands::BAND_850};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
             .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
-            .bands = rasBands,
+            .bands = bandP900,
             .channels = {1, 2}};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = band850,
+            .channels = {128, 129}};
 
     ::android::hardware::radio::V1_5::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 301,
-            .specifiers = {specifier},
+            .specifiers = {specifierP900, specifier850},
             .maxSearchTime = 60,
             .incrementalResults = false,
             .incrementalResultsPeriodicity = 1};
@@ -686,18 +714,23 @@
 TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidMaxSearchTime1) {
     serial = GetRandomSerialNumber();
 
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
-    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
-
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
+    bandP900.geranBands() = {GeranBands::BAND_P900};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
+    band850.geranBands() = {GeranBands::BAND_850};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
             .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
-            .bands = rasBands,
+            .bands = bandP900,
             .channels = {1, 2}};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = band850,
+            .channels = {128, 129}};
 
     ::android::hardware::radio::V1_5::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 60,
-            .specifiers = {specifier},
+            .specifiers = {specifierP900, specifier850},
             .maxSearchTime = 59,
             .incrementalResults = false,
             .incrementalResultsPeriodicity = 1};
@@ -725,18 +758,23 @@
 TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidMaxSearchTime2) {
     serial = GetRandomSerialNumber();
 
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
-    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
-
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
+    bandP900.geranBands() = {GeranBands::BAND_P900};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
+    band850.geranBands() = {GeranBands::BAND_850};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
             .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
-            .bands = rasBands,
+            .bands = bandP900,
             .channels = {1, 2}};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = band850,
+            .channels = {128, 129}};
 
     ::android::hardware::radio::V1_5::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 60,
-            .specifiers = {specifier},
+            .specifiers = {specifierP900, specifier850},
             .maxSearchTime = 3601,
             .incrementalResults = false,
             .incrementalResultsPeriodicity = 1};
@@ -764,18 +802,23 @@
 TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidPeriodicity1) {
     serial = GetRandomSerialNumber();
 
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
-    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
-
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
+    bandP900.geranBands() = {GeranBands::BAND_P900};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
+    band850.geranBands() = {GeranBands::BAND_850};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
             .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
-            .bands = rasBands,
+            .bands = bandP900,
             .channels = {1, 2}};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = band850,
+            .channels = {128, 129}};
 
     ::android::hardware::radio::V1_5::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 60,
-            .specifiers = {specifier},
+            .specifiers = {specifierP900, specifier850},
             .maxSearchTime = 600,
             .incrementalResults = true,
             .incrementalResultsPeriodicity = 0};
@@ -803,18 +846,23 @@
 TEST_P(RadioHidlTest_v1_5, startNetworkScan_InvalidPeriodicity2) {
     serial = GetRandomSerialNumber();
 
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
-    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
-
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
+    bandP900.geranBands() = {GeranBands::BAND_P900};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
+    band850.geranBands() = {GeranBands::BAND_850};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
             .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
-            .bands = rasBands,
+            .bands = bandP900,
             .channels = {1, 2}};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = band850,
+            .channels = {128, 129}};
 
     ::android::hardware::radio::V1_5::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 60,
-            .specifiers = {specifier},
+            .specifiers = {specifierP900, specifier850},
             .maxSearchTime = 600,
             .incrementalResults = true,
             .incrementalResultsPeriodicity = 11};
@@ -842,18 +890,23 @@
 TEST_P(RadioHidlTest_v1_5, startNetworkScan_GoodRequest1) {
     serial = GetRandomSerialNumber();
 
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
-    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
-
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
+    bandP900.geranBands() = {GeranBands::BAND_P900};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
+    band850.geranBands() = {GeranBands::BAND_850};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
             .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
-            .bands = rasBands,
+            .bands = bandP900,
             .channels = {1, 2}};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = band850,
+            .channels = {128, 129}};
 
     ::android::hardware::radio::V1_5::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 60,
-            .specifiers = {specifier},
+            .specifiers = {specifierP900, specifier850},
             .maxSearchTime = 360,
             .incrementalResults = false,
             .incrementalResultsPeriodicity = 10};
@@ -873,6 +926,11 @@
                                      {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
                                       RadioError::REQUEST_NOT_SUPPORTED}));
     }
+
+    if (radioRsp_v1_5->rspInfo.error == RadioError::NONE) {
+        ALOGI("Stop Network Scan");
+        stopNetworkScan();
+    }
 }
 
 /*
@@ -881,18 +939,23 @@
 TEST_P(RadioHidlTest_v1_5, startNetworkScan_GoodRequest2) {
     serial = GetRandomSerialNumber();
 
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands rasBands;
-    rasBands.geranBands() = {GeranBands::BAND_450, GeranBands::BAND_480};
-
-    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier = {
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands bandP900;
+    bandP900.geranBands() = {GeranBands::BAND_P900};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier::Bands band850;
+    band850.geranBands() = {GeranBands::BAND_850};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifierP900 = {
             .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
-            .bands = rasBands,
+            .bands = bandP900,
             .channels = {1, 2}};
+    ::android::hardware::radio::V1_5::RadioAccessSpecifier specifier850 = {
+            .radioAccessNetwork = ::android::hardware::radio::V1_5::RadioAccessNetworks::GERAN,
+            .bands = band850,
+            .channels = {128, 129}};
 
     ::android::hardware::radio::V1_5::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 60,
-            .specifiers = {specifier},
+            .specifiers = {specifierP900, specifier850},
             .maxSearchTime = 360,
             .incrementalResults = false,
             .incrementalResultsPeriodicity = 10,
@@ -913,6 +976,11 @@
                                      {RadioError::NONE, RadioError::INVALID_ARGUMENTS,
                                       RadioError::REQUEST_NOT_SUPPORTED}));
     }
+
+    if (radioRsp_v1_5->rspInfo.error == RadioError::NONE) {
+        ALOGI("Stop Network Scan");
+        stopNetworkScan();
+    }
 }
 
 /*
@@ -1174,6 +1242,17 @@
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
 
+    int32_t firstApiLevel = android::base::GetIntProperty<int32_t>("ro.product.first_api_level", 0);
+    // Allow devices shipping with Radio::1_5 and Android 11 to not support barring info.
+    if (firstApiLevel > 0 && firstApiLevel <= 30) {
+        ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                                     {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+        // Early exit for devices that don't support barring info.
+        if (radioRsp_v1_5->rspInfo.error != RadioError::NONE) {
+            return;
+        }
+    }
+
     ASSERT_TRUE(radioRsp_v1_5->barringInfos.size() > 0);
 
     std::set<BarringInfo::ServiceType> reportedServices;
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_test.cpp b/radio/1.5/vts/functional/radio_hidl_hal_test.cpp
index 7313de4..4155550 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_test.cpp
@@ -78,3 +78,9 @@
     radio_v1_5->getIccCardStatus(serial);
     EXPECT_EQ(std::cv_status::no_timeout, wait());
 }
+
+void RadioHidlTest_v1_5::stopNetworkScan() {
+    serial = GetRandomSerialNumber();
+    radio_v1_5->stopNetworkScan(serial);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+}
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h b/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
index 6a369cc..87ce675 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
+++ b/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
@@ -831,6 +831,9 @@
     /* Update Sim Card Status */
     void updateSimCardStatus();
 
+    /* Stop Network Scan Command */
+    void stopNetworkScan();
+
   public:
     virtual void SetUp() override;
 
diff --git a/radio/1.5/vts/functional/radio_response.cpp b/radio/1.5/vts/functional/radio_response.cpp
index 8cbb2d0..9b6d450 100644
--- a/radio/1.5/vts/functional/radio_response.cpp
+++ b/radio/1.5/vts/functional/radio_response.cpp
@@ -1017,8 +1017,10 @@
     return Void();
 }
 
-Return<void> RadioResponse_v1_5::sendCdmaSmsExpectMoreResponse(const RadioResponseInfo& /*info*/,
+Return<void> RadioResponse_v1_5::sendCdmaSmsExpectMoreResponse(const RadioResponseInfo& info,
                                                                const SendSmsResult& /*sms*/) {
+    rspInfo = info;
+    parent_v1_5.notify(info.serial);
     return Void();
 }
 
diff --git a/radio/1.6/Android.bp b/radio/1.6/Android.bp
new file mode 100644
index 0000000..b363f57
--- /dev/null
+++ b/radio/1.6/Android.bp
@@ -0,0 +1,22 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.radio@1.6",
+    root: "android.hardware",
+    srcs: [
+        "types.hal",
+        "IRadio.hal",
+        "IRadioIndication.hal",
+        "IRadioResponse.hal",
+    ],
+    interfaces: [
+        "android.hardware.radio@1.0",
+        "android.hardware.radio@1.1",
+        "android.hardware.radio@1.2",
+        "android.hardware.radio@1.3",
+        "android.hardware.radio@1.4",
+        "android.hardware.radio@1.5",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/radio/1.6/IRadio.hal b/radio/1.6/IRadio.hal
new file mode 100644
index 0000000..a084b92
--- /dev/null
+++ b/radio/1.6/IRadio.hal
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.radio@1.6;
+
+import @1.5::IRadio;
+
+/**
+ * This interface is used by telephony and telecom to talk to cellular radio.
+ * All the functions have minimum one parameter:
+ * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
+ * duration of a method call. If clients provide colliding serials (including passing the same
+ * serial to different methods), multiple responses (one for each method call) must still be served.
+ * setResponseFunctions must work with @1.6:IRadioResponse and @1.6::IRadioIndication.
+ */
+interface IRadio extends @1.5::IRadio {
+};
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/radio/1.6/IRadioIndication.hal
similarity index 69%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to radio/1.6/IRadioIndication.hal
index 7edec47..9951dd9 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/radio/1.6/IRadioIndication.hal
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+package android.hardware.radio@1.6;
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+import @1.5::IRadioIndication;
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+/**
+ * Interface declaring unsolicited radio indications.
+ */
+interface IRadioIndication extends @1.5::IRadioIndication {
+};
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/radio/1.6/IRadioResponse.hal
similarity index 69%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to radio/1.6/IRadioResponse.hal
index 7edec47..a67aa3f 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/radio/1.6/IRadioResponse.hal
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+package android.hardware.radio@1.6;
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+import @1.5::IRadioResponse;
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+/**
+ * Interface declaring response functions to solicited radio requests.
+ */
+interface IRadioResponse extends @1.5::IRadioResponse {
+};
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/radio/1.6/types.hal
similarity index 69%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to radio/1.6/types.hal
index 7edec47..3395619 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/radio/1.6/types.hal
@@ -14,13 +14,4 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
-
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
-
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+package android.hardware.radio@1.6;
diff --git a/radio/1.6/vts/OWNERS b/radio/1.6/vts/OWNERS
new file mode 100644
index 0000000..3629a6c
--- /dev/null
+++ b/radio/1.6/vts/OWNERS
@@ -0,0 +1,10 @@
+# Telephony team
+refuhoo@google.com
+amitmahajan@google.com
+jackyu@google.com
+fionaxu@google.com
+# more to add
+
+# VTS team
+yuexima@google.com
+dshi@google.com
\ No newline at end of file
diff --git a/radio/1.6/vts/functional/Android.bp b/radio/1.6/vts/functional/Android.bp
new file mode 100644
index 0000000..a6cfc6f
--- /dev/null
+++ b/radio/1.6/vts/functional/Android.bp
@@ -0,0 +1,41 @@
+//
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalRadioV1_6TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "radio_hidl_hal_api.cpp",
+        "radio_hidl_hal_test.cpp",
+        "radio_response.cpp",
+        "radio_indication.cpp",
+        "VtsHalRadioV1_6TargetTest.cpp",
+    ],
+    static_libs: [
+        "RadioVtsTestUtilBase",
+        "android.hardware.radio@1.6",
+        "android.hardware.radio@1.5",
+        "android.hardware.radio@1.4",
+        "android.hardware.radio@1.3",
+        "android.hardware.radio@1.2",
+        "android.hardware.radio@1.1",
+        "android.hardware.radio@1.0",
+        "android.hardware.radio.config@1.0",
+        "android.hardware.radio.config@1.1",
+    ],
+    header_libs: ["radio.util.header@1.0"],
+    test_suites: ["general-tests", "vts"]
+}
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/radio/1.6/vts/functional/VtsHalRadioV1_6TargetTest.cpp
similarity index 64%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to radio/1.6/vts/functional/VtsHalRadioV1_6TargetTest.cpp
index 7edec47..12cefd6 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/radio/1.6/vts/functional/VtsHalRadioV1_6TargetTest.cpp
@@ -14,13 +14,9 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#include <radio_hidl_hal_utils_v1_6.h>
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
-
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+INSTANTIATE_TEST_SUITE_P(PerInstance, RadioHidlTest_v1_6,
+                         testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+                                 android::hardware::radio::V1_6::IRadio::descriptor)),
+                         android::hardware::PrintInstanceNameToString);
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
similarity index 69%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to radio/1.6/vts/functional/radio_hidl_hal_api.cpp
index 7edec47..8ed56ed 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -14,13 +14,6 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+#include <radio_hidl_hal_utils_v1_6.h>
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
-
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_test.cpp b/radio/1.6/vts/functional/radio_hidl_hal_test.cpp
new file mode 100644
index 0000000..e9a4542
--- /dev/null
+++ b/radio/1.6/vts/functional/radio_hidl_hal_test.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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 <radio_hidl_hal_utils_v1_6.h>
+
+void RadioHidlTest_v1_6::SetUp() {
+    radio_v1_6 = android::hardware::radio::V1_6::IRadio::getService(GetParam());
+    ASSERT_NE(nullptr, radio_v1_6.get());
+
+    radioRsp_v1_6 = new (std::nothrow) RadioResponse_v1_6(*this);
+    ASSERT_NE(nullptr, radioRsp_v1_6.get());
+
+    count_ = 0;
+
+    radioInd_v1_6 = new (std::nothrow) RadioIndication_v1_6(*this);
+    ASSERT_NE(nullptr, radioInd_v1_6.get());
+
+    radio_v1_6->setResponseFunctions(radioRsp_v1_6, radioInd_v1_6);
+
+    getDataCallList();
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+    EXPECT_EQ(RadioError::NONE, radioRsp_v1_6->rspInfo.error);
+
+    sp<::android::hardware::radio::config::V1_1::IRadioConfig> radioConfig =
+            ::android::hardware::radio::config::V1_1::IRadioConfig::getService();
+    /* Enforce Vts testing with RadioConfig is existed. */
+    ASSERT_NE(nullptr, radioConfig.get());
+
+    /* Enforce Vts Testing with Sim Status Present only. */
+    EXPECT_EQ(CardState::PRESENT, cardStatus.base.base.base.cardState);
+}
+
+/*
+ * Notify that the response message is received.
+ */
+void RadioHidlTest_v1_6::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 TIMEOUT_PERIOD.
+ */
+std::cv_status RadioHidlTest_v1_6::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(TIMEOUT_PERIOD));
+        if (status == std::cv_status::timeout) {
+            return status;
+        }
+    }
+    count_--;
+    return status;
+}
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h b/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
new file mode 100644
index 0000000..66846ea
--- /dev/null
+++ b/radio/1.6/vts/functional/radio_hidl_hal_utils_v1_6.h
@@ -0,0 +1,856 @@
+/*
+ * 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/logging.h>
+
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+#include <utils/Log.h>
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
+#include <android/hardware/radio/config/1.1/IRadioConfig.h>
+
+#include <android/hardware/radio/1.6/IRadio.h>
+#include <android/hardware/radio/1.6/IRadioIndication.h>
+#include <android/hardware/radio/1.6/IRadioResponse.h>
+#include <android/hardware/radio/1.6/types.h>
+
+#include "vts_test_util.h"
+
+using namespace ::android::hardware::radio::V1_6;
+using namespace ::android::hardware::radio::V1_5;
+using namespace ::android::hardware::radio::V1_4;
+using namespace ::android::hardware::radio::V1_3;
+using namespace ::android::hardware::radio::V1_2;
+using namespace ::android::hardware::radio::V1_1;
+using namespace ::android::hardware::radio::V1_0;
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+#define TIMEOUT_PERIOD 75
+#define MODEM_EMERGENCY_CALL_ESTABLISH_TIME 3
+#define MODEM_EMERGENCY_CALL_DISCONNECT_TIME 3
+
+#define RADIO_SERVICE_NAME "slot1"
+
+class RadioHidlTest_v1_6;
+extern ::android::hardware::radio::V1_5::CardStatus cardStatus;
+
+/* Callback class for radio response v1_5 */
+class RadioResponse_v1_6 : public ::android::hardware::radio::V1_6::IRadioResponse {
+  protected:
+    RadioHidlTest_v1_6& parent_v1_6;
+
+  public:
+    hidl_vec<RadioBandMode> radioBandModes;
+
+    RadioResponseInfo rspInfo;
+
+    // Call
+    hidl_vec<::android::hardware::radio::V1_2::Call> currentCalls;
+
+    // Modem
+    bool isModemEnabled;
+    bool enableModemResponseToggle;
+
+    ::android::hardware::hidl_bitfield<::android::hardware::radio::V1_4::RadioAccessFamily>
+            networkTypeBitmapResponse;
+
+    // Data
+    ::android::hardware::radio::V1_4::DataRegStateResult dataRegResp;
+
+    // SimLock status
+    ::android::hardware::radio::V1_4::CarrierRestrictionsWithPriority carrierRestrictionsResp;
+    ::android::hardware::radio::V1_4::SimLockMultiSimPolicy multiSimPolicyResp;
+
+    // Whether toggling uicc applications operation is supported.
+    bool canToggleUiccApplicationsEnablement;
+
+    // Whether Uicc applications are enabled or not.
+    bool areUiccApplicationsEnabled;
+
+    // Barring Info Response
+    ::android::hardware::radio::V1_5::CellIdentity barringCellIdentity;
+    ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::BarringInfo> barringInfos;
+
+    RadioResponse_v1_6(RadioHidlTest_v1_6& parent_v1_6);
+    virtual ~RadioResponse_v1_6() = default;
+
+    Return<void> getIccCardStatusResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_0::CardStatus& cardStatus);
+
+    Return<void> supplyIccPinForAppResponse(const RadioResponseInfo& info,
+                                            int32_t remainingRetries);
+
+    Return<void> supplyIccPukForAppResponse(const RadioResponseInfo& info,
+                                            int32_t remainingRetries);
+
+    Return<void> supplyIccPin2ForAppResponse(const RadioResponseInfo& info,
+                                             int32_t remainingRetries);
+
+    Return<void> supplyIccPuk2ForAppResponse(const RadioResponseInfo& info,
+                                             int32_t remainingRetries);
+
+    Return<void> changeIccPinForAppResponse(const RadioResponseInfo& info,
+                                            int32_t remainingRetries);
+
+    Return<void> changeIccPin2ForAppResponse(const RadioResponseInfo& info,
+                                             int32_t remainingRetries);
+
+    Return<void> supplyNetworkDepersonalizationResponse(const RadioResponseInfo& info,
+                                                        int32_t remainingRetries);
+
+    Return<void> getCurrentCallsResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::Call>& calls);
+
+    Return<void> dialResponse(const RadioResponseInfo& info);
+
+    Return<void> getIMSIForAppResponse(const RadioResponseInfo& info,
+                                       const ::android::hardware::hidl_string& imsi);
+
+    Return<void> hangupConnectionResponse(const RadioResponseInfo& info);
+
+    Return<void> hangupWaitingOrBackgroundResponse(const RadioResponseInfo& info);
+
+    Return<void> hangupForegroundResumeBackgroundResponse(const RadioResponseInfo& info);
+
+    Return<void> switchWaitingOrHoldingAndActiveResponse(const RadioResponseInfo& info);
+
+    Return<void> conferenceResponse(const RadioResponseInfo& info);
+
+    Return<void> rejectCallResponse(const RadioResponseInfo& info);
+
+    Return<void> getLastCallFailCauseResponse(const RadioResponseInfo& info,
+                                              const LastCallFailCauseInfo& failCauseInfo);
+
+    Return<void> getSignalStrengthResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_0::SignalStrength& sigStrength);
+
+    Return<void> getVoiceRegistrationStateResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_0::VoiceRegStateResult& voiceRegResponse);
+
+    Return<void> getDataRegistrationStateResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_0::DataRegStateResult& dataRegResponse);
+
+    Return<void> getOperatorResponse(const RadioResponseInfo& info,
+                                     const ::android::hardware::hidl_string& longName,
+                                     const ::android::hardware::hidl_string& shortName,
+                                     const ::android::hardware::hidl_string& numeric);
+
+    Return<void> setRadioPowerResponse(const RadioResponseInfo& info);
+
+    Return<void> sendDtmfResponse(const RadioResponseInfo& info);
+
+    Return<void> sendSmsResponse(const RadioResponseInfo& info, const SendSmsResult& sms);
+
+    Return<void> sendSMSExpectMoreResponse(const RadioResponseInfo& info, const SendSmsResult& sms);
+
+    Return<void> setupDataCallResponse(
+            const RadioResponseInfo& info,
+            const android::hardware::radio::V1_0::SetupDataCallResult& dcResponse);
+
+    Return<void> iccIOForAppResponse(const RadioResponseInfo& info, const IccIoResult& iccIo);
+
+    Return<void> sendUssdResponse(const RadioResponseInfo& info);
+
+    Return<void> cancelPendingUssdResponse(const RadioResponseInfo& info);
+
+    Return<void> getClirResponse(const RadioResponseInfo& info, int32_t n, int32_t m);
+
+    Return<void> setClirResponse(const RadioResponseInfo& info);
+
+    Return<void> getCallForwardStatusResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<CallForwardInfo>& call_forwardInfos);
+
+    Return<void> setCallForwardResponse(const RadioResponseInfo& info);
+
+    Return<void> getCallWaitingResponse(const RadioResponseInfo& info, bool enable,
+                                        int32_t serviceClass);
+
+    Return<void> setCallWaitingResponse(const RadioResponseInfo& info);
+
+    Return<void> acknowledgeLastIncomingGsmSmsResponse(const RadioResponseInfo& info);
+
+    Return<void> acceptCallResponse(const RadioResponseInfo& info);
+
+    Return<void> deactivateDataCallResponse(const RadioResponseInfo& info);
+
+    Return<void> getFacilityLockForAppResponse(const RadioResponseInfo& info, int32_t response);
+
+    Return<void> setFacilityLockForAppResponse(const RadioResponseInfo& info, int32_t retry);
+
+    Return<void> setBarringPasswordResponse(const RadioResponseInfo& info);
+
+    Return<void> getNetworkSelectionModeResponse(const RadioResponseInfo& info, bool manual);
+
+    Return<void> setNetworkSelectionModeAutomaticResponse(const RadioResponseInfo& info);
+
+    Return<void> setNetworkSelectionModeManualResponse(const RadioResponseInfo& info);
+
+    Return<void> getAvailableNetworksResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<OperatorInfo>& networkInfos);
+
+    Return<void> startDtmfResponse(const RadioResponseInfo& info);
+
+    Return<void> stopDtmfResponse(const RadioResponseInfo& info);
+
+    Return<void> getBasebandVersionResponse(const RadioResponseInfo& info,
+                                            const ::android::hardware::hidl_string& version);
+
+    Return<void> separateConnectionResponse(const RadioResponseInfo& info);
+
+    Return<void> setMuteResponse(const RadioResponseInfo& info);
+
+    Return<void> getMuteResponse(const RadioResponseInfo& info, bool enable);
+
+    Return<void> getClipResponse(const RadioResponseInfo& info, ClipStatus status);
+
+    Return<void> getDataCallListResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<
+                    android::hardware::radio::V1_0::SetupDataCallResult>& dcResponse);
+
+    Return<void> sendOemRilRequestRawResponse(const RadioResponseInfo& info,
+                                              const ::android::hardware::hidl_vec<uint8_t>& data);
+
+    Return<void> sendOemRilRequestStringsResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<::android::hardware::hidl_string>& data);
+
+    Return<void> setSuppServiceNotificationsResponse(const RadioResponseInfo& info);
+
+    Return<void> writeSmsToSimResponse(const RadioResponseInfo& info, int32_t index);
+
+    Return<void> deleteSmsOnSimResponse(const RadioResponseInfo& info);
+
+    Return<void> setBandModeResponse(const RadioResponseInfo& info);
+
+    Return<void> getAvailableBandModesResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<RadioBandMode>& bandModes);
+
+    Return<void> sendEnvelopeResponse(const RadioResponseInfo& info,
+                                      const ::android::hardware::hidl_string& commandResponse);
+
+    Return<void> sendTerminalResponseToSimResponse(const RadioResponseInfo& info);
+
+    Return<void> handleStkCallSetupRequestFromSimResponse(const RadioResponseInfo& info);
+
+    Return<void> explicitCallTransferResponse(const RadioResponseInfo& info);
+
+    Return<void> setPreferredNetworkTypeResponse(const RadioResponseInfo& info);
+
+    Return<void> getPreferredNetworkTypeResponse(const RadioResponseInfo& info,
+                                                 PreferredNetworkType nwType);
+
+    Return<void> getNeighboringCidsResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<NeighboringCell>& cells);
+
+    Return<void> setLocationUpdatesResponse(const RadioResponseInfo& info);
+
+    Return<void> setCdmaSubscriptionSourceResponse(const RadioResponseInfo& info);
+
+    Return<void> setCdmaRoamingPreferenceResponse(const RadioResponseInfo& info);
+
+    Return<void> getCdmaRoamingPreferenceResponse(const RadioResponseInfo& info,
+                                                  CdmaRoamingType type);
+
+    Return<void> setTTYModeResponse(const RadioResponseInfo& info);
+
+    Return<void> getTTYModeResponse(const RadioResponseInfo& info, TtyMode mode);
+
+    Return<void> setPreferredVoicePrivacyResponse(const RadioResponseInfo& info);
+
+    Return<void> getPreferredVoicePrivacyResponse(const RadioResponseInfo& info, bool enable);
+
+    Return<void> sendCDMAFeatureCodeResponse(const RadioResponseInfo& info);
+
+    Return<void> sendBurstDtmfResponse(const RadioResponseInfo& info);
+
+    Return<void> sendCdmaSmsResponse(const RadioResponseInfo& info, const SendSmsResult& sms);
+
+    Return<void> acknowledgeLastIncomingCdmaSmsResponse(const RadioResponseInfo& info);
+
+    Return<void> getGsmBroadcastConfigResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<GsmBroadcastSmsConfigInfo>& configs);
+
+    Return<void> setGsmBroadcastConfigResponse(const RadioResponseInfo& info);
+
+    Return<void> setGsmBroadcastActivationResponse(const RadioResponseInfo& info);
+
+    Return<void> getCdmaBroadcastConfigResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<CdmaBroadcastSmsConfigInfo>& configs);
+
+    Return<void> setCdmaBroadcastConfigResponse(const RadioResponseInfo& info);
+
+    Return<void> setCdmaBroadcastActivationResponse(const RadioResponseInfo& info);
+
+    Return<void> getCDMASubscriptionResponse(const RadioResponseInfo& info,
+                                             const ::android::hardware::hidl_string& mdn,
+                                             const ::android::hardware::hidl_string& hSid,
+                                             const ::android::hardware::hidl_string& hNid,
+                                             const ::android::hardware::hidl_string& min,
+                                             const ::android::hardware::hidl_string& prl);
+
+    Return<void> writeSmsToRuimResponse(const RadioResponseInfo& info, uint32_t index);
+
+    Return<void> deleteSmsOnRuimResponse(const RadioResponseInfo& info);
+
+    Return<void> getDeviceIdentityResponse(const RadioResponseInfo& info,
+                                           const ::android::hardware::hidl_string& imei,
+                                           const ::android::hardware::hidl_string& imeisv,
+                                           const ::android::hardware::hidl_string& esn,
+                                           const ::android::hardware::hidl_string& meid);
+
+    Return<void> exitEmergencyCallbackModeResponse(const RadioResponseInfo& info);
+
+    Return<void> getSmscAddressResponse(const RadioResponseInfo& info,
+                                        const ::android::hardware::hidl_string& smsc);
+
+    Return<void> setSmscAddressResponse(const RadioResponseInfo& info);
+
+    Return<void> reportSmsMemoryStatusResponse(const RadioResponseInfo& info);
+
+    Return<void> reportStkServiceIsRunningResponse(const RadioResponseInfo& info);
+
+    Return<void> getCdmaSubscriptionSourceResponse(const RadioResponseInfo& info,
+                                                   CdmaSubscriptionSource source);
+
+    Return<void> requestIsimAuthenticationResponse(
+            const RadioResponseInfo& info, const ::android::hardware::hidl_string& response);
+
+    Return<void> acknowledgeIncomingGsmSmsWithPduResponse(const RadioResponseInfo& info);
+
+    Return<void> sendEnvelopeWithStatusResponse(const RadioResponseInfo& info,
+                                                const IccIoResult& iccIo);
+
+    Return<void> getVoiceRadioTechnologyResponse(
+            const RadioResponseInfo& info, ::android::hardware::radio::V1_0::RadioTechnology rat);
+
+    Return<void> getCellInfoListResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::CellInfo>&
+                    cellInfo);
+
+    Return<void> setCellInfoListRateResponse(const RadioResponseInfo& info);
+
+    Return<void> setInitialAttachApnResponse(const RadioResponseInfo& info);
+
+    Return<void> getImsRegistrationStateResponse(const RadioResponseInfo& info, bool isRegistered,
+                                                 RadioTechnologyFamily ratFamily);
+
+    Return<void> sendImsSmsResponse(const RadioResponseInfo& info, const SendSmsResult& sms);
+
+    Return<void> iccTransmitApduBasicChannelResponse(const RadioResponseInfo& info,
+                                                     const IccIoResult& result);
+
+    Return<void> iccOpenLogicalChannelResponse(
+            const RadioResponseInfo& info, int32_t channelId,
+            const ::android::hardware::hidl_vec<int8_t>& selectResponse);
+
+    Return<void> iccCloseLogicalChannelResponse(const RadioResponseInfo& info);
+
+    Return<void> iccTransmitApduLogicalChannelResponse(const RadioResponseInfo& info,
+                                                       const IccIoResult& result);
+
+    Return<void> nvReadItemResponse(const RadioResponseInfo& info,
+                                    const ::android::hardware::hidl_string& result);
+
+    Return<void> nvWriteItemResponse(const RadioResponseInfo& info);
+
+    Return<void> nvWriteCdmaPrlResponse(const RadioResponseInfo& info);
+
+    Return<void> nvResetConfigResponse(const RadioResponseInfo& info);
+
+    Return<void> setUiccSubscriptionResponse(const RadioResponseInfo& info);
+
+    Return<void> setDataAllowedResponse(const RadioResponseInfo& info);
+
+    Return<void> getHardwareConfigResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<HardwareConfig>& config);
+
+    Return<void> requestIccSimAuthenticationResponse(const RadioResponseInfo& info,
+                                                     const IccIoResult& result);
+
+    Return<void> setDataProfileResponse(const RadioResponseInfo& info);
+
+    Return<void> requestShutdownResponse(const RadioResponseInfo& info);
+
+    Return<void> getRadioCapabilityResponse(
+            const RadioResponseInfo& info,
+            const android::hardware::radio::V1_0::RadioCapability& rc);
+
+    Return<void> setRadioCapabilityResponse(
+            const RadioResponseInfo& info,
+            const android::hardware::radio::V1_0::RadioCapability& rc);
+
+    Return<void> startLceServiceResponse(const RadioResponseInfo& info,
+                                         const LceStatusInfo& statusInfo);
+
+    Return<void> stopLceServiceResponse(const RadioResponseInfo& info,
+                                        const LceStatusInfo& statusInfo);
+
+    Return<void> pullLceDataResponse(const RadioResponseInfo& info, const LceDataInfo& lceInfo);
+
+    Return<void> getModemActivityInfoResponse(const RadioResponseInfo& info,
+                                              const ActivityStatsInfo& activityInfo);
+
+    Return<void> setAllowedCarriersResponse(const RadioResponseInfo& info, int32_t numAllowed);
+
+    Return<void> getAllowedCarriersResponse(const RadioResponseInfo& info, bool allAllowed,
+                                            const CarrierRestrictions& carriers);
+
+    Return<void> sendDeviceStateResponse(const RadioResponseInfo& info);
+
+    Return<void> setIndicationFilterResponse(const RadioResponseInfo& info);
+
+    Return<void> setSimCardPowerResponse(const RadioResponseInfo& info);
+
+    Return<void> acknowledgeRequest(int32_t serial);
+
+    /* 1.1 Api */
+    Return<void> setCarrierInfoForImsiEncryptionResponse(const RadioResponseInfo& info);
+
+    Return<void> setSimCardPowerResponse_1_1(const RadioResponseInfo& info);
+
+    Return<void> startNetworkScanResponse(const RadioResponseInfo& info);
+
+    Return<void> stopNetworkScanResponse(const RadioResponseInfo& info);
+
+    Return<void> startKeepaliveResponse(const RadioResponseInfo& info,
+                                        const KeepaliveStatus& status);
+
+    Return<void> stopKeepaliveResponse(const RadioResponseInfo& info);
+
+    /* 1.2 Api */
+    Return<void> setSignalStrengthReportingCriteriaResponse(const RadioResponseInfo& info);
+
+    Return<void> setLinkCapacityReportingCriteriaResponse(const RadioResponseInfo& info);
+
+    Return<void> getIccCardStatusResponse_1_2(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_2::CardStatus& card_status);
+
+    Return<void> getCurrentCallsResponse_1_2(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::Call>& calls);
+
+    Return<void> getSignalStrengthResponse_1_2(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_2::SignalStrength& sig_strength);
+
+    Return<void> getSignalStrengthResponse_1_4(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_4::SignalStrength& sig_strength);
+
+    Return<void> getCellInfoListResponse_1_2(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::CellInfo>&
+                    cellInfo);
+
+    Return<void> getVoiceRegistrationStateResponse_1_2(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_2::VoiceRegStateResult& voiceRegResponse);
+
+    Return<void> getDataRegistrationStateResponse_1_2(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_2::DataRegStateResult& dataRegResponse);
+
+    /* 1.3 Api */
+    Return<void> setSystemSelectionChannelsResponse(const RadioResponseInfo& info);
+
+    Return<void> enableModemResponse(const RadioResponseInfo& info);
+
+    Return<void> getModemStackStatusResponse(const RadioResponseInfo& info, const bool enabled);
+
+    /* 1.4 Api */
+    Return<void> emergencyDialResponse(const RadioResponseInfo& info);
+
+    Return<void> startNetworkScanResponse_1_4(const RadioResponseInfo& info);
+
+    Return<void> getCellInfoListResponse_1_4(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_4::CellInfo>&
+                    cellInfo);
+
+    Return<void> getDataRegistrationStateResponse_1_4(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_4::DataRegStateResult& dataRegResponse);
+
+    Return<void> getIccCardStatusResponse_1_4(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_4::CardStatus& card_status);
+
+    Return<void> getPreferredNetworkTypeBitmapResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_bitfield<
+                    ::android::hardware::radio::V1_4::RadioAccessFamily>
+                    networkTypeBitmap);
+
+    Return<void> setPreferredNetworkTypeBitmapResponse(const RadioResponseInfo& info);
+
+    Return<void> getDataCallListResponse_1_4(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<
+                    ::android::hardware::radio::V1_4::SetupDataCallResult>& dcResponse);
+
+    Return<void> setupDataCallResponse_1_4(
+            const RadioResponseInfo& info,
+            const android::hardware::radio::V1_4::SetupDataCallResult& dcResponse);
+
+    Return<void> setAllowedCarriersResponse_1_4(const RadioResponseInfo& info);
+
+    Return<void> getAllowedCarriersResponse_1_4(const RadioResponseInfo& info,
+                                                const CarrierRestrictionsWithPriority& carriers,
+                                                SimLockMultiSimPolicy multiSimPolicy);
+
+    /* 1.5 Api */
+    Return<void> setSignalStrengthReportingCriteriaResponse_1_5(const RadioResponseInfo& info);
+
+    Return<void> setLinkCapacityReportingCriteriaResponse_1_5(const RadioResponseInfo& info);
+
+    Return<void> enableUiccApplicationsResponse(const RadioResponseInfo& info);
+
+    Return<void> areUiccApplicationsEnabledResponse(const RadioResponseInfo& info, bool enabled);
+
+    Return<void> canToggleUiccApplicationsEnablementResponse(const RadioResponseInfo& info,
+                                                             bool canToggle);
+
+    Return<void> setSystemSelectionChannelsResponse_1_5(const RadioResponseInfo& info);
+
+    Return<void> startNetworkScanResponse_1_5(const RadioResponseInfo& info);
+
+    Return<void> setupDataCallResponse_1_5(
+            const RadioResponseInfo& info,
+            const android::hardware::radio::V1_5::SetupDataCallResult& dcResponse);
+
+    Return<void> getDataCallListResponse_1_5(
+            const RadioResponseInfo& info,
+            const hidl_vec<::android::hardware::radio::V1_5::SetupDataCallResult>& dcResponse);
+
+    Return<void> setInitialAttachApnResponse_1_5(const RadioResponseInfo& info);
+
+    Return<void> setDataProfileResponse_1_5(const RadioResponseInfo& info);
+
+    Return<void> setRadioPowerResponse_1_5(const RadioResponseInfo& info);
+
+    Return<void> setIndicationFilterResponse_1_5(const RadioResponseInfo& info);
+
+    Return<void> getBarringInfoResponse(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_5::CellIdentity& cellIdentity,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::BarringInfo>&
+                    barringInfos);
+
+    Return<void> getVoiceRegistrationStateResponse_1_5(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_5::RegStateResult& regResponse);
+
+    Return<void> getDataRegistrationStateResponse_1_5(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_5::RegStateResult& regResponse);
+
+    Return<void> getCellInfoListResponse_1_5(
+            const RadioResponseInfo& info,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::CellInfo>&
+                    cellInfo);
+
+    Return<void> setNetworkSelectionModeManualResponse_1_5(const RadioResponseInfo& info);
+
+    Return<void> sendCdmaSmsExpectMoreResponse(const RadioResponseInfo& info,
+                                               const SendSmsResult& sms);
+
+    Return<void> supplySimDepersonalizationResponse(
+            const RadioResponseInfo& info,
+            ::android::hardware::radio::V1_5::PersoSubstate persoType, int32_t remainingRetries);
+
+    Return<void> getIccCardStatusResponse_1_5(
+            const RadioResponseInfo& info,
+            const ::android::hardware::radio::V1_5::CardStatus& card_status);
+
+    /* 1.6 Api */
+};
+
+/* Callback class for radio indication */
+class RadioIndication_v1_6 : public ::android::hardware::radio::V1_6::IRadioIndication {
+  protected:
+    RadioHidlTest_v1_6& parent_v1_6;
+
+  public:
+    RadioIndication_v1_6(RadioHidlTest_v1_6& parent_v1_6);
+    virtual ~RadioIndication_v1_6() = default;
+
+    /* 1.6 Api */
+
+    /* 1.5 Api */
+    Return<void> uiccApplicationsEnablementChanged(RadioIndicationType type, bool enabled);
+
+    Return<void> networkScanResult_1_5(
+            RadioIndicationType type,
+            const ::android::hardware::radio::V1_5::NetworkScanResult& result);
+
+    Return<void> cellInfoList_1_5(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::CellInfo>&
+                    records);
+
+    Return<void> dataCallListChanged_1_5(
+            RadioIndicationType type,
+            const hidl_vec<::android::hardware::radio::V1_5::SetupDataCallResult>& dcList);
+
+    /* 1.4 Api */
+    Return<void> currentEmergencyNumberList(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<EmergencyNumber>& emergencyNumberList);
+
+    Return<void> cellInfoList_1_4(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_4::CellInfo>&
+                    records);
+
+    Return<void> networkScanResult_1_4(
+            RadioIndicationType type,
+            const ::android::hardware::radio::V1_4::NetworkScanResult& result);
+
+    Return<void> currentPhysicalChannelConfigs_1_4(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<
+                    ::android::hardware::radio::V1_4::PhysicalChannelConfig>& configs);
+
+    Return<void> dataCallListChanged_1_4(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<
+                    android::hardware::radio::V1_4::SetupDataCallResult>& dcList);
+
+    /* 1.2 Api */
+    Return<void> networkScanResult_1_2(
+            RadioIndicationType type,
+            const ::android::hardware::radio::V1_2::NetworkScanResult& result);
+
+    Return<void> cellInfoList_1_2(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::CellInfo>&
+                    records);
+
+    Return<void> currentLinkCapacityEstimate(
+            RadioIndicationType type,
+            const ::android::hardware::radio::V1_2::LinkCapacityEstimate& lce);
+
+    Return<void> currentPhysicalChannelConfigs(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<
+                    ::android::hardware::radio::V1_2::PhysicalChannelConfig>& configs);
+
+    Return<void> currentSignalStrength_1_2(
+            RadioIndicationType type,
+            const ::android::hardware::radio::V1_2::SignalStrength& signalStrength);
+
+    Return<void> currentSignalStrength_1_4(
+            RadioIndicationType type,
+            const ::android::hardware::radio::V1_4::SignalStrength& signalStrength);
+
+    /* 1.1 Api */
+    Return<void> carrierInfoForImsiEncryption(RadioIndicationType info);
+
+    Return<void> networkScanResult(
+            RadioIndicationType type,
+            const ::android::hardware::radio::V1_1::NetworkScanResult& result);
+
+    Return<void> keepaliveStatus(RadioIndicationType type, const KeepaliveStatus& status);
+
+    /* 1.0 Api */
+    Return<void> radioStateChanged(RadioIndicationType type, RadioState radioState);
+
+    Return<void> callStateChanged(RadioIndicationType type);
+
+    Return<void> networkStateChanged(RadioIndicationType type);
+
+    Return<void> newSms(RadioIndicationType type,
+                        const ::android::hardware::hidl_vec<uint8_t>& pdu);
+
+    Return<void> newSmsStatusReport(RadioIndicationType type,
+                                    const ::android::hardware::hidl_vec<uint8_t>& pdu);
+
+    Return<void> newSmsOnSim(RadioIndicationType type, int32_t recordNumber);
+
+    Return<void> onUssd(RadioIndicationType type, UssdModeType modeType,
+                        const ::android::hardware::hidl_string& msg);
+
+    Return<void> nitzTimeReceived(RadioIndicationType type,
+                                  const ::android::hardware::hidl_string& nitzTime,
+                                  uint64_t receivedTime);
+
+    Return<void> currentSignalStrength(
+            RadioIndicationType type,
+            const ::android::hardware::radio::V1_0::SignalStrength& signalStrength);
+
+    Return<void> dataCallListChanged(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<
+                    android::hardware::radio::V1_0::SetupDataCallResult>& dcList);
+
+    Return<void> suppSvcNotify(RadioIndicationType type, const SuppSvcNotification& suppSvc);
+
+    Return<void> stkSessionEnd(RadioIndicationType type);
+
+    Return<void> stkProactiveCommand(RadioIndicationType type,
+                                     const ::android::hardware::hidl_string& cmd);
+
+    Return<void> stkEventNotify(RadioIndicationType type,
+                                const ::android::hardware::hidl_string& cmd);
+
+    Return<void> stkCallSetup(RadioIndicationType type, int64_t timeout);
+
+    Return<void> simSmsStorageFull(RadioIndicationType type);
+
+    Return<void> simRefresh(RadioIndicationType type, const SimRefreshResult& refreshResult);
+
+    Return<void> callRing(RadioIndicationType type, bool isGsm, const CdmaSignalInfoRecord& record);
+
+    Return<void> simStatusChanged(RadioIndicationType type);
+
+    Return<void> cdmaNewSms(RadioIndicationType type, const CdmaSmsMessage& msg);
+
+    Return<void> newBroadcastSms(RadioIndicationType type,
+                                 const ::android::hardware::hidl_vec<uint8_t>& data);
+
+    Return<void> cdmaRuimSmsStorageFull(RadioIndicationType type);
+
+    Return<void> restrictedStateChanged(RadioIndicationType type, PhoneRestrictedState state);
+
+    Return<void> enterEmergencyCallbackMode(RadioIndicationType type);
+
+    Return<void> cdmaCallWaiting(RadioIndicationType type,
+                                 const CdmaCallWaiting& callWaitingRecord);
+
+    Return<void> cdmaOtaProvisionStatus(RadioIndicationType type, CdmaOtaProvisionStatus status);
+
+    Return<void> cdmaInfoRec(RadioIndicationType type, const CdmaInformationRecords& records);
+
+    Return<void> indicateRingbackTone(RadioIndicationType type, bool start);
+
+    Return<void> resendIncallMute(RadioIndicationType type);
+
+    Return<void> cdmaSubscriptionSourceChanged(RadioIndicationType type,
+                                               CdmaSubscriptionSource cdmaSource);
+
+    Return<void> cdmaPrlChanged(RadioIndicationType type, int32_t version);
+
+    Return<void> exitEmergencyCallbackMode(RadioIndicationType type);
+
+    Return<void> rilConnected(RadioIndicationType type);
+
+    Return<void> voiceRadioTechChanged(RadioIndicationType type,
+                                       ::android::hardware::radio::V1_0::RadioTechnology rat);
+
+    Return<void> cellInfoList(
+            RadioIndicationType type,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::CellInfo>&
+                    records);
+
+    Return<void> imsNetworkStateChanged(RadioIndicationType type);
+
+    Return<void> subscriptionStatusChanged(RadioIndicationType type, bool activate);
+
+    Return<void> srvccStateNotify(RadioIndicationType type, SrvccState state);
+
+    Return<void> hardwareConfigChanged(
+            RadioIndicationType type, const ::android::hardware::hidl_vec<HardwareConfig>& configs);
+
+    Return<void> radioCapabilityIndication(
+            RadioIndicationType type, const android::hardware::radio::V1_0::RadioCapability& rc);
+
+    Return<void> onSupplementaryServiceIndication(RadioIndicationType type,
+                                                  const StkCcUnsolSsResult& ss);
+
+    Return<void> stkCallControlAlphaNotify(RadioIndicationType type,
+                                           const ::android::hardware::hidl_string& alpha);
+
+    Return<void> lceData(RadioIndicationType type, const LceDataInfo& lce);
+
+    Return<void> pcoData(RadioIndicationType type, const PcoDataInfo& pco);
+
+    Return<void> modemReset(RadioIndicationType type,
+                            const ::android::hardware::hidl_string& reason);
+
+    Return<void> registrationFailed(
+            RadioIndicationType type,
+            const ::android::hardware::radio::V1_5::CellIdentity& cellIdentity,
+            const ::android::hardware::hidl_string& chosenPlmn,
+            ::android::hardware::hidl_bitfield<::android::hardware::radio::V1_5::Domain> domain,
+            int32_t causeCode, int32_t additionalCauseCode);
+
+    Return<void> barringInfoChanged(
+            RadioIndicationType /*type*/,
+            const ::android::hardware::radio::V1_5::CellIdentity& /*cellIdentity*/,
+            const ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::BarringInfo>&
+            /*barringInfos*/);
+};
+
+// The main test class for Radio HIDL.
+class RadioHidlTest_v1_6 : public ::testing::TestWithParam<std::string> {
+  protected:
+    std::mutex mtx_;
+    std::condition_variable cv_;
+    int count_;
+
+    /* Serial number for radio request */
+    int serial;
+
+    /* Clear Potential Established Calls */
+    void clearPotentialEstablishedCalls();
+
+    /* Get current data call list */
+    void getDataCallList();
+
+  public:
+    virtual void SetUp() override;
+
+    /* 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();
+
+    /* radio service handle */
+    sp<::android::hardware::radio::V1_6::IRadio> radio_v1_6;
+
+    /* radio response handle */
+    sp<RadioResponse_v1_6> radioRsp_v1_6;
+
+    /* radio indication handle */
+    sp<RadioIndication_v1_6> radioInd_v1_6;
+};
diff --git a/radio/1.6/vts/functional/radio_indication.cpp b/radio/1.6/vts/functional/radio_indication.cpp
new file mode 100644
index 0000000..857ea3c
--- /dev/null
+++ b/radio/1.6/vts/functional/radio_indication.cpp
@@ -0,0 +1,372 @@
+/*
+ * 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 <radio_hidl_hal_utils_v1_6.h>
+
+RadioIndication_v1_6::RadioIndication_v1_6(RadioHidlTest_v1_6& parent) : parent_v1_6(parent) {}
+
+/* 1.6 Apis */
+
+/* 1.5 Apis */
+Return<void> RadioIndication_v1_6::uiccApplicationsEnablementChanged(RadioIndicationType /*type*/,
+                                                                     bool /*enabled*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::registrationFailed(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::radio::V1_5::CellIdentity& /*cellIdentity*/,
+        const hidl_string& /*chosenPlmn*/,
+        ::android::hardware::hidl_bitfield<::android::hardware::radio::V1_5::Domain> /*domain*/,
+        int32_t /*causeCode*/, int32_t /*additionalCauseCode*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::barringInfoChanged(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::radio::V1_5::CellIdentity& /*cellIdentity*/,
+        const hidl_vec<::android::hardware::radio::V1_5::BarringInfo>& /*barringInfos*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::networkScanResult_1_5(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::radio::V1_5::NetworkScanResult& /*result*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::cellInfoList_1_5(
+        RadioIndicationType /*type*/,
+        const hidl_vec<::android::hardware::radio::V1_5::CellInfo>& /*records*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::dataCallListChanged_1_5(
+        RadioIndicationType /*type*/,
+        const hidl_vec<android::hardware::radio::V1_5::SetupDataCallResult>& /*dcList*/) {
+    return Void();
+}
+
+/* 1.4 Apis */
+Return<void> RadioIndication_v1_6::currentPhysicalChannelConfigs_1_4(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_4::PhysicalChannelConfig>& /*configs*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::networkScanResult_1_4(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::radio::V1_4::NetworkScanResult& /*result*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::cellInfoList_1_4(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_4::CellInfo>& /*records*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::currentEmergencyNumberList(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<EmergencyNumber>& /*emergencyNumberList*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::dataCallListChanged_1_4(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<android::hardware::radio::V1_4::SetupDataCallResult>&
+        /*dcList*/) {
+    return Void();
+}
+
+/* 1.2 Apis */
+Return<void> RadioIndication_v1_6::networkScanResult_1_2(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::radio::V1_2::NetworkScanResult& /*result*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::cellInfoList_1_2(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_2::CellInfo>& /*records*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::currentLinkCapacityEstimate(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::radio::V1_2::LinkCapacityEstimate& /*lce*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::currentPhysicalChannelConfigs(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_2::PhysicalChannelConfig>& /*configs*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::currentSignalStrength_1_2(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::radio::V1_2::SignalStrength& /*signalStrength*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::currentSignalStrength_1_4(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::radio::V1_4::SignalStrength& /*signalStrength*/) {
+    return Void();
+}
+
+/* 1.1 Apis */
+Return<void> RadioIndication_v1_6::carrierInfoForImsiEncryption(RadioIndicationType /*info*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::networkScanResult(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::radio::V1_1::NetworkScanResult& /*result*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::keepaliveStatus(RadioIndicationType /*type*/,
+                                                   const KeepaliveStatus& /*status*/) {
+    return Void();
+}
+
+/* 1.0 Apis */
+Return<void> RadioIndication_v1_6::radioStateChanged(RadioIndicationType /*type*/,
+                                                     RadioState /*radioState*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::callStateChanged(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::networkStateChanged(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::newSms(RadioIndicationType /*type*/,
+                                          const ::android::hardware::hidl_vec<uint8_t>& /*pdu*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::newSmsStatusReport(
+        RadioIndicationType /*type*/, const ::android::hardware::hidl_vec<uint8_t>& /*pdu*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::newSmsOnSim(RadioIndicationType /*type*/,
+                                               int32_t /*recordNumber*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::onUssd(RadioIndicationType /*type*/, UssdModeType /*modeType*/,
+                                          const ::android::hardware::hidl_string& /*msg*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::nitzTimeReceived(
+        RadioIndicationType /*type*/, const ::android::hardware::hidl_string& /*nitzTime*/,
+        uint64_t /*receivedTime*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::currentSignalStrength(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::radio::V1_0::SignalStrength& /*signalStrength*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::dataCallListChanged(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<android::hardware::radio::V1_0::SetupDataCallResult>&
+        /*dcList*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::suppSvcNotify(RadioIndicationType /*type*/,
+                                                 const SuppSvcNotification& /*suppSvc*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::stkSessionEnd(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::stkProactiveCommand(
+        RadioIndicationType /*type*/, const ::android::hardware::hidl_string& /*cmd*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::stkEventNotify(RadioIndicationType /*type*/,
+                                                  const ::android::hardware::hidl_string& /*cmd*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::stkCallSetup(RadioIndicationType /*type*/, int64_t /*timeout*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::simSmsStorageFull(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::simRefresh(RadioIndicationType /*type*/,
+                                              const SimRefreshResult& /*refreshResult*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::callRing(RadioIndicationType /*type*/, bool /*isGsm*/,
+                                            const CdmaSignalInfoRecord& /*record*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::simStatusChanged(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::cdmaNewSms(RadioIndicationType /*type*/,
+                                              const CdmaSmsMessage& /*msg*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::newBroadcastSms(
+        RadioIndicationType /*type*/, const ::android::hardware::hidl_vec<uint8_t>& /*data*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::cdmaRuimSmsStorageFull(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::restrictedStateChanged(RadioIndicationType /*type*/,
+                                                          PhoneRestrictedState /*state*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::enterEmergencyCallbackMode(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::cdmaCallWaiting(RadioIndicationType /*type*/,
+                                                   const CdmaCallWaiting& /*callWaitingRecord*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::cdmaOtaProvisionStatus(RadioIndicationType /*type*/,
+                                                          CdmaOtaProvisionStatus /*status*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::cdmaInfoRec(RadioIndicationType /*type*/,
+                                               const CdmaInformationRecords& /*records*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::indicateRingbackTone(RadioIndicationType /*type*/,
+                                                        bool /*start*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::resendIncallMute(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::cdmaSubscriptionSourceChanged(
+        RadioIndicationType /*type*/, CdmaSubscriptionSource /*cdmaSource*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::cdmaPrlChanged(RadioIndicationType /*type*/,
+                                                  int32_t /*version*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::exitEmergencyCallbackMode(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::rilConnected(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::voiceRadioTechChanged(
+        RadioIndicationType /*type*/, ::android::hardware::radio::V1_0::RadioTechnology /*rat*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::cellInfoList(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_0::CellInfo>& /*records*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::imsNetworkStateChanged(RadioIndicationType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::subscriptionStatusChanged(RadioIndicationType /*type*/,
+                                                             bool /*activate*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::srvccStateNotify(RadioIndicationType /*type*/,
+                                                    SrvccState /*state*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::hardwareConfigChanged(
+        RadioIndicationType /*type*/,
+        const ::android::hardware::hidl_vec<HardwareConfig>& /*configs*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::radioCapabilityIndication(
+        RadioIndicationType /*type*/,
+        const android::hardware::radio::V1_0::RadioCapability& /*rc*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::onSupplementaryServiceIndication(
+        RadioIndicationType /*type*/, const StkCcUnsolSsResult& /*ss*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::stkCallControlAlphaNotify(
+        RadioIndicationType /*type*/, const ::android::hardware::hidl_string& /*alpha*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::lceData(RadioIndicationType /*type*/,
+                                           const LceDataInfo& /*lce*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::pcoData(RadioIndicationType /*type*/,
+                                           const PcoDataInfo& /*pco*/) {
+    return Void();
+}
+
+Return<void> RadioIndication_v1_6::modemReset(RadioIndicationType /*type*/,
+                                              const ::android::hardware::hidl_string& /*reason*/) {
+    return Void();
+}
diff --git a/radio/1.6/vts/functional/radio_response.cpp b/radio/1.6/vts/functional/radio_response.cpp
new file mode 100644
index 0000000..44e61b9
--- /dev/null
+++ b/radio/1.6/vts/functional/radio_response.cpp
@@ -0,0 +1,1044 @@
+/*
+ * 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 <radio_hidl_hal_utils_v1_6.h>
+
+::android::hardware::radio::V1_5::CardStatus cardStatus;
+
+RadioResponse_v1_6::RadioResponse_v1_6(RadioHidlTest_v1_6& parent) : parent_v1_6(parent) {}
+
+/* 1.0 Apis */
+Return<void> RadioResponse_v1_6::getIccCardStatusResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::radio::V1_0::CardStatus& /*card_status*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::supplyIccPinForAppResponse(const RadioResponseInfo& /*info*/,
+                                                            int32_t /*remainingRetries*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::supplyIccPukForAppResponse(const RadioResponseInfo& /*info*/,
+                                                            int32_t /*remainingRetries*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::supplyIccPin2ForAppResponse(const RadioResponseInfo& /*info*/,
+                                                             int32_t /*remainingRetries*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::supplyIccPuk2ForAppResponse(const RadioResponseInfo& /*info*/,
+                                                             int32_t /*remainingRetries*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::changeIccPinForAppResponse(const RadioResponseInfo& /*info*/,
+                                                            int32_t /*remainingRetries*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::changeIccPin2ForAppResponse(const RadioResponseInfo& /*info*/,
+                                                             int32_t /*remainingRetries*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::supplyNetworkDepersonalizationResponse(
+        const RadioResponseInfo& /*info*/, int32_t /*remainingRetries*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCurrentCallsResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::Call>& /*calls*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::dialResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getIMSIForAppResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*imsi*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::hangupConnectionResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::hangupWaitingOrBackgroundResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::hangupForegroundResumeBackgroundResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::switchWaitingOrHoldingAndActiveResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::conferenceResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::rejectCallResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getLastCallFailCauseResponse(
+        const RadioResponseInfo& /*info*/, const LastCallFailCauseInfo& /*failCauseInfo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getSignalStrengthResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::radio::V1_0::SignalStrength& /*sig_strength*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getVoiceRegistrationStateResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::radio::V1_0::VoiceRegStateResult& /*voiceRegResponse*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDataRegistrationStateResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::radio::V1_0::DataRegStateResult& /*dataRegResponse*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getOperatorResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*longName*/,
+        const ::android::hardware::hidl_string& /*shortName*/,
+        const ::android::hardware::hidl_string& /*numeric*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setRadioPowerResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendDtmfResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendSmsResponse(const RadioResponseInfo& /*info*/,
+                                                 const SendSmsResult& /*sms*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendSMSExpectMoreResponse(const RadioResponseInfo& /*info*/,
+                                                           const SendSmsResult& /*sms*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setupDataCallResponse(
+        const RadioResponseInfo& /*info*/,
+        const android::hardware::radio::V1_0::SetupDataCallResult& /*dcResponse*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::iccIOForAppResponse(const RadioResponseInfo& /*info*/,
+                                                     const IccIoResult& /*iccIo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendUssdResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::cancelPendingUssdResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getClirResponse(const RadioResponseInfo& /*info*/, int32_t /*n*/,
+                                                 int32_t /*m*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setClirResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCallForwardStatusResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_vec<CallForwardInfo>&
+        /*callForwardInfos*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setCallForwardResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCallWaitingResponse(const RadioResponseInfo& /*info*/,
+                                                        bool /*enable*/, int32_t /*serviceClass*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setCallWaitingResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::acknowledgeLastIncomingGsmSmsResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::acceptCallResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::deactivateDataCallResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getFacilityLockForAppResponse(const RadioResponseInfo& /*info*/,
+                                                               int32_t /*response*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setFacilityLockForAppResponse(const RadioResponseInfo& /*info*/,
+                                                               int32_t /*retry*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setBarringPasswordResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getNetworkSelectionModeResponse(const RadioResponseInfo& /*info*/,
+                                                                 bool /*manual*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setNetworkSelectionModeAutomaticResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setNetworkSelectionModeManualResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getAvailableNetworksResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<OperatorInfo>& /*networkInfos*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::startDtmfResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::stopDtmfResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getBasebandVersionResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*version*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::separateConnectionResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setMuteResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getMuteResponse(const RadioResponseInfo& /*info*/,
+                                                 bool /*enable*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getClipResponse(const RadioResponseInfo& /*info*/,
+                                                 ClipStatus /*status*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDataCallListResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<android::hardware::radio::V1_0::SetupDataCallResult>&
+        /*dcResponse*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendOemRilRequestRawResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_vec<uint8_t>& /*data*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendOemRilRequestStringsResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<::android::hardware::hidl_string>& /*data*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setSuppServiceNotificationsResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::writeSmsToSimResponse(const RadioResponseInfo& /*info*/,
+                                                       int32_t /*index*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::deleteSmsOnSimResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setBandModeResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getAvailableBandModesResponse(
+        const RadioResponseInfo& info,
+        const ::android::hardware::hidl_vec<RadioBandMode>& bandModes) {
+    rspInfo = info;
+    radioBandModes = bandModes;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendEnvelopeResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_string& /*commandResponse*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendTerminalResponseToSimResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::handleStkCallSetupRequestFromSimResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::explicitCallTransferResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setPreferredNetworkTypeResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getPreferredNetworkTypeResponse(const RadioResponseInfo& /*info*/,
+                                                                 PreferredNetworkType /*nw_type*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getNeighboringCidsResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<NeighboringCell>& /*cells*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setLocationUpdatesResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setCdmaSubscriptionSourceResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setCdmaRoamingPreferenceResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCdmaRoamingPreferenceResponse(const RadioResponseInfo& /*info*/,
+                                                                  CdmaRoamingType /*type*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setTTYModeResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getTTYModeResponse(const RadioResponseInfo& /*info*/,
+                                                    TtyMode /*mode*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setPreferredVoicePrivacyResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getPreferredVoicePrivacyResponse(const RadioResponseInfo& /*info*/,
+                                                                  bool /*enable*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendCDMAFeatureCodeResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendBurstDtmfResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendCdmaSmsResponse(const RadioResponseInfo& /*info*/,
+                                                     const SendSmsResult& /*sms*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::acknowledgeLastIncomingCdmaSmsResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getGsmBroadcastConfigResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<GsmBroadcastSmsConfigInfo>& /*configs*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setGsmBroadcastConfigResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setGsmBroadcastActivationResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCdmaBroadcastConfigResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<CdmaBroadcastSmsConfigInfo>& /*configs*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setCdmaBroadcastConfigResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setCdmaBroadcastActivationResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCDMASubscriptionResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*mdn*/,
+        const ::android::hardware::hidl_string& /*hSid*/,
+        const ::android::hardware::hidl_string& /*hNid*/,
+        const ::android::hardware::hidl_string& /*min*/,
+        const ::android::hardware::hidl_string& /*prl*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::writeSmsToRuimResponse(const RadioResponseInfo& /*info*/,
+                                                        uint32_t /*index*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::deleteSmsOnRuimResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDeviceIdentityResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*imei*/,
+        const ::android::hardware::hidl_string& /*imeisv*/,
+        const ::android::hardware::hidl_string& /*esn*/,
+        const ::android::hardware::hidl_string& /*meid*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::exitEmergencyCallbackModeResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getSmscAddressResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*smsc*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setSmscAddressResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::reportSmsMemoryStatusResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::reportStkServiceIsRunningResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCdmaSubscriptionSourceResponse(
+        const RadioResponseInfo& /*info*/, CdmaSubscriptionSource /*source*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::requestIsimAuthenticationResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*response*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::acknowledgeIncomingGsmSmsWithPduResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendEnvelopeWithStatusResponse(const RadioResponseInfo& /*info*/,
+                                                                const IccIoResult& /*iccIo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getVoiceRadioTechnologyResponse(
+        const RadioResponseInfo& /*info*/,
+        ::android::hardware::radio::V1_0::RadioTechnology /*rat*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCellInfoListResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_0::CellInfo>& /*cellInfo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setCellInfoListRateResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setInitialAttachApnResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getImsRegistrationStateResponse(
+        const RadioResponseInfo& /*info*/, bool /*isRegistered*/,
+        RadioTechnologyFamily /*ratFamily*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendImsSmsResponse(const RadioResponseInfo& /*info*/,
+                                                    const SendSmsResult& /*sms*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::iccTransmitApduBasicChannelResponse(
+        const RadioResponseInfo& /*info*/, const IccIoResult& /*result*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::iccOpenLogicalChannelResponse(
+        const RadioResponseInfo& /*info*/, int32_t /*channelId*/,
+        const ::android::hardware::hidl_vec<int8_t>& /*selectResponse*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::iccCloseLogicalChannelResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::iccTransmitApduLogicalChannelResponse(
+        const RadioResponseInfo& /*info*/, const IccIoResult& /*result*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::nvReadItemResponse(
+        const RadioResponseInfo& /*info*/, const ::android::hardware::hidl_string& /*result*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::nvWriteItemResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::nvWriteCdmaPrlResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::nvResetConfigResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setUiccSubscriptionResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setDataAllowedResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getHardwareConfigResponse(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<HardwareConfig>& /*config*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::requestIccSimAuthenticationResponse(
+        const RadioResponseInfo& /*info*/, const IccIoResult& /*result*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setDataProfileResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::requestShutdownResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getRadioCapabilityResponse(
+        const RadioResponseInfo& /*info*/,
+        const android::hardware::radio::V1_0::RadioCapability& /*rc*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setRadioCapabilityResponse(
+        const RadioResponseInfo& /*info*/,
+        const android::hardware::radio::V1_0::RadioCapability& /*rc*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::startLceServiceResponse(const RadioResponseInfo& /*info*/,
+                                                         const LceStatusInfo& /*statusInfo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::stopLceServiceResponse(const RadioResponseInfo& /*info*/,
+                                                        const LceStatusInfo& /*statusInfo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::pullLceDataResponse(const RadioResponseInfo& /*info*/,
+                                                     const LceDataInfo& /*lceInfo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getModemActivityInfoResponse(
+        const RadioResponseInfo& /*info*/, const ActivityStatsInfo& /*activityInfo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setAllowedCarriersResponse(const RadioResponseInfo& /*info*/,
+                                                            int32_t /*numAllowed*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getAllowedCarriersResponse(
+        const RadioResponseInfo& /*info*/, bool /*allAllowed*/,
+        const CarrierRestrictions& /*carriers*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendDeviceStateResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setIndicationFilterResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setSimCardPowerResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::acknowledgeRequest(int32_t /*serial*/) {
+    return Void();
+}
+
+/* 1.1 Apis */
+Return<void> RadioResponse_v1_6::setCarrierInfoForImsiEncryptionResponse(
+        const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setSimCardPowerResponse_1_1(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::startNetworkScanResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::stopNetworkScanResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::startKeepaliveResponse(const RadioResponseInfo& /*info*/,
+                                                        const KeepaliveStatus& /*status*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::stopKeepaliveResponse(const RadioResponseInfo& /*info*/) {
+    return Void();
+}
+
+/* 1.2 Apis */
+Return<void> RadioResponse_v1_6::setSignalStrengthReportingCriteriaResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setLinkCapacityReportingCriteriaResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getIccCardStatusResponse_1_2(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::radio::V1_2::CardStatus& /*card_status*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCurrentCallsResponse_1_2(
+        const RadioResponseInfo& info,
+        const ::android::hardware::hidl_vec<::android::hardware::radio::V1_2::Call>& calls) {
+    rspInfo = info;
+    currentCalls = calls;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getSignalStrengthResponse_1_2(
+        const RadioResponseInfo& info,
+        const ::android::hardware::radio::V1_2::SignalStrength& /*sig_strength*/) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getSignalStrengthResponse_1_4(
+        const RadioResponseInfo& info,
+        const ::android::hardware::radio::V1_4::SignalStrength& /*sig_strength*/) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCellInfoListResponse_1_2(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_2::CellInfo>& /*cellInfo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getVoiceRegistrationStateResponse_1_2(
+        const RadioResponseInfo& info,
+        const ::android::hardware::radio::V1_2::VoiceRegStateResult& /*voiceRegResponse*/) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDataRegistrationStateResponse_1_2(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::radio::V1_2::DataRegStateResult& /*dataRegResponse*/) {
+    return Void();
+}
+
+/* 1.3 Apis */
+Return<void> RadioResponse_v1_6::setSystemSelectionChannelsResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::enableModemResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getModemStackStatusResponse(const RadioResponseInfo& info,
+                                                             const bool enabled) {
+    rspInfo = info;
+    isModemEnabled = enabled;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+/* 1.4 Apis */
+Return<void> RadioResponse_v1_6::emergencyDialResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::startNetworkScanResponse_1_4(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDataRegistrationStateResponse_1_4(
+        const RadioResponseInfo& info,
+        const ::android::hardware::radio::V1_4::DataRegStateResult& dataRegResponse) {
+    rspInfo = info;
+    dataRegResp = dataRegResponse;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCellInfoListResponse_1_4(
+        const RadioResponseInfo& info,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_4::CellInfo>& /*cellInfo*/) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getIccCardStatusResponse_1_4(
+        const RadioResponseInfo& info,
+        const ::android::hardware::radio::V1_4::CardStatus& /*card_status*/) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getPreferredNetworkTypeBitmapResponse(
+        const RadioResponseInfo& info, const ::android::hardware::hidl_bitfield<
+                                               ::android::hardware::radio::V1_4::RadioAccessFamily>
+                                               networkTypeBitmap) {
+    rspInfo = info;
+    networkTypeBitmapResponse = networkTypeBitmap;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setPreferredNetworkTypeBitmapResponse(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDataCallListResponse_1_4(
+        const RadioResponseInfo& info,
+        const ::android::hardware::hidl_vec<::android::hardware::radio::V1_4::SetupDataCallResult>&
+        /*dcResponse*/) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setupDataCallResponse_1_4(
+        const RadioResponseInfo& info,
+        const android::hardware::radio::V1_4::SetupDataCallResult& /*dcResponse*/) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setAllowedCarriersResponse_1_4(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getAllowedCarriersResponse_1_4(
+        const RadioResponseInfo& info, const CarrierRestrictionsWithPriority& carriers,
+        SimLockMultiSimPolicy multiSimPolicy) {
+    rspInfo = info;
+    carrierRestrictionsResp = carriers;
+    multiSimPolicyResp = multiSimPolicy;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+/* 1.5 Apis */
+Return<void> RadioResponse_v1_6::setSignalStrengthReportingCriteriaResponse_1_5(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setLinkCapacityReportingCriteriaResponse_1_5(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::enableUiccApplicationsResponse(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::areUiccApplicationsEnabledResponse(const RadioResponseInfo& info,
+                                                                    bool enabled) {
+    rspInfo = info;
+    areUiccApplicationsEnabled = enabled;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::canToggleUiccApplicationsEnablementResponse(
+        const RadioResponseInfo& info, bool canToggle) {
+    rspInfo = info;
+    canToggleUiccApplicationsEnablement = canToggle;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setSystemSelectionChannelsResponse_1_5(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::startNetworkScanResponse_1_5(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setupDataCallResponse_1_5(
+        const RadioResponseInfo& info,
+        const android::hardware::radio::V1_5::SetupDataCallResult& /* dcResponse */) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDataCallListResponse_1_5(
+        const RadioResponseInfo& info,
+        const hidl_vec<::android::hardware::radio::V1_5::SetupDataCallResult>& /* dcResponse */) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setInitialAttachApnResponse_1_5(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setDataProfileResponse_1_5(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setRadioPowerResponse_1_5(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setIndicationFilterResponse_1_5(const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getBarringInfoResponse(
+        const RadioResponseInfo& info,
+        const ::android::hardware::radio::V1_5::CellIdentity& cellIdentity,
+        const ::android::hardware::hidl_vec<::android::hardware::radio::V1_5::BarringInfo>&
+                barringInfos) {
+    this->barringCellIdentity = cellIdentity;
+    this->barringInfos = barringInfos;
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getVoiceRegistrationStateResponse_1_5(
+        const RadioResponseInfo& info,
+        const ::android::hardware::radio::V1_5::RegStateResult& /*regResponse*/) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getDataRegistrationStateResponse_1_5(
+        const RadioResponseInfo& info,
+        const ::android::hardware::radio::V1_5::RegStateResult& /*regResponse*/) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getCellInfoListResponse_1_5(
+        const RadioResponseInfo& /*info*/,
+        const ::android::hardware::hidl_vec<
+                ::android::hardware::radio::V1_5::CellInfo>& /*cellInfo*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::setNetworkSelectionModeManualResponse_1_5(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::sendCdmaSmsExpectMoreResponse(const RadioResponseInfo& info,
+                                                               const SendSmsResult& /*sms*/) {
+    rspInfo = info;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::supplySimDepersonalizationResponse(
+        const RadioResponseInfo& /*info*/,
+        ::android::hardware::radio::V1_5::PersoSubstate /*persoType*/,
+        int32_t /*remainingRetries*/) {
+    return Void();
+}
+
+Return<void> RadioResponse_v1_6::getIccCardStatusResponse_1_5(
+        const RadioResponseInfo& info,
+        const ::android::hardware::radio::V1_5::CardStatus& card_status) {
+    rspInfo = info;
+    cardStatus = card_status;
+    parent_v1_6.notify(info.serial);
+    return Void();
+}
+
+/* 1.6 Apis */
+
diff --git a/radio/config/1.0/Android.bp b/radio/config/1.0/Android.bp
index 387f953..eea4c34 100644
--- a/radio/config/1.0/Android.bp
+++ b/radio/config/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.radio.config@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IRadioConfig.hal",
diff --git a/radio/config/1.1/Android.bp b/radio/config/1.1/Android.bp
index 1e9071a..a5c3114 100644
--- a/radio/config/1.1/Android.bp
+++ b/radio/config/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.radio.config@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IRadioConfig.hal",
diff --git a/radio/config/1.2/Android.bp b/radio/config/1.2/Android.bp
index 812f166..39d55ff 100644
--- a/radio/config/1.2/Android.bp
+++ b/radio/config/1.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.radio.config@1.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IRadioConfigIndication.hal",
diff --git a/radio/deprecated/1.0/Android.bp b/radio/deprecated/1.0/Android.bp
index cb13b86..1a7cb94 100644
--- a/radio/deprecated/1.0/Android.bp
+++ b/radio/deprecated/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.radio.deprecated@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "IOemHook.hal",
         "IOemHookIndication.hal",
diff --git a/rebootescrow/aidl/default/RebootEscrow.cpp b/rebootescrow/aidl/default/RebootEscrow.cpp
index dbc0921..8e5e97c 100644
--- a/rebootescrow/aidl/default/RebootEscrow.cpp
+++ b/rebootescrow/aidl/default/RebootEscrow.cpp
@@ -28,7 +28,7 @@
 
 using ::android::base::unique_fd;
 
-ndk::ScopedAStatus RebootEscrow::storeKey(const std::vector<int8_t>& kek) {
+ndk::ScopedAStatus RebootEscrow::storeKey(const std::vector<uint8_t>& ukek) {
     int rawFd = TEMP_FAILURE_RETRY(::open(devicePath_.c_str(), O_WRONLY | O_NOFOLLOW | O_CLOEXEC));
     unique_fd fd(rawFd);
     if (fd.get() < 0) {
@@ -36,7 +36,6 @@
         return ndk::ScopedAStatus(AStatus_fromExceptionCode(EX_UNSUPPORTED_OPERATION));
     }
 
-    std::vector<uint8_t> ukek(kek.begin(), kek.end());
     auto encoded = hadamard::EncodeKey(ukek);
 
     if (!::android::base::WriteFully(fd, encoded.data(), encoded.size())) {
@@ -47,7 +46,7 @@
     return ndk::ScopedAStatus::ok();
 }
 
-ndk::ScopedAStatus RebootEscrow::retrieveKey(std::vector<int8_t>* _aidl_return) {
+ndk::ScopedAStatus RebootEscrow::retrieveKey(std::vector<uint8_t>* _aidl_return) {
     int rawFd = TEMP_FAILURE_RETRY(::open(devicePath_.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC));
     unique_fd fd(rawFd);
     if (fd.get() < 0) {
@@ -63,8 +62,7 @@
 
     auto keyBytes = hadamard::DecodeKey(encodedBytes);
 
-    std::vector<int8_t> signedKeyBytes(keyBytes.begin(), keyBytes.end());
-    *_aidl_return = signedKeyBytes;
+    *_aidl_return = keyBytes;
     return ndk::ScopedAStatus::ok();
 }
 
diff --git a/rebootescrow/aidl/default/include/rebootescrow-impl/RebootEscrow.h b/rebootescrow/aidl/default/include/rebootescrow-impl/RebootEscrow.h
index 00ff16b..cdbeb67 100644
--- a/rebootescrow/aidl/default/include/rebootescrow-impl/RebootEscrow.h
+++ b/rebootescrow/aidl/default/include/rebootescrow-impl/RebootEscrow.h
@@ -26,8 +26,8 @@
 class RebootEscrow : public BnRebootEscrow {
   public:
     explicit RebootEscrow(const std::string& devicePath) : devicePath_(devicePath) {}
-    ndk::ScopedAStatus storeKey(const std::vector<int8_t>& kek) override;
-    ndk::ScopedAStatus retrieveKey(std::vector<int8_t>* _aidl_return) override;
+    ndk::ScopedAStatus storeKey(const std::vector<uint8_t>& kek) override;
+    ndk::ScopedAStatus retrieveKey(std::vector<uint8_t>* _aidl_return) override;
 
   private:
     const std::string devicePath_;
diff --git a/rebootescrow/aidl/vts/functional/README.md b/rebootescrow/aidl/vts/functional/README.md
new file mode 100644
index 0000000..9ae5caf
--- /dev/null
+++ b/rebootescrow/aidl/vts/functional/README.md
@@ -0,0 +1,7 @@
+Many of the tests in this directory may require that TEE Keymaster
+"EARLY_BOOT_ONLY" keys be usable when this test runs. In order to accomplish
+this, a build of "vold" that omits the call to "earlyBootEnded()" function
+should be made. Then these DISABLED tests may be run successfully.
+
+The CTS test ResumeOnRebootHostTests will test the functionality without a
+special build.
diff --git a/rebootescrow/aidl/vts/functional/VtsHalRebootEscrowTargetTest.cpp b/rebootescrow/aidl/vts/functional/VtsHalRebootEscrowTargetTest.cpp
index cd8cc3e..809a3b5 100644
--- a/rebootescrow/aidl/vts/functional/VtsHalRebootEscrowTargetTest.cpp
+++ b/rebootescrow/aidl/vts/functional/VtsHalRebootEscrowTargetTest.cpp
@@ -60,7 +60,10 @@
     };
 };
 
-TEST_P(RebootEscrowAidlTest, StoreAndRetrieve_Success) {
+// This test assumes that it can retrieve keys immediately, but some
+// implementations use the TEE's EARLY_BOOT_ONLY keys. This means that the
+// earlyBootEnded() calls will need to be disabled to test this correctly.
+TEST_P(RebootEscrowAidlTest, DISABLED_StoreAndRetrieve_Success) {
     SKIP_UNSUPPORTED;
 
     ASSERT_TRUE(rebootescrow->storeKey(KEY_1).isOk());
@@ -70,7 +73,10 @@
     EXPECT_EQ(actualKey, KEY_1);
 }
 
-TEST_P(RebootEscrowAidlTest, StoreAndRetrieve_SecondRetrieveSucceeds) {
+// This test assumes that it can retrieve keys immediately, but some
+// implementations use the TEE's EARLY_BOOT_ONLY keys. This means that the
+// earlyBootEnded() calls will need to be disabled to test this correctly.
+TEST_P(RebootEscrowAidlTest, DISABLED_StoreAndRetrieve_SecondRetrieveSucceeds) {
     SKIP_UNSUPPORTED;
 
     ASSERT_TRUE(rebootescrow->storeKey(KEY_1).isOk());
@@ -83,7 +89,10 @@
     EXPECT_EQ(actualKey, KEY_1);
 }
 
-TEST_P(RebootEscrowAidlTest, StoreTwiceOverwrites_Success) {
+// This test assumes that it can retrieve keys immediately, but some
+// implementations use the TEE's EARLY_BOOT_ONLY keys. This means that the
+// earlyBootEnded() calls will need to be disabled to test this correctly.
+TEST_P(RebootEscrowAidlTest, DISABLED_StoreTwiceOverwrites_Success) {
     SKIP_UNSUPPORTED;
 
     ASSERT_TRUE(rebootescrow->storeKey(KEY_1).isOk());
@@ -94,7 +103,10 @@
     EXPECT_EQ(actualKey, KEY_2);
 }
 
-TEST_P(RebootEscrowAidlTest, StoreEmpty_AfterGetEmptyKey_Success) {
+// This test assumes that it can retrieve keys immediately, but some
+// implementations use the TEE's EARLY_BOOT_ONLY keys. This means that the
+// earlyBootEnded() calls will need to be disabled to test this correctly.
+TEST_P(RebootEscrowAidlTest, DISABLED_StoreEmpty_AfterGetEmptyKey_Success) {
     SKIP_UNSUPPORTED;
 
     rebootescrow->storeKey(KEY_1);
@@ -105,6 +117,12 @@
     EXPECT_EQ(actualKey, EMPTY_KEY);
 }
 
+TEST_P(RebootEscrowAidlTest, Store_Success) {
+    SKIP_UNSUPPORTED;
+
+    rebootescrow->storeKey(KEY_1);
+}
+
 INSTANTIATE_TEST_SUITE_P(
         RebootEscrow, RebootEscrowAidlTest,
         testing::ValuesIn(android::getAidlHalInstanceNames(IRebootEscrow::descriptor)),
diff --git a/renderscript/1.0/Android.bp b/renderscript/1.0/Android.bp
index feae9f7..d3b5abe 100644
--- a/renderscript/1.0/Android.bp
+++ b/renderscript/1.0/Android.bp
@@ -3,6 +3,8 @@
 hidl_interface {
     name: "android.hardware.renderscript@1.0",
     root: "android.hardware",
+    // TODO(b/153609531): remove when no longer needed.
+    native_bridge_supported: true,
     vndk: {
         enabled: true,
         support_system_process: true,
diff --git a/secure_element/1.0/Android.bp b/secure_element/1.0/Android.bp
index 32b752b..a32b9d1 100644
--- a/secure_element/1.0/Android.bp
+++ b/secure_element/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.secure_element@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ISecureElement.hal",
diff --git a/secure_element/1.0/vts/functional/AndroidTest.xml b/secure_element/1.0/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..4724f23
--- /dev/null
+++ b/secure_element/1.0/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalSecureElementV1_0TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+    <option name="config-descriptor:metadata" key="token" value="SECURE_ELEMENT_SIM_CARD" />
+
+    <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="VtsHalSecureElementV1_0TargetTest->/data/local/tmp/VtsHalSecureElementV1_0TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalSecureElementV1_0TargetTest" />
+    </test>
+</configuration>
diff --git a/secure_element/1.1/Android.bp b/secure_element/1.1/Android.bp
index 3ea2de9..08e6c88 100644
--- a/secure_element/1.1/Android.bp
+++ b/secure_element/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.secure_element@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "ISecureElement.hal",
         "ISecureElementHalCallback.hal",
diff --git a/secure_element/1.1/vts/functional/AndroidTest.xml b/secure_element/1.1/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..3d7b715
--- /dev/null
+++ b/secure_element/1.1/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalSecureElementV1_1TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+    <option name="config-descriptor:metadata" key="token" value="SECURE_ELEMENT_SIM_CARD" />
+
+    <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="VtsHalSecureElementV1_1TargetTest->/data/local/tmp/VtsHalSecureElementV1_1TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalSecureElementV1_1TargetTest" />
+    </test>
+</configuration>
diff --git a/secure_element/1.2/Android.bp b/secure_element/1.2/Android.bp
index e134771..03df5f9 100644
--- a/secure_element/1.2/Android.bp
+++ b/secure_element/1.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.secure_element@1.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "ISecureElement.hal",
     ],
diff --git a/secure_element/1.2/vts/functional/AndroidTest.xml b/secure_element/1.2/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..0bd8061
--- /dev/null
+++ b/secure_element/1.2/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalSecureElementV1_2TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+    <option name="config-descriptor:metadata" key="token" value="SECURE_ELEMENT_SIM_CARD" />
+
+    <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="VtsHalSecureElementV1_2TargetTest->/data/local/tmp/VtsHalSecureElementV1_2TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalSecureElementV1_2TargetTest" />
+    </test>
+</configuration>
diff --git a/sensors/1.0/Android.bp b/sensors/1.0/Android.bp
index 509f72f..1093671 100644
--- a/sensors/1.0/Android.bp
+++ b/sensors/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.sensors@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ISensors.hal",
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index 31424ab..c77733b 100644
--- a/sensors/1.0/vts/functional/Android.bp
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -23,11 +23,6 @@
         "VtsHalSensorsV1_0TargetTest.cpp",
     ],
     static_libs: [
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@2.1",
-        "android.hardware.graphics.mapper@3.0",
         "android.hardware.sensors@1.0",
         "VtsHalSensorsTargetTestUtils",
     ],
diff --git a/sensors/1.0/vts/functional/AndroidTest.xml b/sensors/1.0/vts/functional/AndroidTest.xml
index fb0d64c..5011f09 100644
--- a/sensors/1.0/vts/functional/AndroidTest.xml
+++ b/sensors/1.0/vts/functional/AndroidTest.xml
@@ -17,13 +17,8 @@
     <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.RunCommandTargetPreparer">
-        <option name="run-command" value="stop"/>
-        <option name="teardown-command" value="start"/>
-    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup"/>
 
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
diff --git a/sensors/2.0/Android.bp b/sensors/2.0/Android.bp
index c8517c8..d71f07b 100644
--- a/sensors/2.0/Android.bp
+++ b/sensors/2.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.sensors@2.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ISensors.hal",
diff --git a/sensors/2.0/vts/functional/Android.bp b/sensors/2.0/vts/functional/Android.bp
index 598ad15..83ebc6b 100644
--- a/sensors/2.0/vts/functional/Android.bp
+++ b/sensors/2.0/vts/functional/Android.bp
@@ -25,11 +25,6 @@
         "android.hardware.sensors@2.X-shared-utils",
     ],
     static_libs: [
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@2.1",
-        "android.hardware.graphics.mapper@3.0",
         "android.hardware.sensors@1.0",
         "android.hardware.sensors@1.0-convert",
         "android.hardware.sensors@2.0",
diff --git a/sensors/2.0/vts/functional/AndroidTest.xml b/sensors/2.0/vts/functional/AndroidTest.xml
index b710ed0..b7658a9 100644
--- a/sensors/2.0/vts/functional/AndroidTest.xml
+++ b/sensors/2.0/vts/functional/AndroidTest.xml
@@ -17,13 +17,8 @@
     <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.RunCommandTargetPreparer">
-        <option name="run-command" value="stop"/>
-        <option name="teardown-command" value="start"/>
-    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup"/>
 
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
diff --git a/sensors/2.1/Android.bp b/sensors/2.1/Android.bp
index 8e80e1f..9ba3248 100644
--- a/sensors/2.1/Android.bp
+++ b/sensors/2.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.sensors@2.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ISensors.hal",
diff --git a/sensors/2.1/vts/functional/Android.bp b/sensors/2.1/vts/functional/Android.bp
index 3f01a3e..d257993 100644
--- a/sensors/2.1/vts/functional/Android.bp
+++ b/sensors/2.1/vts/functional/Android.bp
@@ -27,11 +27,6 @@
         "android.hardware.sensors@2.X-shared-utils",
     ],
     static_libs: [
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@2.1",
-        "android.hardware.graphics.mapper@3.0",
         "android.hardware.sensors@1.0",
         "android.hardware.sensors@1.0-convert",
         "android.hardware.sensors@2.0",
diff --git a/sensors/2.1/vts/functional/AndroidTest.xml b/sensors/2.1/vts/functional/AndroidTest.xml
index 0d8593e..2ef8dc6 100644
--- a/sensors/2.1/vts/functional/AndroidTest.xml
+++ b/sensors/2.1/vts/functional/AndroidTest.xml
@@ -17,13 +17,8 @@
     <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.RunCommandTargetPreparer">
-        <option name="run-command" value="stop"/>
-        <option name="teardown-command" value="start"/>
-    </target_preparer>
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+    <target_preparer class="com.android.tradefed.targetprep.StopServicesSetup"/>
 
     <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
         <option name="cleanup" value="true" />
diff --git a/sensors/common/vts/2_X/Android.bp b/sensors/common/vts/2_X/Android.bp
index 8cdb5d1..e5eceb5 100644
--- a/sensors/common/vts/2_X/Android.bp
+++ b/sensors/common/vts/2_X/Android.bp
@@ -29,11 +29,6 @@
         "libbinder",
     ],
     static_libs: [
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@2.1",
-        "android.hardware.graphics.mapper@3.0",
         "android.hardware.sensors@1.0",
         "android.hardware.sensors@1.0-convert",
         "android.hardware.sensors@2.0",
diff --git a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
index 1db667f..2e5aca4 100644
--- a/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
+++ b/sensors/common/vts/2_X/VtsHalSensorsV2_XTargetTest.h
@@ -452,6 +452,10 @@
     for (const auto& s : sensors) {
         auto events = callback.getEvents(s.sensorHandle);
         auto lastEvent = events.back();
+        SCOPED_TRACE(::testing::Message()
+                     << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                     << s.sensorHandle << std::dec << " type=" << static_cast<int>(s.type)
+                     << " name=" << s.name);
 
         // Verify that only a single event has been received
         ASSERT_EQ(events.size(), 1);
@@ -578,6 +582,12 @@
 
         // Flush the sensor
         for (int32_t i = 0; i < flushCalls; i++) {
+            SCOPED_TRACE(::testing::Message()
+                         << "Flush " << i << "/" << flushCalls << ": "
+                         << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                         << sensor.sensorHandle << std::dec
+                         << " type=" << static_cast<int>(sensor.type) << " name=" << sensor.name);
+
             Result flushResult = flush(sensor.sensorHandle);
             ASSERT_EQ(flushResult, expectedResponse);
         }
@@ -595,6 +605,10 @@
 
     // Check that the correct number of flushes are present for each sensor
     for (const SensorInfoType& sensor : sensors) {
+        SCOPED_TRACE(::testing::Message()
+                     << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                     << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
+                     << " name=" << sensor.name);
         ASSERT_EQ(callback.getFlushCount(sensor.sensorHandle), expectedFlushCount);
     }
 }
@@ -643,6 +657,11 @@
 
     activateAllSensors(false /* enable */);
     for (const SensorInfoType& sensor : getSensorsList()) {
+        SCOPED_TRACE(::testing::Message()
+                     << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                     << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
+                     << " name=" << sensor.name);
+
         // Call batch on inactive sensor
         // One shot sensors have minDelay set to -1 which is an invalid
         // parameter. Use 0 instead to avoid errors.
@@ -675,6 +694,11 @@
 
     // Verify that sensor events are generated when activate is called
     for (const SensorInfoType& sensor : getSensorsList()) {
+        SCOPED_TRACE(::testing::Message()
+                     << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                     << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
+                     << " name=" << sensor.name);
+
         batch(sensor.sensorHandle, sensor.minDelay, 0 /* maxReportLatencyNs */);
         ASSERT_EQ(activate(sensor.sensorHandle, true), Result::OK);
 
@@ -722,6 +746,10 @@
     // Save the last received event for each sensor
     std::map<int32_t, int64_t> lastEventTimestampMap;
     for (const SensorInfoType& sensor : sensors) {
+        SCOPED_TRACE(::testing::Message()
+                     << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                     << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
+                     << " name=" << sensor.name);
         // Some on-change sensors may not report an event without stimulus
         if (extractReportMode(sensor.flags) != SensorFlagBits::ON_CHANGE_MODE) {
             ASSERT_GE(callback.getEvents(sensor.sensorHandle).size(), 1);
@@ -742,6 +770,11 @@
     getEnvironment()->unregisterCallback();
 
     for (const SensorInfoType& sensor : sensors) {
+        SCOPED_TRACE(::testing::Message()
+                     << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                     << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
+                     << " name=" << sensor.name);
+
         // Skip sensors that did not previously report an event
         if (lastEventTimestampMap.find(sensor.sensorHandle) == lastEventTimestampMap.end()) {
             continue;
@@ -764,6 +797,12 @@
                                      RateLevel rateLevel) {
     configDirectReport(sensor.sensorHandle, directChannelHandle, rateLevel,
                        [&](Result result, int32_t reportToken) {
+                           SCOPED_TRACE(::testing::Message()
+                                        << " handle=0x" << std::hex << std::setw(8)
+                                        << std::setfill('0') << sensor.sensorHandle << std::dec
+                                        << " type=" << static_cast<int>(sensor.type)
+                                        << " name=" << sensor.name);
+
                            if (isDirectReportRateSupported(sensor, rateLevel)) {
                                ASSERT_EQ(result, Result::OK);
                                if (rateLevel != RateLevel::STOP) {
@@ -821,6 +860,11 @@
 
 void SensorsHidlTest::verifyConfigure(const SensorInfoType& sensor, SharedMemType memType,
                                       int32_t directChannelHandle, bool supportsAnyDirectChannel) {
+    SCOPED_TRACE(::testing::Message()
+                 << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                 << sensor.sensorHandle << std::dec << " type=" << static_cast<int>(sensor.type)
+                 << " name=" << sensor.name);
+
     if (isDirectChannelTypeSupported(sensor, memType)) {
         // Verify that each rate level is properly supported
         checkRateLevel(sensor, directChannelHandle, RateLevel::NORMAL);
diff --git a/sensors/common/vts/utils/Android.bp b/sensors/common/vts/utils/Android.bp
index ca4346a..baaed6c 100644
--- a/sensors/common/vts/utils/Android.bp
+++ b/sensors/common/vts/utils/Android.bp
@@ -31,13 +31,17 @@
         "libutils",
     ],
     static_libs: [
-        "android.hardware.graphics.allocator@2.0",
-        "android.hardware.graphics.allocator@3.0",
-        "android.hardware.graphics.mapper@2.0",
-        "android.hardware.graphics.mapper@2.1",
-        "android.hardware.graphics.mapper@3.0",
         "android.hardware.sensors@1.0",
         "android.hardware.sensors@2.0",
         "android.hardware.sensors@2.1",
     ],
+    whole_static_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.allocator@3.0",
+        "android.hardware.graphics.allocator@4.0",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.graphics.mapper@2.1",
+        "android.hardware.graphics.mapper@3.0",
+        "android.hardware.graphics.mapper@4.0",
+    ],
 }
diff --git a/sensors/common/vts/utils/GrallocWrapper.cpp b/sensors/common/vts/utils/GrallocWrapper.cpp
index e63faa2..47d1f42 100644
--- a/sensors/common/vts/utils/GrallocWrapper.cpp
+++ b/sensors/common/vts/utils/GrallocWrapper.cpp
@@ -18,9 +18,11 @@
 
 #include <android/hardware/graphics/allocator/2.0/IAllocator.h>
 #include <android/hardware/graphics/allocator/3.0/IAllocator.h>
+#include <android/hardware/graphics/allocator/4.0/IAllocator.h>
 #include <android/hardware/graphics/mapper/2.0/IMapper.h>
 #include <android/hardware/graphics/mapper/2.1/IMapper.h>
 #include <android/hardware/graphics/mapper/3.0/IMapper.h>
+#include <android/hardware/graphics/mapper/4.0/IMapper.h>
 
 #include <utils/Log.h>
 
@@ -29,19 +31,19 @@
 
 using IAllocator2 = ::android::hardware::graphics::allocator::V2_0::IAllocator;
 using IAllocator3 = ::android::hardware::graphics::allocator::V3_0::IAllocator;
+using IAllocator4 = ::android::hardware::graphics::allocator::V4_0::IAllocator;
 using IMapper2 = ::android::hardware::graphics::mapper::V2_0::IMapper;
 using IMapper2_1 = ::android::hardware::graphics::mapper::V2_1::IMapper;
 using IMapper3 = ::android::hardware::graphics::mapper::V3_0::IMapper;
+using IMapper4 = ::android::hardware::graphics::mapper::V4_0::IMapper;
 
 using Error2 = ::android::hardware::graphics::mapper::V2_0::Error;
 using Error3 = ::android::hardware::graphics::mapper::V3_0::Error;
+using Error4 = ::android::hardware::graphics::mapper::V4_0::Error;
 
 using ::android::hardware::graphics::common::V1_0::BufferUsage;
 using ::android::hardware::graphics::common::V1_0::PixelFormat;
 
-// This is a typedef to the same underlying type across v2.0 and v3.0
-using ::android::hardware::graphics::mapper::V2_0::BufferDescriptor;
-
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
@@ -58,7 +60,6 @@
     virtual ~IGrallocHalWrapper() = default;
 
     // IAllocator
-    virtual std::string dumpDebugInfo() = 0;
     virtual native_handle_t* allocate(uint32_t size) = 0;
     virtual void freeBuffer(native_handle_t* bufferHandle) = 0;
 
@@ -75,6 +76,24 @@
 bool failed(Error3 error) {
     return (error != Error3::NONE);
 }
+bool failed(Error4 error) {
+    return (error != Error4::NONE);
+}
+
+template <typename>
+struct FirstArg;
+
+// Template specialization for pointer to a non-static member function, which exposes
+// the type of the first argument given to said function
+template <typename ReturnType, typename ClassT, typename Arg1, typename... OtherArgs>
+struct FirstArg<ReturnType (ClassT::*)(Arg1, OtherArgs...)> {
+    using type = Arg1;
+};
+
+// Alias to FirstArg which also removes any reference type and const associated
+template <typename T>
+using BaseTypeOfFirstArg = typename std::remove_const<
+        typename std::remove_reference<typename FirstArg<T>::type>::type>::type;
 
 // Since all the type and function names are the same for the things we use across the major HAL
 // versions, we use template magic to avoid repeating ourselves.
@@ -88,7 +107,6 @@
         }
     }
 
-    virtual std::string dumpDebugInfo() override;
     virtual native_handle_t* allocate(uint32_t size) override;
     virtual void freeBuffer(native_handle_t* bufferHandle) override;
 
@@ -101,21 +119,19 @@
     sp<AllocatorT> mAllocator;
     sp<MapperT> mMapper;
 
-    BufferDescriptor getDescriptor(uint32_t size);
+    // v2.0 and v3.0 use vec<uint32_t> for BufferDescriptor, but v4.0 uses vec<uint8_t>, so use
+    // some template magic to deduce the right type based off of the first argument to allocate(),
+    // which is always the version-specific BufferDescriptor type
+    typedef BaseTypeOfFirstArg<decltype(&AllocatorT::allocate)> BufferDescriptorT;
+
+    BufferDescriptorT getDescriptor(uint32_t size);
     native_handle_t* importBuffer(const hidl_handle& rawHandle);
 };
 
 template <typename AllocatorT, typename MapperT>
-std::string GrallocHalWrapper<AllocatorT, MapperT>::dumpDebugInfo() {
-    std::string debugInfo;
-    mAllocator->dumpDebugInfo([&](const hidl_string& tmpDebugInfo) { debugInfo = tmpDebugInfo; });
-    return debugInfo;
-}
-
-template <typename AllocatorT, typename MapperT>
 native_handle_t* GrallocHalWrapper<AllocatorT, MapperT>::allocate(uint32_t size) {
     constexpr uint32_t kBufferCount = 1;
-    BufferDescriptor descriptor = getDescriptor(size);
+    BufferDescriptorT descriptor = getDescriptor(size);
     native_handle_t* bufferHandle = nullptr;
 
     auto callback = [&](auto error, uint32_t /*stride*/, const hidl_vec<hidl_handle>& buffers) {
@@ -142,7 +158,8 @@
 }
 
 template <typename AllocatorT, typename MapperT>
-BufferDescriptor GrallocHalWrapper<AllocatorT, MapperT>::getDescriptor(uint32_t size) {
+typename GrallocHalWrapper<AllocatorT, MapperT>::BufferDescriptorT
+GrallocHalWrapper<AllocatorT, MapperT>::getDescriptor(uint32_t size) {
     typename MapperT::BufferDescriptorInfo descriptorInfo = {
             .width = size,
             .height = 1,
@@ -151,8 +168,8 @@
             .usage = kBufferUsage,
     };
 
-    BufferDescriptor descriptor;
-    auto callback = [&](auto error, const BufferDescriptor& tmpDescriptor) {
+    BufferDescriptorT descriptor;
+    auto callback = [&](auto error, const BufferDescriptorT& tmpDescriptor) {
         if (failed(error)) {
             ALOGE("Failed to create descriptor: %" PRId32, static_cast<int32_t>(error));
         } else {
@@ -189,7 +206,7 @@
 
     void* data = nullptr;
     mMapper->lock(bufferHandle, kBufferUsage, accessRegion, acquireFenceHandle,
-                  [&](auto error, void* tmpData, ...) {  // V3_0 passes extra args we don't use
+                  [&](auto error, void* tmpData, ...) {  // V3/4 pass extra args we don't use
                       if (failed(error)) {
                           ALOGE("Failed to lock buffer %p: %" PRId32, bufferHandle,
                                 static_cast<int32_t>(error));
@@ -214,28 +231,40 @@
 }  // anonymous namespace
 
 GrallocWrapper::GrallocWrapper() {
-    sp<IAllocator3> allocator3 = IAllocator3::getService();
-    sp<IMapper3> mapper3 = IMapper3::getService();
+    sp<IAllocator4> allocator4 = IAllocator4::getService();
+    sp<IMapper4> mapper4 = IMapper4::getService();
 
-    if (allocator3 != nullptr && mapper3 != nullptr) {
+    if (allocator4 != nullptr && mapper4 != nullptr) {
+        ALOGD("Using IAllocator/IMapper v4.0");
         mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
-                new GrallocHalWrapper<IAllocator3, IMapper3>(allocator3, mapper3));
+                new GrallocHalWrapper<IAllocator4, IMapper4>(allocator4, mapper4));
     } else {
-        ALOGD("Graphics HALs 3.0 not found (allocator %d mapper %d), falling back to 2.x",
-              (allocator3 != nullptr), (mapper3 != nullptr));
+        ALOGD("Graphics HALs 4.0 not found (allocator %d mapper %d), falling back to 3.0",
+              (allocator4 != nullptr), (mapper4 != nullptr));
 
-        sp<IAllocator2> allocator2 = IAllocator2::getService();
-        sp<IMapper2> mapper2 = IMapper2_1::getService();
-        if (mapper2 == nullptr) {
-            mapper2 = IMapper2::getService();
-        }
+        sp<IAllocator3> allocator3 = IAllocator3::getService();
+        sp<IMapper3> mapper3 = IMapper3::getService();
 
-        if (allocator2 != nullptr && mapper2 != nullptr) {
+        if (allocator3 != nullptr && mapper3 != nullptr) {
             mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
-                    new GrallocHalWrapper<IAllocator2, IMapper2>(allocator2, mapper2));
+                    new GrallocHalWrapper<IAllocator3, IMapper3>(allocator3, mapper3));
         } else {
-            ALOGE("Couldn't open 2.x/3.0 graphics HALs (2.x allocator %d mapper %d)",
-                  (allocator2 != nullptr), (mapper2 != nullptr));
+            ALOGD("Graphics HALs 3.0 not found (allocator %d mapper %d), falling back to 2.x",
+                  (allocator3 != nullptr), (mapper3 != nullptr));
+
+            sp<IAllocator2> allocator2 = IAllocator2::getService();
+            sp<IMapper2> mapper2 = IMapper2_1::getService();
+            if (mapper2 == nullptr) {
+                mapper2 = IMapper2::getService();
+            }
+
+            if (allocator2 != nullptr && mapper2 != nullptr) {
+                mGrallocHal = std::unique_ptr<IGrallocHalWrapper>(
+                        new GrallocHalWrapper<IAllocator2, IMapper2>(allocator2, mapper2));
+            } else {
+                ALOGE("Couldn't open graphics HALs (2.x allocator %d mapper %d)",
+                      (allocator2 != nullptr), (mapper2 != nullptr));
+            }
         }
     }
 }
@@ -248,10 +277,6 @@
     mAllocatedBuffers.clear();
 }
 
-std::string GrallocWrapper::dumpDebugInfo() {
-    return mGrallocHal->dumpDebugInfo();
-}
-
 std::pair<native_handle_t*, void*> GrallocWrapper::allocate(uint32_t size) {
     native_handle_t* bufferHandle = mGrallocHal->allocate(size);
     void* buffer = nullptr;
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h b/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h
index 41e6334..ebbcb2c 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h
@@ -37,8 +37,6 @@
     // returns false, other methods are not safe to call.
     bool isInitialized() const { return (mGrallocHal != nullptr); };
 
-    std::string dumpDebugInfo();
-
     // Allocates a gralloc buffer suitable for direct channel sensors usage with the given size.
     // The buffer should be freed using freeBuffer when it's not needed anymore; otherwise it'll
     // be freed when this object is destroyed.
diff --git a/soundtrigger/2.1/Android.bp b/soundtrigger/2.1/Android.bp
index 30173cb..024e0f6 100644
--- a/soundtrigger/2.1/Android.bp
+++ b/soundtrigger/2.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.soundtrigger@2.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "ISoundTriggerHw.hal",
         "ISoundTriggerHwCallback.hal",
diff --git a/soundtrigger/2.2/Android.bp b/soundtrigger/2.2/Android.bp
index 7556aa4..dbf4f8b 100644
--- a/soundtrigger/2.2/Android.bp
+++ b/soundtrigger/2.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.soundtrigger@2.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "ISoundTriggerHw.hal",
     ],
diff --git a/soundtrigger/2.3/Android.bp b/soundtrigger/2.3/Android.bp
index 3253a86..480df4d 100644
--- a/soundtrigger/2.3/Android.bp
+++ b/soundtrigger/2.3/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.soundtrigger@2.3",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ISoundTriggerHw.hal",
diff --git a/tests/bar/1.0/.hidl_for_test b/tests/bar/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/bar/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/baz/1.0/.hidl_for_test b/tests/baz/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/baz/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/expression/1.0/.hidl_for_test b/tests/expression/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/expression/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/extension/light/2.0/.hidl_for_test b/tests/extension/light/2.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/extension/light/2.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/foo/1.0/.hidl_for_test b/tests/foo/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/foo/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/hash/1.0/.hidl_for_test b/tests/hash/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/hash/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/inheritance/1.0/.hidl_for_test b/tests/inheritance/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/inheritance/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/lazy/1.0/.hidl_for_test b/tests/lazy/1.0/.hidl_for_system_ext
similarity index 100%
rename from tests/lazy/1.0/.hidl_for_test
rename to tests/lazy/1.0/.hidl_for_system_ext
diff --git a/tests/lazy/1.0/.hidl_for_test b/tests/lazy/1.1/.hidl_for_system_ext
similarity index 100%
copy from tests/lazy/1.0/.hidl_for_test
copy to tests/lazy/1.1/.hidl_for_system_ext
diff --git a/tests/lazy/1.1/Android.bp b/tests/lazy/1.1/Android.bp
new file mode 100644
index 0000000..ccedd8d
--- /dev/null
+++ b/tests/lazy/1.1/Android.bp
@@ -0,0 +1,15 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.tests.lazy@1.1",
+    root: "android.hardware",
+    system_ext_specific: true,
+    srcs: [
+        "ILazy.hal",
+    ],
+    interfaces: [
+        "android.hardware.tests.lazy@1.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/tests/lazy/1.1/ILazy.hal
similarity index 69%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to tests/lazy/1.1/ILazy.hal
index 7edec47..a15e0e3 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/tests/lazy/1.1/ILazy.hal
@@ -14,13 +14,8 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+package android.hardware.tests.lazy@1.1;
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+import android.hardware.tests.lazy@1.0;
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+interface ILazy extends @1.0::ILazy {};
diff --git a/tests/libhwbinder/1.0/.hidl_for_test b/tests/libhwbinder/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/libhwbinder/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/libhwbinder/aidl/.hidl_for_test b/tests/libhwbinder/aidl/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/libhwbinder/aidl/.hidl_for_test
+++ /dev/null
diff --git a/tests/memory/1.0/.hidl_for_test b/tests/memory/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/memory/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/memory/2.0/.hidl_for_test b/tests/memory/2.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/memory/2.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/msgq/1.0/.hidl_for_test b/tests/msgq/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/msgq/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/msgq/1.0/default/mq_test_service.cpp b/tests/msgq/1.0/default/mq_test_service.cpp
index b5cb662..b921bfd 100644
--- a/tests/msgq/1.0/default/mq_test_service.cpp
+++ b/tests/msgq/1.0/default/mq_test_service.cpp
@@ -24,5 +24,6 @@
 using android::hardware::defaultPassthroughServiceImplementation;
 
 int main() {
+    android::hardware::details::setTrebleTestingOverride(true);
     return defaultPassthroughServiceImplementation<ITestMsgQ>();
 }
diff --git a/tests/multithread/1.0/.hidl_for_test b/tests/multithread/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/multithread/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/safeunion/1.0/.hidl_for_test b/tests/safeunion/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/safeunion/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/safeunion/cpp/1.0/.hidl_for_test b/tests/safeunion/cpp/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/safeunion/cpp/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/trie/1.0/.hidl_for_test b/tests/trie/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/trie/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tetheroffload/config/1.0/Android.bp b/tetheroffload/config/1.0/Android.bp
index 321224a..e774048 100644
--- a/tetheroffload/config/1.0/Android.bp
+++ b/tetheroffload/config/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.tetheroffload.config@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "IOffloadConfig.hal",
     ],
diff --git a/tetheroffload/control/1.0/Android.bp b/tetheroffload/control/1.0/Android.bp
index f894448..4bcaed2 100644
--- a/tetheroffload/control/1.0/Android.bp
+++ b/tetheroffload/control/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.tetheroffload.control@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IOffloadControl.hal",
diff --git a/thermal/1.0/Android.bp b/thermal/1.0/Android.bp
index de168d8..10eeddc 100644
--- a/thermal/1.0/Android.bp
+++ b/thermal/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.thermal@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IThermal.hal",
diff --git a/thermal/1.1/Android.bp b/thermal/1.1/Android.bp
index f38ed3b..7dc30a3 100644
--- a/thermal/1.1/Android.bp
+++ b/thermal/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.thermal@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "IThermal.hal",
         "IThermalCallback.hal",
diff --git a/thermal/2.0/Android.bp b/thermal/2.0/Android.bp
index 1b76f37..3d9cea1 100644
--- a/thermal/2.0/Android.bp
+++ b/thermal/2.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.thermal@2.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IThermal.hal",
diff --git a/tv/cec/1.0/Android.bp b/tv/cec/1.0/Android.bp
index d41a7e7..0e0f284 100644
--- a/tv/cec/1.0/Android.bp
+++ b/tv/cec/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.tv.cec@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IHdmiCec.hal",
diff --git a/tv/cec/2.0/Android.bp b/tv/cec/2.0/Android.bp
index 61450ac..5463b6d 100644
--- a/tv/cec/2.0/Android.bp
+++ b/tv/cec/2.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.tv.cec@2.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IHdmiCec.hal",
diff --git a/tv/input/1.0/Android.bp b/tv/input/1.0/Android.bp
index 1164430..1121f4e 100644
--- a/tv/input/1.0/Android.bp
+++ b/tv/input/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.tv.input@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ITvInput.hal",
diff --git a/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp b/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp
index 59c70eb..8092d5e 100644
--- a/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp
+++ b/tv/input/1.0/vts/functional/VtsHalTvInputV1_0TargetTest.cpp
@@ -337,3 +337,6 @@
         PerInstance, TvInputHidlTest,
         testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITvInput::descriptor)),
         android::hardware::PrintInstanceNameToString);
+
+// TODO remove from the allow list once the cf tv target is enabled for testing
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TvInputHidlTest);
diff --git a/tv/tuner/1.0/Android.bp b/tv/tuner/1.0/Android.bp
index d78f3f2..e578641 100644
--- a/tv/tuner/1.0/Android.bp
+++ b/tv/tuner/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.tv.tuner@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IDemux.hal",
diff --git a/tv/tuner/1.0/default/Demux.cpp b/tv/tuner/1.0/default/Demux.cpp
index 4e5ae4b..9055a43 100644
--- a/tv/tuner/1.0/default/Demux.cpp
+++ b/tv/tuner/1.0/default/Demux.cpp
@@ -48,8 +48,6 @@
         return Result::INVALID_STATE;
     }
 
-    mFrontendSourceFile = mFrontend->getSourceFile();
-
     mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId);
 
     return Result::SUCCESS;
@@ -60,15 +58,7 @@
     ALOGV("%s", __FUNCTION__);
 
     uint32_t filterId;
-    if (!mUnusedFilterIds.empty()) {
-        filterId = *mUnusedFilterIds.begin();
-
-        mUnusedFilterIds.erase(filterId);
-    } else {
-        filterId = ++mLastUsedFilterId;
-    }
-
-    mUsedFilterIds.insert(filterId);
+    filterId = ++mLastUsedFilterId;
 
     if (cb == nullptr) {
         ALOGW("[Demux] callback can't be null");
@@ -84,9 +74,17 @@
     }
 
     mFilters[filterId] = filter;
+    if (filter->isPcrFilter()) {
+        mPcrFilterIds.insert(filterId);
+    }
     bool result = true;
-    if (mDvr != nullptr && mDvr->getType() == DvrType::PLAYBACK) {
-        result = mDvr->addPlaybackFilter(filter);
+    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);
+        }
     }
 
     _hidl_cb(result ? Result::SUCCESS : Result::INVALID_ARGUMENT, filter);
@@ -96,25 +94,59 @@
 Return<void> Demux::openTimeFilter(openTimeFilter_cb _hidl_cb) {
     ALOGV("%s", __FUNCTION__);
 
-    sp<TimeFilter> timeFilter = new TimeFilter(this);
+    mTimeFilter = new TimeFilter(this);
 
-    _hidl_cb(Result::SUCCESS, timeFilter);
+    _hidl_cb(Result::SUCCESS, mTimeFilter);
     return Void();
 }
 
-Return<void> Demux::getAvSyncHwId(const sp<IFilter>& /* filter */, getAvSyncHwId_cb _hidl_cb) {
+Return<void> Demux::getAvSyncHwId(const sp<IFilter>& filter, getAvSyncHwId_cb _hidl_cb) {
     ALOGV("%s", __FUNCTION__);
 
-    AvSyncHwId avSyncHwId = 0;
+    uint32_t avSyncHwId = -1;
+    int id;
+    Result status;
 
-    _hidl_cb(Result::SUCCESS, avSyncHwId);
+    filter->getId([&](Result result, uint32_t filterId) {
+        id = filterId;
+        status = result;
+    });
+
+    if (status != Result::SUCCESS) {
+        ALOGE("[Demux] Can't get filter Id.");
+        _hidl_cb(Result::INVALID_STATE, avSyncHwId);
+        return Void();
+    }
+
+    if (!mFilters[id]->isMediaFilter()) {
+        ALOGE("[Demux] Given filter is not a media filter.");
+        _hidl_cb(Result::INVALID_ARGUMENT, avSyncHwId);
+        return Void();
+    }
+
+    if (!mPcrFilterIds.empty()) {
+        // Return the lowest pcr filter id in the default implementation as the av sync id
+        _hidl_cb(Result::SUCCESS, *mPcrFilterIds.begin());
+        return Void();
+    }
+
+    ALOGE("[Demux] No PCR filter opened.");
+    _hidl_cb(Result::INVALID_STATE, avSyncHwId);
     return Void();
 }
 
-Return<void> Demux::getAvSyncTime(AvSyncHwId /* avSyncHwId */, getAvSyncTime_cb _hidl_cb) {
+Return<void> Demux::getAvSyncTime(AvSyncHwId avSyncHwId, getAvSyncTime_cb _hidl_cb) {
     ALOGV("%s", __FUNCTION__);
 
-    uint64_t avSyncTime = 0;
+    uint64_t avSyncTime = -1;
+    if (mPcrFilterIds.empty()) {
+        _hidl_cb(Result::INVALID_STATE, avSyncTime);
+        return Void();
+    }
+    if (avSyncHwId != *mPcrFilterIds.begin()) {
+        _hidl_cb(Result::INVALID_ARGUMENT, avSyncTime);
+        return Void();
+    }
 
     _hidl_cb(Result::SUCCESS, avSyncTime);
     return Void();
@@ -123,9 +155,15 @@
 Return<Result> Demux::close() {
     ALOGV("%s", __FUNCTION__);
 
-    mUnusedFilterIds.clear();
-    mUsedFilterIds.clear();
+    set<uint32_t>::iterator it;
+    for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
+        mDvrPlayback->removePlaybackFilter(*it);
+    }
+    mPlaybackFilterIds.clear();
+    mRecordFilterIds.clear();
+    mFilters.clear();
     mLastUsedFilterId = -1;
+    mTunerService->removeDemux(mDemuxId);
 
     return Result::SUCCESS;
 }
@@ -140,15 +178,38 @@
         return Void();
     }
 
-    mDvr = new Dvr(type, bufferSize, cb, this);
+    set<uint32_t>::iterator it;
+    switch (type) {
+        case DvrType::PLAYBACK:
+            mDvrPlayback = new Dvr(type, bufferSize, cb, this);
+            if (!mDvrPlayback->createDvrMQ()) {
+                _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
+                return Void();
+            }
 
-    if (!mDvr->createDvrMQ()) {
-        _hidl_cb(Result::UNKNOWN_ERROR, mDvr);
-        return Void();
+            for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
+                if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) {
+                    ALOGE("[Demux] Can't get filter info for DVR playback");
+                    _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
+                    return Void();
+                }
+            }
+
+            _hidl_cb(Result::SUCCESS, mDvrPlayback);
+            return Void();
+        case DvrType::RECORD:
+            mDvrRecord = new Dvr(type, bufferSize, cb, this);
+            if (!mDvrRecord->createDvrMQ()) {
+                _hidl_cb(Result::UNKNOWN_ERROR, mDvrRecord);
+                return Void();
+            }
+
+            _hidl_cb(Result::SUCCESS, mDvrRecord);
+            return Void();
+        default:
+            _hidl_cb(Result::INVALID_ARGUMENT, nullptr);
+            return Void();
     }
-
-    _hidl_cb(Result::SUCCESS, mDvr);
-    return Void();
 }
 
 Return<Result> Demux::connectCiCam(uint32_t ciCamId) {
@@ -168,10 +229,11 @@
 Result Demux::removeFilter(uint32_t filterId) {
     ALOGV("%s", __FUNCTION__);
 
-    // resetFilterRecords(filterId);
-    mUsedFilterIds.erase(filterId);
+    if (mDvrPlayback != nullptr) {
+        mDvrPlayback->removePlaybackFilter(filterId);
+    }
+    mPlaybackFilterIds.erase(filterId);
     mRecordFilterIds.erase(filterId);
-    mUnusedFilterIds.insert(filterId);
     mFilters.erase(filterId);
 
     return Result::SUCCESS;
@@ -183,7 +245,7 @@
     if (DEBUG_DEMUX) {
         ALOGW("[Demux] start ts filter pid: %d", pid);
     }
-    for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
+    for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
         if (pid == mFilters[*it]->getTpid()) {
             mFilters[*it]->updateFilterOutput(data);
         }
@@ -204,7 +266,7 @@
     set<uint32_t>::iterator it;
 
     // Handle the output data per filter type
-    for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
+    for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
         if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) {
             return false;
         }
@@ -233,6 +295,11 @@
     mFilters[filterId]->updateFilterOutput(data);
 }
 
+void Demux::updateMediaFilterOutput(uint16_t filterId, vector<uint8_t> data, uint64_t pts) {
+    updateFilterOutput(filterId, data);
+    mFilters[filterId]->updatePts(pts);
+}
+
 uint16_t Demux::getFilterTpid(uint32_t filterId) {
     return mFilters[filterId]->getTpid();
 }
@@ -251,58 +318,39 @@
 void Demux::frontendInputThreadLoop() {
     std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
     mFrontendInputThreadRunning = true;
-    mKeepFetchingDataFromFrontend = true;
 
-    // open the stream and get its length
-    std::ifstream inputData(mFrontendSourceFile, std::ifstream::binary);
-    // TODO take the packet size from the frontend setting
-    int packetSize = 188;
-    int writePacketAmount = 6;
-    char* buffer = new char[packetSize];
-    ALOGW("[Demux] Frontend input thread loop start %s", mFrontendSourceFile.c_str());
-    if (!inputData.is_open()) {
+    if (!mDvrPlayback) {
+        ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop.");
         mFrontendInputThreadRunning = false;
-        ALOGW("[Demux] Error %s", strerror(errno));
+        return;
     }
 
     while (mFrontendInputThreadRunning) {
-        // move the stream pointer for packet size * 6 every read until the end
-        while (mKeepFetchingDataFromFrontend) {
-            for (int i = 0; i < writePacketAmount; i++) {
-                inputData.read(buffer, packetSize);
-                if (!inputData) {
-                    mKeepFetchingDataFromFrontend = false;
-                    mFrontendInputThreadRunning = false;
-                    break;
-                }
-                // filter and dispatch filter output
-                vector<uint8_t> byteBuffer;
-                byteBuffer.resize(packetSize);
-                for (int index = 0; index < byteBuffer.size(); index++) {
-                    byteBuffer[index] = static_cast<uint8_t>(buffer[index]);
-                }
-                if (mIsRecording) {
-                    // Feed the data into the Dvr recording input
-                    sendFrontendInputToRecord(byteBuffer);
-                } else {
-                    // Feed the data into the broadcast demux filter
-                    startBroadcastTsFilter(byteBuffer);
-                }
+        uint32_t efState = 0;
+        status_t status = mDvrPlayback->getDvrEventFlag()->wait(
+                static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
+                true /* retry on spurious wake */);
+        if (status != OK) {
+            ALOGD("[Demux] wait for data ready on the playback FMQ");
+            continue;
+        }
+        if (mDvrPlayback->getSettings().playback().dataFormat == DataFormat::ES) {
+            if (!mDvrPlayback->processEsDataOnPlayback(true /*isVirtualFrontend*/, mIsRecording)) {
+                ALOGE("[Demux] playback es data failed to be filtered. Ending thread");
+                break;
             }
-            if (mIsRecording) {
-                // Dispatch the data into the broadcasting filters.
-                startRecordFilterDispatcher();
-            } else {
-                // Dispatch the data into the broadcasting filters.
-                startBroadcastFilterDispatcher();
-            }
-            usleep(100);
+        }
+        // Our current implementation filter the data and write it into the filter FMQ immediately
+        // after the DATA_READY from the VTS/framework
+        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.");
-    delete[] buffer;
-    inputData.close();
 }
 
 void Demux::stopFrontendInput() {
@@ -317,18 +365,19 @@
 }
 
 bool Demux::attachRecordFilter(int filterId) {
-    if (mFilters[filterId] == nullptr || mDvr == nullptr) {
+    if (mFilters[filterId] == nullptr || mDvrRecord == nullptr ||
+        !mFilters[filterId]->isRecordFilter()) {
         return false;
     }
 
     mRecordFilterIds.insert(filterId);
-    mFilters[filterId]->attachFilterToRecord(mDvr);
+    mFilters[filterId]->attachFilterToRecord(mDvrRecord);
 
     return true;
 }
 
 bool Demux::detachRecordFilter(int filterId) {
-    if (mFilters[filterId] == nullptr || mDvr == nullptr) {
+    if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
         return false;
     }
 
diff --git a/tv/tuner/1.0/default/Demux.h b/tv/tuner/1.0/default/Demux.h
index 3c91daf..6e93ea3 100644
--- a/tv/tuner/1.0/default/Demux.h
+++ b/tv/tuner/1.0/default/Demux.h
@@ -87,17 +87,28 @@
     bool detachRecordFilter(int filterId);
     Result startFilterHandler(uint32_t filterId);
     void updateFilterOutput(uint16_t filterId, vector<uint8_t> data);
+    void updateMediaFilterOutput(uint16_t filterId, vector<uint8_t> data, uint64_t pts);
     uint16_t getFilterTpid(uint32_t filterId);
     void setIsRecording(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<uint8_t> data);
+
+    void sendFrontendInputToRecord(vector<uint8_t> data);
+    bool startRecordFilterDispatcher();
+
   private:
     // Tuner service
     sp<Tuner> mTunerService;
 
     // Frontend source
     sp<Frontend> mFrontend;
-    string mFrontendSourceFile;
 
     // A struct that passes the arguments to a newly created filter thread
     struct ThreadArgs {
@@ -117,51 +128,41 @@
      */
     void deleteEventFlag();
     bool readDataFromMQ();
-    /**
-     * 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<uint8_t> data);
-
-    void sendFrontendInputToRecord(vector<uint8_t> data);
-    bool startRecordFilterDispatcher();
 
     uint32_t mDemuxId;
     uint32_t mCiCamId;
+    set<uint32_t> mPcrFilterIds;
     /**
      * Record the last used filter id. Initial value is -1.
      * Filter Id starts with 0.
      */
     uint32_t mLastUsedFilterId = -1;
     /**
-     * Record all the used filter Ids.
+     * Record all the used playback filter Ids.
      * Any removed filter id should be removed from this set.
      */
-    set<uint32_t> mUsedFilterIds;
-    /**
-     * Record all the unused filter Ids within mLastUsedFilterId.
-     * Removed filter Id should be added into this set.
-     * When this set is not empty, ids here should be allocated first
-     * and added into usedFilterIds.
-     */
-    set<uint32_t> mUnusedFilterIds;
+    set<uint32_t> mPlaybackFilterIds;
     /**
      * Record all the attached record filter Ids.
      * Any removed filter id should be removed from this set.
      */
     set<uint32_t> mRecordFilterIds;
     /**
-     * A list of created FilterMQ ptrs.
+     * A list of created Filter sp.
      * The array number is the filter ID.
      */
     std::map<uint32_t, sp<Filter>> mFilters;
 
     /**
+     * Local reference to the opened Timer Filter instance.
+     */
+    sp<TimeFilter> mTimeFilter;
+
+    /**
      * Local reference to the opened DVR object.
      */
-    sp<Dvr> mDvr;
+    sp<Dvr> mDvrPlayback;
+    sp<Dvr> mDvrRecord;
 
     // Thread handlers
     pthread_t mFrontendInputThread;
diff --git a/tv/tuner/1.0/default/Dvr.cpp b/tv/tuner/1.0/default/Dvr.cpp
index adb2635..c3edac9 100644
--- a/tv/tuner/1.0/default/Dvr.cpp
+++ b/tv/tuner/1.0/default/Dvr.cpp
@@ -70,8 +70,7 @@
         return status;
     }
 
-    // check if the attached filter is a record filter
-    mFilters[filterId] = filter;
+    // TODO check if the attached filter is a record filter
     if (!mDemux->attachRecordFilter(filterId)) {
         return Result::INVALID_ARGUMENT;
     }
@@ -94,19 +93,8 @@
         return status;
     }
 
-    std::map<uint32_t, sp<IFilter>>::iterator it;
-
-    it = mFilters.find(filterId);
-    if (it != mFilters.end()) {
-        mFilters.erase(filterId);
-        if (!mDemux->detachRecordFilter(filterId)) {
-            return Result::INVALID_ARGUMENT;
-        }
-    }
-
-    // If all the filters are detached, record can't be started
-    if (mFilters.empty()) {
-        mIsRecordFilterAttached = false;
+    if (!mDemux->detachRecordFilter(filterId)) {
+        return Result::INVALID_ARGUMENT;
     }
 
     return Result::SUCCESS;
@@ -141,7 +129,7 @@
 
     mDvrThreadRunning = false;
 
-    std::lock_guard<std::mutex> lock(mDvrThreadLock);
+    lock_guard<mutex> lock(mDvrThreadLock);
 
     mIsRecordStarted = false;
     mDemux->setIsRecording(false);
@@ -167,14 +155,13 @@
     ALOGV("%s", __FUNCTION__);
 
     // Create a synchronized FMQ that supports blocking read/write
-    std::unique_ptr<DvrMQ> tmpDvrMQ =
-            std::unique_ptr<DvrMQ>(new (std::nothrow) DvrMQ(mBufferSize, true));
+    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 = std::move(tmpDvrMQ);
+    mDvrMQ = move(tmpDvrMQ);
 
     if (EventFlag::createEventFlag(mDvrMQ->getEventFlagWord(), &mDvrEventFlag) != OK) {
         return false;
@@ -183,6 +170,10 @@
     return true;
 }
 
+EventFlag* Dvr::getDvrEventFlag() {
+    return mDvrEventFlag;
+}
+
 void* Dvr::__threadLoopPlayback(void* user) {
     Dvr* const self = static_cast<Dvr*>(user);
     self->playbackThreadLoop();
@@ -191,7 +182,7 @@
 
 void Dvr::playbackThreadLoop() {
     ALOGD("[Dvr] playback threadLoop start.");
-    std::lock_guard<std::mutex> lock(mDvrThreadLock);
+    lock_guard<mutex> lock(mDvrThreadLock);
     mDvrThreadRunning = true;
 
     while (mDvrThreadRunning) {
@@ -203,10 +194,19 @@
             ALOGD("[Dvr] wait for data ready on the playback FMQ");
             continue;
         }
+
+        if (mDvrSettings.playback().dataFormat == DataFormat::ES) {
+            if (!processEsDataOnPlayback(false /*isVirtualFrontend*/, false /*isRecording*/)) {
+                ALOGE("[Dvr] playback es data failed to be filtered. Ending thread");
+                break;
+            }
+            maySendPlaybackStatusCallback();
+        }
         // Our current implementation filter the data and write it into the filter FMQ immediately
         // after the DATA_READY from the VTS/framework
-        if (!readPlaybackFMQ() || !startFilterDispatcher()) {
-            ALOGD("[Dvr] playback data failed to be filtered. Ending thread");
+        if (!readPlaybackFMQ(false /*isVirtualFrontend*/, false /*isRecording*/) ||
+            !startFilterDispatcher(false /*isVirtualFrontend*/, false /*isRecording*/)) {
+            ALOGE("[Dvr] playback data failed to be filtered. Ending thread");
             break;
         }
 
@@ -218,7 +218,7 @@
 }
 
 void Dvr::maySendPlaybackStatusCallback() {
-    std::lock_guard<std::mutex> lock(mPlaybackStatusLock);
+    lock_guard<mutex> lock(mPlaybackStatusLock);
     int availableToRead = mDvrMQ->availableToRead();
     int availableToWrite = mDvrMQ->availableToWrite();
 
@@ -245,7 +245,7 @@
     return mPlaybackStatus;
 }
 
-bool Dvr::readPlaybackFMQ() {
+bool Dvr::readPlaybackFMQ(bool isVirtualFrontend, bool isRecording) {
     // Read playback data from the input FMQ
     int size = mDvrMQ->availableToRead();
     int playbackPacketSize = mDvrSettings.playback().packetSize;
@@ -256,14 +256,142 @@
         if (!mDvrMQ->read(dataOutputBuffer.data(), playbackPacketSize)) {
             return false;
         }
-        startTpidFilter(dataOutputBuffer);
+        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<uint8_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<uint8_t> frameData;
+    map<uint32_t, sp<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 filter
+        if (isVirtualFrontend && isRecording) {
+            // TODO validate record
+            mDemux->sendFrontendInputToRecord(frameData);
+        } else {
+            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));
+                    startFilterDispatcher(isVirtualFrontend, isRecording);
+                }
+            }
+        }
+    }
+
+    return true;
+}
+
+void Dvr::getMetaDataValue(int& index, uint8_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<uint8_t> data) {
-    std::map<uint32_t, sp<IFilter>>::iterator it;
+    map<uint32_t, sp<IFilter>>::iterator it;
     for (it = mFilters.begin(); it != mFilters.end(); it++) {
         uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
         if (DEBUG_DVR) {
@@ -275,8 +403,16 @@
     }
 }
 
-bool Dvr::startFilterDispatcher() {
-    std::map<uint32_t, sp<IFilter>>::iterator it;
+bool Dvr::startFilterDispatcher(bool isVirtualFrontend, bool isRecording) {
+    if (isVirtualFrontend) {
+        if (isRecording) {
+            return mDemux->startRecordFilterDispatcher();
+        } else {
+            return mDemux->startBroadcastFilterDispatcher();
+        }
+    }
+
+    map<uint32_t, sp<IFilter>>::iterator it;
     // Handle the output data per filter type
     for (it = mFilters.begin(); it != mFilters.end(); it++) {
         if (mDemux->startFilterHandler(it->first) != Result::SUCCESS) {
@@ -287,8 +423,8 @@
     return true;
 }
 
-bool Dvr::writeRecordFMQ(const std::vector<uint8_t>& data) {
-    std::lock_guard<std::mutex> lock(mWriteLock);
+bool Dvr::writeRecordFMQ(const vector<uint8_t>& data) {
+    lock_guard<mutex> lock(mWriteLock);
     if (mRecordStatus == RecordStatus::OVERFLOW) {
         ALOGW("[Dvr] stops writing and wait for the client side flushing.");
         return true;
@@ -304,7 +440,7 @@
 }
 
 void Dvr::maySendRecordStatusCallback() {
-    std::lock_guard<std::mutex> lock(mRecordStatusLock);
+    lock_guard<mutex> lock(mRecordStatusLock);
     int availableToRead = mDvrMQ->availableToRead();
     int availableToWrite = mDvrMQ->availableToWrite();
 
@@ -329,30 +465,18 @@
     return mRecordStatus;
 }
 
-bool Dvr::addPlaybackFilter(sp<IFilter> filter) {
-    uint32_t filterId;
-    Result status;
-
-    filter->getId([&](Result result, uint32_t id) {
-        filterId = id;
-        status = result;
-    });
-
-    if (status != Result::SUCCESS) {
-        return false;
-    }
-
+bool Dvr::addPlaybackFilter(uint32_t filterId, sp<IFilter> filter) {
     mFilters[filterId] = filter;
     return true;
 }
 
-DvrType Dvr::getType() {
-    return mType;
+bool Dvr::removePlaybackFilter(uint32_t filterId) {
+    mFilters.erase(filterId);
+    return true;
 }
-
 }  // namespace implementation
 }  // namespace V1_0
 }  // namespace tuner
 }  // namespace tv
 }  // namespace hardware
-}  // namespace android
\ No newline at end of file
+}  // namespace android
diff --git a/tv/tuner/1.0/default/Dvr.h b/tv/tuner/1.0/default/Dvr.h
index 08afd5d..3069586 100644
--- a/tv/tuner/1.0/default/Dvr.h
+++ b/tv/tuner/1.0/default/Dvr.h
@@ -44,6 +44,13 @@
 
 using DvrMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
 
+struct MediaEsMetaData {
+    bool isAudio;
+    int startIndex;
+    int len;
+    int pts;
+};
+
 class Demux;
 class Filter;
 class Frontend;
@@ -81,8 +88,13 @@
     bool createDvrMQ();
     void sendBroadcastInputToDvrRecord(vector<uint8_t> byteBuffer);
     bool writeRecordFMQ(const std::vector<uint8_t>& data);
-    DvrType getType();
-    bool addPlaybackFilter(sp<IFilter> filter);
+    bool addPlaybackFilter(uint32_t filterId, sp<IFilter> filter);
+    bool removePlaybackFilter(uint32_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
@@ -95,6 +107,7 @@
 
     void deleteEventFlag();
     bool readDataFromMQ();
+    void getMetaDataValue(int& index, uint8_t* dataOutputBuffer, int& value);
     void maySendPlaybackStatusCallback();
     void maySendRecordStatusCallback();
     PlaybackStatus checkPlaybackStatusChange(uint32_t availableToWrite, uint32_t availableToRead,
@@ -105,9 +118,7 @@
      * 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 readPlaybackFMQ();
     void startTpidFilter(vector<uint8_t> data);
-    bool startFilterDispatcher();
     static void* __threadLoopPlayback(void* user);
     static void* __threadLoopRecord(void* user);
     void playbackThreadLoop();
@@ -123,7 +134,6 @@
 
     // Thread handlers
     pthread_t mDvrThread;
-    pthread_t mBroadcastInputThread;
 
     // FMQ status local records
     PlaybackStatus mPlaybackStatus;
@@ -132,7 +142,6 @@
      * If a specific filter's writing loop is still running
      */
     bool mDvrThreadRunning;
-    bool mBroadcastInputThreadRunning;
     bool mKeepFetchingDataFromFrontend;
     /**
      * Lock to protect writes to the FMQs
@@ -143,7 +152,6 @@
      */
     std::mutex mPlaybackStatusLock;
     std::mutex mRecordStatusLock;
-    std::mutex mBroadcastInputThreadLock;
     std::mutex mDvrThreadLock;
 
     const bool DEBUG_DVR = false;
@@ -151,7 +159,6 @@
     // Booleans to check if recording is running.
     // Recording is ready when both of the following are set to true.
     bool mIsRecordStarted = false;
-    bool mIsRecordFilterAttached = false;
 };
 
 }  // namespace implementation
diff --git a/tv/tuner/1.0/default/Filter.cpp b/tv/tuner/1.0/default/Filter.cpp
index fef7a35..ce748e5 100644
--- a/tv/tuner/1.0/default/Filter.cpp
+++ b/tv/tuner/1.0/default/Filter.cpp
@@ -37,6 +37,38 @@
     mBufferSize = bufferSize;
     mCallback = cb;
     mDemux = demux;
+
+    switch (mType.mainType) {
+        case DemuxFilterMainType::TS:
+            if (mType.subType.tsFilterType() == DemuxTsFilterType::AUDIO ||
+                mType.subType.tsFilterType() == DemuxTsFilterType::VIDEO) {
+                mIsMediaFilter = true;
+            }
+            if (mType.subType.tsFilterType() == DemuxTsFilterType::PCR) {
+                mIsPcrFilter = true;
+            }
+            if (mType.subType.tsFilterType() == DemuxTsFilterType::RECORD) {
+                mIsRecordFilter = true;
+            }
+            break;
+        case DemuxFilterMainType::MMTP:
+            if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
+                mType.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
+                mIsMediaFilter = true;
+            }
+            if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::RECORD) {
+                mIsRecordFilter = true;
+            }
+            break;
+        case DemuxFilterMainType::IP:
+            break;
+        case DemuxFilterMainType::TLV:
+            break;
+        case DemuxFilterMainType::ALP:
+            break;
+        default:
+            break;
+    }
 }
 
 Filter::~Filter() {}
@@ -73,16 +105,8 @@
     switch (mType.mainType) {
         case DemuxFilterMainType::TS:
             mTpid = settings.ts().tpid;
-            if (mType.subType.tsFilterType() == DemuxTsFilterType::AUDIO ||
-                mType.subType.tsFilterType() == DemuxTsFilterType::VIDEO) {
-                mIsMediaFilter = true;
-            }
             break;
         case DemuxFilterMainType::MMTP:
-            if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
-                mType.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
-                mIsMediaFilter = true;
-            }
             break;
         case DemuxFilterMainType::IP:
             break;
@@ -293,6 +317,11 @@
     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<uint8_t> data) {
     std::lock_guard<std::mutex> lock(mRecordFilterOutputLock);
     mRecordFilterOutput.insert(mRecordFilterOutput.end(), data.begin(), data.end());
@@ -436,6 +465,11 @@
     if (mFilterOutput.empty()) {
         return Result::SUCCESS;
     }
+
+    if (mPts) {
+        return createMediaFilterEventWithIon(mFilterOutput);
+    }
+
     for (int i = 0; i < mFilterOutput.size(); i += 188) {
         if (mPesSizeLeft == 0) {
             uint32_t prefix = (mFilterOutput[i + 4] << 16) | (mFilterOutput[i + 5] << 8) |
@@ -469,46 +503,7 @@
             continue;
         }
 
-        int av_fd = createAvIonFd(mPesOutput.size());
-        if (av_fd == -1) {
-            return Result::UNKNOWN_ERROR;
-        }
-        // copy the filtered data to the buffer
-        uint8_t* avBuffer = getIonBuffer(av_fd, mPesOutput.size());
-        if (avBuffer == NULL) {
-            return Result::UNKNOWN_ERROR;
-        }
-        memcpy(avBuffer, mPesOutput.data(), mPesOutput.size() * sizeof(uint8_t));
-
-        native_handle_t* nativeHandle = createNativeHandle(av_fd);
-        if (nativeHandle == NULL) {
-            return Result::UNKNOWN_ERROR;
-        }
-        hidl_handle handle;
-        handle.setTo(nativeHandle, /*shouldOwn=*/true);
-
-        // 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
-        DemuxFilterMediaEvent mediaEvent;
-        mediaEvent = {
-                .avMemory = std::move(handle),
-                .dataLength = static_cast<uint32_t>(mPesOutput.size()),
-                .avDataId = dataId,
-        };
-        int size = mFilterEvent.events.size();
-        mFilterEvent.events.resize(size + 1);
-        mFilterEvent.events[size].media(mediaEvent);
-
-        // Clear and log
-        mPesOutput.clear();
-        mAvBufferCopyCount = 0;
-        ::close(av_fd);
-        if (DEBUG_FILTER) {
-            ALOGD("[Filter] assembled av data length %d", mediaEvent.dataLength);
-        }
+        createMediaFilterEventWithIon(mPesOutput);
     }
 
     mFilterOutput.clear();
@@ -516,13 +511,55 @@
     return Result::SUCCESS;
 }
 
+Result Filter::createMediaFilterEventWithIon(vector<uint8_t> output) {
+    int av_fd = createAvIonFd(output.size());
+    if (av_fd == -1) {
+        return Result::UNKNOWN_ERROR;
+    }
+    // copy the filtered data to the buffer
+    uint8_t* avBuffer = getIonBuffer(av_fd, output.size());
+    if (avBuffer == NULL) {
+        return Result::UNKNOWN_ERROR;
+    }
+    memcpy(avBuffer, output.data(), output.size() * sizeof(uint8_t));
+
+    native_handle_t* nativeHandle = createNativeHandle(av_fd);
+    if (nativeHandle == NULL) {
+        return Result::UNKNOWN_ERROR;
+    }
+    hidl_handle handle;
+    handle.setTo(nativeHandle, /*shouldOwn=*/true);
+
+    // 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
+    DemuxFilterMediaEvent mediaEvent;
+    mediaEvent = {
+            .avMemory = std::move(handle),
+            .dataLength = static_cast<uint32_t>(output.size()),
+            .avDataId = dataId,
+    };
+    if (mPts) {
+        mediaEvent.pts = mPts;
+        mPts = 0;
+    }
+    int size = mFilterEvent.events.size();
+    mFilterEvent.events.resize(size + 1);
+    mFilterEvent.events[size].media(mediaEvent);
+
+    // Clear and log
+    output.clear();
+    mAvBufferCopyCount = 0;
+    ::close(av_fd);
+    if (DEBUG_FILTER) {
+        ALOGD("[Filter] av data length %d", mediaEvent.dataLength);
+    }
+    return Result::SUCCESS;
+}
+
 Result Filter::startRecordFilterHandler() {
-    /*DemuxFilterTsRecordEvent tsRecordEvent;
-    tsRecordEvent.pid.tPid(0);
-    tsRecordEvent.indexMask.tsIndexMask(0x01);
-    mFilterEvent.events.resize(1);
-    mFilterEvent.events[0].tsRecord(tsRecordEvent);
-*/
     std::lock_guard<std::mutex> lock(mRecordFilterOutputLock);
     if (mRecordFilterOutput.empty()) {
         return Result::SUCCESS;
@@ -549,7 +586,7 @@
 
 bool Filter::writeSectionsAndCreateEvent(vector<uint8_t> data) {
     // TODO check how many sections has been read
-    ALOGD("[Filter] section hander");
+    ALOGD("[Filter] section handler");
     std::lock_guard<std::mutex> lock(mFilterEventLock);
     if (!writeDataToFilterMQ(data)) {
         return false;
diff --git a/tv/tuner/1.0/default/Filter.h b/tv/tuner/1.0/default/Filter.h
index 9b49ad8..9b18a66 100644
--- a/tv/tuner/1.0/default/Filter.h
+++ b/tv/tuner/1.0/default/Filter.h
@@ -84,11 +84,15 @@
     uint16_t getTpid();
     void updateFilterOutput(vector<uint8_t> data);
     void updateRecordOutput(vector<uint8_t> data);
+    void updatePts(uint64_t pts);
     Result startFilterHandler();
     Result startRecordFilterHandler();
     void attachFilterToRecord(const sp<Dvr> dvr);
     void detachFilterFromRecord();
     void freeAvHandle();
+    bool isMediaFilter() { return mIsMediaFilter; };
+    bool isPcrFilter() { return mIsPcrFilter; };
+    bool isRecordFilter() { return mIsRecordFilter; };
 
   private:
     // Tuner service
@@ -104,6 +108,8 @@
     uint32_t mBufferSize;
     DemuxFilterType mType;
     bool mIsMediaFilter = false;
+    bool mIsPcrFilter = false;
+    bool mIsRecordFilter = false;
     DemuxFilterSettings mFilterSettings;
 
     uint16_t mTpid;
@@ -111,6 +117,7 @@
     bool mIsDataSourceDemux = true;
     vector<uint8_t> mFilterOutput;
     vector<uint8_t> mRecordFilterOutput;
+    uint64_t mPts = 0;
     unique_ptr<FilterMQ> mFilterMQ;
     bool mIsUsingFMQ = false;
     EventFlag* mFilterEventFlag;
@@ -167,6 +174,7 @@
     int createAvIonFd(int size);
     uint8_t* getIonBuffer(int fd, int size);
     native_handle_t* createNativeHandle(int fd);
+    Result createMediaFilterEventWithIon(vector<uint8_t> output);
 
     /**
      * Lock to protect writes to the FMQs
diff --git a/tv/tuner/1.0/default/Frontend.cpp b/tv/tuner/1.0/default/Frontend.cpp
index 996b6ef..6561c92 100644
--- a/tv/tuner/1.0/default/Frontend.cpp
+++ b/tv/tuner/1.0/default/Frontend.cpp
@@ -42,6 +42,7 @@
     // Reset callback
     mCallback = nullptr;
     mIsLocked = false;
+    mTunerService->removeFrontend(mId);
 
     return Result::SUCCESS;
 }
@@ -66,7 +67,7 @@
 
     mTunerService->frontendStartTune(mId);
     mCallback->onEvent(FrontendEventType::LOCKED);
-    mIsLocked = false;
+    mIsLocked = true;
     return Result::SUCCESS;
 }
 
@@ -254,7 +255,9 @@
 
 Return<Result> Frontend::setLnb(uint32_t /* lnb */) {
     ALOGV("%s", __FUNCTION__);
-
+    if (!supportsSatellite()) {
+        return Result::INVALID_STATE;
+    }
     return Result::SUCCESS;
 }
 
@@ -266,10 +269,14 @@
     return mId;
 }
 
-string Frontend::getSourceFile() {
-    return FRONTEND_STREAM_FILE;
+bool Frontend::supportsSatellite() {
+    return mType == FrontendType::DVBS || mType == FrontendType::ISDBS ||
+           mType == FrontendType::ISDBS3;
 }
 
+bool Frontend::isLocked() {
+    return mIsLocked;
+}
 }  // namespace implementation
 }  // namespace V1_0
 }  // namespace tuner
diff --git a/tv/tuner/1.0/default/Frontend.h b/tv/tuner/1.0/default/Frontend.h
index 65537d7..a529b74 100644
--- a/tv/tuner/1.0/default/Frontend.h
+++ b/tv/tuner/1.0/default/Frontend.h
@@ -68,15 +68,17 @@
 
     string getSourceFile();
 
+    bool isLocked();
+
   private:
     virtual ~Frontend();
+    bool supportsSatellite();
     sp<IFrontendCallback> mCallback;
     sp<Tuner> mTunerService;
     FrontendType mType = FrontendType::UNDEFINED;
     FrontendId mId = 0;
     bool mIsLocked = false;
 
-    const string FRONTEND_STREAM_FILE = "/vendor/etc/segment000000.ts";
     std::ifstream mFrontendData;
 };
 
diff --git a/tv/tuner/1.0/default/TimeFilter.cpp b/tv/tuner/1.0/default/TimeFilter.cpp
index 0b1fd1c..cec824f 100644
--- a/tv/tuner/1.0/default/TimeFilter.cpp
+++ b/tv/tuner/1.0/default/TimeFilter.cpp
@@ -34,24 +34,32 @@
 
 TimeFilter::~TimeFilter() {}
 
-Return<Result> TimeFilter::setTimeStamp(uint64_t /* timeStamp */) {
+Return<Result> TimeFilter::setTimeStamp(uint64_t timeStamp) {
     ALOGV("%s", __FUNCTION__);
+    if (timeStamp == INVALID_TIME_STAMP) {
+        return Result::INVALID_ARGUMENT;
+    }
+    mTimeStamp = timeStamp;
+    mBeginTime = time(NULL);
 
     return Result::SUCCESS;
 }
 
 Return<Result> TimeFilter::clearTimeStamp() {
     ALOGV("%s", __FUNCTION__);
+    mTimeStamp = INVALID_TIME_STAMP;
 
     return Result::SUCCESS;
 }
 
 Return<void> TimeFilter::getTimeStamp(getTimeStamp_cb _hidl_cb) {
     ALOGV("%s", __FUNCTION__);
+    if (mTimeStamp == INVALID_TIME_STAMP) {
+        _hidl_cb(Result::INVALID_STATE, mTimeStamp);
+    }
 
-    uint64_t timeStamp = 0;
-
-    _hidl_cb(Result::SUCCESS, timeStamp);
+    uint64_t currentTimeStamp = mTimeStamp + difftime(time(NULL), mBeginTime) * 900000;
+    _hidl_cb(Result::SUCCESS, currentTimeStamp);
     return Void();
 }
 
@@ -66,6 +74,7 @@
 
 Return<Result> TimeFilter::close() {
     ALOGV("%s", __FUNCTION__);
+    mTimeStamp = INVALID_TIME_STAMP;
 
     return Result::SUCCESS;
 }
diff --git a/tv/tuner/1.0/default/TimeFilter.h b/tv/tuner/1.0/default/TimeFilter.h
index 7131df8..cb3f29d 100644
--- a/tv/tuner/1.0/default/TimeFilter.h
+++ b/tv/tuner/1.0/default/TimeFilter.h
@@ -19,6 +19,7 @@
 
 #include <android/hardware/tv/tuner/1.0/ITimeFilter.h>
 #include "Demux.h"
+#include "time.h"
 
 using namespace std;
 
@@ -35,6 +36,8 @@
 
 using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
 
+#define INVALID_TIME_STAMP -1
+
 class Demux;
 
 class TimeFilter : public ITimeFilter {
@@ -57,6 +60,8 @@
 
   private:
     sp<Demux> mDemux;
+    uint64_t mTimeStamp = INVALID_TIME_STAMP;
+    time_t mBeginTime;
 };
 
 }  // namespace implementation
diff --git a/tv/tuner/1.0/default/Tuner.cpp b/tv/tuner/1.0/default/Tuner.cpp
index 821d83f..9a6ecf7 100644
--- a/tv/tuner/1.0/default/Tuner.cpp
+++ b/tv/tuner/1.0/default/Tuner.cpp
@@ -37,7 +37,6 @@
     // Static Frontends array to maintain local frontends information
     // Array index matches their FrontendId in the default impl
     mFrontendSize = 8;
-    mFrontends.resize(mFrontendSize);
     mFrontends[0] = new Frontend(FrontendType::DVBT, 0, this);
     mFrontends[1] = new Frontend(FrontendType::ATSC, 1, this);
     mFrontends[2] = new Frontend(FrontendType::DVBC, 2, this);
@@ -48,7 +47,6 @@
     mFrontends[7] = new Frontend(FrontendType::ATSC, 7, this);
 
     FrontendInfo::FrontendCapabilities caps;
-    mFrontendCaps.resize(mFrontendSize);
     caps = FrontendInfo::FrontendCapabilities();
     caps.dvbtCaps(FrontendDvbtCapabilities());
     mFrontendCaps[0] = caps;
@@ -139,6 +137,8 @@
 
     DemuxCapabilities caps;
 
+    // IP filter can be an MMTP filter's data source.
+    caps.linkCaps = {0x00, 0x00, 0x02, 0x00, 0x00};
     _hidl_cb(Result::SUCCESS, caps);
     return Void();
 }
@@ -229,6 +229,24 @@
 
 void Tuner::setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId) {
     mFrontendToDemux[frontendId] = demuxId;
+    if (mFrontends[frontendId] != nullptr && mFrontends[frontendId]->isLocked()) {
+        mDemuxes[demuxId]->startFrontendInputLoop();
+    }
+}
+
+void Tuner::removeDemux(uint32_t demuxId) {
+    map<uint32_t, uint32_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(uint32_t frontendId) {
+    mFrontendToDemux.erase(frontendId);
 }
 
 void Tuner::frontendStopTune(uint32_t frontendId) {
diff --git a/tv/tuner/1.0/default/Tuner.h b/tv/tuner/1.0/default/Tuner.h
index 5de568f..1c09d6c 100644
--- a/tv/tuner/1.0/default/Tuner.h
+++ b/tv/tuner/1.0/default/Tuner.h
@@ -65,14 +65,16 @@
 
     void frontendStartTune(uint32_t frontendId);
     void frontendStopTune(uint32_t frontendId);
+    void removeDemux(uint32_t demuxId);
+    void removeFrontend(uint32_t frontendId);
 
   private:
     virtual ~Tuner();
     // Static mFrontends array to maintain local frontends information
-    vector<sp<Frontend>> mFrontends;
-    vector<FrontendInfo::FrontendCapabilities> mFrontendCaps;
-    std::map<uint32_t, uint32_t> mFrontendToDemux;
-    std::map<uint32_t, sp<Demux>> mDemuxes;
+    map<uint32_t, sp<Frontend>> mFrontends;
+    map<uint32_t, FrontendInfo::FrontendCapabilities> mFrontendCaps;
+    map<uint32_t, uint32_t> mFrontendToDemux;
+    map<uint32_t, sp<Demux>> mDemuxes;
     // To maintain how many Frontends we have
     int mFrontendSize;
     // The last used demux id. Initial value is -1.
diff --git a/tv/tuner/1.0/vts/functional/Android.bp b/tv/tuner/1.0/vts/functional/Android.bp
index b152a29..1765915 100644
--- a/tv/tuner/1.0/vts/functional/Android.bp
+++ b/tv/tuner/1.0/vts/functional/Android.bp
@@ -23,8 +23,13 @@
         "DemuxTests.cpp",
         "FilterTests.cpp",
         "DvrTests.cpp",
+        "DescramblerTests.cpp",
+        "LnbTests.cpp",
     ],
     static_libs: [
+        "android.hardware.cas@1.0",
+        "android.hardware.cas@1.1",
+        "android.hardware.cas@1.2",
         "android.hardware.tv.tuner@1.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
diff --git a/tv/tuner/1.0/vts/functional/DemuxTests.cpp b/tv/tuner/1.0/vts/functional/DemuxTests.cpp
index b1d8a0a..37a47d7 100644
--- a/tv/tuner/1.0/vts/functional/DemuxTests.cpp
+++ b/tv/tuner/1.0/vts/functional/DemuxTests.cpp
@@ -33,9 +33,43 @@
     return AssertionResult(status.isOk());
 }
 
+AssertionResult DemuxTests::getDemuxCaps(DemuxCapabilities& demuxCaps) {
+    if (!mDemux) {
+        ALOGW("[vts] Test with openDemux first.");
+        return failure();
+    }
+    Result status;
+    mService->getDemuxCaps([&](Result result, DemuxCapabilities caps) {
+        status = result;
+        demuxCaps = caps;
+    });
+    return AssertionResult(status == Result::SUCCESS);
+}
+
 AssertionResult DemuxTests::closeDemux() {
     EXPECT_TRUE(mDemux) << "Test with openDemux first.";
     auto status = mDemux->close();
     mDemux = nullptr;
     return AssertionResult(status.isOk());
+}
+
+AssertionResult DemuxTests::getAvSyncId(sp<IFilter> filter, uint32_t& avSyncHwId) {
+    EXPECT_TRUE(mDemux) << "Demux is not opened yet.";
+    Result status;
+    mDemux->getAvSyncHwId(filter, [&](Result result, uint32_t id) {
+        status = result;
+        avSyncHwId = id;
+    });
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DemuxTests::getAvSyncTime(uint32_t avSyncId) {
+    EXPECT_TRUE(mDemux) << "Demux is not opened yet.";
+    Result status;
+    uint64_t syncTime;
+    mDemux->getAvSyncTime(avSyncId, [&](Result result, uint64_t time) {
+        status = result;
+        syncTime = time;
+    });
+    return AssertionResult(status == Result::SUCCESS);
 }
\ No newline at end of file
diff --git a/tv/tuner/1.0/vts/functional/DemuxTests.h b/tv/tuner/1.0/vts/functional/DemuxTests.h
index 6e1e395..b249ea8 100644
--- a/tv/tuner/1.0/vts/functional/DemuxTests.h
+++ b/tv/tuner/1.0/vts/functional/DemuxTests.h
@@ -30,7 +30,9 @@
 using android::sp;
 using android::hardware::Return;
 using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::DemuxCapabilities;
 using android::hardware::tv::tuner::V1_0::IDemux;
+using android::hardware::tv::tuner::V1_0::IFilter;
 using android::hardware::tv::tuner::V1_0::ITuner;
 using android::hardware::tv::tuner::V1_0::Result;
 
@@ -42,6 +44,9 @@
 
     AssertionResult openDemux(sp<IDemux>& demux, uint32_t& demuxId);
     AssertionResult setDemuxFrontendDataSource(uint32_t frontendId);
+    AssertionResult getAvSyncId(sp<IFilter> filter, uint32_t& avSyncHwId);
+    AssertionResult getAvSyncTime(uint32_t avSyncId);
+    AssertionResult getDemuxCaps(DemuxCapabilities& demuxCaps);
     AssertionResult closeDemux();
 
   protected:
diff --git a/tv/tuner/1.0/vts/functional/DescramblerTests.cpp b/tv/tuner/1.0/vts/functional/DescramblerTests.cpp
new file mode 100644
index 0000000..2e27475
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/DescramblerTests.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "DescramblerTests.h"
+
+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(TunerKeyToken& 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();
+    }
+
+    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,
+                                              hidl_vec<uint8_t> hidlPvtData, TunerKeyToken& 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(uint32_t demuxId) {
+    Result status;
+    mService->openDescrambler([&](Result result, const sp<IDescrambler>& descrambler) {
+        mDescrambler = descrambler;
+        status = result;
+    });
+    if (status != Result::SUCCESS) {
+        ALOGW("[vts] openDescrambler failed.");
+        return failure();
+    }
+
+    status = mDescrambler->setDemuxSource(demuxId);
+    if (status != Result::SUCCESS) {
+        ALOGW("[vts] setDemuxSource failed.");
+        return failure();
+    }
+
+    return success();
+}
+
+AssertionResult DescramblerTests::setKeyToken(TunerKeyToken token) {
+    Result status;
+    if (!mDescrambler) {
+        ALOGW("[vts] Descrambler is not opened yet.");
+        return failure();
+    }
+
+    status = mDescrambler->setKeyToken(token);
+    if (status != Result::SUCCESS) {
+        ALOGW("[vts] setKeyToken failed.");
+        return failure();
+    }
+
+    return success();
+}
+
+AssertionResult DescramblerTests::addPid(DemuxPid pid, sp<IFilter> optionalSourceFilter) {
+    Result status;
+    if (!mDescrambler) {
+        ALOGW("[vts] Descrambler is not opened yet.");
+        return failure();
+    }
+
+    status = mDescrambler->addPid(pid, optionalSourceFilter);
+    if (status != Result::SUCCESS) {
+        ALOGW("[vts] addPid failed.");
+        return failure();
+    }
+
+    return success();
+}
+
+AssertionResult DescramblerTests::removePid(DemuxPid pid, sp<IFilter> optionalSourceFilter) {
+    Result status;
+    if (!mDescrambler) {
+        ALOGW("[vts] Descrambler is not opened yet.");
+        return failure();
+    }
+
+    status = mDescrambler->removePid(pid, optionalSourceFilter);
+    if (status != Result::SUCCESS) {
+        ALOGW("[vts] removePid failed.");
+        return failure();
+    }
+
+    return success();
+}
+
+AssertionResult DescramblerTests::closeDescrambler() {
+    Result status;
+    if (!mDescrambler) {
+        ALOGW("[vts] Descrambler is not opened yet.");
+        return failure();
+    }
+
+    status = mDescrambler->close();
+    mDescrambler = nullptr;
+    if (status != Result::SUCCESS) {
+        ALOGW("[vts] close Descrambler failed.");
+        return failure();
+    }
+
+    return success();
+}
+
+AssertionResult DescramblerTests::getDemuxPidFromFilterSettings(DemuxFilterType type,
+                                                                DemuxFilterSettings settings,
+                                                                DemuxPid& pid) {
+    switch (type.mainType) {
+        case DemuxFilterMainType::TS:
+            if (type.subType.tsFilterType() == DemuxTsFilterType::AUDIO ||
+                type.subType.tsFilterType() == DemuxTsFilterType::VIDEO) {
+                pid.tPid(settings.ts().tpid);
+            } else {
+                ALOGW("[vts] Not a media ts filter!");
+                return failure();
+            }
+            break;
+        case DemuxFilterMainType::MMTP:
+            if (type.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
+                type.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
+                pid.mmtpPid(settings.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/1.0/vts/functional/DescramblerTests.h b/tv/tuner/1.0/vts/functional/DescramblerTests.h
new file mode 100644
index 0000000..16d480d
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/DescramblerTests.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#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 <android/hardware/tv/tuner/1.0/IDescrambler.h>
+#include <android/hardware/tv/tuner/1.0/IDvr.h>
+#include <android/hardware/tv/tuner/1.0/IDvrCallback.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <fmq/MessageQueue.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/Status.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <fstream>
+#include <iostream>
+#include <map>
+
+using android::Condition;
+using android::Mutex;
+using android::sp;
+using android::hardware::EventFlag;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+using android::hardware::kSynchronizedReadWrite;
+using android::hardware::MessageQueue;
+using android::hardware::MQDescriptorSync;
+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 android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
+using android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxPid;
+using android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
+using android::hardware::tv::tuner::V1_0::IDescrambler;
+using android::hardware::tv::tuner::V1_0::IFilter;
+using android::hardware::tv::tuner::V1_0::ITuner;
+using android::hardware::tv::tuner::V1_0::Result;
+using android::hardware::tv::tuner::V1_0::TunerKeyToken;
+
+using ::testing::AssertionResult;
+
+using namespace std;
+
+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(sp<ITuner> tuner) { mService = tuner; }
+    void setCasService(sp<IMediaCasService> casService) { mMediaCasService = casService; }
+
+    AssertionResult setKeyToken(TunerKeyToken token);
+    AssertionResult openDescrambler(uint32_t demuxId);
+    AssertionResult addPid(DemuxPid pid, sp<IFilter> optionalSourceFilter);
+    AssertionResult removePid(DemuxPid pid, sp<IFilter> optionalSourceFilter);
+    AssertionResult closeDescrambler();
+    AssertionResult getKeyToken(int32_t caSystemId, string provisonStr,
+                                hidl_vec<uint8_t> hidlPvtData, TunerKeyToken& token);
+    AssertionResult getDemuxPidFromFilterSettings(DemuxFilterType type,
+                                                  DemuxFilterSettings settings, DemuxPid& pid);
+
+  protected:
+    static AssertionResult failure() { return ::testing::AssertionFailure(); }
+
+    static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+    sp<ITuner> mService;
+    sp<ICas> mCas;
+    sp<IMediaCasService> mMediaCasService;
+    sp<MediaCasListener> mCasListener;
+    sp<IDescrambler> mDescrambler;
+
+  private:
+    AssertionResult openCasSession(TunerKeyToken& sessionId, vector<uint8_t> hidlPvtData);
+    AssertionResult createCasPlugin(int32_t caSystemId);
+};
diff --git a/tv/tuner/1.0/vts/functional/DvrTests.cpp b/tv/tuner/1.0/vts/functional/DvrTests.cpp
index 7e7f8e6..0dfc032 100644
--- a/tv/tuner/1.0/vts/functional/DvrTests.cpp
+++ b/tv/tuner/1.0/vts/functional/DvrTests.cpp
@@ -49,49 +49,73 @@
     EXPECT_TRUE(EventFlag::createEventFlag(mPlaybackMQ->getEventFlagWord(), &playbackMQEventFlag) ==
                 android::OK);
 
-    // open the stream and get its length
-    std::ifstream inputData(mInputDataFile.c_str(), std::ifstream::binary);
-    int writeSize = mPlaybackSettings.packetSize * 6;
-    char* buffer = new char[writeSize];
-    ALOGW("[vts] playback thread loop start %s!", mInputDataFile.c_str());
-    if (!inputData.is_open()) {
+    int fd = open(mInputDataFile.c_str(), O_RDONLY | O_LARGEFILE);
+    int readBytes;
+    uint32_t regionSize = 0;
+    uint8_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) {
-        // move the stream pointer for packet size * 6 every read until the end
         while (mKeepWritingPlaybackFMQ) {
-            inputData.read(buffer, writeSize);
-            if (!inputData) {
-                int leftSize = inputData.gcount();
-                if (leftSize == 0) {
-                    mPlaybackThreadRunning = false;
-                    break;
-                }
-                inputData.clear();
-                inputData.read(buffer, leftSize);
-                // Write the left over of the input data and quit the thread
-                if (leftSize > 0) {
-                    EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], leftSize));
-                    playbackMQEventFlag->wake(
-                            static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
-                }
+            int totalWrite = mPlaybackMQ->availableToWrite();
+            if (totalWrite * 4 < mPlaybackMQ->getQuantumCount()) {
+                // Wait for the HAL implementation to read more data then write.
+                continue;
+            }
+            MessageQueue<uint8_t, kSynchronizedReadWrite>::MemTransaction memTx;
+            if (!mPlaybackMQ->beginWrite(totalWrite, &memTx)) {
+                ALOGW("[vts] Fail to write into Playback fmq.");
                 mPlaybackThreadRunning = false;
                 break;
             }
-            // Write input FMQ and notify the Tuner Implementation
-            EXPECT_TRUE(mPlaybackMQ->write((unsigned char*)&buffer[0], writeSize));
+            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));
-            inputData.seekg(writeSize, inputData.cur);
-            sleep(1);
         }
     }
 
+    mPlaybackThreadRunning = false;
     ALOGW("[vts] Playback thread end.");
-
-    delete[] buffer;
-    inputData.close();
+    close(fd);
 }
 
 void DvrCallback::testRecordOutput() {
@@ -186,32 +210,65 @@
     EXPECT_TRUE(mDemux) << "Test with openDemux first.";
 
     // Create dvr callback
-    mDvrCallback = new DvrCallback();
+    if (type == DvrType::PLAYBACK) {
+        mDvrPlaybackCallback = new DvrCallback();
+        mDemux->openDvr(type, bufferSize, mDvrPlaybackCallback,
+                        [&](Result result, const sp<IDvr>& dvr) {
+                            mDvrPlayback = dvr;
+                            status = result;
+                        });
+        if (status == Result::SUCCESS) {
+            mDvrPlaybackCallback->setDvr(mDvrPlayback);
+        }
+    }
 
-    mDemux->openDvr(type, bufferSize, mDvrCallback, [&](Result result, const sp<IDvr>& dvr) {
-        mDvr = dvr;
+    if (type == DvrType::RECORD) {
+        mDvrRecordCallback = new DvrCallback();
+        mDemux->openDvr(type, bufferSize, mDvrRecordCallback,
+                        [&](Result result, const sp<IDvr>& dvr) {
+                            mDvrRecord = dvr;
+                            status = result;
+                        });
+        if (status == Result::SUCCESS) {
+            mDvrRecordCallback->setDvr(mDvrRecord);
+        }
+    }
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::configDvrPlayback(DvrSettings setting) {
+    Result status = mDvrPlayback->configure(setting);
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::configDvrRecord(DvrSettings setting) {
+    Result status = mDvrRecord->configure(setting);
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::getDvrPlaybackMQDescriptor() {
+    Result status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
+
+    mDvrPlayback->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
+        mDvrPlaybackMQDescriptor = dvrMQDesc;
         status = result;
     });
 
-    if (status == Result::SUCCESS) {
-        mDvrCallback->setDvr(mDvr);
-    }
     return AssertionResult(status == Result::SUCCESS);
 }
 
-AssertionResult DvrTests::configDvr(DvrSettings setting) {
-    Result status = mDvr->configure(setting);
-
-    return AssertionResult(status == Result::SUCCESS);
-}
-
-AssertionResult DvrTests::getDvrMQDescriptor() {
+AssertionResult DvrTests::getDvrRecordMQDescriptor() {
     Result status;
     EXPECT_TRUE(mDemux) << "Test with openDemux first.";
-    EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+    EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
 
-    mDvr->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
-        mDvrMQDescriptor = dvrMQDesc;
+    mDvrRecord->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
+        mDvrRecordMQDescriptor = dvrMQDesc;
         status = result;
     });
 
@@ -221,9 +278,9 @@
 AssertionResult DvrTests::attachFilterToDvr(sp<IFilter> filter) {
     Result status;
     EXPECT_TRUE(mDemux) << "Test with openDemux first.";
-    EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+    EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
 
-    status = mDvr->attachFilter(filter);
+    status = mDvrRecord->attachFilter(filter);
 
     return AssertionResult(status == Result::SUCCESS);
 }
@@ -231,35 +288,61 @@
 AssertionResult DvrTests::detachFilterToDvr(sp<IFilter> filter) {
     Result status;
     EXPECT_TRUE(mDemux) << "Test with openDemux first.";
-    EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+    EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
 
-    status = mDvr->detachFilter(filter);
+    status = mDvrRecord->detachFilter(filter);
 
     return AssertionResult(status == Result::SUCCESS);
 }
 
-AssertionResult DvrTests::startDvr() {
+AssertionResult DvrTests::startDvrPlayback() {
     Result status;
     EXPECT_TRUE(mDemux) << "Test with openDemux first.";
-    EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+    EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
 
-    status = mDvr->start();
+    status = mDvrPlayback->start();
 
     return AssertionResult(status == Result::SUCCESS);
 }
 
-AssertionResult DvrTests::stopDvr() {
+AssertionResult DvrTests::stopDvrPlayback() {
     Result status;
     EXPECT_TRUE(mDemux) << "Test with openDemux first.";
-    EXPECT_TRUE(mDvr) << "Test with openDvr first.";
+    EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
 
-    status = mDvr->stop();
+    status = mDvrPlayback->stop();
 
     return AssertionResult(status == Result::SUCCESS);
 }
 
-void DvrTests::closeDvr() {
+void DvrTests::closeDvrPlayback() {
     ASSERT_TRUE(mDemux);
-    ASSERT_TRUE(mDvr);
-    ASSERT_TRUE(mDvr->close() == Result::SUCCESS);
+    ASSERT_TRUE(mDvrPlayback);
+    ASSERT_TRUE(mDvrPlayback->close() == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::startDvrRecord() {
+    Result status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+    status = mDvrRecord->start();
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::stopDvrRecord() {
+    Result status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+    status = mDvrRecord->stop();
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+void DvrTests::closeDvrRecord() {
+    ASSERT_TRUE(mDemux);
+    ASSERT_TRUE(mDvrRecord);
+    ASSERT_TRUE(mDvrRecord->close() == Result::SUCCESS);
 }
diff --git a/tv/tuner/1.0/vts/functional/DvrTests.h b/tv/tuner/1.0/vts/functional/DvrTests.h
index dd00c27..3997839 100644
--- a/tv/tuner/1.0/vts/functional/DvrTests.h
+++ b/tv/tuner/1.0/vts/functional/DvrTests.h
@@ -14,14 +14,15 @@
  * limitations under the License.
  */
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/tv/tuner/1.0/IDvr.h>
 #include <android/hardware/tv/tuner/1.0/IDvrCallback.h>
 #include <android/hardware/tv/tuner/1.0/ITuner.h>
 #include <android/hardware/tv/tuner/1.0/types.h>
+#include <fcntl.h>
 #include <fmq/MessageQueue.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
 #include <hidl/Status.h>
 #include <utils/Condition.h>
 #include <utils/Mutex.h>
@@ -52,6 +53,8 @@
 using android::hardware::tv::tuner::V1_0::RecordStatus;
 using android::hardware::tv::tuner::V1_0::Result;
 
+using namespace std;
+
 #define WAIT_TIMEOUT 3000000000
 
 class DvrCallback : public IDvrCallback {
@@ -149,25 +152,31 @@
     void setDemux(sp<IDemux> demux) { mDemux = demux; }
 
     void startPlaybackInputThread(string& dataInputFile, PlaybackSettings& settings) {
-        mDvrCallback->startPlaybackInputThread(dataInputFile, settings, mDvrMQDescriptor);
+        mDvrPlaybackCallback->startPlaybackInputThread(dataInputFile, settings,
+                                                       mDvrPlaybackMQDescriptor);
     };
 
     void startRecordOutputThread(RecordSettings settings) {
-        mDvrCallback->startRecordOutputThread(settings, mDvrMQDescriptor);
+        mDvrRecordCallback->startRecordOutputThread(settings, mDvrRecordMQDescriptor);
     };
 
-    void stopPlaybackThread() { mDvrCallback->stopPlaybackThread(); }
-    void testRecordOutput() { mDvrCallback->testRecordOutput(); }
-    void stopRecordThread() { mDvrCallback->stopPlaybackThread(); }
+    void stopPlaybackThread() { mDvrPlaybackCallback->stopPlaybackThread(); }
+    void testRecordOutput() { mDvrRecordCallback->testRecordOutput(); }
+    void stopRecordThread() { mDvrRecordCallback->stopRecordThread(); }
 
     AssertionResult openDvrInDemux(DvrType type, uint32_t bufferSize);
-    AssertionResult configDvr(DvrSettings setting);
-    AssertionResult getDvrMQDescriptor();
+    AssertionResult configDvrPlayback(DvrSettings setting);
+    AssertionResult configDvrRecord(DvrSettings setting);
+    AssertionResult getDvrPlaybackMQDescriptor();
+    AssertionResult getDvrRecordMQDescriptor();
     AssertionResult attachFilterToDvr(sp<IFilter> filter);
     AssertionResult detachFilterToDvr(sp<IFilter> filter);
-    AssertionResult stopDvr();
-    AssertionResult startDvr();
-    void closeDvr();
+    AssertionResult stopDvrPlayback();
+    AssertionResult startDvrPlayback();
+    AssertionResult stopDvrRecord();
+    AssertionResult startDvrRecord();
+    void closeDvrPlayback();
+    void closeDvrRecord();
 
   protected:
     static AssertionResult failure() { return ::testing::AssertionFailure(); }
@@ -175,11 +184,11 @@
     static AssertionResult success() { return ::testing::AssertionSuccess(); }
 
     sp<ITuner> mService;
-    sp<IDvr> mDvr;
+    sp<IDvr> mDvrPlayback;
+    sp<IDvr> mDvrRecord;
     sp<IDemux> mDemux;
-    sp<DvrCallback> mDvrCallback;
-    MQDesc mDvrMQDescriptor;
-
-    pthread_t mPlaybackshread;
-    bool mPlaybackThreadRunning;
+    sp<DvrCallback> mDvrPlaybackCallback;
+    sp<DvrCallback> mDvrRecordCallback;
+    MQDesc mDvrPlaybackMQDescriptor;
+    MQDesc mDvrRecordMQDescriptor;
 };
diff --git a/tv/tuner/1.0/vts/functional/FilterTests.cpp b/tv/tuner/1.0/vts/functional/FilterTests.cpp
index 4639e59..5f5d108 100644
--- a/tv/tuner/1.0/vts/functional/FilterTests.cpp
+++ b/tv/tuner/1.0/vts/functional/FilterTests.cpp
@@ -85,7 +85,7 @@
             case FilterEventType::MEDIA:
                 return dumpAvData(filterEvent.events[i].media());
             case FilterEventType::RECORD:
-                break;
+                return readRecordData(filterEvent.events[i].tsRecord());
             case FilterEventType::MMTPRECORD:
                 break;
             case FilterEventType::DOWNLOAD:
@@ -128,6 +128,11 @@
     return true;
 }
 
+bool FilterCallback::readRecordData(DemuxFilterTsRecordEvent event) {
+    ALOGD("[vts] got DemuxFilterTsRecordEvent with pid=%d.", event.pid.tPid());
+    return true;
+}
+
 AssertionResult FilterTests::openFilterInDemux(DemuxFilterType type, uint32_t bufferSize) {
     Result status;
     EXPECT_TRUE(mDemux) << "Test with openDemux first.";
@@ -149,6 +154,44 @@
     return AssertionResult(status == Result::SUCCESS);
 }
 
+AssertionResult FilterTests::openTimeFilterInDemux() {
+    if (!mDemux) {
+        ALOGW("[vts] Test with openDemux first.");
+        return failure();
+    }
+
+    // Add time filter to the local demux
+    Result status;
+    mDemux->openTimeFilter([&](Result result, const sp<ITimeFilter>& filter) {
+        mTimeFilter = filter;
+        status = result;
+    });
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::setTimeStamp(uint64_t timeStamp) {
+    if (!mTimeFilter) {
+        ALOGW("[vts] Test with openTimeFilterInDemux first.");
+        return failure();
+    }
+
+    mBeginTimeStamp = timeStamp;
+    return AssertionResult(mTimeFilter->setTimeStamp(timeStamp) == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::getTimeStamp() {
+    if (!mTimeFilter) {
+        ALOGW("[vts] Test with openTimeFilterInDemux first.");
+        return failure();
+    }
+
+    Result status;
+    mTimeFilter->getTimeStamp([&](Result result, uint64_t /*timeStamp*/) { status = result; });
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
 AssertionResult FilterTests::getNewlyOpenedFilterId(uint32_t& filterId) {
     Result status;
     EXPECT_TRUE(mDemux) << "Test with openDemux first.";
@@ -197,6 +240,26 @@
     return AssertionResult(status == Result::SUCCESS);
 }
 
+AssertionResult FilterTests::setFilterDataSource(uint32_t sourceFilterId, uint32_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 == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::setFilterDataSourceToDemux(uint32_t filterId) {
+    if (!mFilters[filterId]) {
+        ALOGE("[vts] setFilterDataSourceToDemux filter not opened.");
+        return failure();
+    }
+
+    auto status = mFilters[filterId]->setDataSource(NULL);
+    return AssertionResult(status == Result::SUCCESS);
+}
+
 AssertionResult FilterTests::startFilter(uint32_t filterId) {
     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
     Result status = mFilters[filterId]->start();
@@ -209,6 +272,15 @@
     return AssertionResult(status == Result::SUCCESS);
 }
 
+AssertionResult FilterTests::clearTimeStamp() {
+    if (!mTimeFilter) {
+        ALOGW("[vts] Test with openTimeFilterInDemux first.");
+        return failure();
+    }
+
+    return AssertionResult(mTimeFilter->clearTimeStamp() == Result::SUCCESS);
+}
+
 AssertionResult FilterTests::closeFilter(uint32_t filterId) {
     EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
     Result status = mFilters[filterId]->close();
@@ -224,3 +296,12 @@
     }
     return AssertionResult(status == Result::SUCCESS);
 }
+
+AssertionResult FilterTests::closeTimeFilter() {
+    if (!mTimeFilter) {
+        ALOGW("[vts] Test with openTimeFilterInDemux first.");
+        return failure();
+    }
+
+    return AssertionResult(mTimeFilter->close() == Result::SUCCESS);
+}
diff --git a/tv/tuner/1.0/vts/functional/FilterTests.h b/tv/tuner/1.0/vts/functional/FilterTests.h
index 71efce4..8ac9c55 100644
--- a/tv/tuner/1.0/vts/functional/FilterTests.h
+++ b/tv/tuner/1.0/vts/functional/FilterTests.h
@@ -50,6 +50,7 @@
 using android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings;
 using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
 using android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using android::hardware::tv::tuner::V1_0::DemuxFilterTsRecordEvent;
 using android::hardware::tv::tuner::V1_0::DemuxFilterType;
 using android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
 using android::hardware::tv::tuner::V1_0::DemuxTsFilterSettings;
@@ -57,6 +58,7 @@
 using android::hardware::tv::tuner::V1_0::IDemux;
 using android::hardware::tv::tuner::V1_0::IFilter;
 using android::hardware::tv::tuner::V1_0::IFilterCallback;
+using android::hardware::tv::tuner::V1_0::ITimeFilter;
 using android::hardware::tv::tuner::V1_0::ITuner;
 using android::hardware::tv::tuner::V1_0::Result;
 
@@ -114,6 +116,7 @@
     void updateGoldenOutputMap(string goldenOutputFile);
     bool readFilterEventData();
     bool dumpAvData(DemuxFilterMediaEvent event);
+    bool readRecordData(DemuxFilterTsRecordEvent event);
 
   private:
     struct FilterThreadArgs {
@@ -151,12 +154,19 @@
     std::map<uint32_t, sp<FilterCallback>> getFilterCallbacks() { return mFilterCallbacks; }
 
     AssertionResult openFilterInDemux(DemuxFilterType type, uint32_t bufferSize);
+    AssertionResult openTimeFilterInDemux();
+    AssertionResult setTimeStamp(uint64_t timeStamp);
+    AssertionResult getTimeStamp();
     AssertionResult getNewlyOpenedFilterId(uint32_t& filterId);
     AssertionResult configFilter(DemuxFilterSettings setting, uint32_t filterId);
     AssertionResult getFilterMQDescriptor(uint32_t filterId);
+    AssertionResult setFilterDataSource(uint32_t sourceFilterId, uint32_t sinkFilterId);
+    AssertionResult setFilterDataSourceToDemux(uint32_t filterId);
     AssertionResult startFilter(uint32_t filterId);
+    AssertionResult clearTimeStamp();
     AssertionResult stopFilter(uint32_t filterId);
     AssertionResult closeFilter(uint32_t filterId);
+    AssertionResult closeTimeFilter();
 
     FilterEventType getFilterEventType(DemuxFilterType type) {
         FilterEventType eventType = FilterEventType::UNDEFINED;
@@ -212,6 +222,7 @@
 
     sp<ITuner> mService;
     sp<IFilter> mFilter;
+    sp<ITimeFilter> mTimeFilter;
     sp<IDemux> mDemux;
     std::map<uint32_t, sp<IFilter>> mFilters;
     std::map<uint32_t, sp<FilterCallback>> mFilterCallbacks;
@@ -221,4 +232,5 @@
     vector<uint32_t> mUsedFilterIds;
 
     uint32_t mFilterId = -1;
+    uint64_t mBeginTimeStamp;
 };
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.cpp b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
index fc5071c..b35d112 100644
--- a/tv/tuner/1.0/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
@@ -246,21 +246,160 @@
     return AssertionResult(status == Result::SUCCESS);
 }
 
-AssertionResult FrontendTests::tuneFrontend(FrontendConfig config) {
+void FrontendTests::verifyFrontendStatus(vector<FrontendStatusType> statusTypes,
+                                         vector<FrontendStatus> expectStatuses) {
+    ASSERT_TRUE(mFrontend) << "Frontend is not opened yet.";
+    Result status;
+    vector<FrontendStatus> realStatuses;
+
+    mFrontend->getStatus(statusTypes, [&](Result result, const hidl_vec<FrontendStatus>& statuses) {
+        status = result;
+        realStatuses = statuses;
+    });
+
+    ASSERT_TRUE(realStatuses.size() == statusTypes.size());
+    for (int i = 0; i < statusTypes.size(); i++) {
+        FrontendStatusType type = statusTypes[i];
+        switch (type) {
+            case FrontendStatusType::DEMOD_LOCK: {
+                ASSERT_TRUE(realStatuses[i].isDemodLocked() == expectStatuses[i].isDemodLocked());
+                break;
+            }
+            case FrontendStatusType::SNR: {
+                ASSERT_TRUE(realStatuses[i].snr() == expectStatuses[i].snr());
+                break;
+            }
+            case FrontendStatusType::BER: {
+                ASSERT_TRUE(realStatuses[i].ber() == expectStatuses[i].ber());
+                break;
+            }
+            case FrontendStatusType::PER: {
+                ASSERT_TRUE(realStatuses[i].per() == expectStatuses[i].per());
+                break;
+            }
+            case FrontendStatusType::PRE_BER: {
+                ASSERT_TRUE(realStatuses[i].preBer() == expectStatuses[i].preBer());
+                break;
+            }
+            case FrontendStatusType::SIGNAL_QUALITY: {
+                ASSERT_TRUE(realStatuses[i].signalQuality() == expectStatuses[i].signalQuality());
+                break;
+            }
+            case FrontendStatusType::SIGNAL_STRENGTH: {
+                ASSERT_TRUE(realStatuses[i].signalStrength() == expectStatuses[i].signalStrength());
+                break;
+            }
+            case FrontendStatusType::SYMBOL_RATE: {
+                ASSERT_TRUE(realStatuses[i].symbolRate() == expectStatuses[i].symbolRate());
+                break;
+            }
+            case FrontendStatusType::FEC: {
+                ASSERT_TRUE(realStatuses[i].innerFec() == expectStatuses[i].innerFec());
+                break;
+            }
+            case FrontendStatusType::MODULATION: {
+                // TODO: check modulation status
+                break;
+            }
+            case FrontendStatusType::SPECTRAL: {
+                ASSERT_TRUE(realStatuses[i].inversion() == expectStatuses[i].inversion());
+                break;
+            }
+            case FrontendStatusType::LNB_VOLTAGE: {
+                ASSERT_TRUE(realStatuses[i].lnbVoltage() == expectStatuses[i].lnbVoltage());
+                break;
+            }
+            case FrontendStatusType::PLP_ID: {
+                ASSERT_TRUE(realStatuses[i].plpId() == expectStatuses[i].plpId());
+                break;
+            }
+            case FrontendStatusType::EWBS: {
+                ASSERT_TRUE(realStatuses[i].isEWBS() == expectStatuses[i].isEWBS());
+                break;
+            }
+            case FrontendStatusType::AGC: {
+                ASSERT_TRUE(realStatuses[i].agc() == expectStatuses[i].agc());
+                break;
+            }
+            case FrontendStatusType::LNA: {
+                ASSERT_TRUE(realStatuses[i].isLnaOn() == expectStatuses[i].isLnaOn());
+                break;
+            }
+            case FrontendStatusType::LAYER_ERROR: {
+                vector<bool> realLayberError = realStatuses[i].isLayerError();
+                vector<bool> expectLayerError = expectStatuses[i].isLayerError();
+                ASSERT_TRUE(realLayberError.size() == expectLayerError.size());
+                for (int i = 0; i < realLayberError.size(); i++) {
+                    ASSERT_TRUE(realLayberError[i] == expectLayerError[i]);
+                }
+                break;
+            }
+            case FrontendStatusType::MER: {
+                ASSERT_TRUE(realStatuses[i].mer() == expectStatuses[i].mer());
+                break;
+            }
+            case FrontendStatusType::FREQ_OFFSET: {
+                ASSERT_TRUE(realStatuses[i].freqOffset() == expectStatuses[i].freqOffset());
+                break;
+            }
+            case FrontendStatusType::HIERARCHY: {
+                ASSERT_TRUE(realStatuses[i].hierarchy() == expectStatuses[i].hierarchy());
+                break;
+            }
+            case FrontendStatusType::RF_LOCK: {
+                ASSERT_TRUE(realStatuses[i].isRfLocked() == expectStatuses[i].isRfLocked());
+                break;
+            }
+            case FrontendStatusType::ATSC3_PLP_INFO:
+                // TODO: verify plpinfo
+                break;
+            default:
+                continue;
+        }
+    }
+    ASSERT_TRUE(status == Result::SUCCESS);
+}
+
+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;
+    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());
+        if (!result) {
+            ALOGW("[vts] Software frontend dvr configure failed.");
+            return failure();
+        }
+    }
     mFrontendCallback->tuneTestOnLock(mFrontend, config.settings);
     return AssertionResult(true);
 }
 
-AssertionResult FrontendTests::stopTuneFrontend() {
+AssertionResult FrontendTests::setLnb(uint32_t lnbId) {
+    if (!mFrontendCallback) {
+        ALOGW("[vts] open and set frontend callback first.");
+        return failure();
+    }
+    return AssertionResult(mFrontend->setLnb(lnbId) == Result::SUCCESS);
+}
+
+AssertionResult FrontendTests::stopTuneFrontend(bool testWithDemux) {
     EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
     Result status;
     status = mFrontend->stopTune();
+    if (mIsSoftwareFe && testWithDemux) {
+        mDvrTests.stopPlaybackThread();
+        mDvrTests.closeDvrPlayback();
+    }
     return AssertionResult(status == Result::SUCCESS);
 }
 
@@ -293,8 +432,9 @@
     ASSERT_TRUE(feId != INVALID_ID);
     ASSERT_TRUE(openFrontendById(feId));
     ASSERT_TRUE(setFrontendCallback());
-    ASSERT_TRUE(tuneFrontend(frontendConf));
-    ASSERT_TRUE(stopTuneFrontend());
+    ASSERT_TRUE(tuneFrontend(frontendConf, false /*testWithDemux*/));
+    verifyFrontendStatus(frontendConf.tuneStatusTypes, frontendConf.expectTuneStatuses);
+    ASSERT_TRUE(stopTuneFrontend(false /*testWithDemux*/));
     ASSERT_TRUE(closeFrontend());
 }
 
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.h b/tv/tuner/1.0/vts/functional/FrontendTests.h
index 1a9bec9..4974ff3 100644
--- a/tv/tuner/1.0/vts/functional/FrontendTests.h
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.h
@@ -31,6 +31,7 @@
 #include <utils/Mutex.h>
 #include <map>
 
+#include "DvrTests.h"
 #include "VtsHalTvTunerV1_0TestConfigurations.h"
 
 #define WAIT_TIMEOUT 3000000000
@@ -100,7 +101,11 @@
   public:
     sp<ITuner> mService;
 
-    void setService(sp<ITuner> tuner) { mService = tuner; }
+    void setService(sp<ITuner> tuner) {
+        mService = tuner;
+        mDvrTests.setService(tuner);
+        getDefaultSoftwareFrontendPlaybackConfig(mDvrConfig);
+    }
 
     AssertionResult getFrontendIds();
     AssertionResult getFrontendInfo(uint32_t frontendId);
@@ -108,17 +113,45 @@
     AssertionResult setFrontendCallback();
     AssertionResult scanFrontend(FrontendConfig config, FrontendScanType type);
     AssertionResult stopScanFrontend();
-    AssertionResult tuneFrontend(FrontendConfig config);
-    AssertionResult stopTuneFrontend();
+    AssertionResult tuneFrontend(FrontendConfig config, bool testWithDemux);
+    AssertionResult setLnb(uint32_t lnbId);
+    void verifyFrontendStatus(vector<FrontendStatusType> statusTypes,
+                              vector<FrontendStatus> expectStatuses);
+    AssertionResult stopTuneFrontend(bool testWithDemux);
     AssertionResult closeFrontend();
 
     void getFrontendIdByType(FrontendType feType, uint32_t& feId);
     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 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::TS,
+                .packetSize = 188,
+        };
+        dvrConfig.type = DvrType::PLAYBACK;
+        dvrConfig.playbackInputFile = "/data/local/tmp/segment000000.ts";
+        dvrConfig.bufferSize = FMQ_SIZE_4M;
+        dvrConfig.settings.playback(playbackSettings);
+    }
+
     sp<IFrontend> mFrontend;
     FrontendInfo mFrontendInfo;
     sp<FrontendCallback> mFrontendCallback;
     hidl_vec<FrontendId> mFeIds;
+
+    DvrTests mDvrTests;
+    bool mIsSoftwareFe = false;
+    DvrConfig mDvrConfig;
 };
diff --git a/tv/tuner/1.0/vts/functional/LnbTests.cpp b/tv/tuner/1.0/vts/functional/LnbTests.cpp
new file mode 100644
index 0000000..9080f59
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/LnbTests.cpp
@@ -0,0 +1,116 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "LnbTests.h"
+
+Return<void> LnbCallback::onEvent(LnbEventType lnbEventType) {
+    android::Mutex::Autolock autoLock(mMsgLock);
+    ALOGD("[vts] lnb event received. Type: %d", lnbEventType);
+    mEventReceived = true;
+    mMsgCondition.signal();
+    return Void();
+}
+
+Return<void> LnbCallback::onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) {
+    string msg(diseqcMessage.begin(), diseqcMessage.end());
+    ALOGD("[vts] onDiseqcMessage %s", msg.c_str());
+    return Void();
+}
+
+AssertionResult LnbTests::getLnbIds(vector<uint32_t>& ids) {
+    Result status;
+    mService->getLnbIds([&](Result result, const hidl_vec<uint32_t>& lnbIds) {
+        status = result;
+        ids = lnbIds;
+    });
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::openLnbById(uint32_t lnbId) {
+    Result status;
+    mService->openLnbById(lnbId, [&](Result result, const sp<ILnb>& lnb) {
+        mLnb = lnb;
+        status = result;
+    });
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::openLnbByName(string lnbName) {
+    Result status;
+    mService->openLnbByName(lnbName, [&](Result result, uint32_t /*lnbId*/, const sp<ILnb>& lnb) {
+        mLnb = lnb;
+        status = result;
+    });
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::setLnbCallback() {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    mLnbCallback = new LnbCallback();
+    auto callbackStatus = mLnb->setCallback(mLnbCallback);
+    return AssertionResult(callbackStatus.isOk());
+}
+
+AssertionResult LnbTests::setVoltage(LnbVoltage voltage) {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    Result status = mLnb->setVoltage(voltage);
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::setTone(LnbTone tone) {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    Result status = mLnb->setTone(tone);
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::setSatellitePosition(LnbPosition position) {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    Result status = mLnb->setSatellitePosition(position);
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::sendDiseqcMessage(vector<uint8_t> diseqcMsg) {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    Result status = mLnb->sendDiseqcMessage(diseqcMsg);
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult LnbTests::closeLnb() {
+    if (!mLnb) {
+        ALOGW("[vts] Open Lnb first");
+        return failure();
+    }
+    Result status = mLnb->close();
+    mLnb = nullptr;
+    mLnbCallback = nullptr;
+    return AssertionResult(status == Result::SUCCESS);
+}
diff --git a/tv/tuner/1.0/vts/functional/LnbTests.h b/tv/tuner/1.0/vts/functional/LnbTests.h
new file mode 100644
index 0000000..2fdbe2c
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/LnbTests.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/hardware/tv/tuner/1.0/ILnb.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/ServiceManagement.h>
+#include <hidl/Status.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <map>
+
+using android::Condition;
+using android::Mutex;
+using android::sp;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::ILnb;
+using android::hardware::tv::tuner::V1_0::ILnbCallback;
+using android::hardware::tv::tuner::V1_0::ITuner;
+using android::hardware::tv::tuner::V1_0::LnbEventType;
+using android::hardware::tv::tuner::V1_0::LnbPosition;
+using android::hardware::tv::tuner::V1_0::LnbTone;
+using android::hardware::tv::tuner::V1_0::LnbVoltage;
+using android::hardware::tv::tuner::V1_0::Result;
+
+using ::testing::AssertionResult;
+
+using namespace std;
+
+class LnbCallback : public ILnbCallback {
+  public:
+    virtual Return<void> onEvent(LnbEventType lnbEventType) override;
+    virtual Return<void> onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) override;
+
+  private:
+    bool mEventReceived = false;
+    android::Mutex mMsgLock;
+    android::Condition mMsgCondition;
+};
+
+class LnbTests {
+  public:
+    void setService(sp<ITuner> tuner) { mService = tuner; }
+
+    AssertionResult getLnbIds(vector<uint32_t>& ids);
+    AssertionResult openLnbById(uint32_t lnbId);
+    AssertionResult openLnbByName(string lnbName);
+    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(); }
+
+    sp<ITuner> mService;
+    sp<ILnb> mLnb;
+    sp<LnbCallback> mLnbCallback;
+    hidl_vec<uint32_t> mLnbIds;
+};
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index c44f77d..4521824 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -18,53 +18,17 @@
 
 namespace {
 
-AssertionResult TunerHidlTest::createDescrambler(uint32_t demuxId) {
-    Result status;
-    mService->openDescrambler([&](Result result, const sp<IDescrambler>& descrambler) {
-        mDescrambler = descrambler;
-        status = result;
-    });
-    if (status != Result::SUCCESS) {
-        return failure();
-    }
-
-    status = mDescrambler->setDemuxSource(demuxId);
-    if (status != Result::SUCCESS) {
-        return failure();
-    }
-
-    // Test if demux source can be set more than once.
-    status = mDescrambler->setDemuxSource(demuxId);
-    return AssertionResult(status == Result::INVALID_STATE);
-}
-
-AssertionResult TunerHidlTest::closeDescrambler() {
-    Result status;
-    EXPECT_TRUE(mDescrambler);
-
-    status = mDescrambler->close();
-    mDescrambler = nullptr;
-    return AssertionResult(status == Result::SUCCESS);
-}
-
 AssertionResult TunerBroadcastHidlTest::filterDataOutputTest(vector<string> /*goldenOutputFiles*/) {
-    // Data Verify Module
-    std::map<uint32_t, sp<FilterCallback>>::iterator it;
-    std::map<uint32_t, sp<FilterCallback>> filterCallbacks = mFilterTests.getFilterCallbacks();
-    for (it = filterCallbacks.begin(); it != filterCallbacks.end(); it++) {
-        it->second->testFilterDataOutput();
-    }
-    return success();
+    return filterDataOutputTestBase(mFilterTests);
 }
 
 AssertionResult TunerPlaybackHidlTest::filterDataOutputTest(vector<string> /*goldenOutputFiles*/) {
-    // Data Verify Module
-    std::map<uint32_t, sp<FilterCallback>>::iterator it;
-    std::map<uint32_t, sp<FilterCallback>> filterCallbacks = mFilterTests.getFilterCallbacks();
-    for (it = filterCallbacks.begin(); it != filterCallbacks.end(); it++) {
-        it->second->testFilterDataOutput();
-    }
-    return success();
+    return filterDataOutputTestBase(mFilterTests);
+}
+
+AssertionResult TunerDescramblerHidlTest::filterDataOutputTest(
+        vector<string> /*goldenOutputFiles*/) {
+    return filterDataOutputTestBase(mFilterTests);
 }
 
 void TunerFilterHidlTest::configSingleFilterInDemuxTest(FilterConfig filterConf,
@@ -92,6 +56,23 @@
     ASSERT_TRUE(mFrontendTests.closeFrontend());
 }
 
+void TunerFilterHidlTest::testTimeFilter(TimeFilterConfig filterConf) {
+    if (!filterConf.supportTimeFilter) {
+        return;
+    }
+    uint32_t demuxId;
+    sp<IDemux> demux;
+
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    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 TunerBroadcastHidlTest::broadcastSingleFilterTest(FilterConfig filterConf,
                                                        FrontendConfig frontendConf) {
     uint32_t feId;
@@ -108,8 +89,12 @@
     }
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+    if (mLnbId) {
+        ASSERT_TRUE(mFrontendTests.setLnb(*mLnbId));
+    }
     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(filterId));
@@ -117,15 +102,35 @@
     ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
     // tune test
-    ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf));
+    ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
     ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
-    ASSERT_TRUE(mFrontendTests.stopTuneFrontend());
+    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 TunerBroadcastHidlTest::broadcastSingleFilterTestWithLnb(FilterConfig filterConf,
+                                                              FrontendConfig frontendConf,
+                                                              LnbConfig lnbConf) {
+    vector<uint32_t> ids;
+    ASSERT_TRUE(mLnbTests.getLnbIds(ids));
+    if (!lnbConf.usingLnb) {
+        return;
+    }
+    ASSERT_TRUE(ids.size() > 0);
+    ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
+    *mLnbId = ids[0];
+    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 TunerPlaybackHidlTest::playbackSingleFilterTest(FilterConfig filterConf, DvrConfig dvrConf) {
     uint32_t demuxId;
     sp<IDemux> demux;
@@ -135,21 +140,21 @@
     mFilterTests.setDemux(demux);
     mDvrTests.setDemux(demux);
     ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
-    ASSERT_TRUE(mDvrTests.configDvr(dvrConf.settings));
-    ASSERT_TRUE(mDvrTests.getDvrMQDescriptor());
+    ASSERT_TRUE(mDvrTests.configDvrPlayback(dvrConf.settings));
+    ASSERT_TRUE(mDvrTests.getDvrPlaybackMQDescriptor());
     ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
     ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
     ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
     mDvrTests.startPlaybackInputThread(dvrConf.playbackInputFile, dvrConf.settings.playback());
-    ASSERT_TRUE(mDvrTests.startDvr());
+    ASSERT_TRUE(mDvrTests.startDvrPlayback());
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
     ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
     mDvrTests.stopPlaybackThread();
     ASSERT_TRUE(mFilterTests.stopFilter(filterId));
-    ASSERT_TRUE(mDvrTests.stopDvr());
+    ASSERT_TRUE(mDvrTests.stopDvrPlayback());
     ASSERT_TRUE(mFilterTests.closeFilter(filterId));
-    mDvrTests.closeDvr();
+    mDvrTests.closeDvrPlayback();
     ASSERT_TRUE(mDemuxTests.closeDemux());
 }
 
@@ -165,13 +170,17 @@
     ASSERT_TRUE(feId != INVALID_ID);
     ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+    if (mLnbId) {
+        ASSERT_TRUE(mFrontendTests.setLnb(*mLnbId));
+    }
     ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
     ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
     mFilterTests.setDemux(demux);
     mDvrTests.setDemux(demux);
+    mFrontendTests.setDvrTests(mDvrTests);
     ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
-    ASSERT_TRUE(mDvrTests.configDvr(dvrConf.settings));
-    ASSERT_TRUE(mDvrTests.getDvrMQDescriptor());
+    ASSERT_TRUE(mDvrTests.configDvrRecord(dvrConf.settings));
+    ASSERT_TRUE(mDvrTests.getDvrRecordMQDescriptor());
     ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
     ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
@@ -180,21 +189,41 @@
     ASSERT_TRUE(filter != nullptr);
     mDvrTests.startRecordOutputThread(dvrConf.settings.record());
     ASSERT_TRUE(mDvrTests.attachFilterToDvr(filter));
-    ASSERT_TRUE(mDvrTests.startDvr());
+    ASSERT_TRUE(mDvrTests.startDvrRecord());
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
-    ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf));
+    ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
     mDvrTests.testRecordOutput();
     mDvrTests.stopRecordThread();
-    ASSERT_TRUE(mFrontendTests.stopTuneFrontend());
+    ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
     ASSERT_TRUE(mFilterTests.stopFilter(filterId));
-    ASSERT_TRUE(mDvrTests.stopDvr());
+    ASSERT_TRUE(mDvrTests.stopDvrRecord());
     ASSERT_TRUE(mDvrTests.detachFilterToDvr(filter));
     ASSERT_TRUE(mFilterTests.closeFilter(filterId));
-    mDvrTests.closeDvr();
+    mDvrTests.closeDvrRecord();
     ASSERT_TRUE(mDemuxTests.closeDemux());
     ASSERT_TRUE(mFrontendTests.closeFrontend());
 }
 
+void TunerRecordHidlTest::recordSingleFilterTestWithLnb(FilterConfig filterConf,
+                                                        FrontendConfig frontendConf,
+                                                        DvrConfig dvrConf, LnbConfig lnbConf) {
+    vector<uint32_t> ids;
+    ASSERT_TRUE(mLnbTests.getLnbIds(ids));
+    if (!lnbConf.usingLnb) {
+        return;
+    }
+    ASSERT_TRUE(ids.size() > 0);
+    ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
+    *mLnbId = ids[0];
+    ASSERT_TRUE(mLnbTests.setLnbCallback());
+    ASSERT_TRUE(mLnbTests.setVoltage(lnbConf.voltage));
+    ASSERT_TRUE(mLnbTests.setTone(lnbConf.tone));
+    ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbConf.position));
+    recordSingleFilterTest(filterConf, frontendConf, dvrConf);
+    ASSERT_TRUE(mLnbTests.closeLnb());
+    mLnbId = nullptr;
+}
+
 void TunerRecordHidlTest::attachSingleFilterToRecordDvrTest(FilterConfig filterConf,
                                                             FrontendConfig frontendConf,
                                                             DvrConfig dvrConf) {
@@ -213,8 +242,8 @@
     mFilterTests.setDemux(demux);
     mDvrTests.setDemux(demux);
     ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
-    ASSERT_TRUE(mDvrTests.configDvr(dvrConf.settings));
-    ASSERT_TRUE(mDvrTests.getDvrMQDescriptor());
+    ASSERT_TRUE(mDvrTests.configDvrRecord(dvrConf.settings));
+    ASSERT_TRUE(mDvrTests.getDvrRecordMQDescriptor());
     ASSERT_TRUE(mFilterTests.openFilterInDemux(filterConf.type, filterConf.bufferSize));
     ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
     ASSERT_TRUE(mFilterTests.configFilter(filterConf.settings, filterId));
@@ -222,13 +251,77 @@
     filter = mFilterTests.getFilterById(filterId);
     ASSERT_TRUE(filter != nullptr);
     ASSERT_TRUE(mDvrTests.attachFilterToDvr(filter));
-    ASSERT_TRUE(mDvrTests.startDvr());
+    ASSERT_TRUE(mDvrTests.startDvrRecord());
     ASSERT_TRUE(mFilterTests.startFilter(filterId));
     ASSERT_TRUE(mFilterTests.stopFilter(filterId));
-    ASSERT_TRUE(mDvrTests.stopDvr());
+    ASSERT_TRUE(mDvrTests.stopDvrRecord());
     ASSERT_TRUE(mDvrTests.detachFilterToDvr(filter));
     ASSERT_TRUE(mFilterTests.closeFilter(filterId));
-    mDvrTests.closeDvr();
+    mDvrTests.closeDvrRecord();
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+    ASSERT_TRUE(mFrontendTests.closeFrontend());
+}
+
+void TunerDescramblerHidlTest::scrambledBroadcastTest(set<struct FilterConfig> mediaFilterConfs,
+                                                      FrontendConfig frontendConf,
+                                                      DescramblerConfig descConfig) {
+    uint32_t feId;
+    uint32_t demuxId;
+    sp<IDemux> demux;
+    set<uint32_t> filterIds;
+    uint32_t filterId;
+    set<struct FilterConfig>::iterator config;
+    set<uint32_t>::iterator id;
+
+    mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+    if (feId == INVALID_ID) {
+        // TODO broadcast test on Cuttlefish needs licensed ts input,
+        // these tests are runnable on vendor device with real frontend module
+        // or with manual ts installing and use DVBT frontend.
+        return;
+    }
+    ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+    ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+    mFilterTests.setDemux(demux);
+    mFrontendTests.setDemux(demux);
+    for (config = mediaFilterConfs.begin(); config != mediaFilterConfs.end(); config++) {
+        ASSERT_TRUE(mFilterTests.openFilterInDemux((*config).type, (*config).bufferSize));
+        ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
+        ASSERT_TRUE(mFilterTests.configFilter((*config).settings, filterId));
+        filterIds.insert(filterId);
+    }
+    ASSERT_TRUE(mDescramblerTests.openDescrambler(demuxId));
+    TunerKeyToken token;
+    ASSERT_TRUE(mDescramblerTests.getKeyToken(descConfig.casSystemId, descConfig.provisionStr,
+                                              descConfig.hidlPvtData, token));
+    ASSERT_TRUE(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));
+    }
+    // tune test
+    ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
+    ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
+    ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
+    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));
+    }
     ASSERT_TRUE(mDemuxTests.closeDemux());
     ASSERT_TRUE(mFrontendTests.closeFrontend());
 }
@@ -248,6 +341,34 @@
     mFrontendTests.scanTest(frontendScanArray[SCAN_DVBT], FrontendScanType::SCAN_BLIND);
 }
 
+TEST_P(TunerLnbHidlTest, OpenLnbByName) {
+    description("Open and configure an Lnb with name then send a diseqc msg to it.");
+    ASSERT_TRUE(mLnbTests.openLnbByName(lnbArray[LNB_EXTERNAL].name));
+    ASSERT_TRUE(mLnbTests.setLnbCallback());
+    ASSERT_TRUE(mLnbTests.setVoltage(lnbArray[LNB_EXTERNAL].voltage));
+    ASSERT_TRUE(mLnbTests.setTone(lnbArray[LNB_EXTERNAL].tone));
+    ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbArray[LNB_EXTERNAL].position));
+    ASSERT_TRUE(mLnbTests.sendDiseqcMessage(diseqcMsgArray[DISEQC_POWER_ON]));
+    ASSERT_TRUE(mLnbTests.closeLnb());
+}
+
+TEST_P(TunerLnbHidlTest, SendDiseqcMessageToLnb) {
+    description("Open and configure an Lnb with specific settings then send a diseqc msg to it.");
+    vector<uint32_t> ids;
+    ASSERT_TRUE(mLnbTests.getLnbIds(ids));
+    if (!lnbArray[LNB0].usingLnb) {
+        return;
+    }
+    ASSERT_TRUE(ids.size() > 0);
+    ASSERT_TRUE(mLnbTests.openLnbById(ids[0]));
+    ASSERT_TRUE(mLnbTests.setLnbCallback());
+    ASSERT_TRUE(mLnbTests.setVoltage(lnbArray[LNB0].voltage));
+    ASSERT_TRUE(mLnbTests.setTone(lnbArray[LNB0].tone));
+    ASSERT_TRUE(mLnbTests.setSatellitePosition(lnbArray[LNB0].position));
+    ASSERT_TRUE(mLnbTests.sendDiseqcMessage(diseqcMsgArray[DISEQC_POWER_ON]));
+    ASSERT_TRUE(mLnbTests.closeLnb());
+}
+
 TEST_P(TunerDemuxHidlTest, openDemux) {
     description("Open and close a Demux.");
     uint32_t feId;
@@ -263,32 +384,164 @@
     ASSERT_TRUE(mFrontendTests.closeFrontend());
 }
 
+TEST_P(TunerDemuxHidlTest, getAvSyncTime) {
+    description("Get the A/V sync time from a PCR filter.");
+    uint32_t feId;
+    uint32_t demuxId;
+    sp<IDemux> demux;
+    uint32_t mediaFilterId;
+    uint32_t pcrFilterId;
+    uint32_t avSyncHwId;
+    sp<IFilter> mediaFilter;
+
+    mFrontendTests.getFrontendIdByType(frontendArray[DVBT].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(filterArray[TS_VIDEO1].type,
+                                               filterArray[TS_VIDEO1].bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(mediaFilterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_VIDEO1].settings, mediaFilterId));
+    mediaFilter = mFilterTests.getFilterById(mediaFilterId);
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterArray[TS_PCR0].type,
+                                               filterArray[TS_PCR0].bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(pcrFilterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_PCR0].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(TunerFilterHidlTest, StartFilterInDemux) {
     description("Open and start a filter in Demux.");
     // TODO use paramterized tests
     configSingleFilterInDemuxTest(filterArray[TS_VIDEO0], frontendArray[DVBT]);
 }
 
+TEST_P(TunerFilterHidlTest, SetFilterLinkage) {
+    description("Pick up all the possible linkages from the demux caps and set them up.");
+    DemuxCapabilities caps;
+    uint32_t demuxId;
+    sp<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)) {
+                uint32_t sourceFilterId;
+                uint32_t sinkFilterId;
+                ASSERT_TRUE(mFilterTests.openFilterInDemux(filterLinkageTypes[SOURCE][i],
+                                                           FMQ_SIZE_16M));
+                ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(sourceFilterId));
+                ASSERT_TRUE(
+                        mFilterTests.openFilterInDemux(filterLinkageTypes[SINK][j], FMQ_SIZE_16M));
+                ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(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(TunerFilterHidlTest, testTimeFilter) {
+    description("Open a timer filter in Demux and set time stamp.");
+    // TODO use paramterized tests
+    testTimeFilter(timeFilterArray[TIMER0]);
+}
+
 TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowVideoFilterTest) {
     description("Test Video Filter functionality in Broadcast use case.");
-    broadcastSingleFilterTest(filterArray[TS_VIDEO1], frontendArray[DVBS]);
+    broadcastSingleFilterTest(filterArray[TS_VIDEO1], frontendArray[DVBT]);
 }
 
 TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowAudioFilterTest) {
     description("Test Audio Filter functionality in Broadcast use case.");
-    broadcastSingleFilterTest(filterArray[TS_AUDIO0], frontendArray[DVBS]);
+    broadcastSingleFilterTest(filterArray[TS_AUDIO0], frontendArray[DVBT]);
 }
 
 TEST_P(TunerBroadcastHidlTest, BroadcastDataFlowSectionFilterTest) {
     description("Test Section Filter functionality in Broadcast use case.");
-    broadcastSingleFilterTest(filterArray[TS_SECTION0], frontendArray[DVBS]);
+    broadcastSingleFilterTest(filterArray[TS_SECTION0], frontendArray[DVBT]);
 }
 
 TEST_P(TunerBroadcastHidlTest, IonBufferTest) {
     description("Test the av filter data bufferring.");
+    broadcastSingleFilterTest(filterArray[TS_VIDEO0], frontendArray[DVBT]);
+}
+
+TEST_P(TunerBroadcastHidlTest, LnbBroadcastDataFlowVideoFilterTest) {
+    description("Test Video Filter functionality in Broadcast with Lnb use case.");
     broadcastSingleFilterTest(filterArray[TS_VIDEO0], frontendArray[DVBS]);
 }
 
+TEST_P(TunerBroadcastHidlTest, BroadcastEsDataFlowMediaFiltersTest) {
+    description("Test Meida Filters functionality in Broadcast use case with ES input.");
+    uint32_t feId;
+    uint32_t demuxId;
+    sp<IDemux> demux;
+    uint32_t filterId;
+
+    mFrontendTests.getFrontendIdByType(frontendArray[DVBT].type, feId);
+    if (feId == INVALID_ID) {
+        // TODO broadcast test on Cuttlefish needs licensed ts input,
+        // these tests are runnable on vendor device with real frontend module
+        // or with manual ts installing and use DVBT frontend.
+        return;
+    }
+    ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+    ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+    ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+    ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+    mFrontendTests.setDemux(demux);
+    mFilterTests.setDemux(demux);
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterArray[TS_AUDIO1].type,
+                                               filterArray[TS_AUDIO1].bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_AUDIO1].settings, filterId));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
+    ASSERT_TRUE(mFilterTests.startFilter(filterId));
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterArray[TS_VIDEO1].type,
+                                               filterArray[TS_VIDEO1].bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId(filterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_VIDEO1].settings, filterId));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
+    ASSERT_TRUE(mFilterTests.startFilter(filterId));
+    // tune test
+    PlaybackSettings playbackSettings{
+            .statusMask = 0xf,
+            .lowThreshold = 0x1000,
+            .highThreshold = 0x07fff,
+            .dataFormat = DataFormat::ES,
+            .packetSize = 188,
+    };
+    DvrConfig dvrConfig{
+            .type = DvrType::PLAYBACK,
+            .playbackInputFile = "/data/local/tmp/test.es",
+            .bufferSize = FMQ_SIZE_4M,
+    };
+    dvrConfig.settings.playback(playbackSettings);
+    mFrontendTests.setSoftwareFrontendDvrConfig(dvrConfig);
+    ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendArray[DVBT], true /*testWithDemux*/));
+    ASSERT_TRUE(filterDataOutputTest(goldenOutputFiles));
+    ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
+    ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+    ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+    ASSERT_TRUE(mFrontendTests.closeFrontend());
+}
+
 TEST_P(TunerPlaybackHidlTest, PlaybackDataFlowWithTsSectionFilterTest) {
     description("Feed ts data from playback and configure Ts section filter to get output");
     playbackSingleFilterTest(filterArray[TS_SECTION0], dvrArray[DVR_PLAYBACK0]);
@@ -306,7 +559,12 @@
     recordSingleFilterTest(filterArray[TS_RECORD0], frontendArray[DVBT], dvrArray[DVR_RECORD0]);
 }
 
-TEST_P(TunerHidlTest, CreateDescrambler) {
+TEST_P(TunerRecordHidlTest, LnbRecordDataFlowWithTsRecordFilterTest) {
+    description("Feed ts data from Fe with Lnb to recording and test with ts record filter");
+    recordSingleFilterTest(filterArray[TS_RECORD0], frontendArray[DVBS], dvrArray[DVR_RECORD0]);
+}
+
+TEST_P(TunerDescramblerHidlTest, CreateDescrambler) {
     description("Create Descrambler");
     uint32_t feId;
     uint32_t demuxId;
@@ -317,18 +575,31 @@
     ASSERT_TRUE(mFrontendTests.setFrontendCallback());
     ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
     ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
-    ASSERT_TRUE(createDescrambler(demuxId));
-    ASSERT_TRUE(closeDescrambler());
+    ASSERT_TRUE(mDescramblerTests.openDescrambler(demuxId));
+    ASSERT_TRUE(mDescramblerTests.closeDescrambler());
     ASSERT_TRUE(mDemuxTests.closeDemux());
     ASSERT_TRUE(mFrontendTests.closeFrontend());
 }
 
+TEST_P(TunerDescramblerHidlTest, ScrambledBroadcastDataFlowMediaFiltersTest) {
+    description("Test ts audio filter in scrambled broadcast use case");
+    set<FilterConfig> filterConfs;
+    filterConfs.insert(filterArray[TS_AUDIO0]);
+    filterConfs.insert(filterArray[TS_VIDEO1]);
+    scrambledBroadcastTest(filterConfs, frontendArray[DVBT], descramblerArray[DESC_0]);
+}
+
 INSTANTIATE_TEST_SUITE_P(
         PerInstance, TunerFrontendHidlTest,
         testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
         android::hardware::PrintInstanceNameToString);
 
 INSTANTIATE_TEST_SUITE_P(
+        PerInstance, TunerLnbHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
+        android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(
         PerInstance, TunerDemuxHidlTest,
         testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
         android::hardware::PrintInstanceNameToString);
@@ -354,7 +625,17 @@
         android::hardware::PrintInstanceNameToString);
 
 INSTANTIATE_TEST_SUITE_P(
-        PerInstance, TunerHidlTest,
+        PerInstance, TunerDescramblerHidlTest,
         testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
         android::hardware::PrintInstanceNameToString);
+
+// TODO remove from the allow list once the cf tv target is enabled for testing
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerFrontendHidlTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerLnbHidlTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerDemuxHidlTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerFilterHidlTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerBroadcastHidlTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerPlaybackHidlTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerRecordHidlTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerDescramblerHidlTest);
 }  // namespace
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
index 21a9855..6804f3c 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
@@ -14,19 +14,14 @@
  * limitations under the License.
  */
 
-#include <android/hardware/tv/tuner/1.0/IDescrambler.h>
-
 #include "DemuxTests.h"
-#include "DvrTests.h"
+#include "DescramblerTests.h"
 #include "FrontendTests.h"
+#include "LnbTests.h"
 
 using android::hardware::tv::tuner::V1_0::DataFormat;
 using android::hardware::tv::tuner::V1_0::IDescrambler;
 
-static AssertionResult failure() {
-    return ::testing::AssertionFailure();
-}
-
 static AssertionResult success() {
     return ::testing::AssertionSuccess();
 }
@@ -36,8 +31,21 @@
 void initConfiguration() {
     initFrontendConfig();
     initFrontendScanConfig();
+    initLnbConfig();
     initFilterConfig();
+    initTimeFilterConfig();
     initDvrConfig();
+    initDescramblerConfig();
+}
+
+AssertionResult filterDataOutputTestBase(FilterTests tests) {
+    // Data Verify Module
+    std::map<uint32_t, sp<FilterCallback>>::iterator it;
+    std::map<uint32_t, sp<FilterCallback>> filterCallbacks = tests.getFilterCallbacks();
+    for (it = filterCallbacks.begin(); it != filterCallbacks.end(); it++) {
+        it->second->testFilterDataOutput();
+    }
+    return success();
 }
 
 class TunerFrontendHidlTest : public testing::TestWithParam<std::string> {
@@ -59,6 +67,25 @@
     FrontendTests mFrontendTests;
 };
 
+class TunerLnbHidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        mService = ITuner::getService(GetParam());
+        ASSERT_NE(mService, nullptr);
+        initConfiguration();
+
+        mLnbTests.setService(mService);
+    }
+
+  protected:
+    static void description(const std::string& description) {
+        RecordProperty("description", description);
+    }
+
+    sp<ITuner> mService;
+    LnbTests mLnbTests;
+};
+
 class TunerDemuxHidlTest : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
@@ -68,6 +95,7 @@
 
         mFrontendTests.setService(mService);
         mDemuxTests.setService(mService);
+        mFilterTests.setService(mService);
     }
 
   protected:
@@ -78,6 +106,7 @@
     sp<ITuner> mService;
     FrontendTests mFrontendTests;
     DemuxTests mDemuxTests;
+    FilterTests mFilterTests;
 };
 
 class TunerFilterHidlTest : public testing::TestWithParam<std::string> {
@@ -98,6 +127,7 @@
     }
 
     void configSingleFilterInDemuxTest(FilterConfig filterConf, FrontendConfig frontendConf);
+    void testTimeFilter(TimeFilterConfig filterConf);
 
     sp<ITuner> mService;
     FrontendTests mFrontendTests;
@@ -115,6 +145,8 @@
         mFrontendTests.setService(mService);
         mDemuxTests.setService(mService);
         mFilterTests.setService(mService);
+        mLnbTests.setService(mService);
+        mDvrTests.setService(mService);
     }
 
   protected:
@@ -126,10 +158,17 @@
     FrontendTests mFrontendTests;
     DemuxTests mDemuxTests;
     FilterTests mFilterTests;
+    LnbTests mLnbTests;
+    DvrTests mDvrTests;
 
     AssertionResult filterDataOutputTest(vector<string> goldenOutputFiles);
 
     void broadcastSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf);
+    void broadcastSingleFilterTestWithLnb(FilterConfig filterConf, FrontendConfig frontendConf,
+                                          LnbConfig lnbConf);
+
+  private:
+    uint32_t* mLnbId = nullptr;
 };
 
 class TunerPlaybackHidlTest : public testing::TestWithParam<std::string> {
@@ -172,6 +211,7 @@
         mDemuxTests.setService(mService);
         mFilterTests.setService(mService);
         mDvrTests.setService(mService);
+        mLnbTests.setService(mService);
     }
 
   protected:
@@ -183,23 +223,34 @@
                                            DvrConfig dvrConf);
     void recordSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf,
                                 DvrConfig dvrConf);
+    void recordSingleFilterTestWithLnb(FilterConfig filterConf, FrontendConfig frontendConf,
+                                       DvrConfig dvrConf, LnbConfig lnbConf);
 
     sp<ITuner> mService;
     FrontendTests mFrontendTests;
     DemuxTests mDemuxTests;
     FilterTests mFilterTests;
     DvrTests mDvrTests;
+    LnbTests mLnbTests;
+
+  private:
+    uint32_t* mLnbId = nullptr;
 };
 
-class TunerHidlTest : public testing::TestWithParam<std::string> {
+class TunerDescramblerHidlTest : public testing::TestWithParam<std::string> {
   public:
     virtual void SetUp() override {
         mService = ITuner::getService(GetParam());
+        mCasService = IMediaCasService::getService();
         ASSERT_NE(mService, nullptr);
+        ASSERT_NE(mCasService, nullptr);
         initConfiguration();
 
         mFrontendTests.setService(mService);
         mDemuxTests.setService(mService);
+        mDvrTests.setService(mService);
+        mDescramblerTests.setService(mService);
+        mDescramblerTests.setCasService(mCasService);
     }
 
   protected:
@@ -207,13 +258,16 @@
         RecordProperty("description", description);
     }
 
+    void scrambledBroadcastTest(set<struct FilterConfig> mediaFilterConfs,
+                                FrontendConfig frontendConf, DescramblerConfig descConfig);
+    AssertionResult filterDataOutputTest(vector<string> /*goldenOutputFiles*/);
+
     sp<ITuner> mService;
+    sp<IMediaCasService> mCasService;
     FrontendTests mFrontendTests;
     DemuxTests mDemuxTests;
-
-    sp<IDescrambler> mDescrambler;
-
-    AssertionResult createDescrambler(uint32_t demuxId);
-    AssertionResult closeDescrambler();
+    FilterTests mFilterTests;
+    DescramblerTests mDescramblerTests;
+    DvrTests mDvrTests;
 };
 }  // namespace
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
index b84013b..27c6593 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
@@ -22,11 +22,15 @@
 #include <hidlmemory/FrameworkUtils.h>
 
 using android::hardware::tv::tuner::V1_0::DataFormat;
+using android::hardware::tv::tuner::V1_0::DemuxAlpFilterType;
 using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
 using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
 using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
 using android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxIpFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
 using android::hardware::tv::tuner::V1_0::DemuxRecordScIndexType;
+using android::hardware::tv::tuner::V1_0::DemuxTlvFilterType;
 using android::hardware::tv::tuner::V1_0::DemuxTpid;
 using android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
 using android::hardware::tv::tuner::V1_0::DvrSettings;
@@ -40,7 +44,12 @@
 using android::hardware::tv::tuner::V1_0::FrontendDvbtStandard;
 using android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode;
 using android::hardware::tv::tuner::V1_0::FrontendSettings;
+using android::hardware::tv::tuner::V1_0::FrontendStatus;
+using android::hardware::tv::tuner::V1_0::FrontendStatusType;
 using android::hardware::tv::tuner::V1_0::FrontendType;
+using android::hardware::tv::tuner::V1_0::LnbPosition;
+using android::hardware::tv::tuner::V1_0::LnbTone;
+using android::hardware::tv::tuner::V1_0::LnbVoltage;
 using android::hardware::tv::tuner::V1_0::PlaybackSettings;
 using android::hardware::tv::tuner::V1_0::RecordSettings;
 
@@ -50,10 +59,25 @@
 const uint32_t FMQ_SIZE_4M = 0x400000;
 const uint32_t FMQ_SIZE_16M = 0x1000000;
 
+#define CLEAR_KEY_SYSTEM_ID 0xF6D8
+#define FILTER_MAIN_TYPE_BIT_COUNT 32
+#define PROVISION_STR                                      \
+    "{                                                   " \
+    "  \"id\": 21140844,                                 " \
+    "  \"name\": \"Test Title\",                         " \
+    "  \"lowercase_organization_name\": \"Android\",     " \
+    "  \"asset_key\": {                                  " \
+    "  \"encryption_key\": \"nezAr3CHFrmBR9R8Tedotw==\"  " \
+    "  },                                                " \
+    "  \"cas_type\": 1,                                  " \
+    "  \"track_types\": [ ]                              " \
+    "}                                                   "
+
 typedef enum {
     TS_VIDEO0,
     TS_VIDEO1,
     TS_AUDIO0,
+    TS_AUDIO1,
     TS_PES0,
     TS_PCR0,
     TS_SECTION0,
@@ -63,12 +87,34 @@
 } Filter;
 
 typedef enum {
+    TIMER0,
+    TIMER_MAX,
+} TimeFilter;
+
+typedef enum {
+    SOURCE,
+    SINK,
+    LINKAGE_DIR,
+} Linkage;
+
+typedef enum {
     DVBT,
     DVBS,
     FRONTEND_MAX,
 } Frontend;
 
 typedef enum {
+    LNB0,
+    LNB_EXTERNAL,
+    LNB_MAX,
+} Lnb;
+
+typedef enum {
+    DISEQC_POWER_ON,
+    DISEQC_MAX,
+} Diseqc;
+
+typedef enum {
     SCAN_DVBT,
     SCAN_MAX,
 } FrontendScan;
@@ -79,15 +125,38 @@
     DVR_MAX,
 } Dvr;
 
+typedef enum {
+    DESC_0,
+    DESC_MAX,
+} Descrambler;
+
 struct FilterConfig {
     uint32_t bufferSize;
     DemuxFilterType type;
     DemuxFilterSettings settings;
+
+    bool operator<(const FilterConfig& /*c*/) const { return false; }
+};
+
+struct TimeFilterConfig {
+    bool supportTimeFilter;
+    uint64_t timeStamp;
 };
 
 struct FrontendConfig {
+    bool isSoftwareFe;
     FrontendType type;
     FrontendSettings settings;
+    vector<FrontendStatusType> tuneStatusTypes;
+    vector<FrontendStatus> expectTuneStatuses;
+};
+
+struct LnbConfig {
+    bool usingLnb;
+    string name;
+    LnbVoltage voltage;
+    LnbTone tone;
+    LnbPosition position;
 };
 
 struct ChannelConfig {
@@ -105,11 +174,22 @@
     string playbackInputFile;
 };
 
+struct DescramblerConfig {
+    uint32_t casSystemId;
+    string provisionStr;
+    vector<uint8_t> hidlPvtData;
+};
+
 static FrontendConfig frontendArray[FILTER_MAX];
 static FrontendConfig frontendScanArray[SCAN_MAX];
+static LnbConfig lnbArray[LNB_MAX];
+static vector<uint8_t> diseqcMsgArray[DISEQC_MAX];
 static ChannelConfig channelArray[FRONTEND_MAX];
 static FilterConfig filterArray[FILTER_MAX];
+static TimeFilterConfig timeFilterArray[TIMER_MAX];
+static DemuxFilterType filterLinkageTypes[LINKAGE_DIR][FILTER_MAIN_TYPE_BIT_COUNT];
 static DvrConfig dvrArray[DVR_MAX];
+static DescramblerConfig descramblerArray[DESC_MAX];
 static vector<string> goldenOutputFiles;
 
 /** Configuration array for the frontend tune test */
@@ -127,7 +207,17 @@
             .standard = FrontendDvbtStandard::T,
     };
     frontendArray[DVBT].type = FrontendType::DVBT, frontendArray[DVBT].settings.dvbt(dvbtSettings);
+    vector<FrontendStatusType> types;
+    types.push_back(FrontendStatusType::DEMOD_LOCK);
+    FrontendStatus status;
+    status.isDemodLocked(true);
+    vector<FrontendStatus> statuses;
+    statuses.push_back(status);
+    frontendArray[DVBT].tuneStatusTypes = types;
+    frontendArray[DVBT].expectTuneStatuses = statuses;
+    frontendArray[DVBT].isSoftwareFe = true;
     frontendArray[DVBS].type = FrontendType::DVBS;
+    frontendArray[DVBS].isSoftwareFe = true;
 };
 
 /** Configuration array for the frontend scan test */
@@ -147,6 +237,24 @@
     });
 };
 
+/** Configuration array for the Lnb test */
+inline void initLnbConfig() {
+    lnbArray[LNB0].usingLnb = true;
+    lnbArray[LNB0].voltage = LnbVoltage::VOLTAGE_12V;
+    lnbArray[LNB0].tone = LnbTone::NONE;
+    lnbArray[LNB0].position = LnbPosition::UNDEFINED;
+    lnbArray[LNB_EXTERNAL].usingLnb = true;
+    lnbArray[LNB_EXTERNAL].name = "default_lnb_external";
+    lnbArray[LNB_EXTERNAL].voltage = LnbVoltage::VOLTAGE_5V;
+    lnbArray[LNB_EXTERNAL].tone = LnbTone::NONE;
+    lnbArray[LNB_EXTERNAL].position = LnbPosition::UNDEFINED;
+};
+
+/** Diseqc messages array for the Lnb test */
+inline void initDiseqcMsg() {
+    diseqcMsgArray[DISEQC_POWER_ON] = {0xE, 0x0, 0x0, 0x0, 0x0, 0x3};
+};
+
 /** Configuration array for the filter test */
 inline void initFilterConfig() {
     // TS VIDEO filter setting for default implementation testing
@@ -166,6 +274,11 @@
     filterArray[TS_AUDIO0].bufferSize = FMQ_SIZE_16M;
     filterArray[TS_AUDIO0].settings.ts().tpid = 256;
     filterArray[TS_AUDIO0].settings.ts().filterSettings.av({.isPassthrough = false});
+    filterArray[TS_AUDIO1].type.mainType = DemuxFilterMainType::TS;
+    filterArray[TS_AUDIO1].type.subType.tsFilterType(DemuxTsFilterType::AUDIO);
+    filterArray[TS_AUDIO1].bufferSize = FMQ_SIZE_16M;
+    filterArray[TS_AUDIO1].settings.ts().tpid = 257;
+    filterArray[TS_AUDIO1].settings.ts().filterSettings.av({.isPassthrough = false});
     // TS PES filter setting
     filterArray[TS_PES0].type.mainType = DemuxFilterMainType::TS;
     filterArray[TS_PES0].type.subType.tsFilterType(DemuxTsFilterType::PES);
@@ -202,8 +315,35 @@
     filterArray[TS_RECORD0].settings.ts().filterSettings.record({
             .scIndexType = DemuxRecordScIndexType::NONE,
     });
+
+    // TS Linkage filter setting
+    filterLinkageTypes[SOURCE][0].mainType = DemuxFilterMainType::TS;
+    filterLinkageTypes[SOURCE][0].subType.tsFilterType(DemuxTsFilterType::TS);
+    filterLinkageTypes[SINK][0] = filterLinkageTypes[SOURCE][0];
+    // MMTP Linkage filter setting
+    filterLinkageTypes[SOURCE][1].mainType = DemuxFilterMainType::MMTP;
+    filterLinkageTypes[SOURCE][1].subType.mmtpFilterType(DemuxMmtpFilterType::AUDIO);
+    filterLinkageTypes[SINK][1] = filterLinkageTypes[SOURCE][1];
+    // IP Linkage filter setting
+    filterLinkageTypes[SOURCE][2].mainType = DemuxFilterMainType::IP;
+    filterLinkageTypes[SOURCE][2].subType.ipFilterType(DemuxIpFilterType::IP);
+    filterLinkageTypes[SINK][2] = filterLinkageTypes[SOURCE][2];
+    // TLV Linkage filter setting
+    filterLinkageTypes[SOURCE][3].mainType = DemuxFilterMainType::TLV;
+    filterLinkageTypes[SOURCE][3].subType.tlvFilterType(DemuxTlvFilterType::TLV);
+    filterLinkageTypes[SINK][3] = filterLinkageTypes[SOURCE][3];
+    // ALP Linkage PTP filter setting
+    filterLinkageTypes[SOURCE][4].mainType = DemuxFilterMainType::ALP;
+    filterLinkageTypes[SOURCE][4].subType.alpFilterType(DemuxAlpFilterType::PTP);
+    filterLinkageTypes[SINK][4] = filterLinkageTypes[SOURCE][4];
 };
 
+/** Configuration array for the timer filter test */
+inline void initTimeFilterConfig() {
+    timeFilterArray[TIMER0].supportTimeFilter = true;
+    timeFilterArray[TIMER0].timeStamp = 1;
+}
+
 /** Configuration array for the dvr test */
 inline void initDvrConfig() {
     RecordSettings recordSettings{
@@ -224,7 +364,14 @@
             .packetSize = 188,
     };
     dvrArray[DVR_PLAYBACK0].type = DvrType::PLAYBACK;
-    dvrArray[DVR_PLAYBACK0].playbackInputFile = "/vendor/etc/segment000000.ts";
+    dvrArray[DVR_PLAYBACK0].playbackInputFile = "/data/local/tmp/segment000000.ts";
     dvrArray[DVR_PLAYBACK0].bufferSize = FMQ_SIZE_4M;
     dvrArray[DVR_PLAYBACK0].settings.playback(playbackSettings);
 };
+
+/** Configuration array for the descrambler test */
+inline void initDescramblerConfig() {
+    descramblerArray[DESC_0].casSystemId = CLEAR_KEY_SYSTEM_ID;
+    descramblerArray[DESC_0].provisionStr = PROVISION_STR;
+    descramblerArray[DESC_0].hidlPvtData.resize(256);
+};
diff --git a/tv/tuner/1.1/Android.bp b/tv/tuner/1.1/Android.bp
new file mode 100644
index 0000000..2019050
--- /dev/null
+++ b/tv/tuner/1.1/Android.bp
@@ -0,0 +1,19 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.tv.tuner@1.1",
+    root: "android.hardware",
+    srcs: [
+        "IDemux.hal",
+        "IFilter.hal",
+        "IFilterCallback.hal",
+        "ITuner.hal",
+        "types.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+        "android.hidl.safe_union@1.0",
+        "android.hardware.tv.tuner@1.0",
+    ],
+    gen_java: false,
+}
diff --git a/tv/tuner/1.1/IDemux.hal b/tv/tuner/1.1/IDemux.hal
new file mode 100644
index 0000000..434ecbd
--- /dev/null
+++ b/tv/tuner/1.1/IDemux.hal
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner@1.1;
+
+import @1.0::IDemux;
+import @1.0::IFilter;
+import @1.0::Result;
+
+/**
+ * Demultiplexer(Demux) takes a single multiplexed input and splits it into
+ * one or more output.
+ */
+interface IDemux extends @1.0::IDemux {
+    /**
+     * Get a 64-bit 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 v1_1 filter instance.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_ARGUMENT if failed for a wrong filter ID.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     * @return avSyncHwId the id of hardware A/V sync.
+     */
+    getAvSyncHwId64Bit(IFilter filter) generates (Result result, uint64_t avSyncHwId);
+};
\ No newline at end of file
diff --git a/tv/tuner/1.1/IFilter.hal b/tv/tuner/1.1/IFilter.hal
new file mode 100644
index 0000000..6c4d8a5
--- /dev/null
+++ b/tv/tuner/1.1/IFilter.hal
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner@1.1;
+
+import @1.0::IFilter;
+import @1.0::Result;
+
+/**
+ * The Filter is used to filter wanted data according to the filter's
+ * configuration.
+ *
+ * To access the v1.1 IFilter APIs, the implementation can cast the IFilter
+ * interface returned from the @1.0::IDemux openFilter into a v1.1 IFiler
+ * using V1_1::IFilter::castFrom(V1_0::IFilter).
+ */
+interface IFilter extends @1.0::IFilter {
+    /**
+     * Get the 64-bit filter Id. This id is 32-bit in Tuner HAL 1.0.
+     *
+     * It is used by the client to ask the hardware resource id for the filter.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     * @return filterId the hardware resource Id for the filter.
+     */
+    getId64Bit() generates (Result result, uint64_t filterId);
+};
diff --git a/tv/tuner/1.1/IFilterCallback.hal b/tv/tuner/1.1/IFilterCallback.hal
new file mode 100644
index 0000000..a80273b
--- /dev/null
+++ b/tv/tuner/1.1/IFilterCallback.hal
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner@1.1;
+
+import @1.0::IFilterCallback;
+import @1.1::DemuxFilterEvent;
+
+interface IFilterCallback extends @1.0::IFilterCallback {
+    /**
+     * Notify the client that a new filter event happened.
+     *
+     * @param filterEvent a v1_1 filter event.
+     */
+    oneway onFilterEvent_1_1(DemuxFilterEvent filterEvent);
+};
diff --git a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp b/tv/tuner/1.1/ITuner.hal
similarity index 63%
copy from wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
copy to tv/tuner/1.1/ITuner.hal
index 7edec47..915fb85 100644
--- a/wifi/supplicant/1.2/vts/functional/VtsHalWifiSupplicantP2pV1_2TargetTest.cpp
+++ b/tv/tuner/1.1/ITuner.hal
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2020 The Android Open Source Project
+ * Copyright 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-#include <VtsCoreUtil.h>
-#include "supplicant_hidl_test_utils.h"
+package android.hardware.tv.tuner@1.1;
 
-int main(int argc, char** argv) {
-    if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct"))
-        return 0;
+import @1.0::ITuner;
+import @1.0::Result;
 
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
+/**
+ * Top level interface to manage Frontend, Demux and Decrambler hardware
+ * resources which are needed for Android TV.
+ */
+interface ITuner extends @1.0::ITuner {};
diff --git a/tv/tuner/1.1/TEST_MAPPING b/tv/tuner/1.1/TEST_MAPPING
new file mode 100644
index 0000000..7c91b8f
--- /dev/null
+++ b/tv/tuner/1.1/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "presubmit": [
+    {
+      "name": "VtsHalTvTunerV1_1TargetTest"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/tv/tuner/1.1/default/Android.bp b/tv/tuner/1.1/default/Android.bp
new file mode 100644
index 0000000..4401f7c
--- /dev/null
+++ b/tv/tuner/1.1/default/Android.bp
@@ -0,0 +1,52 @@
+cc_defaults {
+    name: "tuner_service_defaults@1.1",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: [
+        "Demux.cpp",
+        "Descrambler.cpp",
+        "Dvr.cpp",
+        "Filter.cpp",
+        "Frontend.cpp",
+        "Lnb.cpp",
+        "TimeFilter.cpp",
+        "Tuner.cpp",
+        "service.cpp",
+    ],
+
+    compile_multilib: "first",
+
+    shared_libs: [
+        "android.hardware.tv.tuner@1.0",
+        "android.hardware.tv.tuner@1.1",
+        "android.hidl.memory@1.0",
+        "libcutils",
+        "libfmq",
+        "libhidlbase",
+        "libhidlmemory",
+        "libion",
+        "liblog",
+        "libstagefright_foundation",
+        "libutils",
+    ],
+    header_libs: [
+        "media_plugin_headers",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.tv.tuner@1.1-service",
+    vintf_fragments: ["android.hardware.tv.tuner@1.1-service.xml"],
+    defaults: ["tuner_service_defaults@1.1"],
+    init_rc: ["android.hardware.tv.tuner@1.1-service.rc"],
+}
+
+cc_binary {
+    name: "android.hardware.tv.tuner@1.1-service-lazy",
+    vintf_fragments: ["android.hardware.tv.tuner@1.1-service-lazy.xml"],
+    overrides: ["android.hardware.tv.tuner@1.1-service"],
+    defaults: ["tuner_service_defaults@1.1"],
+    init_rc: ["android.hardware.tv.tuner@1.1-service-lazy.rc"],
+    cflags: ["-DLAZY_SERVICE"],
+}
diff --git a/tv/tuner/1.1/default/Demux.cpp b/tv/tuner/1.1/default/Demux.cpp
new file mode 100644
index 0000000..007d5eb
--- /dev/null
+++ b/tv/tuner/1.1/default/Demux.cpp
@@ -0,0 +1,457 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv.tuner@1.1-Demux"
+
+#include "Demux.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+#define WAIT_TIMEOUT 3000000000
+Demux::Demux(uint32_t demuxId, sp<Tuner> tuner) {
+    mDemuxId = demuxId;
+    mTunerService = tuner;
+}
+
+Demux::~Demux() {}
+
+Return<void> Demux::getAvSyncHwId64Bit(const sp<IFilter>& filter, getAvSyncHwId64Bit_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    uint64_t avSyncHwId = -1;
+    uint64_t id;
+    Result status;
+
+    sp<V1_1::IFilter> filter_v1_1 = V1_1::IFilter::castFrom(filter);
+    if (filter_v1_1 != NULL) {
+        filter_v1_1->getId64Bit([&](Result result, uint64_t filterId) {
+            id = filterId;
+            status = result;
+        });
+    } else {
+        filter->getId([&](Result result, uint32_t filterId) {
+            id = filterId;
+            status = result;
+        });
+    }
+
+    if (status != Result::SUCCESS) {
+        ALOGE("[Demux] Can't get 64-bit filter Id.");
+        _hidl_cb(Result::INVALID_STATE, avSyncHwId);
+        return Void();
+    }
+
+    if (!mFilters[id]->isMediaFilter()) {
+        ALOGE("[Demux] Given filter is not a media filter.");
+        _hidl_cb(Result::INVALID_ARGUMENT, avSyncHwId);
+        return Void();
+    }
+
+    if (!mPcrFilterIds.empty()) {
+        // Return the lowest pcr filter id in the default implementation as the av sync id
+        _hidl_cb(Result::SUCCESS, *mPcrFilterIds.begin());
+        return Void();
+    }
+
+    ALOGE("[Demux] No PCR filter opened.");
+    _hidl_cb(Result::INVALID_STATE, avSyncHwId);
+    return Void();
+}
+
+Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (mTunerService == nullptr) {
+        return Result::NOT_INITIALIZED;
+    }
+
+    mFrontend = mTunerService->getFrontendById(frontendId);
+
+    if (mFrontend == nullptr) {
+        return Result::INVALID_STATE;
+    }
+
+    mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId);
+
+    return Result::SUCCESS;
+}
+
+Return<void> Demux::openFilter(const DemuxFilterType& type, uint32_t bufferSize,
+                               const sp<IFilterCallback>& cb, openFilter_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    uint64_t filterId;
+    filterId = ++mLastUsedFilterId;
+
+    if (cb == nullptr) {
+        ALOGW("[Demux] callback can't be null");
+        _hidl_cb(Result::INVALID_ARGUMENT, new Filter());
+        return Void();
+    }
+
+    sp<Filter> filter = new Filter(type, filterId, bufferSize, cb, this);
+
+    if (!filter->createFilterMQ()) {
+        _hidl_cb(Result::UNKNOWN_ERROR, filter);
+        return Void();
+    }
+
+    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);
+        }
+    }
+
+    _hidl_cb(result ? Result::SUCCESS : Result::INVALID_ARGUMENT, filter);
+    return Void();
+}
+
+Return<void> Demux::openTimeFilter(openTimeFilter_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    mTimeFilter = new TimeFilter(this);
+
+    _hidl_cb(Result::SUCCESS, mTimeFilter);
+    return Void();
+}
+
+Return<void> Demux::getAvSyncHwId(const sp<IFilter>& filter, getAvSyncHwId_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    uint32_t avSyncHwId = -1;
+    uint64_t id;
+    Result status;
+
+    sp<V1_1::IFilter> filter_v1_1 = V1_1::IFilter::castFrom(filter);
+    if (filter_v1_1 != NULL) {
+        filter_v1_1->getId64Bit([&](Result result, uint64_t filterId) {
+            id = filterId;
+            status = result;
+        });
+    } else {
+        filter->getId([&](Result result, uint32_t filterId) {
+            id = filterId;
+            status = result;
+        });
+    }
+
+    if (status != Result::SUCCESS) {
+        ALOGE("[Demux] Can't get filter Id.");
+        _hidl_cb(Result::INVALID_STATE, avSyncHwId);
+        return Void();
+    }
+
+    if (!mFilters[id]->isMediaFilter()) {
+        ALOGE("[Demux] Given filter is not a media filter.");
+        _hidl_cb(Result::INVALID_ARGUMENT, avSyncHwId);
+        return Void();
+    }
+
+    if (!mPcrFilterIds.empty()) {
+        // Return the lowest pcr filter id in the default implementation as the av sync id
+        _hidl_cb(Result::SUCCESS, *mPcrFilterIds.begin());
+        return Void();
+    }
+
+    ALOGE("[Demux] No PCR filter opened.");
+    _hidl_cb(Result::INVALID_STATE, avSyncHwId);
+    return Void();
+}
+
+Return<void> Demux::getAvSyncTime(AvSyncHwId avSyncHwId, getAvSyncTime_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    uint64_t avSyncTime = -1;
+    if (mPcrFilterIds.empty()) {
+        _hidl_cb(Result::INVALID_STATE, avSyncTime);
+        return Void();
+    }
+    if (avSyncHwId != *mPcrFilterIds.begin()) {
+        _hidl_cb(Result::INVALID_ARGUMENT, avSyncTime);
+        return Void();
+    }
+
+    _hidl_cb(Result::SUCCESS, avSyncTime);
+    return Void();
+}
+
+Return<Result> Demux::close() {
+    ALOGV("%s", __FUNCTION__);
+
+    set<uint64_t>::iterator it;
+    for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
+        mDvrPlayback->removePlaybackFilter(*it);
+    }
+    mPlaybackFilterIds.clear();
+    mRecordFilterIds.clear();
+    mFilters.clear();
+    mLastUsedFilterId = -1;
+    mTunerService->removeDemux(mDemuxId);
+
+    return Result::SUCCESS;
+}
+
+Return<void> Demux::openDvr(DvrType type, uint32_t bufferSize, const sp<IDvrCallback>& cb,
+                            openDvr_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (cb == nullptr) {
+        ALOGW("[Demux] DVR callback can't be null");
+        _hidl_cb(Result::INVALID_ARGUMENT, new Dvr());
+        return Void();
+    }
+
+    set<uint64_t>::iterator it;
+    switch (type) {
+        case DvrType::PLAYBACK:
+            mDvrPlayback = new Dvr(type, bufferSize, cb, this);
+            if (!mDvrPlayback->createDvrMQ()) {
+                _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
+                return Void();
+            }
+
+            for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
+                if (!mDvrPlayback->addPlaybackFilter(*it, mFilters[*it])) {
+                    ALOGE("[Demux] Can't get filter info for DVR playback");
+                    _hidl_cb(Result::UNKNOWN_ERROR, mDvrPlayback);
+                    return Void();
+                }
+            }
+
+            _hidl_cb(Result::SUCCESS, mDvrPlayback);
+            return Void();
+        case DvrType::RECORD:
+            mDvrRecord = new Dvr(type, bufferSize, cb, this);
+            if (!mDvrRecord->createDvrMQ()) {
+                _hidl_cb(Result::UNKNOWN_ERROR, mDvrRecord);
+                return Void();
+            }
+
+            _hidl_cb(Result::SUCCESS, mDvrRecord);
+            return Void();
+        default:
+            _hidl_cb(Result::INVALID_ARGUMENT, nullptr);
+            return Void();
+    }
+}
+
+Return<Result> Demux::connectCiCam(uint32_t ciCamId) {
+    ALOGV("%s", __FUNCTION__);
+
+    mCiCamId = ciCamId;
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Demux::disconnectCiCam() {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Result Demux::removeFilter(uint64_t filterId) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (mDvrPlayback != nullptr) {
+        mDvrPlayback->removePlaybackFilter(filterId);
+    }
+    mPlaybackFilterIds.erase(filterId);
+    mRecordFilterIds.erase(filterId);
+    mFilters.erase(filterId);
+
+    return Result::SUCCESS;
+}
+
+void Demux::startBroadcastTsFilter(vector<uint8_t> data) {
+    set<uint64_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<uint8_t> data) {
+    set<uint64_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<uint8_t> data, uint16_t pid, uint64_t pts) {
+    sendFrontendInputToRecord(data);
+    set<uint64_t>::iterator it;
+    for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
+        if (pid == mFilters[*it]->getTpid()) {
+            mFilters[*it]->updatePts(pts);
+        }
+    }
+}
+
+bool Demux::startBroadcastFilterDispatcher() {
+    set<uint64_t>::iterator it;
+
+    // Handle the output data per filter type
+    for (it = mPlaybackFilterIds.begin(); it != mPlaybackFilterIds.end(); it++) {
+        if (mFilters[*it]->startFilterHandler() != Result::SUCCESS) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool Demux::startRecordFilterDispatcher() {
+    set<uint64_t>::iterator it;
+
+    for (it = mRecordFilterIds.begin(); it != mRecordFilterIds.end(); it++) {
+        if (mFilters[*it]->startRecordFilterHandler() != Result::SUCCESS) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+Result Demux::startFilterHandler(uint64_t filterId) {
+    return mFilters[filterId]->startFilterHandler();
+}
+
+void Demux::updateFilterOutput(uint64_t filterId, vector<uint8_t> data) {
+    mFilters[filterId]->updateFilterOutput(data);
+}
+
+void Demux::updateMediaFilterOutput(uint64_t filterId, vector<uint8_t> data, uint64_t pts) {
+    updateFilterOutput(filterId, data);
+    mFilters[filterId]->updatePts(pts);
+}
+
+uint16_t Demux::getFilterTpid(uint64_t filterId) {
+    return mFilters[filterId]->getTpid();
+}
+
+void Demux::startFrontendInputLoop() {
+    pthread_create(&mFrontendInputThread, NULL, __threadLoopFrontend, this);
+    pthread_setname_np(mFrontendInputThread, "frontend_input_thread");
+}
+
+void* Demux::__threadLoopFrontend(void* user) {
+    Demux* const self = static_cast<Demux*>(user);
+    self->frontendInputThreadLoop();
+    return 0;
+}
+
+void Demux::frontendInputThreadLoop() {
+    std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
+    mFrontendInputThreadRunning = true;
+
+    if (!mDvrPlayback) {
+        ALOGW("[Demux] No software Frontend input configured. Ending Frontend thread loop.");
+        mFrontendInputThreadRunning = false;
+        return;
+    }
+
+    while (mFrontendInputThreadRunning) {
+        uint32_t efState = 0;
+        status_t status = mDvrPlayback->getDvrEventFlag()->wait(
+                static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY), &efState, WAIT_TIMEOUT,
+                true /* retry on spurious wake */);
+        if (status != OK) {
+            ALOGD("[Demux] wait for data ready on the playback FMQ");
+            continue;
+        }
+        if (mDvrPlayback->getSettings().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;
+    std::lock_guard<std::mutex> lock(mFrontendInputThreadLock);
+}
+
+void Demux::setIsRecording(bool isRecording) {
+    mIsRecording = isRecording;
+}
+
+bool Demux::attachRecordFilter(uint64_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(uint64_t filterId) {
+    if (mFilters[filterId] == nullptr || mDvrRecord == nullptr) {
+        return false;
+    }
+
+    mRecordFilterIds.erase(filterId);
+    mFilters[filterId]->detachFilterFromRecord();
+
+    return true;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/tuner/1.1/default/Demux.h b/tv/tuner/1.1/default/Demux.h
new file mode 100644
index 0000000..3623d0f
--- /dev/null
+++ b/tv/tuner/1.1/default/Demux.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_TUNER_V1_1_DEMUX_H_
+#define ANDROID_HARDWARE_TV_TUNER_V1_1_DEMUX_H_
+
+#include <android/hardware/tv/tuner/1.1/IDemux.h>
+#include <fmq/MessageQueue.h>
+#include <math.h>
+#include <set>
+#include "Dvr.h"
+#include "Filter.h"
+#include "Frontend.h"
+#include "TimeFilter.h"
+#include "Tuner.h"
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::EventFlag;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::MQDescriptorSync;
+
+using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+class Dvr;
+class Filter;
+class Frontend;
+class TimeFilter;
+class Tuner;
+
+class Demux : public V1_1::IDemux {
+  public:
+    Demux(uint32_t demuxId, sp<Tuner> tuner);
+
+    ~Demux();
+
+    virtual Return<void> getAvSyncHwId64Bit(const sp<IFilter>& filter,
+                                            getAvSyncHwId64Bit_cb _hidl_cb) override;
+
+    virtual Return<Result> setFrontendDataSource(uint32_t frontendId) override;
+
+    virtual Return<void> openFilter(const DemuxFilterType& type, uint32_t bufferSize,
+                                    const sp<IFilterCallback>& cb, openFilter_cb _hidl_cb) override;
+
+    virtual Return<void> openTimeFilter(openTimeFilter_cb _hidl_cb) override;
+
+    virtual Return<void> getAvSyncHwId(const sp<IFilter>& filter,
+                                       getAvSyncHwId_cb _hidl_cb) override;
+
+    virtual Return<void> getAvSyncTime(AvSyncHwId avSyncHwId, getAvSyncTime_cb _hidl_cb) override;
+
+    virtual Return<Result> close() override;
+
+    virtual Return<void> openDvr(DvrType type, uint32_t bufferSize, const sp<IDvrCallback>& cb,
+                                 openDvr_cb _hidl_cb) override;
+
+    virtual Return<Result> connectCiCam(uint32_t ciCamId) override;
+
+    virtual Return<Result> disconnectCiCam() override;
+
+    // Functions interacts with Tuner Service
+    void stopFrontendInput();
+    Result removeFilter(uint64_t filterId);
+    bool attachRecordFilter(uint64_t filterId);
+    bool detachRecordFilter(uint64_t filterId);
+    Result startFilterHandler(uint64_t filterId);
+    void updateFilterOutput(uint64_t filterId, vector<uint8_t> data);
+    void updateMediaFilterOutput(uint64_t filterId, vector<uint8_t> data, uint64_t pts);
+    uint16_t getFilterTpid(uint64_t filterId);
+    void setIsRecording(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<uint8_t> data);
+
+    void sendFrontendInputToRecord(vector<uint8_t> data);
+    void sendFrontendInputToRecord(vector<uint8_t> data, uint16_t pid, uint64_t pts);
+    bool startRecordFilterDispatcher();
+
+  private:
+    // Tuner service
+    sp<Tuner> mTunerService;
+
+    // Frontend source
+    sp<Frontend> mFrontend;
+
+    // A struct that passes the arguments to a newly created filter thread
+    struct ThreadArgs {
+        Demux* user;
+        uint64_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();
+
+    uint32_t mDemuxId = -1;
+    uint32_t mCiCamId;
+    set<uint64_t> mPcrFilterIds;
+    /**
+     * Record the last used filter id. Initial value is -1.
+     * Filter Id starts with 0.
+     */
+    uint64_t mLastUsedFilterId = -1;
+    /**
+     * Record all the used playback filter Ids.
+     * Any removed filter id should be removed from this set.
+     */
+    set<uint64_t> mPlaybackFilterIds;
+    /**
+     * Record all the attached record filter Ids.
+     * Any removed filter id should be removed from this set.
+     */
+    set<uint64_t> mRecordFilterIds;
+    /**
+     * A list of created Filter sp.
+     * The array number is the filter ID.
+     */
+    std::map<uint64_t, sp<Filter>> mFilters;
+
+    /**
+     * Local reference to the opened Timer Filter instance.
+     */
+    sp<TimeFilter> mTimeFilter;
+
+    /**
+     * Local reference to the opened DVR object.
+     */
+    sp<Dvr> mDvrPlayback;
+    sp<Dvr> mDvrRecord;
+
+    // Thread handlers
+    pthread_t mFrontendInputThread;
+    /**
+     * If a specific filter's writing loop is still running
+     */
+    bool mFrontendInputThreadRunning;
+    bool mKeepFetchingDataFromFrontend;
+    /**
+     * If the dvr recording is running.
+     */
+    bool mIsRecording = false;
+    /**
+     * Lock to protect writes to the FMQs
+     */
+    std::mutex mWriteLock;
+    /**
+     * Lock to protect writes to the input status
+     */
+    std::mutex mFrontendInputThreadLock;
+
+    // temp handle single PES filter
+    // TODO handle mulptiple Pes filters
+    int mPesSizeLeft = 0;
+    vector<uint8_t> mPesOutput;
+
+    const bool DEBUG_DEMUX = false;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TV_TUNER_V1_1_DEMUX_H_
diff --git a/tv/tuner/1.1/default/Descrambler.cpp b/tv/tuner/1.1/default/Descrambler.cpp
new file mode 100644
index 0000000..1fbc780
--- /dev/null
+++ b/tv/tuner/1.1/default/Descrambler.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv.tuner@1.1-Descrambler"
+
+#include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
+#include <utils/Log.h>
+
+#include "Descrambler.h"
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+Descrambler::Descrambler() {}
+
+Descrambler::~Descrambler() {}
+
+Return<Result> Descrambler::setDemuxSource(uint32_t demuxId) {
+    ALOGV("%s", __FUNCTION__);
+    if (mDemuxSet) {
+        ALOGW("[   WARN   ] Descrambler has already been set with a demux id %" PRIu32,
+              mSourceDemuxId);
+        return Result::INVALID_STATE;
+    }
+    mDemuxSet = true;
+    mSourceDemuxId = static_cast<uint32_t>(demuxId);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Descrambler::setKeyToken(const hidl_vec<uint8_t>& /* keyToken */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Descrambler::addPid(const DemuxPid& /* pid */,
+                                   const sp<IFilter>& /* optionalSourceFilter */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Descrambler::removePid(const DemuxPid& /* pid */,
+                                      const sp<IFilter>& /* optionalSourceFilter */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Descrambler::close() {
+    ALOGV("%s", __FUNCTION__);
+    mDemuxSet = false;
+
+    return Result::SUCCESS;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/tuner/1.1/default/Descrambler.h b/tv/tuner/1.1/default/Descrambler.h
new file mode 100644
index 0000000..ffc284d
--- /dev/null
+++ b/tv/tuner/1.1/default/Descrambler.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_TUNER_V1_1_DESCRAMBLER_H_
+#define ANDROID_HARDWARE_TV_TUNER_V1_1_DESCRAMBLER_H_
+
+#include <android/hardware/tv/tuner/1.0/IDescrambler.h>
+#include <android/hardware/tv/tuner/1.1/ITuner.h>
+#include <inttypes.h>
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+class Descrambler : public IDescrambler {
+  public:
+    Descrambler();
+
+    virtual Return<Result> setDemuxSource(uint32_t demuxId) override;
+
+    virtual Return<Result> setKeyToken(const hidl_vec<uint8_t>& keyToken) override;
+
+    virtual Return<Result> addPid(const DemuxPid& pid,
+                                  const sp<IFilter>& optionalSourceFilter) override;
+
+    virtual Return<Result> removePid(const DemuxPid& pid,
+                                     const sp<IFilter>& optionalSourceFilter) override;
+
+    virtual Return<Result> close() override;
+
+  private:
+    virtual ~Descrambler();
+    uint32_t mSourceDemuxId;
+    bool mDemuxSet = false;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TV_TUNER_V1_DESCRAMBLER_H_
diff --git a/tv/tuner/1.1/default/Dvr.cpp b/tv/tuner/1.1/default/Dvr.cpp
new file mode 100644
index 0000000..bf4c77e
--- /dev/null
+++ b/tv/tuner/1.1/default/Dvr.cpp
@@ -0,0 +1,499 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv.tuner@1.1-Dvr"
+
+#include "Dvr.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+#define WAIT_TIMEOUT 3000000000
+
+Dvr::Dvr() {}
+
+Dvr::Dvr(DvrType type, uint32_t bufferSize, const sp<IDvrCallback>& cb, sp<Demux> demux) {
+    mType = type;
+    mBufferSize = bufferSize;
+    mCallback = cb;
+    mDemux = demux;
+}
+
+Dvr::~Dvr() {}
+
+Return<void> Dvr::getQueueDesc(getQueueDesc_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    _hidl_cb(Result::SUCCESS, *mDvrMQ->getDesc());
+    return Void();
+}
+
+Return<Result> Dvr::configure(const DvrSettings& settings) {
+    ALOGV("%s", __FUNCTION__);
+
+    mDvrSettings = settings;
+    mDvrConfigured = true;
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Dvr::attachFilter(const sp<V1_0::IFilter>& filter) {
+    ALOGV("%s", __FUNCTION__);
+
+    uint64_t filterId;
+    Result status;
+
+    sp<V1_1::IFilter> filter_v1_1 = V1_1::IFilter::castFrom(filter);
+    if (filter_v1_1 != NULL) {
+        filter_v1_1->getId64Bit([&](Result result, uint64_t id) {
+            filterId = id;
+            status = result;
+        });
+    } else {
+        filter->getId([&](Result result, uint32_t id) {
+            filterId = id;
+            status = result;
+        });
+    }
+
+    if (status != Result::SUCCESS) {
+        return status;
+    }
+
+    // TODO check if the attached filter is a record filter
+    if (!mDemux->attachRecordFilter(filterId)) {
+        return Result::INVALID_ARGUMENT;
+    }
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Dvr::detachFilter(const sp<V1_0::IFilter>& filter) {
+    ALOGV("%s", __FUNCTION__);
+
+    uint64_t filterId;
+    Result status;
+
+    sp<V1_1::IFilter> filter_v1_1 = V1_1::IFilter::castFrom(filter);
+    if (filter_v1_1 != NULL) {
+        filter_v1_1->getId64Bit([&](Result result, uint64_t id) {
+            filterId = id;
+            status = result;
+        });
+    } else {
+        filter->getId([&](Result result, uint32_t id) {
+            filterId = id;
+            status = result;
+        });
+    }
+
+    if (status != Result::SUCCESS) {
+        return status;
+    }
+
+    if (!mDemux->detachRecordFilter(filterId)) {
+        return Result::INVALID_ARGUMENT;
+    }
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Dvr::start() {
+    ALOGV("%s", __FUNCTION__);
+
+    if (!mCallback) {
+        return Result::NOT_INITIALIZED;
+    }
+
+    if (!mDvrConfigured) {
+        return Result::INVALID_STATE;
+    }
+
+    if (mType == DvrType::PLAYBACK) {
+        pthread_create(&mDvrThread, NULL, __threadLoopPlayback, this);
+        pthread_setname_np(mDvrThread, "playback_waiting_loop");
+    } 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 Result::SUCCESS;
+}
+
+Return<Result> Dvr::stop() {
+    ALOGV("%s", __FUNCTION__);
+
+    mDvrThreadRunning = false;
+
+    lock_guard<mutex> lock(mDvrThreadLock);
+
+    mIsRecordStarted = false;
+    mDemux->setIsRecording(false);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Dvr::flush() {
+    ALOGV("%s", __FUNCTION__);
+
+    mRecordStatus = RecordStatus::DATA_READY;
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Dvr::close() {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+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) != OK) {
+        return false;
+    }
+
+    return true;
+}
+
+EventFlag* Dvr::getDvrEventFlag() {
+    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) {
+        uint32_t efState = 0;
+        status_t status =
+                mDvrEventFlag->wait(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY),
+                                    &efState, WAIT_TIMEOUT, true /* retry on spurious wake */);
+        if (status != OK) {
+            ALOGD("[Dvr] wait for data ready on the playback FMQ");
+            continue;
+        }
+
+        if (mDvrSettings.playback().dataFormat == DataFormat::ES) {
+            if (!processEsDataOnPlayback(false /*isVirtualFrontend*/, false /*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(false /*isVirtualFrontend*/, false /*isRecording*/) ||
+            !startFilterDispatcher(false /*isVirtualFrontend*/, false /*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.playback().highThreshold,
+                                                         mDvrSettings.playback().lowThreshold);
+    if (mPlaybackStatus != newStatus) {
+        mCallback->onPlaybackStatus(newStatus);
+        mPlaybackStatus = newStatus;
+    }
+}
+
+PlaybackStatus Dvr::checkPlaybackStatusChange(uint32_t availableToWrite, uint32_t availableToRead,
+                                              uint32_t highThreshold, uint32_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
+    int size = mDvrMQ->availableToRead();
+    int playbackPacketSize = mDvrSettings.playback().packetSize;
+    vector<uint8_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<uint8_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<uint8_t> frameData;
+    map<uint64_t, sp<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);
+    }
+
+    return true;
+}
+
+void Dvr::getMetaDataValue(int& index, uint8_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<uint8_t> data) {
+    map<uint64_t, sp<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<uint64_t, sp<IFilter>>::iterator it;
+    // Handle the output data per filter type
+    for (it = mFilters.begin(); it != mFilters.end(); it++) {
+        if (mDemux->startFilterHandler(it->first) != Result::SUCCESS) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+bool Dvr::writeRecordFMQ(const vector<uint8_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.record().highThreshold,
+                                                     mDvrSettings.record().lowThreshold);
+    if (mRecordStatus != newStatus) {
+        mCallback->onRecordStatus(newStatus);
+        mRecordStatus = newStatus;
+    }
+}
+
+RecordStatus Dvr::checkRecordStatusChange(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 mRecordStatus;
+}
+
+bool Dvr::addPlaybackFilter(uint64_t filterId, sp<IFilter> filter) {
+    mFilters[filterId] = filter;
+    return true;
+}
+
+bool Dvr::removePlaybackFilter(uint64_t filterId) {
+    mFilters.erase(filterId);
+    return true;
+}
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/tuner/1.1/default/Dvr.h b/tv/tuner/1.1/default/Dvr.h
new file mode 100644
index 0000000..7b7efef
--- /dev/null
+++ b/tv/tuner/1.1/default/Dvr.h
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_TUNER_V1_1_DVR_H_
+#define ANDROID_HARDWARE_TV_TUNER_V1_1_DVR_H_
+
+#include <fmq/MessageQueue.h>
+#include <math.h>
+#include <set>
+#include "Demux.h"
+#include "Frontend.h"
+#include "Tuner.h"
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::EventFlag;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::MQDescriptorSync;
+
+using DvrMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+struct MediaEsMetaData {
+    bool isAudio;
+    int startIndex;
+    int len;
+    int pts;
+};
+
+class Demux;
+class Filter;
+class Frontend;
+class Tuner;
+
+class Dvr : public IDvr {
+  public:
+    Dvr();
+
+    Dvr(DvrType type, uint32_t bufferSize, const sp<IDvrCallback>& cb, sp<Demux> demux);
+
+    ~Dvr();
+
+    virtual Return<void> getQueueDesc(getQueueDesc_cb _hidl_cb) override;
+
+    virtual Return<Result> configure(const DvrSettings& settings) override;
+
+    virtual Return<Result> attachFilter(const sp<IFilter>& filter) override;
+
+    virtual Return<Result> detachFilter(const sp<IFilter>& filter) override;
+
+    virtual Return<Result> start() override;
+
+    virtual Return<Result> stop() override;
+
+    virtual Return<Result> flush() override;
+
+    virtual Return<Result> close() override;
+
+    /**
+     * To create a DvrMQ and its Event Flag.
+     *
+     * Return false is any of the above processes fails.
+     */
+    bool createDvrMQ();
+    void sendBroadcastInputToDvrRecord(vector<uint8_t> byteBuffer);
+    bool writeRecordFMQ(const std::vector<uint8_t>& data);
+    bool addPlaybackFilter(uint64_t filterId, sp<IFilter> filter);
+    bool removePlaybackFilter(uint64_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
+    sp<Demux> mDemux;
+
+    DvrType mType;
+    uint32_t mBufferSize;
+    sp<IDvrCallback> mCallback;
+    std::map<uint64_t, sp<IFilter>> mFilters;
+
+    void deleteEventFlag();
+    bool readDataFromMQ();
+    void getMetaDataValue(int& index, uint8_t* dataOutputBuffer, int& value);
+    void maySendPlaybackStatusCallback();
+    void maySendRecordStatusCallback();
+    PlaybackStatus checkPlaybackStatusChange(uint32_t availableToWrite, uint32_t availableToRead,
+                                             uint32_t highThreshold, uint32_t lowThreshold);
+    RecordStatus checkRecordStatusChange(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.
+     */
+    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;
+    /**
+     * Demux callbacks used on filter events or IO buffer status
+     */
+    bool mDvrConfigured = false;
+    DvrSettings mDvrSettings;
+
+    // Thread handlers
+    pthread_t mDvrThread;
+
+    // FMQ status local records
+    PlaybackStatus mPlaybackStatus;
+    RecordStatus mRecordStatus;
+    /**
+     * If a specific filter's writing loop is still running
+     */
+    bool mDvrThreadRunning;
+    bool mKeepFetchingDataFromFrontend;
+    /**
+     * Lock to protect writes to the FMQs
+     */
+    std::mutex mWriteLock;
+    /**
+     * Lock to protect writes to the input status
+     */
+    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
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TV_TUNER_V1_1_DVR_H_
\ No newline at end of file
diff --git a/tv/tuner/1.1/default/Filter.cpp b/tv/tuner/1.1/default/Filter.cpp
new file mode 100644
index 0000000..2d6214d
--- /dev/null
+++ b/tv/tuner/1.1/default/Filter.cpp
@@ -0,0 +1,719 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv.tuner@1.1-Filter"
+
+#include "Filter.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+#define WAIT_TIMEOUT 3000000000
+
+Filter::Filter() {}
+
+Filter::Filter(DemuxFilterType type, uint64_t filterId, uint32_t bufferSize,
+               const sp<IFilterCallback>& cb, sp<Demux> demux) {
+    mType = type;
+    mFilterId = filterId;
+    mBufferSize = bufferSize;
+    mDemux = demux;
+
+    switch (mType.mainType) {
+        case DemuxFilterMainType::TS:
+            if (mType.subType.tsFilterType() == DemuxTsFilterType::AUDIO ||
+                mType.subType.tsFilterType() == DemuxTsFilterType::VIDEO) {
+                mIsMediaFilter = true;
+            }
+            if (mType.subType.tsFilterType() == DemuxTsFilterType::PCR) {
+                mIsPcrFilter = true;
+            }
+            if (mType.subType.tsFilterType() == DemuxTsFilterType::RECORD) {
+                mIsRecordFilter = true;
+            }
+            break;
+        case DemuxFilterMainType::MMTP:
+            if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
+                mType.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
+                mIsMediaFilter = true;
+            }
+            if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::RECORD) {
+                mIsRecordFilter = true;
+            }
+            break;
+        case DemuxFilterMainType::IP:
+            break;
+        case DemuxFilterMainType::TLV:
+            break;
+        case DemuxFilterMainType::ALP:
+            break;
+        default:
+            break;
+    }
+
+    sp<V1_1::IFilterCallback> filterCallback_v1_1 = V1_1::IFilterCallback::castFrom(cb);
+    if (filterCallback_v1_1 != NULL) {
+        mCallback_1_1 = filterCallback_v1_1;
+    } else {
+        mCallback = cb;
+    }
+}
+
+Filter::~Filter() {}
+
+Return<void> Filter::getId64Bit(getId64Bit_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    _hidl_cb(Result::SUCCESS, mFilterId);
+    return Void();
+}
+
+Return<void> Filter::getId(getId_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    _hidl_cb(Result::SUCCESS, static_cast<uint32_t>(mFilterId));
+    return Void();
+}
+
+Return<Result> Filter::setDataSource(const sp<V1_0::IFilter>& filter) {
+    ALOGV("%s", __FUNCTION__);
+
+    mDataSource = filter;
+    mIsDataSourceDemux = false;
+
+    return Result::SUCCESS;
+}
+
+Return<void> Filter::getQueueDesc(getQueueDesc_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    mIsUsingFMQ = mIsRecordFilter ? false : true;
+
+    _hidl_cb(Result::SUCCESS, *mFilterMQ->getDesc());
+    return Void();
+}
+
+Return<Result> Filter::configure(const DemuxFilterSettings& settings) {
+    ALOGV("%s", __FUNCTION__);
+
+    mFilterSettings = settings;
+    switch (mType.mainType) {
+        case DemuxFilterMainType::TS:
+            mTpid = settings.ts().tpid;
+            break;
+        case DemuxFilterMainType::MMTP:
+            break;
+        case DemuxFilterMainType::IP:
+            break;
+        case DemuxFilterMainType::TLV:
+            break;
+        case DemuxFilterMainType::ALP:
+            break;
+        default:
+            break;
+    }
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Filter::start() {
+    ALOGV("%s", __FUNCTION__);
+
+    return startFilterLoop();
+}
+
+Return<Result> Filter::stop() {
+    ALOGV("%s", __FUNCTION__);
+
+    mFilterThreadRunning = false;
+
+    std::lock_guard<std::mutex> lock(mFilterThreadLock);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Filter::flush() {
+    ALOGV("%s", __FUNCTION__);
+
+    // temp implementation to flush the FMQ
+    int size = mFilterMQ->availableToRead();
+    char* buffer = new char[size];
+    mFilterMQ->read((unsigned char*)&buffer[0], size);
+    delete[] buffer;
+    mFilterStatus = DemuxFilterStatus::DATA_READY;
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Filter::releaseAvHandle(const hidl_handle& /*avMemory*/, uint64_t avDataId) {
+    ALOGV("%s", __FUNCTION__);
+    if (mDataId2Avfd.find(avDataId) == mDataId2Avfd.end()) {
+        return Result::INVALID_ARGUMENT;
+    }
+
+    ::close(mDataId2Avfd[avDataId]);
+    return Result::SUCCESS;
+}
+
+Return<Result> Filter::close() {
+    ALOGV("%s", __FUNCTION__);
+
+    return mDemux->removeFilter(mFilterId);
+}
+
+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(), &mFilterEventFlag) != OK) {
+        return false;
+    }
+
+    return true;
+}
+
+Result Filter::startFilterLoop() {
+    pthread_create(&mFilterThread, NULL, __threadLoopFilter, this);
+    pthread_setname_np(mFilterThread, "filter_waiting_loop");
+
+    return Result::SUCCESS;
+}
+
+void* Filter::__threadLoopFilter(void* user) {
+    Filter* const self = static_cast<Filter*>(user);
+    self->filterThreadLoop();
+    return 0;
+}
+
+void Filter::filterThreadLoop() {
+    ALOGD("[Filter] filter %" PRIu64 " threadLoop start.", mFilterId);
+    std::lock_guard<std::mutex> lock(mFilterThreadLock);
+    mFilterThreadRunning = true;
+
+    // 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) {
+        if (mFilterEvent.events.size() == 0 && mFilterEvent_1_1.events.size() == 0) {
+            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 (mFilterEvent_1_1.events.size() > 0) {
+            if (mCallback_1_1 == nullptr) {
+                ALOGE("[Filter] IFilterCallback_1_1 has not been configured yet. Can't send event");
+                mFilterThreadRunning = false;
+                break;
+            }
+            mCallback_1_1->onFilterEvent_1_1(mFilterEvent_1_1);
+            mFilterEvent_1_1.events.resize(0);
+        } else {
+            mCallback->onFilterEvent(mFilterEvent);
+            mFilterEvent.events.resize(0);
+        }
+
+        freeAvHandle();
+        mFilterStatus = DemuxFilterStatus::DATA_READY;
+        if (mCallback != nullptr) {
+            mCallback->onFilterStatus(mFilterStatus);
+        } else if (mCallback_1_1 != nullptr) {
+            mCallback_1_1->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++) {
+            while (mFilterThreadRunning && mIsUsingFMQ) {
+                status_t status = mFilterEventFlag->wait(
+                        static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState,
+                        WAIT_TIMEOUT, true /* retry on spurious wake */);
+                if (status != OK) {
+                    ALOGD("[Filter] wait for data consumed");
+                    continue;
+                }
+                break;
+            }
+
+            maySendFilterStatusCallback();
+
+            while (mFilterThreadRunning) {
+                std::lock_guard<std::mutex> lock(mFilterEventLock);
+                if (mFilterEvent.events.size() == 0) {
+                    continue;
+                }
+                // After successfully write, send a callback and wait for the read to be done
+                if (mCallback != nullptr) {
+                    mCallback->onFilterEvent(mFilterEvent);
+                    mFilterEvent.events.resize(0);
+                } else if (mCallback_1_1 != nullptr) {
+                    mCallback_1_1->onFilterEvent_1_1(mFilterEvent_1_1);
+                    mFilterEvent_1_1.events.resize(0);
+                }
+                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;
+            }
+        }
+        mFilterThreadRunning = false;
+    }
+
+    ALOGD("[Filter] filter thread ended.");
+}
+
+void Filter::freeAvHandle() {
+    if (!mIsMediaFilter) {
+        return;
+    }
+    for (int i = 0; i < mFilterEvent.events.size(); i++) {
+        ::close(mFilterEvent.events[i].media().avMemory.getNativeHandle()->data[0]);
+        native_handle_close(mFilterEvent.events[i].media().avMemory.getNativeHandle());
+    }
+}
+
+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) {
+        if (mCallback != nullptr) {
+            mCallback->onFilterStatus(newStatus);
+        } else if (mCallback_1_1 != nullptr) {
+            mCallback_1_1->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<uint8_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<uint8_t> data) {
+    std::lock_guard<std::mutex> lock(mRecordFilterOutputLock);
+    mRecordFilterOutput.insert(mRecordFilterOutput.end(), data.begin(), data.end());
+}
+
+Result Filter::startFilterHandler() {
+    std::lock_guard<std::mutex> lock(mFilterOutputLock);
+    switch (mType.mainType) {
+        case DemuxFilterMainType::TS:
+            switch (mType.subType.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 Result::SUCCESS;
+}
+
+Result Filter::startSectionFilterHandler() {
+    if (mFilterOutput.empty()) {
+        return Result::SUCCESS;
+    }
+    if (!writeSectionsAndCreateEvent(mFilterOutput)) {
+        ALOGD("[Filter] filter %" PRIu64 " fails to write into FMQ. Ending thread", mFilterId);
+        return Result::UNKNOWN_ERROR;
+    }
+
+    mFilterOutput.clear();
+
+    return Result::SUCCESS;
+}
+
+Result Filter::startPesFilterHandler() {
+    std::lock_guard<std::mutex> lock(mFilterEventLock);
+    if (mFilterOutput.empty()) {
+        return Result::SUCCESS;
+    }
+
+    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<uint8_t>::const_iterator first = mFilterOutput.begin() + i + 4;
+        vector<uint8_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 Result::INVALID_STATE;
+        }
+        maySendFilterStatusCallback();
+        DemuxFilterPesEvent pesEvent;
+        pesEvent = {
+                // temp dump meta data
+                .streamId = mPesOutput[3],
+                .dataLength = static_cast<uint16_t>(mPesOutput.size()),
+        };
+        if (DEBUG_FILTER) {
+            ALOGD("[Filter] assembled pes data length %d", pesEvent.dataLength);
+        }
+
+        int size = mFilterEvent.events.size();
+        mFilterEvent.events.resize(size + 1);
+        mFilterEvent.events[size].pes(pesEvent);
+        mPesOutput.clear();
+    }
+
+    mFilterOutput.clear();
+
+    return Result::SUCCESS;
+}
+
+Result Filter::startTsFilterHandler() {
+    // TODO handle starting TS filter
+    return Result::SUCCESS;
+}
+
+Result Filter::startMediaFilterHandler() {
+    std::lock_guard<std::mutex> lock(mFilterEventLock);
+    if (mFilterOutput.empty()) {
+        return Result::SUCCESS;
+    }
+
+    if (mPts) {
+        return createMediaFilterEventWithIon(mFilterOutput);
+    }
+
+    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<uint8_t>::const_iterator first = mFilterOutput.begin() + i + 4;
+        vector<uint8_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;
+        }
+
+        createMediaFilterEventWithIon(mPesOutput);
+    }
+
+    mFilterOutput.clear();
+
+    return Result::SUCCESS;
+}
+
+Result Filter::createMediaFilterEventWithIon(vector<uint8_t> output) {
+    int av_fd = createAvIonFd(output.size());
+    if (av_fd == -1) {
+        return Result::UNKNOWN_ERROR;
+    }
+    // copy the filtered data to the buffer
+    uint8_t* avBuffer = getIonBuffer(av_fd, output.size());
+    if (avBuffer == NULL) {
+        return Result::UNKNOWN_ERROR;
+    }
+    memcpy(avBuffer, output.data(), output.size() * sizeof(uint8_t));
+
+    native_handle_t* nativeHandle = createNativeHandle(av_fd);
+    if (nativeHandle == NULL) {
+        return Result::UNKNOWN_ERROR;
+    }
+    hidl_handle handle;
+    handle.setTo(nativeHandle, /*shouldOwn=*/true);
+
+    // 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
+    DemuxFilterMediaEvent mediaEvent;
+    mediaEvent = {
+            .avMemory = std::move(handle),
+            .dataLength = static_cast<uint32_t>(output.size()),
+            .avDataId = dataId,
+    };
+    if (mPts) {
+        mediaEvent.pts = mPts;
+        mPts = 0;
+    }
+    int size = mFilterEvent.events.size();
+    mFilterEvent.events.resize(size + 1);
+    mFilterEvent.events[size].media(mediaEvent);
+
+    // Clear and log
+    output.clear();
+    mAvBufferCopyCount = 0;
+    ::close(av_fd);
+    if (DEBUG_FILTER) {
+        ALOGD("[Filter] av data length %d", mediaEvent.dataLength);
+    }
+    return Result::SUCCESS;
+}
+
+Result Filter::startRecordFilterHandler() {
+    std::lock_guard<std::mutex> lock(mRecordFilterOutputLock);
+    if (mRecordFilterOutput.empty()) {
+        return Result::SUCCESS;
+    }
+
+    if (mDvr == nullptr || !mDvr->writeRecordFMQ(mRecordFilterOutput)) {
+        ALOGD("[Filter] dvr fails to write into record FMQ.");
+        return Result::UNKNOWN_ERROR;
+    }
+
+    V1_0::DemuxFilterTsRecordEvent recordEvent;
+    recordEvent = {
+            .byteNumber = mRecordFilterOutput.size(),
+    };
+    V1_1::DemuxFilterTsRecordEvent recordEvent_1_1;
+    recordEvent_1_1 = {
+            .tsRecordEvent_1_0 = recordEvent,
+            .pts = (mPts == 0) ? time(NULL) * 900000 : mPts,
+    };
+
+    int size;
+    if (mCallback_1_1 != nullptr) {
+        size = mFilterEvent_1_1.events.size();
+        mFilterEvent_1_1.events.resize(size + 1);
+        mFilterEvent_1_1.events[size].tsRecord(recordEvent_1_1);
+    } else if (mCallback != nullptr) {
+        size = mFilterEvent.events.size();
+        mFilterEvent.events.resize(size + 1);
+        mFilterEvent.events[size].tsRecord(recordEvent);
+    }
+
+    mRecordFilterOutput.clear();
+    return Result::SUCCESS;
+}
+
+Result Filter::startPcrFilterHandler() {
+    // TODO handle starting PCR filter
+    return Result::SUCCESS;
+}
+
+Result Filter::startTemiFilterHandler() {
+    // TODO handle starting TEMI filter
+    return Result::SUCCESS;
+}
+
+bool Filter::writeSectionsAndCreateEvent(vector<uint8_t> data) {
+    // TODO check how many sections has been read
+    ALOGD("[Filter] section handler");
+    std::lock_guard<std::mutex> lock(mFilterEventLock);
+    if (!writeDataToFilterMQ(data)) {
+        return false;
+    }
+    int size = mFilterEvent.events.size();
+    mFilterEvent.events.resize(size + 1);
+    DemuxFilterSectionEvent secEvent;
+    secEvent = {
+            // temp dump meta data
+            .tableId = 0,
+            .version = 1,
+            .sectionNum = 1,
+            .dataLength = static_cast<uint16_t>(data.size()),
+    };
+    mFilterEvent.events[size].section(secEvent);
+    return true;
+}
+
+bool Filter::writeDataToFilterMQ(const std::vector<uint8_t>& data) {
+    std::lock_guard<std::mutex> lock(mWriteLock);
+    if (mFilterMQ->write(data.data(), data.size())) {
+        return true;
+    }
+    return false;
+}
+
+void Filter::attachFilterToRecord(const sp<Dvr> dvr) {
+    mDvr = dvr;
+}
+
+void Filter::detachFilterFromRecord() {
+    mDvr = nullptr;
+}
+
+int Filter::createAvIonFd(int size) {
+    // Create an ion fd and allocate an av fd mapped to a buffer to it.
+    int ion_fd = ion_open();
+    if (ion_fd == -1) {
+        ALOGE("[Filter] Failed to open ion fd %d", errno);
+        return -1;
+    }
+    int av_fd = -1;
+    ion_alloc_fd(dup(ion_fd), size, 0 /*align*/, ION_HEAP_SYSTEM_MASK, 0 /*flags*/, &av_fd);
+    if (av_fd == -1) {
+        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) {
+    // Create a native handle to pass the av fd via the callback event.
+    native_handle_t* nativeHandle = native_handle_create(/*numFd*/ 1, 0);
+    if (nativeHandle == NULL) {
+        ALOGE("[Filter] Failed to create native_handle %d", errno);
+        return NULL;
+    }
+    nativeHandle->data[0] = dup(fd);
+    return nativeHandle;
+}
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/tuner/1.1/default/Filter.h b/tv/tuner/1.1/default/Filter.h
new file mode 100644
index 0000000..8e6fe38
--- /dev/null
+++ b/tv/tuner/1.1/default/Filter.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_TUNER_V1_1_FILTER_H_
+#define ANDROID_HARDWARE_TV_TUNER_V1_1_FILTER_H_
+
+#include <android/hardware/tv/tuner/1.1/IFilter.h>
+#include <android/hardware/tv/tuner/1.1/IFilterCallback.h>
+#include <fmq/MessageQueue.h>
+#include <inttypes.h>
+#include <ion/ion.h>
+#include <math.h>
+#include <set>
+#include "Demux.h"
+#include "Dvr.h"
+#include "Frontend.h"
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::EventFlag;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::MQDescriptorSync;
+
+using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+class Demux;
+class Dvr;
+
+class Filter : public V1_1::IFilter {
+  public:
+    Filter();
+
+    Filter(DemuxFilterType type, uint64_t filterId, uint32_t bufferSize,
+           const sp<IFilterCallback>& cb, sp<Demux> demux);
+
+    ~Filter();
+
+    virtual Return<void> getId64Bit(getId64Bit_cb _hidl_cb) override;
+
+    virtual Return<void> getId(getId_cb _hidl_cb) override;
+
+    virtual Return<Result> setDataSource(const sp<V1_0::IFilter>& filter) override;
+
+    virtual Return<void> getQueueDesc(getQueueDesc_cb _hidl_cb) override;
+
+    virtual Return<Result> configure(const DemuxFilterSettings& settings) override;
+
+    virtual Return<Result> start() override;
+
+    virtual Return<Result> stop() override;
+
+    virtual Return<Result> flush() override;
+
+    virtual Return<Result> releaseAvHandle(const hidl_handle& avMemory, uint64_t avDataId) override;
+
+    virtual Return<Result> close() 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<uint8_t> data);
+    void updateRecordOutput(vector<uint8_t> data);
+    void updatePts(uint64_t pts);
+    Result startFilterHandler();
+    Result startRecordFilterHandler();
+    void attachFilterToRecord(const sp<Dvr> dvr);
+    void detachFilterFromRecord();
+    void freeAvHandle();
+    bool isMediaFilter() { return mIsMediaFilter; };
+    bool isPcrFilter() { return mIsPcrFilter; };
+    bool isRecordFilter() { return mIsRecordFilter; };
+
+  private:
+    // Tuner service
+    sp<Demux> mDemux;
+    // Dvr reference once the filter is attached to any
+    sp<Dvr> mDvr = nullptr;
+    /**
+     * Filter callbacks used on filter events or FMQ status
+     */
+    sp<IFilterCallback> mCallback = nullptr;
+
+    /**
+     * V1_1 Filter callbacks used on filter events or FMQ status
+     */
+    sp<V1_1::IFilterCallback> mCallback_1_1 = nullptr;
+
+    uint64_t mFilterId;
+    uint32_t mBufferSize;
+    DemuxFilterType mType;
+    bool mIsMediaFilter = false;
+    bool mIsPcrFilter = false;
+    bool mIsRecordFilter = false;
+    DemuxFilterSettings mFilterSettings;
+
+    uint16_t mTpid;
+    sp<V1_0::IFilter> mDataSource;
+    bool mIsDataSourceDemux = true;
+    vector<uint8_t> mFilterOutput;
+    vector<uint8_t> mRecordFilterOutput;
+    uint64_t mPts = 0;
+    unique_ptr<FilterMQ> mFilterMQ;
+    bool mIsUsingFMQ = false;
+    EventFlag* mFilterEventFlag;
+    DemuxFilterEvent mFilterEvent;
+    V1_1::DemuxFilterEvent mFilterEvent_1_1;
+
+    // Thread handlers
+    pthread_t mFilterThread;
+
+    // FMQ status local records
+    DemuxFilterStatus mFilterStatus;
+    /**
+     * If a specific filter's writing loop is still running
+     */
+    bool mFilterThreadRunning;
+    bool mKeepFetchingDataFromFrontend;
+
+    /**
+     * 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.
+     */
+    Result startSectionFilterHandler();
+    Result startPesFilterHandler();
+    Result startTsFilterHandler();
+    Result startMediaFilterHandler();
+    Result startPcrFilterHandler();
+    Result startTemiFilterHandler();
+    Result startFilterLoop();
+
+    void deleteEventFlag();
+    bool writeDataToFilterMQ(const std::vector<uint8_t>& data);
+    bool readDataFromMQ();
+    bool writeSectionsAndCreateEvent(vector<uint8_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.
+     */
+    void startTsFilter(vector<uint8_t> data);
+    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);
+    Result createMediaFilterEventWithIon(vector<uint8_t> output);
+
+    /**
+     * 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 mFilterEventLock;
+    /**
+     * Lock to protect writes to the input status
+     */
+    std::mutex mFilterStatusLock;
+    std::mutex mFilterThreadLock;
+    std::mutex mFilterOutputLock;
+    std::mutex mRecordFilterOutputLock;
+
+    // temp handle single PES filter
+    // TODO handle mulptiple Pes filters
+    int mPesSizeLeft = 0;
+    vector<uint8_t> mPesOutput;
+
+    // A map from data id to ion handle
+    std::map<uint64_t, int> mDataId2Avfd;
+    uint64_t mLastUsedDataId = 1;
+    int mAvBufferCopyCount = 0;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TV_TUNER_V1_1_FILTER_H_
diff --git a/tv/tuner/1.1/default/Frontend.cpp b/tv/tuner/1.1/default/Frontend.cpp
new file mode 100644
index 0000000..6f5885f
--- /dev/null
+++ b/tv/tuner/1.1/default/Frontend.cpp
@@ -0,0 +1,285 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv.tuner@1.1-Frontend"
+
+#include "Frontend.h"
+#include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+Frontend::Frontend(FrontendType type, FrontendId id, sp<Tuner> tuner) {
+    mType = type;
+    mId = id;
+    mTunerService = tuner;
+    // Init callback to nullptr
+    mCallback = nullptr;
+}
+
+Frontend::~Frontend() {}
+
+Return<Result> Frontend::close() {
+    ALOGV("%s", __FUNCTION__);
+    // Reset callback
+    mCallback = nullptr;
+    mIsLocked = false;
+    mTunerService->removeFrontend(mId);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Frontend::setCallback(const sp<IFrontendCallback>& callback) {
+    ALOGV("%s", __FUNCTION__);
+    if (callback == nullptr) {
+        ALOGW("[   WARN   ] Set Frontend callback with nullptr");
+        return Result::INVALID_ARGUMENT;
+    }
+
+    mCallback = callback;
+    return Result::SUCCESS;
+}
+
+Return<Result> Frontend::tune(const FrontendSettings& /* settings */) {
+    ALOGV("%s", __FUNCTION__);
+    if (mCallback == nullptr) {
+        ALOGW("[   WARN   ] Frontend callback is not set when tune");
+        return Result::INVALID_STATE;
+    }
+
+    mTunerService->frontendStartTune(mId);
+    mCallback->onEvent(FrontendEventType::LOCKED);
+    mIsLocked = true;
+    return Result::SUCCESS;
+}
+
+Return<Result> Frontend::stopTune() {
+    ALOGV("%s", __FUNCTION__);
+
+    mTunerService->frontendStopTune(mId);
+    mIsLocked = false;
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Frontend::scan(const FrontendSettings& settings, FrontendScanType type) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (mType == FrontendType::ATSC) {
+        FrontendScanMessage msg;
+        msg.isLocked(true);
+        mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg);
+        mIsLocked = true;
+        return Result::SUCCESS;
+    }
+    if (mType != FrontendType::DVBT) {
+        return Result::UNAVAILABLE;
+    }
+
+    FrontendScanMessage msg;
+
+    if (mIsLocked) {
+        msg.isEnd(true);
+        mCallback->onScanMessage(FrontendScanMessageType::END, msg);
+        return Result::SUCCESS;
+    }
+
+    uint32_t frequency = settings.dvbt().frequency;
+    if (type == FrontendScanType::SCAN_BLIND) {
+        frequency += 100;
+    }
+    msg.frequencies({frequency});
+    mCallback->onScanMessage(FrontendScanMessageType::FREQUENCY, msg);
+    msg.isLocked(true);
+    mCallback->onScanMessage(FrontendScanMessageType::LOCKED, msg);
+    mIsLocked = true;
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Frontend::stopScan() {
+    ALOGV("%s", __FUNCTION__);
+
+    mIsLocked = false;
+    return Result::SUCCESS;
+}
+
+Return<void> Frontend::getStatus(const hidl_vec<FrontendStatusType>& statusTypes,
+                                 getStatus_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    vector<FrontendStatus> statuses;
+    for (int i = 0; i < statusTypes.size(); i++) {
+        FrontendStatusType type = statusTypes[i];
+        FrontendStatus status;
+        // assign randomly selected values for testing.
+        switch (type) {
+            case FrontendStatusType::DEMOD_LOCK: {
+                status.isDemodLocked(true);
+                break;
+            }
+            case FrontendStatusType::SNR: {
+                status.snr(221);
+                break;
+            }
+            case FrontendStatusType::BER: {
+                status.ber(1);
+                break;
+            }
+            case FrontendStatusType::PER: {
+                status.per(2);
+                break;
+            }
+            case FrontendStatusType::PRE_BER: {
+                status.preBer(3);
+                break;
+            }
+            case FrontendStatusType::SIGNAL_QUALITY: {
+                status.signalQuality(4);
+                break;
+            }
+            case FrontendStatusType::SIGNAL_STRENGTH: {
+                status.signalStrength(5);
+                break;
+            }
+            case FrontendStatusType::SYMBOL_RATE: {
+                status.symbolRate(6);
+                break;
+            }
+            case FrontendStatusType::FEC: {
+                status.innerFec(FrontendInnerFec::FEC_2_9);  // value = 1 << 7
+                break;
+            }
+            case FrontendStatusType::MODULATION: {
+                FrontendModulationStatus modulationStatus;
+                modulationStatus.isdbt(FrontendIsdbtModulation::MOD_16QAM);  // value = 1 << 3
+                status.modulation(modulationStatus);
+                break;
+            }
+            case FrontendStatusType::SPECTRAL: {
+                status.inversion(FrontendDvbcSpectralInversion::NORMAL);
+                break;
+            }
+            case FrontendStatusType::LNB_VOLTAGE: {
+                status.lnbVoltage(LnbVoltage::VOLTAGE_5V);
+                break;
+            }
+            case FrontendStatusType::PLP_ID: {
+                status.plpId(101);  // type uint8_t
+                break;
+            }
+            case FrontendStatusType::EWBS: {
+                status.isEWBS(false);
+                break;
+            }
+            case FrontendStatusType::AGC: {
+                status.agc(7);
+                break;
+            }
+            case FrontendStatusType::LNA: {
+                status.isLnaOn(false);
+                break;
+            }
+            case FrontendStatusType::LAYER_ERROR: {
+                vector<bool> v = {false, true, true};
+                status.isLayerError(v);
+                break;
+            }
+            case FrontendStatusType::MER: {
+                status.mer(8);
+                break;
+            }
+            case FrontendStatusType::FREQ_OFFSET: {
+                status.freqOffset(9);
+                break;
+            }
+            case FrontendStatusType::HIERARCHY: {
+                status.hierarchy(FrontendDvbtHierarchy::HIERARCHY_1_NATIVE);
+                break;
+            }
+            case FrontendStatusType::RF_LOCK: {
+                status.isRfLocked(false);
+                break;
+            }
+            case FrontendStatusType::ATSC3_PLP_INFO: {
+                vector<FrontendStatusAtsc3PlpInfo> v;
+                FrontendStatusAtsc3PlpInfo info1{
+                        .plpId = 3,
+                        .isLocked = false,
+                        .uec = 313,
+                };
+                FrontendStatusAtsc3PlpInfo info2{
+                        .plpId = 5,
+                        .isLocked = true,
+                        .uec = 515,
+                };
+                v.push_back(info1);
+                v.push_back(info2);
+                status.plpInfo(v);
+                break;
+            }
+            default: {
+                continue;
+            }
+        }
+        statuses.push_back(status);
+    }
+    _hidl_cb(Result::SUCCESS, statuses);
+
+    return Void();
+}
+
+Return<Result> Frontend::setLna(bool /* bEnable */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Frontend::setLnb(uint32_t /* lnb */) {
+    ALOGV("%s", __FUNCTION__);
+    if (!supportsSatellite()) {
+        return Result::INVALID_STATE;
+    }
+    return Result::SUCCESS;
+}
+
+FrontendType Frontend::getFrontendType() {
+    return mType;
+}
+
+FrontendId Frontend::getFrontendId() {
+    return mId;
+}
+
+bool Frontend::supportsSatellite() {
+    return mType == FrontendType::DVBS || mType == FrontendType::ISDBS ||
+           mType == FrontendType::ISDBS3;
+}
+
+bool Frontend::isLocked() {
+    return mIsLocked;
+}
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/tuner/1.1/default/Frontend.h b/tv/tuner/1.1/default/Frontend.h
new file mode 100644
index 0000000..89b4a6b
--- /dev/null
+++ b/tv/tuner/1.1/default/Frontend.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_TUNER_V1_1_FRONTEND_H_
+#define ANDROID_HARDWARE_TV_TUNER_V1_1_FRONTEND_H_
+
+#include <fstream>
+#include <iostream>
+#include "Tuner.h"
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+class Tuner;
+
+class Frontend : public IFrontend {
+  public:
+    Frontend(FrontendType type, FrontendId id, sp<Tuner> tuner);
+
+    virtual Return<Result> close() override;
+
+    virtual Return<Result> setCallback(const sp<IFrontendCallback>& callback) override;
+
+    virtual Return<Result> tune(const FrontendSettings& settings) override;
+
+    virtual Return<Result> stopTune() override;
+
+    virtual Return<Result> scan(const FrontendSettings& settings, FrontendScanType type) override;
+
+    virtual Return<Result> stopScan() override;
+
+    virtual Return<void> getStatus(const hidl_vec<FrontendStatusType>& statusTypes,
+                                   getStatus_cb _hidl_cb) override;
+
+    virtual Return<Result> setLna(bool bEnable) override;
+
+    virtual Return<Result> setLnb(uint32_t lnb) override;
+
+    FrontendType getFrontendType();
+
+    FrontendId getFrontendId();
+
+    string getSourceFile();
+
+    bool isLocked();
+
+  private:
+    virtual ~Frontend();
+    bool supportsSatellite();
+    sp<IFrontendCallback> mCallback;
+    sp<Tuner> mTunerService;
+    FrontendType mType = FrontendType::UNDEFINED;
+    FrontendId mId = 0;
+    bool mIsLocked = false;
+
+    std::ifstream mFrontendData;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TV_TUNER_V1_1_FRONTEND_H_
diff --git a/tv/tuner/1.1/default/Lnb.cpp b/tv/tuner/1.1/default/Lnb.cpp
new file mode 100644
index 0000000..044727f
--- /dev/null
+++ b/tv/tuner/1.1/default/Lnb.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv.tuner@1.1-Lnb"
+
+#include "Lnb.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+Lnb::Lnb() {}
+Lnb::Lnb(int id) {
+    mId = id;
+}
+
+Lnb::~Lnb() {}
+
+Return<Result> Lnb::setCallback(const sp<ILnbCallback>& /* callback */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Lnb::setVoltage(LnbVoltage /* voltage */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Lnb::setTone(LnbTone /* tone */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Lnb::setSatellitePosition(LnbPosition /* position */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Lnb::sendDiseqcMessage(const hidl_vec<uint8_t>& /* diseqcMessage */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Lnb::close() {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+int Lnb::getId() {
+    return mId;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/tuner/1.1/default/Lnb.h b/tv/tuner/1.1/default/Lnb.h
new file mode 100644
index 0000000..70a8e41
--- /dev/null
+++ b/tv/tuner/1.1/default/Lnb.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_TUNER_V1_1_LNB_H_
+#define ANDROID_HARDWARE_TV_TUNER_V1_1_LNB_H_
+
+#include <android/hardware/tv/tuner/1.0/ILnb.h>
+#include <android/hardware/tv/tuner/1.1/ITuner.h>
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+class Lnb : public ILnb {
+  public:
+    Lnb();
+    Lnb(int id);
+
+    virtual Return<Result> setCallback(const sp<ILnbCallback>& callback) override;
+
+    virtual Return<Result> setVoltage(LnbVoltage voltage) override;
+
+    virtual Return<Result> setTone(LnbTone tone) override;
+
+    virtual Return<Result> setSatellitePosition(LnbPosition position) override;
+
+    virtual Return<Result> sendDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) override;
+
+    virtual Return<Result> close() override;
+
+    int getId();
+
+  private:
+    int mId;
+    virtual ~Lnb();
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TV_TUNER_V1_1_LNB_H_
diff --git a/tv/tuner/1.1/default/OWNERS b/tv/tuner/1.1/default/OWNERS
new file mode 100644
index 0000000..1b3d095
--- /dev/null
+++ b/tv/tuner/1.1/default/OWNERS
@@ -0,0 +1,4 @@
+nchalko@google.com
+amyjojo@google.com
+shubang@google.com
+quxiangfang@google.com
diff --git a/tv/tuner/1.1/default/TimeFilter.cpp b/tv/tuner/1.1/default/TimeFilter.cpp
new file mode 100644
index 0000000..bb243a6
--- /dev/null
+++ b/tv/tuner/1.1/default/TimeFilter.cpp
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv.tuner@1.1-TimeFilter"
+
+#include "TimeFilter.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+TimeFilter::TimeFilter() {}
+
+TimeFilter::TimeFilter(sp<Demux> demux) {
+    mDemux = demux;
+}
+
+TimeFilter::~TimeFilter() {}
+
+Return<Result> TimeFilter::setTimeStamp(uint64_t timeStamp) {
+    ALOGV("%s", __FUNCTION__);
+    if (timeStamp == INVALID_TIME_STAMP) {
+        return Result::INVALID_ARGUMENT;
+    }
+    mTimeStamp = timeStamp;
+    mBeginTime = time(NULL);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> TimeFilter::clearTimeStamp() {
+    ALOGV("%s", __FUNCTION__);
+    mTimeStamp = INVALID_TIME_STAMP;
+
+    return Result::SUCCESS;
+}
+
+Return<void> TimeFilter::getTimeStamp(getTimeStamp_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+    if (mTimeStamp == INVALID_TIME_STAMP) {
+        _hidl_cb(Result::INVALID_STATE, mTimeStamp);
+    }
+
+    uint64_t currentTimeStamp = mTimeStamp + difftime(time(NULL), mBeginTime) * 900000;
+    _hidl_cb(Result::SUCCESS, currentTimeStamp);
+    return Void();
+}
+
+Return<void> TimeFilter::getSourceTime(getSourceTime_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    uint64_t time = 0;
+
+    _hidl_cb(Result::SUCCESS, time);
+    return Void();
+}
+
+Return<Result> TimeFilter::close() {
+    ALOGV("%s", __FUNCTION__);
+    mTimeStamp = INVALID_TIME_STAMP;
+
+    return Result::SUCCESS;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
\ No newline at end of file
diff --git a/tv/tuner/1.1/default/TimeFilter.h b/tv/tuner/1.1/default/TimeFilter.h
new file mode 100644
index 0000000..d53ad2c
--- /dev/null
+++ b/tv/tuner/1.1/default/TimeFilter.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_TUNER_V1_1_TIMEFILTER_H_
+#define ANDROID_HARDWARE_TV_TUNER_V1_1_TIMEFILTER_H_
+
+#include <android/hardware/tv/tuner/1.0/ITimeFilter.h>
+#include "Demux.h"
+#include "time.h"
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+#define INVALID_TIME_STAMP -1
+
+class Demux;
+
+class TimeFilter : public ITimeFilter {
+  public:
+    TimeFilter();
+
+    TimeFilter(sp<Demux> demux);
+
+    ~TimeFilter();
+
+    virtual Return<Result> setTimeStamp(uint64_t timeStamp) override;
+
+    virtual Return<Result> clearTimeStamp() override;
+
+    virtual Return<void> getTimeStamp(getTimeStamp_cb _hidl_cb) override;
+
+    virtual Return<void> getSourceTime(getSourceTime_cb _hidl_cb) override;
+
+    virtual Return<Result> close() override;
+
+  private:
+    sp<Demux> mDemux;
+    uint64_t mTimeStamp = INVALID_TIME_STAMP;
+    time_t mBeginTime;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TV_TUNER_V1_1_TIMEFILTER_H_
\ No newline at end of file
diff --git a/tv/tuner/1.1/default/Tuner.cpp b/tv/tuner/1.1/default/Tuner.cpp
new file mode 100644
index 0000000..87a4d36
--- /dev/null
+++ b/tv/tuner/1.1/default/Tuner.cpp
@@ -0,0 +1,272 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv.tuner@1.1-Tuner"
+
+#include "Tuner.h"
+#include <utils/Log.h>
+#include "Demux.h"
+#include "Descrambler.h"
+#include "Frontend.h"
+#include "Lnb.h"
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+Tuner::Tuner() {
+    // Static Frontends array to maintain local frontends information
+    // Array index matches their FrontendId in the default impl
+    mFrontendSize = 8;
+    mFrontends[0] = new Frontend(FrontendType::DVBT, 0, this);
+    mFrontends[1] = new Frontend(FrontendType::ATSC, 1, this);
+    mFrontends[2] = new Frontend(FrontendType::DVBC, 2, this);
+    mFrontends[3] = new Frontend(FrontendType::DVBS, 3, this);
+    mFrontends[4] = new Frontend(FrontendType::DVBT, 4, this);
+    mFrontends[5] = new Frontend(FrontendType::ISDBT, 5, this);
+    mFrontends[6] = new Frontend(FrontendType::ANALOG, 6, this);
+    mFrontends[7] = new Frontend(FrontendType::ATSC, 7, this);
+
+    FrontendInfo::FrontendCapabilities caps;
+    caps = FrontendInfo::FrontendCapabilities();
+    caps.dvbtCaps(FrontendDvbtCapabilities());
+    mFrontendCaps[0] = caps;
+
+    caps = FrontendInfo::FrontendCapabilities();
+    caps.atscCaps(FrontendAtscCapabilities());
+    mFrontendCaps[1] = caps;
+
+    caps = FrontendInfo::FrontendCapabilities();
+    caps.dvbcCaps(FrontendDvbcCapabilities());
+    mFrontendCaps[2] = caps;
+
+    caps = FrontendInfo::FrontendCapabilities();
+    caps.dvbsCaps(FrontendDvbsCapabilities());
+    mFrontendCaps[3] = caps;
+
+    caps = FrontendInfo::FrontendCapabilities();
+    caps.dvbtCaps(FrontendDvbtCapabilities());
+    mFrontendCaps[4] = caps;
+
+    caps = FrontendInfo::FrontendCapabilities();
+    FrontendIsdbtCapabilities isdbtCaps{
+            .modeCap = FrontendIsdbtMode::MODE_1 | FrontendIsdbtMode::MODE_2,
+            .bandwidthCap = (unsigned int)FrontendIsdbtBandwidth::BANDWIDTH_6MHZ,
+            .modulationCap = (unsigned int)FrontendIsdbtModulation::MOD_16QAM,
+            // ISDBT shares coderate and guard interval with DVBT
+            .coderateCap = FrontendDvbtCoderate::CODERATE_4_5 | FrontendDvbtCoderate::CODERATE_6_7,
+            .guardIntervalCap = (unsigned int)FrontendDvbtGuardInterval::INTERVAL_1_128,
+    };
+    caps.isdbtCaps(isdbtCaps);
+    mFrontendCaps[5] = caps;
+
+    caps = FrontendInfo::FrontendCapabilities();
+    caps.analogCaps(FrontendAnalogCapabilities());
+    mFrontendCaps[6] = caps;
+
+    caps = FrontendInfo::FrontendCapabilities();
+    caps.atscCaps(FrontendAtscCapabilities());
+    mFrontendCaps[7] = caps;
+
+    mLnbs.resize(2);
+    mLnbs[0] = new Lnb(0);
+    mLnbs[1] = new Lnb(1);
+}
+
+Tuner::~Tuner() {}
+
+Return<void> Tuner::getFrontendIds(getFrontendIds_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    vector<FrontendId> frontendIds;
+    frontendIds.resize(mFrontendSize);
+    for (int i = 0; i < mFrontendSize; i++) {
+        frontendIds[i] = mFrontends[i]->getFrontendId();
+    }
+
+    _hidl_cb(Result::SUCCESS, frontendIds);
+    return Void();
+}
+
+Return<void> Tuner::openFrontendById(uint32_t frontendId, openFrontendById_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (frontendId >= mFrontendSize || frontendId < 0) {
+        ALOGW("[   WARN   ] Frontend with id %d isn't available", frontendId);
+        _hidl_cb(Result::UNAVAILABLE, nullptr);
+        return Void();
+    }
+
+    _hidl_cb(Result::SUCCESS, mFrontends[frontendId]);
+    return Void();
+}
+
+Return<void> Tuner::openDemux(openDemux_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    uint32_t demuxId = mLastUsedId + 1;
+    mLastUsedId += 1;
+    sp<Demux> demux = new Demux(demuxId, this);
+    mDemuxes[demuxId] = demux;
+
+    _hidl_cb(Result::SUCCESS, demuxId, demux);
+    return Void();
+}
+
+Return<void> Tuner::getDemuxCaps(getDemuxCaps_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    DemuxCapabilities caps;
+
+    // IP filter can be an MMTP filter's data source.
+    caps.linkCaps = {0x00, 0x00, 0x02, 0x00, 0x00};
+    _hidl_cb(Result::SUCCESS, caps);
+    return Void();
+}
+
+Return<void> Tuner::openDescrambler(openDescrambler_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    sp<V1_0::IDescrambler> descrambler = new Descrambler();
+
+    _hidl_cb(Result::SUCCESS, descrambler);
+    return Void();
+}
+
+Return<void> Tuner::getFrontendInfo(FrontendId frontendId, getFrontendInfo_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    FrontendInfo info;
+    if (frontendId >= mFrontendSize) {
+        _hidl_cb(Result::INVALID_ARGUMENT, info);
+        return Void();
+    }
+
+    vector<FrontendStatusType> statusCaps = {
+            FrontendStatusType::DEMOD_LOCK,
+            FrontendStatusType::SNR,
+            FrontendStatusType::FEC,
+            FrontendStatusType::MODULATION,
+            FrontendStatusType::PLP_ID,
+            FrontendStatusType::LAYER_ERROR,
+            FrontendStatusType::ATSC3_PLP_INFO,
+    };
+    // assign randomly selected values for testing.
+    info = {
+            .type = mFrontends[frontendId]->getFrontendType(),
+            .minFrequency = 139,
+            .maxFrequency = 1139,
+            .minSymbolRate = 45,
+            .maxSymbolRate = 1145,
+            .acquireRange = 30,
+            .exclusiveGroupId = 57,
+            .statusCaps = statusCaps,
+            .frontendCaps = mFrontendCaps[frontendId],
+    };
+
+    _hidl_cb(Result::SUCCESS, info);
+    return Void();
+}
+
+Return<void> Tuner::getLnbIds(getLnbIds_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    vector<V1_0::LnbId> lnbIds;
+    lnbIds.resize(mLnbs.size());
+    for (int i = 0; i < lnbIds.size(); i++) {
+        lnbIds[i] = mLnbs[i]->getId();
+    }
+
+    _hidl_cb(Result::SUCCESS, lnbIds);
+    return Void();
+}
+
+Return<void> Tuner::openLnbById(V1_0::LnbId lnbId, openLnbById_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (lnbId >= mLnbs.size()) {
+        _hidl_cb(Result::INVALID_ARGUMENT, nullptr);
+        return Void();
+    }
+
+    _hidl_cb(Result::SUCCESS, mLnbs[lnbId]);
+    return Void();
+}
+
+sp<Frontend> Tuner::getFrontendById(uint32_t frontendId) {
+    ALOGV("%s", __FUNCTION__);
+
+    return mFrontends[frontendId];
+}
+
+Return<void> Tuner::openLnbByName(const hidl_string& /*lnbName*/, openLnbByName_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    sp<V1_0::ILnb> lnb = new Lnb();
+
+    _hidl_cb(Result::SUCCESS, 1234, lnb);
+    return Void();
+}
+
+void Tuner::setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId) {
+    mFrontendToDemux[frontendId] = demuxId;
+    if (mFrontends[frontendId] != nullptr && mFrontends[frontendId]->isLocked()) {
+        mDemuxes[demuxId]->startFrontendInputLoop();
+    }
+}
+
+void Tuner::removeDemux(uint32_t demuxId) {
+    map<uint32_t, uint32_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(uint32_t frontendId) {
+    mFrontendToDemux.erase(frontendId);
+}
+
+void Tuner::frontendStopTune(uint32_t frontendId) {
+    map<uint32_t, uint32_t>::iterator it = mFrontendToDemux.find(frontendId);
+    uint32_t demuxId;
+    if (it != mFrontendToDemux.end()) {
+        demuxId = it->second;
+        mDemuxes[demuxId]->stopFrontendInput();
+    }
+}
+
+void Tuner::frontendStartTune(uint32_t frontendId) {
+    map<uint32_t, uint32_t>::iterator it = mFrontendToDemux.find(frontendId);
+    uint32_t demuxId;
+    if (it != mFrontendToDemux.end()) {
+        demuxId = it->second;
+        mDemuxes[demuxId]->startFrontendInputLoop();
+    }
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/tuner/1.1/default/Tuner.h b/tv/tuner/1.1/default/Tuner.h
new file mode 100644
index 0000000..3b1574b
--- /dev/null
+++ b/tv/tuner/1.1/default/Tuner.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_TUNER_V1_1_TUNER_H_
+#define ANDROID_HARDWARE_TV_TUNER_V1_1_TUNER_H_
+
+#include <android/hardware/tv/tuner/1.1/ITuner.h>
+#include <map>
+#include "Demux.h"
+#include "Frontend.h"
+#include "Lnb.h"
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::tv::tuner::V1_1::ITuner;
+
+class Frontend;
+class Demux;
+class Lnb;
+
+class Tuner : public ITuner {
+  public:
+    Tuner();
+
+    virtual Return<void> getFrontendIds(getFrontendIds_cb _hidl_cb) override;
+
+    virtual Return<void> openFrontendById(uint32_t frontendId,
+                                          openFrontendById_cb _hidl_cb) override;
+
+    virtual Return<void> openDemux(openDemux_cb _hidl_cb) override;
+
+    virtual Return<void> getDemuxCaps(getDemuxCaps_cb _hidl_cb) override;
+
+    virtual Return<void> openDescrambler(openDescrambler_cb _hidl_cb) override;
+
+    virtual Return<void> getFrontendInfo(uint32_t frontendId, getFrontendInfo_cb _hidl_cb) override;
+
+    virtual Return<void> getLnbIds(getLnbIds_cb _hidl_cb) override;
+
+    virtual Return<void> openLnbById(uint32_t lnbId, openLnbById_cb _hidl_cb) override;
+
+    virtual Return<void> openLnbByName(const hidl_string& lnbName,
+                                       openLnbByName_cb _hidl_cb) override;
+
+    sp<Frontend> getFrontendById(uint32_t frontendId);
+
+    void setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId);
+
+    void frontendStartTune(uint32_t frontendId);
+    void frontendStopTune(uint32_t frontendId);
+    void removeDemux(uint32_t demuxId);
+    void removeFrontend(uint32_t frontendId);
+
+  private:
+    virtual ~Tuner();
+    // Static mFrontends array to maintain local frontends information
+    map<uint32_t, sp<Frontend>> mFrontends;
+    map<uint32_t, FrontendInfo::FrontendCapabilities> mFrontendCaps;
+    map<uint32_t, uint32_t> mFrontendToDemux;
+    map<uint32_t, sp<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.
+    uint32_t mLastUsedId = -1;
+    vector<sp<Lnb>> mLnbs;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TV_TUNER_V1_1_TUNER_H_
diff --git a/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service-lazy.rc b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service-lazy.rc
new file mode 100644
index 0000000..abff430
--- /dev/null
+++ b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service-lazy.rc
@@ -0,0 +1,10 @@
+service vendor.tuner-hal-1-1 /vendor/bin/hw/android.hardware.tv.tuner@1.1-service-lazy
+    interface android.hardware.tv.tuner@1.0::ITuner default
+    interface android.hardware.tv.tuner@1.1::ITuner default
+    oneshot
+    disabled
+    class hal
+    user media
+    group mediadrm drmrpc
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks
\ No newline at end of file
diff --git a/wifi/1.4/default/android.hardware.wifi@1.0-service.xml b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service-lazy.xml
similarity index 64%
copy from wifi/1.4/default/android.hardware.wifi@1.0-service.xml
copy to tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service-lazy.xml
index b5d25cd..86b0445 100644
--- a/wifi/1.4/default/android.hardware.wifi@1.0-service.xml
+++ b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service-lazy.xml
@@ -1,11 +1,11 @@
 <manifest version="1.0" type="device">
     <hal format="hidl">
-        <name>android.hardware.wifi</name>
+        <name>android.hardware.tv.tuner</name>
         <transport>hwbinder</transport>
-        <version>1.4</version>
+        <version>1.1</version>
         <interface>
-            <name>IWifi</name>
+            <name>ITuner</name>
             <instance>default</instance>
         </interface>
     </hal>
-</manifest>
+</manifest>
\ No newline at end of file
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
new file mode 100644
index 0000000..3718a93
--- /dev/null
+++ b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.rc
@@ -0,0 +1,6 @@
+service vendor.tuner-hal-1-1 /vendor/bin/hw/android.hardware.tv.tuner@1.1-service
+    class hal
+    user media
+    group mediadrm drmrpc
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks
\ No newline at end of file
diff --git a/wifi/1.4/default/android.hardware.wifi@1.0-service.xml b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.xml
similarity index 64%
copy from wifi/1.4/default/android.hardware.wifi@1.0-service.xml
copy to tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.xml
index b5d25cd..86b0445 100644
--- a/wifi/1.4/default/android.hardware.wifi@1.0-service.xml
+++ b/tv/tuner/1.1/default/android.hardware.tv.tuner@1.1-service.xml
@@ -1,11 +1,11 @@
 <manifest version="1.0" type="device">
     <hal format="hidl">
-        <name>android.hardware.wifi</name>
+        <name>android.hardware.tv.tuner</name>
         <transport>hwbinder</transport>
-        <version>1.4</version>
+        <version>1.1</version>
         <interface>
-            <name>IWifi</name>
+            <name>ITuner</name>
             <instance>default</instance>
         </interface>
     </hal>
-</manifest>
+</manifest>
\ No newline at end of file
diff --git a/tv/tuner/1.1/default/service.cpp b/tv/tuner/1.1/default/service.cpp
new file mode 100644
index 0000000..2320308
--- /dev/null
+++ b/tv/tuner/1.1/default/service.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#ifdef LAZY_SERVICE
+#define LOG_TAG "android.hardware.tv.tuner@1.1-service-lazy"
+#else
+#define LOG_TAG "android.hardware.tv.tuner@1.1-service"
+#endif
+
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/LegacySupport.h>
+
+#include "Tuner.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::LazyServiceRegistrar;
+using android::hardware::tv::tuner::V1_0::implementation::Tuner;
+using android::hardware::tv::tuner::V1_1::ITuner;
+
+#ifdef LAZY_SERVICE
+const bool kLazyService = true;
+#else
+const bool kLazyService = false;
+#endif
+
+int main() {
+    configureRpcThreadpool(8, true /* callerWillJoin */);
+
+    // Setup hwbinder service
+    android::sp<ITuner> service = new Tuner();
+    android::status_t status;
+    if (kLazyService) {
+        auto serviceRegistrar = LazyServiceRegistrar::getInstance();
+        status = serviceRegistrar.registerService(service);
+    } else {
+        status = service->registerAsService();
+    }
+    LOG_ALWAYS_FATAL_IF(status != android::OK, "Error while registering tuner service: %d", status);
+
+    joinRpcThreadpool();
+    return 0;
+}
diff --git a/tv/tuner/1.1/types.hal b/tv/tuner/1.1/types.hal
new file mode 100644
index 0000000..21c7021
--- /dev/null
+++ b/tv/tuner/1.1/types.hal
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner@1.1;
+
+import @1.0::DemuxFilterDownloadEvent;
+import @1.0::DemuxFilterIpPayloadEvent;
+import @1.0::DemuxFilterMediaEvent;
+import @1.0::DemuxFilterMmtpRecordEvent;
+import @1.0::DemuxFilterPesEvent;
+import @1.0::DemuxFilterSectionEvent;
+import @1.0::DemuxFilterTemiEvent;
+import @1.0::DemuxFilterTsRecordEvent;
+import android.hidl.safe_union@1.0;
+
+/**
+ * Filter Event for TS Record data.
+ */
+struct DemuxFilterTsRecordEvent {
+    /**
+     * V1_0 Filter Event for TS Record data.
+     */
+    @1.0::DemuxFilterTsRecordEvent tsRecordEvent_1_0;
+
+    /**
+     * 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. It is used only for the SC and
+     * the SC_HEVC.
+     */
+    uint64_t pts;
+};
+
+/**
+ * Filter Event for MMTP Record data.
+ */
+struct DemuxFilterMmtpRecordEvent {
+    /**
+     * V1_0 Filter Event for MMTP Record data.
+     */
+    @1.0::DemuxFilterMmtpRecordEvent mmtpRecordEvent_1_0;
+
+    /**
+     * MPU sequence number of the filtered data. This is only used for MMTP.
+     */
+    uint32_t mpuSequenceNumber;
+};
+
+/**
+ * Filter Event.
+ */
+struct DemuxFilterEvent {
+    safe_union Event {
+        DemuxFilterSectionEvent section;
+
+        DemuxFilterMediaEvent media;
+
+        DemuxFilterPesEvent pes;
+
+        @1.1::DemuxFilterTsRecordEvent tsRecord;
+
+        @1.1::DemuxFilterMmtpRecordEvent mmtpRecord;
+
+        DemuxFilterDownloadEvent download;
+
+        DemuxFilterIpPayloadEvent ipPayload;
+
+        DemuxFilterTemiEvent temi;
+    };
+
+    /**
+     * An array of events
+     */
+    vec<Event> events;
+};
diff --git a/tv/tuner/1.1/vts/OWNERS b/tv/tuner/1.1/vts/OWNERS
new file mode 100644
index 0000000..1b3d095
--- /dev/null
+++ b/tv/tuner/1.1/vts/OWNERS
@@ -0,0 +1,4 @@
+nchalko@google.com
+amyjojo@google.com
+shubang@google.com
+quxiangfang@google.com
diff --git a/tv/tuner/1.1/vts/functional/Android.bp b/tv/tuner/1.1/vts/functional/Android.bp
new file mode 100644
index 0000000..1fc36f1
--- /dev/null
+++ b/tv/tuner/1.1/vts/functional/Android.bp
@@ -0,0 +1,49 @@
+//
+// Copyright 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalTvTunerV1_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "DemuxTests.cpp",
+        "DvrTests.cpp",
+        "FilterTests.cpp",
+        "FrontendTests.cpp",
+        "VtsHalTvTunerV1_1TargetTest.cpp",
+    ],
+    static_libs: [
+        "android.hardware.cas@1.0",
+        "android.hardware.cas@1.1",
+        "android.hardware.cas@1.2",
+        "android.hardware.tv.tuner@1.0",
+        "android.hardware.tv.tuner@1.1",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libhidlallocatorutils",
+        "libhidlmemory",
+        "libcutils",
+        "libfmq",
+    ],
+    shared_libs: [
+        "libbinder",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+
+    require_root: true,
+}
diff --git a/tv/tuner/1.1/vts/functional/DemuxTests.cpp b/tv/tuner/1.1/vts/functional/DemuxTests.cpp
new file mode 100644
index 0000000..e0600b6
--- /dev/null
+++ b/tv/tuner/1.1/vts/functional/DemuxTests.cpp
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "DemuxTests.h"
+
+AssertionResult DemuxTests::openDemux(sp<IDemux>& demux, uint32_t& demuxId) {
+    Result status;
+    mService->openDemux([&](Result result, uint32_t id, const sp<IDemux>& demuxSp) {
+        mDemux = demuxSp;
+        demux = demuxSp;
+        demuxId = id;
+        status = result;
+    });
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DemuxTests::setDemuxFrontendDataSource(uint32_t frontendId) {
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    auto status = mDemux->setFrontendDataSource(frontendId);
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult DemuxTests::closeDemux() {
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    auto status = mDemux->close();
+    mDemux = nullptr;
+    return AssertionResult(status.isOk());
+}
+
+AssertionResult DemuxTests::getAvSyncId_64bit(sp<IFilter> filter, uint64_t& avSyncHwId) {
+    EXPECT_TRUE(mDemux) << "Demux is not opened yet.";
+    Result status;
+
+    sp<android::hardware::tv::tuner::V1_1::IDemux> demux_v1_1 =
+            android::hardware::tv::tuner::V1_1::IDemux::castFrom(mDemux);
+    if (demux_v1_1 != NULL) {
+        demux_v1_1->getAvSyncHwId64Bit(filter, [&](Result result, uint64_t id) {
+            status = result;
+            avSyncHwId = id;
+        });
+    } else {
+        ALOGW("[vts] Can't cast IDemux into v1_1.");
+        return failure();
+    }
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DemuxTests::getAvSyncTime(uint32_t avSyncId) {
+    EXPECT_TRUE(mDemux) << "Demux is not opened yet.";
+    Result status;
+    uint64_t syncTime;
+    mDemux->getAvSyncTime(avSyncId, [&](Result result, uint64_t time) {
+        status = result;
+        syncTime = time;
+    });
+    return AssertionResult(status == Result::SUCCESS);
+}
\ No newline at end of file
diff --git a/tv/tuner/1.1/vts/functional/DemuxTests.h b/tv/tuner/1.1/vts/functional/DemuxTests.h
new file mode 100644
index 0000000..393757c
--- /dev/null
+++ b/tv/tuner/1.1/vts/functional/DemuxTests.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/hardware/tv/tuner/1.0/IDemux.h>
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <android/hardware/tv/tuner/1.1/IDemux.h>
+#include <android/hardware/tv/tuner/1.1/IFilter.h>
+#include <android/hardware/tv/tuner/1.1/ITuner.h>
+#include <binder/MemoryDealer.h>
+#include <gtest/gtest.h>
+#include <hidl/ServiceManagement.h>
+#include <hidl/Status.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <map>
+
+using android::sp;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::IDemux;
+using android::hardware::tv::tuner::V1_0::IFilter;
+using android::hardware::tv::tuner::V1_0::Result;
+using android::hardware::tv::tuner::V1_1::ITuner;
+
+using ::testing::AssertionResult;
+
+class DemuxTests {
+  public:
+    void setService(sp<ITuner> tuner) { mService = tuner; }
+
+    AssertionResult openDemux(sp<IDemux>& demux, uint32_t& demuxId);
+    AssertionResult setDemuxFrontendDataSource(uint32_t frontendId);
+    AssertionResult getAvSyncId_64bit(sp<IFilter> filter, uint64_t& avSyncHwId);
+    AssertionResult getAvSyncTime(uint32_t avSyncId);
+    AssertionResult closeDemux();
+
+  protected:
+    static AssertionResult failure() { return ::testing::AssertionFailure(); }
+
+    static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+    sp<ITuner> mService;
+    sp<IDemux> mDemux;
+};
diff --git a/tv/tuner/1.1/vts/functional/DvrTests.cpp b/tv/tuner/1.1/vts/functional/DvrTests.cpp
new file mode 100644
index 0000000..0dfc032
--- /dev/null
+++ b/tv/tuner/1.1/vts/functional/DvrTests.cpp
@@ -0,0 +1,348 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "DvrTests.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);
+    pthread_create(&mPlaybackThread, NULL, __threadLoopPlayback, this);
+    pthread_setname_np(mPlaybackThread, "test_playback_input_loop");
+}
+
+void DvrCallback::stopPlaybackThread() {
+    mPlaybackThreadRunning = false;
+    mKeepWritingPlaybackFMQ = false;
+
+    android::Mutex::Autolock autoLock(mPlaybackThreadLock);
+}
+
+void* DvrCallback::__threadLoopPlayback(void* user) {
+    DvrCallback* const self = static_cast<DvrCallback*>(user);
+    self->playbackThreadLoop();
+    return 0;
+}
+
+void DvrCallback::playbackThreadLoop() {
+    android::Mutex::Autolock autoLock(mPlaybackThreadLock);
+    mPlaybackThreadRunning = 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;
+    uint8_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;
+            }
+            MessageQueue<uint8_t, kSynchronizedReadWrite>::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() {
+    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";
+            stopRecordThread();
+            return;
+        }
+    }
+    stopRecordThread();
+    ALOGW("[vts] record pass and stop");
+}
+
+void DvrCallback::startRecordOutputThread(RecordSettings recordSettings,
+                                          MQDesc& recordMQDescriptor) {
+    mRecordMQ = std::make_unique<FilterMQ>(recordMQDescriptor, true /* resetPointers */);
+    EXPECT_TRUE(mRecordMQ);
+    struct RecordThreadArgs* threadArgs =
+            (struct RecordThreadArgs*)malloc(sizeof(struct RecordThreadArgs));
+    threadArgs->user = this;
+    threadArgs->recordSettings = &recordSettings;
+    threadArgs->keepReadingRecordFMQ = &mKeepReadingRecordFMQ;
+
+    pthread_create(&mRecordThread, NULL, __threadLoopRecord, (void*)threadArgs);
+    pthread_setname_np(mRecordThread, "test_record_input_loop");
+}
+
+void* DvrCallback::__threadLoopRecord(void* threadArgs) {
+    DvrCallback* const self =
+            static_cast<DvrCallback*>(((struct RecordThreadArgs*)threadArgs)->user);
+    self->recordThreadLoop(((struct RecordThreadArgs*)threadArgs)->recordSettings,
+                           ((struct RecordThreadArgs*)threadArgs)->keepReadingRecordFMQ);
+    return 0;
+}
+
+void DvrCallback::recordThreadLoop(RecordSettings* /*recordSettings*/, bool* keepReadingRecordFMQ) {
+    ALOGD("[vts] DvrCallback record threadLoop start.");
+    android::Mutex::Autolock autoLock(mRecordThreadLock);
+    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 (*keepReadingRecordFMQ) {
+            uint32_t efState = 0;
+            android::status_t status = recordMQEventFlag->wait(
+                    static_cast<uint32_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;
+    mDataOutputBuffer.clear();
+    mDataOutputBuffer.resize(mRecordMQ->availableToRead());
+    result = mRecordMQ->read(mDataOutputBuffer.data(), mRecordMQ->availableToRead());
+    EXPECT_TRUE(result) << "can't read from Record MQ";
+    mMsgCondition.signal();
+    return result;
+}
+
+void DvrCallback::stopRecordThread() {
+    mKeepReadingRecordFMQ = false;
+    mRecordThreadRunning = false;
+}
+
+AssertionResult DvrTests::openDvrInDemux(DvrType type, uint32_t bufferSize) {
+    Result status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+
+    // Create dvr callback
+    if (type == DvrType::PLAYBACK) {
+        mDvrPlaybackCallback = new DvrCallback();
+        mDemux->openDvr(type, bufferSize, mDvrPlaybackCallback,
+                        [&](Result result, const sp<IDvr>& dvr) {
+                            mDvrPlayback = dvr;
+                            status = result;
+                        });
+        if (status == Result::SUCCESS) {
+            mDvrPlaybackCallback->setDvr(mDvrPlayback);
+        }
+    }
+
+    if (type == DvrType::RECORD) {
+        mDvrRecordCallback = new DvrCallback();
+        mDemux->openDvr(type, bufferSize, mDvrRecordCallback,
+                        [&](Result result, const sp<IDvr>& dvr) {
+                            mDvrRecord = dvr;
+                            status = result;
+                        });
+        if (status == Result::SUCCESS) {
+            mDvrRecordCallback->setDvr(mDvrRecord);
+        }
+    }
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::configDvrPlayback(DvrSettings setting) {
+    Result status = mDvrPlayback->configure(setting);
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::configDvrRecord(DvrSettings setting) {
+    Result status = mDvrRecord->configure(setting);
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::getDvrPlaybackMQDescriptor() {
+    Result status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
+
+    mDvrPlayback->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
+        mDvrPlaybackMQDescriptor = dvrMQDesc;
+        status = result;
+    });
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::getDvrRecordMQDescriptor() {
+    Result status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+    mDvrRecord->getQueueDesc([&](Result result, const MQDesc& dvrMQDesc) {
+        mDvrRecordMQDescriptor = dvrMQDesc;
+        status = result;
+    });
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::attachFilterToDvr(sp<IFilter> filter) {
+    Result status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+    status = mDvrRecord->attachFilter(filter);
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::detachFilterToDvr(sp<IFilter> filter) {
+    Result status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+    status = mDvrRecord->detachFilter(filter);
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::startDvrPlayback() {
+    Result status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
+
+    status = mDvrPlayback->start();
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::stopDvrPlayback() {
+    Result status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
+
+    status = mDvrPlayback->stop();
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+void DvrTests::closeDvrPlayback() {
+    ASSERT_TRUE(mDemux);
+    ASSERT_TRUE(mDvrPlayback);
+    ASSERT_TRUE(mDvrPlayback->close() == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::startDvrRecord() {
+    Result status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+    status = mDvrRecord->start();
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult DvrTests::stopDvrRecord() {
+    Result status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+    status = mDvrRecord->stop();
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+void DvrTests::closeDvrRecord() {
+    ASSERT_TRUE(mDemux);
+    ASSERT_TRUE(mDvrRecord);
+    ASSERT_TRUE(mDvrRecord->close() == Result::SUCCESS);
+}
diff --git a/tv/tuner/1.1/vts/functional/DvrTests.h b/tv/tuner/1.1/vts/functional/DvrTests.h
new file mode 100644
index 0000000..289ddf6
--- /dev/null
+++ b/tv/tuner/1.1/vts/functional/DvrTests.h
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/hardware/tv/tuner/1.0/IDvr.h>
+#include <android/hardware/tv/tuner/1.0/IDvrCallback.h>
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <android/hardware/tv/tuner/1.1/ITuner.h>
+#include <fcntl.h>
+#include <fmq/MessageQueue.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/Status.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <fstream>
+#include <iostream>
+#include <map>
+
+#include "FilterTests.h"
+
+using android::Condition;
+using android::Mutex;
+using android::sp;
+using android::hardware::EventFlag;
+using android::hardware::kSynchronizedReadWrite;
+using android::hardware::MessageQueue;
+using android::hardware::MQDescriptorSync;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
+using android::hardware::tv::tuner::V1_0::DvrSettings;
+using android::hardware::tv::tuner::V1_0::DvrType;
+using android::hardware::tv::tuner::V1_0::IDvr;
+using android::hardware::tv::tuner::V1_0::IDvrCallback;
+using android::hardware::tv::tuner::V1_0::PlaybackSettings;
+using android::hardware::tv::tuner::V1_0::PlaybackStatus;
+using android::hardware::tv::tuner::V1_0::RecordSettings;
+using android::hardware::tv::tuner::V1_0::RecordStatus;
+using android::hardware::tv::tuner::V1_0::Result;
+using android::hardware::tv::tuner::V1_1::ITuner;
+
+using namespace std;
+
+#define WAIT_TIMEOUT 3000000000
+
+class DvrCallback : public IDvrCallback {
+  public:
+    virtual Return<void> onRecordStatus(DemuxFilterStatus status) override {
+        ALOGD("[vts] record status %hhu", status);
+        switch (status) {
+            case DemuxFilterStatus::DATA_READY:
+                break;
+            case DemuxFilterStatus::LOW_WATER:
+                break;
+            case DemuxFilterStatus::HIGH_WATER:
+            case DemuxFilterStatus::OVERFLOW:
+                ALOGD("[vts] record overflow. Flushing.");
+                EXPECT_TRUE(mDvr) << "Dvr callback is not set with an IDvr";
+                if (mDvr) {
+                    Result result = mDvr->flush();
+                    ALOGD("[vts] Flushing result %d.", result);
+                }
+                break;
+        }
+        return Void();
+    }
+
+    virtual Return<void> 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 Void();
+    }
+
+    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(RecordSettings* recordSetting, bool* keepWritingPlaybackFMQ);
+
+    bool readRecordFMQ();
+
+    void setDvr(sp<IDvr> dvr) { mDvr = dvr; }
+
+  private:
+    struct RecordThreadArgs {
+        DvrCallback* user;
+        RecordSettings* recordSettings;
+        bool* keepReadingRecordFMQ;
+    };
+    // uint16_t mDataLength = 0;
+    std::vector<uint8_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::Mutex mPlaybackThreadLock;
+    android::Mutex mRecordThreadLock;
+    android::Condition mMsgCondition;
+
+    bool mKeepWritingPlaybackFMQ = true;
+    bool mKeepReadingRecordFMQ = true;
+    bool mPlaybackThreadRunning;
+    bool mRecordThreadRunning;
+    pthread_t mPlaybackThread;
+    pthread_t mRecordThread;
+    string mInputDataFile;
+    PlaybackSettings mPlaybackSettings;
+
+    sp<IDvr> mDvr = nullptr;
+
+    // int mPidFilterOutputCount = 0;
+};
+
+class DvrTests {
+  public:
+    void setService(sp<ITuner> tuner) { mService = tuner; }
+    void setDemux(sp<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, uint32_t bufferSize);
+    AssertionResult configDvrPlayback(DvrSettings setting);
+    AssertionResult configDvrRecord(DvrSettings setting);
+    AssertionResult getDvrPlaybackMQDescriptor();
+    AssertionResult getDvrRecordMQDescriptor();
+    AssertionResult attachFilterToDvr(sp<IFilter> filter);
+    AssertionResult detachFilterToDvr(sp<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(); }
+
+    sp<ITuner> mService;
+    sp<IDvr> mDvrPlayback;
+    sp<IDvr> mDvrRecord;
+    sp<IDemux> mDemux;
+    sp<DvrCallback> mDvrPlaybackCallback;
+    sp<DvrCallback> mDvrRecordCallback;
+    MQDesc mDvrPlaybackMQDescriptor;
+    MQDesc mDvrRecordMQDescriptor;
+};
diff --git a/tv/tuner/1.1/vts/functional/FilterTests.cpp b/tv/tuner/1.1/vts/functional/FilterTests.cpp
new file mode 100644
index 0000000..9cbec86
--- /dev/null
+++ b/tv/tuner/1.1/vts/functional/FilterTests.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FilterTests.h"
+
+bool FilterCallback::readFilterEventData() {
+    bool result = false;
+    ALOGW("[vts] reading from filter FMQ or buffer %d", mFilterId);
+    // todo separate filter handlers
+    for (int i = 0; i < mFilterEvent.events.size(); i++) {
+        switch (mFilterEventType) {
+            case FilterEventType::RECORD:
+                ALOGW("[vts] Record filter event, pts=%" PRIu64 ".",
+                      mFilterEvent.events[0].tsRecord().pts);
+                break;
+            default:
+                break;
+        }
+    }
+    return result;
+}
+
+AssertionResult FilterTests::openFilterInDemux(DemuxFilterType type, uint32_t bufferSize) {
+    Result status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+
+    // Create demux callback
+    mFilterCallback = new FilterCallback();
+
+    // Add filter to the local demux
+    mDemux->openFilter(type, bufferSize, mFilterCallback,
+                       [&](Result result, const sp<IFilter>& filter) {
+                           mFilter = filter;
+                           status = result;
+                       });
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::getNewlyOpenedFilterId_64bit(uint64_t& filterId) {
+    Result status;
+    EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+    EXPECT_TRUE(mFilter) << "Test with openFilterInDemux first.";
+    EXPECT_TRUE(mFilterCallback) << "Test with openFilterInDemux first.";
+
+    sp<android::hardware::tv::tuner::V1_1::IFilter> filter_v1_1 =
+            android::hardware::tv::tuner::V1_1::IFilter::castFrom(mFilter);
+    if (filter_v1_1 != NULL) {
+        filter_v1_1->getId64Bit([&](Result result, uint64_t filterId) {
+            mFilterId = filterId;
+            status = result;
+        });
+    } else {
+        ALOGW("[vts] Can't cast IFilter into v1_1.");
+        return failure();
+    }
+
+    if (status == Result::SUCCESS) {
+        mFilterCallback->setFilterId(mFilterId);
+        mFilterCallback->setFilterInterface(mFilter);
+        mUsedFilterIds.insert(mUsedFilterIds.end(), mFilterId);
+        mFilters[mFilterId] = mFilter;
+        mFilterCallbacks[mFilterId] = mFilterCallback;
+        filterId = mFilterId;
+    }
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::configFilter(DemuxFilterSettings setting, uint64_t filterId) {
+    Result status;
+    EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+    status = mFilters[filterId]->configure(setting);
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::getFilterMQDescriptor(uint64_t filterId) {
+    Result status;
+    EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+    EXPECT_TRUE(mFilterCallbacks[filterId]) << "Test with getNewlyOpenedFilterId first.";
+
+    mFilter->getQueueDesc([&](Result result, const MQDesc& filterMQDesc) {
+        mFilterMQDescriptor = filterMQDesc;
+        status = result;
+    });
+
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::startFilter(uint64_t filterId) {
+    EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+    Result status = mFilters[filterId]->start();
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::stopFilter(uint64_t filterId) {
+    EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+    Result status = mFilters[filterId]->stop();
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FilterTests::closeFilter(uint64_t filterId) {
+    EXPECT_TRUE(mFilters[filterId]) << "Test with getNewlyOpenedFilterId first.";
+    Result status = mFilters[filterId]->close();
+    if (status == Result::SUCCESS) {
+        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 == Result::SUCCESS);
+}
diff --git a/tv/tuner/1.1/vts/functional/FilterTests.h b/tv/tuner/1.1/vts/functional/FilterTests.h
new file mode 100644
index 0000000..8156f14
--- /dev/null
+++ b/tv/tuner/1.1/vts/functional/FilterTests.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/hardware/tv/tuner/1.0/IDemux.h>
+#include <android/hardware/tv/tuner/1.0/IFilter.h>
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <android/hardware/tv/tuner/1.1/IFilter.h>
+#include <android/hardware/tv/tuner/1.1/IFilterCallback.h>
+#include <android/hardware/tv/tuner/1.1/ITuner.h>
+#include <android/hardware/tv/tuner/1.1/types.h>
+#include <fmq/MessageQueue.h>
+#include <gtest/gtest.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/Status.h>
+#include <inttypes.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <map>
+
+using android::Condition;
+using android::Mutex;
+using android::sp;
+using android::hardware::EventFlag;
+using android::hardware::hidl_handle;
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+using android::hardware::kSynchronizedReadWrite;
+using android::hardware::MessageQueue;
+using android::hardware::MQDescriptorSync;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
+using android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
+using android::hardware::tv::tuner::V1_0::IDemux;
+using android::hardware::tv::tuner::V1_0::IFilter;
+using android::hardware::tv::tuner::V1_0::Result;
+using android::hardware::tv::tuner::V1_1::DemuxFilterEvent;
+using android::hardware::tv::tuner::V1_1::IFilterCallback;
+using android::hardware::tv::tuner::V1_1::ITuner;
+
+using ::testing::AssertionResult;
+
+using namespace std;
+
+enum FilterEventType : uint8_t {
+    UNDEFINED,
+    SECTION,
+    MEDIA,
+    PES,
+    RECORD,
+    MMTPRECORD,
+    DOWNLOAD,
+    TEMI,
+};
+
+using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+using MQDesc = MQDescriptorSync<uint8_t>;
+
+#define WAIT_TIMEOUT 3000000000
+
+class FilterCallback : public IFilterCallback {
+  public:
+    virtual Return<void> onFilterEvent_1_1(const DemuxFilterEvent& filterEvent) override {
+        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();
+        mPidFilterOutputCount++;
+        mMsgCondition.signal();
+        return Void();
+    }
+
+    virtual Return<void> onFilterEvent(
+            const android::hardware::tv::tuner::V1_0::DemuxFilterEvent& /*filterEvent*/) override {
+        return Void();
+    }
+
+    virtual Return<void> onFilterStatus(const DemuxFilterStatus /*status*/) override {
+        return Void();
+    }
+
+    void setFilterId(uint32_t filterId) { mFilterId = filterId; }
+    void setFilterInterface(sp<IFilter> filter) { mFilter = filter; }
+    void setFilterEventType(FilterEventType type) { mFilterEventType = type; }
+
+    bool readFilterEventData();
+
+  private:
+    uint32_t mFilterId;
+    sp<IFilter> mFilter;
+    FilterEventType mFilterEventType;
+    DemuxFilterEvent mFilterEvent;
+
+    android::Mutex mMsgLock;
+    android::Mutex mFilterOutputLock;
+    android::Condition mMsgCondition;
+
+    int mPidFilterOutputCount = 0;
+};
+
+class FilterTests {
+  public:
+    void setService(sp<ITuner> tuner) { mService = tuner; }
+    void setDemux(sp<IDemux> demux) { mDemux = demux; }
+    sp<IFilter> getFilterById(uint64_t filterId) { return mFilters[filterId]; }
+
+    std::map<uint64_t, sp<FilterCallback>> getFilterCallbacks() { return mFilterCallbacks; }
+
+    AssertionResult openFilterInDemux(DemuxFilterType type, uint32_t bufferSize);
+    AssertionResult getNewlyOpenedFilterId_64bit(uint64_t& filterId);
+    AssertionResult configFilter(DemuxFilterSettings setting, uint64_t filterId);
+    AssertionResult getFilterMQDescriptor(uint64_t filterId);
+    AssertionResult startFilter(uint64_t filterId);
+    AssertionResult stopFilter(uint64_t filterId);
+    AssertionResult closeFilter(uint64_t filterId);
+
+    FilterEventType getFilterEventType(DemuxFilterType type) {
+        FilterEventType eventType = FilterEventType::UNDEFINED;
+        switch (type.mainType) {
+            case DemuxFilterMainType::TS:
+                switch (type.subType.tsFilterType()) {
+                    case DemuxTsFilterType::UNDEFINED:
+                        break;
+                    case DemuxTsFilterType::SECTION:
+                        eventType = FilterEventType::SECTION;
+                        break;
+                    case DemuxTsFilterType::PES:
+                        eventType = FilterEventType::PES;
+                        break;
+                    case DemuxTsFilterType::TS:
+                        break;
+                    case DemuxTsFilterType::AUDIO:
+                    case DemuxTsFilterType::VIDEO:
+                        eventType = FilterEventType::MEDIA;
+                        break;
+                    case DemuxTsFilterType::PCR:
+                        break;
+                    case DemuxTsFilterType::RECORD:
+                        eventType = FilterEventType::RECORD;
+                        break;
+                    case DemuxTsFilterType::TEMI:
+                        eventType = FilterEventType::TEMI;
+                        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 eventType;
+    }
+
+  protected:
+    static AssertionResult failure() { return ::testing::AssertionFailure(); }
+
+    static AssertionResult success() { return ::testing::AssertionSuccess(); }
+
+    sp<ITuner> mService;
+    sp<IFilter> mFilter;
+    sp<IDemux> mDemux;
+    std::map<uint64_t, sp<IFilter>> mFilters;
+    std::map<uint64_t, sp<FilterCallback>> mFilterCallbacks;
+
+    sp<FilterCallback> mFilterCallback;
+    MQDesc mFilterMQDescriptor;
+    vector<uint64_t> mUsedFilterIds;
+
+    uint64_t mFilterId = -1;
+};
diff --git a/tv/tuner/1.1/vts/functional/FrontendTests.cpp b/tv/tuner/1.1/vts/functional/FrontendTests.cpp
new file mode 100644
index 0000000..da46adb
--- /dev/null
+++ b/tv/tuner/1.1/vts/functional/FrontendTests.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FrontendTests.h"
+
+Return<void> 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();
+            return Void();
+        default:
+            // do nothing
+            return Void();
+    }
+}
+
+Return<void> FrontendCallback::onScanMessage(FrontendScanMessageType /*type*/,
+                                             const FrontendScanMessage& /*message*/) {
+    return Void();
+}
+
+void FrontendCallback::tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings) {
+    Result result = frontend->tune(settings);
+    EXPECT_TRUE(result == Result::SUCCESS);
+
+    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;
+}
+
+AssertionResult FrontendTests::getFrontendIds() {
+    Result status;
+    mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
+        status = result;
+        mFeIds = frontendIds;
+    });
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FrontendTests::getFrontendInfo(uint32_t frontendId) {
+    Result status;
+    mService->getFrontendInfo(frontendId, [&](Result result, const FrontendInfo& frontendInfo) {
+        mFrontendInfo = frontendInfo;
+        status = result;
+    });
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FrontendTests::openFrontendById(uint32_t frontendId) {
+    Result status;
+    mService->openFrontendById(frontendId, [&](Result result, const sp<IFrontend>& frontend) {
+        mFrontend = frontend;
+        status = result;
+    });
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FrontendTests::setFrontendCallback() {
+    EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
+    mFrontendCallback = new FrontendCallback();
+    auto callbackStatus = mFrontend->setCallback(mFrontendCallback);
+    return AssertionResult(callbackStatus.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;
+    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());
+        if (!result) {
+            ALOGW("[vts] Software frontend dvr configure failed.");
+            return failure();
+        }
+    }
+    mFrontendCallback->tuneTestOnLock(mFrontend, config.settings);
+    return AssertionResult(true);
+}
+
+AssertionResult FrontendTests::stopTuneFrontend(bool testWithDemux) {
+    EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
+    Result status;
+    status = mFrontend->stopTune();
+    if (mIsSoftwareFe && testWithDemux) {
+        mDvrTests.stopPlaybackThread();
+        mDvrTests.closeDvrPlayback();
+    }
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+AssertionResult FrontendTests::closeFrontend() {
+    EXPECT_TRUE(mFrontend) << "Test with openFrontendById first.";
+    Result status;
+    status = mFrontend->close();
+    mFrontend = nullptr;
+    mFrontendCallback = nullptr;
+    return AssertionResult(status == Result::SUCCESS);
+}
+
+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) {
+            continue;
+        }
+        feId = mFeIds[i];
+        return;
+    }
+    feId = INVALID_ID;
+}
diff --git a/tv/tuner/1.1/vts/functional/FrontendTests.h b/tv/tuner/1.1/vts/functional/FrontendTests.h
new file mode 100644
index 0000000..492f2f0
--- /dev/null
+++ b/tv/tuner/1.1/vts/functional/FrontendTests.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android-base/logging.h>
+#include <android/hardware/tv/tuner/1.0/IFrontend.h>
+#include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <android/hardware/tv/tuner/1.1/ITuner.h>
+#include <binder/MemoryDealer.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/ServiceManagement.h>
+#include <hidl/Status.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <map>
+
+#include "DvrTests.h"
+#include "VtsHalTvTunerV1_1TestConfigurations.h"
+
+#define WAIT_TIMEOUT 3000000000
+#define INVALID_ID -1
+
+using android::Condition;
+using android::IMemory;
+using android::IMemoryHeap;
+using android::MemoryDealer;
+using android::Mutex;
+using android::sp;
+using android::hardware::fromHeap;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::FrontendEventType;
+using android::hardware::tv::tuner::V1_0::FrontendId;
+using android::hardware::tv::tuner::V1_0::FrontendInfo;
+using android::hardware::tv::tuner::V1_0::FrontendScanMessage;
+using android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
+using android::hardware::tv::tuner::V1_0::IFrontend;
+using android::hardware::tv::tuner::V1_0::IFrontendCallback;
+using android::hardware::tv::tuner::V1_0::Result;
+using android::hardware::tv::tuner::V1_1::ITuner;
+
+using ::testing::AssertionResult;
+
+using namespace std;
+
+#define INVALID_ID -1
+#define WAIT_TIMEOUT 3000000000
+
+class FrontendCallback : public IFrontendCallback {
+  public:
+    virtual Return<void> onEvent(FrontendEventType frontendEventType) override;
+    virtual Return<void> onScanMessage(FrontendScanMessageType type,
+                                       const FrontendScanMessage& message) override;
+
+    void tuneTestOnLock(sp<IFrontend>& frontend, FrontendSettings settings);
+
+  private:
+    bool mEventReceived = false;
+    bool mLockMsgReceived = false;
+    hidl_vec<uint8_t> mEventMessage;
+    android::Mutex mMsgLock;
+    android::Condition mMsgCondition;
+    android::Condition mLockMsgCondition;
+};
+
+class FrontendTests {
+  public:
+    sp<ITuner> mService;
+
+    void setService(sp<ITuner> tuner) {
+        mService = tuner;
+        mDvrTests.setService(tuner);
+        getDefaultSoftwareFrontendPlaybackConfig(mDvrConfig);
+    }
+
+    AssertionResult getFrontendIds();
+    AssertionResult getFrontendInfo(uint32_t frontendId);
+    AssertionResult openFrontendById(uint32_t frontendId);
+    AssertionResult setFrontendCallback();
+    AssertionResult tuneFrontend(FrontendConfig config, bool testWithDemux);
+    AssertionResult stopTuneFrontend(bool testWithDemux);
+    AssertionResult closeFrontend();
+
+    void getFrontendIdByType(FrontendType feType, uint32_t& feId);
+
+    void setDvrTests(DvrTests dvrTests) { mDvrTests = dvrTests; }
+    void setDemux(sp<IDemux> demux) { mDvrTests.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 = 188,
+        };
+        dvrConfig.type = DvrType::PLAYBACK;
+        dvrConfig.playbackInputFile = "/data/local/tmp/test.es";
+        dvrConfig.bufferSize = FMQ_SIZE_4M;
+        dvrConfig.settings.playback(playbackSettings);
+    }
+
+    sp<IFrontend> mFrontend;
+    FrontendInfo mFrontendInfo;
+    sp<FrontendCallback> mFrontendCallback;
+    hidl_vec<FrontendId> mFeIds;
+
+    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
new file mode 100644
index 0000000..c9873b2
--- /dev/null
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "VtsHalTvTunerV1_1TargetTest.h"
+
+namespace {
+
+void TunerFilterHidlTest::configSingleFilterInDemuxTest(FilterConfig filterConf,
+                                                        FrontendConfig frontendConf) {
+    uint32_t feId;
+    uint32_t demuxId;
+    sp<IDemux> demux;
+    uint64_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));
+    ASSERT_TRUE(mFilterTests.getFilterMQDescriptor(filterId));
+    ASSERT_TRUE(mFilterTests.startFilter(filterId));
+    ASSERT_TRUE(mFilterTests.stopFilter(filterId));
+    ASSERT_TRUE(mFilterTests.closeFilter(filterId));
+    ASSERT_TRUE(mDemuxTests.closeDemux());
+    ASSERT_TRUE(mFrontendTests.closeFrontend());
+}
+
+void TunerRecordHidlTest::recordSingleFilterTest(FilterConfig filterConf,
+                                                 FrontendConfig frontendConf, DvrConfig dvrConf) {
+    uint32_t feId;
+    uint32_t demuxId;
+    sp<IDemux> demux;
+    uint64_t filterId;
+    sp<IFilter> filter;
+
+    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);
+    mDvrTests.setDemux(demux);
+    mFrontendTests.setDvrTests(mDvrTests);
+    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));
+    filter = mFilterTests.getFilterById(filterId);
+    ASSERT_TRUE(filter != nullptr);
+    mDvrTests.startRecordOutputThread(dvrConf.settings.record());
+    ASSERT_TRUE(mDvrTests.attachFilterToDvr(filter));
+    ASSERT_TRUE(mDvrTests.startDvrRecord());
+    ASSERT_TRUE(mFilterTests.startFilter(filterId));
+    ASSERT_TRUE(mFrontendTests.tuneFrontend(frontendConf, true /*testWithDemux*/));
+    mDvrTests.testRecordOutput();
+    mDvrTests.stopRecordThread();
+    ASSERT_TRUE(mFrontendTests.stopTuneFrontend(true /*testWithDemux*/));
+    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());
+    ASSERT_TRUE(mFrontendTests.closeFrontend());
+}
+
+TEST_P(TunerDemuxHidlTest, getAvSyncTime) {
+    description("Get the A/V sync time from a PCR filter.");
+    uint32_t feId;
+    uint32_t demuxId;
+    sp<IDemux> demux;
+    uint64_t mediaFilterId;
+    uint64_t pcrFilterId;
+    uint64_t avSyncHwId;
+    sp<IFilter> mediaFilter;
+
+    mFrontendTests.getFrontendIdByType(frontendArray[DVBT].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(filterArray[TS_VIDEO1].type,
+                                               filterArray[TS_VIDEO1].bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(mediaFilterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_VIDEO1].settings, mediaFilterId));
+    mediaFilter = mFilterTests.getFilterById(mediaFilterId);
+    ASSERT_TRUE(mFilterTests.openFilterInDemux(filterArray[TS_PCR0].type,
+                                               filterArray[TS_PCR0].bufferSize));
+    ASSERT_TRUE(mFilterTests.getNewlyOpenedFilterId_64bit(pcrFilterId));
+    ASSERT_TRUE(mFilterTests.configFilter(filterArray[TS_PCR0].settings, pcrFilterId));
+    ASSERT_TRUE(mDemuxTests.getAvSyncId_64bit(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(TunerFilterHidlTest, StartFilterInDemux) {
+    description("Open and start a filter in Demux.");
+    // TODO use parameterized tests
+    configSingleFilterInDemuxTest(filterArray[TS_VIDEO0], frontendArray[DVBT]);
+}
+
+TEST_P(TunerRecordHidlTest, RecordDataFlowWithTsRecordFilterTest) {
+    description("Feed ts data from frontend to recording and test with ts record filter");
+    recordSingleFilterTest(filterArray[TS_RECORD0], frontendArray[DVBT], dvrArray[DVR_RECORD0]);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, TunerFilterHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
+        android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, TunerDemuxHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
+        android::hardware::PrintInstanceNameToString);
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, TunerRecordHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(ITuner::descriptor)),
+        android::hardware::PrintInstanceNameToString);
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerFilterHidlTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerDemuxHidlTest);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerRecordHidlTest);
+}  // namespace
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
new file mode 100644
index 0000000..1b28853
--- /dev/null
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TargetTest.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "DemuxTests.h"
+#include "FrontendTests.h"
+
+namespace {
+
+void initConfiguration() {
+    initFrontendConfig();
+    initFilterConfig();
+    initDvrConfig();
+}
+
+class TunerFilterHidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        mService = ITuner::getService(GetParam());
+        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);
+
+    sp<ITuner> mService;
+    FrontendTests mFrontendTests;
+    DemuxTests mDemuxTests;
+    FilterTests mFilterTests;
+};
+
+class TunerDemuxHidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        mService = ITuner::getService(GetParam());
+        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);
+    }
+
+    sp<ITuner> mService;
+    FrontendTests mFrontendTests;
+    DemuxTests mDemuxTests;
+    FilterTests mFilterTests;
+};
+
+class TunerRecordHidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        mService = ITuner::getService(GetParam());
+        ASSERT_NE(mService, nullptr);
+        initConfiguration();
+
+        mFrontendTests.setService(mService);
+        mDemuxTests.setService(mService);
+        mFilterTests.setService(mService);
+        mDvrTests.setService(mService);
+    }
+
+  protected:
+    static void description(const std::string& description) {
+        RecordProperty("description", description);
+    }
+
+    void recordSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf,
+                                DvrConfig dvrConf);
+
+    sp<ITuner> mService;
+    FrontendTests mFrontendTests;
+    DemuxTests mDemuxTests;
+    FilterTests mFilterTests;
+    DvrTests mDvrTests;
+};
+}  // namespace
\ No newline at end of file
diff --git a/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
new file mode 100644
index 0000000..39872d2
--- /dev/null
+++ b/tv/tuner/1.1/vts/functional/VtsHalTvTunerV1_1TestConfigurations.h
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <binder/MemoryDealer.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/Status.h>
+#include <hidlmemory/FrameworkUtils.h>
+
+using android::hardware::tv::tuner::V1_0::DataFormat;
+using android::hardware::tv::tuner::V1_0::DemuxAlpFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxFilterMainType;
+using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
+using android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxIpFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxMmtpFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxRecordScIndexType;
+using android::hardware::tv::tuner::V1_0::DemuxTsFilterType;
+using android::hardware::tv::tuner::V1_0::DvrSettings;
+using android::hardware::tv::tuner::V1_0::DvrType;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtBandwidth;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtCoderate;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtConstellation;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtGuardInterval;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtHierarchy;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtSettings;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtStandard;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtTransmissionMode;
+using android::hardware::tv::tuner::V1_0::FrontendSettings;
+using android::hardware::tv::tuner::V1_0::FrontendStatus;
+using android::hardware::tv::tuner::V1_0::FrontendStatusType;
+using android::hardware::tv::tuner::V1_0::FrontendType;
+using android::hardware::tv::tuner::V1_0::PlaybackSettings;
+using android::hardware::tv::tuner::V1_0::RecordSettings;
+
+using namespace std;
+
+const uint32_t FMQ_SIZE_1M = 0x100000;
+const uint32_t FMQ_SIZE_4M = 0x400000;
+const uint32_t FMQ_SIZE_16M = 0x1000000;
+
+typedef enum {
+    TS_VIDEO0,
+    TS_VIDEO1,
+    TS_AUDIO0,
+    TS_AUDIO1,
+    TS_PES0,
+    TS_PCR0,
+    TS_SECTION0,
+    TS_TS0,
+    TS_RECORD0,
+    FILTER_MAX,
+} Filter;
+
+typedef enum {
+    DVBT,
+    DVBS,
+    FRONTEND_MAX,
+} Frontend;
+
+typedef enum {
+    DVR_RECORD0,
+    DVR_PLAYBACK0,
+    DVR_MAX,
+} Dvr;
+
+struct FilterConfig {
+    uint32_t bufferSize;
+    DemuxFilterType type;
+    DemuxFilterSettings settings;
+
+    bool operator<(const FilterConfig& /*c*/) const { return false; }
+};
+
+struct FrontendConfig {
+    bool isSoftwareFe;
+    FrontendType type;
+    FrontendSettings settings;
+    vector<FrontendStatusType> tuneStatusTypes;
+    vector<FrontendStatus> expectTuneStatuses;
+};
+
+struct DvrConfig {
+    DvrType type;
+    uint32_t bufferSize;
+    DvrSettings settings;
+    string playbackInputFile;
+};
+
+static FrontendConfig frontendArray[FILTER_MAX];
+static FilterConfig filterArray[FILTER_MAX];
+static DvrConfig dvrArray[DVR_MAX];
+
+/** Configuration array for the frontend tune test */
+inline void initFrontendConfig() {
+    FrontendDvbtSettings dvbtSettings{
+            .frequency = 578000,
+            .transmissionMode = FrontendDvbtTransmissionMode::AUTO,
+            .bandwidth = FrontendDvbtBandwidth::BANDWIDTH_8MHZ,
+            .constellation = FrontendDvbtConstellation::AUTO,
+            .hierarchy = FrontendDvbtHierarchy::AUTO,
+            .hpCoderate = FrontendDvbtCoderate::AUTO,
+            .lpCoderate = FrontendDvbtCoderate::AUTO,
+            .guardInterval = FrontendDvbtGuardInterval::AUTO,
+            .isHighPriority = true,
+            .standard = FrontendDvbtStandard::T,
+    };
+    frontendArray[DVBT].type = FrontendType::DVBT, frontendArray[DVBT].settings.dvbt(dvbtSettings);
+    vector<FrontendStatusType> types;
+    types.push_back(FrontendStatusType::DEMOD_LOCK);
+    FrontendStatus status;
+    status.isDemodLocked(true);
+    vector<FrontendStatus> statuses;
+    statuses.push_back(status);
+    frontendArray[DVBT].tuneStatusTypes = types;
+    frontendArray[DVBT].expectTuneStatuses = statuses;
+    frontendArray[DVBT].isSoftwareFe = true;
+    frontendArray[DVBS].type = FrontendType::DVBS;
+    frontendArray[DVBS].isSoftwareFe = true;
+};
+
+/** Configuration array for the filter test */
+inline void initFilterConfig() {
+    // TS VIDEO filter setting for default implementation testing
+    filterArray[TS_VIDEO0].type.mainType = DemuxFilterMainType::TS;
+    filterArray[TS_VIDEO0].type.subType.tsFilterType(DemuxTsFilterType::VIDEO);
+    filterArray[TS_VIDEO0].bufferSize = FMQ_SIZE_16M;
+    filterArray[TS_VIDEO0].settings.ts().tpid = 256;
+    filterArray[TS_VIDEO0].settings.ts().filterSettings.av({.isPassthrough = false});
+    filterArray[TS_VIDEO1].type.mainType = DemuxFilterMainType::TS;
+    filterArray[TS_VIDEO1].type.subType.tsFilterType(DemuxTsFilterType::VIDEO);
+    filterArray[TS_VIDEO1].bufferSize = FMQ_SIZE_16M;
+    filterArray[TS_VIDEO1].settings.ts().tpid = 256;
+    filterArray[TS_VIDEO1].settings.ts().filterSettings.av({.isPassthrough = false});
+    // TS AUDIO filter setting
+    filterArray[TS_AUDIO0].type.mainType = DemuxFilterMainType::TS;
+    filterArray[TS_AUDIO0].type.subType.tsFilterType(DemuxTsFilterType::AUDIO);
+    filterArray[TS_AUDIO0].bufferSize = FMQ_SIZE_16M;
+    filterArray[TS_AUDIO0].settings.ts().tpid = 256;
+    filterArray[TS_AUDIO0].settings.ts().filterSettings.av({.isPassthrough = false});
+    filterArray[TS_AUDIO1].type.mainType = DemuxFilterMainType::TS;
+    filterArray[TS_AUDIO1].type.subType.tsFilterType(DemuxTsFilterType::AUDIO);
+    filterArray[TS_AUDIO1].bufferSize = FMQ_SIZE_16M;
+    filterArray[TS_AUDIO1].settings.ts().tpid = 257;
+    filterArray[TS_AUDIO1].settings.ts().filterSettings.av({.isPassthrough = false});
+    // TS PES filter setting
+    filterArray[TS_PES0].type.mainType = DemuxFilterMainType::TS;
+    filterArray[TS_PES0].type.subType.tsFilterType(DemuxTsFilterType::PES);
+    filterArray[TS_PES0].bufferSize = FMQ_SIZE_16M;
+    filterArray[TS_PES0].settings.ts().tpid = 256;
+    filterArray[TS_PES0].settings.ts().filterSettings.pesData({
+            .isRaw = false,
+            .streamId = 0xbd,
+    });
+    // TS PCR filter setting
+    filterArray[TS_PCR0].type.mainType = DemuxFilterMainType::TS;
+    filterArray[TS_PCR0].type.subType.tsFilterType(DemuxTsFilterType::PCR);
+    filterArray[TS_PCR0].bufferSize = FMQ_SIZE_16M;
+    filterArray[TS_PCR0].settings.ts().tpid = 256;
+    filterArray[TS_PCR0].settings.ts().filterSettings.noinit();
+    // TS filter setting
+    filterArray[TS_TS0].type.mainType = DemuxFilterMainType::TS;
+    filterArray[TS_TS0].type.subType.tsFilterType(DemuxTsFilterType::TS);
+    filterArray[TS_TS0].bufferSize = FMQ_SIZE_16M;
+    filterArray[TS_TS0].settings.ts().tpid = 256;
+    filterArray[TS_TS0].settings.ts().filterSettings.noinit();
+    // TS SECTION filter setting
+    filterArray[TS_SECTION0].type.mainType = DemuxFilterMainType::TS;
+    filterArray[TS_SECTION0].type.subType.tsFilterType(DemuxTsFilterType::SECTION);
+    filterArray[TS_SECTION0].bufferSize = FMQ_SIZE_16M;
+    filterArray[TS_SECTION0].settings.ts().tpid = 256;
+    filterArray[TS_SECTION0].settings.ts().filterSettings.section({
+            .isRaw = false,
+    });
+    // TS RECORD filter setting
+    filterArray[TS_RECORD0].type.mainType = DemuxFilterMainType::TS;
+    filterArray[TS_RECORD0].type.subType.tsFilterType(DemuxTsFilterType::RECORD);
+    filterArray[TS_RECORD0].settings.ts().tpid = 256;
+    filterArray[TS_RECORD0].settings.ts().filterSettings.record({
+            .scIndexType = DemuxRecordScIndexType::NONE,
+    });
+};
+
+/** Configuration array for the dvr test */
+inline void initDvrConfig() {
+    RecordSettings recordSettings{
+            .statusMask = 0xf,
+            .lowThreshold = 0x1000,
+            .highThreshold = 0x07fff,
+            .dataFormat = DataFormat::TS,
+            .packetSize = 188,
+    };
+    dvrArray[DVR_RECORD0].type = DvrType::RECORD;
+    dvrArray[DVR_RECORD0].bufferSize = FMQ_SIZE_4M;
+    dvrArray[DVR_RECORD0].settings.record(recordSettings);
+    PlaybackSettings playbackSettings{
+            .statusMask = 0xf,
+            .lowThreshold = 0x1000,
+            .highThreshold = 0x07fff,
+            .dataFormat = DataFormat::TS,
+            .packetSize = 188,
+    };
+    dvrArray[DVR_PLAYBACK0].type = DvrType::PLAYBACK;
+    dvrArray[DVR_PLAYBACK0].playbackInputFile = "/data/local/tmp/segment000000.ts";
+    dvrArray[DVR_PLAYBACK0].bufferSize = FMQ_SIZE_4M;
+    dvrArray[DVR_PLAYBACK0].settings.playback(playbackSettings);
+};
diff --git a/usb/1.0/Android.bp b/usb/1.0/Android.bp
index c0e883f..607d1ac 100644
--- a/usb/1.0/Android.bp
+++ b/usb/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.usb@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IUsb.hal",
diff --git a/usb/1.1/Android.bp b/usb/1.1/Android.bp
index 6f2abae..8742e77 100644
--- a/usb/1.1/Android.bp
+++ b/usb/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.usb@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IUsb.hal",
diff --git a/usb/1.2/Android.bp b/usb/1.2/Android.bp
index b3ba81f..8b9f0fb 100644
--- a/usb/1.2/Android.bp
+++ b/usb/1.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.usb@1.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IUsb.hal",
diff --git a/usb/gadget/1.0/Android.bp b/usb/gadget/1.0/Android.bp
index 4921abf..21f152c 100644
--- a/usb/gadget/1.0/Android.bp
+++ b/usb/gadget/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.usb.gadget@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IUsbGadget.hal",
diff --git a/usb/gadget/1.1/Android.bp b/usb/gadget/1.1/Android.bp
index b41eb9c..e510069 100644
--- a/usb/gadget/1.1/Android.bp
+++ b/usb/gadget/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.usb.gadget@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "IUsbGadget.hal",
     ],
diff --git a/vibrator/1.0/Android.bp b/vibrator/1.0/Android.bp
index 792e130..d6321fb 100644
--- a/vibrator/1.0/Android.bp
+++ b/vibrator/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.vibrator@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IVibrator.hal",
diff --git a/vibrator/1.1/Android.bp b/vibrator/1.1/Android.bp
index 0d04a87..0302220 100644
--- a/vibrator/1.1/Android.bp
+++ b/vibrator/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.vibrator@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IVibrator.hal",
diff --git a/vibrator/1.2/Android.bp b/vibrator/1.2/Android.bp
index 290a0cf..1fa0114 100644
--- a/vibrator/1.2/Android.bp
+++ b/vibrator/1.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.vibrator@1.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IVibrator.hal",
diff --git a/vibrator/1.3/Android.bp b/vibrator/1.3/Android.bp
index 357ea9a..d742388 100644
--- a/vibrator/1.3/Android.bp
+++ b/vibrator/1.3/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.vibrator@1.3",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IVibrator.hal",
diff --git a/vibrator/aidl/default/Vibrator.cpp b/vibrator/aidl/default/Vibrator.cpp
index b359100..c446afd 100644
--- a/vibrator/aidl/default/Vibrator.cpp
+++ b/vibrator/aidl/default/Vibrator.cpp
@@ -163,6 +163,10 @@
             }
             LOG(INFO) << "triggering primitive " << static_cast<int>(e.primitive) << " @ scale "
                       << e.scale;
+
+            int32_t durationMs;
+            getPrimitiveDuration(e.primitive, &durationMs);
+            usleep(durationMs * 1000);
         }
 
         if (callback != nullptr) {
diff --git a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
index 8340517..c539865 100644
--- a/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
+++ b/vibrator/aidl/vts/VtsHalVibratorTargetTest.cpp
@@ -34,6 +34,7 @@
 using android::hardware::vibrator::Effect;
 using android::hardware::vibrator::EffectStrength;
 using android::hardware::vibrator::IVibrator;
+using std::chrono::high_resolution_clock;
 
 const std::vector<Effect> kEffects{android::enum_range<Effect>().begin(),
                                    android::enum_range<Effect>().end()};
@@ -442,26 +443,52 @@
 }
 
 TEST_P(VibratorAidl, ComposeCallback) {
+    constexpr std::chrono::milliseconds allowedLatency{10};
+
     if (capabilities & IVibrator::CAP_COMPOSE_EFFECTS) {
-        std::promise<void> completionPromise;
-        std::future<void> completionFuture{completionPromise.get_future()};
-        sp<CompletionCallback> callback =
-                new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
-        CompositePrimitive primitive = CompositePrimitive::CLICK;
-        CompositeEffect effect;
-        std::vector<CompositeEffect> composite;
-        int32_t duration;
+        std::vector<CompositePrimitive> supported;
 
-        effect.delayMs = 0;
-        effect.primitive = primitive;
-        effect.scale = 1.0f;
-        composite.emplace_back(effect);
+        ASSERT_TRUE(vibrator->getSupportedPrimitives(&supported).isOk());
 
-        EXPECT_EQ(Status::EX_NONE,
-                  vibrator->getPrimitiveDuration(primitive, &duration).exceptionCode());
-        EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode());
-        EXPECT_EQ(completionFuture.wait_for(std::chrono::milliseconds(duration * 2)),
-                  std::future_status::ready);
+        for (auto primitive : supported) {
+            if (primitive == CompositePrimitive::NOOP) {
+                continue;
+            }
+
+            std::promise<void> completionPromise;
+            std::future<void> completionFuture{completionPromise.get_future()};
+            sp<CompletionCallback> callback =
+                    new CompletionCallback([&completionPromise] { completionPromise.set_value(); });
+            CompositeEffect effect;
+            std::vector<CompositeEffect> composite;
+            int32_t durationMs;
+            std::chrono::milliseconds duration;
+            std::chrono::time_point<high_resolution_clock> start, end;
+            std::chrono::milliseconds elapsed;
+
+            effect.delayMs = 0;
+            effect.primitive = primitive;
+            effect.scale = 1.0f;
+            composite.emplace_back(effect);
+
+            EXPECT_EQ(Status::EX_NONE,
+                      vibrator->getPrimitiveDuration(primitive, &durationMs).exceptionCode())
+                    << toString(primitive);
+            duration = std::chrono::milliseconds(durationMs);
+
+            EXPECT_EQ(Status::EX_NONE, vibrator->compose(composite, callback).exceptionCode())
+                    << toString(primitive);
+            start = high_resolution_clock::now();
+
+            EXPECT_EQ(completionFuture.wait_for(duration + allowedLatency),
+                      std::future_status::ready)
+                    << toString(primitive);
+            end = high_resolution_clock::now();
+
+            elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
+            EXPECT_LE(elapsed.count(), (duration + allowedLatency).count()) << toString(primitive);
+            EXPECT_GE(elapsed.count(), (duration - allowedLatency).count()) << toString(primitive);
+        }
     }
 }
 
diff --git a/vr/1.0/Android.bp b/vr/1.0/Android.bp
index f91f874..769ee3b 100644
--- a/vr/1.0/Android.bp
+++ b/vr/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.vr@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "IVr.hal",
     ],
diff --git a/weaver/1.0/Android.bp b/weaver/1.0/Android.bp
index 7d5b8fe..11fc685 100644
--- a/weaver/1.0/Android.bp
+++ b/weaver/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.weaver@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IWeaver.hal",
diff --git a/wifi/1.0/Android.bp b/wifi/1.0/Android.bp
index 958ff3f..c41864f 100644
--- a/wifi/1.0/Android.bp
+++ b/wifi/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.wifi@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IWifi.hal",
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index 793dd8c..14a8509 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -23,14 +23,14 @@
         "wifi_hidl_test_utils.cpp",
     ],
     export_include_dirs: [
-        "."
+        ".",
     ],
     shared_libs: [
         "libnativehelper",
     ],
     static_libs: [
         "android.hardware.wifi@1.0",
-        "libwifi-system-iface"
+        "libwifi-system-iface",
     ],
 }
 
@@ -49,9 +49,12 @@
         "android.hardware.wifi@1.1",
         "android.hardware.wifi@1.2",
         "android.hardware.wifi@1.3",
-        "libwifi-system-iface"
+        "libwifi-system-iface",
     ],
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
 
 // These tests are split out so that they can be conditioned on presence of the
@@ -66,9 +69,12 @@
     static_libs: [
         "VtsHalWifiV1_0TargetTestUtil",
         "android.hardware.wifi@1.0",
-        "libwifi-system-iface"
+        "libwifi-system-iface",
     ],
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
 
 // These tests are split out so that they can be conditioned on presence of
@@ -83,7 +89,10 @@
     static_libs: [
         "VtsHalWifiV1_0TargetTestUtil",
         "android.hardware.wifi@1.0",
-        "libwifi-system-iface"
+        "libwifi-system-iface",
     ],
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
diff --git a/wifi/1.0/vts/functional/wifi_chip_hidl_nan_test.cpp b/wifi/1.0/vts/functional/wifi_chip_hidl_nan_test.cpp
index c95f4d2..bb7a3a6 100644
--- a/wifi/1.0/vts/functional/wifi_chip_hidl_nan_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_chip_hidl_nan_test.cpp
@@ -16,6 +16,7 @@
 
 #include <android-base/logging.h>
 
+#include <VtsCoreUtil.h>
 #include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/1.0/IWifiChip.h>
 #include <gtest/gtest.h>
@@ -41,6 +42,9 @@
 class WifiChipHidlNanTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
+        if (!::testing::deviceSupportsFeature("android.hardware.wifi.aware"))
+            GTEST_SKIP() << "Skipping this test since NAN is not supported.";
+
         // Make sure test starts with a clean state
         stopWifi(GetInstanceName());
 
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
index 3ff33a5..5b11dd3 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
@@ -89,8 +89,12 @@
 }
 }  // namespace
 
+sp<IWifi> getWifi(const std::string& instance_name) {
+    return IWifi::getService(instance_name);
+}
+
 sp<IWifiChip> getWifiChip(const std::string& instance_name) {
-    sp<IWifi> wifi = IWifi::getService(instance_name);
+    sp<IWifi> wifi = getWifi(instance_name);
     if (!wifi.get()) {
         return nullptr;
     }
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
index d22ed77..5c78637 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.h
@@ -31,6 +31,8 @@
 // Note: We only have a single instance of each of these objects currently.
 // These helper functions should be modified to return vectors if we support
 // multiple instances.
+android::sp<android::hardware::wifi::V1_0::IWifi> getWifi(
+    const std::string& instance_name);
 android::sp<android::hardware::wifi::V1_0::IWifiChip> getWifiChip(
     const std::string& instance_name);
 android::sp<android::hardware::wifi::V1_0::IWifiApIface> getWifiApIface(
diff --git a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp
index 47a1938..2b63ddc 100644
--- a/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_nan_iface_hidl_test.cpp
@@ -16,6 +16,7 @@
 
 #include <android-base/logging.h>
 
+#include <VtsCoreUtil.h>
 #include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/1.0/IWifiNanIface.h>
 #include <android/hardware/wifi/1.0/IWifiNanIfaceEventCallback.h>
@@ -44,6 +45,9 @@
 class WifiNanIfaceHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
+        if (!::testing::deviceSupportsFeature("android.hardware.wifi.aware"))
+            GTEST_SKIP() << "Skipping this test since NAN is not supported.";
+
         // Make sure test starts with a clean state
         stopWifi(GetInstanceName());
 
diff --git a/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp
index 1014c1d..3c9ed9e 100644
--- a/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_rtt_controller_hidl_test.cpp
@@ -16,6 +16,7 @@
 
 #include <android-base/logging.h>
 
+#include <VtsCoreUtil.h>
 #include <android/hardware/wifi/1.0/IWifi.h>
 #include <android/hardware/wifi/1.0/IWifiRttController.h>
 #include <gtest/gtest.h>
@@ -38,6 +39,8 @@
 class WifiRttControllerHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
+        if (!::testing::deviceSupportsFeature("android.hardware.wifi.rtt"))
+            GTEST_SKIP() << "Skipping this test since RTT is not supported.";
         // Make sure test starts with a clean state
         stopWifi(GetInstanceName());
     }
diff --git a/wifi/1.1/Android.bp b/wifi/1.1/Android.bp
index a34ac44..4068b31 100644
--- a/wifi/1.1/Android.bp
+++ b/wifi/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.wifi@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "IWifi.hal",
         "IWifiChip.hal",
diff --git a/wifi/1.1/vts/functional/Android.bp b/wifi/1.1/vts/functional/Android.bp
index eb68bc0..7dc78e4 100644
--- a/wifi/1.1/vts/functional/Android.bp
+++ b/wifi/1.1/vts/functional/Android.bp
@@ -18,14 +18,18 @@
     name: "VtsHalWifiV1_1TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
-        "wifi_chip_hidl_test.cpp"],
+        "wifi_chip_hidl_test.cpp",
+    ],
     static_libs: [
         "VtsHalWifiV1_0TargetTestUtil",
         "android.hardware.wifi@1.0",
         "android.hardware.wifi@1.1",
         "android.hardware.wifi@1.2",
         "android.hardware.wifi@1.3",
-        "libwifi-system-iface"
+        "libwifi-system-iface",
     ],
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
diff --git a/wifi/1.2/Android.bp b/wifi/1.2/Android.bp
index c28d09b..5812b82 100644
--- a/wifi/1.2/Android.bp
+++ b/wifi/1.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.wifi@1.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IWifi.hal",
diff --git a/wifi/1.2/vts/functional/Android.bp b/wifi/1.2/vts/functional/Android.bp
index 90bcac1..159ba94 100644
--- a/wifi/1.2/vts/functional/Android.bp
+++ b/wifi/1.2/vts/functional/Android.bp
@@ -27,10 +27,13 @@
         "android.hardware.wifi@1.1",
         "android.hardware.wifi@1.2",
         "android.hardware.wifi@1.3",
-        "libwifi-system-iface"
+        "libwifi-system-iface",
     ],
     disable_framework: true,
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
 
 cc_test {
@@ -44,8 +47,10 @@
         "android.hardware.wifi@1.0",
         "android.hardware.wifi@1.1",
         "android.hardware.wifi@1.2",
-        "libwifi-system-iface"
+        "libwifi-system-iface",
     ],
-    disable_framework: true,
-    test_suites: ["general-tests", "vts"],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
 }
diff --git a/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp
index 96656f3..bc392a9 100644
--- a/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp
+++ b/wifi/1.2/vts/functional/wifi_nan_iface_hidl_test.cpp
@@ -16,6 +16,7 @@
 
 #include <android-base/logging.h>
 
+#include <VtsCoreUtil.h>
 #include <android/hardware/wifi/1.2/IWifi.h>
 #include <android/hardware/wifi/1.2/IWifiNanIface.h>
 #include <android/hardware/wifi/1.2/IWifiNanIfaceEventCallback.h>
@@ -50,6 +51,8 @@
 class WifiNanIfaceHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
+        if (!::testing::deviceSupportsFeature("android.hardware.wifi.aware"))
+            GTEST_SKIP() << "Skipping this test since NAN is not supported.";
         // Make sure to start with a clean state
         stopWifi(GetInstanceName());
 
diff --git a/wifi/1.3/Android.bp b/wifi/1.3/Android.bp
index 3719c2b..f4e130a 100644
--- a/wifi/1.3/Android.bp
+++ b/wifi/1.3/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.wifi@1.3",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IWifi.hal",
diff --git a/wifi/1.4/Android.bp b/wifi/1.4/Android.bp
index 3b94619..5620d03 100644
--- a/wifi/1.4/Android.bp
+++ b/wifi/1.4/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.wifi@1.4",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IWifi.hal",
diff --git a/wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc b/wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc
deleted file mode 100644
index cf917b5..0000000
--- a/wifi/1.4/default/android.hardware.wifi@1.0-service-lazy.rc
+++ /dev/null
@@ -1,8 +0,0 @@
-service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service-lazy
-    interface android.hardware.wifi@1.0::IWifi default
-    oneshot
-    disabled
-    class hal
-    capabilities NET_ADMIN NET_RAW SYS_MODULE
-    user wifi
-    group wifi gps
diff --git a/wifi/1.4/vts/functional/Android.bp b/wifi/1.4/vts/functional/Android.bp
index 3824c3a..59a35e0 100644
--- a/wifi/1.4/vts/functional/Android.bp
+++ b/wifi/1.4/vts/functional/Android.bp
@@ -21,7 +21,51 @@
     srcs: [
         "wifi_ap_iface_hidl_test.cpp",
         "wifi_chip_hidl_test.cpp",
+    ],
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.1",
+        "android.hardware.wifi@1.2",
+        "android.hardware.wifi@1.3",
+        "android.hardware.wifi@1.4",
+        "libwifi-system-iface",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
+
+// These tests are split out so that they can be conditioned on presence of the
+// "android.hardware.wifi.aware" feature.
+cc_test {
+    name: "VtsHalWifiNanV1_4TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
         "wifi_nan_iface_hidl_test.cpp",
+    ],
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.1",
+        "android.hardware.wifi@1.2",
+        "android.hardware.wifi@1.3",
+        "android.hardware.wifi@1.4",
+        "libwifi-system-iface",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts",
+    ],
+}
+
+// These tests are split out so that they can be conditioned on presence of the
+// "android.hardware.wifi.rtt" feature.
+cc_test {
+    name: "VtsHalWifiRttV1_4TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
         "wifi_rtt_controller_hidl_test.cpp",
     ],
     static_libs: [
diff --git a/wifi/1.4/vts/functional/wifi_chip_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_chip_hidl_test.cpp
index 1c39550..be5c3bd 100644
--- a/wifi/1.4/vts/functional/wifi_chip_hidl_test.cpp
+++ b/wifi/1.4/vts/functional/wifi_chip_hidl_test.cpp
@@ -150,28 +150,6 @@
     }
 }
 
-/*
- * createRttController_1_4
- * Ensures that an instance of the IWifiRttController proxy object is
- * successfully created.
- */
-TEST_P(WifiChipHidlTest, createRttController_1_4) {
-    configureChipForIfaceType(IfaceType::STA, true);
-
-    const auto& status_and_iface = HIDL_INVOKE(wifi_chip_, createStaIface);
-    EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_iface.first.code);
-    sp<IWifiStaIface> iface = IWifiStaIface::castFrom(status_and_iface.second);
-    EXPECT_NE(nullptr, iface.get());
-
-    const auto& status_and_controller =
-        HIDL_INVOKE(wifi_chip_, createRttController_1_4, iface);
-    if (status_and_controller.first.code !=
-        WifiStatusCode::ERROR_NOT_SUPPORTED) {
-        EXPECT_EQ(WifiStatusCode::SUCCESS, status_and_controller.first.code);
-        EXPECT_NE(nullptr, status_and_controller.second.get());
-    }
-}
-
 INSTANTIATE_TEST_SUITE_P(
     PerInstance, WifiChipHidlTest,
     testing::ValuesIn(android::hardware::getAllHalInstanceNames(
diff --git a/wifi/1.4/vts/functional/wifi_nan_iface_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_nan_iface_hidl_test.cpp
index 24daee6..f6a1147 100644
--- a/wifi/1.4/vts/functional/wifi_nan_iface_hidl_test.cpp
+++ b/wifi/1.4/vts/functional/wifi_nan_iface_hidl_test.cpp
@@ -16,6 +16,7 @@
 
 #include <android-base/logging.h>
 
+#include <VtsCoreUtil.h>
 #include <android/hardware/wifi/1.2/IWifiNanIfaceEventCallback.h>
 #include <android/hardware/wifi/1.4/IWifi.h>
 #include <android/hardware/wifi/1.4/IWifiNanIface.h>
@@ -51,6 +52,8 @@
 class WifiNanIfaceHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
+        if (!::testing::deviceSupportsFeature("android.hardware.wifi.aware"))
+            GTEST_SKIP() << "Skipping this test since NAN is not supported.";
         // Make sure to start with a clean state
         stopWifi(GetInstanceName());
 
diff --git a/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp b/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
index 4035fb8..a099c8a 100644
--- a/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
+++ b/wifi/1.4/vts/functional/wifi_rtt_controller_hidl_test.cpp
@@ -19,6 +19,7 @@
 
 #undef NAN  // NAN is defined in bionic/libc/include/math.h:38
 
+#include <VtsCoreUtil.h>
 #include <android/hardware/wifi/1.3/IWifiStaIface.h>
 #include <android/hardware/wifi/1.4/IWifi.h>
 #include <android/hardware/wifi/1.4/IWifiChip.h>
@@ -59,6 +60,8 @@
 class WifiRttControllerHidlTest : public ::testing::TestWithParam<std::string> {
    public:
     virtual void SetUp() override {
+        if (!::testing::deviceSupportsFeature("android.hardware.wifi.rtt"))
+            GTEST_SKIP() << "Skipping this test since RTT is not supported.";
         // Make sure to start with a clean state
         stopWifi(GetInstanceName());
 
@@ -222,8 +225,8 @@
     int cmdId = 55;
     WifiChannelInfo channelInfo;
     channelInfo.width = WifiChannelWidthInMhz::WIDTH_80;
-    channelInfo.centerFreq = 5690;
-    channelInfo.centerFreq0 = 5690;
+    channelInfo.centerFreq = 5660;
+    channelInfo.centerFreq0 = 5660;
     channelInfo.centerFreq1 = 0;
 
     // Get the responder first
diff --git a/wifi/1.5/Android.bp b/wifi/1.5/Android.bp
new file mode 100644
index 0000000..37a1cf3
--- /dev/null
+++ b/wifi/1.5/Android.bp
@@ -0,0 +1,21 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.wifi@1.5",
+    root: "android.hardware",
+    srcs: [
+        "IWifi.hal",
+    ],
+    interfaces: [
+        "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.1",
+        "android.hardware.wifi@1.2",
+        "android.hardware.wifi@1.3",
+        "android.hardware.wifi@1.4",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+    apex_available: [
+        "com.android.wifi",
+    ],
+}
diff --git a/wifi/1.5/IWifi.hal b/wifi/1.5/IWifi.hal
new file mode 100644
index 0000000..66d0a9c
--- /dev/null
+++ b/wifi/1.5/IWifi.hal
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi@1.5;
+
+import @1.4::IWifi;
+
+/**
+ * This is the root of the HAL module and is the interface returned when
+ * loading an implementation of the Wi-Fi HAL. There must be at most one
+ * module loaded in the system.
+ * IWifi.getChip() must return @1.5::IWifiChip
+ */
+interface IWifi extends @1.4::IWifi {};
diff --git a/wifi/1.4/default/Android.mk b/wifi/1.5/default/Android.mk
similarity index 95%
rename from wifi/1.4/default/Android.mk
rename to wifi/1.5/default/Android.mk
index 6be7dad..236dae2 100644
--- a/wifi/1.4/default/Android.mk
+++ b/wifi/1.5/default/Android.mk
@@ -71,7 +71,8 @@
     android.hardware.wifi@1.1 \
     android.hardware.wifi@1.2 \
     android.hardware.wifi@1.3 \
-    android.hardware.wifi@1.4
+    android.hardware.wifi@1.4 \
+    android.hardware.wifi@1.5
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)
 include $(BUILD_STATIC_LIBRARY)
 
@@ -99,7 +100,8 @@
     android.hardware.wifi@1.1 \
     android.hardware.wifi@1.2 \
     android.hardware.wifi@1.3 \
-    android.hardware.wifi@1.4
+    android.hardware.wifi@1.4 \
+    android.hardware.wifi@1.5
 LOCAL_STATIC_LIBRARIES := \
     android.hardware.wifi@1.0-service-lib
 LOCAL_INIT_RC := android.hardware.wifi@1.0-service.rc
@@ -131,7 +133,8 @@
     android.hardware.wifi@1.1 \
     android.hardware.wifi@1.2 \
     android.hardware.wifi@1.3 \
-    android.hardware.wifi@1.4
+    android.hardware.wifi@1.4 \
+    android.hardware.wifi@1.5
 LOCAL_STATIC_LIBRARIES := \
     android.hardware.wifi@1.0-service-lib
 LOCAL_INIT_RC := android.hardware.wifi@1.0-service-lazy.rc
@@ -164,6 +167,7 @@
     android.hardware.wifi@1.2 \
     android.hardware.wifi@1.3 \
     android.hardware.wifi@1.4 \
+    android.hardware.wifi@1.5 \
     android.hardware.wifi@1.0-service-lib
 LOCAL_SHARED_LIBRARIES := \
     libbase \
diff --git a/wifi/1.4/default/OWNERS b/wifi/1.5/default/OWNERS
similarity index 100%
rename from wifi/1.4/default/OWNERS
rename to wifi/1.5/default/OWNERS
diff --git a/wifi/1.4/default/THREADING.README b/wifi/1.5/default/THREADING.README
similarity index 100%
rename from wifi/1.4/default/THREADING.README
rename to wifi/1.5/default/THREADING.README
diff --git a/wifi/1.4/default/android.hardware.wifi@1.0-service.rc b/wifi/1.5/default/android.hardware.wifi@1.0-service-lazy.rc
similarity index 89%
rename from wifi/1.4/default/android.hardware.wifi@1.0-service.rc
rename to wifi/1.5/default/android.hardware.wifi@1.0-service-lazy.rc
index 64a51b0..061689d 100644
--- a/wifi/1.4/default/android.hardware.wifi@1.0-service.rc
+++ b/wifi/1.5/default/android.hardware.wifi@1.0-service-lazy.rc
@@ -1,9 +1,11 @@
-service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service
+service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service-lazy
     interface android.hardware.wifi@1.0::IWifi default
     interface android.hardware.wifi@1.1::IWifi default
     interface android.hardware.wifi@1.2::IWifi default
     interface android.hardware.wifi@1.3::IWifi default
     interface android.hardware.wifi@1.4::IWifi default
+    oneshot
+    disabled
     class hal
     capabilities NET_ADMIN NET_RAW SYS_MODULE
     user wifi
diff --git a/wifi/1.4/default/android.hardware.wifi@1.0-service.rc b/wifi/1.5/default/android.hardware.wifi@1.0-service.rc
similarity index 88%
copy from wifi/1.4/default/android.hardware.wifi@1.0-service.rc
copy to wifi/1.5/default/android.hardware.wifi@1.0-service.rc
index 64a51b0..05706ef 100644
--- a/wifi/1.4/default/android.hardware.wifi@1.0-service.rc
+++ b/wifi/1.5/default/android.hardware.wifi@1.0-service.rc
@@ -4,6 +4,7 @@
     interface android.hardware.wifi@1.2::IWifi default
     interface android.hardware.wifi@1.3::IWifi default
     interface android.hardware.wifi@1.4::IWifi default
+    interface android.hardware.wifi@1.5::IWifi default
     class hal
     capabilities NET_ADMIN NET_RAW SYS_MODULE
     user wifi
diff --git a/wifi/1.4/default/android.hardware.wifi@1.0-service.xml b/wifi/1.5/default/android.hardware.wifi@1.0-service.xml
similarity index 89%
rename from wifi/1.4/default/android.hardware.wifi@1.0-service.xml
rename to wifi/1.5/default/android.hardware.wifi@1.0-service.xml
index b5d25cd..88dd1e3 100644
--- a/wifi/1.4/default/android.hardware.wifi@1.0-service.xml
+++ b/wifi/1.5/default/android.hardware.wifi@1.0-service.xml
@@ -2,7 +2,7 @@
     <hal format="hidl">
         <name>android.hardware.wifi</name>
         <transport>hwbinder</transport>
-        <version>1.4</version>
+        <version>1.5</version>
         <interface>
             <name>IWifi</name>
             <instance>default</instance>
diff --git a/wifi/1.4/default/hidl_callback_util.h b/wifi/1.5/default/hidl_callback_util.h
similarity index 98%
rename from wifi/1.4/default/hidl_callback_util.h
rename to wifi/1.5/default/hidl_callback_util.h
index fc601b8..d144658 100644
--- a/wifi/1.4/default/hidl_callback_util.h
+++ b/wifi/1.5/default/hidl_callback_util.h
@@ -52,7 +52,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace hidl_callback_util {
 template <typename CallbackType>
@@ -117,7 +117,7 @@
 
 }  // namespace hidl_callback_util
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/hidl_return_util.h b/wifi/1.5/default/hidl_return_util.h
similarity index 98%
rename from wifi/1.4/default/hidl_return_util.h
rename to wifi/1.5/default/hidl_return_util.h
index 99c7092..4455185 100644
--- a/wifi/1.4/default/hidl_return_util.h
+++ b/wifi/1.5/default/hidl_return_util.h
@@ -23,7 +23,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace hidl_return_util {
 using namespace android::hardware::wifi::V1_0;
@@ -113,7 +113,7 @@
 
 }  // namespace hidl_return_util
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/hidl_struct_util.cpp b/wifi/1.5/default/hidl_struct_util.cpp
similarity index 97%
rename from wifi/1.4/default/hidl_struct_util.cpp
rename to wifi/1.5/default/hidl_struct_util.cpp
index fd1d5b1..a155ff8 100644
--- a/wifi/1.4/default/hidl_struct_util.cpp
+++ b/wifi/1.5/default/hidl_struct_util.cpp
@@ -22,7 +22,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace hidl_struct_util {
 
@@ -314,7 +314,7 @@
 
 bool convertLegacyWifiMacInfoToHidl(
     const legacy_hal::WifiMacInfo& legacy_mac_info,
-    IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) {
+    V1_4::IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) {
     if (!hidl_radio_mode_info) {
         return false;
     }
@@ -326,21 +326,21 @@
     if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND &&
         legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND &&
         legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND) {
-        hidl_radio_mode_info->bandInfo = WifiBand::BAND_24GHZ_5GHZ_6GHZ;
+        hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_24GHZ_5GHZ_6GHZ;
     } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND &&
                legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) {
-        hidl_radio_mode_info->bandInfo = WifiBand::BAND_5GHZ_6GHZ;
+        hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_5GHZ_6GHZ;
     } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND) {
-        hidl_radio_mode_info->bandInfo = WifiBand::BAND_6GHZ;
+        hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_6GHZ;
     } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND &&
                legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) {
-        hidl_radio_mode_info->bandInfo = WifiBand::BAND_24GHZ_5GHZ;
+        hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_24GHZ_5GHZ;
     } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND) {
-        hidl_radio_mode_info->bandInfo = WifiBand::BAND_24GHZ;
+        hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_24GHZ;
     } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) {
-        hidl_radio_mode_info->bandInfo = WifiBand::BAND_5GHZ;
+        hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_5GHZ;
     } else {
-        hidl_radio_mode_info->bandInfo = WifiBand::BAND_UNSPECIFIED;
+        hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_UNSPECIFIED;
     }
     std::vector<V1_2::IWifiChipEventCallback::IfaceInfo> iface_info_vec;
     for (const auto& legacy_iface_info : legacy_mac_info.iface_infos) {
@@ -355,14 +355,15 @@
 
 bool convertLegacyWifiMacInfosToHidl(
     const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos,
-    std::vector<IWifiChipEventCallback::RadioModeInfo>* hidl_radio_mode_infos) {
+    std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo>*
+        hidl_radio_mode_infos) {
     if (!hidl_radio_mode_infos) {
         return false;
     }
     *hidl_radio_mode_infos = {};
 
     for (const auto& legacy_mac_info : legacy_mac_infos) {
-        IWifiChipEventCallback::RadioModeInfo hidl_radio_mode_info;
+        V1_4::IWifiChipEventCallback::RadioModeInfo hidl_radio_mode_info;
         if (!convertLegacyWifiMacInfoToHidl(legacy_mac_info,
                                             &hidl_radio_mode_info)) {
             return false;
@@ -1079,7 +1080,7 @@
 }
 
 bool convertHidlNanEnableRequestToLegacy(
-    const NanEnableRequest& hidl_request,
+    const V1_4::NanEnableRequest& hidl_request,
     legacy_hal::NanEnableRequest* legacy_request) {
     if (!legacy_request) {
         LOG(ERROR)
@@ -1275,7 +1276,7 @@
 }
 
 bool convertHidlNanEnableRequest_1_4ToLegacy(
-    const NanEnableRequest& hidl_request1,
+    const V1_4::NanEnableRequest& hidl_request1,
     const V1_2::NanConfigRequestSupplemental& hidl_request2,
     legacy_hal::NanEnableRequest* legacy_request) {
     if (!legacy_request) {
@@ -1674,7 +1675,7 @@
 }
 
 bool convertHidlNanConfigRequestToLegacy(
-    const NanConfigRequest& hidl_request,
+    const V1_4::NanConfigRequest& hidl_request,
     legacy_hal::NanConfigRequest* legacy_request) {
     if (!legacy_request) {
         LOG(ERROR)
@@ -1789,7 +1790,7 @@
 }
 
 bool convertHidlNanConfigRequest_1_4ToLegacy(
-    const NanConfigRequest& hidl_request1,
+    const V1_4::NanConfigRequest& hidl_request1,
     const V1_2::NanConfigRequestSupplemental& hidl_request2,
     legacy_hal::NanConfigRequest* legacy_request) {
     if (!legacy_request) {
@@ -2298,30 +2299,32 @@
     CHECK(false) << "Unknown legacy type: " << type;
 }
 
-legacy_hal::wifi_rtt_preamble convertHidlRttPreambleToLegacy(RttPreamble type) {
+legacy_hal::wifi_rtt_preamble convertHidlRttPreambleToLegacy(
+    V1_4::RttPreamble type) {
     switch (type) {
-        case RttPreamble::LEGACY:
+        case V1_4::RttPreamble::LEGACY:
             return legacy_hal::WIFI_RTT_PREAMBLE_LEGACY;
-        case RttPreamble::HT:
+        case V1_4::RttPreamble::HT:
             return legacy_hal::WIFI_RTT_PREAMBLE_HT;
-        case RttPreamble::VHT:
+        case V1_4::RttPreamble::VHT:
             return legacy_hal::WIFI_RTT_PREAMBLE_VHT;
-        case RttPreamble::HE:
+        case V1_4::RttPreamble::HE:
             return legacy_hal::WIFI_RTT_PREAMBLE_HE;
     };
     CHECK(false);
 }
 
-RttPreamble convertLegacyRttPreambleToHidl(legacy_hal::wifi_rtt_preamble type) {
+V1_4::RttPreamble convertLegacyRttPreambleToHidl(
+    legacy_hal::wifi_rtt_preamble type) {
     switch (type) {
         case legacy_hal::WIFI_RTT_PREAMBLE_LEGACY:
-            return RttPreamble::LEGACY;
+            return V1_4::RttPreamble::LEGACY;
         case legacy_hal::WIFI_RTT_PREAMBLE_HT:
-            return RttPreamble::HT;
+            return V1_4::RttPreamble::HT;
         case legacy_hal::WIFI_RTT_PREAMBLE_VHT:
-            return RttPreamble::VHT;
+            return V1_4::RttPreamble::VHT;
         case legacy_hal::WIFI_RTT_PREAMBLE_HE:
-            return RttPreamble::HE;
+            return V1_4::RttPreamble::HE;
     };
     CHECK(false) << "Unknown legacy type: " << type;
 }
@@ -2375,20 +2378,20 @@
     CHECK(false);
 }
 
-WifiRatePreamble convertLegacyWifiRatePreambleToHidl(uint8_t preamble) {
+V1_4::WifiRatePreamble convertLegacyWifiRatePreambleToHidl(uint8_t preamble) {
     switch (preamble) {
         case 0:
-            return WifiRatePreamble::OFDM;
+            return V1_4::WifiRatePreamble::OFDM;
         case 1:
-            return WifiRatePreamble::CCK;
+            return V1_4::WifiRatePreamble::CCK;
         case 2:
-            return WifiRatePreamble::HT;
+            return V1_4::WifiRatePreamble::HT;
         case 3:
-            return WifiRatePreamble::VHT;
+            return V1_4::WifiRatePreamble::VHT;
         case 4:
-            return WifiRatePreamble::HE;
+            return V1_4::WifiRatePreamble::HE;
         default:
-            return WifiRatePreamble::RESERVED;
+            return V1_4::WifiRatePreamble::RESERVED;
     };
     CHECK(false) << "Unknown legacy preamble: " << preamble;
 }
@@ -2478,7 +2481,7 @@
     return true;
 }
 
-bool convertHidlRttConfigToLegacy(const RttConfig& hidl_config,
+bool convertHidlRttConfigToLegacy(const V1_4::RttConfig& hidl_config,
                                   legacy_hal::wifi_rtt_config* legacy_config) {
     if (!legacy_config) {
         return false;
@@ -2509,7 +2512,7 @@
 }
 
 bool convertHidlVectorOfRttConfigToLegacy(
-    const std::vector<RttConfig>& hidl_configs,
+    const std::vector<V1_4::RttConfig>& hidl_configs,
     std::vector<legacy_hal::wifi_rtt_config>* legacy_configs) {
     if (!legacy_configs) {
         return false;
@@ -2566,7 +2569,7 @@
 }
 
 bool convertHidlRttResponderToLegacy(
-    const RttResponder& hidl_responder,
+    const V1_4::RttResponder& hidl_responder,
     legacy_hal::wifi_rtt_responder* legacy_responder) {
     if (!legacy_responder) {
         return false;
@@ -2583,7 +2586,7 @@
 
 bool convertLegacyRttResponderToHidl(
     const legacy_hal::wifi_rtt_responder& legacy_responder,
-    RttResponder* hidl_responder) {
+    V1_4::RttResponder* hidl_responder) {
     if (!hidl_responder) {
         return false;
     }
@@ -2599,7 +2602,7 @@
 
 bool convertLegacyRttCapabilitiesToHidl(
     const legacy_hal::wifi_rtt_capabilities& legacy_capabilities,
-    RttCapabilities* hidl_capabilities) {
+    V1_4::RttCapabilities* hidl_capabilities) {
     if (!hidl_capabilities) {
         return false;
     }
@@ -2618,7 +2621,7 @@
           legacy_hal::WIFI_RTT_PREAMBLE_HE}) {
         if (legacy_capabilities.preamble_support & flag) {
             hidl_capabilities->preambleSupport |=
-                static_cast<std::underlying_type<RttPreamble>::type>(
+                static_cast<std::underlying_type<V1_4::RttPreamble>::type>(
                     convertLegacyRttPreambleToHidl(flag));
         }
     }
@@ -2638,7 +2641,7 @@
 }
 
 bool convertLegacyWifiRateInfoToHidl(const legacy_hal::wifi_rate& legacy_rate,
-                                     WifiRateInfo* hidl_rate) {
+                                     V1_4::WifiRateInfo* hidl_rate) {
     if (!hidl_rate) {
         return false;
     }
@@ -2654,7 +2657,8 @@
 }
 
 bool convertLegacyRttResultToHidl(
-    const legacy_hal::wifi_rtt_result& legacy_result, RttResult* hidl_result) {
+    const legacy_hal::wifi_rtt_result& legacy_result,
+    V1_4::RttResult* hidl_result) {
     if (!hidl_result) {
         return false;
     }
@@ -2701,13 +2705,13 @@
 
 bool convertLegacyVectorOfRttResultToHidl(
     const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
-    std::vector<RttResult>* hidl_results) {
+    std::vector<V1_4::RttResult>* hidl_results) {
     if (!hidl_results) {
         return false;
     }
     *hidl_results = {};
     for (const auto legacy_result : legacy_results) {
-        RttResult hidl_result;
+        V1_4::RttResult hidl_result;
         if (!convertLegacyRttResultToHidl(*legacy_result, &hidl_result)) {
             return false;
         }
@@ -2732,7 +2736,7 @@
 }
 }  // namespace hidl_struct_util
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/hidl_struct_util.h b/wifi/1.5/default/hidl_struct_util.h
similarity index 93%
rename from wifi/1.4/default/hidl_struct_util.h
rename to wifi/1.5/default/hidl_struct_util.h
index 929f877..b6567ff 100644
--- a/wifi/1.4/default/hidl_struct_util.h
+++ b/wifi/1.5/default/hidl_struct_util.h
@@ -38,7 +38,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace hidl_struct_util {
 using namespace android::hardware::wifi::V1_0;
@@ -64,7 +64,8 @@
     V1_2::IWifiChip::TxPowerScenario hidl_scenario);
 bool convertLegacyWifiMacInfosToHidl(
     const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos,
-    std::vector<IWifiChipEventCallback::RadioModeInfo>* hidl_radio_mode_infos);
+    std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo>*
+        hidl_radio_mode_infos);
 legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy(
     IfaceType hidl_interface_type);
 
@@ -114,17 +115,17 @@
 void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str,
                             size_t max_len, WifiNanStatus* wifiNanStatus);
 bool convertHidlNanEnableRequestToLegacy(
-    const NanEnableRequest& hidl_request,
+    const V1_4::NanEnableRequest& hidl_request,
     legacy_hal::NanEnableRequest* legacy_request);
 bool convertHidlNanConfigRequestToLegacy(
-    const NanConfigRequest& hidl_request,
+    const V1_4::NanConfigRequest& hidl_request,
     legacy_hal::NanConfigRequest* legacy_request);
 bool convertHidlNanEnableRequest_1_4ToLegacy(
-    const NanEnableRequest& hidl_request1,
+    const V1_4::NanEnableRequest& hidl_request1,
     const V1_2::NanConfigRequestSupplemental& hidl_request2,
     legacy_hal::NanEnableRequest* legacy_request);
 bool convertHidlNanConfigRequest_1_4ToLegacy(
-    const NanConfigRequest& hidl_request1,
+    const V1_4::NanConfigRequest& hidl_request1,
     const V1_2::NanConfigRequestSupplemental& hidl_request2,
     legacy_hal::NanConfigRequest* legacy_request);
 bool convertHidlNanPublishRequestToLegacy(
@@ -165,7 +166,7 @@
 
 // RTT controller conversion methods.
 bool convertHidlVectorOfRttConfigToLegacy(
-    const std::vector<RttConfig>& hidl_configs,
+    const std::vector<V1_4::RttConfig>& hidl_configs,
     std::vector<legacy_hal::wifi_rtt_config>* legacy_configs);
 bool convertHidlRttLciInformationToLegacy(
     const RttLciInformation& hidl_info,
@@ -174,23 +175,23 @@
     const RttLcrInformation& hidl_info,
     legacy_hal::wifi_lcr_information* legacy_info);
 bool convertHidlRttResponderToLegacy(
-    const RttResponder& hidl_responder,
+    const V1_4::RttResponder& hidl_responder,
     legacy_hal::wifi_rtt_responder* legacy_responder);
 bool convertHidlWifiChannelInfoToLegacy(
     const WifiChannelInfo& hidl_info,
     legacy_hal::wifi_channel_info* legacy_info);
 bool convertLegacyRttResponderToHidl(
     const legacy_hal::wifi_rtt_responder& legacy_responder,
-    RttResponder* hidl_responder);
+    V1_4::RttResponder* hidl_responder);
 bool convertLegacyRttCapabilitiesToHidl(
     const legacy_hal::wifi_rtt_capabilities& legacy_capabilities,
-    RttCapabilities* hidl_capabilities);
+    V1_4::RttCapabilities* hidl_capabilities);
 bool convertLegacyVectorOfRttResultToHidl(
     const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
-    std::vector<RttResult>* hidl_results);
+    std::vector<V1_4::RttResult>* hidl_results);
 }  // namespace hidl_struct_util
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/hidl_sync_util.cpp b/wifi/1.5/default/hidl_sync_util.cpp
similarity index 96%
rename from wifi/1.4/default/hidl_sync_util.cpp
rename to wifi/1.5/default/hidl_sync_util.cpp
index 593a3bc..93eefe9 100644
--- a/wifi/1.4/default/hidl_sync_util.cpp
+++ b/wifi/1.5/default/hidl_sync_util.cpp
@@ -23,7 +23,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace hidl_sync_util {
 
@@ -33,7 +33,7 @@
 
 }  // namespace hidl_sync_util
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/hidl_sync_util.h b/wifi/1.5/default/hidl_sync_util.h
similarity index 96%
rename from wifi/1.4/default/hidl_sync_util.h
rename to wifi/1.5/default/hidl_sync_util.h
index 0244421..e706f4c 100644
--- a/wifi/1.4/default/hidl_sync_util.h
+++ b/wifi/1.5/default/hidl_sync_util.h
@@ -24,13 +24,13 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace hidl_sync_util {
 std::unique_lock<std::recursive_mutex> acquireGlobalLock();
 }  // namespace hidl_sync_util
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/ringbuffer.cpp b/wifi/1.5/default/ringbuffer.cpp
similarity index 97%
rename from wifi/1.4/default/ringbuffer.cpp
rename to wifi/1.5/default/ringbuffer.cpp
index 0fe8ef4..26971ff 100644
--- a/wifi/1.4/default/ringbuffer.cpp
+++ b/wifi/1.5/default/ringbuffer.cpp
@@ -21,7 +21,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 
 Ringbuffer::Ringbuffer(size_t maxSize) : size_(0), maxSize_(maxSize) {}
@@ -48,7 +48,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/ringbuffer.h b/wifi/1.5/default/ringbuffer.h
similarity index 97%
rename from wifi/1.4/default/ringbuffer.h
rename to wifi/1.5/default/ringbuffer.h
index ddce648..d8b87f2 100644
--- a/wifi/1.4/default/ringbuffer.h
+++ b/wifi/1.5/default/ringbuffer.h
@@ -23,7 +23,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 
 /**
@@ -45,7 +45,7 @@
 };
 
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/service.cpp b/wifi/1.5/default/service.cpp
similarity index 85%
rename from wifi/1.4/default/service.cpp
rename to wifi/1.5/default/service.cpp
index 3f7f609..f53d528 100644
--- a/wifi/1.4/default/service.cpp
+++ b/wifi/1.5/default/service.cpp
@@ -28,11 +28,11 @@
 using android::hardware::configureRpcThreadpool;
 using android::hardware::joinRpcThreadpool;
 using android::hardware::LazyServiceRegistrar;
-using android::hardware::wifi::V1_4::implementation::feature_flags::
+using android::hardware::wifi::V1_5::implementation::feature_flags::
     WifiFeatureFlags;
-using android::hardware::wifi::V1_4::implementation::iface_util::WifiIfaceUtil;
-using android::hardware::wifi::V1_4::implementation::legacy_hal::WifiLegacyHal;
-using android::hardware::wifi::V1_4::implementation::mode_controller::
+using android::hardware::wifi::V1_5::implementation::iface_util::WifiIfaceUtil;
+using android::hardware::wifi::V1_5::implementation::legacy_hal::WifiLegacyHal;
+using android::hardware::wifi::V1_5::implementation::mode_controller::
     WifiModeController;
 
 #ifdef LAZY_SERVICE
@@ -51,8 +51,8 @@
     const auto iface_tool =
         std::make_shared<android::wifi_system::InterfaceTool>();
     // Setup hwbinder service
-    android::sp<android::hardware::wifi::V1_4::IWifi> service =
-        new android::hardware::wifi::V1_4::implementation::Wifi(
+    android::sp<android::hardware::wifi::V1_5::IWifi> service =
+        new android::hardware::wifi::V1_5::implementation::Wifi(
             iface_tool, std::make_shared<WifiLegacyHal>(iface_tool),
             std::make_shared<WifiModeController>(),
             std::make_shared<WifiIfaceUtil>(iface_tool),
diff --git a/wifi/1.4/default/tests/hidl_struct_util_unit_tests.cpp b/wifi/1.5/default/tests/hidl_struct_util_unit_tests.cpp
similarity index 91%
rename from wifi/1.4/default/tests/hidl_struct_util_unit_tests.cpp
rename to wifi/1.5/default/tests/hidl_struct_util_unit_tests.cpp
index b71d549..81eb14e 100644
--- a/wifi/1.4/default/tests/hidl_struct_util_unit_tests.cpp
+++ b/wifi/1.5/default/tests/hidl_struct_util_unit_tests.cpp
@@ -34,7 +34,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 using namespace android::hardware::wifi::V1_0;
 using ::android::hardware::wifi::V1_0::WifiChannelWidthInMhz;
@@ -55,14 +55,15 @@
     legacy_mac_info1.iface_infos.push_back(legacy_iface_info2);
     legacy_mac_infos.push_back(legacy_mac_info1);
 
-    std::vector<IWifiChipEventCallback::RadioModeInfo> hidl_radio_mode_infos;
+    std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo>
+        hidl_radio_mode_infos;
     ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl(
         legacy_mac_infos, &hidl_radio_mode_infos));
 
     ASSERT_EQ(1u, hidl_radio_mode_infos.size());
     auto hidl_radio_mode_info1 = hidl_radio_mode_infos[0];
     EXPECT_EQ(legacy_mac_info1.wlan_mac_id, hidl_radio_mode_info1.radioId);
-    EXPECT_EQ(WifiBand::BAND_24GHZ_5GHZ, hidl_radio_mode_info1.bandInfo);
+    EXPECT_EQ(V1_4::WifiBand::BAND_24GHZ_5GHZ, hidl_radio_mode_info1.bandInfo);
     ASSERT_EQ(2u, hidl_radio_mode_info1.ifaceInfos.size());
     auto hidl_iface_info1 = hidl_radio_mode_info1.ifaceInfos[0];
     EXPECT_EQ(legacy_iface_info1.name, hidl_iface_info1.name);
@@ -89,20 +90,22 @@
     legacy_mac_info2.iface_infos.push_back(legacy_iface_info2);
     legacy_mac_infos.push_back(legacy_mac_info2);
 
-    std::vector<IWifiChipEventCallback::RadioModeInfo> hidl_radio_mode_infos;
+    std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo>
+        hidl_radio_mode_infos;
     ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl(
         legacy_mac_infos, &hidl_radio_mode_infos));
 
     ASSERT_EQ(2u, hidl_radio_mode_infos.size());
 
     // Find mac info 1.
-    const auto hidl_radio_mode_info1 = std::find_if(
-        hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
-        [&legacy_mac_info1](const IWifiChipEventCallback::RadioModeInfo& x) {
-            return x.radioId == legacy_mac_info1.wlan_mac_id;
-        });
+    const auto hidl_radio_mode_info1 =
+        std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
+                     [&legacy_mac_info1](
+                         const V1_4::IWifiChipEventCallback::RadioModeInfo& x) {
+                         return x.radioId == legacy_mac_info1.wlan_mac_id;
+                     });
     ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info1);
-    EXPECT_EQ(WifiBand::BAND_5GHZ, hidl_radio_mode_info1->bandInfo);
+    EXPECT_EQ(V1_4::WifiBand::BAND_5GHZ, hidl_radio_mode_info1->bandInfo);
     ASSERT_EQ(1u, hidl_radio_mode_info1->ifaceInfos.size());
     auto hidl_iface_info1 = hidl_radio_mode_info1->ifaceInfos[0];
     EXPECT_EQ(legacy_iface_info1.name, hidl_iface_info1.name);
@@ -110,13 +113,14 @@
               hidl_iface_info1.channel);
 
     // Find mac info 2.
-    const auto hidl_radio_mode_info2 = std::find_if(
-        hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
-        [&legacy_mac_info2](const IWifiChipEventCallback::RadioModeInfo& x) {
-            return x.radioId == legacy_mac_info2.wlan_mac_id;
-        });
+    const auto hidl_radio_mode_info2 =
+        std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
+                     [&legacy_mac_info2](
+                         const V1_4::IWifiChipEventCallback::RadioModeInfo& x) {
+                         return x.radioId == legacy_mac_info2.wlan_mac_id;
+                     });
     ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info2);
-    EXPECT_EQ(WifiBand::BAND_24GHZ, hidl_radio_mode_info2->bandInfo);
+    EXPECT_EQ(V1_4::WifiBand::BAND_24GHZ, hidl_radio_mode_info2->bandInfo);
     ASSERT_EQ(1u, hidl_radio_mode_info2->ifaceInfos.size());
     auto hidl_iface_info2 = hidl_radio_mode_info2->ifaceInfos[0];
     EXPECT_EQ(legacy_iface_info2.name, hidl_iface_info2.name);
@@ -288,7 +292,7 @@
               hidle_caps);
 }
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/tests/main.cpp b/wifi/1.5/default/tests/main.cpp
similarity index 100%
rename from wifi/1.4/default/tests/main.cpp
rename to wifi/1.5/default/tests/main.cpp
diff --git a/wifi/1.4/default/tests/mock_interface_tool.cpp b/wifi/1.5/default/tests/mock_interface_tool.cpp
similarity index 100%
rename from wifi/1.4/default/tests/mock_interface_tool.cpp
rename to wifi/1.5/default/tests/mock_interface_tool.cpp
diff --git a/wifi/1.4/default/tests/mock_interface_tool.h b/wifi/1.5/default/tests/mock_interface_tool.h
similarity index 100%
rename from wifi/1.4/default/tests/mock_interface_tool.h
rename to wifi/1.5/default/tests/mock_interface_tool.h
diff --git a/wifi/1.4/default/tests/mock_wifi_feature_flags.cpp b/wifi/1.5/default/tests/mock_wifi_feature_flags.cpp
similarity index 96%
rename from wifi/1.4/default/tests/mock_wifi_feature_flags.cpp
rename to wifi/1.5/default/tests/mock_wifi_feature_flags.cpp
index b1fa432..2f66ba1 100644
--- a/wifi/1.4/default/tests/mock_wifi_feature_flags.cpp
+++ b/wifi/1.5/default/tests/mock_wifi_feature_flags.cpp
@@ -21,7 +21,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace feature_flags {
 
@@ -29,7 +29,7 @@
 
 }  // namespace feature_flags
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/tests/mock_wifi_feature_flags.h b/wifi/1.5/default/tests/mock_wifi_feature_flags.h
similarity index 96%
rename from wifi/1.4/default/tests/mock_wifi_feature_flags.h
rename to wifi/1.5/default/tests/mock_wifi_feature_flags.h
index 72d2304..92fbb05 100644
--- a/wifi/1.4/default/tests/mock_wifi_feature_flags.h
+++ b/wifi/1.5/default/tests/mock_wifi_feature_flags.h
@@ -25,7 +25,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace feature_flags {
 
@@ -39,7 +39,7 @@
 
 }  // namespace feature_flags
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/tests/mock_wifi_iface_util.cpp b/wifi/1.5/default/tests/mock_wifi_iface_util.cpp
similarity index 96%
rename from wifi/1.4/default/tests/mock_wifi_iface_util.cpp
rename to wifi/1.5/default/tests/mock_wifi_iface_util.cpp
index 0968569..fe6e9e2 100644
--- a/wifi/1.4/default/tests/mock_wifi_iface_util.cpp
+++ b/wifi/1.5/default/tests/mock_wifi_iface_util.cpp
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace iface_util {
 
@@ -33,7 +33,7 @@
     : WifiIfaceUtil(iface_tool) {}
 }  // namespace iface_util
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/tests/mock_wifi_iface_util.h b/wifi/1.5/default/tests/mock_wifi_iface_util.h
similarity index 94%
rename from wifi/1.4/default/tests/mock_wifi_iface_util.h
rename to wifi/1.5/default/tests/mock_wifi_iface_util.h
index 3b36f13..a719fec 100644
--- a/wifi/1.4/default/tests/mock_wifi_iface_util.h
+++ b/wifi/1.5/default/tests/mock_wifi_iface_util.h
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace iface_util {
 
@@ -41,10 +41,11 @@
                  void(const std::string&, IfaceEventHandlers));
     MOCK_METHOD1(unregisterIfaceEventHandlers, void(const std::string&));
     MOCK_METHOD2(setUpState, bool(const std::string&, bool));
+    MOCK_METHOD1(ifNameToIndex, unsigned(const std::string&));
 };
 }  // namespace iface_util
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/tests/mock_wifi_legacy_hal.cpp b/wifi/1.5/default/tests/mock_wifi_legacy_hal.cpp
similarity index 96%
rename from wifi/1.4/default/tests/mock_wifi_legacy_hal.cpp
rename to wifi/1.5/default/tests/mock_wifi_legacy_hal.cpp
index 8d65c59..501bd7f 100644
--- a/wifi/1.4/default/tests/mock_wifi_legacy_hal.cpp
+++ b/wifi/1.5/default/tests/mock_wifi_legacy_hal.cpp
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace legacy_hal {
 
@@ -33,7 +33,7 @@
     : WifiLegacyHal(iface_tool) {}
 }  // namespace legacy_hal
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/tests/mock_wifi_legacy_hal.h b/wifi/1.5/default/tests/mock_wifi_legacy_hal.h
similarity index 98%
rename from wifi/1.4/default/tests/mock_wifi_legacy_hal.h
rename to wifi/1.5/default/tests/mock_wifi_legacy_hal.h
index 3bb7b54..f938347 100644
--- a/wifi/1.4/default/tests/mock_wifi_legacy_hal.h
+++ b/wifi/1.5/default/tests/mock_wifi_legacy_hal.h
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace legacy_hal {
 
@@ -64,7 +64,7 @@
 };
 }  // namespace legacy_hal
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/tests/mock_wifi_mode_controller.cpp b/wifi/1.5/default/tests/mock_wifi_mode_controller.cpp
similarity index 96%
rename from wifi/1.4/default/tests/mock_wifi_mode_controller.cpp
rename to wifi/1.5/default/tests/mock_wifi_mode_controller.cpp
index ee09029..e7ab22a 100644
--- a/wifi/1.4/default/tests/mock_wifi_mode_controller.cpp
+++ b/wifi/1.5/default/tests/mock_wifi_mode_controller.cpp
@@ -24,14 +24,14 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace mode_controller {
 
 MockWifiModeController::MockWifiModeController() : WifiModeController() {}
 }  // namespace mode_controller
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/tests/mock_wifi_mode_controller.h b/wifi/1.5/default/tests/mock_wifi_mode_controller.h
similarity index 97%
rename from wifi/1.4/default/tests/mock_wifi_mode_controller.h
rename to wifi/1.5/default/tests/mock_wifi_mode_controller.h
index 1e1ce69..b9151f1 100644
--- a/wifi/1.4/default/tests/mock_wifi_mode_controller.h
+++ b/wifi/1.5/default/tests/mock_wifi_mode_controller.h
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace mode_controller {
 
@@ -38,7 +38,7 @@
 };
 }  // namespace mode_controller
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/tests/ringbuffer_unit_tests.cpp b/wifi/1.5/default/tests/ringbuffer_unit_tests.cpp
similarity index 98%
rename from wifi/1.4/default/tests/ringbuffer_unit_tests.cpp
rename to wifi/1.5/default/tests/ringbuffer_unit_tests.cpp
index a65347f..6fd34ee 100644
--- a/wifi/1.4/default/tests/ringbuffer_unit_tests.cpp
+++ b/wifi/1.5/default/tests/ringbuffer_unit_tests.cpp
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 
 class RingbufferTest : public Test {
@@ -91,7 +91,7 @@
     EXPECT_EQ(input, buffer_.getData().front());
 }
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/tests/runtests.sh b/wifi/1.5/default/tests/runtests.sh
similarity index 100%
rename from wifi/1.4/default/tests/runtests.sh
rename to wifi/1.5/default/tests/runtests.sh
diff --git a/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.5/default/tests/wifi_chip_unit_tests.cpp
similarity index 96%
rename from wifi/1.4/default/tests/wifi_chip_unit_tests.cpp
rename to wifi/1.5/default/tests/wifi_chip_unit_tests.cpp
index d5b1a50..1d55e16 100644
--- a/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.5/default/tests/wifi_chip_unit_tests.cpp
@@ -41,7 +41,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 
 class WifiChipTest : public Test {
@@ -173,18 +173,18 @@
     std::string createIface(const IfaceType& type) {
         std::string iface_name;
         if (type == IfaceType::AP) {
-            chip_->createApIface([&iface_name](
-                                     const WifiStatus& status,
-                                     const sp<V1_0::IWifiApIface>& iface) {
-                if (WifiStatusCode::SUCCESS == status.code) {
-                    ASSERT_NE(iface.get(), nullptr);
-                    iface->getName([&iface_name](const WifiStatus& status,
-                                                 const hidl_string& name) {
-                        ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
-                        iface_name = name.c_str();
-                    });
-                }
-            });
+            chip_->createApIface(
+                [&iface_name](const WifiStatus& status,
+                              const sp<V1_0::IWifiApIface>& iface) {
+                    if (WifiStatusCode::SUCCESS == status.code) {
+                        ASSERT_NE(iface.get(), nullptr);
+                        iface->getName([&iface_name](const WifiStatus& status,
+                                                     const hidl_string& name) {
+                            ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
+                            iface_name = name.c_str();
+                        });
+                    }
+                });
         } else if (type == IfaceType::NAN) {
             chip_->createNanIface(
                 [&iface_name](
@@ -263,6 +263,8 @@
         return success;
     }
 
+    static void subsystemRestartHandler(const std::string& /*error*/) {}
+
     sp<WifiChip> chip_;
     ChipId chip_id_ = kFakeChipId;
     std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
@@ -278,8 +280,9 @@
 
    public:
     void SetUp() override {
-        chip_ = new WifiChip(chip_id_, legacy_hal_, mode_controller_,
-                             iface_util_, feature_flags_);
+        chip_ =
+            new WifiChip(chip_id_, legacy_hal_, mode_controller_, iface_util_,
+                         feature_flags_, subsystemRestartHandler);
 
         EXPECT_CALL(*mode_controller_, changeFirmwareMode(testing::_))
             .WillRepeatedly(testing::Return(true));
@@ -787,6 +790,8 @@
     property_set("wifi.aware.interface", "aware0");
     findModeAndConfigureForIfaceType(IfaceType::STA);
     ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+    EXPECT_CALL(*iface_util_, ifNameToIndex("aware0"))
+        .WillOnce(testing::Return(4));
     EXPECT_CALL(*iface_util_, setUpState("aware0", true))
         .WillOnce(testing::Return(true));
     ASSERT_EQ(createIface(IfaceType::NAN), "aware0");
@@ -892,7 +897,7 @@
     ASSERT_EQ(createIface(IfaceType::STA), "wlan3");
 }
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/tests/wifi_iface_util_unit_tests.cpp b/wifi/1.5/default/tests/wifi_iface_util_unit_tests.cpp
similarity index 98%
rename from wifi/1.4/default/tests/wifi_iface_util_unit_tests.cpp
rename to wifi/1.5/default/tests/wifi_iface_util_unit_tests.cpp
index 03394bc..d70e42f 100644
--- a/wifi/1.4/default/tests/wifi_iface_util_unit_tests.cpp
+++ b/wifi/1.5/default/tests/wifi_iface_util_unit_tests.cpp
@@ -41,7 +41,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace iface_util {
 class WifiIfaceUtilTest : public Test {
@@ -90,7 +90,7 @@
 }
 }  // namespace iface_util
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/tests/wifi_nan_iface_unit_tests.cpp b/wifi/1.5/default/tests/wifi_nan_iface_unit_tests.cpp
similarity index 99%
rename from wifi/1.4/default/tests/wifi_nan_iface_unit_tests.cpp
rename to wifi/1.5/default/tests/wifi_nan_iface_unit_tests.cpp
index 70424db..3e7026f 100644
--- a/wifi/1.4/default/tests/wifi_nan_iface_unit_tests.cpp
+++ b/wifi/1.5/default/tests/wifi_nan_iface_unit_tests.cpp
@@ -38,7 +38,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 
 using android::hardware::wifi::V1_2::IWifiNanIfaceEventCallback;
@@ -151,7 +151,7 @@
     captured_iface_event_handlers.on_state_toggle_off_on(kIfaceName);
 }
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi.cpp b/wifi/1.5/default/wifi.cpp
similarity index 89%
rename from wifi/1.4/default/wifi.cpp
rename to wifi/1.5/default/wifi.cpp
index 9c6b0f0..c4e2333 100644
--- a/wifi/1.4/default/wifi.cpp
+++ b/wifi/1.5/default/wifi.cpp
@@ -28,7 +28,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 using hidl_return_util::validateAndCall;
 using hidl_return_util::validateAndCallWithLock;
@@ -107,9 +107,23 @@
     }
     WifiStatus wifi_status = initializeModeControllerAndLegacyHal();
     if (wifi_status.code == WifiStatusCode::SUCCESS) {
+        // Register the callback for subsystem restart
+        const auto& on_subsystem_restart_callback =
+            [this](const std::string& error) {
+                WifiStatus wifi_status =
+                    createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, error);
+                for (const auto& callback : event_cb_handler_.getCallbacks()) {
+                    if (!callback->onFailure(wifi_status).isOk()) {
+                        LOG(ERROR) << "Failed to invoke onFailure callback";
+                    }
+                }
+            };
+
         // Create the chip instance once the HAL is started.
-        chip_ = new WifiChip(kChipId, legacy_hal_, mode_controller_,
-                             iface_util_, feature_flags_);
+        // Need to consider the case of multiple chips TODO(156998862)
+        chip_ =
+            new WifiChip(kChipId, legacy_hal_, mode_controller_, iface_util_,
+                         feature_flags_, on_subsystem_restart_callback);
         run_state_ = RunState::STARTED;
         for (const auto& callback : event_cb_handler_.getCallbacks()) {
             if (!callback->onStart().isOk()) {
@@ -173,7 +187,8 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), std::move(chip_ids)};
 }
 
-std::pair<WifiStatus, sp<IWifiChip>> Wifi::getChipInternal(ChipId chip_id) {
+std::pair<WifiStatus, sp<V1_4::IWifiChip>> Wifi::getChipInternal(
+    ChipId chip_id) {
     if (!chip_.get()) {
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_STARTED), nullptr};
     }
@@ -214,7 +229,7 @@
     return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi.h b/wifi/1.5/default/wifi.h
similarity index 94%
rename from wifi/1.4/default/wifi.h
rename to wifi/1.5/default/wifi.h
index 087d6f7..8de0ef4 100644
--- a/wifi/1.4/default/wifi.h
+++ b/wifi/1.5/default/wifi.h
@@ -20,7 +20,7 @@
 #include <functional>
 
 #include <android-base/macros.h>
-#include <android/hardware/wifi/1.4/IWifi.h>
+#include <android/hardware/wifi/1.5/IWifi.h>
 #include <utils/Looper.h>
 
 #include "hidl_callback_util.h"
@@ -32,13 +32,13 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 
 /**
  * Root HIDL interface object used to control the Wifi HAL.
  */
-class Wifi : public V1_4::IWifi {
+class Wifi : public V1_5::IWifi {
    public:
     Wifi(const std::shared_ptr<wifi_system::InterfaceTool> iface_tool,
          const std::shared_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
@@ -70,7 +70,7 @@
     WifiStatus startInternal();
     WifiStatus stopInternal(std::unique_lock<std::recursive_mutex>* lock);
     std::pair<WifiStatus, std::vector<ChipId>> getChipIdsInternal();
-    std::pair<WifiStatus, sp<IWifiChip>> getChipInternal(ChipId chip_id);
+    std::pair<WifiStatus, sp<V1_4::IWifiChip>> getChipInternal(ChipId chip_id);
 
     WifiStatus initializeModeControllerAndLegacyHal();
     WifiStatus stopLegacyHalAndDeinitializeModeController(
@@ -92,7 +92,7 @@
 };
 
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_ap_iface.cpp b/wifi/1.5/default/wifi_ap_iface.cpp
similarity index 98%
rename from wifi/1.4/default/wifi_ap_iface.cpp
rename to wifi/1.5/default/wifi_ap_iface.cpp
index 8777a4c..04e382a 100644
--- a/wifi/1.4/default/wifi_ap_iface.cpp
+++ b/wifi/1.5/default/wifi_ap_iface.cpp
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 using hidl_return_util::validateAndCall;
 
@@ -131,7 +131,7 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), mac};
 }
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_ap_iface.h b/wifi/1.5/default/wifi_ap_iface.h
similarity index 98%
rename from wifi/1.4/default/wifi_ap_iface.h
rename to wifi/1.5/default/wifi_ap_iface.h
index bf16d5e..48b444a 100644
--- a/wifi/1.4/default/wifi_ap_iface.h
+++ b/wifi/1.5/default/wifi_ap_iface.h
@@ -26,7 +26,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 using namespace android::hardware::wifi::V1_0;
 
@@ -76,7 +76,7 @@
 };
 
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
similarity index 97%
rename from wifi/1.4/default/wifi_chip.cpp
rename to wifi/1.5/default/wifi_chip.cpp
index 61912a5..069fd65 100644
--- a/wifi/1.4/default/wifi_chip.cpp
+++ b/wifi/1.5/default/wifi_chip.cpp
@@ -326,7 +326,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 using hidl_return_util::validateAndCall;
 using hidl_return_util::validateAndCallWithLock;
@@ -335,7 +335,8 @@
     ChipId chip_id, const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
     const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
     const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util,
-    const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags)
+    const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags,
+    const std::function<void(const std::string&)>& handler)
     : chip_id_(chip_id),
       legacy_hal_(legacy_hal),
       mode_controller_(mode_controller),
@@ -343,7 +344,8 @@
       is_valid_(true),
       current_mode_id_(feature_flags::chip_mode_ids::kInvalid),
       modes_(feature_flags.lock()->getChipModes()),
-      debug_ring_buffer_cb_registered_(false) {
+      debug_ring_buffer_cb_registered_(false),
+      subsystemCallbackHandler_(handler) {
     setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue);
 }
 
@@ -360,7 +362,7 @@
 
 bool WifiChip::isValid() { return is_valid_; }
 
-std::set<sp<IWifiChipEventCallback>> WifiChip::getEventCallbacks() {
+std::set<sp<V1_4::IWifiChipEventCallback>> WifiChip::getEventCallbacks() {
     return event_cb_handler_.getCallbacks();
 }
 
@@ -624,6 +626,15 @@
 Return<void> WifiChip::debug(const hidl_handle& handle,
                              const hidl_vec<hidl_string>&) {
     if (handle != nullptr && handle->numFds >= 1) {
+        {
+            std::unique_lock<std::mutex> lk(lock_t);
+            for (const auto& item : ringbuffer_map_) {
+                forceDumpToDebugRingBufferInternal(item.first);
+            }
+            // unique_lock unlocked here
+        }
+        usleep(100 * 1000);  // sleep for 100 milliseconds to wait for
+                             // ringbuffer updates.
         int fd = handle->data[0];
         if (!writeRingbufferFilesInternal()) {
             LOG(ERROR) << "Error writing files to flash";
@@ -648,7 +659,7 @@
 }
 
 Return<void> WifiChip::registerEventCallback_1_4(
-    const sp<IWifiChipEventCallback>& event_callback,
+    const sp<V1_4::IWifiChipEventCallback>& event_callback,
     registerEventCallback_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
                            &WifiChip::registerEventCallbackInternal_1_4,
@@ -704,7 +715,7 @@
     return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), 0};
 }
 
-std::pair<WifiStatus, std::vector<IWifiChip::ChipMode>>
+std::pair<WifiStatus, std::vector<V1_4::IWifiChip::ChipMode>>
 WifiChip::getAvailableModesInternal() {
     return {createWifiStatus(WifiStatusCode::SUCCESS), modes_};
 }
@@ -737,6 +748,10 @@
     current_mode_id_ = mode_id;
     LOG(INFO) << "Configured chip in mode " << mode_id;
     setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
+
+    legacy_hal_.lock()->registerSubsystemRestartCallbackHandler(
+        subsystemCallbackHandler_);
+
     return status;
 }
 
@@ -748,9 +763,9 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), current_mode_id_};
 }
 
-std::pair<WifiStatus, IWifiChip::ChipDebugInfo>
+std::pair<WifiStatus, V1_4::IWifiChip::ChipDebugInfo>
 WifiChip::requestChipDebugInfoInternal() {
-    IWifiChip::ChipDebugInfo result;
+    V1_4::IWifiChip::ChipDebugInfo result;
     legacy_hal::wifi_error legacy_status;
     std::string driver_desc;
     const auto ifname = getFirstActiveWlanIfaceName();
@@ -879,13 +894,14 @@
     return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
-std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::createNanIfaceInternal() {
+std::pair<WifiStatus, sp<V1_4::IWifiNanIface>>
+WifiChip::createNanIfaceInternal() {
     if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::NAN)) {
         return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
     }
     bool is_dedicated_iface = true;
     std::string ifname = getNanIfaceName();
-    if (ifname.empty()) {
+    if (ifname.empty() || !iface_util_.lock()->ifNameToIndex(ifname)) {
         // Use the first shared STA iface (wlan0) if a dedicated aware iface is
         // not defined.
         ifname = getFirstActiveWlanIfaceName();
@@ -910,7 +926,7 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(nan_ifaces_)};
 }
 
-std::pair<WifiStatus, sp<IWifiNanIface>> WifiChip::getNanIfaceInternal(
+std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> WifiChip::getNanIfaceInternal(
     const std::string& ifname) {
     const auto iface = findUsingName(nan_ifaces_, ifname);
     if (!iface.get()) {
@@ -1120,6 +1136,9 @@
     legacy_hal::wifi_error legacy_status =
         legacy_hal_.lock()->deregisterRingBufferCallbackHandler(
             getFirstActiveWlanIfaceName());
+    if (legacy_status == legacy_hal::WIFI_SUCCESS) {
+        debug_ring_buffer_cb_registered_ = false;
+    }
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
@@ -1227,7 +1246,7 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
 }
 
-std::pair<WifiStatus, sp<IWifiRttController>>
+std::pair<WifiStatus, sp<V1_4::IWifiRttController>>
 WifiChip::createRttControllerInternal_1_4(const sp<IWifiIface>& bound_iface) {
     if (sta_ifaces_.size() == 0 &&
         !canCurrentModeSupportIfaceOfType(IfaceType::STA)) {
@@ -1243,7 +1262,7 @@
 }
 
 WifiStatus WifiChip::registerEventCallbackInternal_1_4(
-    const sp<IWifiChipEventCallback>& event_callback) {
+    const sp<V1_4::IWifiChipEventCallback>& event_callback) {
     if (!event_cb_handler_.addCallback(event_callback)) {
         return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
     }
@@ -1291,7 +1310,7 @@
         LOG(ERROR) << "Failed to register radio mode change callback";
     }
     // Extract and save the version information into property.
-    std::pair<WifiStatus, IWifiChip::ChipDebugInfo> version_info;
+    std::pair<WifiStatus, V1_4::IWifiChip::ChipDebugInfo> version_info;
     version_info = WifiChip::requestChipDebugInfoInternal();
     if (WifiStatusCode::SUCCESS == version_info.first.code) {
         property_set("vendor.wlan.firmware.version",
@@ -1335,7 +1354,7 @@
                     LOG(ERROR) << "Ringname " << name << " not found";
                     return;
                 }
-                // unlock
+                // unique_lock unlocked here
             }
         };
     legacy_hal::wifi_error legacy_status =
@@ -1357,7 +1376,7 @@
                 LOG(ERROR) << "Callback invoked on an invalid object";
                 return;
             }
-            std::vector<IWifiChipEventCallback::RadioModeInfo>
+            std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo>
                 hidl_radio_mode_infos;
             if (!hidl_struct_util::convertLegacyWifiMacInfosToHidl(
                     mac_infos, &hidl_radio_mode_infos)) {
@@ -1378,7 +1397,7 @@
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
-std::vector<IWifiChip::ChipIfaceCombination>
+std::vector<V1_4::IWifiChip::ChipIfaceCombination>
 WifiChip::getCurrentModeIfaceCombinations() {
     if (!isValidModeId(current_mode_id_)) {
         LOG(ERROR) << "Chip not configured in a mode yet";
@@ -1409,7 +1428,7 @@
 // of ifaces of each type in the combination.
 // This method is a port of HalDeviceManager.expandIfaceCombos() from framework.
 std::vector<std::map<IfaceType, size_t>> WifiChip::expandIfaceCombinations(
-    const IWifiChip::ChipIfaceCombination& combination) {
+    const V1_4::IWifiChip::ChipIfaceCombination& combination) {
     uint32_t num_expanded_combos = 1;
     for (const auto& limit : combination.limits) {
         for (uint32_t i = 0; i < limit.maxIfaces; i++) {
@@ -1637,13 +1656,13 @@
                 }
             }
         }
-        // unlock
+        // unique_lock unlocked here
     }
     return true;
 }
 
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_chip.h b/wifi/1.5/default/wifi_chip.h
similarity index 91%
rename from wifi/1.4/default/wifi_chip.h
rename to wifi/1.5/default/wifi_chip.h
index 98e18bb..36c191c 100644
--- a/wifi/1.4/default/wifi_chip.h
+++ b/wifi/1.5/default/wifi_chip.h
@@ -39,7 +39,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 using namespace android::hardware::wifi::V1_0;
 
@@ -50,13 +50,14 @@
  */
 class WifiChip : public V1_4::IWifiChip {
    public:
-    WifiChip(
-        ChipId chip_id,
-        const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
-        const std::weak_ptr<mode_controller::WifiModeController>
-            mode_controller,
-        const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util,
-        const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags);
+    WifiChip(ChipId chip_id,
+             const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+             const std::weak_ptr<mode_controller::WifiModeController>
+                 mode_controller,
+             const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util,
+             const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags,
+             const std::function<void(const std::string&)>&
+                 subsystemCallbackHandler);
     // HIDL does not provide a built-in mechanism to let the server invalidate
     // a HIDL interface object after creation. If any client process holds onto
     // a reference to the object in their context, any method calls on that
@@ -72,7 +73,7 @@
     // marked valid before processing them.
     void invalidate();
     bool isValid();
-    std::set<sp<IWifiChipEventCallback>> getEventCallbacks();
+    std::set<sp<V1_4::IWifiChipEventCallback>> getEventCallbacks();
 
     // HIDL methods exposed.
     Return<void> getId(getId_cb hidl_status_cb) override;
@@ -158,7 +159,7 @@
         const sp<IWifiIface>& bound_iface,
         createRttController_1_4_cb hidl_status_cb) override;
     Return<void> registerEventCallback_1_4(
-        const sp<IWifiChipEventCallback>& event_callback,
+        const sp<V1_4::IWifiChipEventCallback>& event_callback,
         registerEventCallback_1_4_cb hidl_status_cb) override;
 
    private:
@@ -188,9 +189,9 @@
     std::pair<WifiStatus, sp<IWifiApIface>> getApIfaceInternal(
         const std::string& ifname);
     WifiStatus removeApIfaceInternal(const std::string& ifname);
-    std::pair<WifiStatus, sp<IWifiNanIface>> createNanIfaceInternal();
+    std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> createNanIfaceInternal();
     std::pair<WifiStatus, std::vector<hidl_string>> getNanIfaceNamesInternal();
-    std::pair<WifiStatus, sp<IWifiNanIface>> getNanIfaceInternal(
+    std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> getNanIfaceInternal(
         const std::string& ifname);
     WifiStatus removeNanIfaceInternal(const std::string& ifname);
     std::pair<WifiStatus, sp<IWifiP2pIface>> createP2pIfaceInternal();
@@ -225,21 +226,21 @@
         const sp<V1_2::IWifiChipEventCallback>& event_callback);
     WifiStatus selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario);
     std::pair<WifiStatus, uint32_t> getCapabilitiesInternal_1_3();
-    std::pair<WifiStatus, sp<IWifiRttController>>
+    std::pair<WifiStatus, sp<V1_4::IWifiRttController>>
     createRttControllerInternal_1_4(const sp<IWifiIface>& bound_iface);
     WifiStatus registerEventCallbackInternal_1_4(
-        const sp<IWifiChipEventCallback>& event_callback);
+        const sp<V1_4::IWifiChipEventCallback>& event_callback);
 
     WifiStatus handleChipConfiguration(
         std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id);
     WifiStatus registerDebugRingBufferCallback();
     WifiStatus registerRadioModeChangeCallback();
 
-    std::vector<IWifiChip::ChipIfaceCombination>
+    std::vector<V1_4::IWifiChip::ChipIfaceCombination>
     getCurrentModeIfaceCombinations();
     std::map<IfaceType, size_t> getCurrentIfaceCombination();
     std::vector<std::map<IfaceType, size_t>> expandIfaceCombinations(
-        const IWifiChip::ChipIfaceCombination& combination);
+        const V1_4::IWifiChip::ChipIfaceCombination& combination);
     bool canExpandedIfaceComboSupportIfaceOfTypeWithCurrentIfaces(
         const std::map<IfaceType, size_t>& expanded_combo,
         IfaceType requested_type);
@@ -274,19 +275,21 @@
     // Members pertaining to chip configuration.
     uint32_t current_mode_id_;
     std::mutex lock_t;
-    std::vector<IWifiChip::ChipMode> modes_;
+    std::vector<V1_4::IWifiChip::ChipMode> modes_;
     // The legacy ring buffer callback API has only a global callback
     // registration mechanism. Use this to check if we have already
     // registered a callback.
     bool debug_ring_buffer_cb_registered_;
-    hidl_callback_util::HidlCallbackHandler<IWifiChipEventCallback>
+    hidl_callback_util::HidlCallbackHandler<V1_4::IWifiChipEventCallback>
         event_cb_handler_;
 
+    const std::function<void(const std::string&)> subsystemCallbackHandler_;
+
     DISALLOW_COPY_AND_ASSIGN(WifiChip);
 };
 
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_feature_flags.cpp b/wifi/1.5/default/wifi_feature_flags.cpp
similarity index 99%
rename from wifi/1.4/default/wifi_feature_flags.cpp
rename to wifi/1.5/default/wifi_feature_flags.cpp
index 195b460..151d473 100644
--- a/wifi/1.4/default/wifi_feature_flags.cpp
+++ b/wifi/1.5/default/wifi_feature_flags.cpp
@@ -19,7 +19,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace feature_flags {
 
@@ -160,7 +160,7 @@
 
 }  // namespace feature_flags
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_feature_flags.h b/wifi/1.5/default/wifi_feature_flags.h
similarity index 97%
rename from wifi/1.4/default/wifi_feature_flags.h
rename to wifi/1.5/default/wifi_feature_flags.h
index 292dedf..73d18ec 100644
--- a/wifi/1.4/default/wifi_feature_flags.h
+++ b/wifi/1.5/default/wifi_feature_flags.h
@@ -22,7 +22,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace feature_flags {
 
@@ -47,7 +47,7 @@
 
 }  // namespace feature_flags
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_iface_util.cpp b/wifi/1.5/default/wifi_iface_util.cpp
similarity index 95%
rename from wifi/1.4/default/wifi_iface_util.cpp
rename to wifi/1.5/default/wifi_iface_util.cpp
index 13ba022..07175e4 100644
--- a/wifi/1.4/default/wifi_iface_util.cpp
+++ b/wifi/1.5/default/wifi_iface_util.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <net/if.h>
 #include <cstddef>
 #include <iostream>
 #include <limits>
@@ -35,7 +36,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace iface_util {
 
@@ -122,9 +123,13 @@
     }
     return true;
 }
+
+unsigned WifiIfaceUtil::ifNameToIndex(const std::string& iface_name) {
+    return if_nametoindex(iface_name.c_str());
+}
 }  // namespace iface_util
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_iface_util.h b/wifi/1.5/default/wifi_iface_util.h
similarity index 95%
rename from wifi/1.4/default/wifi_iface_util.h
rename to wifi/1.5/default/wifi_iface_util.h
index f83d717..7b812fa 100644
--- a/wifi/1.4/default/wifi_iface_util.h
+++ b/wifi/1.5/default/wifi_iface_util.h
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace iface_util {
 
@@ -57,6 +57,7 @@
                                             IfaceEventHandlers handlers);
     virtual void unregisterIfaceEventHandlers(const std::string& iface_name);
     virtual bool setUpState(const std::string& iface_name, bool request_up);
+    virtual unsigned ifNameToIndex(const std::string& iface_name);
 
    private:
     std::array<uint8_t, 6> createRandomMacAddress();
@@ -68,7 +69,7 @@
 
 }  // namespace iface_util
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_legacy_hal.cpp b/wifi/1.5/default/wifi_legacy_hal.cpp
similarity index 98%
rename from wifi/1.4/default/wifi_legacy_hal.cpp
rename to wifi/1.5/default/wifi_legacy_hal.cpp
index 29123bf..4070568 100644
--- a/wifi/1.4/default/wifi_legacy_hal.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal.cpp
@@ -51,7 +51,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace legacy_hal {
 // Legacy HAL functions accept "C" style function pointers, so use global
@@ -162,6 +162,15 @@
     }
 }
 
+// Callback to be invoked to report subsystem restart
+std::function<void(const char*)> on_subsystem_restart_internal_callback;
+void onAsyncSubsystemRestart(const char* error) {
+    const auto lock = hidl_sync_util::acquireGlobalLock();
+    if (on_subsystem_restart_internal_callback) {
+        on_subsystem_restart_internal_callback(error);
+    }
+}
+
 // Callback to be invoked for rtt results results.
 std::function<void(wifi_request_id, unsigned num_results,
                    wifi_rtt_result* rtt_results[])>
@@ -1049,6 +1058,23 @@
     return status;
 }
 
+wifi_error WifiLegacyHal::registerSubsystemRestartCallbackHandler(
+    const on_subsystem_restart_callback& on_restart_callback) {
+    if (on_subsystem_restart_internal_callback) {
+        return WIFI_ERROR_NOT_AVAILABLE;
+    }
+    on_subsystem_restart_internal_callback =
+        [on_restart_callback](const char* error) {
+            on_restart_callback(error);
+        };
+    wifi_error status = global_func_table_.wifi_set_subsystem_restart_handler(
+        global_handle_, {onAsyncSubsystemRestart});
+    if (status != WIFI_SUCCESS) {
+        on_subsystem_restart_internal_callback = nullptr;
+    }
+    return status;
+}
+
 wifi_error WifiLegacyHal::startRttRangeRequest(
     const std::string& iface_name, wifi_request_id id,
     const std::vector<wifi_rtt_config>& rtt_configs,
@@ -1471,6 +1497,7 @@
     on_ring_buffer_data_internal_callback = nullptr;
     on_error_alert_internal_callback = nullptr;
     on_radio_mode_change_internal_callback = nullptr;
+    on_subsystem_restart_internal_callback = nullptr;
     on_rtt_results_internal_callback = nullptr;
     on_nan_notify_response_user_callback = nullptr;
     on_nan_event_publish_terminated_user_callback = nullptr;
@@ -1493,7 +1520,7 @@
 
 }  // namespace legacy_hal
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_legacy_hal.h b/wifi/1.5/default/wifi_legacy_hal.h
similarity index 98%
rename from wifi/1.4/default/wifi_legacy_hal.h
rename to wifi/1.5/default/wifi_legacy_hal.h
index 9964460..ae520a8 100644
--- a/wifi/1.4/default/wifi_legacy_hal.h
+++ b/wifi/1.5/default/wifi_legacy_hal.h
@@ -35,7 +35,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 // This is in a separate namespace to prevent typename conflicts between
 // the legacy HAL types and the HIDL interface types.
@@ -142,6 +142,9 @@
 using on_error_alert_callback =
     std::function<void(int32_t, const std::vector<uint8_t>&)>;
 
+// Callback for subsystem restart
+using on_subsystem_restart_callback = std::function<void(const std::string&)>;
+
 // Struct for the mac info from the legacy HAL. This is a cleaner version
 // of the |wifi_mac_info| & |wifi_iface_info|.
 typedef struct {
@@ -277,6 +280,8 @@
         const on_ring_buffer_data_callback& on_data_callback);
     wifi_error deregisterRingBufferCallbackHandler(
         const std::string& iface_name);
+    wifi_error registerSubsystemRestartCallbackHandler(
+        const on_subsystem_restart_callback& on_restart_callback);
     std::pair<wifi_error, std::vector<wifi_ring_buffer_status>>
     getRingBuffersStatus(const std::string& iface_name);
     wifi_error startRingBufferLogging(const std::string& iface_name,
@@ -407,7 +412,7 @@
 
 }  // namespace legacy_hal
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_legacy_hal_stubs.cpp b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
similarity index 98%
rename from wifi/1.4/default/wifi_legacy_hal_stubs.cpp
rename to wifi/1.5/default/wifi_legacy_hal_stubs.cpp
index 153a685..73b5856 100644
--- a/wifi/1.4/default/wifi_legacy_hal_stubs.cpp
+++ b/wifi/1.5/default/wifi_legacy_hal_stubs.cpp
@@ -20,7 +20,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace legacy_hal {
 template <typename>
@@ -143,11 +143,12 @@
     populateStubFor(&hal_fn->wifi_virtual_interface_delete);
     populateStubFor(&hal_fn->wifi_map_dscp_access_category);
     populateStubFor(&hal_fn->wifi_reset_dscp_mapping);
+    populateStubFor(&hal_fn->wifi_set_subsystem_restart_handler);
     return true;
 }
 }  // namespace legacy_hal
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_legacy_hal_stubs.h b/wifi/1.5/default/wifi_legacy_hal_stubs.h
similarity index 96%
rename from wifi/1.4/default/wifi_legacy_hal_stubs.h
rename to wifi/1.5/default/wifi_legacy_hal_stubs.h
index 577a545..7e4eb0a 100644
--- a/wifi/1.4/default/wifi_legacy_hal_stubs.h
+++ b/wifi/1.5/default/wifi_legacy_hal_stubs.h
@@ -20,7 +20,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace legacy_hal {
 #include <hardware_legacy/wifi_hal.h>
@@ -28,7 +28,7 @@
 bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn);
 }  // namespace legacy_hal
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_mode_controller.cpp b/wifi/1.5/default/wifi_mode_controller.cpp
similarity index 98%
rename from wifi/1.4/default/wifi_mode_controller.cpp
rename to wifi/1.5/default/wifi_mode_controller.cpp
index 252121a..b1db8b3 100644
--- a/wifi/1.4/default/wifi_mode_controller.cpp
+++ b/wifi/1.5/default/wifi_mode_controller.cpp
@@ -48,7 +48,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace mode_controller {
 
@@ -85,7 +85,7 @@
 }
 }  // namespace mode_controller
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_mode_controller.h b/wifi/1.5/default/wifi_mode_controller.h
similarity index 97%
rename from wifi/1.4/default/wifi_mode_controller.h
rename to wifi/1.5/default/wifi_mode_controller.h
index 45fa999..2eeca78 100644
--- a/wifi/1.4/default/wifi_mode_controller.h
+++ b/wifi/1.5/default/wifi_mode_controller.h
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 namespace mode_controller {
 using namespace android::hardware::wifi::V1_0;
@@ -55,7 +55,7 @@
 
 }  // namespace mode_controller
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_nan_iface.cpp b/wifi/1.5/default/wifi_nan_iface.cpp
similarity index 99%
rename from wifi/1.4/default/wifi_nan_iface.cpp
rename to wifi/1.5/default/wifi_nan_iface.cpp
index 5764d35..84fb558 100644
--- a/wifi/1.4/default/wifi_nan_iface.cpp
+++ b/wifi/1.5/default/wifi_nan_iface.cpp
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 using hidl_return_util::validateAndCall;
 
@@ -718,7 +718,7 @@
 }
 
 Return<void> WifiNanIface::enableRequest_1_4(
-    uint16_t cmd_id, const NanEnableRequest& msg1,
+    uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
     const V1_2::NanConfigRequestSupplemental& msg2,
     enableRequest_1_4_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
@@ -727,7 +727,7 @@
 }
 
 Return<void> WifiNanIface::configRequest_1_4(
-    uint16_t cmd_id, const NanConfigRequest& msg1,
+    uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
     const V1_2::NanConfigRequestSupplemental& msg2,
     configRequest_1_4_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
@@ -898,7 +898,7 @@
 }
 
 WifiStatus WifiNanIface::enableRequest_1_4Internal(
-    uint16_t cmd_id, const NanEnableRequest& msg1,
+    uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
     const V1_2::NanConfigRequestSupplemental& msg2) {
     legacy_hal::NanEnableRequest legacy_msg;
     if (!hidl_struct_util::convertHidlNanEnableRequest_1_4ToLegacy(
@@ -911,7 +911,7 @@
 }
 
 WifiStatus WifiNanIface::configRequest_1_4Internal(
-    uint16_t cmd_id, const NanConfigRequest& msg1,
+    uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
     const V1_2::NanConfigRequestSupplemental& msg2) {
     legacy_hal::NanConfigRequest legacy_msg;
     if (!hidl_struct_util::convertHidlNanConfigRequest_1_4ToLegacy(
@@ -924,7 +924,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_nan_iface.h b/wifi/1.5/default/wifi_nan_iface.h
similarity index 95%
rename from wifi/1.4/default/wifi_nan_iface.h
rename to wifi/1.5/default/wifi_nan_iface.h
index 06edbf2..efdb2da 100644
--- a/wifi/1.4/default/wifi_nan_iface.h
+++ b/wifi/1.5/default/wifi_nan_iface.h
@@ -28,7 +28,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 using namespace android::hardware::wifi::V1_0;
 using namespace android::hardware::wifi::V1_2;
@@ -105,13 +105,13 @@
         const V1_2::NanConfigRequestSupplemental& msg2,
         configRequest_1_2_cb hidl_status_cb) override;
     Return<void> enableRequest_1_4(
-        uint16_t cmd_id, const NanEnableRequest& msg1,
+        uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
         const V1_2::NanConfigRequestSupplemental& msg2,
-        enableRequest_1_2_cb hidl_status_cb) override;
+        enableRequest_1_4_cb hidl_status_cb) override;
     Return<void> configRequest_1_4(
-        uint16_t cmd_id, const NanConfigRequest& msg1,
+        uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
         const V1_2::NanConfigRequestSupplemental& msg2,
-        configRequest_1_2_cb hidl_status_cb) override;
+        configRequest_1_4_cb hidl_status_cb) override;
 
    private:
     // Corresponding worker functions for the HIDL methods.
@@ -153,10 +153,10 @@
         uint16_t cmd_id, const V1_0::NanConfigRequest& msg,
         const V1_2::NanConfigRequestSupplemental& msg2);
     WifiStatus enableRequest_1_4Internal(
-        uint16_t cmd_id, const NanEnableRequest& msg1,
+        uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
         const V1_2::NanConfigRequestSupplemental& msg2);
     WifiStatus configRequest_1_4Internal(
-        uint16_t cmd_id, const NanConfigRequest& msg,
+        uint16_t cmd_id, const V1_4::NanConfigRequest& msg,
         const V1_2::NanConfigRequestSupplemental& msg2);
 
     // all 1_0 and descendant callbacks
@@ -178,7 +178,7 @@
 };
 
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_p2p_iface.cpp b/wifi/1.5/default/wifi_p2p_iface.cpp
similarity index 97%
rename from wifi/1.4/default/wifi_p2p_iface.cpp
rename to wifi/1.5/default/wifi_p2p_iface.cpp
index 9e7341f..b8893da 100644
--- a/wifi/1.4/default/wifi_p2p_iface.cpp
+++ b/wifi/1.5/default/wifi_p2p_iface.cpp
@@ -23,7 +23,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 using hidl_return_util::validateAndCall;
 
@@ -60,7 +60,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_p2p_iface.h b/wifi/1.5/default/wifi_p2p_iface.h
similarity index 97%
rename from wifi/1.4/default/wifi_p2p_iface.h
rename to wifi/1.5/default/wifi_p2p_iface.h
index a6fc59d..c1adc50 100644
--- a/wifi/1.4/default/wifi_p2p_iface.h
+++ b/wifi/1.5/default/wifi_p2p_iface.h
@@ -25,7 +25,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 using namespace android::hardware::wifi::V1_0;
 
@@ -58,7 +58,7 @@
 };
 
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_rtt_controller.cpp b/wifi/1.5/default/wifi_rtt_controller.cpp
similarity index 94%
rename from wifi/1.4/default/wifi_rtt_controller.cpp
rename to wifi/1.5/default/wifi_rtt_controller.cpp
index 594a116..a0f9969 100644
--- a/wifi/1.4/default/wifi_rtt_controller.cpp
+++ b/wifi/1.5/default/wifi_rtt_controller.cpp
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 using hidl_return_util::validateAndCall;
 
@@ -44,7 +44,7 @@
 
 bool WifiRttController::isValid() { return is_valid_; }
 
-std::vector<sp<IWifiRttControllerEventCallback>>
+std::vector<sp<V1_4::IWifiRttControllerEventCallback>>
 WifiRttController::getEventCallbacks() {
     return event_callbacks_;
 }
@@ -131,7 +131,7 @@
 }
 
 Return<void> WifiRttController::registerEventCallback_1_4(
-    const sp<IWifiRttControllerEventCallback>& callback,
+    const sp<V1_4::IWifiRttControllerEventCallback>& callback,
     registerEventCallback_1_4_cb hidl_status_cb) {
     return validateAndCall(
         this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
@@ -140,7 +140,7 @@
 }
 
 Return<void> WifiRttController::rangeRequest_1_4(
-    uint32_t cmd_id, const hidl_vec<RttConfig>& rtt_configs,
+    uint32_t cmd_id, const hidl_vec<V1_4::RttConfig>& rtt_configs,
     rangeRequest_1_4_cb hidl_status_cb) {
     return validateAndCall(this,
                            WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
@@ -164,7 +164,7 @@
 
 Return<void> WifiRttController::enableResponder_1_4(
     uint32_t cmd_id, const WifiChannelInfo& channel_hint,
-    uint32_t max_duration_seconds, const RttResponder& info,
+    uint32_t max_duration_seconds, const V1_4::RttResponder& info,
     enableResponder_1_4_cb hidl_status_cb) {
     return validateAndCall(
         this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
@@ -252,14 +252,14 @@
 }
 
 WifiStatus WifiRttController::registerEventCallbackInternal_1_4(
-    const sp<IWifiRttControllerEventCallback>& callback) {
+    const sp<V1_4::IWifiRttControllerEventCallback>& callback) {
     // TODO(b/31632518): remove the callback when the client is destroyed
     event_callbacks_.emplace_back(callback);
     return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
 WifiStatus WifiRttController::rangeRequestInternal_1_4(
-    uint32_t cmd_id, const std::vector<RttConfig>& rtt_configs) {
+    uint32_t cmd_id, const std::vector<V1_4::RttConfig>& rtt_configs) {
     std::vector<legacy_hal::wifi_rtt_config> legacy_configs;
     if (!hidl_struct_util::convertHidlVectorOfRttConfigToLegacy(
             rtt_configs, &legacy_configs)) {
@@ -275,7 +275,7 @@
                 LOG(ERROR) << "Callback invoked on an invalid object";
                 return;
             }
-            std::vector<RttResult> hidl_results;
+            std::vector<V1_4::RttResult> hidl_results;
             if (!hidl_struct_util::convertLegacyVectorOfRttResultToHidl(
                     results, &hidl_results)) {
                 LOG(ERROR) << "Failed to convert rtt results to HIDL structs";
@@ -291,7 +291,7 @@
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
-std::pair<WifiStatus, RttCapabilities>
+std::pair<WifiStatus, V1_4::RttCapabilities>
 WifiRttController::getCapabilitiesInternal_1_4() {
     legacy_hal::wifi_error legacy_status;
     legacy_hal::wifi_rtt_capabilities legacy_caps;
@@ -300,7 +300,7 @@
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), {}};
     }
-    RttCapabilities hidl_caps;
+    V1_4::RttCapabilities hidl_caps;
     if (!hidl_struct_util::convertLegacyRttCapabilitiesToHidl(legacy_caps,
                                                               &hidl_caps)) {
         return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
@@ -308,7 +308,7 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
 }
 
-std::pair<WifiStatus, RttResponder>
+std::pair<WifiStatus, V1_4::RttResponder>
 WifiRttController::getResponderInfoInternal_1_4() {
     legacy_hal::wifi_error legacy_status;
     legacy_hal::wifi_rtt_responder legacy_responder;
@@ -317,7 +317,7 @@
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), {}};
     }
-    RttResponder hidl_responder;
+    V1_4::RttResponder hidl_responder;
     if (!hidl_struct_util::convertLegacyRttResponderToHidl(legacy_responder,
                                                            &hidl_responder)) {
         return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
@@ -327,7 +327,7 @@
 
 WifiStatus WifiRttController::enableResponderInternal_1_4(
     uint32_t cmd_id, const WifiChannelInfo& channel_hint,
-    uint32_t max_duration_seconds, const RttResponder& info) {
+    uint32_t max_duration_seconds, const V1_4::RttResponder& info) {
     legacy_hal::wifi_channel_info legacy_channel_info;
     if (!hidl_struct_util::convertHidlWifiChannelInfoToLegacy(
             channel_hint, &legacy_channel_info)) {
@@ -345,7 +345,7 @@
     return createWifiStatusFromLegacyError(legacy_status);
 }
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_rtt_controller.h b/wifi/1.5/default/wifi_rtt_controller.h
similarity index 86%
rename from wifi/1.4/default/wifi_rtt_controller.h
rename to wifi/1.5/default/wifi_rtt_controller.h
index 1f12555..9ac3e06 100644
--- a/wifi/1.4/default/wifi_rtt_controller.h
+++ b/wifi/1.5/default/wifi_rtt_controller.h
@@ -27,7 +27,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 
 /**
@@ -41,7 +41,7 @@
     // Refer to |WifiChip::invalidate()|.
     void invalidate();
     bool isValid();
-    std::vector<sp<IWifiRttControllerEventCallback>> getEventCallbacks();
+    std::vector<sp<V1_4::IWifiRttControllerEventCallback>> getEventCallbacks();
     std::string getIfaceName();
 
     // HIDL methods exposed.
@@ -69,10 +69,10 @@
     Return<void> disableResponder(uint32_t cmd_id,
                                   disableResponder_cb hidl_status_cb) override;
     Return<void> registerEventCallback_1_4(
-        const sp<IWifiRttControllerEventCallback>& callback,
+        const sp<V1_4::IWifiRttControllerEventCallback>& callback,
         registerEventCallback_1_4_cb hidl_status_cb) override;
     Return<void> rangeRequest_1_4(uint32_t cmd_id,
-                                  const hidl_vec<RttConfig>& rtt_configs,
+                                  const hidl_vec<V1_4::RttConfig>& rtt_configs,
                                   rangeRequest_1_4_cb hidl_status_cb) override;
     Return<void> getCapabilities_1_4(
         getCapabilities_1_4_cb hidl_status_cb) override;
@@ -80,7 +80,7 @@
         getResponderInfo_1_4_cb hidl_status_cb) override;
     Return<void> enableResponder_1_4(
         uint32_t cmd_id, const WifiChannelInfo& channel_hint,
-        uint32_t max_duration_seconds, const RttResponder& info,
+        uint32_t max_duration_seconds, const V1_4::RttResponder& info,
         enableResponder_1_4_cb hidl_status_cb) override;
 
    private:
@@ -102,27 +102,27 @@
                                        const V1_0::RttResponder& info);
     WifiStatus disableResponderInternal(uint32_t cmd_id);
     WifiStatus registerEventCallbackInternal_1_4(
-        const sp<IWifiRttControllerEventCallback>& callback);
+        const sp<V1_4::IWifiRttControllerEventCallback>& callback);
     WifiStatus rangeRequestInternal_1_4(
-        uint32_t cmd_id, const std::vector<RttConfig>& rtt_configs);
-    std::pair<WifiStatus, RttCapabilities> getCapabilitiesInternal_1_4();
-    std::pair<WifiStatus, RttResponder> getResponderInfoInternal_1_4();
+        uint32_t cmd_id, const std::vector<V1_4::RttConfig>& rtt_configs);
+    std::pair<WifiStatus, V1_4::RttCapabilities> getCapabilitiesInternal_1_4();
+    std::pair<WifiStatus, V1_4::RttResponder> getResponderInfoInternal_1_4();
     WifiStatus enableResponderInternal_1_4(uint32_t cmd_id,
                                            const WifiChannelInfo& channel_hint,
                                            uint32_t max_duration_seconds,
-                                           const RttResponder& info);
+                                           const V1_4::RttResponder& info);
 
     std::string ifname_;
     sp<IWifiIface> bound_iface_;
     std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
-    std::vector<sp<IWifiRttControllerEventCallback>> event_callbacks_;
+    std::vector<sp<V1_4::IWifiRttControllerEventCallback>> event_callbacks_;
     bool is_valid_;
 
     DISALLOW_COPY_AND_ASSIGN(WifiRttController);
 };
 
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_sta_iface.cpp b/wifi/1.5/default/wifi_sta_iface.cpp
similarity index 99%
rename from wifi/1.4/default/wifi_sta_iface.cpp
rename to wifi/1.5/default/wifi_sta_iface.cpp
index 49f383a..04087fd 100644
--- a/wifi/1.4/default/wifi_sta_iface.cpp
+++ b/wifi/1.5/default/wifi_sta_iface.cpp
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 using hidl_return_util::validateAndCall;
 
@@ -640,7 +640,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_sta_iface.h b/wifi/1.5/default/wifi_sta_iface.h
similarity index 99%
rename from wifi/1.4/default/wifi_sta_iface.h
rename to wifi/1.5/default/wifi_sta_iface.h
index dee04f2..7695f3c 100644
--- a/wifi/1.4/default/wifi_sta_iface.h
+++ b/wifi/1.5/default/wifi_sta_iface.h
@@ -28,7 +28,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 using namespace android::hardware::wifi::V1_0;
 
@@ -172,7 +172,7 @@
 };
 
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_status_util.cpp b/wifi/1.5/default/wifi_status_util.cpp
similarity index 98%
rename from wifi/1.4/default/wifi_status_util.cpp
rename to wifi/1.5/default/wifi_status_util.cpp
index 8ceb926..eb8c869 100644
--- a/wifi/1.4/default/wifi_status_util.cpp
+++ b/wifi/1.5/default/wifi_status_util.cpp
@@ -19,7 +19,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 
 std::string legacyErrorToString(legacy_hal::wifi_error error) {
@@ -106,7 +106,7 @@
 }
 
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/1.4/default/wifi_status_util.h b/wifi/1.5/default/wifi_status_util.h
similarity index 97%
rename from wifi/1.4/default/wifi_status_util.h
rename to wifi/1.5/default/wifi_status_util.h
index 3ff58f0..68f2168 100644
--- a/wifi/1.4/default/wifi_status_util.h
+++ b/wifi/1.5/default/wifi_status_util.h
@@ -24,7 +24,7 @@
 namespace android {
 namespace hardware {
 namespace wifi {
-namespace V1_4 {
+namespace V1_5 {
 namespace implementation {
 using namespace android::hardware::wifi::V1_0;
 
@@ -37,7 +37,7 @@
 WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error);
 
 }  // namespace implementation
-}  // namespace V1_4
+}  // namespace V1_5
 }  // namespace wifi
 }  // namespace hardware
 }  // namespace android
diff --git a/wifi/hostapd/1.0/Android.bp b/wifi/hostapd/1.0/Android.bp
index cce1182..b736167 100644
--- a/wifi/hostapd/1.0/Android.bp
+++ b/wifi/hostapd/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.wifi.hostapd@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IHostapd.hal",
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
index d4063fe..3ddb2b3 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_test_utils.cpp
@@ -47,16 +47,24 @@
 // Helper function to initialize the driver and firmware to AP mode
 // using the vendor HAL HIDL interface.
 void initilializeDriverAndFirmware(const std::string& wifi_instance_name) {
-    sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
-    ChipModeId mode_id;
-    EXPECT_TRUE(configureChipToSupportIfaceType(
-        wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::AP, &mode_id));
+    if (getWifi(wifi_instance_name) != nullptr) {
+        sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
+        ChipModeId mode_id;
+        EXPECT_TRUE(configureChipToSupportIfaceType(
+            wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::AP, &mode_id));
+    } else {
+        LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+    }
 }
 
 // Helper function to deinitialize the driver and firmware
 // using the vendor HAL HIDL interface.
 void deInitilializeDriverAndFirmware(const std::string& wifi_instance_name) {
-    stopWifi(wifi_instance_name);
+    if (getWifi(wifi_instance_name) != nullptr) {
+        stopWifi(wifi_instance_name);
+    } else {
+        LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+    }
 }
 }  // namespace
 
diff --git a/wifi/hostapd/1.1/Android.bp b/wifi/hostapd/1.1/Android.bp
index 64fbc93..bba065d 100644
--- a/wifi/hostapd/1.1/Android.bp
+++ b/wifi/hostapd/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.wifi.hostapd@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "IHostapd.hal",
         "IHostapdCallback.hal",
diff --git a/wifi/hostapd/1.2/Android.bp b/wifi/hostapd/1.2/Android.bp
index 3dcad71..9b26ece 100644
--- a/wifi/hostapd/1.2/Android.bp
+++ b/wifi/hostapd/1.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.wifi.hostapd@1.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IHostapd.hal",
diff --git a/wifi/offload/1.0/Android.bp b/wifi/offload/1.0/Android.bp
index 110bb70..91ed476 100644
--- a/wifi/offload/1.0/Android.bp
+++ b/wifi/offload/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.wifi.offload@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "IOffload.hal",
diff --git a/wifi/supplicant/1.0/Android.bp b/wifi/supplicant/1.0/Android.bp
index d91512f..d46e463 100644
--- a/wifi/supplicant/1.0/Android.bp
+++ b/wifi/supplicant/1.0/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.wifi.supplicant@1.0",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ISupplicant.hal",
diff --git a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
index 3815323..addf066 100644
--- a/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
+++ b/wifi/supplicant/1.0/vts/functional/supplicant_hidl_test_utils.cpp
@@ -58,11 +58,14 @@
     if (wifi_instance_name == "") {
         return;
     }
-
-    sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
-    ChipModeId mode_id;
-    EXPECT_TRUE(configureChipToSupportIfaceType(
-        wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::STA, &mode_id));
+    if (getWifi(wifi_instance_name) != nullptr) {
+        sp<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name);
+        ChipModeId mode_id;
+        EXPECT_TRUE(configureChipToSupportIfaceType(
+            wifi_chip, ::android::hardware::wifi::V1_0::IfaceType::STA, &mode_id));
+    } else {
+        LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+    }
 }
 
 // Helper function to deinitialize the driver and firmware
@@ -72,8 +75,11 @@
     if (wifi_instance_name == "") {
         return;
     }
-
-    stopWifi(wifi_instance_name);
+    if (getWifi(wifi_instance_name) != nullptr) {
+        stopWifi(wifi_instance_name);
+    } else {
+        LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+    }
 }
 
 // Helper function to find any iface of the desired type exposed.
diff --git a/wifi/supplicant/1.1/Android.bp b/wifi/supplicant/1.1/Android.bp
index 6d940d1..bc20dca 100644
--- a/wifi/supplicant/1.1/Android.bp
+++ b/wifi/supplicant/1.1/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.wifi.supplicant@1.1",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "ISupplicant.hal",
         "ISupplicantStaIface.hal",
diff --git a/wifi/supplicant/1.2/Android.bp b/wifi/supplicant/1.2/Android.bp
index 185d2b8..aa2fa7b 100644
--- a/wifi/supplicant/1.2/Android.bp
+++ b/wifi/supplicant/1.2/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.wifi.supplicant@1.2",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ISupplicant.hal",
diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp
index 7b96b87..1eb8eea 100644
--- a/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.2/vts/functional/supplicant_p2p_iface_hidl_test.cpp
@@ -43,6 +43,9 @@
     virtual void SetUp() override {
         SupplicantHidlTestBase::SetUp();
         EXPECT_TRUE(turnOnExcessiveLogging(supplicant_));
+        if (!::testing::deviceSupportsFeature("android.hardware.wifi.direct")) {
+            GTEST_SKIP() << "Wi-Fi Direct is not supported, skip this test.";
+        }
         p2p_iface_ = getSupplicantP2pIface_1_2(supplicant_);
         ASSERT_NE(p2p_iface_.get(), nullptr);
     }
diff --git a/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp
index f38dda4..7377f78 100644
--- a/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.2/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -302,7 +302,8 @@
     }
 
     hidl_string uri =
-        "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
+        "DPP:C:81/1,117/"
+        "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
         "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;";
     uint32_t peer_id = 0;
 
@@ -347,7 +348,8 @@
     }
 
     hidl_string uri =
-        "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
+        "DPP:C:81/1,117/"
+        "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
         "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;";
     uint32_t peer_id = 0;
 
@@ -413,7 +415,8 @@
     }
 
     hidl_string uri =
-        "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
+        "DPP:C:81/1,117/"
+        "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
         "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;";
     uint32_t peer_id = 0;
 
diff --git a/wifi/supplicant/1.3/Android.bp b/wifi/supplicant/1.3/Android.bp
index 15c72fe..4268490 100644
--- a/wifi/supplicant/1.3/Android.bp
+++ b/wifi/supplicant/1.3/Android.bp
@@ -3,9 +3,6 @@
 hidl_interface {
     name: "android.hardware.wifi.supplicant@1.3",
     root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
     srcs: [
         "types.hal",
         "ISupplicant.hal",
diff --git a/wifi/supplicant/1.3/vts/functional/Android.bp b/wifi/supplicant/1.3/vts/functional/Android.bp
index 8eebed0..68c2929 100644
--- a/wifi/supplicant/1.3/vts/functional/Android.bp
+++ b/wifi/supplicant/1.3/vts/functional/Android.bp
@@ -64,4 +64,5 @@
         "general-tests",
         "vts",
     ],
+    disable_framework: true,
 }
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
index 4020298..12bd122 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -419,7 +419,8 @@
     }
 
     hidl_string uri =
-        "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
+        "DPP:C:81/1,117/"
+        "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
         "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;";
     uint32_t peer_id = 0;
 
@@ -470,7 +471,8 @@
     }
 
     hidl_string uri =
-        "DPP:C:81/1;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
+        "DPP:C:81/1,117/"
+        "40;M:48d6d5bd1de1;I:G1197843;K:MDkwEwYHKoZIzj0CAQYIKoZIzj"
         "0DAQcDIgAD0edY4X3N//HhMFYsZfMbQJTiNFtNIWF/cIwMB/gzqOM=;;";
     uint32_t peer_id = 0;
 
diff --git a/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp b/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
index 7603c5b..25091a5 100644
--- a/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
+++ b/wifi/supplicant/1.3/vts/functional/supplicant_sta_network_hidl_test.cpp
@@ -288,6 +288,49 @@
             });
     }
 }
+
+/*
+ * SetGetWapiPsk
+ */
+TEST_P(SupplicantStaNetworkHidlTest, SetGetWapiPsk) {
+    uint32_t keyMgmt = (uint32_t)ISupplicantStaNetwork::KeyMgmtMask::WAPI_PSK;
+    char kTestPskPassphrase[] = "\"123456780abcdef0123456780abcdef0deadbeef\"";
+    char kTestPskHex[] = "12345678";
+
+    if (!isWapiSupported()) {
+        GTEST_SKIP() << "Skipping test since WAPI is not supported.";
+    }
+
+    sta_network_->setKeyMgmt_1_3(keyMgmt, [](const SupplicantStatus &status) {
+        if (SupplicantStatusCode::SUCCESS != status.code) {
+            // for unsupport case
+            EXPECT_EQ(SupplicantStatusCode::FAILURE_UNKNOWN, status.code);
+        }
+    });
+
+    sta_network_->setPskPassphrase(
+        kTestPskPassphrase, [](const SupplicantStatus &status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
+
+    sta_network_->getPskPassphrase(
+        [&](const SupplicantStatus &status, const hidl_string &psk) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+            EXPECT_EQ(kTestPskPassphrase, std::string(psk.c_str()));
+        });
+
+    sta_network_->setPskPassphrase(
+        kTestPskHex, [](const SupplicantStatus &status) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+        });
+
+    sta_network_->getPskPassphrase(
+        [&](const SupplicantStatus &status, const hidl_string &psk) {
+            EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+            EXPECT_EQ(kTestPskHex, std::string(psk.c_str()));
+        });
+}
+
 /*
  * SetEapErp
  */