Merge "Add DescramberTests in Tuner VTS" into rvc-dev
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/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/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 2e6fa25..341aae7 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -2527,14 +2527,21 @@
      * 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]: -1      // 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".
      *
      * 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
@@ -4367,6 +4374,12 @@
      * Name of the user that should be created.
      */
     string userNameToCreate;
+
+    /**
+     * System locales of the initial user (value will be passed as-is to
+     * android.provider.Settings.System.SYSTEM_LOCALES)
+     */
+    string userLocales;
 };
 
 /**
diff --git a/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp b/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
index fbddf6d..613c528 100644
--- a/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
+++ b/boot/1.0/vts/functional/VtsHalBootV1_0TargetTest.cpp
@@ -82,6 +82,10 @@
 
 // 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 +94,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);
     }
@@ -105,19 +119,22 @@
 
 // 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/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 40cb4e0..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;
@@ -306,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/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/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.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/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.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/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/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/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index bf5fbfe..550a2e0 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -6942,8 +6942,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/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/current.txt b/current.txt
index edf96b2..e2d1408 100644
--- a/current.txt
+++ b/current.txt
@@ -590,6 +590,7 @@
 d3a344b7bd4c0d2658ae7209f55a979b8f53f361fd00f4fca29d5baa56d11fd2 android.hardware.automotive.evs@1.0::types
 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 +602,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
@@ -717,6 +720,7 @@
 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
 b454df853441c12f6e425e8a60dd29fda20f5e6e39b93d1103e4b37495db38aa android.hardware.radio@1.5::IRadio
 fcbb0742a88215ee7a6d7ce0825d253eb2b50391fc6c8c48667f9fd7f6d4549e android.hardware.radio@1.5::IRadioIndication
 b809193970a91ca637a4b0184767315601d32e3ef3d5992ffbc7a8d14a14f015 android.hardware.radio@1.5::IRadioResponse
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/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/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/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
index c93e89b..094c7c1 100644
--- a/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/2.0/vts/functional/gnss_hal_test_cases.cpp
@@ -223,9 +223,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();
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/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
index 9e56534..529fb18 100644
--- a/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
+++ b/graphics/mapper/4.0/vts/functional/VtsHalGraphicsMapperV4_0TargetTest.cpp
@@ -1927,8 +1927,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));
@@ -1943,8 +1948,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));
@@ -1958,8 +1968,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));
@@ -1973,9 +1988,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));
@@ -2009,8 +2028,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));
@@ -2022,8 +2045,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));
@@ -2035,8 +2063,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));
@@ -2048,8 +2081,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));
@@ -2061,8 +2099,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));
@@ -2074,9 +2117,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/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..d7f47e8 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.
@@ -176,7 +194,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.
@@ -274,7 +293,7 @@
      *            "DeviceAuthentication",
      *            SessionTranscript,
      *            DocType,
-     *            DeviceNameSpaceBytes,
+     *            DeviceNameSpacesBytes,
      *        ]
      *
      *        DocType = tstr
@@ -343,4 +362,25 @@
      * @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/IWritableIdentityCredential.aidl b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
index 07486e6..b7ad283 100644
--- a/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
+++ b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
@@ -120,6 +120,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().
      *
@@ -288,4 +290,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..8a00d22 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,6 +33,7 @@
 namespace aidl::android::hardware::identity {
 
 using ::aidl::android::hardware::keymaster::Timestamp;
+using ::android::base::StringPrintf;
 using ::std::optional;
 
 using namespace ::android::hardware::identity;
@@ -196,15 +198,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 +207,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";
@@ -225,19 +229,11 @@
         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,6 +249,18 @@
     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,
@@ -451,7 +459,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,13 +471,13 @@
                             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.
+    // Validate all the access control profiles in the requestData.
     bool haveAuthToken = (authToken.mac.size() > 0);
     for (const auto& profile : accessControlProfiles) {
         if (!secureAccessControlProfileCheckMac(profile, storageKey_)) {
@@ -479,7 +487,8 @@
         }
         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) {
@@ -500,10 +509,118 @@
     itemsRequest_ = itemsRequest;
     signingKeyBlob_ = byteStringToUnsigned(signingKeyBlobS);
 
+    // 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 +679,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"));
@@ -608,7 +725,6 @@
 ndk::ScopedAStatus IdentityCredential::retrieveEntryValue(const vector<int8_t>& encryptedContentS,
                                                           vector<int8_t>* outContent) {
     auto encryptedContent = byteStringToUnsigned(encryptedContentS);
-
     optional<vector<uint8_t>> content =
             support::decryptAes128Gcm(storageKey_, encryptedContent, entryAdditionalData_);
     if (!content) {
@@ -659,6 +775,17 @@
     }
     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;
diff --git a/identity/aidl/default/IdentityCredential.h b/identity/aidl/default/IdentityCredential.h
index fc29254..40070c0 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,16 +32,19 @@
 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.
@@ -51,6 +55,9 @@
     ndk::ScopedAStatus createEphemeralKeyPair(vector<int8_t>* outKeyPair) override;
     ndk::ScopedAStatus setReaderEphemeralPublicKey(const vector<int8_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,
@@ -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/WritableIdentityCredential.cpp b/identity/aidl/default/WritableIdentityCredential.cpp
index 52cd496..7732c33 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;
 
@@ -105,6 +107,12 @@
     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_) {
@@ -255,7 +263,7 @@
 }
 
 ndk::ScopedAStatus WritableIdentityCredential::addEntryValue(const vector<int8_t>& contentS,
-                                                             vector<int8_t>* outEncryptedContent) {
+                                                             vector<int8_t>* outEncryptedContentS) {
     auto content = byteStringToUnsigned(contentS);
     size_t contentSize = content.size();
 
@@ -311,7 +319,7 @@
         signedDataCurrentNamespace_.add(std::move(entryMap));
     }
 
-    *outEncryptedContent = byteStringToSigned(encryptedContent.value());
+    *outEncryptedContentS = byteStringToSigned(encryptedContent.value());
     return ndk::ScopedAStatus::ok();
 }
 
@@ -384,6 +392,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
diff --git a/identity/aidl/default/WritableIdentityCredential.h b/identity/aidl/default/WritableIdentityCredential.h
index cb91f7b..05104d7 100644
--- a/identity/aidl/default/WritableIdentityCredential.h
+++ b/identity/aidl/default/WritableIdentityCredential.h
@@ -43,6 +43,9 @@
                                                  const vector<int8_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;
 
@@ -62,7 +65,7 @@
             vector<int8_t>* outCredentialData,
             vector<int8_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..5b075c6 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -8,10 +8,16 @@
         "VtsHalIdentityEndToEndTest.cpp",
         "VtsIWritableIdentityCredentialTests.cpp",
         "VtsIdentityTestUtils.cpp",
+        "VtsAttestationTests.cpp",
+        "VtsAttestationParserSupport.cpp",
     ],
     shared_libs: [
+        "android.hardware.keymaster@4.0",
         "libbinder",
         "libcrypto",
+        "libkeymaster_portable",
+        "libsoft_attestation_cert",
+        "libpuresoftkeymasterdevice",
     ],
     static_libs: [
         "libcppbor",
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..00b5893
--- /dev/null
+++ b/identity/aidl/vts/VtsAttestationTests.cpp
@@ -0,0 +1,188 @@
+/*
+ * 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, verifyAttestationWithEmptyChallengeEmptyId) {
+    Status result;
+
+    HardwareInformation hwInfo;
+    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
+    sp<IWritableIdentityCredential> writableCredential;
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
+
+    vector<uint8_t> attestationChallenge;
+    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, verifyAttestationWithEmptyChallengeNonemptyId) {
+    Status result;
+
+    HardwareInformation hwInfo;
+    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
+    sp<IWritableIdentityCredential> writableCredential;
+    ASSERT_TRUE(setupWritableCredential(writableCredential, credentialStore_));
+
+    vector<uint8_t> attestationChallenge;
+    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, 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..464ab0c 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>
@@ -43,6 +43,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:
@@ -68,13 +71,13 @@
     // 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 +85,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 +116,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 +145,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));
     }
 
@@ -268,6 +288,11 @@
     Certificate signingKeyCertificate;
     ASSERT_TRUE(credential->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
 
+    vector<RequestNamespace> requestedNamespaces = test_utils::buildRequestNamespaces(testEntries);
+    // OK to fail, not available in v1 HAL
+    credential->setRequestedNamespaces(requestedNamespaces).isOk();
+    // OK to fail, not available in v1 HAL
+    credential->setVerificationToken(verificationToken);
     ASSERT_TRUE(credential
                         ->startRetrieval(secureProfiles.value(), authToken, itemsRequestBytes,
                                          signingKeyBlob, sessionTranscriptBytes,
diff --git a/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp b/identity/aidl/vts/VtsIWritableIdentityCredentialTests.cpp
index b68fbb5..8b0c050 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;
@@ -68,13 +72,18 @@
     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, 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 +96,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,7 +126,7 @@
 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};
@@ -131,7 +147,7 @@
 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};
@@ -143,7 +159,7 @@
 TEST_P(IdentityCredentialTests, verifyStartPersonalizationZero) {
     Status result;
     sp<IWritableIdentityCredential> writableCredential;
-    ASSERT_TRUE(test_utils::SetupWritableCredential(writableCredential, credentialStore_));
+    ASSERT_TRUE(test_utils::setupWritableCredential(writableCredential, credentialStore_));
 
     const vector<int32_t> entryCounts = {0};
     writableCredential->startPersonalization(0, entryCounts);
@@ -154,7 +170,7 @@
 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};
@@ -166,7 +182,7 @@
 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};
@@ -178,7 +194,7 @@
 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};
@@ -186,7 +202,7 @@
     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 +212,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 +221,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,7 +231,7 @@
 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);
@@ -272,25 +288,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 +318,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 +375,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 +393,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 +427,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 +534,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);
+    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 +576,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 +596,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, {});
@@ -584,11 +612,11 @@
     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 +624,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 +635,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 +653,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 +662,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,7 +671,7 @@
 
 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};
     Status result = writableCredential->startPersonalization(1, entryCounts);
diff --git a/identity/aidl/vts/VtsIdentityTestUtils.cpp b/identity/aidl/vts/VtsIdentityTestUtils.cpp
index 3aeebc6..aaebcbe 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;
@@ -120,7 +126,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 +170,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/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..366cd0e 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++) {
+        uint8_t byte = data[offset + n];
+        value |= byte << (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++) {
+        uint8_t byte = data[offset + n];
+        value |= byte << (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/aidl/Android.bp b/keymaster/aidl/Android.bp
index 3011da6..56a3ca9 100644
--- a/keymaster/aidl/Android.bp
+++ b/keymaster/aidl/Android.bp
@@ -15,5 +15,8 @@
             },
         },
     },
-    versions: ["1"],
+    versions: [
+        "1",
+        "2",
+    ],
 }
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/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.2/types.hal b/neuralnetworks/1.2/types.hal
index 2c3c599..92cf2aa 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,
 
diff --git a/neuralnetworks/1.3/types.hal b/neuralnetworks/1.3/types.hal
index 56930c2..39ea4c2 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,
 
diff --git a/neuralnetworks/1.3/vts/functional/AndroidTest.xml b/neuralnetworks/1.3/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..30cff2e
--- /dev/null
+++ b/neuralnetworks/1.3/vts/functional/AndroidTest.xml
@@ -0,0 +1,36 @@
+<?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" >
+        <!-- b/156691406, b/155577050, 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=-*Validation*:*DynamicOutputShapeTest*:*FencedComputeTest*:*MemoryDomain*:*QuantizationCouplingTest*:*DeadlineTest*:*resize_*_v1_3*:*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_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/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.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
index 95136bb..e4c0877 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
@@ -22,6 +22,13 @@
  * 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 +60,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 +99,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;
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/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/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/tv/tuner/1.0/default/Demux.cpp b/tv/tuner/1.0/default/Demux.cpp
index 4e5ae4b..da56041 100644
--- a/tv/tuner/1.0/default/Demux.cpp
+++ b/tv/tuner/1.0/default/Demux.cpp
@@ -60,13 +60,7 @@
     ALOGV("%s", __FUNCTION__);
 
     uint32_t filterId;
-    if (!mUnusedFilterIds.empty()) {
-        filterId = *mUnusedFilterIds.begin();
-
-        mUnusedFilterIds.erase(filterId);
-    } else {
-        filterId = ++mLastUsedFilterId;
-    }
+    filterId = ++mLastUsedFilterId;
 
     mUsedFilterIds.insert(filterId);
 
@@ -84,6 +78,9 @@
     }
 
     mFilters[filterId] = filter;
+    if (filter->isPcrFilter()) {
+        mPcrFilterIds.insert(filterId);
+    }
     bool result = true;
     if (mDvr != nullptr && mDvr->getType() == DvrType::PLAYBACK) {
         result = mDvr->addPlaybackFilter(filter);
@@ -102,19 +99,53 @@
     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()) {
+        ALOGE("[Demux] No PCR filter opened.");
+        // Return the lowest pcr filter id in the default implementation as the av sync id
+        _hidl_cb(Result::SUCCESS, *mPcrFilterIds.begin());
+        return Void();
+    }
+
+    _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,7 +154,6 @@
 Return<Result> Demux::close() {
     ALOGV("%s", __FUNCTION__);
 
-    mUnusedFilterIds.clear();
     mUsedFilterIds.clear();
     mLastUsedFilterId = -1;
 
@@ -171,7 +201,6 @@
     // resetFilterRecords(filterId);
     mUsedFilterIds.erase(filterId);
     mRecordFilterIds.erase(filterId);
-    mUnusedFilterIds.insert(filterId);
     mFilters.erase(filterId);
 
     return Result::SUCCESS;
diff --git a/tv/tuner/1.0/default/Demux.h b/tv/tuner/1.0/default/Demux.h
index 3c91daf..6c46b0d 100644
--- a/tv/tuner/1.0/default/Demux.h
+++ b/tv/tuner/1.0/default/Demux.h
@@ -130,6 +130,7 @@
 
     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.
@@ -141,13 +142,6 @@
      */
     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;
-    /**
      * Record all the attached record filter Ids.
      * Any removed filter id should be removed from this set.
      */
diff --git a/tv/tuner/1.0/default/Filter.cpp b/tv/tuner/1.0/default/Filter.cpp
index fef7a35..8bca70c 100644
--- a/tv/tuner/1.0/default/Filter.cpp
+++ b/tv/tuner/1.0/default/Filter.cpp
@@ -37,6 +37,32 @@
     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;
+            }
+            break;
+        case DemuxFilterMainType::MMTP:
+            if (mType.subType.mmtpFilterType() == DemuxMmtpFilterType::AUDIO ||
+                mType.subType.mmtpFilterType() == DemuxMmtpFilterType::VIDEO) {
+                mIsMediaFilter = true;
+            }
+            break;
+        case DemuxFilterMainType::IP:
+            break;
+        case DemuxFilterMainType::TLV:
+            break;
+        case DemuxFilterMainType::ALP:
+            break;
+        default:
+            break;
+    }
 }
 
 Filter::~Filter() {}
@@ -73,16 +99,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;
diff --git a/tv/tuner/1.0/default/Filter.h b/tv/tuner/1.0/default/Filter.h
index 9b49ad8..09e9604 100644
--- a/tv/tuner/1.0/default/Filter.h
+++ b/tv/tuner/1.0/default/Filter.h
@@ -89,6 +89,8 @@
     void attachFilterToRecord(const sp<Dvr> dvr);
     void detachFilterFromRecord();
     void freeAvHandle();
+    bool isMediaFilter() { return mIsMediaFilter; };
+    bool isPcrFilter() { return mIsPcrFilter; };
 
   private:
     // Tuner service
@@ -104,6 +106,7 @@
     uint32_t mBufferSize;
     DemuxFilterType mType;
     bool mIsMediaFilter = false;
+    bool mIsPcrFilter = false;
     DemuxFilterSettings mFilterSettings;
 
     uint16_t mTpid;
diff --git a/tv/tuner/1.0/vts/functional/DemuxTests.cpp b/tv/tuner/1.0/vts/functional/DemuxTests.cpp
index b1d8a0a..6c32534 100644
--- a/tv/tuner/1.0/vts/functional/DemuxTests.cpp
+++ b/tv/tuner/1.0/vts/functional/DemuxTests.cpp
@@ -38,4 +38,25 @@
     auto status = mDemux->close();
     mDemux = nullptr;
     return AssertionResult(status.isOk());
+}
+
+void DemuxTests::getAvSyncId(sp<IFilter> filter, uint32_t& avSyncHwId) {
+    ASSERT_TRUE(mDemux) << "Demux is not opened yet.";
+    Result status;
+    mDemux->getAvSyncHwId(filter, [&](Result result, uint32_t id) {
+        status = result;
+        avSyncHwId = id;
+    });
+    ASSERT_TRUE(status == Result::SUCCESS) << "Fail to get avSyncHwId.";
+}
+
+void DemuxTests::getAvSyncTime(uint32_t avSyncId) {
+    ASSERT_TRUE(mDemux) << "Demux is not opened yet.";
+    Result status;
+    uint64_t syncTime;
+    mDemux->getAvSyncTime(avSyncId, [&](Result result, uint64_t time) {
+        status = result;
+        syncTime = time;
+    });
+    ASSERT_TRUE(status == Result::SUCCESS) << "Fail to get avSyncTime.";
 }
\ 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..0443c67 100644
--- a/tv/tuner/1.0/vts/functional/DemuxTests.h
+++ b/tv/tuner/1.0/vts/functional/DemuxTests.h
@@ -31,6 +31,7 @@
 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::ITuner;
 using android::hardware::tv::tuner::V1_0::Result;
 
@@ -42,6 +43,8 @@
 
     AssertionResult openDemux(sp<IDemux>& demux, uint32_t& demuxId);
     AssertionResult setDemuxFrontendDataSource(uint32_t frontendId);
+    void getAvSyncId(sp<IFilter> filter, uint32_t& avSyncHwId);
+    void getAvSyncTime(uint32_t avSyncId);
     AssertionResult closeDemux();
 
   protected:
diff --git a/tv/tuner/1.0/vts/functional/FrontendTests.cpp b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
index fc5071c..d54a959 100644
--- a/tv/tuner/1.0/vts/functional/FrontendTests.cpp
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.cpp
@@ -246,6 +246,120 @@
     return AssertionResult(status == Result::SUCCESS);
 }
 
+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) {
     EXPECT_TRUE(mFrontendCallback)
             << "test with openFrontendById/setFrontendCallback/getFrontendInfo first.";
@@ -294,6 +408,7 @@
     ASSERT_TRUE(openFrontendById(feId));
     ASSERT_TRUE(setFrontendCallback());
     ASSERT_TRUE(tuneFrontend(frontendConf));
+    verifyFrontendStatus(frontendConf.tuneStatusTypes, frontendConf.expectTuneStatuses);
     ASSERT_TRUE(stopTuneFrontend());
     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..2bdc8fd 100644
--- a/tv/tuner/1.0/vts/functional/FrontendTests.h
+++ b/tv/tuner/1.0/vts/functional/FrontendTests.h
@@ -109,6 +109,8 @@
     AssertionResult scanFrontend(FrontendConfig config, FrontendScanType type);
     AssertionResult stopScanFrontend();
     AssertionResult tuneFrontend(FrontendConfig config);
+    void verifyFrontendStatus(vector<FrontendStatusType> statusTypes,
+                              vector<FrontendStatus> expectStatuses);
     AssertionResult stopTuneFrontend();
     AssertionResult closeFrontend();
 
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
index 86cea1f..a365282 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -290,6 +290,41 @@
     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));
+    mDemuxTests.getAvSyncId(mediaFilter, avSyncHwId);
+    ASSERT_TRUE(pcrFilterId == avSyncHwId);
+    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
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
index 6ce30c0..2bdb537 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.h
@@ -74,6 +74,7 @@
 
         mFrontendTests.setService(mService);
         mDemuxTests.setService(mService);
+        mFilterTests.setService(mService);
     }
 
   protected:
@@ -84,6 +85,7 @@
     sp<ITuner> mService;
     FrontendTests mFrontendTests;
     DemuxTests mDemuxTests;
+    FilterTests mFilterTests;
 };
 
 class TunerFilterHidlTest : public testing::TestWithParam<std::string> {
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
index 73d83ff..f2dd197 100644
--- a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TestConfigurations.h
@@ -40,6 +40,8 @@
 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;
@@ -108,6 +110,8 @@
 struct FrontendConfig {
     FrontendType type;
     FrontendSettings settings;
+    vector<FrontendStatusType> tuneStatusTypes;
+    vector<FrontendStatus> expectTuneStatuses;
 };
 
 struct ChannelConfig {
@@ -154,6 +158,14 @@
             .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[DVBS].type = FrontendType::DVBS;
 };
 
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_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/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/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.4/default/tests/mock_wifi_iface_util.h b/wifi/1.4/default/tests/mock_wifi_iface_util.h
index 3b36f13..8d77a7d 100644
--- a/wifi/1.4/default/tests/mock_wifi_iface_util.h
+++ b/wifi/1.4/default/tests/mock_wifi_iface_util.h
@@ -41,6 +41,7 @@
                  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
diff --git a/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp
index d5b1a50..323d2ff 100644
--- a/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.4/default/tests/wifi_chip_unit_tests.cpp
@@ -787,6 +787,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");
diff --git a/wifi/1.4/default/wifi_chip.cpp b/wifi/1.4/default/wifi_chip.cpp
index 61912a5..8747e61 100644
--- a/wifi/1.4/default/wifi_chip.cpp
+++ b/wifi/1.4/default/wifi_chip.cpp
@@ -885,7 +885,7 @@
     }
     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();
diff --git a/wifi/1.4/default/wifi_iface_util.cpp b/wifi/1.4/default/wifi_iface_util.cpp
index 13ba022..49b7674 100644
--- a/wifi/1.4/default/wifi_iface_util.cpp
+++ b/wifi/1.4/default/wifi_iface_util.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <net/if.h>
 #include <cstddef>
 #include <iostream>
 #include <limits>
@@ -122,6 +123,10 @@
     }
     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
diff --git a/wifi/1.4/default/wifi_iface_util.h b/wifi/1.4/default/wifi_iface_util.h
index f83d717..126b6ca 100644
--- a/wifi/1.4/default/wifi_iface_util.h
+++ b/wifi/1.4/default/wifi_iface_util.h
@@ -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();
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..9d84223 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());
 
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,
 }