Merge "vibrator: Document the source of always-on source IDs."
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 0e18f48..543acf6 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -7,7 +7,7 @@
       "name": "vts_treble_vintf_vendor_test"
     },
     {
-      "name": "hidl_implementation_test"
+      "name": "hal_implementation_test"
     }
   ]
 }
diff --git a/audio/common/all-versions/copyHAL.sh b/audio/common/all-versions/copyHAL.sh
index 56559d1..0a32a51 100755
--- a/audio/common/all-versions/copyHAL.sh
+++ b/audio/common/all-versions/copyHAL.sh
@@ -21,7 +21,7 @@
 
 readonly FWK_DIRECTORY=frameworks/av/media/libaudiohal
 readonly IMPL_DIRECTORY=impl
-readonly IMPL_FACTORYHAL=$IMPL_DIRECTORY/include/libaudiohal/FactoryHalHidl.h
+readonly IMPL_FACTORYHAL=FactoryHalHidl.cpp
 
 readonly VTS_DIRECTORY=test/vts-testcase/hal/audio
 readonly VTS_LIST=test/vts/tools/build/tasks/list/vts_test_lib_hidl_package_list.mk
@@ -150,7 +150,7 @@
 
 createFrameworkAdapter() {
     updateVersion -v original_before=1 Android.bp
-    updateVersion -v original_before=1 -v RS= -v ORS='\n\n' $IMPL_FACTORYHAL/Android.bp
+    updateVersion -v original_before=1 -v RS= -v ORS='\n\n' $IMPL_DIRECTORY/Android.bp
     updateVersion -v original_after=1 $IMPL_FACTORYHAL
 }
 echo "Now creating the framework adapter version"
diff --git a/audio/effect/6.0/xml/api/current.txt b/audio/effect/6.0/xml/api/current.txt
index 072cf8f..cd5ca2a 100644
--- a/audio/effect/6.0/xml/api/current.txt
+++ b/audio/effect/6.0/xml/api/current.txt
@@ -34,6 +34,10 @@
 
   public class DeviceProcessType extends audio.effects.V6_0.StreamProcessingType {
     ctor public DeviceProcessType();
+    method public String getAddress();
+    method public audio.effects.V6_0.DeviceType getType();
+    method public void setAddress(String);
+    method public void setType(audio.effects.V6_0.DeviceType);
   }
 
   public enum DeviceType {
diff --git a/audio/effect/6.0/xml/audio_effects_conf.xsd b/audio/effect/6.0/xml/audio_effects_conf.xsd
index fcfecda..eeaaf63 100644
--- a/audio/effect/6.0/xml/audio_effects_conf.xsd
+++ b/audio/effect/6.0/xml/audio_effects_conf.xsd
@@ -255,10 +255,8 @@
     </xs:annotation>
     <xs:complexContent>
       <xs:extension base="aec:streamProcessingType">
-         <xs:complexType>
-             <xs:attribute name="address" type="xs:string" use="required"/>
-             <xs:attribute name="type" type="aec:deviceType" use="required"/>
-         </xs:complexType>
+         <xs:attribute name="address" type="xs:string" use="required"/>
+         <xs:attribute name="type" type="aec:deviceType" use="required"/>
       </xs:extension>
     </xs:complexContent>
   </xs:complexType>
@@ -322,4 +320,4 @@
       <xs:field xpath="@effect"/>
     </xs:keyref>
   </xs:element>
-</xs:schema>
\ No newline at end of file
+</xs:schema>
diff --git a/automotive/evs/1.0/vts/functional/Android.bp b/automotive/evs/1.0/vts/functional/Android.bp
index 2ef33fd..47702fd 100644
--- a/automotive/evs/1.0/vts/functional/Android.bp
+++ b/automotive/evs/1.0/vts/functional/Android.bp
@@ -25,8 +25,10 @@
     shared_libs: [
         "libui",
     ],
-    static_libs: ["android.hardware.automotive.evs@1.0"],
-    test_suites: ["general-tests"],
+    static_libs: [
+        "android.hardware.automotive.evs@1.0",
+    ],
+    test_suites: ["vts-core"],
     cflags: [
         "-O0",
         "-g",
diff --git a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
index f7580f0..54862a2 100644
--- a/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
+++ b/automotive/evs/1.0/vts/functional/VtsHalEvsV1_0TargetTest.cpp
@@ -17,15 +17,6 @@
 #define LOG_TAG "VtsHalEvsTest"
 
 
-// Note:  We have't got a great way to indicate which target
-// should be tested, so we'll leave the interface served by the
-// default (mock) EVS driver here for easy reference.  All
-// actual EVS drivers should serve on the EvsEnumeratorHw name,
-// however, so the code is checked in that way.
-//const static char kEnumeratorName[]  = "EvsEnumeratorHw-Mock";
-const static char kEnumeratorName[]  = "EvsEnumeratorHw";
-
-
 // These values are called out in the EVS design doc (as of Mar 8, 2017)
 static const int kMaxStreamStartMilliseconds = 500;
 static const int kMinimumFramesPerSecond = 10;
@@ -53,8 +44,9 @@
 #include <android/hardware/automotive/evs/1.0/IEvsCameraStream.h>
 #include <android/hardware/automotive/evs/1.0/IEvsDisplay.h>
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 using namespace ::android::hardware::automotive::evs::V1_0;
 using ::android::hardware::Return;
@@ -64,32 +56,19 @@
 using ::android::hardware::hidl_string;
 using ::android::sp;
 
-// Test environment for Evs HIDL HAL.
-class EvsHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static EvsHidlEnvironment* Instance() {
-        static EvsHidlEnvironment* instance = new EvsHidlEnvironment;
-        return instance;
-    }
-
-    virtual void registerTestServices() override { registerTestService<IEvsEnumerator>(); }
-
-   private:
-    EvsHidlEnvironment() {}
-};
-
 // The main test class for EVS
-class EvsHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+class EvsHidlTest : public ::testing::TestWithParam<std::string> {
 public:
     virtual void SetUp() override {
         // Make sure we can connect to the enumerator
-        string service_name =
-            EvsHidlEnvironment::Instance()->getServiceName<IEvsEnumerator>(kEnumeratorName);
-        pEnumerator = getService<IEvsEnumerator>(service_name);
+        std::string service_name = GetParam();
+        pEnumerator = IEvsEnumerator::getService(service_name);
+
         ASSERT_NE(pEnumerator.get(), nullptr);
 
-        mIsHwModule = !service_name.compare(kEnumeratorName);
+        // "default" is reserved for EVS manager.
+        constexpr static char kEvsManagerName[] = "default";
+        mIsHwModule = service_name.compare(kEvsManagerName);
     }
 
     virtual void TearDown() override {}
@@ -130,7 +109,7 @@
  * Opens each camera reported by the enumerator and then explicitly closes it via a
  * call to closeCamera.  Then repeats the test to ensure all cameras can be reopened.
  */
-TEST_F(EvsHidlTest, CameraOpenClean) {
+TEST_P(EvsHidlTest, CameraOpenClean) {
     ALOGI("Starting CameraOpenClean test");
 
     // Get the camera list
@@ -162,7 +141,7 @@
  * call.  This ensures that the intended "aggressive open" behavior works.  This is necessary for
  * the system to be tolerant of shutdown/restart race conditions.
  */
-TEST_F(EvsHidlTest, CameraOpenAggressive) {
+TEST_P(EvsHidlTest, CameraOpenAggressive) {
     ALOGI("Starting CameraOpenAggressive test");
 
     // Get the camera list
@@ -216,7 +195,7 @@
  * DisplayOpen:
  * Test both clean shut down and "aggressive open" device stealing behavior.
  */
-TEST_F(EvsHidlTest, DisplayOpen) {
+TEST_P(EvsHidlTest, DisplayOpen) {
     ALOGI("Starting DisplayOpen test");
 
     // Request exclusive access to the EVS display, then let it go
@@ -264,7 +243,7 @@
  * Validate that display states transition as expected and can be queried from either the display
  * object itself or the owning enumerator.
  */
-TEST_F(EvsHidlTest, DisplayStates) {
+TEST_P(EvsHidlTest, DisplayStates) {
     ALOGI("Starting DisplayStates test");
 
     // Ensure the display starts in the expected state
@@ -324,7 +303,7 @@
  * CameraStreamPerformance:
  * Measure and qualify the stream start up time and streaming frame rate of each reported camera
  */
-TEST_F(EvsHidlTest, CameraStreamPerformance) {
+TEST_P(EvsHidlTest, CameraStreamPerformance) {
     ALOGI("Starting CameraStreamPerformance test");
 
     // Get the camera list
@@ -387,7 +366,7 @@
  * Ensure the camera implementation behaves properly when the client holds onto buffers for more
  * than one frame time.  The camera must cleanly skip frames until the client is ready again.
  */
-TEST_F(EvsHidlTest, CameraStreamBuffering) {
+TEST_P(EvsHidlTest, CameraStreamBuffering) {
     ALOGI("Starting CameraStreamBuffering test");
 
     // Arbitrary constant (should be > 1 and less than crazy)
@@ -456,7 +435,7 @@
  * imagery is simply copied to the display buffer and presented on screen.  This is the one test
  * which a human could observe to see the operation of the system on the physical display.
  */
-TEST_F(EvsHidlTest, CameraToDisplayRoundTrip) {
+TEST_P(EvsHidlTest, CameraToDisplayRoundTrip) {
     ALOGI("Starting CameraToDisplayRoundTrip test");
 
     // Get the camera list
@@ -517,7 +496,7 @@
  * Verify that each client can start and stop video streams on the same
  * underlying camera.
  */
-TEST_F(EvsHidlTest, MultiCameraStream) {
+TEST_P(EvsHidlTest, MultiCameraStream) {
     ALOGI("Starting MultiCameraStream test");
 
     if (mIsHwModule) {
@@ -601,11 +580,8 @@
 }
 
 
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(EvsHidlEnvironment::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    EvsHidlEnvironment::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    ALOGI("Test result = %d", status);
-    return status;
-}
+INSTANTIATE_TEST_SUITE_P(
+    PerInstance,
+    EvsHidlTest,
+    testing::ValuesIn(android::hardware::getAllHalInstanceNames(IEvsEnumerator::descriptor)),
+    android::hardware::PrintInstanceNameToString);
diff --git a/bluetooth/1.0/vts/functional/Android.bp b/bluetooth/1.0/vts/functional/Android.bp
index 54039e5..cf25cc8 100644
--- a/bluetooth/1.0/vts/functional/Android.bp
+++ b/bluetooth/1.0/vts/functional/Android.bp
@@ -22,5 +22,8 @@
         "android.hardware.bluetooth@1.0",
         "libbluetooth-types",
     ],
-    test_suites: ["general-tests"],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
 }
diff --git a/boot/1.1/default/boot_control/Android.bp b/boot/1.1/default/boot_control/Android.bp
new file mode 100644
index 0000000..b2e68df
--- /dev/null
+++ b/boot/1.1/default/boot_control/Android.bp
@@ -0,0 +1,61 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_defaults {
+    name: "libboot_control_defaults",
+    vendor: true,
+    recovery_available: true,
+    relative_install_path: "hw",
+
+    cflags: [
+        "-D_FILE_OFFSET_BITS=64",
+        "-Werror",
+        "-Wall",
+        "-Wextra",
+    ],
+
+    shared_libs: [
+        "android.hardware.boot@1.1",
+        "libbase",
+        "liblog",
+    ],
+    static_libs: [
+        "libbootloader_message_vendor",
+        "libfstab",
+    ],
+}
+
+cc_library_static {
+    name: "libboot_control",
+    defaults: ["libboot_control_defaults"],
+    export_include_dirs: ["include"],
+
+    srcs: ["libboot_control.cpp"],
+}
+
+cc_library_shared {
+    name: "bootctrl.default",
+    defaults: ["libboot_control_defaults"],
+
+    srcs: ["legacy_boot_control.cpp"],
+
+    static_libs: [
+        "libboot_control",
+    ],
+    shared_libs: [
+        "libhardware",
+    ],
+}
diff --git a/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h b/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h
new file mode 100644
index 0000000..5468658
--- /dev/null
+++ b/boot/1.1/default/boot_control/include/libboot_control/libboot_control.h
@@ -0,0 +1,89 @@
+//
+// Copyright (C) 2019 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#pragma once
+
+#include <string>
+
+#include <android/hardware/boot/1.1/IBootControl.h>
+
+namespace android {
+namespace bootable {
+
+// Helper library to implement the IBootControl HAL using the misc partition.
+class BootControl {
+  using MergeStatus = ::android::hardware::boot::V1_1::MergeStatus;
+
+ public:
+  bool Init();
+  unsigned int GetNumberSlots();
+  unsigned int GetCurrentSlot();
+  bool MarkBootSuccessful();
+  bool SetActiveBootSlot(unsigned int slot);
+  bool SetSlotAsUnbootable(unsigned int slot);
+  bool SetSlotBootable(unsigned int slot);
+  bool IsSlotBootable(unsigned int slot);
+  const char* GetSuffix(unsigned int slot);
+  bool IsSlotMarkedSuccessful(unsigned int slot);
+  bool SetSnapshotMergeStatus(MergeStatus status);
+  MergeStatus GetSnapshotMergeStatus();
+
+  bool IsValidSlot(unsigned int slot);
+
+  const std::string& misc_device() const {
+    return misc_device_;
+  }
+
+ private:
+  // Whether this object was initialized with data from the bootloader message
+  // that doesn't change until next reboot.
+  bool initialized_ = false;
+
+  // The path to the misc_device as reported in the fstab.
+  std::string misc_device_;
+
+  // The number of slots present on the device.
+  unsigned int num_slots_ = 0;
+
+  // The slot where we are running from.
+  unsigned int current_slot_ = 0;
+};
+
+// Helper functions to write the Virtual A/B merge status message. These are
+// separate because BootControl uses bootloader_control_ab in vendor space,
+// whereas the Virtual A/B merge status is in system space. A HAL might not
+// use bootloader_control_ab, but may want to use the AOSP method of maintaining
+// the merge status.
+
+// If the Virtual A/B message has not yet been initialized, then initialize it.
+// This should be called when the BootControl HAL first loads.
+//
+// If the Virtual A/B message in misc was already initialized, true is returned.
+// If initialization was attempted, but failed, false is returned, and the HAL
+// should fail to load.
+bool InitMiscVirtualAbMessageIfNeeded();
+
+// Save the current merge status as well as the current slot.
+bool SetMiscVirtualAbMergeStatus(unsigned int current_slot,
+                                 android::hardware::boot::V1_1::MergeStatus status);
+
+// Return the current merge status. If the saved status is SNAPSHOTTED but the
+// slot hasn't changed, the status returned will be NONE.
+bool GetMiscVirtualAbMergeStatus(unsigned int current_slot,
+                                 android::hardware::boot::V1_1::MergeStatus* status);
+
+}  // namespace bootable
+}  // namespace android
diff --git a/boot/1.1/default/boot_control/include/private/boot_control_definition.h b/boot/1.1/default/boot_control/include/private/boot_control_definition.h
new file mode 100644
index 0000000..8f02111
--- /dev/null
+++ b/boot/1.1/default/boot_control/include/private/boot_control_definition.h
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ */
+
+
+/**
+ * The A/B-specific bootloader message structure (4-KiB).
+ *
+ * We separate A/B boot control metadata from the regular bootloader
+ * message struct and keep it here. Everything that's A/B-specific
+ * stays after struct bootloader_message, which belongs to the vendor
+ * space of /misc partition. Also, the A/B-specific contents should be
+ * managed by the A/B-bootloader or boot control HAL.
+ *
+ * The slot_suffix field is used for A/B implementations where the
+ * bootloader does not set the androidboot.ro.boot.slot_suffix kernel
+ * commandline parameter. This is used by fs_mgr to mount /system and
+ * other partitions with the slotselect flag set in fstab. A/B
+ * implementations are free to use all 32 bytes and may store private
+ * data past the first NUL-byte in this field. It is encouraged, but
+ * not mandatory, to use 'struct bootloader_control' described below.
+ *
+ * The update_channel field is used to store the Omaha update channel
+ * if update_engine is compiled with Omaha support.
+ */
+struct bootloader_message_ab {
+    struct bootloader_message message;
+    char slot_suffix[32];
+    char update_channel[128];
+
+    // Round up the entire struct to 4096-byte.
+    char reserved[1888];
+};
+
+/**
+ * Be cautious about the struct size change, in case we put anything post
+ * bootloader_message_ab struct (b/29159185).
+ */
+#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus)
+static_assert(sizeof(struct bootloader_message_ab) == 4096,
+              "struct bootloader_message_ab size changes");
+#endif
+
+#define BOOT_CTRL_MAGIC   0x42414342 /* Bootloader Control AB */
+#define BOOT_CTRL_VERSION 1
+
+struct slot_metadata {
+    // Slot priority with 15 meaning highest priority, 1 lowest
+    // priority and 0 the slot is unbootable.
+    uint8_t priority : 4;
+    // Number of times left attempting to boot this slot.
+    uint8_t tries_remaining : 3;
+    // 1 if this slot has booted successfully, 0 otherwise.
+    uint8_t successful_boot : 1;
+    // 1 if this slot is corrupted from a dm-verity corruption, 0
+    // otherwise.
+    uint8_t verity_corrupted : 1;
+    // Reserved for further use.
+    uint8_t reserved : 7;
+} __attribute__((packed));
+
+/* Bootloader Control AB
+ *
+ * This struct can be used to manage A/B metadata. It is designed to
+ * be put in the 'slot_suffix' field of the 'bootloader_message'
+ * structure described above. It is encouraged to use the
+ * 'bootloader_control' structure to store the A/B metadata, but not
+ * mandatory.
+ */
+struct bootloader_control {
+    // NUL terminated active slot suffix.
+    char slot_suffix[4];
+    // Bootloader Control AB magic number (see BOOT_CTRL_MAGIC).
+    uint32_t magic;
+    // Version of struct being used (see BOOT_CTRL_VERSION).
+    uint8_t version;
+    // Number of slots being managed.
+    uint8_t nb_slot : 3;
+    // Number of times left attempting to boot recovery.
+    uint8_t recovery_tries_remaining : 3;
+    // Status of any pending snapshot merge of dynamic partitions.
+    uint8_t merge_status : 3;
+    // Ensure 4-bytes alignment for slot_info field.
+    uint8_t reserved0[1];
+    // Per-slot information.  Up to 4 slots.
+    struct slot_metadata slot_info[4];
+    // Reserved for further use.
+    uint8_t reserved1[8];
+    // CRC32 of all 28 bytes preceding this field (little endian
+    // format).
+    uint32_t crc32_le;
+} __attribute__((packed));
+
+#if (__STDC_VERSION__ >= 201112L) || defined(__cplusplus)
+static_assert(sizeof(struct bootloader_control) ==
+              sizeof(((struct bootloader_message_ab *)0)->slot_suffix),
+              "struct bootloader_control has wrong size");
+#endif
+
diff --git a/boot/1.1/default/boot_control/legacy_boot_control.cpp b/boot/1.1/default/boot_control/legacy_boot_control.cpp
new file mode 100644
index 0000000..73d3a58
--- /dev/null
+++ b/boot/1.1/default/boot_control/legacy_boot_control.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string>
+
+#include <hardware/boot_control.h>
+#include <hardware/hardware.h>
+
+#include <libboot_control/libboot_control.h>
+
+using android::bootable::BootControl;
+
+struct boot_control_private_t {
+  // The base struct needs to be first in the list.
+  boot_control_module_t base;
+
+  BootControl impl;
+};
+
+namespace {
+
+void BootControl_init(boot_control_module_t* module) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  impl.Init();
+}
+
+unsigned int BootControl_getNumberSlots(boot_control_module_t* module) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  return impl.GetNumberSlots();
+}
+
+unsigned int BootControl_getCurrentSlot(boot_control_module_t* module) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  return impl.GetCurrentSlot();
+}
+
+int BootControl_markBootSuccessful(boot_control_module_t* module) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  return impl.MarkBootSuccessful() ? 0 : -1;
+}
+
+int BootControl_setActiveBootSlot(boot_control_module_t* module, unsigned int slot) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  return impl.SetActiveBootSlot(slot) ? 0 : -1;
+}
+
+int BootControl_setSlotAsUnbootable(struct boot_control_module* module, unsigned int slot) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  return impl.SetSlotAsUnbootable(slot) ? 0 : -1;
+}
+
+int BootControl_isSlotBootable(struct boot_control_module* module, unsigned int slot) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  return impl.IsSlotBootable(slot) ? 0 : -1;
+}
+
+int BootControl_isSlotMarkedSuccessful(struct boot_control_module* module, unsigned int slot) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  return impl.IsSlotMarkedSuccessful(slot) ? 0 : -1;
+}
+
+const char* BootControl_getSuffix(boot_control_module_t* module, unsigned int slot) {
+  auto& impl = reinterpret_cast<boot_control_private_t*>(module)->impl;
+  return impl.GetSuffix(slot);
+}
+
+static int BootControl_open(const hw_module_t* module __unused, const char* id __unused,
+                            hw_device_t** device __unused) {
+  /* Nothing to do currently. */
+  return 0;
+}
+
+struct hw_module_methods_t BootControl_methods = {
+  .open = BootControl_open,
+};
+
+}  // namespace
+
+boot_control_private_t HAL_MODULE_INFO_SYM = {
+  .base =
+      {
+          .common =
+              {
+                  .tag = HARDWARE_MODULE_TAG,
+                  .module_api_version = BOOT_CONTROL_MODULE_API_VERSION_0_1,
+                  .hal_api_version = HARDWARE_HAL_API_VERSION,
+                  .id = BOOT_CONTROL_HARDWARE_MODULE_ID,
+                  .name = "AOSP reference bootctrl HAL",
+                  .author = "The Android Open Source Project",
+                  .methods = &BootControl_methods,
+              },
+          .init = BootControl_init,
+          .getNumberSlots = BootControl_getNumberSlots,
+          .getCurrentSlot = BootControl_getCurrentSlot,
+          .markBootSuccessful = BootControl_markBootSuccessful,
+          .setActiveBootSlot = BootControl_setActiveBootSlot,
+          .setSlotAsUnbootable = BootControl_setSlotAsUnbootable,
+          .isSlotBootable = BootControl_isSlotBootable,
+          .getSuffix = BootControl_getSuffix,
+          .isSlotMarkedSuccessful = BootControl_isSlotMarkedSuccessful,
+      },
+};
diff --git a/boot/1.1/default/boot_control/libboot_control.cpp b/boot/1.1/default/boot_control/libboot_control.cpp
new file mode 100644
index 0000000..2c6ccaf
--- /dev/null
+++ b/boot/1.1/default/boot_control/libboot_control.cpp
@@ -0,0 +1,425 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <libboot_control/libboot_control.h>
+
+#include <endian.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <string>
+
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
+#include <android-base/unique_fd.h>
+#include <bootloader_message/bootloader_message.h>
+
+#include "private/boot_control_definition.h"
+
+namespace android {
+namespace bootable {
+
+using ::android::hardware::boot::V1_1::MergeStatus;
+
+// The number of boot attempts that should be made from a new slot before
+// rolling back to the previous slot.
+constexpr unsigned int kDefaultBootAttempts = 7;
+static_assert(kDefaultBootAttempts < 8, "tries_remaining field only has 3 bits");
+
+constexpr unsigned int kMaxNumSlots =
+    sizeof(bootloader_control::slot_info) / sizeof(bootloader_control::slot_info[0]);
+constexpr const char* kSlotSuffixes[kMaxNumSlots] = { "_a", "_b", "_c", "_d" };
+constexpr off_t kBootloaderControlOffset = offsetof(bootloader_message_ab, slot_suffix);
+
+static uint32_t CRC32(const uint8_t* buf, size_t size) {
+  static uint32_t crc_table[256];
+
+  // Compute the CRC-32 table only once.
+  if (!crc_table[1]) {
+    for (uint32_t i = 0; i < 256; ++i) {
+      uint32_t crc = i;
+      for (uint32_t j = 0; j < 8; ++j) {
+        uint32_t mask = -(crc & 1);
+        crc = (crc >> 1) ^ (0xEDB88320 & mask);
+      }
+      crc_table[i] = crc;
+    }
+  }
+
+  uint32_t ret = -1;
+  for (size_t i = 0; i < size; ++i) {
+    ret = (ret >> 8) ^ crc_table[(ret ^ buf[i]) & 0xFF];
+  }
+
+  return ~ret;
+}
+
+// Return the little-endian representation of the CRC-32 of the first fields
+// in |boot_ctrl| up to the crc32_le field.
+uint32_t BootloaderControlLECRC(const bootloader_control* boot_ctrl) {
+  return htole32(
+      CRC32(reinterpret_cast<const uint8_t*>(boot_ctrl), offsetof(bootloader_control, crc32_le)));
+}
+
+bool LoadBootloaderControl(const std::string& misc_device, bootloader_control* buffer) {
+  android::base::unique_fd fd(open(misc_device.c_str(), O_RDONLY));
+  if (fd.get() == -1) {
+    PLOG(ERROR) << "failed to open " << misc_device;
+    return false;
+  }
+  if (lseek(fd, kBootloaderControlOffset, SEEK_SET) != kBootloaderControlOffset) {
+    PLOG(ERROR) << "failed to lseek " << misc_device;
+    return false;
+  }
+  if (!android::base::ReadFully(fd.get(), buffer, sizeof(bootloader_control))) {
+    PLOG(ERROR) << "failed to read " << misc_device;
+    return false;
+  }
+  return true;
+}
+
+bool UpdateAndSaveBootloaderControl(const std::string& misc_device, bootloader_control* buffer) {
+  buffer->crc32_le = BootloaderControlLECRC(buffer);
+  android::base::unique_fd fd(open(misc_device.c_str(), O_WRONLY | O_SYNC));
+  if (fd.get() == -1) {
+    PLOG(ERROR) << "failed to open " << misc_device;
+    return false;
+  }
+  if (lseek(fd.get(), kBootloaderControlOffset, SEEK_SET) != kBootloaderControlOffset) {
+    PLOG(ERROR) << "failed to lseek " << misc_device;
+    return false;
+  }
+  if (!android::base::WriteFully(fd.get(), buffer, sizeof(bootloader_control))) {
+    PLOG(ERROR) << "failed to write " << misc_device;
+    return false;
+  }
+  return true;
+}
+
+void InitDefaultBootloaderControl(BootControl* control, bootloader_control* boot_ctrl) {
+  memset(boot_ctrl, 0, sizeof(*boot_ctrl));
+
+  unsigned int current_slot = control->GetCurrentSlot();
+  if (current_slot < kMaxNumSlots) {
+    strlcpy(boot_ctrl->slot_suffix, kSlotSuffixes[current_slot], sizeof(boot_ctrl->slot_suffix));
+  }
+  boot_ctrl->magic = BOOT_CTRL_MAGIC;
+  boot_ctrl->version = BOOT_CTRL_VERSION;
+
+  // Figure out the number of slots by checking if the partitions exist,
+  // otherwise assume the maximum supported by the header.
+  boot_ctrl->nb_slot = kMaxNumSlots;
+  std::string base_path = control->misc_device();
+  size_t last_path_sep = base_path.rfind('/');
+  if (last_path_sep != std::string::npos) {
+    // We test the existence of the "boot" partition on each possible slot,
+    // which is a partition required by Android Bootloader Requirements.
+    base_path = base_path.substr(0, last_path_sep + 1) + "boot";
+    int last_existing_slot = -1;
+    int first_missing_slot = -1;
+    for (unsigned int slot = 0; slot < kMaxNumSlots; ++slot) {
+      std::string partition_path = base_path + kSlotSuffixes[slot];
+      struct stat part_stat;
+      int err = stat(partition_path.c_str(), &part_stat);
+      if (!err) {
+        last_existing_slot = slot;
+        LOG(INFO) << "Found slot: " << kSlotSuffixes[slot];
+      } else if (err < 0 && errno == ENOENT && first_missing_slot == -1) {
+        first_missing_slot = slot;
+      }
+    }
+    // We only declare that we found the actual number of slots if we found all
+    // the boot partitions up to the number of slots, and no boot partition
+    // after that. Not finding any of the boot partitions implies a problem so
+    // we just leave the number of slots in the maximum value.
+    if ((last_existing_slot != -1 && last_existing_slot + 1 == first_missing_slot) ||
+        (first_missing_slot == -1 && last_existing_slot + 1 == kMaxNumSlots)) {
+      boot_ctrl->nb_slot = last_existing_slot + 1;
+      LOG(INFO) << "Found a system with " << last_existing_slot + 1 << " slots.";
+    }
+  }
+
+  for (unsigned int slot = 0; slot < kMaxNumSlots; ++slot) {
+    slot_metadata entry = {};
+
+    if (slot < boot_ctrl->nb_slot) {
+      entry.priority = 7;
+      entry.tries_remaining = kDefaultBootAttempts;
+      entry.successful_boot = 0;
+    } else {
+      entry.priority = 0;  // Unbootable
+    }
+
+    // When the boot_control stored on disk is invalid, we assume that the
+    // current slot is successful. The bootloader should repair this situation
+    // before booting and write a valid boot_control slot, so if we reach this
+    // stage it means that the misc partition was corrupted since boot.
+    if (current_slot == slot) {
+      entry.successful_boot = 1;
+    }
+
+    boot_ctrl->slot_info[slot] = entry;
+  }
+  boot_ctrl->recovery_tries_remaining = 0;
+
+  boot_ctrl->crc32_le = BootloaderControlLECRC(boot_ctrl);
+}
+
+// Return the index of the slot suffix passed or -1 if not a valid slot suffix.
+int SlotSuffixToIndex(const char* suffix) {
+  for (unsigned int slot = 0; slot < kMaxNumSlots; ++slot) {
+    if (!strcmp(kSlotSuffixes[slot], suffix)) return slot;
+  }
+  return -1;
+}
+
+// Initialize the boot_control_private struct with the information from
+// the bootloader_message buffer stored in |boot_ctrl|. Returns whether the
+// initialization succeeded.
+bool BootControl::Init() {
+  if (initialized_) return true;
+
+  // Initialize the current_slot from the read-only property. If the property
+  // was not set (from either the command line or the device tree), we can later
+  // initialize it from the bootloader_control struct.
+  std::string suffix_prop = android::base::GetProperty("ro.boot.slot_suffix", "");
+  if (suffix_prop.empty()) {
+    LOG(ERROR) << "Slot suffix property is not set";
+    return false;
+  }
+  current_slot_ = SlotSuffixToIndex(suffix_prop.c_str());
+
+  std::string err;
+  std::string device = get_bootloader_message_blk_device(&err);
+  if (device.empty()) {
+    LOG(ERROR) << "Could not find bootloader message block device: " << err;
+    return false;
+  }
+
+  bootloader_control boot_ctrl;
+  if (!LoadBootloaderControl(device.c_str(), &boot_ctrl)) {
+    LOG(ERROR) << "Failed to load bootloader control block";
+    return false;
+  }
+
+  // Note that since there isn't a module unload function this memory is leaked.
+  // We use `device` below sometimes, so it's not moved out of here.
+  misc_device_ = device;
+  initialized_ = true;
+
+  // Validate the loaded data, otherwise we will destroy it and re-initialize it
+  // with the current information.
+  uint32_t computed_crc32 = BootloaderControlLECRC(&boot_ctrl);
+  if (boot_ctrl.crc32_le != computed_crc32) {
+    LOG(WARNING) << "Invalid boot control found, expected CRC-32 0x" << std::hex << computed_crc32
+                 << " but found 0x" << std::hex << boot_ctrl.crc32_le << ". Re-initializing.";
+    InitDefaultBootloaderControl(this, &boot_ctrl);
+    UpdateAndSaveBootloaderControl(device.c_str(), &boot_ctrl);
+  }
+
+  if (!InitMiscVirtualAbMessageIfNeeded()) {
+    return false;
+  }
+
+  num_slots_ = boot_ctrl.nb_slot;
+  return true;
+}
+
+unsigned int BootControl::GetNumberSlots() {
+  return num_slots_;
+}
+
+unsigned int BootControl::GetCurrentSlot() {
+  return current_slot_;
+}
+
+bool BootControl::MarkBootSuccessful() {
+  bootloader_control bootctrl;
+  if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+  bootctrl.slot_info[current_slot_].successful_boot = 1;
+  // tries_remaining == 0 means that the slot is not bootable anymore, make
+  // sure we mark the current slot as bootable if it succeeds in the last
+  // attempt.
+  bootctrl.slot_info[current_slot_].tries_remaining = 1;
+  return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl);
+}
+
+bool BootControl::SetActiveBootSlot(unsigned int slot) {
+  if (slot >= kMaxNumSlots || slot >= num_slots_) {
+    // Invalid slot number.
+    return false;
+  }
+
+  bootloader_control bootctrl;
+  if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+  // Set every other slot with a lower priority than the new "active" slot.
+  const unsigned int kActivePriority = 15;
+  const unsigned int kActiveTries = 6;
+  for (unsigned int i = 0; i < num_slots_; ++i) {
+    if (i != slot) {
+      if (bootctrl.slot_info[i].priority >= kActivePriority)
+        bootctrl.slot_info[i].priority = kActivePriority - 1;
+    }
+  }
+
+  // Note that setting a slot as active doesn't change the successful bit.
+  // The successful bit will only be changed by setSlotAsUnbootable().
+  bootctrl.slot_info[slot].priority = kActivePriority;
+  bootctrl.slot_info[slot].tries_remaining = kActiveTries;
+
+  // Setting the current slot as active is a way to revert the operation that
+  // set *another* slot as active at the end of an updater. This is commonly
+  // used to cancel the pending update. We should only reset the verity_corrpted
+  // bit when attempting a new slot, otherwise the verity bit on the current
+  // slot would be flip.
+  if (slot != current_slot_) bootctrl.slot_info[slot].verity_corrupted = 0;
+
+  return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl);
+}
+
+bool BootControl::SetSlotAsUnbootable(unsigned int slot) {
+  if (slot >= kMaxNumSlots || slot >= num_slots_) {
+    // Invalid slot number.
+    return false;
+  }
+
+  bootloader_control bootctrl;
+  if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+  // The only way to mark a slot as unbootable, regardless of the priority is to
+  // set the tries_remaining to 0.
+  bootctrl.slot_info[slot].successful_boot = 0;
+  bootctrl.slot_info[slot].tries_remaining = 0;
+  return UpdateAndSaveBootloaderControl(misc_device_, &bootctrl);
+}
+
+bool BootControl::IsSlotBootable(unsigned int slot) {
+  if (slot >= kMaxNumSlots || slot >= num_slots_) {
+    // Invalid slot number.
+    return false;
+  }
+
+  bootloader_control bootctrl;
+  if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+  return bootctrl.slot_info[slot].tries_remaining != 0;
+}
+
+bool BootControl::IsSlotMarkedSuccessful(unsigned int slot) {
+  if (slot >= kMaxNumSlots || slot >= num_slots_) {
+    // Invalid slot number.
+    return false;
+  }
+
+  bootloader_control bootctrl;
+  if (!LoadBootloaderControl(misc_device_, &bootctrl)) return false;
+
+  return bootctrl.slot_info[slot].successful_boot && bootctrl.slot_info[slot].tries_remaining;
+}
+
+bool BootControl::IsValidSlot(unsigned int slot) {
+  return slot < kMaxNumSlots && slot < num_slots_;
+}
+
+bool BootControl::SetSnapshotMergeStatus(MergeStatus status) {
+  return SetMiscVirtualAbMergeStatus(current_slot_, status);
+}
+
+MergeStatus BootControl::GetSnapshotMergeStatus() {
+  MergeStatus status;
+  if (!GetMiscVirtualAbMergeStatus(current_slot_, &status)) {
+    return MergeStatus::UNKNOWN;
+  }
+  return status;
+}
+
+const char* BootControl::GetSuffix(unsigned int slot) {
+  if (slot >= kMaxNumSlots || slot >= num_slots_) {
+    return nullptr;
+  }
+  return kSlotSuffixes[slot];
+}
+
+bool InitMiscVirtualAbMessageIfNeeded() {
+  std::string err;
+  misc_virtual_ab_message message;
+  if (!ReadMiscVirtualAbMessage(&message, &err)) {
+    LOG(ERROR) << "Could not read merge status: " << err;
+    return false;
+  }
+
+  if (message.version == MISC_VIRTUAL_AB_MESSAGE_VERSION &&
+      message.magic == MISC_VIRTUAL_AB_MAGIC_HEADER) {
+    // Already initialized.
+    return true;
+  }
+
+  message = {};
+  message.version = MISC_VIRTUAL_AB_MESSAGE_VERSION;
+  message.magic = MISC_VIRTUAL_AB_MAGIC_HEADER;
+  if (!WriteMiscVirtualAbMessage(message, &err)) {
+    LOG(ERROR) << "Could not write merge status: " << err;
+    return false;
+  }
+  return true;
+}
+
+bool SetMiscVirtualAbMergeStatus(unsigned int current_slot,
+                                 android::hardware::boot::V1_1::MergeStatus status) {
+  std::string err;
+  misc_virtual_ab_message message;
+
+  if (!ReadMiscVirtualAbMessage(&message, &err)) {
+    LOG(ERROR) << "Could not read merge status: " << err;
+    return false;
+  }
+
+  message.merge_status = static_cast<uint8_t>(status);
+  message.source_slot = current_slot;
+  if (!WriteMiscVirtualAbMessage(message, &err)) {
+    LOG(ERROR) << "Could not write merge status: " << err;
+    return false;
+  }
+  return true;
+}
+
+bool GetMiscVirtualAbMergeStatus(unsigned int current_slot,
+                                 android::hardware::boot::V1_1::MergeStatus* status) {
+  std::string err;
+  misc_virtual_ab_message message;
+
+  if (!ReadMiscVirtualAbMessage(&message, &err)) {
+    LOG(ERROR) << "Could not read merge status: " << err;
+    return false;
+  }
+
+  // If the slot reverted after having created a snapshot, then the snapshot will
+  // be thrown away at boot. Thus we don't count this as being in a snapshotted
+  // state.
+  *status = static_cast<MergeStatus>(message.merge_status);
+  if (*status == MergeStatus::SNAPSHOTTED && current_slot == message.source_slot) {
+    *status = MergeStatus::NONE;
+  }
+  return true;
+}
+
+}  // namespace bootable
+}  // namespace android
diff --git a/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
index f6cd6ae..8ab2b43 100644
--- a/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
+++ b/broadcastradio/common/vts/utils/include/broadcastradio-vts-utils/mock-timeout.h
@@ -82,33 +82,44 @@
     };                                                                \
     return EGMockFlippedComma_<decltype(invokeMock())>(invokeMock, notify);
 
+// We define this as a variadic macro in case F contains unprotected
+// commas (the same reason that we use variadic macros in other places
+// in this file).
+#define EGMOCK_RESULT_(tn, ...) \
+    tn ::testing::internal::Function<__VA_ARGS__>::Result
+
+// The type of argument N of the given function type.
+// INTERNAL IMPLEMENTATION - DON'T USE IN USER CODE!!!
+#define EGMOCK_ARG_(tn, N, ...) \
+    tn ::testing::internal::Function<__VA_ARGS__>::template Arg<N-1>::type
+
 /**
  * Gmock MOCK_METHOD0 timeout-capable extension.
  */
 #define MOCK_TIMEOUT_METHOD0(Method, ...)       \
     MOCK_METHOD0(egmock_##Method, __VA_ARGS__); \
     EGMOCK_TIMEOUT_METHOD_DEF_(Method);         \
-    virtual GMOCK_RESULT_(, __VA_ARGS__) Method() { EGMOCK_TIMEOUT_METHOD_BODY_(Method); }
+    virtual EGMOCK_RESULT_(, __VA_ARGS__) Method() { EGMOCK_TIMEOUT_METHOD_BODY_(Method); }
 
 /**
  * Gmock MOCK_METHOD1 timeout-capable extension.
  */
-#define MOCK_TIMEOUT_METHOD1(Method, ...)                                                 \
-    MOCK_METHOD1(egmock_##Method, __VA_ARGS__);                                           \
-    EGMOCK_TIMEOUT_METHOD_DEF_(Method);                                                   \
-    virtual GMOCK_RESULT_(, __VA_ARGS__) Method(GMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1) { \
-        EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1);                                   \
+#define MOCK_TIMEOUT_METHOD1(Method, ...)                                                   \
+    MOCK_METHOD1(egmock_##Method, __VA_ARGS__);                                             \
+    EGMOCK_TIMEOUT_METHOD_DEF_(Method);                                                     \
+    virtual EGMOCK_RESULT_(, __VA_ARGS__) Method(EGMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1) { \
+        EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1);                                     \
     }
 
 /**
  * Gmock MOCK_METHOD2 timeout-capable extension.
  */
-#define MOCK_TIMEOUT_METHOD2(Method, ...)                                                        \
-    MOCK_METHOD2(egmock_##Method, __VA_ARGS__);                                                  \
-    EGMOCK_TIMEOUT_METHOD_DEF_(Method);                                                          \
-    virtual GMOCK_RESULT_(, __VA_ARGS__)                                                         \
-        Method(GMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1, GMOCK_ARG_(, 2, __VA_ARGS__) egmock_a2) { \
-        EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1, egmock_a2);                               \
+#define MOCK_TIMEOUT_METHOD2(Method, ...)                                                          \
+    MOCK_METHOD2(egmock_##Method, __VA_ARGS__);                                                    \
+    EGMOCK_TIMEOUT_METHOD_DEF_(Method);                                                            \
+    virtual EGMOCK_RESULT_(, __VA_ARGS__)                                                          \
+        Method(EGMOCK_ARG_(, 1, __VA_ARGS__) egmock_a1, EGMOCK_ARG_(, 2, __VA_ARGS__) egmock_a2) { \
+        EGMOCK_TIMEOUT_METHOD_BODY_(Method, egmock_a1, egmock_a2);                                 \
     }
 
 /**
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index bb057fb..21459b7 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -276,6 +276,13 @@
             <instance>default</instance>
         </interface>
     </hal>
+    <hal format="aidl" optional="true">
+        <name>android.hardware.light</name>
+        <interface>
+            <name>ILights</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.media.c2</name>
         <version>1.0</version>
@@ -329,7 +336,7 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="aidl" optional="true">
+    <hal format="aidl" optional="false">
         <name>android.hardware.power</name>
         <interface>
             <name>IPower</name>
@@ -364,7 +371,10 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.radio.config</name>
-        <version>1.3</version>
+        <!--
+        See compatibility_matrix.4.xml on versioning of radio config HAL.
+        -->
+        <version>1.1</version>
         <interface>
             <name>IRadioConfig</name>
             <instance>default</instance>
diff --git a/confirmationui/1.0/vts/functional/Android.bp b/confirmationui/1.0/vts/functional/Android.bp
index fd088cd..c8b522c 100644
--- a/confirmationui/1.0/vts/functional/Android.bp
+++ b/confirmationui/1.0/vts/functional/Android.bp
@@ -27,5 +27,5 @@
         "libcn-cbor",
         "android.hardware.confirmationui-support-lib",
     ],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp b/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp
index 278d1f4..d953ab0 100644
--- a/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp
+++ b/confirmationui/1.0/vts/functional/VtsHalConfirmationUIV1_0TargetTest.cpp
@@ -26,8 +26,12 @@
 #include <android/hardware/confirmationui/1.0/types.h>
 #include <android/hardware/confirmationui/support/confirmationui_utils.h>
 
+#include <gtest/gtest.h>
+
 #include <VtsHalHidlTargetCallbackBase.h>
-#include <VtsHalHidlTargetTestBase.h>
+
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
 
 #include <openssl/hmac.h>
 #include <openssl/sha.h>
@@ -199,43 +203,18 @@
     }
 };
 
-class ConfirmationUIHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static ConfirmationUIHidlEnvironment* Instance() {
-        static ConfirmationUIHidlEnvironment* instance = new ConfirmationUIHidlEnvironment;
-        return instance;
-    }
-
-    void registerTestServices() override { registerTestService<IConfirmationUI>(); }
-
-   private:
-    ConfirmationUIHidlEnvironment(){};
-
-    GTEST_DISALLOW_COPY_AND_ASSIGN_(ConfirmationUIHidlEnvironment);
-};
-
-class ConfirmationUIHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-   public:
-    void TearDown() override { confirmator().abort(); }
-
-    static void SetUpTestCase() {
-        string service_name =
-            ConfirmationUIHidlEnvironment::Instance()->getServiceName<IConfirmationUI>();
-        confirmator_ = IConfirmationUI::getService(service_name);
+class ConfirmationUIHidlTest : public ::testing::TestWithParam<std::string> {
+  public:
+    void TearDown() override { confirmator_->abort(); }
+    void SetUp() override {
+        confirmator_ = IConfirmationUI::getService(GetParam());
         ASSERT_NE(nullptr, confirmator_.get());
     }
 
-    static void TearDownTestCase() { confirmator_.clear(); }
-
-    static IConfirmationUI& confirmator() { return *confirmator_; }
-
-   private:
-    static sp<IConfirmationUI> confirmator_;
+  protected:
+    sp<IConfirmationUI> confirmator_;
 };
 
-sp<IConfirmationUI> ConfirmationUIHidlTest::confirmator_;
-
 #define ASSERT_HAL_CALL(expected, call)                               \
     {                                                                 \
         auto result = call;                                           \
@@ -250,17 +229,17 @@
 typedef std::unique_ptr<cn_cbor, CnCborDeleter> CnCborPtr;
 
 // Simulates the User taping Ok
-TEST_F(ConfirmationUIHidlTest, UserOkTest) {
+TEST_P(ConfirmationUIHidlTest, UserOkTest) {
     static constexpr char test_prompt[] = "Me first, gimme gimme!";
     static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
     sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
     ASSERT_HAL_CALL(ResponseCode::OK,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 
-    ASSERT_HAL_CALL(ResponseCode::OK, confirmator().deliverSecureInputEvent(
-                                          makeTestToken(TestModeCommands::OK_EVENT)));
+    ASSERT_HAL_CALL(ResponseCode::OK, confirmator_->deliverSecureInputEvent(
+                                              makeTestToken(TestModeCommands::OK_EVENT)));
 
     auto result = conf_cb->WaitForCallback();
     ASSERT_EQ(ResponseCode::OK, result.args->error_);
@@ -294,40 +273,40 @@
 }
 
 // Initiates a confirmation prompt with a message that is too long
-TEST_F(ConfirmationUIHidlTest, MessageTooLongTest) {
+TEST_P(ConfirmationUIHidlTest, MessageTooLongTest) {
     static constexpr uint8_t test_extra[static_cast<uint32_t>(MessageSize::MAX)] = {};
     static constexpr char test_prompt[] = "D\'oh!";
     sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
     ASSERT_HAL_CALL(ResponseCode::UIErrorMessageTooLong,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 }
 
 // If the message gets very long some HAL implementations might fail even before the message
 // reaches the trusted app implementation. But the HAL must still diagnose the correct error.
-TEST_F(ConfirmationUIHidlTest, MessageWayTooLongTest) {
+TEST_P(ConfirmationUIHidlTest, MessageWayTooLongTest) {
     static constexpr uint8_t test_extra[static_cast<uint32_t>(MessageSize::MAX) * 10] = {};
     static constexpr char test_prompt[] = "D\'oh!";
     sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
     ASSERT_HAL_CALL(ResponseCode::UIErrorMessageTooLong,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 }
 
 // Simulates the User tapping the Cancel
-TEST_F(ConfirmationUIHidlTest, UserCancelTest) {
+TEST_P(ConfirmationUIHidlTest, UserCancelTest) {
     static constexpr char test_prompt[] = "Me first, gimme gimme!";
     static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
     sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
     ASSERT_HAL_CALL(ResponseCode::OK,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 
-    ASSERT_HAL_CALL(ResponseCode::OK, confirmator().deliverSecureInputEvent(
-                                          makeTestToken(TestModeCommands::CANCEL_EVENT)));
+    ASSERT_HAL_CALL(ResponseCode::OK, confirmator_->deliverSecureInputEvent(
+                                              makeTestToken(TestModeCommands::CANCEL_EVENT)));
 
     auto result = conf_cb->WaitForCallback();
     ASSERT_EQ(ResponseCode::Canceled, result.args->error_);
@@ -336,17 +315,103 @@
     ASSERT_EQ(0U, result.args->formattedMessage_.size());
 }
 
-// Simulates the framework candelling an ongoing prompt
-TEST_F(ConfirmationUIHidlTest, AbortTest) {
+// Simulates the framework cancelling an ongoing prompt
+TEST_P(ConfirmationUIHidlTest, AbortTest) {
     static constexpr char test_prompt[] = "Me first, gimme gimme!";
     static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
     sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
     ASSERT_HAL_CALL(ResponseCode::OK,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 
-    confirmator().abort();
+    confirmator_->abort();
+
+    auto result = conf_cb->WaitForCallback();
+    ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
+    ASSERT_EQ(0U, result.args->confirmationToken_.size());
+    ASSERT_EQ(0U, result.args->formattedMessage_.size());
+}
+
+// Tests if the confirmation dialog can successfully render 100 'W' characters as required by
+// the design guidelines.
+TEST_P(ConfirmationUIHidlTest, PortableMessageTest1) {
+    static constexpr char test_prompt[] =
+            "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
+            "WWWWWWWWWWWWWW";
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
+    hidl_string prompt_text(test_prompt);
+    hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
+    ASSERT_HAL_CALL(ResponseCode::OK,
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+
+    confirmator_->abort();
+
+    auto result = conf_cb->WaitForCallback();
+    ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
+    ASSERT_EQ(0U, result.args->confirmationToken_.size());
+    ASSERT_EQ(0U, result.args->formattedMessage_.size());
+}
+
+// Tests if the confirmation dialog can successfully render 100 'W' characters as required by
+// the design guidelines in magnified mode.
+TEST_P(ConfirmationUIHidlTest, PortableMessageTest1Magnified) {
+    static constexpr char test_prompt[] =
+            "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
+            "WWWWWWWWWWWWWW";
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
+    hidl_string prompt_text(test_prompt);
+    hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
+    ASSERT_HAL_CALL(ResponseCode::OK,
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
+                                                         {UIOption::AccessibilityMagnified}));
+
+    confirmator_->abort();
+
+    auto result = conf_cb->WaitForCallback();
+    ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
+    ASSERT_EQ(0U, result.args->confirmationToken_.size());
+    ASSERT_EQ(0U, result.args->formattedMessage_.size());
+}
+
+// Tests if the confirmation dialog can successfully render 8 groups of 12 'W' characters as
+// required by the design guidelines.
+TEST_P(ConfirmationUIHidlTest, PortableMessageTest2) {
+    static constexpr char test_prompt[] =
+            "WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW "
+            "WWWWWWWWWWWW WWWWWWWWWWWW";
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
+    hidl_string prompt_text(test_prompt);
+    hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
+    ASSERT_HAL_CALL(ResponseCode::OK,
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+
+    confirmator_->abort();
+
+    auto result = conf_cb->WaitForCallback();
+    ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
+    ASSERT_EQ(0U, result.args->confirmationToken_.size());
+    ASSERT_EQ(0U, result.args->formattedMessage_.size());
+}
+
+// Tests if the confirmation dialog can successfully render 8 groups of 12 'W' characters as
+// required by the design guidelines in magnified mode.
+TEST_P(ConfirmationUIHidlTest, PortableMessageTest2Magnified) {
+    static constexpr char test_prompt[] =
+            "WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW "
+            "WWWWWWWWWWWW WWWWWWWWWWWW";
+    static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+    sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
+    hidl_string prompt_text(test_prompt);
+    hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
+    ASSERT_HAL_CALL(ResponseCode::OK,
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
+                                                         {UIOption::AccessibilityMagnified}));
+
+    confirmator_->abort();
 
     auto result = conf_cb->WaitForCallback();
     ASSERT_EQ(ResponseCode::Aborted, result.args->error_);
@@ -356,19 +421,19 @@
 
 // Passing malformed UTF-8 to the confirmation UI
 // This test passes a string that ends in the middle of a multibyte character
-TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test1) {
+TEST_P(ConfirmationUIHidlTest, MalformedUTF8Test1) {
     static constexpr char test_prompt[] = {char(0xc0), 0};
     static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
     sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
     ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 }
 
 // Passing malformed UTF-8 to the confirmation UI
 // This test passes a string with a 5-byte character.
-TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test2) {
+TEST_P(ConfirmationUIHidlTest, MalformedUTF8Test2) {
     static constexpr char test_prompt[] = {char(0xf8), char(0x82), char(0x82),
                                            char(0x82), char(0x82), 0};
     static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
@@ -376,19 +441,19 @@
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
     ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 }
 
 // Passing malformed UTF-8 to the confirmation UI
 // This test passes a string with a 2-byte character followed by a stray non UTF-8 character.
-TEST_F(ConfirmationUIHidlTest, MalformedUTF8Test3) {
+TEST_P(ConfirmationUIHidlTest, MalformedUTF8Test3) {
     static constexpr char test_prompt[] = {char(0xc0), char(0x82), char(0x83), 0};
     static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
     sp<ConfirmationTestCallback> conf_cb = new ConfirmationTestCallback;
     hidl_string prompt_text(test_prompt);
     hidl_vec<uint8_t> extra(test_extra, test_extra + 3);
     ASSERT_HAL_CALL(ResponseCode::UIErrorMalformedUTF8Encoding,
-                    confirmator().promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
+                    confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}));
 }
 
 // Test the implementation of HMAC SHA 256 against a golden blob.
@@ -408,16 +473,13 @@
     ASSERT_EQ(expected, result.value());
 }
 
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, ConfirmationUIHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IConfirmationUI::descriptor)),
+        android::hardware::PrintInstanceNameToString);
+
 }  // namespace test
 }  // namespace V1_0
 }  // namespace confirmationui
 }  // namespace hardware
 }  // namespace android
-
-int main(int argc, char** argv) {
-    ::testing::InitGoogleTest(&argc, argv);
-    std::vector<std::string> positional_args;
-    int status = RUN_ALL_TESTS();
-    ALOGI("Test result = %d", status);
-    return status;
-}
diff --git a/current.txt b/current.txt
index fa27765..08ee89b 100644
--- a/current.txt
+++ b/current.txt
@@ -578,7 +578,7 @@
 5f6d3097ba84cb63c430787123f4de1b31c11f90b531b98eae9a8623a5ae962a android.hardware.neuralnetworks@1.1::types
 fb382e986c10b8fbb797a8546e8f9ea6d1107bfe6f3fb7e57f6bbbf1f807a906 android.hardware.neuralnetworks@1.2::IDevice
 40e71cd693de5b832325c5d8f081f2ff20a7ba2b89d401cee5b4b3eb0e241681 android.hardware.neuralnetworks@1.2::IPreparedModel
-7f7ef383268c95a1b8fe4e55c662bc806bb0ac11a154f6b049a113a44b0f024f android.hardware.neuralnetworks@1.2::types
+00649d29680f2c47edf60000c3ae7ae906ba638f0616947147e3676a83cf36fa android.hardware.neuralnetworks@1.2::types
 a785a57447a81e9c130eef6904c3a5c256076c6a04588c40620ebd6fa2660d77 android.hardware.radio@1.2::types
 1a6e2bd289f22931c526b21916910f1d4c436b7acb9556e4243de4ce8e6cc2e4 android.hardware.soundtrigger@2.0::ISoundTriggerHwCallback
 fd65298e1e09e0e3c781ab18305920d757dbe55a3b459ce17814ec5cf6dfee99 android.hardware.wifi@1.0::IWifiP2pIface
@@ -612,36 +612,32 @@
 40ab2c6866c18d32baf6e49e3053949e79601f56963a791e93e68b9ee18f718d android.hardware.bluetooth@1.1::IBluetoothHciCallbacks
 07d0a252b2d8fa35887908a996ba395cf392968395fc30afab791f46e0c22a52 android.hardware.boot@1.1::IBootControl
 74049a402be913963edfdd80828a53736570e9d8124a1bf18166b6ed46a6b0ab android.hardware.boot@1.1::types
-881aa8720fb1d69aa9843bfab69d810ab7654a61d2f5ab5e2626cbf240f24eaf android.hardware.dumpstate@1.1::types
-13b33f623521ded51a6c0f7ea5b77e97066d0aa1e38a83c2873f08ad67294f89 android.hardware.dumpstate@1.1::IDumpstateDevice
+d9df99be0f59d8f33a9699fe316c67bfd11818aa69440bb1123ba43e717cea85 android.hardware.dumpstate@1.1::types
+186bc152ae189ab48f3a761a44ddf5edd0d483073c5b6ca1f802f8b50488b754 android.hardware.dumpstate@1.1::IDumpstateDevice
 ce8dbe76eb9ee94b46ef98f725be992e760a5751073d4f4912484026541371f3 android.hardware.health@2.1::IHealth
 26f04510a0b57aba5167c5c0a7c2f077c2acbb98b81902a072517829fd9fd67f android.hardware.health@2.1::IHealthInfoCallback
-db47f4ceceb1f06c656f39caa70c557b0f8471ef59fd58611bea667ffca20101 android.hardware.health@2.1::types
+e2f8bc1868fd4a3fd587c172773ea5a8c2f5a3deaf7958394102ca455252b255 android.hardware.health@2.1::types
 0589e410f519e36514e7ece18f283f022df0f70efd2c12821d822f67f74aba98 android.hardware.identity@1.0::types
 bbeee9604128ede83ee755b67e73b5ad29e6e1dbac9ec41fea6ffe2745b0c50a android.hardware.identity@1.0::IIdentityCredential
 96ce8aad80f4c476f25261f790d357c117e79e18474c7dadd850dac704bbe65e android.hardware.identity@1.0::IIdentityCredentialStore
-6e1e28a96c90ba78d47257faea3f3bb4e6360affbbfa5822f0dc31211f9266ff android.hardware.identity@1.0::IWritableIdentityCredential
+8da9c938e58f7d636ddd2f92c646f99d9a9e79612e6441b6380ab12744251873 android.hardware.identity@1.0::IWritableIdentityCredential
 27ae3724053940462114228872b3ffaf0b8e6177d5ba97f5a76339d12b8a99dd android.hardware.keymaster@4.1::IKeymasterDevice
 adb0efdf1462e9b2e742c0dcadd598666aac551f178be06e755bfcdf5797abd0 android.hardware.keymaster@4.1::IOperation
-ac429fca0da4ce91218768ec31b64ded88251f8a26d8c4f27c06abdc5b1926d9 android.hardware.keymaster@4.1::types
+ddcf89cd8ee2df0d32aee55050826446fb64f7aafde0a7cd946c64f61b1a364c android.hardware.keymaster@4.1::types
 65c16331e57f6dd68b3971f06f78fe9e3209afb60630c31705aa355f9a52bf0d android.hardware.neuralnetworks@1.3::IBuffer
-d1f382d14e1384b907d5bb5780df7f01934650d556fedbed2f15a90773c657d6 android.hardware.neuralnetworks@1.3::IDevice
+9db064ee44268a876be0367ff771e618362d39ec603b6ecab17e1575725fcd87 android.hardware.neuralnetworks@1.3::IDevice
 4167dc3ad35e9cd0d2057d4868c7675ae2c3c9d05bbd614c1f5dccfa5fd68797 android.hardware.neuralnetworks@1.3::IExecutionCallback
 2fa3679ad7c94b5e88724adcd560c561041068a4ca565c63830e68101988746a android.hardware.neuralnetworks@1.3::IFencedExecutionCallback
-237b23b126a66f3432658020fed78cdd06ba6297459436fe6bae0ba753370833 android.hardware.neuralnetworks@1.3::IPreparedModel
+43088ffc71945b463a7279262cfe2e290f6ed2f15d3fd6032798a3be299fb08f android.hardware.neuralnetworks@1.3::IPreparedModel
 0439a1fbbec7f16e5e4c653d85ac685d51bfafbae15b8f8cca530acdd7d6a8ce android.hardware.neuralnetworks@1.3::IPreparedModelCallback
-3646950b10f7cacdafca13609b0e18496cea942f3bdfe920494661856eff48bb android.hardware.neuralnetworks@1.3::types
+dd39887aa4fb60ce60ea9cc043edeadbbae6e922d09d3946311b0b410024ae14 android.hardware.neuralnetworks@1.3::types
 3e01d4446cd69fd1c48f8572efd97487bc179564b32bd795800b97bbe10be37b android.hardware.wifi@1.4::IWifi
 a64467bae843569f0d465c5be7f0c7a5b987985b55a3ef4794dd5afc68538650 android.hardware.wifi.supplicant@1.3::ISupplicant
 44445b8a03d7b9e68b2fbd954672c18a8fce9e32851b0692f4f4ab3407f86ecb android.hardware.wifi.supplicant@1.3::ISupplicantStaIface
 619fc9839ec6e369cfa9b28e3e9412e6885720ff8f9b5750c1b6ffb905120391 android.hardware.wifi.supplicant@1.3::ISupplicantStaIfaceCallback
 c9273429fcf98d797d3bb07fdba6f1be95bf960f9255cde169fd1ca4db85f856 android.hardware.wifi.supplicant@1.3::ISupplicantStaNetwork
 9b0a3ab6f4f74b971ed094426d8a443e29b512ff03e1ab50c07156396cdb2483 android.hardware.wifi.supplicant@1.3::types
-50e22cd55ad5499e68e81541bbc67bd10e59c1b9f3ff8cc7ba70dcb0d2918381 android.hardware.radio@1.5::types
-8cc3306e8cd755d04521d1611b217b9d13a2a76d2af57cbea8f875333b3363f7 android.hardware.radio@1.5::IRadio
+85af67af743b8cebb65023f196ee3df0e57b88c84d048f40439e98f845bab3d6 android.hardware.radio@1.5::types
+e5947273509cd23b432c1a0781245a1e5a1dedca77f41db6dbcc02c0d7a7e40a android.hardware.radio@1.5::IRadio
 e96ae1c3a9c0689002ec2318e9c587f4f607c16a75a3cd38788b77eb91072021 android.hardware.radio@1.5::IRadioIndication
-7b77721a7716e163f5cc5f2830ed5616b953fcf0e5406f69de0fde5ce95e4184 android.hardware.radio@1.5::IRadioResponse
-2fd107f3de1b7e36825e241a88dfae8edf3a77c166cb746f00ddf6440ab78db1 android.hardware.radio.config@1.3::types
-a2977755bc5f1ef47f04b7f2400632efda6218e1515dba847da487145cfabc4f android.hardware.radio.config@1.3::IRadioConfig
-742360c775313438b0f82256eac62fb5bbc76a6ae6f388573f3aa142fb2c1eea android.hardware.radio.config@1.3::IRadioConfigIndication
-0006ab8e8b0910cbd3bbb08d5f17d5fac7d65a2bdad5f2334e4851db9d1e6fa8 android.hardware.radio.config@1.3::IRadioConfigResponse
\ No newline at end of file
+6759e59cef81b5e15137bf99a4cd14236ce0c2974dd307ada265b67e819b9060 android.hardware.radio@1.5::IRadioResponse
diff --git a/drm/1.0/vts/functional/Android.bp b/drm/1.0/vts/functional/Android.bp
index 235bfb4..e4d3393 100644
--- a/drm/1.0/vts/functional/Android.bp
+++ b/drm/1.0/vts/functional/Android.bp
@@ -24,7 +24,7 @@
         "vendor_modules.cpp",
     ],
     static_libs: [
-       "android.hardware.drm@1.0-helper",
+        "android.hardware.drm@1.0-helper",
     ],
     export_include_dirs: ["include"],
 }
@@ -43,12 +43,12 @@
         "android.hardware.drm@1.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
+        "libcrypto",
         "libhidlmemory",
         "libnativehelper",
     ],
     static_libs: [
         "android.hardware.drm@1.0-helper",
-        "libcrypto_static",
         "libdrmvtshelper",
     ],
     export_shared_lib_headers: [
@@ -76,14 +76,28 @@
         "android.hardware.drm@1.0",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
+        "libcrypto",
         "libhidlmemory",
         "libnativehelper",
     ],
     static_libs: [
         "android.hardware.drm@1.0-helper",
-        "libcrypto_static",
         "libdrmvtshelper",
     ],
+    arch: {
+        arm: {
+            data: [":libvtswidevine-arm-prebuilts"],
+        },
+        arm64: {
+            data: [":libvtswidevine-arm64-prebuilts"],
+        },
+        x86: {
+            data: [":libvtswidevine-x86-prebuilts"],
+        },
+        x86_64: {
+            data: [":libvtswidevine-x86_64-prebuilts"],
+        },
+    },
     test_suites: [
         "general-tests",
         "vts-core",
diff --git a/drm/1.0/vts/functional/AndroidTest.xml b/drm/1.0/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..92ea7e4
--- /dev/null
+++ b/drm/1.0/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalDrmV1_0TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push-file" key="VtsHalDrmV1_0TargetTest" value="/data/local/tmp/VtsHalDrmV1_0TargetTest" />
+        <option name="push-file" key="libvtswidevine64.so" value="/data/local/tmp/64/lib/libvtswidevine.so" />
+        <option name="push-file" key="libvtswidevine32.so" value="/data/local/tmp/32/lib/libvtswidevine.so" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalDrmV1_0TargetTest" />
+    </test>
+</configuration>
diff --git a/drm/1.1/vts/functional/Android.bp b/drm/1.1/vts/functional/Android.bp
index e08d760..c31aee0 100644
--- a/drm/1.1/vts/functional/Android.bp
+++ b/drm/1.1/vts/functional/Android.bp
@@ -60,11 +60,25 @@
         "drm_hal_test_main.cpp",
     ],
     whole_static_libs: [
-        "android.hardware.drm@1.1-vts"
+        "android.hardware.drm@1.1-vts",
     ],
     shared_libs: [
         "android.hardware.drm@1.1",
     ],
+    arch: {
+        arm: {
+            data: [":libvtswidevine-arm-prebuilts"],
+        },
+        arm64: {
+            data: [":libvtswidevine-arm64-prebuilts"],
+        },
+        x86: {
+            data: [":libvtswidevine-x86-prebuilts"],
+        },
+        x86_64: {
+            data: [":libvtswidevine-x86_64-prebuilts"],
+        },
+    },
     test_suites: [
         "general-tests",
         "vts-core",
diff --git a/drm/1.1/vts/functional/AndroidTest.xml b/drm/1.1/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..65c45ac
--- /dev/null
+++ b/drm/1.1/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalDrmV1_1TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push-file" key="VtsHalDrmV1_1TargetTest" value="/data/local/tmp/VtsHalDrmV1_1TargetTest" />
+        <option name="push-file" key="libvtswidevine64.so" value="/data/local/tmp/64/lib/libvtswidevine.so" />
+        <option name="push-file" key="libvtswidevine32.so" value="/data/local/tmp/32/lib/libvtswidevine.so" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalDrmV1_1TargetTest" />
+    </test>
+</configuration>
diff --git a/drm/1.2/vts/functional/Android.bp b/drm/1.2/vts/functional/Android.bp
index ecc7d6c..793ef80 100644
--- a/drm/1.2/vts/functional/Android.bp
+++ b/drm/1.2/vts/functional/Android.bp
@@ -31,12 +31,12 @@
         "android.hardware.drm@1.2",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
+        "libcrypto",
         "libhidlmemory",
         "libnativehelper",
     ],
     static_libs: [
         "android.hardware.drm@1.0-helper",
-        "libcrypto_static",
         "libdrmvtshelper",
     ],
     export_shared_lib_headers: [
@@ -63,13 +63,27 @@
         "android.hardware.drm@1.0",
         "android.hardware.drm@1.2",
         "android.hidl.allocator@1.0",
+        "libcrypto",
         "libhidlmemory",
     ],
     static_libs: [
         "android.hardware.drm@1.0-helper",
-        "libcrypto_static",
         "libdrmvtshelper",
     ],
+    arch: {
+        arm: {
+            data: [":libvtswidevine-arm-prebuilts"],
+        },
+        arm64: {
+            data: [":libvtswidevine-arm64-prebuilts"],
+        },
+        x86: {
+            data: [":libvtswidevine-x86-prebuilts"],
+        },
+        x86_64: {
+            data: [":libvtswidevine-x86_64-prebuilts"],
+        },
+    },
     test_suites: [
         "general-tests",
         "vts-core",
diff --git a/drm/1.2/vts/functional/AndroidTest.xml b/drm/1.2/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..5da38ae
--- /dev/null
+++ b/drm/1.2/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalDrmV1_2TargetTest.">
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="apct-native" />
+
+    <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer"/>
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push-file" key="VtsHalDrmV1_2TargetTest" value="/data/local/tmp/VtsHalDrmV1_2TargetTest" />
+        <option name="push-file" key="libvtswidevine64.so" value="/data/local/tmp/64/lib/libvtswidevine.so" />
+        <option name="push-file" key="libvtswidevine32.so" value="/data/local/tmp/32/lib/libvtswidevine.so" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalDrmV1_2TargetTest" />
+    </test>
+</configuration>
diff --git a/dumpstate/1.1/IDumpstateDevice.hal b/dumpstate/1.1/IDumpstateDevice.hal
index 24831b3..183404d 100644
--- a/dumpstate/1.1/IDumpstateDevice.hal
+++ b/dumpstate/1.1/IDumpstateDevice.hal
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.hardware.dumpstate@1.1;
 
 import @1.0::IDumpstateDevice;
@@ -28,17 +29,23 @@
      * The 1.0 version of #dumpstateBoard(handle) should just delegate to this new method and pass
      * DumpstateMode::DEFAULT and a timeout of 30,000ms (30 seconds).
      *
+     * This method may still be called by the dumpstate routine even if getVerboseLoggingEnabled
+     * returns false. In this case, it may include essential information but must not include
+     * information that identifies the user.
+     *
      * @param h A native handle with one or two valid file descriptors. The first FD is for text
      *     output, the second (if present) is for binary output.
      * @param mode A mode value to restrict dumped content.
      * @param timeoutMillis An approximate "budget" for how much time this call has been allotted.
      *     If execution runs longer than this, the IDumpstateDevice service may be killed and only
      *     partial information will be included in the report.
+     * @return status A DumpstateStatus value indicating the final result.
      */
-    dumpstateBoard_1_1(handle h, DumpstateMode mode, uint64_t timeoutMillis);
+    dumpstateBoard_1_1(handle h, DumpstateMode mode, uint64_t timeoutMillis)
+        generates (DumpstateStatus status);
 
     /**
-     * Turns device vendor logging on or off.
+     * Turns verbose device vendor logging on or off.
      *
      * The setting should be persistent across reboots. Underlying implementations may need to start
      * vendor logging daemons, set system properties, or change logging masks, for example. Given
@@ -46,8 +53,21 @@
      * memory/storage/battery impacts, calling this method on a user build should only be done after
      * user consent has been obtained, e.g. from a toggle in developer settings.
      *
-     * @param enable Whether to enable or disable device vendor logging.
-     * @return success Whether or not the change took effect.
+     * Even if verbose logging has been disabled, dumpstateBoard may still be called by the
+     * dumpstate routine, and essential information that does not identify the user may be included.
+     *
+     * @param enable Whether to enable or disable verbose vendor logging.
      */
-    setDeviceLoggingEnabled(bool enable) generates (bool success);
+    setVerboseLoggingEnabled(bool enable);
+
+    /**
+     * Queries the current state of verbose device logging. Primarily for UI and informative
+     * purposes.
+     *
+     * Even if verbose logging has been disabled, dumpstateBoard may still be called by the
+     * dumpstate routine, and essential information that does not identify the user may be included.
+     *
+     * @return enabled Whether or not verbose vendor logging is currently enabled.
+     */
+    getVerboseLoggingEnabled() generates (bool enabled);
 };
diff --git a/dumpstate/1.1/types.hal b/dumpstate/1.1/types.hal
index a6f391a..c522f7c 100644
--- a/dumpstate/1.1/types.hal
+++ b/dumpstate/1.1/types.hal
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+
 package android.hardware.dumpstate@1.1;
 
 /**
@@ -23,22 +24,18 @@
      * Takes a bug report without user interference.
      */
     FULL = 0,
-
     /**
      * Interactive bug report, i.e. triggered by the user.
      */
     INTERACTIVE = 1,
-
     /**
      * Remote bug report triggered by DevicePolicyManager, for example.
      */
     REMOTE = 2,
-
     /**
      * Bug report triggered on a wear device.
      */
     WEAR = 3,
-
     /**
      * Bug report limited to only connectivity info (cellular, wifi, and networking). Sometimes
      * called "telephony" in legacy contexts.
@@ -49,14 +46,41 @@
      * user application traffic.
      */
     CONNECTIVITY = 4,
-
     /**
      * Bug report limited to only wifi info.
      */
     WIFI = 5,
-
     /**
-     * Default mode.
+     * Default mode, essentially analogous to calling @1.0::IDumpstateDevice.dumpstateBoard(handle).
+     * This mode MUST be supported if the dumpstate HAL is implemented.
      */
-    DEFAULT = 6
+    DEFAULT = 6,
+    /**
+     * Takes a report in protobuf.
+     *
+     * The content, if implemented, must be a binary protobuf message written to the first file
+     * descriptor of the native handle. The protobuf schema shall be defined by the vendor.
+     */
+    PROTO = 7,
+};
+
+/**
+ * A simple return enum for use with dumpstateBoard_1_1.
+ */
+enum DumpstateStatus : uint32_t {
+    OK = 0,
+    /**
+     * Returned for cases where the device doesn't support the given DumpstateMode (e.g. a phone
+     * trying to use DumpstateMode::WEAR).
+     */
+    UNSUPPORTED_MODE = 1,
+    /**
+     * Returned for cases where an IllegalArgumentException is typically appropriate, e.g. missing
+     * file descriptors.
+     */
+    ILLEGAL_ARGUMENT = 2,
+    /**
+     * Returned when device logging is not enabled.
+     */
+    DEVICE_LOGGING_NOT_ENABLED = 3,
 };
diff --git a/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp b/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp
index 583efbf..1bef663 100644
--- a/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp
+++ b/dumpstate/1.1/vts/functional/VtsHalDumpstateV1_1TargetTest.cpp
@@ -19,6 +19,8 @@
 #include <fcntl.h>
 #include <unistd.h>
 
+#include <functional>
+#include <tuple>
 #include <vector>
 
 #include <android/hardware/dumpstate/1.1/IDumpstateDevice.h>
@@ -26,6 +28,7 @@
 #include <cutils/native_handle.h>
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
+#include <hidl/HidlSupport.h>
 #include <hidl/ServiceManagement.h>
 #include <log/log.h>
 
@@ -34,54 +37,126 @@
 using ::android::sp;
 using ::android::hardware::Return;
 using ::android::hardware::dumpstate::V1_1::DumpstateMode;
+using ::android::hardware::dumpstate::V1_1::DumpstateStatus;
 using ::android::hardware::dumpstate::V1_1::IDumpstateDevice;
+using ::android::hardware::dumpstate::V1_1::toString;
 
-class DumpstateHidl1_1Test : public ::testing::TestWithParam<std::string> {
-  public:
-    virtual void SetUp() override {
-        dumpstate = IDumpstateDevice::getService(GetParam());
-        ASSERT_NE(dumpstate, nullptr) << "Could not get HIDL instance";
+// Base class common to all dumpstate HAL v1.1 tests.
+template <typename T>
+class DumpstateHidl1_1TestBase : public ::testing::TestWithParam<T> {
+  protected:
+    virtual void SetUp() override { GetService(); }
+
+    virtual std::string GetInstanceName() = 0;
+
+    void GetService() {
+        const std::string instance_name = GetInstanceName();
+        dumpstate = IDumpstateDevice::getService(instance_name);
+        ASSERT_NE(dumpstate, nullptr) << "Could not get HIDL instance " << instance_name;
     }
 
+    void ToggleVerboseLogging(bool enable) {
+        Return<void> status = dumpstate->setVerboseLoggingEnabled(enable);
+        ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+
+        if (!dumpstate->ping().isOk()) {
+            ALOGW("IDumpstateDevice service appears to have exited lazily, attempting to get "
+                  "again");
+            GetService();
+        }
+
+        Return<bool> logging_enabled = dumpstate->getVerboseLoggingEnabled();
+        ASSERT_TRUE(logging_enabled.isOk())
+                << "Status should be ok: " << logging_enabled.description();
+        ASSERT_EQ(logging_enabled, enable)
+                << "Verbose logging should now be " << (enable ? "enabled" : "disabled");
+
+        if (!dumpstate->ping().isOk()) {
+            ALOGW("IDumpstateDevice service appears to have exited lazily, attempting to get "
+                  "again");
+            GetService();
+        }
+    }
+
+    void EnableVerboseLogging() { ToggleVerboseLogging(true); }
+
+    void DisableVerboseLogging() { ToggleVerboseLogging(false); }
+
     sp<IDumpstateDevice> dumpstate;
 };
 
-#define TEST_FOR_DUMPSTATE_MODE(name, body, mode) \
-    TEST_P(DumpstateHidl1_1Test, name##_##mode) { body(DumpstateMode::mode); }
+// Tests that don't need to iterate every single DumpstateMode value for dumpstateBoard_1_1.
+class DumpstateHidl1_1GeneralTest : public DumpstateHidl1_1TestBase<std::string> {
+  protected:
+    virtual std::string GetInstanceName() override { return GetParam(); }
+};
 
-#define TEST_FOR_ALL_DUMPSTATE_MODES(name, body)       \
-    TEST_FOR_DUMPSTATE_MODE(name, body, FULL);         \
-    TEST_FOR_DUMPSTATE_MODE(name, body, INTERACTIVE);  \
-    TEST_FOR_DUMPSTATE_MODE(name, body, REMOTE);       \
-    TEST_FOR_DUMPSTATE_MODE(name, body, WEAR);         \
-    TEST_FOR_DUMPSTATE_MODE(name, body, CONNECTIVITY); \
-    TEST_FOR_DUMPSTATE_MODE(name, body, WIFI);         \
-    TEST_FOR_DUMPSTATE_MODE(name, body, DEFAULT);
+// Tests that iterate every single DumpstateMode value for dumpstateBoard_1_1.
+class DumpstateHidl1_1PerModeTest
+    : public DumpstateHidl1_1TestBase<std::tuple<std::string, DumpstateMode>> {
+  protected:
+    virtual std::string GetInstanceName() override { return std::get<0>(GetParam()); }
+
+    DumpstateMode GetMode() { return std::get<1>(GetParam()); }
+
+    // Will only execute additional_assertions when status == expected.
+    void AssertStatusForMode(const Return<DumpstateStatus>& status, const DumpstateStatus expected,
+                             std::function<void()> additional_assertions = nullptr) {
+        ASSERT_TRUE(status.isOk())
+                << "Status should be ok and return a more specific DumpstateStatus: "
+                << status.description();
+        if (GetMode() == DumpstateMode::DEFAULT) {
+            ASSERT_EQ(expected, status)
+                    << "Required mode (DumpstateMode::" << toString(GetMode())
+                    << "): status should be DumpstateStatus::" << toString(expected)
+                    << ", but got DumpstateStatus::" << toString(status);
+        } else {
+            // The rest of the modes are optional to support, but they MUST return either the
+            // expected value or UNSUPPORTED_MODE.
+            ASSERT_TRUE(status == expected || status == DumpstateStatus::UNSUPPORTED_MODE)
+                    << "Optional mode (DumpstateMode::" << toString(GetMode())
+                    << "): status should be DumpstateStatus::" << toString(expected)
+                    << " or DumpstateStatus::UNSUPPORTED_MODE, but got DumpstateStatus::"
+                    << toString(status);
+        }
+        if (status == expected && additional_assertions != nullptr) {
+            additional_assertions();
+        }
+    }
+};
 
 constexpr uint64_t kDefaultTimeoutMillis = 30 * 1000;  // 30 seconds
 
 // Negative test: make sure dumpstateBoard() doesn't crash when passed a null pointer.
-TEST_FOR_ALL_DUMPSTATE_MODES(TestNullHandle, [this](DumpstateMode mode) {
-    Return<void> status = dumpstate->dumpstateBoard_1_1(nullptr, mode, kDefaultTimeoutMillis);
+TEST_P(DumpstateHidl1_1PerModeTest, TestNullHandle) {
+    EnableVerboseLogging();
 
-    ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
-});
+    Return<DumpstateStatus> status =
+            dumpstate->dumpstateBoard_1_1(nullptr, GetMode(), kDefaultTimeoutMillis);
+
+    AssertStatusForMode(status, DumpstateStatus::ILLEGAL_ARGUMENT);
+}
 
 // Negative test: make sure dumpstateBoard() ignores a handle with no FD.
-TEST_FOR_ALL_DUMPSTATE_MODES(TestHandleWithNoFd, [this](DumpstateMode mode) {
+TEST_P(DumpstateHidl1_1PerModeTest, TestHandleWithNoFd) {
+    EnableVerboseLogging();
+
     native_handle_t* handle = native_handle_create(0, 0);
     ASSERT_NE(handle, nullptr) << "Could not create native_handle";
 
-    Return<void> status = dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
+    Return<DumpstateStatus> status =
+            dumpstate->dumpstateBoard_1_1(handle, GetMode(), kDefaultTimeoutMillis);
 
-    ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+    AssertStatusForMode(status, DumpstateStatus::ILLEGAL_ARGUMENT);
 
     native_handle_close(handle);
     native_handle_delete(handle);
-});
+}
 
 // Positive test: make sure dumpstateBoard() writes something to the FD.
-TEST_FOR_ALL_DUMPSTATE_MODES(TestOk, [this](DumpstateMode mode) {
+TEST_P(DumpstateHidl1_1PerModeTest, TestOk) {
+    EnableVerboseLogging();
+
     // Index 0 corresponds to the read end of the pipe; 1 to the write end.
     int fds[2];
     ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
@@ -90,19 +165,23 @@
     ASSERT_NE(handle, nullptr) << "Could not create native_handle";
     handle->data[0] = fds[1];
 
-    Return<void> status = dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
-    ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+    Return<DumpstateStatus> status =
+            dumpstate->dumpstateBoard_1_1(handle, GetMode(), kDefaultTimeoutMillis);
 
-    // Check that at least one byte was written
-    char buff;
-    ASSERT_EQ(1, read(fds[0], &buff, 1)) << "dumped nothing";
+    AssertStatusForMode(status, DumpstateStatus::OK, [&fds]() {
+        // Check that at least one byte was written.
+        char buff;
+        ASSERT_EQ(1, read(fds[0], &buff, 1)) << "Dumped nothing";
+    });
 
     native_handle_close(handle);
     native_handle_delete(handle);
-});
+}
 
 // Positive test: make sure dumpstateBoard() doesn't crash with two FDs.
-TEST_FOR_ALL_DUMPSTATE_MODES(TestHandleWithTwoFds, [this](DumpstateMode mode) {
+TEST_P(DumpstateHidl1_1PerModeTest, TestHandleWithTwoFds) {
+    EnableVerboseLogging();
+
     int fds1[2];
     int fds2[2];
     ASSERT_EQ(0, pipe2(fds1, O_NONBLOCK)) << errno;
@@ -113,15 +192,26 @@
     handle->data[0] = fds1[1];
     handle->data[1] = fds2[1];
 
-    Return<void> status = dumpstate->dumpstateBoard_1_1(handle, mode, kDefaultTimeoutMillis);
-    ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+    Return<DumpstateStatus> status =
+            dumpstate->dumpstateBoard_1_1(handle, GetMode(), kDefaultTimeoutMillis);
+
+    AssertStatusForMode(status, DumpstateStatus::OK, [&fds1, &fds2]() {
+        // Check that at least one byte was written to one of the FDs.
+        char buff;
+        size_t read1 = read(fds1[0], &buff, 1);
+        size_t read2 = read(fds2[0], &buff, 1);
+        // Sometimes read returns -1, so we can't just add them together and expect >= 1.
+        ASSERT_TRUE(read1 == 1 || read2 == 1) << "Dumped nothing";
+    });
 
     native_handle_close(handle);
     native_handle_delete(handle);
-});
+}
 
 // Make sure dumpstateBoard_1_1 actually validates its arguments.
-TEST_P(DumpstateHidl1_1Test, TestInvalidModeArgument_Negative) {
+TEST_P(DumpstateHidl1_1GeneralTest, TestInvalidModeArgument_Negative) {
+    EnableVerboseLogging();
+
     int fds[2];
     ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
 
@@ -129,16 +219,21 @@
     ASSERT_NE(handle, nullptr) << "Could not create native_handle";
     handle->data[0] = fds[1];
 
-    Return<void> status = dumpstate->dumpstateBoard_1_1(handle, static_cast<DumpstateMode>(-100),
-                                                        kDefaultTimeoutMillis);
-    ASSERT_FALSE(status.isOk()) << "Status should not be ok with invalid mode param: "
-                                << status.description();
+    Return<DumpstateStatus> status = dumpstate->dumpstateBoard_1_1(
+            handle, static_cast<DumpstateMode>(-100), kDefaultTimeoutMillis);
+
+    ASSERT_TRUE(status.isOk()) << "Status should be ok and return a more specific DumpstateStatus: "
+                               << status.description();
+    ASSERT_EQ(status, DumpstateStatus::ILLEGAL_ARGUMENT)
+            << "Should return DumpstateStatus::ILLEGAL_ARGUMENT for invalid mode param";
 
     native_handle_close(handle);
     native_handle_delete(handle);
 }
 
-TEST_P(DumpstateHidl1_1Test, TestInvalidModeArgument_Undefined) {
+TEST_P(DumpstateHidl1_1GeneralTest, TestInvalidModeArgument_Undefined) {
+    EnableVerboseLogging();
+
     int fds[2];
     ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
 
@@ -146,31 +241,104 @@
     ASSERT_NE(handle, nullptr) << "Could not create native_handle";
     handle->data[0] = fds[1];
 
-    Return<void> status = dumpstate->dumpstateBoard_1_1(handle, static_cast<DumpstateMode>(9001),
-                                                        kDefaultTimeoutMillis);
-    ASSERT_FALSE(status.isOk()) << "Status should not be ok with invalid mode param: "
-                                << status.description();
+    Return<DumpstateStatus> status = dumpstate->dumpstateBoard_1_1(
+            handle, static_cast<DumpstateMode>(9001), kDefaultTimeoutMillis);
+
+    ASSERT_TRUE(status.isOk()) << "Status should be ok and return a more specific DumpstateStatus: "
+                               << status.description();
+    ASSERT_EQ(status, DumpstateStatus::ILLEGAL_ARGUMENT)
+            << "Should return DumpstateStatus::ILLEGAL_ARGUMENT for invalid mode param";
 
     native_handle_close(handle);
     native_handle_delete(handle);
 }
 
-// Make sure toggling device logging doesn't crash.
-TEST_P(DumpstateHidl1_1Test, TestEnableDeviceLogging) {
-    Return<bool> status = dumpstate->setDeviceLoggingEnabled(true);
+// Positive test: make sure dumpstateBoard() from 1.0 doesn't fail.
+TEST_P(DumpstateHidl1_1GeneralTest, Test1_0MethodOk) {
+    EnableVerboseLogging();
+
+    int fds[2];
+    ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
+
+    native_handle_t* handle = native_handle_create(1, 0);
+    ASSERT_NE(handle, nullptr) << "Could not create native_handle";
+    handle->data[0] = fds[1];
+
+    Return<void> status = dumpstate->dumpstateBoard(handle);
 
     ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+
+    // Check that at least one byte was written.
+    char buff;
+    ASSERT_EQ(1, read(fds[0], &buff, 1)) << "Dumped nothing";
+
+    native_handle_close(handle);
+    native_handle_delete(handle);
 }
 
-TEST_P(DumpstateHidl1_1Test, TestDisableDeviceLogging) {
-    Return<bool> status = dumpstate->setDeviceLoggingEnabled(false);
+// Make sure disabling verbose logging behaves correctly. Some info is still allowed to be emitted,
+// but it can't have privacy/storage/battery impacts.
+TEST_P(DumpstateHidl1_1PerModeTest, TestDeviceLoggingDisabled) {
+    DisableVerboseLogging();
 
-    ASSERT_TRUE(status.isOk()) << "Status should be ok: " << status.description();
+    // Index 0 corresponds to the read end of the pipe; 1 to the write end.
+    int fds[2];
+    ASSERT_EQ(0, pipe2(fds, O_NONBLOCK)) << errno;
+
+    native_handle_t* handle = native_handle_create(1, 0);
+    ASSERT_NE(handle, nullptr) << "Could not create native_handle";
+    handle->data[0] = fds[1];
+
+    Return<DumpstateStatus> status =
+            dumpstate->dumpstateBoard_1_1(handle, GetMode(), kDefaultTimeoutMillis);
+
+    // We don't include additional assertions here about the file passed in. If verbose logging is
+    // disabled, the OEM may choose to include nothing at all, but it is allowed to include some
+    // essential information based on the mode as long as it isn't private user information.
+    AssertStatusForMode(status, DumpstateStatus::OK);
+
+    native_handle_close(handle);
+    native_handle_delete(handle);
+}
+
+// Double-enable is perfectly valid, but the second call shouldn't do anything.
+TEST_P(DumpstateHidl1_1GeneralTest, TestRepeatedEnable) {
+    EnableVerboseLogging();
+    EnableVerboseLogging();
+}
+
+// Double-disable is perfectly valid, but the second call shouldn't do anything.
+TEST_P(DumpstateHidl1_1GeneralTest, TestRepeatedDisable) {
+    DisableVerboseLogging();
+    DisableVerboseLogging();
+}
+
+// Toggling in short order is perfectly valid.
+TEST_P(DumpstateHidl1_1GeneralTest, TestRepeatedToggle) {
+    EnableVerboseLogging();
+    DisableVerboseLogging();
+    EnableVerboseLogging();
+    DisableVerboseLogging();
 }
 
 INSTANTIATE_TEST_SUITE_P(
-        PerInstance, DumpstateHidl1_1Test,
+        PerInstance, DumpstateHidl1_1GeneralTest,
         testing::ValuesIn(android::hardware::getAllHalInstanceNames(IDumpstateDevice::descriptor)),
         android::hardware::PrintInstanceNameToString);
 
+// Includes the mode's name as part of the description string.
+static inline std::string PrintInstanceNameToStringWithMode(
+        const testing::TestParamInfo<std::tuple<std::string, DumpstateMode>>& info) {
+    return android::hardware::PrintInstanceNameToString(
+                   testing::TestParamInfo(std::get<0>(info.param), info.index)) +
+           "_" + toString(std::get<1>(info.param));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        PerInstanceAndMode, DumpstateHidl1_1PerModeTest,
+        testing::Combine(testing::ValuesIn(android::hardware::getAllHalInstanceNames(
+                                 IDumpstateDevice::descriptor)),
+                         testing::ValuesIn(android::hardware::hidl_enum_range<DumpstateMode>())),
+        PrintInstanceNameToStringWithMode);
+
 }  // namespace
diff --git a/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h
index 8540068..13df3bc 100644
--- a/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h
+++ b/graphics/mapper/2.1/utils/passthrough/include/mapper-passthrough/2.1/Gralloc0Hal.h
@@ -49,7 +49,12 @@
                  mModule, bufferHandle, descriptorInfo.width, descriptorInfo.height,
                  static_cast<int32_t>(descriptorInfo.format),
                  static_cast<uint64_t>(descriptorInfo.usage), stride);
-         return static_cast<Error>(ret);
+         if (ret == -EINVAL) {
+             return Error::BAD_BUFFER;
+         } else if (ret < 0) {
+             return Error::BAD_VALUE;
+         }
+         return Error::NONE;
      }
      Error getTransportSize(const native_handle_t* bufferHandle, uint32_t* outNumFds,
                             uint32_t* outNumInts) override {
diff --git a/health/2.0/default/Health.cpp b/health/2.0/default/Health.cpp
index 4225fd8..65eada8 100644
--- a/health/2.0/default/Health.cpp
+++ b/health/2.0/default/Health.cpp
@@ -156,7 +156,7 @@
     const HealthInfo_1_0& health_info = battery_monitor_->getHealthInfo_1_0();
     struct BatteryProperties props;
     convertFromHealthInfo(health_info, &props);
-    bool log = healthd_board_battery_update(&props);
+    bool log = (healthd_board_battery_update(&props) == 0);
     if (log) {
         battery_monitor_->logValues();
     }
diff --git a/health/2.0/default/HealthImplDefault.cpp b/health/2.0/default/HealthImplDefault.cpp
index e3cbefd..08fee9e 100644
--- a/health/2.0/default/HealthImplDefault.cpp
+++ b/health/2.0/default/HealthImplDefault.cpp
@@ -21,18 +21,6 @@
 using android::hardware::health::V2_0::implementation::Health;
 
 static struct healthd_config gHealthdConfig = {
-    .batteryStatusPath = android::String8(android::String8::kEmptyString),
-    .batteryHealthPath = android::String8(android::String8::kEmptyString),
-    .batteryPresentPath = android::String8(android::String8::kEmptyString),
-    .batteryCapacityPath = android::String8(android::String8::kEmptyString),
-    .batteryVoltagePath = android::String8(android::String8::kEmptyString),
-    .batteryTemperaturePath = android::String8(android::String8::kEmptyString),
-    .batteryTechnologyPath = android::String8(android::String8::kEmptyString),
-    .batteryCurrentNowPath = android::String8(android::String8::kEmptyString),
-    .batteryCurrentAvgPath = android::String8(android::String8::kEmptyString),
-    .batteryChargeCounterPath = android::String8(android::String8::kEmptyString),
-    .batteryFullChargePath = android::String8(android::String8::kEmptyString),
-    .batteryCycleCountPath = android::String8(android::String8::kEmptyString),
     .energyCounter = nullptr,
     .boot_min_cap = 0,
     .screen_on = nullptr};
diff --git a/health/2.1/types.hal b/health/2.1/types.hal
index efd8d6f..d775491 100644
--- a/health/2.1/types.hal
+++ b/health/2.1/types.hal
@@ -19,6 +19,10 @@
 import @1.0::HealthConfig;
 import @2.0::HealthInfo;
 
+enum Constants : int64_t {
+    BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED = -1,
+};
+
 /**
  * Battery capacity level. This enum provides additional information along side
  * with the battery capacity.
@@ -27,11 +31,17 @@
  */
 enum BatteryCapacityLevel : int32_t {
     /**
+     * Battery capacity level is unsupported.
+     * Battery capacity level must be set to this value if and only if the
+     * implementation is unsupported.
+     */
+    UNSUPPORTED = -1,
+    /**
      * Battery capacity level is unknown.
      * Battery capacity level must be set to this value if and only if battery
-     * is not present.
+     * is not present or the battery capacity level is unknown/uninitialized.
      */
-    UNKNOWN = 0,
+    UNKNOWN,
     /**
      * Battery is at critical level. The Android framework must schedule a
      * shutdown when it sees this value from the HAL.
@@ -78,18 +88,21 @@
 
     /**
      * Estimated time to fully charge the device (in seconds).
+     * Value must be BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED if and
+     * only if the implementation is unsupported.
      * Value must be 0 if and only if batteryCapacityLevel is FULL or UNKNOWN.
      * Otherwise, value must be positive.
      */
     int64_t batteryChargeTimeToFullNowSeconds;
 
     /**
-     * Estimated battery full capacity (in microamp hours, uAh).
+     * Estimated battery full charge design capacity (in microamp hours, uAh).
      * Value must be 0 if unknown.
-     * Value must be positive if known, and must be between [50%, 120%] of
-     * batteryFullCharge (the designed capacity).
+     * Value must be positive if known.
+     * Value must be greater than 100 000 uAh.
+     * Value must be less than 100 000 000 uAh.
      */
-    int32_t batteryFullCapacityUah;
+    int32_t batteryFullChargeDesignCapacityUah;
 };
 
 /**
diff --git a/health/2.1/vts/functional/VtsHalHealthV2_1TargetTest.cpp b/health/2.1/vts/functional/VtsHalHealthV2_1TargetTest.cpp
index e75b299..deb1a29 100644
--- a/health/2.1/vts/functional/VtsHalHealthV2_1TargetTest.cpp
+++ b/health/2.1/vts/functional/VtsHalHealthV2_1TargetTest.cpp
@@ -219,6 +219,9 @@
     return AssertionFailure() << static_cast<std::underlying_type_t<T>>(value) << " is not valid";
 }
 
+#define FULL_CHARGE_DESIGN_CAP_MIN ((long)100 * 1000)
+#define FULL_CHARGE_DESIGN_CAP_MAX ((long)100000 * 1000)
+
 /*
  * Tests the values returned by getHealthInfo() from interface IHealth.
  */
@@ -228,18 +231,18 @@
             return;
         }
         ASSERT_EQ(Result::SUCCESS, result);
-        const auto& legacy = value.legacy.legacy;
 
         EXPECT_TRUE(IsEnum(value.batteryCapacityLevel)) << " BatteryCapacityLevel";
         EXPECT_GE(value.batteryChargeTimeToFullNowSeconds, 0);
 
-        EXPECT_GE(value.batteryFullCapacityUah, 0)
-                << "batteryFullCapacityUah should not be negative";
+        EXPECT_GE(value.batteryFullChargeDesignCapacityUah, 0)
+                << "batteryFullChargeDesignCapacityUah should not be negative";
 
-        if (value.batteryFullCapacityUah > 0) {
-            EXPECT_GE(value.batteryFullCapacityUah, legacy.batteryFullCharge * 0.50);
-            EXPECT_LE(value.batteryFullCapacityUah, legacy.batteryFullCharge * 1.20);
-        }
+        EXPECT_GT((long)value.batteryFullChargeDesignCapacityUah, FULL_CHARGE_DESIGN_CAP_MIN)
+                << "batteryFullChargeDesignCapacityUah should be greater than 100 mAh";
+
+        EXPECT_LT((long)value.batteryFullChargeDesignCapacityUah, FULL_CHARGE_DESIGN_CAP_MAX)
+                << "batteryFullChargeDesignCapacityUah should be less than 100,000 mAh";
     })));
 }
 
diff --git a/health/storage/1.0/vts/functional/Android.bp b/health/storage/1.0/vts/functional/Android.bp
index a30cdde..4c703c5 100644
--- a/health/storage/1.0/vts/functional/Android.bp
+++ b/health/storage/1.0/vts/functional/Android.bp
@@ -22,6 +22,9 @@
     shared_libs: [
         "libhidlbase",
     ],
-    test_suites: ["general-tests", "vts-core"],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
+    test_config: "VtsHalHealthStorageV1_0TargetTest.config",
 }
-
diff --git a/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.config b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.config
new file mode 100644
index 0000000..0cd1c11
--- /dev/null
+++ b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.config
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs VtsHalHealthStorageV1_0TargetTest.">
+    <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="VtsHalHealthStorageV1_0TargetTest->/data/local/tmp/VtsHalHealthStorageV1_0TargetTest" />
+    </target_preparer>
+
+    <test class="com.android.tradefed.testtype.GTest" >
+        <option name="native-test-device-path" value="/data/local/tmp" />
+        <option name="module-name" value="VtsHalHealthStorageV1_0TargetTest" />
+        <option name="native-test-timeout" value="3m" />
+    </test>
+</configuration>
diff --git a/health/utils/libhealthloop/utils.cpp b/health/utils/libhealthloop/utils.cpp
index ebfd8d8..cd8c7a9 100644
--- a/health/utils/libhealthloop/utils.cpp
+++ b/health/utils/libhealthloop/utils.cpp
@@ -28,20 +28,6 @@
     *healthd_config = {
             .periodic_chores_interval_fast = DEFAULT_PERIODIC_CHORES_INTERVAL_FAST,
             .periodic_chores_interval_slow = DEFAULT_PERIODIC_CHORES_INTERVAL_SLOW,
-            .batteryStatusPath = String8(String8::kEmptyString),
-            .batteryHealthPath = String8(String8::kEmptyString),
-            .batteryPresentPath = String8(String8::kEmptyString),
-            .batteryCapacityPath = String8(String8::kEmptyString),
-            .batteryVoltagePath = String8(String8::kEmptyString),
-            .batteryTemperaturePath = String8(String8::kEmptyString),
-            .batteryTechnologyPath = String8(String8::kEmptyString),
-            .batteryCurrentNowPath = String8(String8::kEmptyString),
-            .batteryCurrentAvgPath = String8(String8::kEmptyString),
-            .batteryChargeCounterPath = String8(String8::kEmptyString),
-            .batteryFullChargePath = String8(String8::kEmptyString),
-            .batteryCycleCountPath = String8(String8::kEmptyString),
-            .batteryCapacityLevelPath = String8(String8::kEmptyString),
-            .batteryChargeTimeToFullNowPath = String8(String8::kEmptyString),
             .energyCounter = NULL,
             .boot_min_cap = 0,
             .screen_on = NULL,
diff --git a/identity/1.0/Android.bp b/identity/1.0/Android.bp
deleted file mode 100644
index e0a6332..0000000
--- a/identity/1.0/Android.bp
+++ /dev/null
@@ -1,20 +0,0 @@
-// This file is autogenerated by hidl-gen -Landroidbp.
-
-hidl_interface {
-    name: "android.hardware.identity@1.0",
-    root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
-    srcs: [
-        "types.hal",
-        "IIdentityCredential.hal",
-        "IIdentityCredentialStore.hal",
-        "IWritableIdentityCredential.hal",
-    ],
-    interfaces: [
-        "android.hardware.keymaster@4.0",
-        "android.hidl.base@1.0",
-    ],
-    gen_java: false,
-}
diff --git a/identity/1.0/default/Android.bp b/identity/1.0/default/Android.bp
deleted file mode 100644
index d2b2966..0000000
--- a/identity/1.0/default/Android.bp
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-cc_binary {
-    name: "android.hardware.identity@1.0-service.example",
-    init_rc: ["android.hardware.identity@1.0-service.example.rc"],
-    vendor: true,
-    relative_install_path: "hw",
-    cflags: [
-        "-Wall",
-        "-Wextra",
-    ],
-    srcs: [
-        "service.cpp",
-        "IdentityCredential.cpp",
-        "IdentityCredentialStore.cpp",
-        "WritableIdentityCredential.cpp",
-    ],
-    shared_libs: [
-        "android.hardware.identity@1.0",
-        "android.hardware.identity-support-lib",
-        "android.hardware.keymaster@4.0",
-        "libcppbor",
-        "libcrypto",
-        "libbase",
-        "libhidlbase",
-        "liblog",
-        "libutils",
-    ],
-}
diff --git a/identity/1.0/default/IdentityCredential.cpp b/identity/1.0/default/IdentityCredential.cpp
deleted file mode 100644
index b0a5e56..0000000
--- a/identity/1.0/default/IdentityCredential.cpp
+++ /dev/null
@@ -1,773 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "IdentityCredential"
-
-#include "IdentityCredential.h"
-#include "IdentityCredentialStore.h"
-
-#include <android/hardware/identity/support/IdentityCredentialSupport.h>
-
-#include <string.h>
-
-#include <android-base/logging.h>
-
-#include <cppbor.h>
-#include <cppbor_parse.h>
-
-namespace android {
-namespace hardware {
-namespace identity {
-namespace implementation {
-
-using ::android::hardware::keymaster::V4_0::Timestamp;
-using ::std::optional;
-
-Return<void> IdentityCredential::deleteCredential(deleteCredential_cb _hidl_cb) {
-    cppbor::Array array = {"ProofOfDeletion", docType_, testCredential_};
-    vector<uint8_t> proofOfDeletion = array.encode();
-
-    optional<vector<uint8_t>> proofOfDeletionSignature =
-            support::coseSignEcDsa(credentialPrivKey_,
-                                   proofOfDeletion,  // payload
-                                   {},               // additionalData
-                                   {});              // certificateChain
-    if (!proofOfDeletionSignature) {
-        _hidl_cb(support::result(ResultCode::FAILED, "Error signing data"), {});
-        return Void();
-    }
-
-    _hidl_cb(support::resultOK(), proofOfDeletionSignature.value());
-    return Void();
-}
-
-Return<void> IdentityCredential::createEphemeralKeyPair(createEphemeralKeyPair_cb _hidl_cb) {
-    optional<vector<uint8_t>> keyPair = support::createEcKeyPair();
-    if (!keyPair) {
-        _hidl_cb(support::result(ResultCode::FAILED, "Error creating ephemeral key pair"), {});
-        return Void();
-    }
-
-    // Stash public key of this key-pair for later check in startRetrieval().
-    optional<vector<uint8_t>> publicKey = support::ecKeyPairGetPublicKey(keyPair.value());
-    if (!publicKey) {
-        _hidl_cb(support::result(ResultCode::FAILED,
-                                 "Error getting public part of ephemeral key pair"),
-                 {});
-        return Void();
-    }
-    ephemeralPublicKey_ = publicKey.value();
-
-    _hidl_cb(support::resultOK(), keyPair.value());
-    return Void();
-}
-
-Return<void> IdentityCredential::setReaderEphemeralPublicKey(
-        const hidl_vec<uint8_t>& publicKey, setReaderEphemeralPublicKey_cb _hidl_cb) {
-    readerPublicKey_ = publicKey;
-    _hidl_cb(support::resultOK());
-    return Void();
-}
-
-ResultCode IdentityCredential::initialize() {
-    auto [item, _, message] = cppbor::parse(credentialData_);
-    if (item == nullptr) {
-        LOG(ERROR) << "CredentialData is not valid CBOR: " << message;
-        return ResultCode::INVALID_DATA;
-    }
-
-    const cppbor::Array* arrayItem = item->asArray();
-    if (arrayItem == nullptr || arrayItem->size() != 3) {
-        LOG(ERROR) << "CredentialData is not an array with three elements";
-        return ResultCode::INVALID_DATA;
-    }
-
-    const cppbor::Tstr* docTypeItem = (*arrayItem)[0]->asTstr();
-    const cppbor::Bool* testCredentialItem =
-            ((*arrayItem)[1]->asSimple() != nullptr ? ((*arrayItem)[1]->asSimple()->asBool())
-                                                    : nullptr);
-    const cppbor::Bstr* encryptedCredentialKeysItem = (*arrayItem)[2]->asBstr();
-    if (docTypeItem == nullptr || testCredentialItem == nullptr ||
-        encryptedCredentialKeysItem == nullptr) {
-        LOG(ERROR) << "CredentialData unexpected item types";
-        return ResultCode::INVALID_DATA;
-    }
-
-    docType_ = docTypeItem->value();
-    testCredential_ = testCredentialItem->value();
-
-    vector<uint8_t> hardwareBoundKey;
-    if (testCredential_) {
-        hardwareBoundKey = support::getTestHardwareBoundKey();
-    } else {
-        hardwareBoundKey = support::getHardwareBoundKey();
-    }
-
-    const vector<uint8_t>& encryptedCredentialKeys = encryptedCredentialKeysItem->value();
-    const vector<uint8_t> docTypeVec(docType_.begin(), docType_.end());
-    optional<vector<uint8_t>> decryptedCredentialKeys =
-            support::decryptAes128Gcm(hardwareBoundKey, encryptedCredentialKeys, docTypeVec);
-    if (!decryptedCredentialKeys) {
-        LOG(ERROR) << "Error decrypting CredentialKeys";
-        return ResultCode::INVALID_DATA;
-    }
-
-    auto [dckItem, dckPos, dckMessage] = cppbor::parse(decryptedCredentialKeys.value());
-    if (dckItem == nullptr) {
-        LOG(ERROR) << "Decrypted CredentialKeys is not valid CBOR: " << dckMessage;
-        return ResultCode::INVALID_DATA;
-    }
-    const cppbor::Array* dckArrayItem = dckItem->asArray();
-    if (dckArrayItem == nullptr || dckArrayItem->size() != 2) {
-        LOG(ERROR) << "Decrypted CredentialKeys is not an array with two elements";
-        return ResultCode::INVALID_DATA;
-    }
-    const cppbor::Bstr* storageKeyItem = (*dckArrayItem)[0]->asBstr();
-    const cppbor::Bstr* credentialPrivKeyItem = (*dckArrayItem)[1]->asBstr();
-    if (storageKeyItem == nullptr || credentialPrivKeyItem == nullptr) {
-        LOG(ERROR) << "CredentialKeys unexpected item types";
-        return ResultCode::INVALID_DATA;
-    }
-    storageKey_ = storageKeyItem->value();
-    credentialPrivKey_ = credentialPrivKeyItem->value();
-
-    return ResultCode::OK;
-}
-
-Return<void> IdentityCredential::createAuthChallenge(createAuthChallenge_cb _hidl_cb) {
-    uint64_t challenge = 0;
-    while (challenge == 0) {
-        optional<vector<uint8_t>> bytes = support::getRandom(8);
-        if (!bytes) {
-            _hidl_cb(support::result(ResultCode::FAILED, "Error getting random data for challenge"),
-                     0);
-            return Void();
-        }
-
-        challenge = 0;
-        for (size_t n = 0; n < bytes.value().size(); n++) {
-            challenge |= ((bytes.value())[n] << (n * 8));
-        }
-    }
-
-    authChallenge_ = challenge;
-    _hidl_cb(support::resultOK(), challenge);
-    return Void();
-}
-
-// TODO: this could be a lot faster if we did all the splitting and pubkey extraction
-// ahead of time.
-bool checkReaderAuthentication(const SecureAccessControlProfile& profile,
-                               const vector<uint8_t>& readerCertificateChain) {
-    optional<vector<uint8_t>> acpPubKey =
-            support::certificateChainGetTopMostKey(profile.readerCertificate);
-    if (!acpPubKey) {
-        LOG(ERROR) << "Error extracting public key from readerCertificate in profile";
-        return false;
-    }
-
-    optional<vector<vector<uint8_t>>> certificatesInChain =
-            support::certificateChainSplit(readerCertificateChain);
-    if (!certificatesInChain) {
-        LOG(ERROR) << "Error splitting readerCertificateChain";
-        return false;
-    }
-    for (const vector<uint8_t>& certInChain : certificatesInChain.value()) {
-        optional<vector<uint8_t>> certPubKey = support::certificateChainGetTopMostKey(certInChain);
-        if (!certPubKey) {
-            LOG(ERROR)
-                    << "Error extracting public key from certificate in chain presented by reader";
-            return false;
-        }
-        if (acpPubKey.value() == certPubKey.value()) {
-            return true;
-        }
-    }
-    return false;
-}
-
-Timestamp clockGetTime() {
-    struct timespec time;
-    clock_gettime(CLOCK_MONOTONIC, &time);
-    return time.tv_sec * 1000 + time.tv_nsec / 1000000;
-}
-
-bool checkUserAuthentication(const SecureAccessControlProfile& profile,
-                             const HardwareAuthToken& authToken, uint64_t authChallenge) {
-    if (profile.secureUserId != authToken.userId) {
-        LOG(ERROR) << "secureUserId in profile (" << profile.secureUserId
-                   << ") differs from userId in authToken (" << authToken.userId << ")";
-        return false;
-    }
-
-    if (profile.timeoutMillis == 0) {
-        if (authToken.challenge == 0) {
-            LOG(ERROR) << "No challenge in authToken";
-            return false;
-        }
-
-        if (authToken.challenge != authChallenge) {
-            LOG(ERROR) << "Challenge in authToken doesn't match the challenge we created";
-            return false;
-        }
-        return true;
-    }
-
-    // Note that the Epoch for timestamps in HardwareAuthToken is at the
-    // discretion of the vendor:
-    //
-    //   "[...] 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();
-    if (authToken.timestamp > now) {
-        LOG(ERROR) << "Timestamp in authToken (" << authToken.timestamp
-                   << ") is in the future (now: " << now << ")";
-        return false;
-    }
-    if (now > authToken.timestamp + profile.timeoutMillis) {
-        LOG(ERROR) << "Deadline for authToken (" << authToken.timestamp << " + "
-                   << profile.timeoutMillis << " = "
-                   << (authToken.timestamp + profile.timeoutMillis)
-                   << ") is in the past (now: " << now << ")";
-        return false;
-    }
-
-    return true;
-}
-
-Return<void> IdentityCredential::startRetrieval(
-        const hidl_vec<SecureAccessControlProfile>& accessControlProfiles,
-        const HardwareAuthToken& authToken, const hidl_vec<uint8_t>& itemsRequest,
-        const hidl_vec<uint8_t>& sessionTranscript, const hidl_vec<uint8_t>& readerSignature,
-        const hidl_vec<uint16_t>& requestCounts, startRetrieval_cb _hidl_cb) {
-    if (sessionTranscript.size() > 0) {
-        auto [item, _, message] = cppbor::parse(sessionTranscript);
-        if (item == nullptr) {
-            _hidl_cb(support::result(ResultCode::INVALID_DATA,
-                                     "SessionTranscript contains invalid CBOR"));
-            return Void();
-        }
-        sessionTranscriptItem_ = std::move(item);
-    }
-    if (numStartRetrievalCalls_ > 0) {
-        if (sessionTranscript_ != vector<uint8_t>(sessionTranscript)) {
-            _hidl_cb(support::result(
-                    ResultCode::SESSION_TRANSCRIPT_MISMATCH,
-                    "Passed-in SessionTranscript doesn't match previously used SessionTranscript"));
-            return Void();
-        }
-    }
-    sessionTranscript_ = sessionTranscript;
-
-    // If there is a signature, validate that it was made with the top-most key in the
-    // certificate chain embedded in the COSE_Sign1 structure.
-    optional<vector<uint8_t>> readerCertificateChain;
-    if (readerSignature.size() > 0) {
-        readerCertificateChain = support::coseSignGetX5Chain(readerSignature);
-        if (!readerCertificateChain) {
-            _hidl_cb(support::result(ResultCode::READER_SIGNATURE_CHECK_FAILED,
-                                     "Unable to get reader certificate chain from COSE_Sign1"));
-            return Void();
-        }
-
-        if (!support::certificateChainValidate(readerCertificateChain.value())) {
-            _hidl_cb(support::result(ResultCode::READER_SIGNATURE_CHECK_FAILED,
-                                     "Error validating reader certificate chain"));
-            return Void();
-        }
-
-        optional<vector<uint8_t>> readerPublicKey =
-                support::certificateChainGetTopMostKey(readerCertificateChain.value());
-        if (!readerPublicKey) {
-            _hidl_cb(support::result(ResultCode::READER_SIGNATURE_CHECK_FAILED,
-                                     "Unable to get public key from reader certificate chain"));
-            return Void();
-        }
-
-        const vector<uint8_t>& itemsRequestBytes = itemsRequest;
-        vector<uint8_t> dataThatWasSigned = cppbor::Array()
-                                                    .add("ReaderAuthentication")
-                                                    .add(sessionTranscriptItem_->clone())
-                                                    .add(cppbor::Semantic(24, itemsRequestBytes))
-                                                    .encode();
-        if (!support::coseCheckEcDsaSignature(readerSignature,
-                                              dataThatWasSigned,  // detached content
-                                              readerPublicKey.value())) {
-            _hidl_cb(support::result(ResultCode::READER_SIGNATURE_CHECK_FAILED,
-                                     "readerSignature check failed"));
-            return Void();
-        }
-    }
-
-    // Here's where we would validate the passed-in |authToken| to assure ourselves
-    // that it comes from the e.g. biometric hardware and wasn't made up by an attacker.
-    //
-    // However this involves calculating the MAC. However this requires access
-    // to the key needed to a pre-shared key which we don't have...
-    //
-
-    // To prevent replay-attacks, we check that the public part of the ephemeral
-    // key we previously created, is present in the DeviceEngagement part of
-    // SessionTranscript as a COSE_Key, in uncompressed form.
-    //
-    // We do this by just searching for the X and Y coordinates.
-    if (sessionTranscript.size() > 0) {
-        const cppbor::Array* array = sessionTranscriptItem_->asArray();
-        if (array == nullptr || array->size() != 2) {
-            _hidl_cb(support::result(ResultCode::EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
-                                     "SessionTranscript is not an array with two items"));
-            return Void();
-        }
-        const cppbor::Semantic* taggedEncodedDE = (*array)[0]->asSemantic();
-        if (taggedEncodedDE == nullptr || taggedEncodedDE->value() != 24) {
-            _hidl_cb(support::result(ResultCode::EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
-                                     "First item in SessionTranscript array is not a "
-                                     "semantic with value 24"));
-            return Void();
-        }
-        const cppbor::Bstr* encodedDE = (taggedEncodedDE->child())->asBstr();
-        if (encodedDE == nullptr) {
-            _hidl_cb(support::result(ResultCode::EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
-                                     "Child of semantic in first item in SessionTranscript "
-                                     "array is not a bstr"));
-            return Void();
-        }
-        const vector<uint8_t>& bytesDE = encodedDE->value();
-
-        auto [getXYSuccess, ePubX, ePubY] = support::ecPublicKeyGetXandY(ephemeralPublicKey_);
-        if (!getXYSuccess) {
-            _hidl_cb(support::result(ResultCode::EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
-                                     "Error extracting X and Y from ePub"));
-            return Void();
-        }
-        if (sessionTranscript.size() > 0 &&
-            !(memmem(bytesDE.data(), bytesDE.size(), ePubX.data(), ePubX.size()) != nullptr &&
-              memmem(bytesDE.data(), bytesDE.size(), ePubY.data(), ePubY.size()) != nullptr)) {
-            _hidl_cb(support::result(ResultCode::EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
-                                     "Did not find ephemeral public key's X and Y coordinates in "
-                                     "SessionTranscript (make sure leading zeroes are not used)"));
-            return Void();
-        }
-    }
-
-    // itemsRequest: If non-empty, contains request data that may be signed by the
-    // reader.  The content can be defined in the way appropriate for the
-    // credential, but there are three requirements that must be met to work with
-    // this HAL:
-    if (itemsRequest.size() > 0) {
-        // 1. The content must be a CBOR-encoded structure.
-        auto [item, _, message] = cppbor::parse(itemsRequest);
-        if (item == nullptr) {
-            _hidl_cb(support::result(ResultCode::INVALID_ITEMS_REQUEST_MESSAGE,
-                                     "Error decoding CBOR in itemsRequest: %s", message.c_str()));
-            return Void();
-        }
-
-        // 2. The CBOR structure must be a map.
-        const cppbor::Map* map = item->asMap();
-        if (map == nullptr) {
-            _hidl_cb(support::result(ResultCode::INVALID_ITEMS_REQUEST_MESSAGE,
-                                     "itemsRequest is not a CBOR map"));
-            return Void();
-        }
-
-        // 3. The map must contain a key "nameSpaces" whose value contains a map, as described in
-        //    the example below.
-        //
-        //   NameSpaces = {
-        //     + NameSpace => DataElements ; Requested data elements for each NameSpace
-        //   }
-        //
-        //   NameSpace = tstr
-        //
-        //   DataElements = {
-        //     + DataElement => IntentToRetain
-        //   }
-        //
-        //   DataElement = tstr
-        //   IntentToRetain = bool
-        //
-        // Here's an example of an |itemsRequest| CBOR value satisfying above requirements 1.
-        // through 3.:
-        //
-        //    {
-        //        'docType' : 'org.iso.18013-5.2019',
-        //        'nameSpaces' : {
-        //            'org.iso.18013-5.2019' : {
-        //                'Last name' : false,
-        //                'Birth date' : false,
-        //                'First name' : false,
-        //                'Home address' : true
-        //            },
-        //            'org.aamva.iso.18013-5.2019' : {
-        //                'Real Id' : false
-        //            }
-        //        }
-        //    }
-        //
-        const cppbor::Map* nsMap = nullptr;
-        for (size_t n = 0; n < map->size(); n++) {
-            const auto& [keyItem, valueItem] = (*map)[n];
-            if (keyItem->type() == cppbor::TSTR && keyItem->asTstr()->value() == "nameSpaces" &&
-                valueItem->type() == cppbor::MAP) {
-                nsMap = valueItem->asMap();
-                break;
-            }
-        }
-        if (nsMap == nullptr) {
-            _hidl_cb(support::result(ResultCode::INVALID_ITEMS_REQUEST_MESSAGE,
-                                     "No nameSpaces map in top-most map"));
-            return Void();
-        }
-
-        for (size_t n = 0; n < nsMap->size(); n++) {
-            auto [nsKeyItem, nsValueItem] = (*nsMap)[n];
-            const cppbor::Tstr* nsKey = nsKeyItem->asTstr();
-            const cppbor::Map* nsInnerMap = nsValueItem->asMap();
-            if (nsKey == nullptr || nsInnerMap == nullptr) {
-                _hidl_cb(support::result(ResultCode::INVALID_ITEMS_REQUEST_MESSAGE,
-                                         "Type mismatch in nameSpaces map"));
-                return Void();
-            }
-            string requestedNamespace = nsKey->value();
-            vector<string> requestedKeys;
-            for (size_t m = 0; m < nsInnerMap->size(); m++) {
-                const auto& [innerMapKeyItem, innerMapValueItem] = (*nsInnerMap)[m];
-                const cppbor::Tstr* nameItem = innerMapKeyItem->asTstr();
-                const cppbor::Simple* simple = innerMapValueItem->asSimple();
-                const cppbor::Bool* intentToRetainItem =
-                        (simple != nullptr) ? simple->asBool() : nullptr;
-                if (nameItem == nullptr || intentToRetainItem == nullptr) {
-                    _hidl_cb(support::result(ResultCode::INVALID_ITEMS_REQUEST_MESSAGE,
-                                             "Type mismatch in value in nameSpaces map"));
-                    return Void();
-                }
-                requestedKeys.push_back(nameItem->value());
-            }
-            requestedNameSpacesAndNames_[requestedNamespace] = requestedKeys;
-        }
-    }
-
-    // Finally, validate all the access control profiles in the requestData.
-    bool haveAuthToken = (authToken.mac.size() > 0);
-    for (const auto& profile : accessControlProfiles) {
-        if (!support::secureAccessControlProfileCheckMac(profile, storageKey_)) {
-            _hidl_cb(support::result(ResultCode::INVALID_DATA,
-                                     "Error checking MAC for profile with id %d", int(profile.id)));
-            return Void();
-        }
-        ResultCode accessControlCheck = ResultCode::OK;
-        if (profile.userAuthenticationRequired) {
-            if (!haveAuthToken || !checkUserAuthentication(profile, authToken, authChallenge_)) {
-                accessControlCheck = ResultCode::USER_AUTHENTICATION_FAILED;
-            }
-        } else if (profile.readerCertificate.size() > 0) {
-            if (!readerCertificateChain ||
-                !checkReaderAuthentication(profile, readerCertificateChain.value())) {
-                accessControlCheck = ResultCode::READER_AUTHENTICATION_FAILED;
-            }
-        }
-        profileIdToAccessCheckResult_[profile.id] = accessControlCheck;
-    }
-
-    deviceNameSpacesMap_ = cppbor::Map();
-    currentNameSpaceDeviceNameSpacesMap_ = cppbor::Map();
-
-    requestCountsRemaining_ = requestCounts;
-    currentNameSpace_ = "";
-
-    itemsRequest_ = itemsRequest;
-
-    numStartRetrievalCalls_ += 1;
-    _hidl_cb(support::resultOK());
-    return Void();
-}
-
-Return<void> IdentityCredential::startRetrieveEntryValue(
-        const hidl_string& nameSpace, const hidl_string& name, uint32_t entrySize,
-        const hidl_vec<uint16_t>& accessControlProfileIds, startRetrieveEntryValue_cb _hidl_cb) {
-    if (name.empty()) {
-        _hidl_cb(support::result(ResultCode::INVALID_DATA, "Name cannot be empty"));
-        return Void();
-    }
-    if (nameSpace.empty()) {
-        _hidl_cb(support::result(ResultCode::INVALID_DATA, "Name space cannot be empty"));
-        return Void();
-    }
-
-    if (requestCountsRemaining_.size() == 0) {
-        _hidl_cb(support::result(ResultCode::INVALID_DATA,
-                                 "No more name spaces left to go through"));
-        return Void();
-    }
-
-    if (currentNameSpace_ == "") {
-        // First call.
-        currentNameSpace_ = nameSpace;
-    }
-
-    if (nameSpace == currentNameSpace_) {
-        // Same namespace.
-        if (requestCountsRemaining_[0] == 0) {
-            _hidl_cb(support::result(ResultCode::INVALID_DATA,
-                                     "No more entries to be retrieved in current name space"));
-            return Void();
-        }
-        requestCountsRemaining_[0] -= 1;
-    } else {
-        // New namespace.
-        if (requestCountsRemaining_[0] != 0) {
-            _hidl_cb(support::result(ResultCode::INVALID_DATA,
-                                     "Moved to new name space but %d entries need to be retrieved "
-                                     "in current name space",
-                                     int(requestCountsRemaining_[0])));
-            return Void();
-        }
-        if (currentNameSpaceDeviceNameSpacesMap_.size() > 0) {
-            deviceNameSpacesMap_.add(currentNameSpace_,
-                                     std::move(currentNameSpaceDeviceNameSpacesMap_));
-        }
-        currentNameSpaceDeviceNameSpacesMap_ = cppbor::Map();
-
-        requestCountsRemaining_.erase(requestCountsRemaining_.begin());
-        currentNameSpace_ = nameSpace;
-    }
-
-    // It's permissible to have an empty itemsRequest... but if non-empty you can
-    // only request what was specified in said itemsRequest. Enforce that.
-    if (itemsRequest_.size() > 0) {
-        const auto& it = requestedNameSpacesAndNames_.find(nameSpace);
-        if (it == requestedNameSpacesAndNames_.end()) {
-            _hidl_cb(support::result(ResultCode::NOT_IN_REQUEST_MESSAGE,
-                                     "Name space '%s' was not requested in startRetrieval",
-                                     nameSpace.c_str()));
-            return Void();
-        }
-        const auto& dataItemNames = it->second;
-        if (std::find(dataItemNames.begin(), dataItemNames.end(), name) == dataItemNames.end()) {
-            _hidl_cb(support::result(
-                    ResultCode::NOT_IN_REQUEST_MESSAGE,
-                    "Data item name '%s' in name space '%s' was not requested in startRetrieval",
-                    name.c_str(), nameSpace.c_str()));
-            return Void();
-        }
-    }
-
-    // Enforce access control.
-    //
-    // Access is granted if at least one of the profiles grants access.
-    //
-    // If an item is configured without any profiles, access is denied.
-    //
-    ResultCode accessControl = ResultCode::NO_ACCESS_CONTROL_PROFILES;
-    for (auto id : accessControlProfileIds) {
-        auto search = profileIdToAccessCheckResult_.find(id);
-        if (search == profileIdToAccessCheckResult_.end()) {
-            _hidl_cb(support::result(ResultCode::INVALID_DATA,
-                                     "Requested entry with unvalidated profile id %d", (int(id))));
-            return Void();
-        }
-        ResultCode accessControlForProfile = search->second;
-        if (accessControlForProfile == ResultCode::OK) {
-            accessControl = ResultCode::OK;
-            break;
-        }
-        accessControl = accessControlForProfile;
-    }
-    if (accessControl != ResultCode::OK) {
-        _hidl_cb(support::result(accessControl, "Access control check failed"));
-        return Void();
-    }
-
-    entryAdditionalData_ =
-            support::entryCreateAdditionalData(nameSpace, name, accessControlProfileIds);
-
-    currentName_ = name;
-    entryRemainingBytes_ = entrySize;
-    entryValue_.resize(0);
-
-    _hidl_cb(support::resultOK());
-    return Void();
-}
-
-Return<void> IdentityCredential::retrieveEntryValue(const hidl_vec<uint8_t>& encryptedContent,
-                                                    retrieveEntryValue_cb _hidl_cb) {
-    optional<vector<uint8_t>> content =
-            support::decryptAes128Gcm(storageKey_, encryptedContent, entryAdditionalData_);
-    if (!content) {
-        _hidl_cb(support::result(ResultCode::INVALID_DATA, "Error decrypting data"), {});
-        return Void();
-    }
-
-    size_t chunkSize = content.value().size();
-
-    if (chunkSize > entryRemainingBytes_) {
-        LOG(ERROR) << "Retrieved chunk of size " << chunkSize
-                   << " is bigger than remaining space of size " << entryRemainingBytes_;
-        _hidl_cb(support::result(ResultCode::INVALID_DATA,
-                                 "Retrieved chunk of size %zd is bigger than remaining space "
-                                 "of size %zd",
-                                 chunkSize, entryRemainingBytes_),
-                 {});
-        return Void();
-    }
-
-    entryRemainingBytes_ -= chunkSize;
-    if (entryRemainingBytes_ > 0) {
-        if (chunkSize != IdentityCredentialStore::kGcmChunkSize) {
-            _hidl_cb(support::result(ResultCode::INVALID_DATA,
-                                     "Retrieved non-final chunk of size %zd but expected "
-                                     "kGcmChunkSize which is %zd",
-                                     chunkSize, IdentityCredentialStore::kGcmChunkSize),
-                     {});
-            return Void();
-        }
-    }
-
-    entryValue_.insert(entryValue_.end(), content.value().begin(), content.value().end());
-
-    if (entryRemainingBytes_ == 0) {
-        auto [entryValueItem, _, message] = cppbor::parse(entryValue_);
-        if (entryValueItem == nullptr) {
-            _hidl_cb(support::result(ResultCode::INVALID_DATA, "Retrieved data invalid CBOR"), {});
-            return Void();
-        }
-        currentNameSpaceDeviceNameSpacesMap_.add(currentName_, std::move(entryValueItem));
-    }
-
-    _hidl_cb(support::resultOK(), content.value());
-    return Void();
-}
-
-Return<void> IdentityCredential::finishRetrieval(const hidl_vec<uint8_t>& signingKeyBlob,
-                                                 finishRetrieval_cb _hidl_cb) {
-    if (currentNameSpaceDeviceNameSpacesMap_.size() > 0) {
-        deviceNameSpacesMap_.add(currentNameSpace_,
-                                 std::move(currentNameSpaceDeviceNameSpacesMap_));
-    }
-    vector<uint8_t> encodedDeviceNameSpaces = deviceNameSpacesMap_.encode();
-
-    // 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;
-    if (signingKeyBlob.size() > 0 && sessionTranscript_.size() > 0 && readerPublicKey_.size() > 0) {
-        cppbor::Array array;
-        array.add("DeviceAuthentication");
-        array.add(sessionTranscriptItem_->clone());
-        array.add(docType_);
-        array.add(cppbor::Semantic(24, encodedDeviceNameSpaces));
-        vector<uint8_t> encodedDeviceAuthentication = array.encode();
-
-        vector<uint8_t> docTypeAsBlob(docType_.begin(), docType_.end());
-        optional<vector<uint8_t>> signingKey =
-                support::decryptAes128Gcm(storageKey_, signingKeyBlob, docTypeAsBlob);
-        if (!signingKey) {
-            _hidl_cb(support::result(ResultCode::INVALID_DATA, "Error decrypting signingKeyBlob"),
-                     {}, {});
-            return Void();
-        }
-
-        optional<vector<uint8_t>> sharedSecret =
-                support::ecdh(readerPublicKey_, signingKey.value());
-        if (!sharedSecret) {
-            _hidl_cb(support::result(ResultCode::FAILED, "Error doing ECDH"), {}, {});
-            return Void();
-        }
-
-        vector<uint8_t> salt = {0x00};
-        vector<uint8_t> info = {};
-        optional<vector<uint8_t>> derivedKey = support::hkdf(sharedSecret.value(), salt, info, 32);
-        if (!derivedKey) {
-            _hidl_cb(support::result(ResultCode::FAILED, "Error deriving key from shared secret"),
-                     {}, {});
-            return Void();
-        }
-
-        mac = support::coseMac0(derivedKey.value(), {},        // payload
-                                encodedDeviceAuthentication);  // additionalData
-        if (!mac) {
-            _hidl_cb(support::result(ResultCode::FAILED, "Error MACing data"), {}, {});
-            return Void();
-        }
-    }
-
-    _hidl_cb(support::resultOK(), mac.value_or(vector<uint8_t>({})), encodedDeviceNameSpaces);
-    return Void();
-}
-
-Return<void> IdentityCredential::generateSigningKeyPair(generateSigningKeyPair_cb _hidl_cb) {
-    string serialDecimal = "0";  // TODO: set serial to something unique
-    string issuer = "Android Open Source Project";
-    string subject = "Android IdentityCredential Reference Implementation";
-    time_t validityNotBefore = time(nullptr);
-    time_t validityNotAfter = validityNotBefore + 365 * 24 * 3600;
-
-    optional<vector<uint8_t>> signingKeyPKCS8 = support::createEcKeyPair();
-    if (!signingKeyPKCS8) {
-        _hidl_cb(support::result(ResultCode::FAILED, "Error creating signingKey"), {}, {});
-        return Void();
-    }
-
-    optional<vector<uint8_t>> signingPublicKey =
-            support::ecKeyPairGetPublicKey(signingKeyPKCS8.value());
-    if (!signingPublicKey) {
-        _hidl_cb(support::result(ResultCode::FAILED, "Error getting public part of signingKey"), {},
-                 {});
-        return Void();
-    }
-
-    optional<vector<uint8_t>> signingKey = support::ecKeyPairGetPrivateKey(signingKeyPKCS8.value());
-    if (!signingKey) {
-        _hidl_cb(support::result(ResultCode::FAILED, "Error getting private part of signingKey"),
-                 {}, {});
-        return Void();
-    }
-
-    optional<vector<uint8_t>> certificate = support::ecPublicKeyGenerateCertificate(
-            signingPublicKey.value(), credentialPrivKey_, serialDecimal, issuer, subject,
-            validityNotBefore, validityNotAfter);
-    if (!certificate) {
-        _hidl_cb(support::result(ResultCode::FAILED, "Error creating signingKey"), {}, {});
-        return Void();
-    }
-
-    optional<vector<uint8_t>> nonce = support::getRandom(12);
-    if (!nonce) {
-        _hidl_cb(support::result(ResultCode::FAILED, "Error getting random"), {}, {});
-        return Void();
-    }
-    vector<uint8_t> docTypeAsBlob(docType_.begin(), docType_.end());
-    optional<vector<uint8_t>> encryptedSigningKey = support::encryptAes128Gcm(
-            storageKey_, nonce.value(), signingKey.value(), docTypeAsBlob);
-    if (!encryptedSigningKey) {
-        _hidl_cb(support::result(ResultCode::FAILED, "Error encrypting signingKey"), {}, {});
-        return Void();
-    }
-    _hidl_cb(support::resultOK(), encryptedSigningKey.value(), certificate.value());
-    return Void();
-}
-
-}  // namespace implementation
-}  // namespace identity
-}  // namespace hardware
-}  // namespace android
diff --git a/identity/1.0/default/IdentityCredential.h b/identity/1.0/default/IdentityCredential.h
deleted file mode 100644
index eb8787b..0000000
--- a/identity/1.0/default/IdentityCredential.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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 ANDROID_HARDWARE_IDENTITY_IDENTITYCREDENTIAL_H
-#define ANDROID_HARDWARE_IDENTITY_IDENTITYCREDENTIAL_H
-
-#include <android/hardware/identity/1.0/IIdentityCredential.h>
-
-#include <android/hardware/identity/support/IdentityCredentialSupport.h>
-
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#include <cppbor/cppbor.h>
-
-namespace android {
-namespace hardware {
-namespace identity {
-namespace implementation {
-
-using ::std::map;
-using ::std::string;
-using ::std::vector;
-
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::identity::V1_0::IIdentityCredential;
-using ::android::hardware::identity::V1_0::Result;
-using ::android::hardware::identity::V1_0::ResultCode;
-using ::android::hardware::identity::V1_0::SecureAccessControlProfile;
-using ::android::hardware::keymaster::V4_0::HardwareAuthToken;
-
-using MapStringToVectorOfStrings = map<string, vector<string>>;
-
-class IdentityCredential : public IIdentityCredential {
-  public:
-    IdentityCredential(const hidl_vec<uint8_t>& credentialData)
-        : credentialData_(credentialData), numStartRetrievalCalls_(0), authChallenge_(0) {}
-
-    // Parses and decrypts credentialData_, return false on failure. Must be
-    // called right after construction.
-    ResultCode initialize();
-
-    // Methods from ::android::hardware::identity::IIdentityCredential follow.
-
-    Return<void> deleteCredential(deleteCredential_cb _hidl_cb) override;
-    Return<void> createEphemeralKeyPair(createEphemeralKeyPair_cb _hidl_cb) override;
-
-    Return<void> setReaderEphemeralPublicKey(const hidl_vec<uint8_t>& publicKey,
-                                             setReaderEphemeralPublicKey_cb _hidl_cb) override;
-
-    Return<void> createAuthChallenge(createAuthChallenge_cb _hidl_cb) override;
-
-    Return<void> startRetrieval(const hidl_vec<SecureAccessControlProfile>& accessControlProfiles,
-                                const HardwareAuthToken& authToken,
-                                const hidl_vec<uint8_t>& itemsRequest,
-                                const hidl_vec<uint8_t>& sessionTranscript,
-                                const hidl_vec<uint8_t>& readerSignature,
-                                const hidl_vec<uint16_t>& requestCounts,
-                                startRetrieval_cb _hidl_cb) override;
-    Return<void> startRetrieveEntryValue(const hidl_string& nameSpace, const hidl_string& name,
-                                         uint32_t entrySize,
-                                         const hidl_vec<uint16_t>& accessControlProfileIds,
-                                         startRetrieveEntryValue_cb _hidl_cb) override;
-    Return<void> retrieveEntryValue(const hidl_vec<uint8_t>& encryptedContent,
-                                    retrieveEntryValue_cb _hidl_cb) override;
-    Return<void> finishRetrieval(const hidl_vec<uint8_t>& signingKeyBlob,
-                                 finishRetrieval_cb _hidl_cb) override;
-
-    Return<void> generateSigningKeyPair(generateSigningKeyPair_cb _hidl_cb) override;
-
-  private:
-    // Set by constructor
-    vector<uint8_t> credentialData_;
-    int numStartRetrievalCalls_;
-
-    // Set by initialize()
-    string docType_;
-    bool testCredential_;
-    vector<uint8_t> storageKey_;
-    vector<uint8_t> credentialPrivKey_;
-
-    // Set by createEphemeralKeyPair()
-    vector<uint8_t> ephemeralPublicKey_;
-
-    // Set by setReaderEphemeralPublicKey()
-    vector<uint8_t> readerPublicKey_;
-
-    // Set by createAuthChallenge()
-    uint64_t authChallenge_;
-
-    // Set at startRetrieval() time.
-    map<uint16_t, ResultCode> profileIdToAccessCheckResult_;
-    vector<uint8_t> sessionTranscript_;
-    std::unique_ptr<cppbor::Item> sessionTranscriptItem_;
-    vector<uint8_t> itemsRequest_;
-    vector<uint16_t> requestCountsRemaining_;
-    MapStringToVectorOfStrings requestedNameSpacesAndNames_;
-    cppbor::Map deviceNameSpacesMap_;
-    cppbor::Map currentNameSpaceDeviceNameSpacesMap_;
-
-    // Set at startRetrieveEntryValue() time.
-    string currentNameSpace_;
-    string currentName_;
-    size_t entryRemainingBytes_;
-    vector<uint8_t> entryValue_;
-    vector<uint8_t> entryAdditionalData_;
-};
-
-}  // namespace implementation
-}  // namespace identity
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_IDENTITY_IDENTITYCREDENTIAL_H
diff --git a/identity/1.0/default/IdentityCredentialStore.cpp b/identity/1.0/default/IdentityCredentialStore.cpp
deleted file mode 100644
index 9eb1e70..0000000
--- a/identity/1.0/default/IdentityCredentialStore.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "IdentityCredentialStore"
-
-#include "IdentityCredentialStore.h"
-#include "IdentityCredential.h"
-#include "WritableIdentityCredential.h"
-
-#include <android-base/logging.h>
-
-namespace android {
-namespace hardware {
-namespace identity {
-namespace implementation {
-
-// Methods from ::android::hardware::identity::IIdentityCredentialStore follow.
-
-Return<void> IdentityCredentialStore::getHardwareInformation(getHardwareInformation_cb _hidl_cb) {
-    _hidl_cb(support::resultOK(), "IdentityCredential Reference Implementation", "Google",
-             kGcmChunkSize, false /* isDirectAccess */, {} /* supportedDocTypes */);
-    return Void();
-}
-
-Return<void> IdentityCredentialStore::createCredential(const hidl_string& docType,
-                                                       bool testCredential,
-                                                       createCredential_cb _hidl_cb) {
-    auto writable_credential = new WritableIdentityCredential(docType, testCredential);
-    if (!writable_credential->initialize()) {
-        _hidl_cb(support::result(ResultCode::FAILED,
-                                 "Error initializing WritableIdentityCredential"),
-                 writable_credential);
-        return Void();
-    }
-    _hidl_cb(support::resultOK(), writable_credential);
-    return Void();
-}
-
-Return<void> IdentityCredentialStore::getCredential(const hidl_vec<uint8_t>& credentialData,
-                                                    getCredential_cb _hidl_cb) {
-    auto credential = new IdentityCredential(credentialData);
-    // We only support CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 right now.
-    auto ret = credential->initialize();
-    if (ret != ResultCode::OK) {
-        _hidl_cb(support::result(ret, "Error initializing IdentityCredential"), credential);
-        return Void();
-    }
-    _hidl_cb(support::resultOK(), credential);
-    return Void();
-}
-
-}  // namespace implementation
-}  // namespace identity
-}  // namespace hardware
-}  // namespace android
diff --git a/identity/1.0/default/IdentityCredentialStore.h b/identity/1.0/default/IdentityCredentialStore.h
deleted file mode 100644
index ad75360..0000000
--- a/identity/1.0/default/IdentityCredentialStore.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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 ANDROID_HARDWARE_IDENTITY_IDENTITYCREDENTIALSTORE_H
-#define ANDROID_HARDWARE_IDENTITY_IDENTITYCREDENTIALSTORE_H
-
-#include <android/hardware/identity/1.0/IIdentityCredentialStore.h>
-
-namespace android {
-namespace hardware {
-namespace identity {
-namespace implementation {
-
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::identity::V1_0::IIdentityCredentialStore;
-using ::android::hardware::identity::V1_0::Result;
-using ::android::hardware::identity::V1_0::ResultCode;
-
-class IdentityCredentialStore : public IIdentityCredentialStore {
-  public:
-    IdentityCredentialStore() {}
-
-    // The GCM chunk size used by this implementation is 64 KiB.
-    static constexpr size_t kGcmChunkSize = 64 * 1024;
-
-    // Methods from ::android::hardware::identity::IIdentityCredentialStore follow.
-    Return<void> getHardwareInformation(getHardwareInformation_cb _hidl_cb) override;
-    Return<void> createCredential(const hidl_string& docType, bool testCredential,
-                                  createCredential_cb _hidl_cb) override;
-    Return<void> getCredential(const hidl_vec<uint8_t>& credentialData,
-                               getCredential_cb _hidl_cb) override;
-};
-
-}  // namespace implementation
-}  // namespace identity
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_IDENTITY_IDENTITYCREDENTIALSTORE_H
diff --git a/identity/1.0/default/OWNERS b/identity/1.0/default/OWNERS
deleted file mode 100644
index 6969910..0000000
--- a/identity/1.0/default/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-swillden@google.com
-zeuthen@google.com
diff --git a/identity/1.0/default/WritableIdentityCredential.cpp b/identity/1.0/default/WritableIdentityCredential.cpp
deleted file mode 100644
index 548b4c0..0000000
--- a/identity/1.0/default/WritableIdentityCredential.cpp
+++ /dev/null
@@ -1,426 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "WritableIdentityCredential"
-
-#include "WritableIdentityCredential.h"
-#include "IdentityCredentialStore.h"
-
-#include <android/hardware/identity/support/IdentityCredentialSupport.h>
-
-#include <android-base/logging.h>
-
-#include <cppbor/cppbor.h>
-#include <cppbor/cppbor_parse.h>
-
-namespace android {
-namespace hardware {
-namespace identity {
-namespace implementation {
-
-using ::std::optional;
-
-// Writes CBOR-encoded structure to |credentialKeys| containing |storageKey| and
-// |credentialPrivKey|.
-static bool generateCredentialKeys(const vector<uint8_t>& storageKey,
-                                   const vector<uint8_t>& credentialPrivKey,
-                                   vector<uint8_t>& credentialKeys) {
-    if (storageKey.size() != 16) {
-        LOG(ERROR) << "Size of storageKey is not 16";
-        return false;
-    }
-
-    cppbor::Array array;
-    array.add(cppbor::Bstr(storageKey));
-    array.add(cppbor::Bstr(credentialPrivKey));
-    credentialKeys = array.encode();
-    return true;
-}
-
-// Writes CBOR-encoded structure to |credentialData| containing |docType|,
-// |testCredential| and |credentialKeys|. The latter element will be stored in
-// encrypted form, using |hardwareBoundKey| as the encryption key.
-bool generateCredentialData(const vector<uint8_t>& hardwareBoundKey, const string& docType,
-                            bool testCredential, const vector<uint8_t>& credentialKeys,
-                            vector<uint8_t>& credentialData) {
-    optional<vector<uint8_t>> nonce = support::getRandom(12);
-    if (!nonce) {
-        LOG(ERROR) << "Error getting random";
-        return false;
-    }
-    vector<uint8_t> docTypeAsVec(docType.begin(), docType.end());
-    optional<vector<uint8_t>> credentialBlob = support::encryptAes128Gcm(
-            hardwareBoundKey, nonce.value(), credentialKeys, docTypeAsVec);
-    if (!credentialBlob) {
-        LOG(ERROR) << "Error encrypting CredentialKeys blob";
-        return false;
-    }
-
-    cppbor::Array array;
-    array.add(docType);
-    array.add(testCredential);
-    array.add(cppbor::Bstr(credentialBlob.value()));
-    credentialData = array.encode();
-    return true;
-}
-
-bool WritableIdentityCredential::initialize() {
-    optional<vector<uint8_t>> keyPair = support::createEcKeyPair();
-    if (!keyPair) {
-        LOG(ERROR) << "Error creating credentialKey";
-        return false;
-    }
-
-    optional<vector<uint8_t>> pubKey = support::ecKeyPairGetPublicKey(keyPair.value());
-    if (!pubKey) {
-        LOG(ERROR) << "Error getting public part of credentialKey";
-        return false;
-    }
-    credentialPubKey_ = pubKey.value();
-
-    optional<vector<uint8_t>> privKey = support::ecKeyPairGetPrivateKey(keyPair.value());
-    if (!privKey) {
-        LOG(ERROR) << "Error getting private part of credentialKey";
-        return false;
-    }
-    credentialPrivKey_ = privKey.value();
-
-    optional<vector<uint8_t>> random = support::getRandom(16);
-    if (!random) {
-        LOG(ERROR) << "Error creating storageKey";
-        return false;
-    }
-    storageKey_ = random.value();
-
-    return true;
-}
-
-Return<void> WritableIdentityCredential::getAttestationCertificate(
-        const hidl_vec<uint8_t>& /* attestationChallenge */,
-        getAttestationCertificate_cb _hidl_cb) {
-    // For now, we dynamically generate an attestion key on each and every
-    // request and use that to sign CredentialKey. In a real implementation this
-    // would look very differently.
-    optional<vector<uint8_t>> attestationKeyPair = support::createEcKeyPair();
-    if (!attestationKeyPair) {
-        _hidl_cb(support::result(ResultCode::FAILED, "Error creating attestationKey"), {});
-        return Void();
-    }
-
-    optional<vector<uint8_t>> attestationPubKey =
-            support::ecKeyPairGetPublicKey(attestationKeyPair.value());
-    if (!attestationPubKey) {
-        _hidl_cb(support::result(ResultCode::FAILED, "Error getting public part of attestationKey"),
-                 {});
-        return Void();
-    }
-
-    optional<vector<uint8_t>> attestationPrivKey =
-            support::ecKeyPairGetPrivateKey(attestationKeyPair.value());
-    if (!attestationPrivKey) {
-        _hidl_cb(
-                support::result(ResultCode::FAILED, "Error getting private part of attestationKey"),
-                {});
-        return Void();
-    }
-
-    string serialDecimal;
-    string issuer;
-    string subject;
-    time_t validityNotBefore = time(nullptr);
-    time_t validityNotAfter = validityNotBefore + 365 * 24 * 3600;
-
-    // First create a certificate for |credentialPubKey| which is signed by
-    // |attestationPrivKey|.
-    //
-    serialDecimal = "0";  // TODO: set serial to |attestationChallenge|
-    issuer = "Android Open Source Project";
-    subject = "Android IdentityCredential CredentialKey";
-    optional<vector<uint8_t>> credentialPubKeyCertificate = support::ecPublicKeyGenerateCertificate(
-            credentialPubKey_, attestationPrivKey.value(), serialDecimal, issuer, subject,
-            validityNotBefore, validityNotAfter);
-    if (!credentialPubKeyCertificate) {
-        _hidl_cb(support::result(ResultCode::FAILED,
-                                 "Error creating certificate for credentialPubKey"),
-                 {});
-        return Void();
-    }
-
-    // This is followed by a certificate for |attestationPubKey| self-signed by
-    // |attestationPrivKey|.
-    serialDecimal = "0";  // TODO: set serial
-    issuer = "Android Open Source Project";
-    subject = "Android IdentityCredential AttestationKey";
-    optional<vector<uint8_t>> attestationKeyCertificate = support::ecPublicKeyGenerateCertificate(
-            attestationPubKey.value(), attestationPrivKey.value(), serialDecimal, issuer, subject,
-            validityNotBefore, validityNotAfter);
-    if (!attestationKeyCertificate) {
-        _hidl_cb(support::result(ResultCode::FAILED,
-                                 "Error creating certificate for attestationPubKey"),
-                 {});
-        return Void();
-    }
-
-    // Concatenate the certificates to form the chain.
-    vector<uint8_t> certificateChain;
-    certificateChain.insert(certificateChain.end(), credentialPubKeyCertificate.value().begin(),
-                            credentialPubKeyCertificate.value().end());
-    certificateChain.insert(certificateChain.end(), attestationKeyCertificate.value().begin(),
-                            attestationKeyCertificate.value().end());
-
-    _hidl_cb(support::resultOK(), certificateChain);
-    return Void();
-}
-
-Return<void> WritableIdentityCredential::startPersonalization(uint16_t accessControlProfileCount,
-                                                              const hidl_vec<uint16_t>& entryCounts,
-                                                              startPersonalization_cb _hidl_cb) {
-    numAccessControlProfileRemaining_ = accessControlProfileCount;
-    remainingEntryCounts_ = entryCounts;
-    entryNameSpace_ = "";
-
-    signedDataAccessControlProfiles_ = cppbor::Array();
-    signedDataNamespaces_ = cppbor::Map();
-    signedDataCurrentNamespace_ = cppbor::Array();
-
-    _hidl_cb(support::resultOK());
-    return Void();
-}
-
-Return<void> WritableIdentityCredential::addAccessControlProfile(
-        uint16_t id, const hidl_vec<uint8_t>& readerCertificate, bool userAuthenticationRequired,
-        uint64_t timeoutMillis, uint64_t secureUserId, addAccessControlProfile_cb _hidl_cb) {
-    SecureAccessControlProfile profile;
-
-    if (numAccessControlProfileRemaining_ == 0) {
-        _hidl_cb(support::result(ResultCode::INVALID_DATA,
-                                 "numAccessControlProfileRemaining_ is 0 and expected non-zero"),
-                 profile);
-        return Void();
-    }
-
-    // Spec requires if |userAuthenticationRequired| is false, then |timeoutMillis| must also
-    // be zero.
-    if (!userAuthenticationRequired && timeoutMillis != 0) {
-        _hidl_cb(support::result(ResultCode::INVALID_DATA,
-                                 "userAuthenticationRequired is false but timeout is non-zero"),
-                 profile);
-        return Void();
-    }
-
-    profile.id = id;
-    profile.readerCertificate = readerCertificate;
-    profile.userAuthenticationRequired = userAuthenticationRequired;
-    profile.timeoutMillis = timeoutMillis;
-    profile.secureUserId = secureUserId;
-    optional<vector<uint8_t>> mac =
-            support::secureAccessControlProfileCalcMac(profile, storageKey_);
-    if (!mac) {
-        _hidl_cb(support::result(ResultCode::FAILED, "Error calculating MAC for profile"), profile);
-        return Void();
-    }
-    profile.mac = mac.value();
-
-    cppbor::Map profileMap;
-    profileMap.add("id", profile.id);
-    if (profile.readerCertificate.size() > 0) {
-        profileMap.add("readerCertificate", cppbor::Bstr(profile.readerCertificate));
-    }
-    if (profile.userAuthenticationRequired) {
-        profileMap.add("userAuthenticationRequired", profile.userAuthenticationRequired);
-        profileMap.add("timeoutMillis", profile.timeoutMillis);
-    }
-    signedDataAccessControlProfiles_.add(std::move(profileMap));
-
-    numAccessControlProfileRemaining_--;
-
-    _hidl_cb(support::resultOK(), profile);
-    return Void();
-}
-
-Return<void> WritableIdentityCredential::beginAddEntry(
-        const hidl_vec<uint16_t>& accessControlProfileIds, const hidl_string& nameSpace,
-        const hidl_string& name, uint32_t entrySize, beginAddEntry_cb _hidl_cb) {
-    if (numAccessControlProfileRemaining_ != 0) {
-        LOG(ERROR) << "numAccessControlProfileRemaining_ is " << numAccessControlProfileRemaining_
-                   << " and expected zero";
-        _hidl_cb(support::result(ResultCode::INVALID_DATA,
-                                 "numAccessControlProfileRemaining_ is %zd and expected zero",
-                                 numAccessControlProfileRemaining_));
-        return Void();
-    }
-
-    if (remainingEntryCounts_.size() == 0) {
-        _hidl_cb(support::result(ResultCode::INVALID_DATA, "No more namespaces to add to"));
-        return Void();
-    }
-
-    // Handle initial beginEntry() call.
-    if (entryNameSpace_ == "") {
-        entryNameSpace_ = nameSpace;
-    }
-
-    // If the namespace changed...
-    if (nameSpace != entryNameSpace_) {
-        // Then check that all entries in the previous namespace have been added..
-        if (remainingEntryCounts_[0] != 0) {
-            _hidl_cb(support::result(ResultCode::INVALID_DATA,
-                                     "New namespace but %d entries remain to be added",
-                                     int(remainingEntryCounts_[0])));
-            return Void();
-        }
-        remainingEntryCounts_.erase(remainingEntryCounts_.begin());
-
-        if (signedDataCurrentNamespace_.size() > 0) {
-            signedDataNamespaces_.add(entryNameSpace_, std::move(signedDataCurrentNamespace_));
-            signedDataCurrentNamespace_ = cppbor::Array();
-        }
-    } else {
-        // Same namespace...
-        if (remainingEntryCounts_[0] == 0) {
-            _hidl_cb(support::result(ResultCode::INVALID_DATA,
-                                     "Same namespace but no entries remain to be added"));
-            return Void();
-        }
-        remainingEntryCounts_[0] -= 1;
-    }
-
-    entryAdditionalData_ =
-            support::entryCreateAdditionalData(nameSpace, name, accessControlProfileIds);
-
-    entryRemainingBytes_ = entrySize;
-    entryNameSpace_ = nameSpace;
-    entryName_ = name;
-    entryAccessControlProfileIds_ = accessControlProfileIds;
-    entryBytes_.resize(0);
-    // LOG(INFO) << "name=" << name << " entrySize=" << entrySize;
-
-    _hidl_cb(support::resultOK());
-    return Void();
-}
-
-Return<void> WritableIdentityCredential::addEntryValue(const hidl_vec<uint8_t>& content,
-                                                       addEntryValue_cb _hidl_cb) {
-    size_t contentSize = content.size();
-
-    if (contentSize > IdentityCredentialStore::kGcmChunkSize) {
-        _hidl_cb(support::result(
-                         ResultCode::INVALID_DATA,
-                         "Passed in chunk of size %zd is bigger than kGcmChunkSize which is %zd",
-                         contentSize, IdentityCredentialStore::kGcmChunkSize),
-                 {});
-        return Void();
-    }
-    if (contentSize > entryRemainingBytes_) {
-        _hidl_cb(support::result(ResultCode::INVALID_DATA,
-                                 "Passed in chunk of size %zd is bigger than remaining space "
-                                 "of size %zd",
-                                 contentSize, entryRemainingBytes_),
-                 {});
-        return Void();
-    }
-
-    entryBytes_.insert(entryBytes_.end(), content.begin(), content.end());
-    entryRemainingBytes_ -= contentSize;
-    if (entryRemainingBytes_ > 0) {
-        if (contentSize != IdentityCredentialStore::kGcmChunkSize) {
-            _hidl_cb(support::result(ResultCode::INVALID_DATA,
-                                     "Retrieved non-final chunk of size %zd but expected "
-                                     "kGcmChunkSize which is %zd",
-                                     contentSize, IdentityCredentialStore::kGcmChunkSize),
-                     {});
-            return Void();
-        }
-    }
-
-    optional<vector<uint8_t>> nonce = support::getRandom(12);
-    if (!nonce) {
-        _hidl_cb(support::result(ResultCode::FAILED, "Error getting nonce"), {});
-        return Void();
-    }
-    optional<vector<uint8_t>> encryptedContent =
-            support::encryptAes128Gcm(storageKey_, nonce.value(), content, entryAdditionalData_);
-    if (!encryptedContent) {
-        _hidl_cb(support::result(ResultCode::FAILED, "Error encrypting content"), {});
-        return Void();
-    }
-
-    if (entryRemainingBytes_ == 0) {
-        // TODO: ideally do do this without parsing the data (but still validate data is valid
-        // CBOR).
-        auto [item, _, message] = cppbor::parse(entryBytes_);
-        if (item == nullptr) {
-            _hidl_cb(support::result(ResultCode::INVALID_DATA, "Data is not valid CBOR"), {});
-            return Void();
-        }
-        cppbor::Map entryMap;
-        entryMap.add("name", entryName_);
-        entryMap.add("value", std::move(item));
-        cppbor::Array profileIdArray;
-        for (auto id : entryAccessControlProfileIds_) {
-            profileIdArray.add(id);
-        }
-        entryMap.add("accessControlProfiles", std::move(profileIdArray));
-        signedDataCurrentNamespace_.add(std::move(entryMap));
-    }
-
-    _hidl_cb(support::resultOK(), encryptedContent.value());
-    return Void();
-}
-
-Return<void> WritableIdentityCredential::finishAddingEntries(finishAddingEntries_cb _hidl_cb) {
-    if (signedDataCurrentNamespace_.size() > 0) {
-        signedDataNamespaces_.add(entryNameSpace_, std::move(signedDataCurrentNamespace_));
-    }
-    cppbor::Array popArray;
-    popArray.add("ProofOfProvisioning")
-            .add(docType_)
-            .add(std::move(signedDataAccessControlProfiles_))
-            .add(std::move(signedDataNamespaces_))
-            .add(testCredential_);
-    vector<uint8_t> encodedCbor = popArray.encode();
-
-    optional<vector<uint8_t>> signature = support::coseSignEcDsa(credentialPrivKey_,
-                                                                 encodedCbor,  // payload
-                                                                 {},           // additionalData
-                                                                 {});          // certificateChain
-    if (!signature) {
-        _hidl_cb(support::result(ResultCode::FAILED, "Error signing data"), {}, {});
-        return Void();
-    }
-
-    vector<uint8_t> credentialKeys;
-    if (!generateCredentialKeys(storageKey_, credentialPrivKey_, credentialKeys)) {
-        _hidl_cb(support::result(ResultCode::FAILED, "Error generating CredentialKeys"), {}, {});
-        return Void();
-    }
-
-    vector<uint8_t> credentialData;
-    if (!generateCredentialData(testCredential_ ? support::getTestHardwareBoundKey()
-                                                : support::getHardwareBoundKey(),
-                                docType_, testCredential_, credentialKeys, credentialData)) {
-        _hidl_cb(support::result(ResultCode::FAILED, "Error generating CredentialData"), {}, {});
-        return Void();
-    }
-
-    _hidl_cb(support::resultOK(), credentialData, signature.value());
-    return Void();
-}
-
-}  // namespace implementation
-}  // namespace identity
-}  // namespace hardware
-}  // namespace android
diff --git a/identity/1.0/default/WritableIdentityCredential.h b/identity/1.0/default/WritableIdentityCredential.h
deleted file mode 100644
index 9f4e303..0000000
--- a/identity/1.0/default/WritableIdentityCredential.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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 ANDROID_HARDWARE_IDENTITY_WRITABLEIDENTITYCREDENTIAL_H
-#define ANDROID_HARDWARE_IDENTITY_WRITABLEIDENTITYCREDENTIAL_H
-
-#include <android/hardware/identity/1.0/IWritableIdentityCredential.h>
-
-#include <android/hardware/identity/support/IdentityCredentialSupport.h>
-
-#include <cppbor.h>
-
-namespace android {
-namespace hardware {
-namespace identity {
-namespace implementation {
-
-using ::std::string;
-using ::std::vector;
-
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::identity::V1_0::IWritableIdentityCredential;
-using ::android::hardware::identity::V1_0::Result;
-using ::android::hardware::identity::V1_0::ResultCode;
-using ::android::hardware::identity::V1_0::SecureAccessControlProfile;
-
-class WritableIdentityCredential : public IWritableIdentityCredential {
-  public:
-    WritableIdentityCredential(const hidl_string& docType, bool testCredential)
-        : docType_(docType), testCredential_(testCredential) {}
-
-    // Creates the Credential Key. Returns false on failure. Must be called
-    // right after construction.
-    bool initialize();
-
-    // Methods from ::android::hardware::identity::IWritableIdentityCredential
-    // follow.
-    Return<void> getAttestationCertificate(const hidl_vec<uint8_t>& attestationChallenge,
-                                           getAttestationCertificate_cb _hidl_cb) override;
-
-    Return<void> startPersonalization(uint16_t accessControlProfileCount,
-                                      const hidl_vec<uint16_t>& entryCounts,
-                                      startPersonalization_cb _hidl_cb) override;
-
-    Return<void> addAccessControlProfile(uint16_t id, const hidl_vec<uint8_t>& readerCertificate,
-                                         bool userAuthenticationRequired, uint64_t timeoutMillis,
-                                         uint64_t secureUserId,
-                                         addAccessControlProfile_cb _hidl_cb) override;
-
-    Return<void> beginAddEntry(const hidl_vec<uint16_t>& accessControlProfileIds,
-                               const hidl_string& nameSpace, const hidl_string& name,
-                               uint32_t entrySize, beginAddEntry_cb _hidl_cb) override;
-
-    Return<void> addEntryValue(const hidl_vec<uint8_t>& content,
-                               addEntryValue_cb _hidl_cb) override;
-
-    Return<void> finishAddingEntries(finishAddingEntries_cb _hidl_cb) override;
-
-  private:
-    string docType_;
-    bool testCredential_;
-
-    // These are set in initialize().
-    vector<uint8_t> storageKey_;
-    vector<uint8_t> credentialPrivKey_;
-    vector<uint8_t> credentialPubKey_;
-
-    // These fields are initialized during startPersonalization()
-    size_t numAccessControlProfileRemaining_;
-    vector<uint16_t> remainingEntryCounts_;
-    cppbor::Array signedDataAccessControlProfiles_;
-    cppbor::Map signedDataNamespaces_;
-    cppbor::Array signedDataCurrentNamespace_;
-
-    // These fields are initialized during beginAddEntry()
-    size_t entryRemainingBytes_;
-    vector<uint8_t> entryAdditionalData_;
-    string entryNameSpace_;
-    string entryName_;
-    vector<uint16_t> entryAccessControlProfileIds_;
-    vector<uint8_t> entryBytes_;
-};
-
-}  // namespace implementation
-}  // namespace identity
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_IDENTITY_WRITABLEIDENTITYCREDENTIAL_H
diff --git a/identity/1.0/default/android.hardware.identity@1.0-service.example.rc b/identity/1.0/default/android.hardware.identity@1.0-service.example.rc
deleted file mode 100644
index 1eb7319..0000000
--- a/identity/1.0/default/android.hardware.identity@1.0-service.example.rc
+++ /dev/null
@@ -1,3 +0,0 @@
-service vendor.identity-1-0 /vendor/bin/hw/android.hardware.identity@1.0-service.example
-    class hal
-    user nobody
diff --git a/identity/1.0/default/service.cpp b/identity/1.0/default/service.cpp
deleted file mode 100644
index 839e803..0000000
--- a/identity/1.0/default/service.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.
- */
-
-#define LOG_TAG "android.hardware.identity@1.0-service"
-
-#include <android-base/logging.h>
-#include <hidl/HidlTransportSupport.h>
-
-#include "IdentityCredentialStore.h"
-
-using android::hardware::joinRpcThreadpool;
-using android::hardware::identity::implementation::IdentityCredentialStore;
-
-int main(int /* argc */, char* argv[]) {
-    ::android::hardware::configureRpcThreadpool(1, true /*willJoinThreadpool*/);
-
-    ::android::base::InitLogging(argv, &android::base::StderrLogger);
-
-    auto identity_store = new IdentityCredentialStore();
-    auto status = identity_store->registerAsService();
-    if (status != android::OK) {
-        LOG(FATAL) << "Could not register service for IdentityCredentialStore 1.0 (" << status
-                   << ")";
-    }
-    joinRpcThreadpool();
-    return -1;  // Should never get here.
-}
diff --git a/identity/1.0/types.hal b/identity/1.0/types.hal
deleted file mode 100644
index 5aedfea..0000000
--- a/identity/1.0/types.hal
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.identity@1.0;
-
-/**
- * The ResultCode enumeration is used to convey the status of an operation.
- */
-enum ResultCode : int32_t {
-    /**
-     * Success.
-     */
-    OK = 0,
-
-    /**
-     * The operation failed. This is used as a generic catch-all for errors that don't belong
-     * in other categories, including memory/resource allocation failures and I/O errors.
-     */
-    FAILED = 1,
-
-    /**
-     * The passed data was invalid. This is a generic catch all for errors that don't belong
-     * in other categories related to parameter validation.
-     */
-    INVALID_DATA = 2,
-
-    /**
-     * The authToken parameter passed to IIdentityCredential.startRetrieval() is not valid.
-     */
-    INVALID_AUTH_TOKEN = 3,
-
-    /**
-     * The itemsRequest parameter passed to IIdentityCredential.startRetrieval() does not meet
-     * the requirements described in the documentation for that method.
-     */
-    INVALID_ITEMS_REQUEST_MESSAGE = 4,
-
-    /**
-     * The readerSignature parameter in IIdentityCredential.startRetrieval() is invalid,
-     * doesn't contain an embedded certificate chain, or the signature failed to
-     * validate.
-     */
-    READER_SIGNATURE_CHECK_FAILED = 5,
-
-    /**
-     * The sessionTranscript passed to startRetrieval() did not contain the ephmeral public
-     * key returned by createEphemeralPublicKey().
-     */
-    EPHEMERAL_PUBLIC_KEY_NOT_FOUND = 6,
-
-    /**
-     * An access condition related to user authentication was not satisfied.
-     */
-    USER_AUTHENTICATION_FAILED = 7,
-
-    /**
-     * An access condition related to reader authentication was not satisfied.
-     */
-    READER_AUTHENTICATION_FAILED = 8,
-
-    /**
-    * The request data element has no access control profiles associated so it cannot be accessed.
-    */
-    NO_ACCESS_CONTROL_PROFILES = 9,
-
-    /**
-     * The requested data element is not in the provided non-empty itemsRequest message.
-     */
-    NOT_IN_REQUEST_MESSAGE = 10,
-
-    /**
-     * The passed-in sessionTranscript doesn't match the previously passed-in sessionTranscript.
-     */
-    SESSION_TRANSCRIPT_MISMATCH = 11,
-};
-
-/**
- * A result has a ResultCode and corresponding textual message.
- */
-struct Result {
-    /**
-     * The result code.
-     *
-     * Implementations must not use values not defined in the ResultCode enumeration.
-     */
-    ResultCode code;
-
-    /**
-     * A human-readable message in English conveying more detail about a failure.
-     *
-     * If code is ResultCode::OK this field must be set to the empty string.
-     */
-    string message;
-};
-
-struct SecureAccessControlProfile {
-    /**
-     * id is a numeric identifier that must be unique within the context of a Credential and may be
-     * used to reference the profile.
-     */
-    uint16_t id;
-
-    /**
-     * readerCertificate, if non-empty, specifies a single X.509 certificate (not a chain
-     * of certificates) that must be used to authenticate requests. For details about how
-     * this is done, see the readerSignature paremter of IIdentityCredential.startRetrieval.
-     */
-    vec<uint8_t> readerCertificate;
-
-    /**
-     * if true, the user is required to authenticate to allow requests.  Required authentication
-     * fressness is specified by timeout below.
-     *
-     */
-    bool userAuthenticationRequired;
-
-    /**
-     * Timeout specifies the amount of time, in milliseconds, for which a user authentication (see
-     * above) is valid, if userAuthenticationRequired is set to true.  If userAuthenticationRequired
-     * is true and timout is zero then authentication is required for each reader session.
-     *
-     * If userAuthenticationRequired is false, timeout must be zero.
-     */
-    uint64_t timeoutMillis;
-
-    /**
-     * secureUserId must be non-zero if userAuthenticationRequired is true.
-     * It is not related to any Android user ID or UID, but is created in the
-     * Gatekeeper application in the secure environment.
-     */
-    uint64_t secureUserId;
-
-    /**
-     * The mac is used to authenticate the access control profile.  It contains:
-     *
-     *      AES-GCM-ENC(storageKey, R, {}, AccessControlProfile)
-     *
-     *  where AccessControlProfile is the CBOR map:
-     *
-     *      AccessControlProfile = {
-     *          "id": uint,
-     *          ? "readerCertificate" : bstr,
-     *          ? (
-     *              "userAuthenticationRequired" : bool,
-     *              "timeoutMillis" : uint,
-     *              "secureUserId" : uint
-     *          )
-     *      }
-     */
-    vec<uint8_t> mac;
-};
diff --git a/identity/1.0/vts/functional/VtsHalIdentityCredentialTargetTest.cpp b/identity/1.0/vts/functional/VtsHalIdentityCredentialTargetTest.cpp
deleted file mode 100644
index 903e912..0000000
--- a/identity/1.0/vts/functional/VtsHalIdentityCredentialTargetTest.cpp
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "IdentityCredentialHidlHalTest"
-
-#include <map>
-
-#include <android-base/logging.h>
-#include <android/hardware/identity/1.0/IIdentityCredentialStore.h>
-#include <android/hardware/identity/1.0/types.h>
-#include <android/hardware/identity/support/IdentityCredentialSupport.h>
-
-#include <cppbor.h>
-#include <cppbor_parse.h>
-#include <gtest/gtest.h>
-#include <hidl/GtestPrinter.h>
-#include <hidl/ServiceManagement.h>
-
-using std::map;
-using std::optional;
-using std::string;
-using std::vector;
-
-namespace android {
-namespace hardware {
-namespace identity {
-namespace test {
-
-using ::android::hardware::identity::V1_0::IIdentityCredential;
-using ::android::hardware::identity::V1_0::IIdentityCredentialStore;
-using ::android::hardware::identity::V1_0::IWritableIdentityCredential;
-using ::android::hardware::identity::V1_0::Result;
-using ::android::hardware::identity::V1_0::ResultCode;
-using ::android::hardware::identity::V1_0::SecureAccessControlProfile;
-using ::android::hardware::keymaster::V4_0::HardwareAuthToken;
-
-// ---------------------------------------------------------------------------
-// Test Data.
-// ---------------------------------------------------------------------------
-
-struct TestEntryData {
-    TestEntryData(string nameSpace, string name, vector<uint16_t> profileIds)
-        : nameSpace(nameSpace), name(name), profileIds(profileIds) {}
-
-    TestEntryData(string nameSpace, string name, const string& value, vector<uint16_t> profileIds)
-        : TestEntryData(nameSpace, name, profileIds) {
-        valueCbor = cppbor::Tstr(((const char*)value.data())).encode();
-    }
-    TestEntryData(string nameSpace, string name, const vector<uint8_t>& value,
-                  vector<uint16_t> profileIds)
-        : TestEntryData(nameSpace, name, profileIds) {
-        valueCbor = cppbor::Bstr(value).encode();
-    }
-    TestEntryData(string nameSpace, string name, bool value, vector<uint16_t> profileIds)
-        : TestEntryData(nameSpace, name, profileIds) {
-        valueCbor = cppbor::Bool(value).encode();
-    }
-    TestEntryData(string nameSpace, string name, int64_t value, vector<uint16_t> profileIds)
-        : TestEntryData(nameSpace, name, profileIds) {
-        if (value >= 0) {
-            valueCbor = cppbor::Uint(value).encode();
-        } else {
-            valueCbor = cppbor::Nint(-value).encode();
-        }
-    }
-
-    string nameSpace;
-    string name;
-    vector<uint8_t> valueCbor;
-    vector<uint16_t> profileIds;
-};
-
-struct TestProfile {
-    uint16_t id;
-    hidl_vec<uint8_t> readerCertificate;
-    bool userAuthenticationRequired;
-    uint64_t timeoutMillis;
-};
-
-/************************************
- *   TEST DATA FOR AUTHENTICATION
- ************************************/
-// Test authentication token for user authentication
-
-class IdentityCredentialStoreHidlTest : public ::testing::TestWithParam<std::string> {
-  public:
-    virtual void SetUp() override {
-        string serviceName = GetParam();
-        ASSERT_FALSE(serviceName.empty());
-        credentialStore_ = IIdentityCredentialStore::getService(serviceName);
-        ASSERT_NE(credentialStore_, nullptr);
-
-        credentialStore_->getHardwareInformation(
-                [&](const Result& result, const hidl_string& credentialStoreName,
-                    const hidl_string& credentialStoreAuthorName, uint32_t chunkSize,
-                    bool /* isDirectAccess */,
-                    const hidl_vec<hidl_string> /* supportedDocTypes */) {
-                    EXPECT_EQ("", result.message);
-                    ASSERT_EQ(ResultCode::OK, result.code);
-                    ASSERT_GT(credentialStoreName.size(), 0u);
-                    ASSERT_GT(credentialStoreAuthorName.size(), 0u);
-                    ASSERT_GE(chunkSize, 256u);  // Chunk sizes < APDU buffer won't be supported
-                    dataChunkSize_ = chunkSize;
-                });
-    }
-    virtual void TearDown() override {}
-
-    uint32_t dataChunkSize_ = 0;
-
-    sp<IIdentityCredentialStore> credentialStore_;
-};
-
-TEST_P(IdentityCredentialStoreHidlTest, HardwareConfiguration) {
-    credentialStore_->getHardwareInformation(
-            [&](const Result& result, const hidl_string& credentialStoreName,
-                const hidl_string& credentialStoreAuthorName, uint32_t chunkSize,
-                bool /* isDirectAccess */, const hidl_vec<hidl_string> /* supportedDocTypes */) {
-                EXPECT_EQ("", result.message);
-                ASSERT_EQ(ResultCode::OK, result.code);
-                ASSERT_GT(credentialStoreName.size(), 0u);
-                ASSERT_GT(credentialStoreAuthorName.size(), 0u);
-                ASSERT_GE(chunkSize, 256u);  // Chunk sizes < APDU buffer won't be supported
-            });
-}
-
-TEST_P(IdentityCredentialStoreHidlTest, createAndRetrieveCredential) {
-    // First, generate a key-pair for the reader since its public key will be
-    // part of the request data.
-    optional<vector<uint8_t>> readerKeyPKCS8 = support::createEcKeyPair();
-    ASSERT_TRUE(readerKeyPKCS8);
-    optional<vector<uint8_t>> readerPublicKey =
-            support::ecKeyPairGetPublicKey(readerKeyPKCS8.value());
-    optional<vector<uint8_t>> readerKey = support::ecKeyPairGetPrivateKey(readerKeyPKCS8.value());
-    string serialDecimal = "1234";
-    string issuer = "Android Open Source Project";
-    string subject = "Android IdentityCredential VTS Test";
-    time_t validityNotBefore = time(nullptr);
-    time_t validityNotAfter = validityNotBefore + 365 * 24 * 3600;
-    optional<vector<uint8_t>> readerCertificate = support::ecPublicKeyGenerateCertificate(
-            readerPublicKey.value(), readerKey.value(), serialDecimal, issuer, subject,
-            validityNotBefore, validityNotAfter);
-    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;
-    portraitImage.resize(256 * 1024 - 10);
-    for (size_t n = 0; n < portraitImage.size(); n++) {
-        portraitImage[n] = (uint8_t)n;
-    }
-
-    // Access control profiles:
-    const vector<TestProfile> testProfiles = {// Profile 0 (reader authentication)
-                                              {0, readerCertificate.value(), false, 0},
-                                              // Profile 1 (no authentication)
-                                              {1, {}, false, 0}};
-
-    HardwareAuthToken authToken = {};
-
-    // Here's the actual test data:
-    const vector<TestEntryData> testEntries = {
-            {"PersonalData", "Last name", string("Turing"), vector<uint16_t>{0, 1}},
-            {"PersonalData", "Birth date", string("19120623"), vector<uint16_t>{0, 1}},
-            {"PersonalData", "First name", string("Alan"), vector<uint16_t>{0, 1}},
-            {"PersonalData", "Home address", string("Maida Vale, London, England"),
-             vector<uint16_t>{0}},
-            {"Image", "Portrait image", portraitImage, vector<uint16_t>{0, 1}},
-    };
-    const vector<uint16_t> testEntriesEntryCounts = {static_cast<uint16_t>(testEntries.size() - 1),
-                                                     1u};
-
-    string cborPretty;
-    sp<IWritableIdentityCredential> writableCredential;
-
-    hidl_vec<uint8_t> empty{0};
-
-    string docType = "org.iso.18013-5.2019.mdl";
-    bool testCredential = true;
-    Result result;
-    credentialStore_->createCredential(
-            docType, testCredential,
-            [&](const Result& _result, const sp<IWritableIdentityCredential>& _writableCredential) {
-                result = _result;
-                writableCredential = _writableCredential;
-            });
-    EXPECT_EQ("", result.message);
-    ASSERT_EQ(ResultCode::OK, result.code);
-    ASSERT_NE(writableCredential, nullptr);
-
-    string challenge = "attestationChallenge";
-    vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
-    vector<uint8_t> attestationCertificate;
-    writableCredential->getAttestationCertificate(
-            attestationChallenge,
-            [&](const Result& _result, const hidl_vec<uint8_t>& _attestationCertificate) {
-                result = _result;
-                attestationCertificate = _attestationCertificate;
-            });
-    EXPECT_EQ("", result.message);
-    ASSERT_EQ(ResultCode::OK, result.code);
-
-    writableCredential->startPersonalization(testProfiles.size(), testEntriesEntryCounts,
-                                             [&](const Result& _result) { result = _result; });
-    EXPECT_EQ("", result.message);
-    ASSERT_EQ(ResultCode::OK, result.code);
-
-    vector<SecureAccessControlProfile> returnedSecureProfiles;
-    for (const auto& testProfile : testProfiles) {
-        SecureAccessControlProfile profile;
-        writableCredential->addAccessControlProfile(
-                testProfile.id, testProfile.readerCertificate,
-                testProfile.userAuthenticationRequired, testProfile.timeoutMillis,
-                0,  // secureUserId
-                [&](const Result& _result, const SecureAccessControlProfile& _profile) {
-                    result = _result;
-                    profile = _profile;
-                });
-        EXPECT_EQ("", result.message);
-        ASSERT_EQ(ResultCode::OK, result.code);
-        ASSERT_EQ(testProfile.id, profile.id);
-        ASSERT_EQ(testProfile.readerCertificate, profile.readerCertificate);
-        ASSERT_EQ(testProfile.userAuthenticationRequired, profile.userAuthenticationRequired);
-        ASSERT_EQ(testProfile.timeoutMillis, profile.timeoutMillis);
-        ASSERT_EQ(support::kAesGcmTagSize + support::kAesGcmIvSize, profile.mac.size());
-        returnedSecureProfiles.push_back(profile);
-    }
-
-    // Uses TestEntryData* pointer as key and values are the encrypted blobs. This
-    // is a little hacky but it works well enough.
-    map<const TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
-
-    for (const auto& entry : testEntries) {
-        vector<vector<uint8_t>> chunks = support::chunkVector(entry.valueCbor, dataChunkSize_);
-
-        writableCredential->beginAddEntry(entry.profileIds, entry.nameSpace, entry.name,
-                                          entry.valueCbor.size(),
-                                          [&](const Result& _result) { result = _result; });
-        EXPECT_EQ("", result.message);
-        ASSERT_EQ(ResultCode::OK, result.code);
-
-        vector<vector<uint8_t>> encryptedChunks;
-        for (const auto& chunk : chunks) {
-            writableCredential->addEntryValue(
-                    chunk, [&](const Result& result, hidl_vec<uint8_t> encryptedContent) {
-                        EXPECT_EQ("", result.message);
-                        ASSERT_EQ(ResultCode::OK, result.code);
-                        ASSERT_GT(encryptedContent.size(), 0u);
-                        encryptedChunks.push_back(encryptedContent);
-                    });
-        }
-        encryptedBlobs[&entry] = encryptedChunks;
-    }
-
-    vector<uint8_t> credentialData;
-    vector<uint8_t> proofOfProvisioningSignature;
-    writableCredential->finishAddingEntries(
-            [&](const Result& _result, const hidl_vec<uint8_t>& _credentialData,
-                const hidl_vec<uint8_t>& _proofOfProvisioningSignature) {
-                result = _result;
-                credentialData = _credentialData;
-                proofOfProvisioningSignature = _proofOfProvisioningSignature;
-            });
-    EXPECT_EQ("", result.message);
-    ASSERT_EQ(ResultCode::OK, result.code);
-
-    optional<vector<uint8_t>> proofOfProvisioning =
-            support::coseSignGetPayload(proofOfProvisioningSignature);
-    ASSERT_TRUE(proofOfProvisioning);
-    cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
-    EXPECT_EQ(
-            "[\n"
-            "  'ProofOfProvisioning',\n"
-            "  'org.iso.18013-5.2019.mdl',\n"
-            "  [\n"
-            "    {\n"
-            "      'id' : 0,\n"
-            "      'readerCertificate' : <not printed>,\n"
-            "    },\n"
-            "    {\n"
-            "      'id' : 1,\n"
-            "    },\n"
-            "  ],\n"
-            "  {\n"
-            "    'PersonalData' : [\n"
-            "      {\n"
-            "        'name' : 'Last name',\n"
-            "        'value' : 'Turing',\n"
-            "        'accessControlProfiles' : [0, 1, ],\n"
-            "      },\n"
-            "      {\n"
-            "        'name' : 'Birth date',\n"
-            "        'value' : '19120623',\n"
-            "        'accessControlProfiles' : [0, 1, ],\n"
-            "      },\n"
-            "      {\n"
-            "        'name' : 'First name',\n"
-            "        'value' : 'Alan',\n"
-            "        'accessControlProfiles' : [0, 1, ],\n"
-            "      },\n"
-            "      {\n"
-            "        'name' : 'Home address',\n"
-            "        'value' : 'Maida Vale, London, England',\n"
-            "        'accessControlProfiles' : [0, ],\n"
-            "      },\n"
-            "    ],\n"
-            "    'Image' : [\n"
-            "      {\n"
-            "        'name' : 'Portrait image',\n"
-            "        'value' : <bstr size=262134 sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
-            "        'accessControlProfiles' : [0, 1, ],\n"
-            "      },\n"
-            "    ],\n"
-            "  },\n"
-            "  true,\n"
-            "]",
-            cborPretty);
-
-    optional<vector<uint8_t>> credentialPubKey =
-            support::certificateChainGetTopMostKey(attestationCertificate);
-    ASSERT_TRUE(credentialPubKey);
-    EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
-                                                 {},  // Additional data
-                                                 credentialPubKey.value()));
-    writableCredential = nullptr;
-
-    // Now that the credential has been provisioned, read it back and check the
-    // correct data is returned.
-    sp<IIdentityCredential> credential;
-    credentialStore_->getCredential(
-            credentialData, [&](const Result& _result, const sp<IIdentityCredential>& _credential) {
-                result = _result;
-                credential = _credential;
-            });
-    EXPECT_EQ("", result.message);
-    ASSERT_EQ(ResultCode::OK, result.code);
-    ASSERT_NE(credential, nullptr);
-
-    optional<vector<uint8_t>> readerEphemeralKeyPair = support::createEcKeyPair();
-    ASSERT_TRUE(readerEphemeralKeyPair);
-    optional<vector<uint8_t>> readerEphemeralPublicKey =
-            support::ecKeyPairGetPublicKey(readerEphemeralKeyPair.value());
-    credential->setReaderEphemeralPublicKey(readerEphemeralPublicKey.value(),
-                                            [&](const Result& _result) { result = _result; });
-    EXPECT_EQ("", result.message);
-    ASSERT_EQ(ResultCode::OK, result.code);
-
-    vector<uint8_t> ephemeralKeyPair;
-    credential->createEphemeralKeyPair(
-            [&](const Result& _result, const hidl_vec<uint8_t>& _ephemeralKeyPair) {
-                result = _result;
-                ephemeralKeyPair = _ephemeralKeyPair;
-            });
-    EXPECT_EQ("", result.message);
-    ASSERT_EQ(ResultCode::OK, result.code);
-    optional<vector<uint8_t>> ephemeralPublicKey = support::ecKeyPairGetPublicKey(ephemeralKeyPair);
-
-    // Calculate requestData field and sign it with the reader key.
-    auto [getXYSuccess, ephX, ephY] = support::ecPublicKeyGetXandY(ephemeralPublicKey.value());
-    ASSERT_TRUE(getXYSuccess);
-    cppbor::Map deviceEngagement = cppbor::Map().add("ephX", ephX).add("ephY", ephY);
-    vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
-    vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
-    cppbor::Array sessionTranscript = cppbor::Array()
-                                              .add(cppbor::Semantic(24, deviceEngagementBytes))
-                                              .add(cppbor::Semantic(24, eReaderPubBytes));
-    vector<uint8_t> sessionTranscriptBytes = sessionTranscript.encode();
-
-    vector<uint8_t> itemsRequestBytes =
-            cppbor::Map("nameSpaces",
-                        cppbor::Map()
-                                .add("PersonalData", cppbor::Map()
-                                                             .add("Last name", false)
-                                                             .add("Birth date", false)
-                                                             .add("First name", false)
-                                                             .add("Home address", true))
-                                .add("Image", cppbor::Map().add("Portrait image", false)))
-                    .encode();
-    cborPretty = support::cborPrettyPrint(itemsRequestBytes, 32, {"EphemeralPublicKey"});
-    EXPECT_EQ(
-            "{\n"
-            "  'nameSpaces' : {\n"
-            "    'PersonalData' : {\n"
-            "      'Last name' : false,\n"
-            "      'Birth date' : false,\n"
-            "      'First name' : false,\n"
-            "      'Home address' : true,\n"
-            "    },\n"
-            "    'Image' : {\n"
-            "      'Portrait image' : false,\n"
-            "    },\n"
-            "  },\n"
-            "}",
-            cborPretty);
-    vector<uint8_t> dataToSign = cppbor::Array()
-                                         .add("ReaderAuthentication")
-                                         .add(sessionTranscript.clone())
-                                         .add(cppbor::Semantic(24, itemsRequestBytes))
-                                         .encode();
-    optional<vector<uint8_t>> readerSignature =
-            support::coseSignEcDsa(readerKey.value(), {},  // content
-                                   dataToSign,             // detached content
-                                   readerCertificate.value());
-    ASSERT_TRUE(readerSignature);
-
-    credential->startRetrieval(returnedSecureProfiles, authToken, itemsRequestBytes,
-                               sessionTranscriptBytes, readerSignature.value(),
-                               testEntriesEntryCounts,
-                               [&](const Result& _result) { result = _result; });
-    EXPECT_EQ("", result.message);
-    ASSERT_EQ(ResultCode::OK, result.code);
-
-    for (const auto& entry : testEntries) {
-        credential->startRetrieveEntryValue(entry.nameSpace, entry.name, entry.valueCbor.size(),
-                                            entry.profileIds,
-                                            [&](const Result& _result) { result = _result; });
-        EXPECT_EQ("", result.message);
-        ASSERT_EQ(ResultCode::OK, result.code);
-
-        auto it = encryptedBlobs.find(&entry);
-        ASSERT_NE(it, encryptedBlobs.end());
-        const vector<vector<uint8_t>>& encryptedChunks = it->second;
-
-        vector<uint8_t> content;
-        for (const auto& encryptedChunk : encryptedChunks) {
-            vector<uint8_t> chunk;
-            credential->retrieveEntryValue(
-                    encryptedChunk, [&](const Result& _result, const hidl_vec<uint8_t>& _chunk) {
-                        result = _result;
-                        chunk = _chunk;
-                    });
-            EXPECT_EQ("", result.message);
-            ASSERT_EQ(ResultCode::OK, result.code);
-            content.insert(content.end(), chunk.begin(), chunk.end());
-        }
-        EXPECT_EQ(content, entry.valueCbor);
-    }
-
-    // Generate the key that will be used to sign AuthenticatedData.
-    vector<uint8_t> signingKeyBlob;
-    vector<uint8_t> signingKeyCertificate;
-    credential->generateSigningKeyPair([&](const Result& _result,
-                                           const hidl_vec<uint8_t> _signingKeyBlob,
-                                           const hidl_vec<uint8_t> _signingKeyCertificate) {
-        result = _result;
-        signingKeyBlob = _signingKeyBlob;
-        signingKeyCertificate = _signingKeyCertificate;
-    });
-    EXPECT_EQ("", result.message);
-    ASSERT_EQ(ResultCode::OK, result.code);
-
-    vector<uint8_t> mac;
-    vector<uint8_t> deviceNameSpacesBytes;
-    credential->finishRetrieval(signingKeyBlob,
-                                [&](const Result& _result, const hidl_vec<uint8_t> _mac,
-                                    const hidl_vec<uint8_t> _deviceNameSpacesBytes) {
-                                    result = _result;
-                                    mac = _mac;
-                                    deviceNameSpacesBytes = _deviceNameSpacesBytes;
-                                });
-    EXPECT_EQ("", result.message);
-    ASSERT_EQ(ResultCode::OK, result.code);
-    cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 32, {});
-    ASSERT_EQ(
-            "{\n"
-            "  'PersonalData' : {\n"
-            "    'Last name' : 'Turing',\n"
-            "    'Birth date' : '19120623',\n"
-            "    'First name' : 'Alan',\n"
-            "    'Home address' : 'Maida Vale, London, England',\n"
-            "  },\n"
-            "  'Image' : {\n"
-            "    'Portrait image' : <bstr size=262134 "
-            "sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
-            "  },\n"
-            "}",
-            cborPretty);
-    // The data that is MACed is ["DeviceAuthentication", sessionTranscriptBytes, docType,
-    // deviceNameSpacesBytes] so build up that structure
-    cppbor::Array deviceAuthentication;
-    deviceAuthentication.add("DeviceAuthentication");
-    deviceAuthentication.add(sessionTranscript.clone());
-    deviceAuthentication.add(docType);
-    deviceAuthentication.add(cppbor::Semantic(24, deviceNameSpacesBytes));
-    vector<uint8_t> encodedDeviceAuthentication = deviceAuthentication.encode();
-    optional<vector<uint8_t>> signingPublicKey =
-            support::certificateChainGetTopMostKey(signingKeyCertificate);
-    EXPECT_TRUE(signingPublicKey);
-
-    // Derive the key used for MACing.
-    optional<vector<uint8_t>> readerEphemeralPrivateKey =
-            support::ecKeyPairGetPrivateKey(readerEphemeralKeyPair.value());
-    optional<vector<uint8_t>> sharedSecret =
-            support::ecdh(signingPublicKey.value(), readerEphemeralPrivateKey.value());
-    ASSERT_TRUE(sharedSecret);
-    vector<uint8_t> salt = {0x00};
-    vector<uint8_t> info = {};
-    optional<vector<uint8_t>> derivedKey = support::hkdf(sharedSecret.value(), salt, info, 32);
-    ASSERT_TRUE(derivedKey);
-    optional<vector<uint8_t>> calculatedMac =
-            support::coseMac0(derivedKey.value(), {},        // payload
-                              encodedDeviceAuthentication);  // detached content
-    ASSERT_TRUE(calculatedMac);
-    EXPECT_EQ(mac, calculatedMac);
-}
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, IdentityCredentialStoreHidlTest,
-                         testing::ValuesIn(android::hardware::getAllHalInstanceNames(
-                                 IIdentityCredentialStore::descriptor)),
-                         android::hardware::PrintInstanceNameToString);
-
-}  // namespace test
-}  // namespace identity
-}  // namespace hardware
-}  // namespace android
diff --git a/identity/1.0/vts/OWNERS b/identity/OWNERS
similarity index 100%
rename from identity/1.0/vts/OWNERS
rename to identity/OWNERS
diff --git a/identity/aidl/Android.bp b/identity/aidl/Android.bp
new file mode 100644
index 0000000..72b19a1
--- /dev/null
+++ b/identity/aidl/Android.bp
@@ -0,0 +1,21 @@
+aidl_interface {
+    name: "android.hardware.identity",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/identity/*.aidl",
+    ],
+    imports: [
+        "android.hardware.keymaster",
+    ],
+    stability: "vintf",
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
diff --git a/radio/config/1.3/IRadioConfigIndication.hal b/identity/aidl/android/hardware/identity/Certificate.aidl
similarity index 63%
copy from radio/config/1.3/IRadioConfigIndication.hal
copy to identity/aidl/android/hardware/identity/Certificate.aidl
index 9ef496c..5bbc17c 100644
--- a/radio/config/1.3/IRadioConfigIndication.hal
+++ b/identity/aidl/android/hardware/identity/Certificate.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,13 +14,14 @@
  * limitations under the License.
  */
 
-package android.hardware.radio.config@1.3;
+package android.hardware.identity;
 
-import @1.2::IRadioConfigIndication;
-
-/**
- * Interface declaring unsolicited radio config indications.
- */
-interface IRadioConfigIndication extends @1.2::IRadioConfigIndication {
-
-};
+@VintfStability
+parcelable Certificate {
+    /**
+     * encodedCertificate contains the bytes of a DER-encoded X.509 certificate.
+     *
+     * If there is no certificate, this array is empty.
+     */
+    byte[] encodedCertificate;
+}
diff --git a/identity/aidl/android/hardware/identity/CipherSuite.aidl b/identity/aidl/android/hardware/identity/CipherSuite.aidl
new file mode 100644
index 0000000..20b02a8
--- /dev/null
+++ b/identity/aidl/android/hardware/identity/CipherSuite.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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;
+
+/**
+ * Cipher suites that can be used for communication between holder and reader devices.
+ */
+@VintfStability
+@Backing(type="int")
+enum CipherSuite {
+    /**
+     * Specifies that the cipher suite that will be used to secure communications between the reader
+     * is:
+     *
+     * - ECDHE with HKDF-SHA-256 for key agreement.
+     * - AES-256 with GCM block mode for authenticated encryption (nonces are incremented by
+     *   one for every message).
+     * - ECDSA with SHA-256 for signing (used for signing session transcripts to defeat
+     *   man-in-the-middle attacks), signing keys are not ephemeral.
+     *
+     * At present this is the only supported cipher suite and it is mandatory for all
+     * implementations to support it.
+     */
+    CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 = 1,
+}
diff --git a/identity/aidl/android/hardware/identity/HardwareInformation.aidl b/identity/aidl/android/hardware/identity/HardwareInformation.aidl
new file mode 100644
index 0000000..d67739d
--- /dev/null
+++ b/identity/aidl/android/hardware/identity/HardwareInformation.aidl
@@ -0,0 +1,54 @@
+/*
+ * 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 HardwareInformation {
+    /**
+     * credentialStoreName is the name of the credential store implementation.
+     */
+    @utf8InCpp String credentialStoreName;
+
+    /**
+     * credentialStoreAuthorName is the name of the credential store author.
+     */
+    @utf8InCpp String credentialStoreAuthorName;
+
+    /**
+     * dataChunkSize is the size of data chunks to be used when sending and recieving data
+     * entries. All data chunks for a data item must be this size except for the last.
+     */
+    int dataChunkSize;
+
+    /**
+     * isDirectAccess specifies whether the provisioned credential is available through
+     * direct access. Credentials provisioned in credential stores with this set
+     * to true, should use reader authentication on all data elements.
+     */
+    boolean isDirectAccess;
+
+    /**
+     * supportedDocTypes if empty, then any document type is supported, otherwise
+     * only the document types returned are supported.
+     *
+     * Document types are defined in the relevant standard for the document, for example for the
+     * for Mobile Driving License as defined by ISO 18013-5 the document type is defined to
+     * be "org.iso.18013.5.1.mDL".
+     *
+     */
+    @utf8InCpp String[] supportedDocTypes;
+}
diff --git a/identity/1.0/IIdentityCredential.hal b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
similarity index 75%
rename from identity/1.0/IIdentityCredential.hal
rename to identity/aidl/android/hardware/identity/IIdentityCredential.aidl
index 75f6e18..cc14271 100644
--- a/identity/1.0/IIdentityCredential.hal
+++ b/identity/aidl/android/hardware/identity/IIdentityCredential.aidl
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
-package android.hardware.identity@1.0;
+package android.hardware.identity;
 
-import android.hardware.keymaster@4.0::HardwareAuthToken;
+import android.hardware.identity.Certificate;
+import android.hardware.identity.SecureAccessControlProfile;
+import android.hardware.keymaster.HardwareAuthToken;
 
+@VintfStability
 interface IIdentityCredential {
     /**
      * Delete a credential.
@@ -35,10 +38,9 @@
      * After this method has been called, the persistent storage used for credentialData should
      * be deleted.
      *
-     * @return proofOfDeletionSignature is a COSE_Sign1 signature described above.
+     * @return a COSE_Sign1 signature described above.
      */
-    deleteCredential()
-        generates(Result result, vec<uint8_t> proofOfDeletionSignature);
+    byte[] deleteCredential();
 
     /**
      * Creates an ephemeral EC key pair, for use in establishing a seceure session with a reader.
@@ -46,39 +48,33 @@
      * with the reader.  The reason for generating the key pair in the secure environment is so that
      * the secure environment knows what public key to expect to find in the session transcript.
      *
-     * This method may only be called once per instance. If called more than once, FAILED
+     * This method may only be called once per instance. If called more than once, STATUS_FAILED
      * will be returned.
      *
-     * @return result is OK on success or FAILED if an error occurred.
-     *
-     * @return keyPair contains the unencrypted key-pair in PKCS#8 format.
+     * @return the unencrypted key-pair in PKCS#8 format.
      */
-    createEphemeralKeyPair() generates (Result result, vec<uint8_t> keyPair);
+    byte[] createEphemeralKeyPair();
 
     /**
      * Sets the public part of the reader's ephemeral key pair.
      *
-     * This method may only be called once per instance. If called more than once, FAILED
+     * This method may only be called once per instance. If called more than once, STATUS_FAILED
      * will be returned.
      *
      * @param publicKey contains the reader's ephemeral public key, in uncompressed form.
-     *
-     * @return result is OK on success or FAILED if an error occurred.
      */
-    setReaderEphemeralPublicKey(vec<uint8_t> publicKey) generates (Result result);
+    void setReaderEphemeralPublicKey(in byte[] publicKey);
 
     /**
      * Creates a challenge value to be used for proving successful user authentication. This
      * is included in the authToken passed to the startRetrieval() method.
      *
-     * This method may only be called once per instance. If called more than once, FAILED
+     * This method may only be called once per instance. If called more than once, STATUS_FAILED
      * will be returned.
      *
-     * @return result is OK on success or FAILED if an error occurred.
-     *
-     * @return challenge on success, is a non-zero number.
+     * @return challenge, a non-zero number.
      */
-    createAuthChallenge() generates (Result result, uint64_t challenge);
+    long createAuthChallenge();
 
     /**
      * Start an entry retrieval process.
@@ -92,12 +88,12 @@
      * startRetrieval(), then multiple calls of startRetrieveEntryValue(), retrieveEntryValue(),
      * then finally finishRetrieval()) but if this is done, the sessionTranscript parameter
      * must be identical for each startRetrieval() invocation. If this is not the case, this call
-     * fails with the SESSION_TRANSCRIPT_MISMATCH error.
+     * fails with the STATUS_SESSION_TRANSCRIPT_MISMATCH error.
      *
-     * If the provided authToken is not valid this method fails with INVALID_AUTH_TOKEN.
+     * If the provided authToken is not valid this method fails with STATUS_INVALID_AUTH_TOKEN.
      *
      * Each of the provided accessControlProfiles is checked in this call. If they are not
-     * all valid, the call fails with INVALID_DATA.
+     * all valid, the call fails with STATUS_INVALID_DATA.
      *
      * For the itemsRequest parameter, the content can be defined in the way appropriate for
      * the credential, but there are three requirements that must be met to work with this HAL:
@@ -108,7 +104,7 @@
      *     the example below.
      *
      * If these requirements are not met the startRetrieval() call fails with
-     * INVALID_ITEMS_REQUEST_MESSAGE.
+     * STATUS_INVALID_ITEMS_REQUEST_MESSAGE.
      *
      * Here's an example of ItemsRequest CBOR which conforms to this requirement:
      *
@@ -156,17 +152,18 @@
      * 'x5chain' unprotected header element of the COSE_Sign1 structure (as as described
      * in 'draft-ietf-cose-x509-04'). There will be at least one certificate in said element
      * and there may be more (and if so, each certificate must be signed by its successor).
-     * This is checked and if the check fails the call fails with READER_SIGNATURE_CHECK_FAILED.
+     * This is checked and if the check fails the call fails with
+     * STATUS_READER_SIGNATURE_CHECK_FAILED.
      *
      * The SessionTranscript CBOR is conveyed in the sessionTranscript parameter. It
      * is permissible for this to be empty in which case the readerSignature parameter
-     * must also be empty. If this is not the case, the call fails with FAILED.
+     * must also be empty. If this is not the case, the call fails with STATUS_FAILED.
      *
      * If the SessionTranscript CBOR is not empty, the X and Y coordinates of the public
      * part of the key-pair previously generated by createEphemeralKeyPair() must appear
      * somewhere in the bytes of DeviceEngagement structure. Both X and Y should be in
      * uncompressed form. If this is not satisfied, the call fails with
-     * EPHEMERAL_PUBLIC_KEY_NOT_FOUND.
+     * STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND.
      *
      * @param accessControlProfiles
      *   Access control profiles that are required to retrieve the entries that are going to be
@@ -179,6 +176,10 @@
      * @param itemsRequest
      *   If non-empty, contains request data that is signed by the reader. See above.
      *
+     * @param signingKeyBlob is either empty or a signingKeyBlob (see generateSigningKeyPair(),
+     *    below) containing the signing key to use to sign the data retrieved. If this
+     *    is not in the right format the call fails with STATUS_INVALID_DATA.
+     *
      * @param sessionTranscript
      *   Either empty or the CBOR of the SessionTranscript. See above.
      *
@@ -196,16 +197,10 @@
      *   will succeed (i.e. that the access control profile checks will succeed).  This means that
      *   it's the responsibility of the caller to determine which access control checks will fail
      *   and remove the corresponding requests from the counts.
-     *
-     * @return result is OK on success. If an error occurs one of the values described above
-     *   will be returned.
      */
-    startRetrieval(vec<SecureAccessControlProfile> accessControlProfiles,
-                   HardwareAuthToken authToken,
-                   vec<uint8_t> itemsRequest,
-                   vec<uint8_t> sessionTranscript,
-                   vec<uint8_t> readerSignature,
-                   vec<uint16_t> requestCounts) generates(Result result);
+    void startRetrieval(in SecureAccessControlProfile[] accessControlProfiles,
+        in HardwareAuthToken authToken, in byte[] itemsRequest, in byte[] signingKeyBlob,
+        in byte[] sessionTranscript, in byte[] readerSignature, in int[] requestCounts);
 
     /**
      * Starts retrieving an entry, subject to access control requirements.  Entries must be
@@ -213,15 +208,15 @@
      *
      * If the requestData parameter as passed to startRetrieval() was non-empty
      * this method must only be called with entries specified in that field. If this
-     * requirement is not met, the call fails with NOT_IN_REQUEST_MESSAGE.
+     * requirement is not met, the call fails with STATUS_NOT_IN_REQUEST_MESSAGE.
      *
-     * If nameSpace or name is empty this call fails with INVALID_DATA.
+     * If nameSpace or name is empty this call fails with STATUS_INVALID_DATA.
      *
      * Each access control profile for the entry is checked. If user authentication
      * is required and the supplied auth token doesn't provide it the call fails
-     * with USER_AUTHENTICATION_FAILED. If reader authentication is required and
+     * with STATUS_USER_AUTHENTICATION_FAILED. If reader authentication is required and
      * a suitable reader certificate chain isn't presented, the call fails with
-     * READER_AUTHENTICATION_FAILED.
+     * STATUS_READER_AUTHENTICATION_FAILED.
      *
      * It is permissible to keep retrieving values if an access control check fails.
      *
@@ -231,38 +226,29 @@
      *
      * @param entrySize is the size of the entry value, if it's a text string or a byte string.
      *     It must be zero if the entry value is an integer or boolean. If this requirement
-     *     is not met the call fails with INVALID_DATA.
+     *     is not met the call fails with STATUS_INVALID_DATA.
      *
      * @param accessControlProfileIds specifies the set of access control profiles that can
      *     authorize access to the provisioned element. If an identifier of a profile
      *     is given and this profile wasn't passed to startRetrieval() this call fails
-     *     with INVALID_DATA.
-     *
-     * @return result is OK on success. Otherwise one of INVALID_DATA, FAILED,
-     *     USER_AUTHENTICATION_FAILED, READER_AUTHENTICATION_FAILED.
+     *     with STATUS_INVALID_DATA.
      */
-    startRetrieveEntryValue(string nameSpace, string name, uint32_t entrySize,
-                            vec<uint16_t> accessControlProfileIds)
-        generates (Result result);
-
+    void startRetrieveEntryValue(in @utf8InCpp String nameSpace, in @utf8InCpp String name,
+                                 in int entrySize, in int[] accessControlProfileIds);
 
     /**
      * Retrieves an entry value, or part of one, if the entry value is larger than gcmChunkSize.
      * May only be called after startRetrieveEntry().
      *
      * If the passed in data is not authentic, can't be decrypted, is of the wrong size, or can't
-     * be decoded, this call fails with INVALID_DATA.
+     * be decoded, this call fails with STATUS_INVALID_DATA.
      *
      * @param encryptedContent contains the encrypted and MACed content.
      *
-     * @return result is OK on success, INVALID_DATA, or FAILED if an error occurred.
-     *
-     * @return content is the entry value as CBOR, or part of the entry value in the case the
+     * @return the entry value as CBOR, or part of the entry value in the case the
      *    content exceeds gcmChunkSize in length.
      */
-    retrieveEntryValue(vec<uint8_t> encryptedContent)
-        generates (Result result, vec<uint8_t> content);
-
+    byte[] retrieveEntryValue(in byte[] encryptedContent);
 
     /**
      * End retrieval of data, optionally returning a message authentication code over the
@@ -271,13 +257,7 @@
      * If signingKeyBlob or the sessionTranscript parameter passed to startRetrieval() is
      * empty then the returned MAC will be empty.
      *
-     * @param signingKeyBlob is either empty or a signingKeyBlob (see generateSigningKeyPair(),
-     *    below) containing the signing key to use to sign the data retrieved. If this
-     *    is not in the right format the call fails with INVALID_DATA.
-     *
-     * @return result is OK on success, INVALID_DATA or FAILED if an error occurred.
-     *
-     * @return mac is empty if signingKeyBlob or the sessionTranscript passed to
+     * @param out mac is empty if signingKeyBlob or the sessionTranscript passed to
      *    startRetrieval() is empty. Otherwise it is a COSE_Mac0 with empty payload
      *    and the detached content is set to DeviceAuthentication as defined below.
      *    The key used for the MAC operation is EMacKey and is derived as follows:
@@ -321,23 +301,17 @@
      *        DataItemValue = any
      *
      *
-     * @return deviceNameSpaces the bytes of DeviceNameSpaces.
+     * @param out deviceNameSpaces the bytes of DeviceNameSpaces.
      */
-    finishRetrieval(vec<uint8_t> signingKeyBlob)
-        generates(Result result, vec<uint8_t> mac, vec<uint8_t> deviceNameSpaces);
-
+    void finishRetrieval(out byte[] mac, out byte[] deviceNameSpaces);
 
     /**
      * Generate a key pair to be used for signing session data and retrieved data items.
      *
-     * @return result is OK on success or FAILED if an error occurred.
+     * @param out signingKeyBlob contains an encrypted copy of the newly-generated private
+     *     signing key.
      *
-     * @return signingKeyBlob contains an encrypted copy of the newly-generated private signing key.
-     *
-     * @return signingKeyCertificate contains an X.509 certificate for the new signing key, signed
-     *     by the credential key.
+     * @return an X.509 certificate for the new signing key, signed by the credential key.
      */
-    generateSigningKeyPair()
-        generates(Result result, vec<uint8_t> signingKeyBlob,
-                  vec<uint8_t> signingKeyCertificate);
-};
+    Certificate generateSigningKeyPair(out byte[] signingKeyBlob);
+}
diff --git a/identity/1.0/IIdentityCredentialStore.hal b/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
similarity index 67%
rename from identity/1.0/IIdentityCredentialStore.hal
rename to identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
index 118ca6f..23cb1b7 100644
--- a/identity/1.0/IIdentityCredentialStore.hal
+++ b/identity/aidl/android/hardware/identity/IIdentityCredentialStore.aidl
@@ -14,10 +14,12 @@
  * limitations under the License.
  */
 
-package android.hardware.identity@1.0;
+package android.hardware.identity;
 
-import IWritableIdentityCredential;
-import IIdentityCredential;
+import android.hardware.identity.IIdentityCredential;
+import android.hardware.identity.IWritableIdentityCredential;
+import android.hardware.identity.HardwareInformation;
+import android.hardware.identity.CipherSuite;
 
 /**
  * IIdentityCredentialStore provides an interface to a secure store for user identity documents.
@@ -98,37 +100,90 @@
  * define appropriate encodings, those are used.  For example, X.509 certificates.  Where new
  * encodings are needed, CBOR is used.  CBOR maps are described in CDDL notation
  * (https://tools.ietf.org/html/draft-ietf-cbor-cddl-06).
+ *
+ * All binder calls in the HAL may return a ServiceSpecificException with statuses from the
+ * STATUS_* integers defined in this interface. Each method states which status can be returned
+ * and under which circumstances.
  */
+@VintfStability
 interface IIdentityCredentialStore {
+    /**
+     * Success.
+     */
+    const int STATUS_OK = 0;
+
+    /**
+     * The operation failed. This is used as a generic catch-all for errors that don't belong
+     * in other categories, including memory/resource allocation failures and I/O errors.
+     */
+    const int STATUS_FAILED = 1;
+
+    /**
+     * Unsupported cipher suite.
+     */
+    const int STATUS_CIPHER_SUITE_NOT_SUPPORTED = 2;
+
+    /**
+     * The passed data was invalid. This is a generic catch all for errors that don't belong
+     * in other categories related to parameter validation.
+     */
+    const int STATUS_INVALID_DATA = 3;
+
+    /**
+     * The authToken parameter passed to IIdentityCredential.startRetrieval() is not valid.
+     */
+    const int STATUS_INVALID_AUTH_TOKEN = 4;
+
+    /**
+     * The itemsRequest parameter passed to IIdentityCredential.startRetrieval() does not meet
+     * the requirements described in the documentation for that method.
+     */
+    const int STATUS_INVALID_ITEMS_REQUEST_MESSAGE = 5;
+
+    /**
+     * The readerSignature parameter in IIdentityCredential.startRetrieval() is invalid,
+     * doesn't contain an embedded certificate chain, or the signature failed to
+     * validate.
+     */
+    const int STATUS_READER_SIGNATURE_CHECK_FAILED = 6;
+
+    /**
+     * The sessionTranscript passed to startRetrieval() did not contain the ephmeral public
+     * key returned by createEphemeralPublicKey().
+     */
+    const int STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND = 7;
+
+    /**
+     * An access condition related to user authentication was not satisfied.
+     */
+    const int STATUS_USER_AUTHENTICATION_FAILED = 8;
+
+    /**
+     * An access condition related to reader authentication was not satisfied.
+     */
+    const int STATUS_READER_AUTHENTICATION_FAILED = 9;
+
+    /**
+     * The request data element has no access control profiles associated so it cannot be accessed.
+     */
+    const int STATUS_NO_ACCESS_CONTROL_PROFILES = 10;
+
+    /**
+     * The requested data element is not in the provided non-empty itemsRequest message.
+     */
+    const int STATUS_NOT_IN_REQUEST_MESSAGE = 11;
+
+    /**
+     * The passed-in sessionTranscript doesn't match the previously passed-in sessionTranscript.
+     */
+    const int STATUS_SESSION_TRANSCRIPT_MISMATCH = 12;
 
     /**
      * Returns information about hardware.
      *
-     * The isDirectAccess output parameter indicates whether this credential store
-     * implementation is for direct access. Credentials provisioned in credential
-     * stores with this set to true, should use reader authentication on all data elements.
-     *
-     * @return result is OK on success, FAILED if an error occurred.
-     *
-     * @return credentialStoreName the name of the credential store implementation.
-     *
-     * @return credentialStoreAuthorName the name of the credential store author.
-     *
-     * @return dataChunkSize the maximum size of data chunks.
-     *
-     * @return isDirectAccess whether the provisioned credential is available through
-     *     direct access.
-     *
-     * @return supportedDocTypes if empty, then any document type is supported, otherwise
-     *     only the document types returned are supported.
+     * @return a HardwareInformation with information about the hardware.
      */
-    getHardwareInformation()
-        generates(Result result,
-                  string credentialStoreName,
-                  string credentialStoreAuthorName,
-                  uint32_t dataChunkSize,
-                  bool isDirectAccess,
-                  vec<string> supportedDocTypes);
+    HardwareInformation getHardwareInformation();
 
     /**
      * createCredential creates a new Credential.  When a Credential is created, two cryptographic
@@ -147,16 +202,14 @@
      *     all-zeros hardware-bound key (HBK) and must set the test bit in the
      *     personalizationReceipt (see finishAddingEntries(), in IWritableIdentityCredential).
      *
-     * @return result is OK on success, FAILED if an error occurred.
-     *
-     * @return writableCredential is an IWritableIdentityCredential HIDL interface that provides
-     *     operations to provision a credential.
+     * @return an IWritableIdentityCredential interface that provides operations to
+     *     provision a credential.
      */
-    createCredential(string docType, bool testCredential)
-        generates(Result result, IWritableIdentityCredential writableCredential);
+    IWritableIdentityCredential createCredential(in @utf8InCpp String docType,
+                                                 in boolean testCredential);
 
     /**
-     * getCredential retrieves an IIdentityCredential HIDL interface which allows use of a stored
+     * getCredential retrieves an IIdentityCredential interface which allows use of a stored
      * Credential.
      *
      * The cipher suite used to communicate with the remote verifier must also be specified. Currently
@@ -170,16 +223,17 @@
      *
      * Support for other cipher suites may be added in a future version of this HAL.
      *
+     * This method fails with STATUS_INVALID_DATA if the passed in credentialData cannot be
+     * decoded or decrypted.
+     *
+     * @param cipherSuite is the cipher suite to use.
+     *
      * @param credentialData is a CBOR-encoded structure containing metadata about the credential
      *     and an encrypted byte array that contains data used to secure the credential.  See the
-     *     return argument of the same name in finishAddingEntries(), in IWritableIdentityCredential.
+     *     return argument of the same name in finishAddingEntries(), in
+     *     IWritableIdentityCredential.
      *
-     * @return result is OK on success or INVALID_DATA if the passed in credentialData
-     *     cannot be decoded or decrypted.
-     *
-     * @return credential is an IIdentityCredential HIDL interface that provides operations on the
-     *     Credential.
+     * @return an IIdentityCredential HIDL interface that provides operations on the Credential.
      */
-    getCredential(vec<uint8_t> credentialData)
-        generates (Result result, IIdentityCredential credential);
-};
+    IIdentityCredential getCredential(in CipherSuite cipherSuite, in byte[] credentialData);
+}
diff --git a/identity/1.0/IWritableIdentityCredential.hal b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
similarity index 62%
rename from identity/1.0/IWritableIdentityCredential.hal
rename to identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
index b1ce00d..483b0c7 100644
--- a/identity/1.0/IWritableIdentityCredential.hal
+++ b/identity/aidl/android/hardware/identity/IWritableIdentityCredential.aidl
@@ -14,50 +14,82 @@
  * limitations under the License.
  */
 
-package android.hardware.identity@1.0;
+package android.hardware.identity;
+
+import android.hardware.identity.Certificate;
+import android.hardware.identity.SecureAccessControlProfile;
 
 /**
  * IWritableIdentityCredential is used to personalize a new identity credential.  Credentials cannot
  * be updated or modified after creation; any changes require deletion and re-creation.
  */
+@VintfStability
 interface IWritableIdentityCredential {
     /**
      * Gets the certificate chain for credentialKey which can be used to prove the hardware
      * characteristics to an issuing authority.  Must not be called more than once.
      *
      * The certificate chain must be generated using Keymaster Attestation
-     * (see https://source.android.com/security/keystore/attestation) and must also
-     * have the Tag::IDENTITY_CREDENTIAL_KEY tag from KeyMaster 4.1 set. This tag indicates
-     * that this key is an Identity Credential key (which can only sign/MAC very
-     * specific messages) and not an Android Keystore key (which can be used to sign/MAC
-     * anything).
+     * (see https://source.android.com/security/keystore/attestation) with the
+     * following additional requirements:
+     *
+     *  - The attestationVersion field in the attestation extension must be at least 3.
+     *
+     *  - The attestationSecurityLevel field must be set to either Software (0),
+     *    TrustedEnvironment (1), or StrongBox (2) depending on how attestation is
+     *    implemented. Only the default AOSP implementation of this HAL may use
+     *    value 0 (additionally, this implementation must not be used on production
+     *    devices).
+     *
+     *  - The keymasterVersion field in the attestation extension must be set to (10*major + minor)
+     *    where major and minor are the Identity Credential interface major and minor versions.
+     *    Specifically for this version of the interface (1.0) this value is 10.
+     *
+     *  - The keymasterSecurityLevel field in the attestation extension must be set to
+     *    either Software (0), TrustedEnvironment (1), or StrongBox (2) depending on how
+     *    the Trusted Application backing the HAL implementation is implemented. Only
+     *    the default AOSP implementation of this HAL may use value 0 (additionally, this
+     *    implementation must not be used on production devices)
+     *
+     *  - The attestationChallenge field must be set to the passed-in challenge.
+     *
+     *  - The uniqueId field must be empty.
+     *
+     *  - The softwareEnforced field in the attestation extension must include
+     *    Tag::ATTESTATION_APPLICATION_ID which must be set to the bytes of the passed-in
+     *    attestationApplicationId.
+     *
+     *  - The teeEnforced field in the attestation extension must include
+     *    Tag::IDENTITY_CREDENTIAL_KEY. This tag indicates that the key is an Identity
+     *    Credential key (which can only sign/MAC very specific messages) and not an Android
+     *    Keystore key (which can be used to sign/MAC anything).
+     *
+     * Additional authorizations may be needed in the softwareEnforced and teeEnforced
+     * fields - the above is not an exhaustive list.
+     *
+     * @param attestationApplicationId is the DER encoded value to be stored
+     *     in Tag::ATTESTATION_APPLICATION_ID. This schema is described in
+     *     https://developer.android.com/training/articles/security-key-attestation#certificate_schema_attestationid
      *
      * @param attestationChallenge a challenge set by the issuer to ensure freshness.
      *
-     * @return result is OK on success, FAILED if an error occurred.
-     *
-     * @return certificate is the X.509 certificate chain for the credentialKey
+     * @return the X.509 certificate chain for the credentialKey
      */
-    getAttestationCertificate(vec<uint8_t> attestationChallenge)
-        generates(Result result, vec<uint8_t> certificate);
+    Certificate[] getAttestationCertificate(in byte[] attestationApplicationId, in byte[] attestationChallenge);
 
     /**
      * Start the personalization process.
      *
      * startPersonalization must not be called more than once.
      *
-     * @param accessControlProfileCount specifies the number of access control profiles that will be
-     *     provisioned with addAccessControlProfile().
+     * @param accessControlProfileCount specifies the number of access control profiles that will
+     *     be provisioned with addAccessControlProfile().
      *
      * @param entryCounts specifies the number of data entries that will be provisioned with
      *     beginAddEntry() and addEntry(). Each item in the array specifies how many entries
      *     will be added for each name space.
-     *
-     * @return result is OK on success, FAILED if an error occurred.
-     *
      */
-    startPersonalization(uint16_t accessControlProfileCount, vec<uint16_t> entryCounts)
-        generates(Result result);
+    void startPersonalization(in int accessControlProfileCount, in int[] entryCounts);
 
     /**
      * Add an access control profile, which defines the requirements or retrieval of one or more
@@ -67,15 +99,15 @@
      *
      * This method must be called exactly as many times as specified in the startPersonalization()
      * accessControlProfileCount parameter. If this is requirement is not met, the method fails
-     * with INVALID_DATA.
+     * with STATUS_INVALID_DATA.
      *
      * @param id a numeric identifier that must be unique within the context of a Credential and may
      *     be used to reference the profile. If this is not satisfied the call fails with
-     *     INVALID_DATA.
+     *     STATUS_INVALID_DATA.
      *
-     * @param readerCertificate if non-empty, specifies a X.509 certificate (or chain of certificates)
-     *     that must be used to authenticate requests (see the readerSignature parameter in
-     *     IIdentityCredential.startRetrieval).
+     * @param readerCertificate if non-empty, specifies a X.509 certificate (or chain of
+     *     certificates) that must be used to authenticate requests (see the readerSignature
+     *     parameter in IIdentityCredential.startRetrieval).
      *
      * @param userAuthenticationRequired if true, specifies that the user is required to
      *     authenticate to allow requests.  Required authentication freshness is specified by
@@ -85,22 +117,18 @@
      *     authentication (see userAuthenticationRequired above) is valid, if
      *     userAuthenticationRequired is true. If the timout is zero then authentication is
      *     required for each reader session. If userAuthenticationRequired is false, the timeout
-     *     must be zero. If this requirement is not met the call fails with INVALID_DATA.
+     *     must be zero. If this requirement is not met the call fails with STATUS_INVALID_DATA.
      *
      * @param secureUserId must be non-zero if userAuthenticationRequired is true. It is not
      *     related to any Android user ID or UID, but is created in the Gatekeeper application
      *     in the secure environment. If this requirement is not met the call fails with
-     *     INVALID_DATA.
+     *     STATUS_INVALID_DATA.
      *
-     * @return result is OK on success, INVALID_DATA or FAILED if an error occurred.
-     *
-     * @return secureAccessControlProfile is a structure with the passed-in data and MAC created
-     *     with storageKey for authenticating the data at a later point in time.
+     * @return a structure with the passed-in data and MAC created with storageKey for authenticating
+     *     the data at a later point in time.
      */
-    addAccessControlProfile(uint16_t id, vec<uint8_t> readerCertificate,
-                            bool userAuthenticationRequired, uint64_t timeoutMillis,
-                            uint64_t secureUserId)
-        generates(Result result, SecureAccessControlProfile secureAccessControlProfile);
+    SecureAccessControlProfile addAccessControlProfile(in int id, in Certificate readerCertificate,
+        in boolean userAuthenticationRequired, in long timeoutMillis, in long secureUserId);
 
     /**
      * Begins the process of adding an entry to the credential.  All access control profiles must be
@@ -109,7 +137,7 @@
      *
      * This method must be called exactly as many times as the sum of the items in the entryCounts
      * parameter specified in the startPersonalization(), and must be followed by one or more calls
-     * to addEntryValue(). If this requirement is not met the method fails with INVALID_DATA.
+     * to addEntryValue(). If this requirement is not met the method fails with STATUS_INVALID_DATA.
      *
      * @param accessControlProfileIds specifies the set of access control profiles that can
      *     authorize access to the provisioned element.
@@ -119,13 +147,10 @@
      * @param name is the name of the element.
      *
      * @param entrySize is the size of the entry value. If this requirement
-     *     is not met this method fails with INVALID_DATA.
-     *
-     * @return result is OK on success, INVALID_DATA or FAILED if an error occurred.
+     *     is not met this method fails with STATUS_INVALID_DATA.
      */
-    beginAddEntry(vec<uint16_t> accessControlProfileIds, string nameSpace,
-                  string name, uint32_t entrySize)
-        generates(Result result);
+    void beginAddEntry(in int[] accessControlProfileIds, in @utf8InCpp String nameSpace,
+        in @utf8InCpp String name, in int entrySize);
 
     /**
      * Continues the process of adding an entry, providing a value or part of a value.
@@ -135,18 +160,13 @@
      * (see IIdentityCredentialStore.getHardwareInformation()), the caller must provide the
      * value in chunks.  All chunks must be exactly gcmChunkSize except the last and the sum of all
      * chunk sizes must equal the value of the beginAddEntry() entrySize argument. If this
-     * requirement is not met the call fails with INVALID_DATA.
+     * requirement is not met the call fails with STATUS_INVALID_DATA.
      *
      * @param content is the entry value, encoded as CBOR. In the case the content exceeds gcmChunkSize,
      *     this may be partial content up to gcmChunkSize bytes long.
      *
-     * @return result is OK on success, INVALID_DATA or FAILED if an error occurred.
-     *
-     * @return encryptedContent contains the encrypted and MACed content.  For directly-available
-     *     credentials the contents are implementation-defined but must not exceed 32 bytes in
-     *     length.
-     *
-     *     For other credentials, encryptedContent contains:
+     * @return the encrypted and MACed content.  For directly-available credentials the contents are
+     *     implementation-defined. For other credentials, the result contains
      *
      *         AES-GCM-ENC(storageKey, R, Data, AdditionalData)
      *
@@ -160,18 +180,15 @@
      *             "AccessControlProfileIds" : [ + uint ],
      *         }
      */
-    addEntryValue(vec<uint8_t> content)
-        generates(Result result, vec<uint8_t> encryptedContent);
+    byte[] addEntryValue(in byte[] content);
 
     /**
-     * Finishes adding entries and returns a signature that an issuing authority may use to validate
-     * that all data was provisioned correctly.
+     * Finishes adding entries and returns a signature that an issuing authority may use to
+     * validate that all data was provisioned correctly.
      *
      * After this method is called, the IWritableIdentityCredential is no longer usable.
      *
-     * @return result is OK on success or FAILED if an error occurred.
-     *
-     * @return credentialData is a CBOR-encoded structure (in CDDL notation):
+     * @param out credentialData is a CBOR-encoded structure (in CDDL notation):
      *
      *         CredentialData = [
      *              tstr,   ; docType, an optional name that identifies the type of credential
@@ -194,10 +211,10 @@
      *              bstr    ; credentialPrivKey, the private key for credentialKey
      *         ]
      *
-     * @return proofOfProvisioningSignature proves to the IA that the credential was imported into the
-     *     secure hardware without alteration or error.  When the final addEntry() call is made
-     *     (when the number of provisioned entries equals the sum of the items in
-     *     startPersonalization() entryCounts parameter), it a COSE_Sign1 structure
+     * @param out proofOfProvisioningSignature proves to the IA that the credential was imported
+     *     into the secure hardware without alteration or error.  When the final addEntry() call is
+     *     made (when the number of provisioned entries equals the sum of the items in
+     *     startPersonalization() entryCounts parameter), a COSE_Sign1 structure
      *     signed by CredentialKey with payload set to the ProofOfProvisioning CBOR below:
      *
      *          ProofOfProvisioning = [
@@ -230,7 +247,6 @@
      *              "accessControlProfiles" : [ * uint ],
      *          }
      */
-    finishAddingEntries()
-        generates(Result result, vec<uint8_t> credentialData,
-                  vec<uint8_t> proofOfProvisioningSignature);
-};
+    void finishAddingEntries(out byte[] credentialData,
+        out byte[] proofOfProvisioningSignature);
+}
diff --git a/identity/aidl/android/hardware/identity/SecureAccessControlProfile.aidl b/identity/aidl/android/hardware/identity/SecureAccessControlProfile.aidl
new file mode 100644
index 0000000..01d312d
--- /dev/null
+++ b/identity/aidl/android/hardware/identity/SecureAccessControlProfile.aidl
@@ -0,0 +1,78 @@
+/*
+ * 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.Certificate;
+
+@VintfStability
+parcelable SecureAccessControlProfile {
+    /**
+     * id is a numeric identifier that must be unique within the context of a Credential and may be
+     * used to reference the profile.
+     */
+    int id;
+
+    /**
+     * readerCertificate, if non-empty, specifies a single X.509 certificate (not a chain
+     * of certificates) that must be used to authenticate requests. For details about how
+     * this is done, see the readerSignature paremter of IIdentityCredential.startRetrieval.
+     */
+    Certificate readerCertificate;
+
+    /**
+     * if true, the user is required to authenticate to allow requests.  Required authentication
+     * fressness is specified by timeout below.
+     *
+     */
+    boolean userAuthenticationRequired;
+
+    /**
+     * Timeout specifies the amount of time, in milliseconds, for which a user authentication (see
+     * above) is valid, if userAuthenticationRequired is set to true.  If userAuthenticationRequired
+     * is true and timout is zero then authentication is required for each reader session.
+     *
+     * If userAuthenticationRequired is false, timeout must be zero.
+     */
+    long timeoutMillis;
+
+    /**
+     * secureUserId must be non-zero if userAuthenticationRequired is true.
+     * It is not related to any Android user ID or UID, but is created in the
+     * Gatekeeper application in the secure environment.
+     */
+    long secureUserId;
+
+    /**
+     * The mac is used to authenticate the access control profile.  It contains:
+     *
+     *      AES-GCM-ENC(storageKey, R, {}, AccessControlProfile)
+     *
+     *  where AccessControlProfile is the CBOR map:
+     *
+     *      AccessControlProfile = {
+     *          "id": uint,
+     *          ? "readerCertificate" : bstr,
+     *          ? (
+     *              "userAuthenticationRequired" : bool,
+     *              "timeoutMillis" : uint,
+     *              "secureUserId" : uint
+     *          )
+     *      }
+     */
+    byte[] mac;
+}
+
diff --git a/identity/aidl/default/Android.bp b/identity/aidl/default/Android.bp
new file mode 100644
index 0000000..2eb0faa
--- /dev/null
+++ b/identity/aidl/default/Android.bp
@@ -0,0 +1,29 @@
+cc_binary {
+    name: "android.hardware.identity-service.example",
+    relative_install_path: "hw",
+    init_rc: ["identity-default.rc"],
+    vintf_fragments: ["identity-default.xml"],
+    vendor: true,
+    cflags: [
+        "-Wall",
+        "-Wextra",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libcppbor",
+        "libcrypto",
+        "liblog",
+        "libutils",
+        "android.hardware.identity-support-lib",
+        "android.hardware.identity-ndk_platform",
+        "android.hardware.keymaster-ndk_platform",
+    ],
+    srcs: [
+        "IdentityCredential.cpp",
+        "IdentityCredentialStore.cpp",
+        "WritableIdentityCredential.cpp",
+        "Util.cpp",
+        "service.cpp",
+    ],
+}
diff --git a/identity/aidl/default/IdentityCredential.cpp b/identity/aidl/default/IdentityCredential.cpp
new file mode 100644
index 0000000..341fae6
--- /dev/null
+++ b/identity/aidl/default/IdentityCredential.cpp
@@ -0,0 +1,767 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "IdentityCredential"
+
+#include "IdentityCredential.h"
+#include "IdentityCredentialStore.h"
+#include "Util.h"
+
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+
+#include <string.h>
+
+#include <android-base/logging.h>
+
+#include <cppbor.h>
+#include <cppbor_parse.h>
+
+namespace aidl::android::hardware::identity {
+
+using ::aidl::android::hardware::keymaster::Timestamp;
+using ::std::optional;
+
+using namespace ::android::hardware::identity;
+
+int IdentityCredential::initialize() {
+    auto [item, _, message] = cppbor::parse(credentialData_);
+    if (item == nullptr) {
+        LOG(ERROR) << "CredentialData is not valid CBOR: " << message;
+        return IIdentityCredentialStore::STATUS_INVALID_DATA;
+    }
+
+    const cppbor::Array* arrayItem = item->asArray();
+    if (arrayItem == nullptr || arrayItem->size() != 3) {
+        LOG(ERROR) << "CredentialData is not an array with three elements";
+        return IIdentityCredentialStore::STATUS_INVALID_DATA;
+    }
+
+    const cppbor::Tstr* docTypeItem = (*arrayItem)[0]->asTstr();
+    const cppbor::Bool* testCredentialItem =
+            ((*arrayItem)[1]->asSimple() != nullptr ? ((*arrayItem)[1]->asSimple()->asBool())
+                                                    : nullptr);
+    const cppbor::Bstr* encryptedCredentialKeysItem = (*arrayItem)[2]->asBstr();
+    if (docTypeItem == nullptr || testCredentialItem == nullptr ||
+        encryptedCredentialKeysItem == nullptr) {
+        LOG(ERROR) << "CredentialData unexpected item types";
+        return IIdentityCredentialStore::STATUS_INVALID_DATA;
+    }
+
+    docType_ = docTypeItem->value();
+    testCredential_ = testCredentialItem->value();
+
+    vector<uint8_t> hardwareBoundKey;
+    if (testCredential_) {
+        hardwareBoundKey = support::getTestHardwareBoundKey();
+    } else {
+        hardwareBoundKey = getHardwareBoundKey();
+    }
+
+    const vector<uint8_t>& encryptedCredentialKeys = encryptedCredentialKeysItem->value();
+    const vector<uint8_t> docTypeVec(docType_.begin(), docType_.end());
+    optional<vector<uint8_t>> decryptedCredentialKeys =
+            support::decryptAes128Gcm(hardwareBoundKey, encryptedCredentialKeys, docTypeVec);
+    if (!decryptedCredentialKeys) {
+        LOG(ERROR) << "Error decrypting CredentialKeys";
+        return IIdentityCredentialStore::STATUS_INVALID_DATA;
+    }
+
+    auto [dckItem, dckPos, dckMessage] = cppbor::parse(decryptedCredentialKeys.value());
+    if (dckItem == nullptr) {
+        LOG(ERROR) << "Decrypted CredentialKeys is not valid CBOR: " << dckMessage;
+        return IIdentityCredentialStore::STATUS_INVALID_DATA;
+    }
+    const cppbor::Array* dckArrayItem = dckItem->asArray();
+    if (dckArrayItem == nullptr || dckArrayItem->size() != 2) {
+        LOG(ERROR) << "Decrypted CredentialKeys is not an array with two elements";
+        return IIdentityCredentialStore::STATUS_INVALID_DATA;
+    }
+    const cppbor::Bstr* storageKeyItem = (*dckArrayItem)[0]->asBstr();
+    const cppbor::Bstr* credentialPrivKeyItem = (*dckArrayItem)[1]->asBstr();
+    if (storageKeyItem == nullptr || credentialPrivKeyItem == nullptr) {
+        LOG(ERROR) << "CredentialKeys unexpected item types";
+        return IIdentityCredentialStore::STATUS_INVALID_DATA;
+    }
+    storageKey_ = storageKeyItem->value();
+    credentialPrivKey_ = credentialPrivKeyItem->value();
+
+    return IIdentityCredentialStore::STATUS_OK;
+}
+
+ndk::ScopedAStatus IdentityCredential::deleteCredential(
+        vector<int8_t>* outProofOfDeletionSignature) {
+    cppbor::Array array = {"ProofOfDeletion", docType_, testCredential_};
+    vector<uint8_t> proofOfDeletion = array.encode();
+
+    optional<vector<uint8_t>> signature = support::coseSignEcDsa(credentialPrivKey_,
+                                                                 proofOfDeletion,  // payload
+                                                                 {},               // additionalData
+                                                                 {});  // certificateChain
+    if (!signature) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Error signing data"));
+    }
+
+    *outProofOfDeletionSignature = byteStringToSigned(signature.value());
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus IdentityCredential::createEphemeralKeyPair(vector<int8_t>* outKeyPair) {
+    optional<vector<uint8_t>> kp = support::createEcKeyPair();
+    if (!kp) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Error creating ephemeral key pair"));
+    }
+
+    // Stash public key of this key-pair for later check in startRetrieval().
+    optional<vector<uint8_t>> publicKey = support::ecKeyPairGetPublicKey(kp.value());
+    if (!publicKey) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED,
+                "Error getting public part of ephemeral key pair"));
+    }
+    ephemeralPublicKey_ = publicKey.value();
+
+    *outKeyPair = byteStringToSigned(kp.value());
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus IdentityCredential::setReaderEphemeralPublicKey(
+        const vector<int8_t>& publicKey) {
+    readerPublicKey_ = byteStringToUnsigned(publicKey);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus IdentityCredential::createAuthChallenge(int64_t* outChallenge) {
+    uint64_t challenge = 0;
+    while (challenge == 0) {
+        optional<vector<uint8_t>> bytes = support::getRandom(8);
+        if (!bytes) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_FAILED,
+                    "Error getting random data for challenge"));
+        }
+
+        challenge = 0;
+        for (size_t n = 0; n < bytes.value().size(); n++) {
+            challenge |= ((bytes.value())[n] << (n * 8));
+        }
+    }
+
+    *outChallenge = challenge;
+    return ndk::ScopedAStatus::ok();
+}
+
+// TODO: this could be a lot faster if we did all the splitting and pubkey extraction
+// ahead of time.
+bool checkReaderAuthentication(const SecureAccessControlProfile& profile,
+                               const vector<uint8_t>& readerCertificateChain) {
+    optional<vector<uint8_t>> acpPubKey = support::certificateChainGetTopMostKey(
+            byteStringToUnsigned(profile.readerCertificate.encodedCertificate));
+    if (!acpPubKey) {
+        LOG(ERROR) << "Error extracting public key from readerCertificate in profile";
+        return false;
+    }
+
+    optional<vector<vector<uint8_t>>> certificatesInChain =
+            support::certificateChainSplit(readerCertificateChain);
+    if (!certificatesInChain) {
+        LOG(ERROR) << "Error splitting readerCertificateChain";
+        return false;
+    }
+    for (const vector<uint8_t>& certInChain : certificatesInChain.value()) {
+        optional<vector<uint8_t>> certPubKey = support::certificateChainGetTopMostKey(certInChain);
+        if (!certPubKey) {
+            LOG(ERROR)
+                    << "Error extracting public key from certificate in chain presented by reader";
+            return false;
+        }
+        if (acpPubKey.value() == certPubKey.value()) {
+            return true;
+        }
+    }
+    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 HardwareAuthToken& authToken, uint64_t authChallenge) {
+    if (profile.secureUserId != authToken.userId) {
+        LOG(ERROR) << "secureUserId in profile (" << profile.secureUserId
+                   << ") differs from userId in authToken (" << authToken.userId << ")";
+        return false;
+    }
+
+    if (profile.timeoutMillis == 0) {
+        if (authToken.challenge == 0) {
+            LOG(ERROR) << "No challenge in authToken";
+            return false;
+        }
+
+        if (authToken.challenge != int64_t(authChallenge)) {
+            LOG(ERROR) << "Challenge in authToken doesn't match the challenge we created";
+            return false;
+        }
+        return true;
+    }
+
+    // Note that the Epoch for timestamps in HardwareAuthToken is at the
+    // discretion of the vendor:
+    //
+    //   "[...] 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();
+    if (authToken.timestamp.milliSeconds > now.milliSeconds) {
+        LOG(ERROR) << "Timestamp in authToken (" << authToken.timestamp.milliSeconds
+                   << ") is in the future (now: " << now.milliSeconds << ")";
+        return false;
+    }
+    if (now.milliSeconds > authToken.timestamp.milliSeconds + profile.timeoutMillis) {
+        LOG(ERROR) << "Deadline for authToken (" << authToken.timestamp.milliSeconds << " + "
+                   << profile.timeoutMillis << " = "
+                   << (authToken.timestamp.milliSeconds + profile.timeoutMillis)
+                   << ") is in the past (now: " << now.milliSeconds << ")";
+        return false;
+    }
+    return true;
+}
+
+ndk::ScopedAStatus IdentityCredential::startRetrieval(
+        const vector<SecureAccessControlProfile>& accessControlProfiles,
+        const HardwareAuthToken& authToken, const vector<int8_t>& itemsRequestS,
+        const vector<int8_t>& signingKeyBlobS, const vector<int8_t>& sessionTranscriptS,
+        const vector<int8_t>& readerSignatureS, const vector<int32_t>& requestCounts) {
+    auto sessionTranscript = byteStringToUnsigned(sessionTranscriptS);
+    auto itemsRequest = byteStringToUnsigned(itemsRequestS);
+    auto readerSignature = byteStringToUnsigned(readerSignatureS);
+
+    if (sessionTranscript.size() > 0) {
+        auto [item, _, message] = cppbor::parse(sessionTranscript);
+        if (item == nullptr) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_INVALID_DATA,
+                    "SessionTranscript contains invalid CBOR"));
+        }
+        sessionTranscriptItem_ = std::move(item);
+    }
+    if (numStartRetrievalCalls_ > 0) {
+        if (sessionTranscript_ != sessionTranscript) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_SESSION_TRANSCRIPT_MISMATCH,
+                    "Passed-in SessionTranscript doesn't match previously used SessionTranscript"));
+        }
+    }
+    sessionTranscript_ = sessionTranscript;
+
+    // If there is a signature, validate that it was made with the top-most key in the
+    // certificate chain embedded in the COSE_Sign1 structure.
+    optional<vector<uint8_t>> readerCertificateChain;
+    if (readerSignature.size() > 0) {
+        readerCertificateChain = support::coseSignGetX5Chain(readerSignature);
+        if (!readerCertificateChain) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_READER_SIGNATURE_CHECK_FAILED,
+                    "Unable to get reader certificate chain from COSE_Sign1"));
+        }
+
+        if (!support::certificateChainValidate(readerCertificateChain.value())) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_READER_SIGNATURE_CHECK_FAILED,
+                    "Error validating reader certificate chain"));
+        }
+
+        optional<vector<uint8_t>> readerPublicKey =
+                support::certificateChainGetTopMostKey(readerCertificateChain.value());
+        if (!readerPublicKey) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_READER_SIGNATURE_CHECK_FAILED,
+                    "Unable to get public key from reader certificate chain"));
+        }
+
+        const vector<uint8_t>& itemsRequestBytes = itemsRequest;
+        vector<uint8_t> dataThatWasSigned = cppbor::Array()
+                                                    .add("ReaderAuthentication")
+                                                    .add(sessionTranscriptItem_->clone())
+                                                    .add(cppbor::Semantic(24, itemsRequestBytes))
+                                                    .encode();
+        if (!support::coseCheckEcDsaSignature(readerSignature,
+                                              dataThatWasSigned,  // detached content
+                                              readerPublicKey.value())) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_READER_SIGNATURE_CHECK_FAILED,
+                    "readerSignature check failed"));
+        }
+    }
+
+    // Here's where we would validate the passed-in |authToken| to assure ourselves
+    // that it comes from the e.g. biometric hardware and wasn't made up by an attacker.
+    //
+    // However this involves calculating the MAC. However this requires access
+    // to the key needed to a pre-shared key which we don't have...
+    //
+
+    // To prevent replay-attacks, we check that the public part of the ephemeral
+    // key we previously created, is present in the DeviceEngagement part of
+    // SessionTranscript as a COSE_Key, in uncompressed form.
+    //
+    // We do this by just searching for the X and Y coordinates.
+    if (sessionTranscript.size() > 0) {
+        const cppbor::Array* array = sessionTranscriptItem_->asArray();
+        if (array == nullptr || array->size() != 2) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
+                    "SessionTranscript is not an array with two items"));
+        }
+        const cppbor::Semantic* taggedEncodedDE = (*array)[0]->asSemantic();
+        if (taggedEncodedDE == nullptr || taggedEncodedDE->value() != 24) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
+                    "First item in SessionTranscript array is not a "
+                    "semantic with value 24"));
+        }
+        const cppbor::Bstr* encodedDE = (taggedEncodedDE->child())->asBstr();
+        if (encodedDE == nullptr) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
+                    "Child of semantic in first item in SessionTranscript "
+                    "array is not a bstr"));
+        }
+        const vector<uint8_t>& bytesDE = encodedDE->value();
+
+        auto [getXYSuccess, ePubX, ePubY] = support::ecPublicKeyGetXandY(ephemeralPublicKey_);
+        if (!getXYSuccess) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
+                    "Error extracting X and Y from ePub"));
+        }
+        if (sessionTranscript.size() > 0 &&
+            !(memmem(bytesDE.data(), bytesDE.size(), ePubX.data(), ePubX.size()) != nullptr &&
+              memmem(bytesDE.data(), bytesDE.size(), ePubY.data(), ePubY.size()) != nullptr)) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_EPHEMERAL_PUBLIC_KEY_NOT_FOUND,
+                    "Did not find ephemeral public key's X and Y coordinates in "
+                    "SessionTranscript (make sure leading zeroes are not used)"));
+        }
+    }
+
+    // itemsRequest: If non-empty, contains request data that may be signed by the
+    // reader.  The content can be defined in the way appropriate for the
+    // credential, but there are three requirements that must be met to work with
+    // this HAL:
+    if (itemsRequest.size() > 0) {
+        // 1. The content must be a CBOR-encoded structure.
+        auto [item, _, message] = cppbor::parse(itemsRequest);
+        if (item == nullptr) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_INVALID_ITEMS_REQUEST_MESSAGE,
+                    "Error decoding CBOR in itemsRequest"));
+        }
+
+        // 2. The CBOR structure must be a map.
+        const cppbor::Map* map = item->asMap();
+        if (map == nullptr) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_INVALID_ITEMS_REQUEST_MESSAGE,
+                    "itemsRequest is not a CBOR map"));
+        }
+
+        // 3. The map must contain a key "nameSpaces" whose value contains a map, as described in
+        //    the example below.
+        //
+        //   NameSpaces = {
+        //     + NameSpace => DataElements ; Requested data elements for each NameSpace
+        //   }
+        //
+        //   NameSpace = tstr
+        //
+        //   DataElements = {
+        //     + DataElement => IntentToRetain
+        //   }
+        //
+        //   DataElement = tstr
+        //   IntentToRetain = bool
+        //
+        // Here's an example of an |itemsRequest| CBOR value satisfying above requirements 1.
+        // through 3.:
+        //
+        //    {
+        //        'docType' : 'org.iso.18013-5.2019',
+        //        'nameSpaces' : {
+        //            'org.iso.18013-5.2019' : {
+        //                'Last name' : false,
+        //                'Birth date' : false,
+        //                'First name' : false,
+        //                'Home address' : true
+        //            },
+        //            'org.aamva.iso.18013-5.2019' : {
+        //                'Real Id' : false
+        //            }
+        //        }
+        //    }
+        //
+        const cppbor::Map* nsMap = nullptr;
+        for (size_t n = 0; n < map->size(); n++) {
+            const auto& [keyItem, valueItem] = (*map)[n];
+            if (keyItem->type() == cppbor::TSTR && keyItem->asTstr()->value() == "nameSpaces" &&
+                valueItem->type() == cppbor::MAP) {
+                nsMap = valueItem->asMap();
+                break;
+            }
+        }
+        if (nsMap == nullptr) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_INVALID_ITEMS_REQUEST_MESSAGE,
+                    "No nameSpaces map in top-most map"));
+        }
+
+        for (size_t n = 0; n < nsMap->size(); n++) {
+            auto [nsKeyItem, nsValueItem] = (*nsMap)[n];
+            const cppbor::Tstr* nsKey = nsKeyItem->asTstr();
+            const cppbor::Map* nsInnerMap = nsValueItem->asMap();
+            if (nsKey == nullptr || nsInnerMap == nullptr) {
+                return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                        IIdentityCredentialStore::STATUS_INVALID_ITEMS_REQUEST_MESSAGE,
+                        "Type mismatch in nameSpaces map"));
+            }
+            string requestedNamespace = nsKey->value();
+            vector<string> requestedKeys;
+            for (size_t m = 0; m < nsInnerMap->size(); m++) {
+                const auto& [innerMapKeyItem, innerMapValueItem] = (*nsInnerMap)[m];
+                const cppbor::Tstr* nameItem = innerMapKeyItem->asTstr();
+                const cppbor::Simple* simple = innerMapValueItem->asSimple();
+                const cppbor::Bool* intentToRetainItem =
+                        (simple != nullptr) ? simple->asBool() : nullptr;
+                if (nameItem == nullptr || intentToRetainItem == nullptr) {
+                    return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                            IIdentityCredentialStore::STATUS_INVALID_ITEMS_REQUEST_MESSAGE,
+                            "Type mismatch in value in nameSpaces map"));
+                }
+                requestedKeys.push_back(nameItem->value());
+            }
+            requestedNameSpacesAndNames_[requestedNamespace] = requestedKeys;
+        }
+    }
+
+    // Finally, validate all the access control profiles in the requestData.
+    bool haveAuthToken = (authToken.mac.size() > 0);
+    for (const auto& profile : accessControlProfiles) {
+        if (!secureAccessControlProfileCheckMac(profile, storageKey_)) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_INVALID_DATA,
+                    "Error checking MAC for profile"));
+        }
+        int accessControlCheck = IIdentityCredentialStore::STATUS_OK;
+        if (profile.userAuthenticationRequired) {
+            if (!haveAuthToken || !checkUserAuthentication(profile, authToken, authChallenge_)) {
+                accessControlCheck = IIdentityCredentialStore::STATUS_USER_AUTHENTICATION_FAILED;
+            }
+        } else if (profile.readerCertificate.encodedCertificate.size() > 0) {
+            if (!readerCertificateChain ||
+                !checkReaderAuthentication(profile, readerCertificateChain.value())) {
+                accessControlCheck = IIdentityCredentialStore::STATUS_READER_AUTHENTICATION_FAILED;
+            }
+        }
+        profileIdToAccessCheckResult_[profile.id] = accessControlCheck;
+    }
+
+    deviceNameSpacesMap_ = cppbor::Map();
+    currentNameSpaceDeviceNameSpacesMap_ = cppbor::Map();
+
+    requestCountsRemaining_ = requestCounts;
+    currentNameSpace_ = "";
+
+    itemsRequest_ = itemsRequest;
+    signingKeyBlob_ = byteStringToUnsigned(signingKeyBlobS);
+
+    numStartRetrievalCalls_ += 1;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus IdentityCredential::startRetrieveEntryValue(
+        const string& nameSpace, const string& name, int32_t entrySize,
+        const vector<int32_t>& accessControlProfileIds) {
+    if (name.empty()) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA, "Name cannot be empty"));
+    }
+    if (nameSpace.empty()) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA, "Name space cannot be empty"));
+    }
+
+    if (requestCountsRemaining_.size() == 0) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA,
+                "No more name spaces left to go through"));
+    }
+
+    if (currentNameSpace_ == "") {
+        // First call.
+        currentNameSpace_ = nameSpace;
+    }
+
+    if (nameSpace == currentNameSpace_) {
+        // Same namespace.
+        if (requestCountsRemaining_[0] == 0) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_INVALID_DATA,
+                    "No more entries to be retrieved in current name space"));
+        }
+        requestCountsRemaining_[0] -= 1;
+    } else {
+        // New namespace.
+        if (requestCountsRemaining_[0] != 0) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_INVALID_DATA,
+                    "Moved to new name space but one or more entries need to be retrieved "
+                    "in current name space"));
+        }
+        if (currentNameSpaceDeviceNameSpacesMap_.size() > 0) {
+            deviceNameSpacesMap_.add(currentNameSpace_,
+                                     std::move(currentNameSpaceDeviceNameSpacesMap_));
+        }
+        currentNameSpaceDeviceNameSpacesMap_ = cppbor::Map();
+
+        requestCountsRemaining_.erase(requestCountsRemaining_.begin());
+        currentNameSpace_ = nameSpace;
+    }
+
+    // It's permissible to have an empty itemsRequest... but if non-empty you can
+    // only request what was specified in said itemsRequest. Enforce that.
+    if (itemsRequest_.size() > 0) {
+        const auto& it = requestedNameSpacesAndNames_.find(nameSpace);
+        if (it == requestedNameSpacesAndNames_.end()) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    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()) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_NOT_IN_REQUEST_MESSAGE,
+                    "Data item name in name space was not requested in startRetrieval"));
+        }
+    }
+
+    // Enforce access control.
+    //
+    // Access is granted if at least one of the profiles grants access.
+    //
+    // If an item is configured without any profiles, access is denied.
+    //
+    int accessControl = IIdentityCredentialStore::STATUS_NO_ACCESS_CONTROL_PROFILES;
+    for (auto id : accessControlProfileIds) {
+        auto search = profileIdToAccessCheckResult_.find(id);
+        if (search == profileIdToAccessCheckResult_.end()) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_INVALID_DATA,
+                    "Requested entry with unvalidated profile id"));
+        }
+        int accessControlForProfile = search->second;
+        if (accessControlForProfile == IIdentityCredentialStore::STATUS_OK) {
+            accessControl = IIdentityCredentialStore::STATUS_OK;
+            break;
+        }
+        accessControl = accessControlForProfile;
+    }
+    if (accessControl != IIdentityCredentialStore::STATUS_OK) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                int(accessControl), "Access control check failed"));
+    }
+
+    entryAdditionalData_ = entryCreateAdditionalData(nameSpace, name, accessControlProfileIds);
+
+    currentName_ = name;
+    entryRemainingBytes_ = entrySize;
+    entryValue_.resize(0);
+
+    return ndk::ScopedAStatus::ok();
+}
+
+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) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA, "Error decrypting data"));
+    }
+
+    size_t chunkSize = content.value().size();
+
+    if (chunkSize > entryRemainingBytes_) {
+        LOG(ERROR) << "Retrieved chunk of size " << chunkSize
+                   << " is bigger than remaining space of size " << entryRemainingBytes_;
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA,
+                "Retrieved chunk is bigger than remaining space"));
+    }
+
+    entryRemainingBytes_ -= chunkSize;
+    if (entryRemainingBytes_ > 0) {
+        if (chunkSize != IdentityCredentialStore::kGcmChunkSize) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_INVALID_DATA,
+                    "Retrieved non-final chunk of size which isn't kGcmChunkSize"));
+        }
+    }
+
+    entryValue_.insert(entryValue_.end(), content.value().begin(), content.value().end());
+
+    if (entryRemainingBytes_ == 0) {
+        auto [entryValueItem, _, message] = cppbor::parse(entryValue_);
+        if (entryValueItem == nullptr) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_INVALID_DATA,
+                    "Retrieved data which is invalid CBOR"));
+        }
+        currentNameSpaceDeviceNameSpacesMap_.add(currentName_, std::move(entryValueItem));
+    }
+
+    *outContent = byteStringToSigned(content.value());
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus IdentityCredential::finishRetrieval(vector<int8_t>* outMac,
+                                                       vector<int8_t>* outDeviceNameSpaces) {
+    if (currentNameSpaceDeviceNameSpacesMap_.size() > 0) {
+        deviceNameSpacesMap_.add(currentNameSpace_,
+                                 std::move(currentNameSpaceDeviceNameSpacesMap_));
+    }
+    vector<uint8_t> encodedDeviceNameSpaces = deviceNameSpacesMap_.encode();
+
+    // 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;
+    if (signingKeyBlob_.size() > 0 && sessionTranscript_.size() > 0 &&
+        readerPublicKey_.size() > 0) {
+        cppbor::Array array;
+        array.add("DeviceAuthentication");
+        array.add(sessionTranscriptItem_->clone());
+        array.add(docType_);
+        array.add(cppbor::Semantic(24, encodedDeviceNameSpaces));
+        vector<uint8_t> encodedDeviceAuthentication = array.encode();
+
+        vector<uint8_t> docTypeAsBlob(docType_.begin(), docType_.end());
+        optional<vector<uint8_t>> signingKey =
+                support::decryptAes128Gcm(storageKey_, signingKeyBlob_, docTypeAsBlob);
+        if (!signingKey) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_INVALID_DATA,
+                    "Error decrypting signingKeyBlob"));
+        }
+
+        optional<vector<uint8_t>> sharedSecret =
+                support::ecdh(readerPublicKey_, signingKey.value());
+        if (!sharedSecret) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_FAILED, "Error doing ECDH"));
+        }
+
+        vector<uint8_t> salt = {0x00};
+        vector<uint8_t> info = {};
+        optional<vector<uint8_t>> derivedKey = support::hkdf(sharedSecret.value(), salt, info, 32);
+        if (!derivedKey) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_FAILED,
+                    "Error deriving key from shared secret"));
+        }
+
+        mac = support::coseMac0(derivedKey.value(), {},        // payload
+                                encodedDeviceAuthentication);  // additionalData
+        if (!mac) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_FAILED, "Error MACing data"));
+        }
+    }
+
+    *outMac = byteStringToSigned(mac.value_or(vector<uint8_t>({})));
+    *outDeviceNameSpaces = byteStringToSigned(encodedDeviceNameSpaces);
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus IdentityCredential::generateSigningKeyPair(
+        vector<int8_t>* outSigningKeyBlob, Certificate* outSigningKeyCertificate) {
+    string serialDecimal = "0";  // TODO: set serial to something unique
+    string issuer = "Android Open Source Project";
+    string subject = "Android IdentityCredential Reference Implementation";
+    time_t validityNotBefore = time(nullptr);
+    time_t validityNotAfter = validityNotBefore + 365 * 24 * 3600;
+
+    optional<vector<uint8_t>> signingKeyPKCS8 = support::createEcKeyPair();
+    if (!signingKeyPKCS8) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Error creating signingKey"));
+    }
+
+    optional<vector<uint8_t>> signingPublicKey =
+            support::ecKeyPairGetPublicKey(signingKeyPKCS8.value());
+    if (!signingPublicKey) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED,
+                "Error getting public part of signingKey"));
+    }
+
+    optional<vector<uint8_t>> signingKey = support::ecKeyPairGetPrivateKey(signingKeyPKCS8.value());
+    if (!signingKey) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED,
+                "Error getting private part of signingKey"));
+    }
+
+    optional<vector<uint8_t>> certificate = support::ecPublicKeyGenerateCertificate(
+            signingPublicKey.value(), credentialPrivKey_, serialDecimal, issuer, subject,
+            validityNotBefore, validityNotAfter);
+    if (!certificate) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Error creating signingKey"));
+    }
+
+    optional<vector<uint8_t>> nonce = support::getRandom(12);
+    if (!nonce) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Error getting random"));
+    }
+    vector<uint8_t> docTypeAsBlob(docType_.begin(), docType_.end());
+    optional<vector<uint8_t>> encryptedSigningKey = support::encryptAes128Gcm(
+            storageKey_, nonce.value(), signingKey.value(), docTypeAsBlob);
+    if (!encryptedSigningKey) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Error encrypting signingKey"));
+    }
+    *outSigningKeyBlob = byteStringToSigned(encryptedSigningKey.value());
+    *outSigningKeyCertificate = Certificate();
+    outSigningKeyCertificate->encodedCertificate = byteStringToSigned(certificate.value());
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/IdentityCredential.h b/identity/aidl/default/IdentityCredential.h
new file mode 100644
index 0000000..fc29254
--- /dev/null
+++ b/identity/aidl/default/IdentityCredential.h
@@ -0,0 +1,110 @@
+/*
+ * 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 ANDROID_HARDWARE_IDENTITY_IDENTITYCREDENTIAL_H
+#define ANDROID_HARDWARE_IDENTITY_IDENTITYCREDENTIAL_H
+
+#include <aidl/android/hardware/identity/BnIdentityCredential.h>
+#include <aidl/android/hardware/keymaster/HardwareAuthToken.h>
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+#include <cppbor/cppbor.h>
+
+namespace aidl::android::hardware::identity {
+
+using ::aidl::android::hardware::keymaster::HardwareAuthToken;
+using ::std::map;
+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) {}
+
+    // Parses and decrypts credentialData_, return a status code from
+    // IIdentityCredentialStore. Must be called right after construction.
+    int initialize();
+
+    // Methods from IIdentityCredential follow.
+    ndk::ScopedAStatus deleteCredential(vector<int8_t>* outProofOfDeletionSignature) override;
+    ndk::ScopedAStatus createEphemeralKeyPair(vector<int8_t>* outKeyPair) override;
+    ndk::ScopedAStatus setReaderEphemeralPublicKey(const vector<int8_t>& publicKey) override;
+    ndk::ScopedAStatus createAuthChallenge(int64_t* outChallenge) override;
+    ndk::ScopedAStatus startRetrieval(
+            const vector<SecureAccessControlProfile>& accessControlProfiles,
+            const HardwareAuthToken& authToken, const vector<int8_t>& itemsRequest,
+            const vector<int8_t>& signingKeyBlob, const vector<int8_t>& sessionTranscript,
+            const vector<int8_t>& readerSignature, const vector<int32_t>& requestCounts) override;
+    ndk::ScopedAStatus startRetrieveEntryValue(
+            const string& nameSpace, const string& name, int32_t entrySize,
+            const vector<int32_t>& accessControlProfileIds) override;
+    ndk::ScopedAStatus retrieveEntryValue(const vector<int8_t>& encryptedContent,
+                                          vector<int8_t>* outContent) override;
+    ndk::ScopedAStatus finishRetrieval(vector<int8_t>* outMac,
+                                       vector<int8_t>* outDeviceNameSpaces) override;
+    ndk::ScopedAStatus generateSigningKeyPair(vector<int8_t>* outSigningKeyBlob,
+                                              Certificate* outSigningKeyCertificate) override;
+
+  private:
+    // Set by constructor
+    vector<uint8_t> credentialData_;
+    int numStartRetrievalCalls_;
+
+    // Set by initialize()
+    string docType_;
+    bool testCredential_;
+    vector<uint8_t> storageKey_;
+    vector<uint8_t> credentialPrivKey_;
+
+    // Set by createEphemeralKeyPair()
+    vector<uint8_t> ephemeralPublicKey_;
+
+    // Set by setReaderEphemeralPublicKey()
+    vector<uint8_t> readerPublicKey_;
+
+    // Set by createAuthChallenge()
+    uint64_t authChallenge_;
+
+    // Set at startRetrieval() time.
+    map<int32_t, int> profileIdToAccessCheckResult_;
+    vector<uint8_t> signingKeyBlob_;
+    vector<uint8_t> sessionTranscript_;
+    std::unique_ptr<cppbor::Item> sessionTranscriptItem_;
+    vector<uint8_t> itemsRequest_;
+    vector<int32_t> requestCountsRemaining_;
+    MapStringToVectorOfStrings requestedNameSpacesAndNames_;
+    cppbor::Map deviceNameSpacesMap_;
+    cppbor::Map currentNameSpaceDeviceNameSpacesMap_;
+
+    // Set at startRetrieveEntryValue() time.
+    string currentNameSpace_;
+    string currentName_;
+    size_t entryRemainingBytes_;
+    vector<uint8_t> entryValue_;
+    vector<uint8_t> entryAdditionalData_;
+};
+
+}  // namespace aidl::android::hardware::identity
+
+#endif  // ANDROID_HARDWARE_IDENTITY_IDENTITYCREDENTIAL_H
diff --git a/identity/aidl/default/IdentityCredentialStore.cpp b/identity/aidl/default/IdentityCredentialStore.cpp
new file mode 100644
index 0000000..1efb4b4
--- /dev/null
+++ b/identity/aidl/default/IdentityCredentialStore.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "IdentityCredentialStore"
+
+#include <android-base/logging.h>
+
+#include "IdentityCredential.h"
+#include "IdentityCredentialStore.h"
+#include "WritableIdentityCredential.h"
+
+namespace aidl::android::hardware::identity {
+
+ndk::ScopedAStatus IdentityCredentialStore::getHardwareInformation(
+        HardwareInformation* hardwareInformation) {
+    HardwareInformation hw;
+    hw.credentialStoreName = "Identity Credential Reference Implementation";
+    hw.credentialStoreAuthorName = "Google";
+    hw.dataChunkSize = kGcmChunkSize;
+    hw.isDirectAccess = false;
+    hw.supportedDocTypes = {};
+    *hardwareInformation = hw;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus IdentityCredentialStore::createCredential(
+        const string& docType, bool testCredential,
+        shared_ptr<IWritableIdentityCredential>* outWritableCredential) {
+    shared_ptr<WritableIdentityCredential> wc =
+            ndk::SharedRefBase::make<WritableIdentityCredential>(docType, testCredential);
+    if (!wc->initialize()) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED,
+                "Error initializing WritableIdentityCredential"));
+    }
+    *outWritableCredential = wc;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus IdentityCredentialStore::getCredential(
+        CipherSuite cipherSuite, const vector<int8_t>& credentialData,
+        shared_ptr<IIdentityCredential>* outCredential) {
+    // We only support CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256 right now.
+    if (cipherSuite != CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_CIPHER_SUITE_NOT_SUPPORTED,
+                "Unsupported cipher suite"));
+    }
+
+    vector<uint8_t> data = vector<uint8_t>(credentialData.begin(), credentialData.end());
+    shared_ptr<IdentityCredential> credential = ndk::SharedRefBase::make<IdentityCredential>(data);
+    auto ret = credential->initialize();
+    if (ret != IIdentityCredentialStore::STATUS_OK) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                int(ret), "Error initializing IdentityCredential"));
+    }
+    *outCredential = credential;
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/IdentityCredentialStore.h b/identity/aidl/default/IdentityCredentialStore.h
new file mode 100644
index 0000000..a205113
--- /dev/null
+++ b/identity/aidl/default/IdentityCredentialStore.h
@@ -0,0 +1,48 @@
+/*
+ * 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 ANDROID_HARDWARE_IDENTITY_IDENTITYCREDENTIALSTORE_H
+#define ANDROID_HARDWARE_IDENTITY_IDENTITYCREDENTIALSTORE_H
+
+#include <aidl/android/hardware/identity/BnIdentityCredentialStore.h>
+
+namespace aidl::android::hardware::identity {
+
+using ::std::shared_ptr;
+using ::std::string;
+using ::std::vector;
+
+class IdentityCredentialStore : public BnIdentityCredentialStore {
+  public:
+    IdentityCredentialStore() {}
+
+    // The GCM chunk size used by this implementation is 64 KiB.
+    static constexpr size_t kGcmChunkSize = 64 * 1024;
+
+    // Methods from IIdentityCredentialStore follow.
+    ndk::ScopedAStatus getHardwareInformation(HardwareInformation* hardwareInformation) override;
+
+    ndk::ScopedAStatus createCredential(
+            const string& docType, bool testCredential,
+            shared_ptr<IWritableIdentityCredential>* outWritableCredential) override;
+
+    ndk::ScopedAStatus getCredential(CipherSuite cipherSuite, const vector<int8_t>& credentialData,
+                                     shared_ptr<IIdentityCredential>* outCredential) override;
+};
+
+}  // namespace aidl::android::hardware::identity
+
+#endif  // ANDROID_HARDWARE_IDENTITY_IDENTITYCREDENTIALSTORE_H
diff --git a/identity/aidl/default/Util.cpp b/identity/aidl/default/Util.cpp
new file mode 100644
index 0000000..a0f86be
--- /dev/null
+++ b/identity/aidl/default/Util.cpp
@@ -0,0 +1,117 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "Util"
+
+#include "Util.h"
+
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+
+#include <string.h>
+
+#include <android-base/logging.h>
+
+#include <cppbor.h>
+#include <cppbor_parse.h>
+
+namespace aidl::android::hardware::identity {
+
+using namespace ::android::hardware::identity;
+
+// This is not a very random HBK but that's OK because this is the SW
+// implementation where it can't be kept secret.
+vector<uint8_t> hardwareBoundKey = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+
+const vector<uint8_t>& getHardwareBoundKey() {
+    return hardwareBoundKey;
+}
+
+vector<uint8_t> byteStringToUnsigned(const vector<int8_t>& value) {
+    return vector<uint8_t>(value.begin(), value.end());
+}
+
+vector<int8_t> byteStringToSigned(const vector<uint8_t>& value) {
+    return vector<int8_t>(value.begin(), value.end());
+}
+
+vector<uint8_t> secureAccessControlProfileEncodeCbor(const SecureAccessControlProfile& profile) {
+    cppbor::Map map;
+    map.add("id", profile.id);
+
+    if (profile.readerCertificate.encodedCertificate.size() > 0) {
+        map.add("readerCertificate",
+                cppbor::Bstr(byteStringToUnsigned(profile.readerCertificate.encodedCertificate)));
+    }
+
+    if (profile.userAuthenticationRequired) {
+        map.add("userAuthenticationRequired", profile.userAuthenticationRequired);
+        map.add("timeoutMillis", profile.timeoutMillis);
+        map.add("secureUserId", profile.secureUserId);
+    }
+
+    return map.encode();
+}
+
+optional<vector<uint8_t>> secureAccessControlProfileCalcMac(
+        const SecureAccessControlProfile& profile, const vector<uint8_t>& storageKey) {
+    vector<uint8_t> cborData = secureAccessControlProfileEncodeCbor(profile);
+
+    optional<vector<uint8_t>> nonce = support::getRandom(12);
+    if (!nonce) {
+        return {};
+    }
+    optional<vector<uint8_t>> macO =
+            support::encryptAes128Gcm(storageKey, nonce.value(), {}, cborData);
+    if (!macO) {
+        return {};
+    }
+    return macO.value();
+}
+
+bool secureAccessControlProfileCheckMac(const SecureAccessControlProfile& profile,
+                                        const vector<uint8_t>& storageKey) {
+    vector<uint8_t> cborData = secureAccessControlProfileEncodeCbor(profile);
+
+    if (profile.mac.size() < support::kAesGcmIvSize) {
+        return false;
+    }
+    vector<uint8_t> nonce =
+            vector<uint8_t>(profile.mac.begin(), profile.mac.begin() + support::kAesGcmIvSize);
+    optional<vector<uint8_t>> mac = support::encryptAes128Gcm(storageKey, nonce, {}, cborData);
+    if (!mac) {
+        return false;
+    }
+    if (mac.value() != byteStringToUnsigned(profile.mac)) {
+        return false;
+    }
+    return true;
+}
+
+vector<uint8_t> entryCreateAdditionalData(const string& nameSpace, const string& name,
+                                          const vector<int32_t> accessControlProfileIds) {
+    cppbor::Map map;
+    map.add("Namespace", nameSpace);
+    map.add("Name", name);
+
+    cppbor::Array acpIds;
+    for (auto id : accessControlProfileIds) {
+        acpIds.add(id);
+    }
+    map.add("AccessControlProfileIds", std::move(acpIds));
+    return map.encode();
+}
+
+}  // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/Util.h b/identity/aidl/default/Util.h
new file mode 100644
index 0000000..ee41ad1
--- /dev/null
+++ b/identity/aidl/default/Util.h
@@ -0,0 +1,58 @@
+/*
+ * 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 ANDROID_HARDWARE_IDENTITY_UTIL_H
+#define ANDROID_HARDWARE_IDENTITY_UTIL_H
+
+#include <aidl/android/hardware/identity/BnIdentityCredential.h>
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+
+#include <map>
+#include <optional>
+#include <set>
+#include <string>
+#include <vector>
+
+#include <cppbor/cppbor.h>
+
+namespace aidl::android::hardware::identity {
+
+using ::std::optional;
+using ::std::string;
+using ::std::vector;
+
+// Returns the hardware-bound AES-128 key.
+const vector<uint8_t>& getHardwareBoundKey();
+
+// Calculates the MAC for |profile| using |storageKey|.
+optional<vector<uint8_t>> secureAccessControlProfileCalcMac(
+        const SecureAccessControlProfile& profile, const vector<uint8_t>& storageKey);
+
+// Checks authenticity of the MAC in |profile| using |storageKey|.
+bool secureAccessControlProfileCheckMac(const SecureAccessControlProfile& profile,
+                                        const vector<uint8_t>& storageKey);
+
+// Creates the AdditionalData CBOR used in the addEntryValue() HIDL method.
+vector<uint8_t> entryCreateAdditionalData(const string& nameSpace, const string& name,
+                                          const vector<int32_t> accessControlProfileIds);
+
+vector<uint8_t> byteStringToUnsigned(const vector<int8_t>& value);
+
+vector<int8_t> byteStringToSigned(const vector<uint8_t>& value);
+
+}  // namespace aidl::android::hardware::identity
+
+#endif  // ANDROID_HARDWARE_IDENTITY_UTIL_H
diff --git a/identity/aidl/default/WritableIdentityCredential.cpp b/identity/aidl/default/WritableIdentityCredential.cpp
new file mode 100644
index 0000000..89f7f35
--- /dev/null
+++ b/identity/aidl/default/WritableIdentityCredential.cpp
@@ -0,0 +1,372 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "WritableIdentityCredential"
+
+#include "WritableIdentityCredential.h"
+#include "IdentityCredentialStore.h"
+
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+
+#include <android-base/logging.h>
+
+#include <cppbor/cppbor.h>
+#include <cppbor/cppbor_parse.h>
+
+#include <utility>
+
+#include "IdentityCredentialStore.h"
+#include "Util.h"
+#include "WritableIdentityCredential.h"
+
+namespace aidl::android::hardware::identity {
+
+using ::std::optional;
+using namespace ::android::hardware::identity;
+
+bool WritableIdentityCredential::initialize() {
+    optional<vector<uint8_t>> random = support::getRandom(16);
+    if (!random) {
+        LOG(ERROR) << "Error creating storageKey";
+        return false;
+    }
+    storageKey_ = random.value();
+
+    return true;
+}
+
+// This function generates the attestation certificate using the passed in
+// |attestationApplicationId| and |attestationChallenge|.  It will generate an
+// attestation certificate with current time and expires one year from now.  The
+// certificate shall contain all values as specified in hal.
+ndk::ScopedAStatus WritableIdentityCredential::getAttestationCertificate(
+        const vector<int8_t>& attestationApplicationId,  //
+        const vector<int8_t>& attestationChallenge,      //
+        vector<Certificate>* outCertificateChain) {
+    if (!credentialPrivKey_.empty() || !credentialPubKey_.empty() || !certificateChain_.empty()) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED,
+                "Error attestation certificate previously generated"));
+    }
+
+    vector<uint8_t> challenge(attestationChallenge.begin(), attestationChallenge.end());
+    vector<uint8_t> appId(attestationApplicationId.begin(), attestationApplicationId.end());
+
+    optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> keyAttestationPair =
+            support::createEcKeyPairAndAttestation(challenge, appId);
+    if (!keyAttestationPair) {
+        LOG(ERROR) << "Error creating credentialKey and attestation";
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED,
+                "Error creating credentialKey and attestation"));
+    }
+
+    vector<uint8_t> keyPair = keyAttestationPair.value().first;
+    certificateChain_ = keyAttestationPair.value().second;
+
+    optional<vector<uint8_t>> pubKey = support::ecKeyPairGetPublicKey(keyPair);
+    if (!pubKey) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED,
+                "Error getting public part of credentialKey"));
+    }
+    credentialPubKey_ = pubKey.value();
+
+    optional<vector<uint8_t>> privKey = support::ecKeyPairGetPrivateKey(keyPair);
+    if (!privKey) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED,
+                "Error getting private part of credentialKey"));
+    }
+    credentialPrivKey_ = privKey.value();
+
+    // convert from vector<vector<uint8_t>>> to vector<Certificate>*
+    *outCertificateChain = vector<Certificate>();
+    for (const vector<uint8_t>& cert : certificateChain_) {
+        Certificate c = Certificate();
+        c.encodedCertificate = byteStringToSigned(cert);
+        outCertificateChain->push_back(std::move(c));
+    }
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus WritableIdentityCredential::startPersonalization(
+        int32_t accessControlProfileCount, const vector<int32_t>& entryCounts) {
+    numAccessControlProfileRemaining_ = accessControlProfileCount;
+    remainingEntryCounts_ = entryCounts;
+    entryNameSpace_ = "";
+
+    signedDataAccessControlProfiles_ = cppbor::Array();
+    signedDataNamespaces_ = cppbor::Map();
+    signedDataCurrentNamespace_ = cppbor::Array();
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus WritableIdentityCredential::addAccessControlProfile(
+        int32_t id, const Certificate& readerCertificate, bool userAuthenticationRequired,
+        int64_t timeoutMillis, int64_t secureUserId,
+        SecureAccessControlProfile* outSecureAccessControlProfile) {
+    SecureAccessControlProfile profile;
+
+    if (numAccessControlProfileRemaining_ == 0) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA,
+                "numAccessControlProfileRemaining_ is 0 and expected non-zero"));
+    }
+
+    // Spec requires if |userAuthenticationRequired| is false, then |timeoutMillis| must also
+    // be zero.
+    if (!userAuthenticationRequired && timeoutMillis != 0) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA,
+                "userAuthenticationRequired is false but timeout is non-zero"));
+    }
+
+    profile.id = id;
+    profile.readerCertificate = readerCertificate;
+    profile.userAuthenticationRequired = userAuthenticationRequired;
+    profile.timeoutMillis = timeoutMillis;
+    profile.secureUserId = secureUserId;
+    optional<vector<uint8_t>> mac = secureAccessControlProfileCalcMac(profile, storageKey_);
+    if (!mac) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Error calculating MAC for profile"));
+    }
+    profile.mac = byteStringToSigned(mac.value());
+
+    cppbor::Map profileMap;
+    profileMap.add("id", profile.id);
+    if (profile.readerCertificate.encodedCertificate.size() > 0) {
+        profileMap.add(
+                "readerCertificate",
+                cppbor::Bstr(byteStringToUnsigned(profile.readerCertificate.encodedCertificate)));
+    }
+    if (profile.userAuthenticationRequired) {
+        profileMap.add("userAuthenticationRequired", profile.userAuthenticationRequired);
+        profileMap.add("timeoutMillis", profile.timeoutMillis);
+    }
+    signedDataAccessControlProfiles_.add(std::move(profileMap));
+
+    numAccessControlProfileRemaining_--;
+
+    *outSecureAccessControlProfile = profile;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus WritableIdentityCredential::beginAddEntry(
+        const vector<int32_t>& accessControlProfileIds, const string& nameSpace, const string& name,
+        int32_t entrySize) {
+    if (numAccessControlProfileRemaining_ != 0) {
+        LOG(ERROR) << "numAccessControlProfileRemaining_ is " << numAccessControlProfileRemaining_
+                   << " and expected zero";
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA,
+                "numAccessControlProfileRemaining_ is not zero"));
+    }
+
+    if (remainingEntryCounts_.size() == 0) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA, "No more namespaces to add to"));
+    }
+
+    // Handle initial beginEntry() call.
+    if (entryNameSpace_ == "") {
+        entryNameSpace_ = nameSpace;
+    }
+
+    // If the namespace changed...
+    if (nameSpace != entryNameSpace_) {
+        // Then check that all entries in the previous namespace have been added..
+        if (remainingEntryCounts_[0] != 0) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_INVALID_DATA,
+                    "New namespace but a non-zero number of entries remain to be added"));
+        }
+        remainingEntryCounts_.erase(remainingEntryCounts_.begin());
+
+        if (signedDataCurrentNamespace_.size() > 0) {
+            signedDataNamespaces_.add(entryNameSpace_, std::move(signedDataCurrentNamespace_));
+            signedDataCurrentNamespace_ = cppbor::Array();
+        }
+    } else {
+        // Same namespace...
+        if (remainingEntryCounts_[0] == 0) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_INVALID_DATA,
+                    "Same namespace but no entries remain to be added"));
+        }
+        remainingEntryCounts_[0] -= 1;
+    }
+
+    entryAdditionalData_ = entryCreateAdditionalData(nameSpace, name, accessControlProfileIds);
+
+    entryRemainingBytes_ = entrySize;
+    entryNameSpace_ = nameSpace;
+    entryName_ = name;
+    entryAccessControlProfileIds_ = accessControlProfileIds;
+    entryBytes_.resize(0);
+    // LOG(INFO) << "name=" << name << " entrySize=" << entrySize;
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus WritableIdentityCredential::addEntryValue(const vector<int8_t>& contentS,
+                                                             vector<int8_t>* outEncryptedContent) {
+    auto content = byteStringToUnsigned(contentS);
+    size_t contentSize = content.size();
+
+    if (contentSize > IdentityCredentialStore::kGcmChunkSize) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA,
+                "Passed in chunk of is bigger than kGcmChunkSize"));
+    }
+    if (contentSize > entryRemainingBytes_) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_INVALID_DATA,
+                "Passed in chunk is bigger than remaining space"));
+    }
+
+    entryBytes_.insert(entryBytes_.end(), content.begin(), content.end());
+    entryRemainingBytes_ -= contentSize;
+    if (entryRemainingBytes_ > 0) {
+        if (contentSize != IdentityCredentialStore::kGcmChunkSize) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_INVALID_DATA,
+                    "Retrieved non-final chunk which isn't kGcmChunkSize"));
+        }
+    }
+
+    optional<vector<uint8_t>> nonce = support::getRandom(12);
+    if (!nonce) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Error getting nonce"));
+    }
+    optional<vector<uint8_t>> encryptedContent =
+            support::encryptAes128Gcm(storageKey_, nonce.value(), content, entryAdditionalData_);
+    if (!encryptedContent) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Error encrypting content"));
+    }
+
+    if (entryRemainingBytes_ == 0) {
+        // TODO: ideally do do this without parsing the data (but still validate data is valid
+        // CBOR).
+        auto [item, _, message] = cppbor::parse(entryBytes_);
+        if (item == nullptr) {
+            return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                    IIdentityCredentialStore::STATUS_INVALID_DATA, "Data is not valid CBOR"));
+        }
+        cppbor::Map entryMap;
+        entryMap.add("name", entryName_);
+        entryMap.add("value", std::move(item));
+        cppbor::Array profileIdArray;
+        for (auto id : entryAccessControlProfileIds_) {
+            profileIdArray.add(id);
+        }
+        entryMap.add("accessControlProfiles", std::move(profileIdArray));
+        signedDataCurrentNamespace_.add(std::move(entryMap));
+    }
+
+    *outEncryptedContent = byteStringToSigned(encryptedContent.value());
+    return ndk::ScopedAStatus::ok();
+}
+
+// Writes CBOR-encoded structure to |credentialKeys| containing |storageKey| and
+// |credentialPrivKey|.
+static bool generateCredentialKeys(const vector<uint8_t>& storageKey,
+                                   const vector<uint8_t>& credentialPrivKey,
+                                   vector<uint8_t>& credentialKeys) {
+    if (storageKey.size() != 16) {
+        LOG(ERROR) << "Size of storageKey is not 16";
+        return false;
+    }
+
+    cppbor::Array array;
+    array.add(cppbor::Bstr(storageKey));
+    array.add(cppbor::Bstr(credentialPrivKey));
+    credentialKeys = array.encode();
+    return true;
+}
+
+// Writes CBOR-encoded structure to |credentialData| containing |docType|,
+// |testCredential| and |credentialKeys|. The latter element will be stored in
+// encrypted form, using |hardwareBoundKey| as the encryption key.
+bool generateCredentialData(const vector<uint8_t>& hardwareBoundKey, const string& docType,
+                            bool testCredential, const vector<uint8_t>& credentialKeys,
+                            vector<uint8_t>& credentialData) {
+    optional<vector<uint8_t>> nonce = support::getRandom(12);
+    if (!nonce) {
+        LOG(ERROR) << "Error getting random";
+        return false;
+    }
+    vector<uint8_t> docTypeAsVec(docType.begin(), docType.end());
+    optional<vector<uint8_t>> credentialBlob = support::encryptAes128Gcm(
+            hardwareBoundKey, nonce.value(), credentialKeys, docTypeAsVec);
+    if (!credentialBlob) {
+        LOG(ERROR) << "Error encrypting CredentialKeys blob";
+        return false;
+    }
+
+    cppbor::Array array;
+    array.add(docType);
+    array.add(testCredential);
+    array.add(cppbor::Bstr(credentialBlob.value()));
+    credentialData = array.encode();
+    return true;
+}
+
+ndk::ScopedAStatus WritableIdentityCredential::finishAddingEntries(
+        vector<int8_t>* outCredentialData, vector<int8_t>* outProofOfProvisioningSignature) {
+    if (signedDataCurrentNamespace_.size() > 0) {
+        signedDataNamespaces_.add(entryNameSpace_, std::move(signedDataCurrentNamespace_));
+    }
+    cppbor::Array popArray;
+    popArray.add("ProofOfProvisioning")
+            .add(docType_)
+            .add(std::move(signedDataAccessControlProfiles_))
+            .add(std::move(signedDataNamespaces_))
+            .add(testCredential_);
+    vector<uint8_t> encodedCbor = popArray.encode();
+
+    optional<vector<uint8_t>> signature = support::coseSignEcDsa(credentialPrivKey_,
+                                                                 encodedCbor,  // payload
+                                                                 {},           // additionalData
+                                                                 {});          // certificateChain
+    if (!signature) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Error signing data"));
+    }
+
+    vector<uint8_t> credentialKeys;
+    if (!generateCredentialKeys(storageKey_, credentialPrivKey_, credentialKeys)) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Error generating CredentialKeys"));
+    }
+
+    vector<uint8_t> credentialData;
+    if (!generateCredentialData(
+                testCredential_ ? support::getTestHardwareBoundKey() : getHardwareBoundKey(),
+                docType_, testCredential_, credentialKeys, credentialData)) {
+        return ndk::ScopedAStatus(AStatus_fromServiceSpecificErrorWithMessage(
+                IIdentityCredentialStore::STATUS_FAILED, "Error generating CredentialData"));
+    }
+
+    *outCredentialData = byteStringToSigned(credentialData);
+    *outProofOfProvisioningSignature = byteStringToSigned(signature.value());
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace aidl::android::hardware::identity
diff --git a/identity/aidl/default/WritableIdentityCredential.h b/identity/aidl/default/WritableIdentityCredential.h
new file mode 100644
index 0000000..b182862
--- /dev/null
+++ b/identity/aidl/default/WritableIdentityCredential.h
@@ -0,0 +1,93 @@
+/*
+ * 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 ANDROID_HARDWARE_IDENTITY_WRITABLEIDENTITYCREDENTIAL_H
+#define ANDROID_HARDWARE_IDENTITY_WRITABLEIDENTITYCREDENTIAL_H
+
+#include <aidl/android/hardware/identity/BnWritableIdentityCredential.h>
+#include <android/hardware/identity/support/IdentityCredentialSupport.h>
+
+#include <cppbor.h>
+
+namespace aidl::android::hardware::identity {
+
+using ::std::string;
+using ::std::vector;
+
+class WritableIdentityCredential : public BnWritableIdentityCredential {
+  public:
+    WritableIdentityCredential(const string& docType, bool testCredential)
+        : docType_(docType), testCredential_(testCredential) {}
+
+    // Creates the Credential Key. Returns false on failure. Must be called
+    // right after construction.
+    bool initialize();
+
+    // Methods from IWritableIdentityCredential follow.
+    ndk::ScopedAStatus getAttestationCertificate(const vector<int8_t>& attestationApplicationId,
+                                                 const vector<int8_t>& attestationChallenge,
+                                                 vector<Certificate>* outCertificateChain) override;
+
+    ndk::ScopedAStatus startPersonalization(int32_t accessControlProfileCount,
+                                            const vector<int32_t>& entryCounts) override;
+
+    ndk::ScopedAStatus addAccessControlProfile(
+            int32_t id, const Certificate& readerCertificate, bool userAuthenticationRequired,
+            int64_t timeoutMillis, int64_t secureUserId,
+            SecureAccessControlProfile* outSecureAccessControlProfile) override;
+
+    ndk::ScopedAStatus beginAddEntry(const vector<int32_t>& accessControlProfileIds,
+                                     const string& nameSpace, const string& name,
+                                     int32_t entrySize) override;
+
+    ndk::ScopedAStatus addEntryValue(const vector<int8_t>& content,
+                                     vector<int8_t>* outEncryptedContent) override;
+
+    ndk::ScopedAStatus finishAddingEntries(
+            vector<int8_t>* outCredentialData,
+            vector<int8_t>* outProofOfProvisioningSignature) override;
+
+    // private:
+    string docType_;
+    bool testCredential_;
+
+    // This is set in initialize().
+    vector<uint8_t> storageKey_;
+
+    // These are set in getAttestationCertificate().
+    vector<uint8_t> credentialPrivKey_;
+    vector<uint8_t> credentialPubKey_;
+    vector<vector<uint8_t>> certificateChain_;
+
+    // These fields are initialized during startPersonalization()
+    size_t numAccessControlProfileRemaining_;
+    vector<int32_t> remainingEntryCounts_;
+    cppbor::Array signedDataAccessControlProfiles_;
+    cppbor::Map signedDataNamespaces_;
+    cppbor::Array signedDataCurrentNamespace_;
+
+    // These fields are initialized during beginAddEntry()
+    size_t entryRemainingBytes_;
+    vector<uint8_t> entryAdditionalData_;
+    string entryNameSpace_;
+    string entryName_;
+    vector<int32_t> entryAccessControlProfileIds_;
+    vector<uint8_t> entryBytes_;
+};
+
+}  // namespace aidl::android::hardware::identity
+
+#endif  // ANDROID_HARDWARE_IDENTITY_WRITABLEIDENTITYCREDENTIAL_H
diff --git a/identity/aidl/default/identity-default.rc b/identity/aidl/default/identity-default.rc
new file mode 100644
index 0000000..d3b62c1
--- /dev/null
+++ b/identity/aidl/default/identity-default.rc
@@ -0,0 +1,3 @@
+service vendor.identity-default /vendor/bin/hw/android.hardware.identity-service.example
+    class hal
+    user nobody
diff --git a/identity/aidl/default/identity-default.xml b/identity/aidl/default/identity-default.xml
new file mode 100644
index 0000000..a47d354
--- /dev/null
+++ b/identity/aidl/default/identity-default.xml
@@ -0,0 +1,9 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.identity</name>
+        <interface>
+            <name>IIdentityCredentialStore</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/identity/aidl/default/service.cpp b/identity/aidl/default/service.cpp
new file mode 100644
index 0000000..f05c615
--- /dev/null
+++ b/identity/aidl/default/service.cpp
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "android.hardware.identity-service"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include "IdentityCredentialStore.h"
+
+using aidl::android::hardware::identity::IdentityCredentialStore;
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    std::shared_ptr<IdentityCredentialStore> store =
+            ndk::SharedRefBase::make<IdentityCredentialStore>();
+
+    const std::string instance = std::string() + IdentityCredentialStore::descriptor + "/default";
+    LOG(INFO) << "instance: " << instance;
+    binder_status_t status = AServiceManager_addService(store->asBinder().get(), instance.c_str());
+    CHECK(status == STATUS_OK);
+
+    ABinderProcess_joinThreadPool();
+    return EXIT_FAILURE;  // should not reach
+}
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
new file mode 100644
index 0000000..cecc814
--- /dev/null
+++ b/identity/aidl/vts/Android.bp
@@ -0,0 +1,22 @@
+cc_test {
+    name: "VtsHalIdentityTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
+    ],
+    srcs: ["VtsHalIdentityTargetTest.cpp"],
+    shared_libs: [
+        "libbinder",
+        "libcrypto",
+    ],
+    static_libs: [
+        "libcppbor",
+        "android.hardware.identity-support-lib",
+        "android.hardware.identity-cpp",
+        "android.hardware.keymaster-cpp",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
+}
diff --git a/identity/aidl/vts/VtsHalIdentityTargetTest.cpp b/identity/aidl/vts/VtsHalIdentityTargetTest.cpp
new file mode 100644
index 0000000..ea37fdc
--- /dev/null
+++ b/identity/aidl/vts/VtsHalIdentityTargetTest.cpp
@@ -0,0 +1,446 @@
+/*
+ * 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 "VtsHalIdentityTargetTest"
+
+#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>
+
+namespace android::hardware::identity {
+
+using std::map;
+using std::optional;
+using std::string;
+using std::vector;
+
+using ::android::sp;
+using ::android::String16;
+using ::android::binder::Status;
+
+using ::android::hardware::keymaster::HardwareAuthToken;
+
+// ---------------------------------------------------------------------------
+// Test Data.
+// ---------------------------------------------------------------------------
+
+struct TestEntryData {
+    TestEntryData(string nameSpace, string name, vector<int32_t> profileIds)
+        : nameSpace(nameSpace), name(name), profileIds(profileIds) {}
+
+    TestEntryData(string nameSpace, string name, const string& value, vector<int32_t> profileIds)
+        : TestEntryData(nameSpace, name, profileIds) {
+        valueCbor = cppbor::Tstr(((const char*)value.data())).encode();
+    }
+    TestEntryData(string nameSpace, string name, const vector<uint8_t>& value,
+                  vector<int32_t> profileIds)
+        : TestEntryData(nameSpace, name, profileIds) {
+        valueCbor = cppbor::Bstr(value).encode();
+    }
+    TestEntryData(string nameSpace, string name, bool value, vector<int32_t> profileIds)
+        : TestEntryData(nameSpace, name, profileIds) {
+        valueCbor = cppbor::Bool(value).encode();
+    }
+    TestEntryData(string nameSpace, string name, int64_t value, vector<int32_t> profileIds)
+        : TestEntryData(nameSpace, name, profileIds) {
+        if (value >= 0) {
+            valueCbor = cppbor::Uint(value).encode();
+        } else {
+            valueCbor = cppbor::Nint(-value).encode();
+        }
+    }
+
+    string nameSpace;
+    string name;
+    vector<uint8_t> valueCbor;
+    vector<int32_t> profileIds;
+};
+
+struct TestProfile {
+    uint16_t id;
+    vector<uint8_t> readerCertificate;
+    bool userAuthenticationRequired;
+    uint64_t timeoutMillis;
+};
+
+// ----------------------------------------------------------------
+
+class IdentityAidl : 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(IdentityAidl, hardwareInformation) {
+    HardwareInformation info;
+    ASSERT_TRUE(credentialStore_->getHardwareInformation(&info).isOk());
+    ASSERT_GT(info.credentialStoreName.size(), 0);
+    ASSERT_GT(info.credentialStoreAuthorName.size(), 0);
+    ASSERT_GE(info.dataChunkSize, 256);
+}
+
+TEST_P(IdentityAidl, createAndRetrieveCredential) {
+    // First, generate a key-pair for the reader since its public key will be
+    // part of the request data.
+    optional<vector<uint8_t>> readerKeyPKCS8 = support::createEcKeyPair();
+    ASSERT_TRUE(readerKeyPKCS8);
+    optional<vector<uint8_t>> readerPublicKey =
+            support::ecKeyPairGetPublicKey(readerKeyPKCS8.value());
+    optional<vector<uint8_t>> readerKey = support::ecKeyPairGetPrivateKey(readerKeyPKCS8.value());
+    string serialDecimal = "1234";
+    string issuer = "Android Open Source Project";
+    string subject = "Android IdentityCredential VTS Test";
+    time_t validityNotBefore = time(nullptr);
+    time_t validityNotAfter = validityNotBefore + 365 * 24 * 3600;
+    optional<vector<uint8_t>> readerCertificate = support::ecPublicKeyGenerateCertificate(
+            readerPublicKey.value(), readerKey.value(), serialDecimal, issuer, subject,
+            validityNotBefore, validityNotAfter);
+    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;
+    portraitImage.resize(256 * 1024 - 10);
+    for (size_t n = 0; n < portraitImage.size(); n++) {
+        portraitImage[n] = (uint8_t)n;
+    }
+
+    // Access control profiles:
+    const vector<TestProfile> testProfiles = {// Profile 0 (reader authentication)
+                                              {0, readerCertificate.value(), false, 0},
+                                              // Profile 1 (no authentication)
+                                              {1, {}, false, 0}};
+
+    HardwareAuthToken authToken;
+
+    // Here's the actual test data:
+    const vector<TestEntryData> testEntries = {
+            {"PersonalData", "Last name", string("Turing"), vector<int32_t>{0, 1}},
+            {"PersonalData", "Birth date", string("19120623"), vector<int32_t>{0, 1}},
+            {"PersonalData", "First name", string("Alan"), vector<int32_t>{0, 1}},
+            {"PersonalData", "Home address", string("Maida Vale, London, England"),
+             vector<int32_t>{0}},
+            {"Image", "Portrait image", portraitImage, vector<int32_t>{0, 1}},
+    };
+    const vector<int32_t> testEntriesEntryCounts = {static_cast<int32_t>(testEntries.size() - 1),
+                                                    1u};
+    HardwareInformation hwInfo;
+    ASSERT_TRUE(credentialStore_->getHardwareInformation(&hwInfo).isOk());
+
+    string cborPretty;
+    sp<IWritableIdentityCredential> writableCredential;
+    string docType = "org.iso.18013-5.2019.mdl";
+    bool testCredential = true;
+    ASSERT_TRUE(credentialStore_->createCredential(docType, testCredential, &writableCredential)
+                        .isOk());
+    ASSERT_NE(writableCredential, nullptr);
+
+    string challenge = "attestationChallenge";
+    // TODO: set it to something random and check it's in the cert chain
+    vector<uint8_t> attestationApplicationId = {};
+    vector<uint8_t> attestationChallenge(challenge.begin(), challenge.end());
+    vector<Certificate> attestationCertificates;
+    ASSERT_TRUE(writableCredential
+                        ->getAttestationCertificate(attestationApplicationId, attestationChallenge,
+                                                    &attestationCertificates)
+                        .isOk());
+    ASSERT_GE(attestationCertificates.size(), 2);
+
+    ASSERT_TRUE(
+            writableCredential->startPersonalization(testProfiles.size(), testEntriesEntryCounts)
+                    .isOk());
+
+    vector<SecureAccessControlProfile> returnedSecureProfiles;
+    for (const auto& testProfile : testProfiles) {
+        SecureAccessControlProfile profile;
+        Certificate cert;
+        cert.encodedCertificate = testProfile.readerCertificate;
+        ASSERT_TRUE(writableCredential
+                            ->addAccessControlProfile(testProfile.id, cert,
+                                                      testProfile.userAuthenticationRequired,
+                                                      testProfile.timeoutMillis,
+                                                      0,  // secureUserId
+                                                      &profile)
+                            .isOk());
+        ASSERT_EQ(testProfile.id, profile.id);
+        ASSERT_EQ(testProfile.readerCertificate, profile.readerCertificate.encodedCertificate);
+        ASSERT_EQ(testProfile.userAuthenticationRequired, profile.userAuthenticationRequired);
+        ASSERT_EQ(testProfile.timeoutMillis, profile.timeoutMillis);
+        ASSERT_EQ(support::kAesGcmTagSize + support::kAesGcmIvSize, profile.mac.size());
+        returnedSecureProfiles.push_back(profile);
+    }
+
+    // Uses TestEntryData* pointer as key and values are the encrypted blobs. This
+    // is a little hacky but it works well enough.
+    map<const TestEntryData*, vector<vector<uint8_t>>> encryptedBlobs;
+
+    for (const auto& entry : testEntries) {
+        vector<vector<uint8_t>> chunks =
+                support::chunkVector(entry.valueCbor, hwInfo.dataChunkSize);
+
+        ASSERT_TRUE(writableCredential
+                            ->beginAddEntry(entry.profileIds, entry.nameSpace, entry.name,
+                                            entry.valueCbor.size())
+                            .isOk());
+
+        vector<vector<uint8_t>> encryptedChunks;
+        for (const auto& chunk : chunks) {
+            vector<uint8_t> encryptedChunk;
+            ASSERT_TRUE(writableCredential->addEntryValue(chunk, &encryptedChunk).isOk());
+            encryptedChunks.push_back(encryptedChunk);
+        }
+        encryptedBlobs[&entry] = encryptedChunks;
+    }
+
+    vector<uint8_t> credentialData;
+    vector<uint8_t> proofOfProvisioningSignature;
+    ASSERT_TRUE(
+            writableCredential->finishAddingEntries(&credentialData, &proofOfProvisioningSignature)
+                    .isOk());
+
+    optional<vector<uint8_t>> proofOfProvisioning =
+            support::coseSignGetPayload(proofOfProvisioningSignature);
+    ASSERT_TRUE(proofOfProvisioning);
+    cborPretty = support::cborPrettyPrint(proofOfProvisioning.value(), 32, {"readerCertificate"});
+    EXPECT_EQ(
+            "[\n"
+            "  'ProofOfProvisioning',\n"
+            "  'org.iso.18013-5.2019.mdl',\n"
+            "  [\n"
+            "    {\n"
+            "      'id' : 0,\n"
+            "      'readerCertificate' : <not printed>,\n"
+            "    },\n"
+            "    {\n"
+            "      'id' : 1,\n"
+            "    },\n"
+            "  ],\n"
+            "  {\n"
+            "    'PersonalData' : [\n"
+            "      {\n"
+            "        'name' : 'Last name',\n"
+            "        'value' : 'Turing',\n"
+            "        'accessControlProfiles' : [0, 1, ],\n"
+            "      },\n"
+            "      {\n"
+            "        'name' : 'Birth date',\n"
+            "        'value' : '19120623',\n"
+            "        'accessControlProfiles' : [0, 1, ],\n"
+            "      },\n"
+            "      {\n"
+            "        'name' : 'First name',\n"
+            "        'value' : 'Alan',\n"
+            "        'accessControlProfiles' : [0, 1, ],\n"
+            "      },\n"
+            "      {\n"
+            "        'name' : 'Home address',\n"
+            "        'value' : 'Maida Vale, London, England',\n"
+            "        'accessControlProfiles' : [0, ],\n"
+            "      },\n"
+            "    ],\n"
+            "    'Image' : [\n"
+            "      {\n"
+            "        'name' : 'Portrait image',\n"
+            "        'value' : <bstr size=262134 sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
+            "        'accessControlProfiles' : [0, 1, ],\n"
+            "      },\n"
+            "    ],\n"
+            "  },\n"
+            "  true,\n"
+            "]",
+            cborPretty);
+
+    optional<vector<uint8_t>> credentialPubKey =
+            support::certificateChainGetTopMostKey(attestationCertificates[0].encodedCertificate);
+    ASSERT_TRUE(credentialPubKey);
+    EXPECT_TRUE(support::coseCheckEcDsaSignature(proofOfProvisioningSignature,
+                                                 {},  // Additional data
+                                                 credentialPubKey.value()));
+    writableCredential = nullptr;
+
+    // Now that the credential has been provisioned, read it back and check the
+    // correct data is returned.
+    sp<IIdentityCredential> credential;
+    ASSERT_TRUE(credentialStore_
+                        ->getCredential(
+                                CipherSuite::CIPHERSUITE_ECDHE_HKDF_ECDSA_WITH_AES_256_GCM_SHA256,
+                                credentialData, &credential)
+                        .isOk());
+    ASSERT_NE(credential, nullptr);
+
+    optional<vector<uint8_t>> readerEphemeralKeyPair = support::createEcKeyPair();
+    ASSERT_TRUE(readerEphemeralKeyPair);
+    optional<vector<uint8_t>> readerEphemeralPublicKey =
+            support::ecKeyPairGetPublicKey(readerEphemeralKeyPair.value());
+    ASSERT_TRUE(credential->setReaderEphemeralPublicKey(readerEphemeralPublicKey.value()).isOk());
+
+    vector<uint8_t> ephemeralKeyPair;
+    ASSERT_TRUE(credential->createEphemeralKeyPair(&ephemeralKeyPair).isOk());
+    optional<vector<uint8_t>> ephemeralPublicKey = support::ecKeyPairGetPublicKey(ephemeralKeyPair);
+
+    // Calculate requestData field and sign it with the reader key.
+    auto [getXYSuccess, ephX, ephY] = support::ecPublicKeyGetXandY(ephemeralPublicKey.value());
+    ASSERT_TRUE(getXYSuccess);
+    cppbor::Map deviceEngagement = cppbor::Map().add("ephX", ephX).add("ephY", ephY);
+    vector<uint8_t> deviceEngagementBytes = deviceEngagement.encode();
+    vector<uint8_t> eReaderPubBytes = cppbor::Tstr("ignored").encode();
+    cppbor::Array sessionTranscript = cppbor::Array()
+                                              .add(cppbor::Semantic(24, deviceEngagementBytes))
+                                              .add(cppbor::Semantic(24, eReaderPubBytes));
+    vector<uint8_t> sessionTranscriptBytes = sessionTranscript.encode();
+
+    vector<uint8_t> itemsRequestBytes =
+            cppbor::Map("nameSpaces",
+                        cppbor::Map()
+                                .add("PersonalData", cppbor::Map()
+                                                             .add("Last name", false)
+                                                             .add("Birth date", false)
+                                                             .add("First name", false)
+                                                             .add("Home address", true))
+                                .add("Image", cppbor::Map().add("Portrait image", false)))
+                    .encode();
+    cborPretty = support::cborPrettyPrint(itemsRequestBytes, 32, {"EphemeralPublicKey"});
+    EXPECT_EQ(
+            "{\n"
+            "  'nameSpaces' : {\n"
+            "    'PersonalData' : {\n"
+            "      'Last name' : false,\n"
+            "      'Birth date' : false,\n"
+            "      'First name' : false,\n"
+            "      'Home address' : true,\n"
+            "    },\n"
+            "    'Image' : {\n"
+            "      'Portrait image' : false,\n"
+            "    },\n"
+            "  },\n"
+            "}",
+            cborPretty);
+    vector<uint8_t> dataToSign = cppbor::Array()
+                                         .add("ReaderAuthentication")
+                                         .add(sessionTranscript.clone())
+                                         .add(cppbor::Semantic(24, itemsRequestBytes))
+                                         .encode();
+    optional<vector<uint8_t>> readerSignature =
+            support::coseSignEcDsa(readerKey.value(), {},  // content
+                                   dataToSign,             // detached content
+                                   readerCertificate.value());
+    ASSERT_TRUE(readerSignature);
+
+    // Generate the key that will be used to sign AuthenticatedData.
+    vector<uint8_t> signingKeyBlob;
+    Certificate signingKeyCertificate;
+    ASSERT_TRUE(credential->generateSigningKeyPair(&signingKeyBlob, &signingKeyCertificate).isOk());
+
+    ASSERT_TRUE(credential
+                        ->startRetrieval(returnedSecureProfiles, authToken, itemsRequestBytes,
+                                         signingKeyBlob, sessionTranscriptBytes,
+                                         readerSignature.value(), testEntriesEntryCounts)
+                        .isOk());
+
+    for (const auto& entry : testEntries) {
+        ASSERT_TRUE(credential
+                            ->startRetrieveEntryValue(entry.nameSpace, entry.name,
+                                                      entry.valueCbor.size(), entry.profileIds)
+                            .isOk());
+
+        auto it = encryptedBlobs.find(&entry);
+        ASSERT_NE(it, encryptedBlobs.end());
+        const vector<vector<uint8_t>>& encryptedChunks = it->second;
+
+        vector<uint8_t> content;
+        for (const auto& encryptedChunk : encryptedChunks) {
+            vector<uint8_t> chunk;
+            ASSERT_TRUE(credential->retrieveEntryValue(encryptedChunk, &chunk).isOk());
+            content.insert(content.end(), chunk.begin(), chunk.end());
+        }
+        EXPECT_EQ(content, entry.valueCbor);
+    }
+
+    vector<uint8_t> mac;
+    vector<uint8_t> deviceNameSpacesBytes;
+    ASSERT_TRUE(credential->finishRetrieval(&mac, &deviceNameSpacesBytes).isOk());
+    cborPretty = support::cborPrettyPrint(deviceNameSpacesBytes, 32, {});
+    ASSERT_EQ(
+            "{\n"
+            "  'PersonalData' : {\n"
+            "    'Last name' : 'Turing',\n"
+            "    'Birth date' : '19120623',\n"
+            "    'First name' : 'Alan',\n"
+            "    'Home address' : 'Maida Vale, London, England',\n"
+            "  },\n"
+            "  'Image' : {\n"
+            "    'Portrait image' : <bstr size=262134 "
+            "sha1=941e372f654d86c32d88fae9e41b706afbfd02bb>,\n"
+            "  },\n"
+            "}",
+            cborPretty);
+    // The data that is MACed is ["DeviceAuthentication", sessionTranscriptBytes, docType,
+    // deviceNameSpacesBytes] so build up that structure
+    cppbor::Array deviceAuthentication;
+    deviceAuthentication.add("DeviceAuthentication");
+    deviceAuthentication.add(sessionTranscript.clone());
+    deviceAuthentication.add(docType);
+    deviceAuthentication.add(cppbor::Semantic(24, deviceNameSpacesBytes));
+    vector<uint8_t> encodedDeviceAuthentication = deviceAuthentication.encode();
+    optional<vector<uint8_t>> signingPublicKey =
+            support::certificateChainGetTopMostKey(signingKeyCertificate.encodedCertificate);
+    EXPECT_TRUE(signingPublicKey);
+
+    // Derive the key used for MACing.
+    optional<vector<uint8_t>> readerEphemeralPrivateKey =
+            support::ecKeyPairGetPrivateKey(readerEphemeralKeyPair.value());
+    optional<vector<uint8_t>> sharedSecret =
+            support::ecdh(signingPublicKey.value(), readerEphemeralPrivateKey.value());
+    ASSERT_TRUE(sharedSecret);
+    vector<uint8_t> salt = {0x00};
+    vector<uint8_t> info = {};
+    optional<vector<uint8_t>> derivedKey = support::hkdf(sharedSecret.value(), salt, info, 32);
+    ASSERT_TRUE(derivedKey);
+    optional<vector<uint8_t>> calculatedMac =
+            support::coseMac0(derivedKey.value(), {},        // payload
+                              encodedDeviceAuthentication);  // detached content
+    ASSERT_TRUE(calculatedMac);
+    EXPECT_EQ(mac, calculatedMac);
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        Identity, IdentityAidl,
+        testing::ValuesIn(android::getAidlHalInstanceNames(IIdentityCredentialStore::descriptor)),
+        android::PrintInstanceNameToString);
+// INSTANTIATE_TEST_SUITE_P(Identity, IdentityAidl,
+// testing::Values("android.hardware.identity.IIdentityCredentialStore/default"));
+
+}  // namespace android::hardware::identity
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ::android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
+    ::android::ProcessState::self()->startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/identity/support/Android.bp b/identity/support/Android.bp
index 38dc10b..2b6c695 100644
--- a/identity/support/Android.bp
+++ b/identity/support/Android.bp
@@ -23,11 +23,14 @@
         "include",
     ],
     shared_libs: [
-        "android.hardware.identity@1.0",
+        "android.hardware.keymaster@4.0",
         "libcrypto",
         "libbase",
         "libhidlbase",
         "libhardware",
+        "libkeymaster_portable",
+        "libsoft_attestation_cert",
+        "libpuresoftkeymasterdevice",
     ],
     static_libs: [
         "libcppbor",
@@ -41,7 +44,6 @@
     ],
     shared_libs: [
         "android.hardware.identity-support-lib",
-        "android.hardware.identity@1.0",
         "libcrypto",
         "libbase",
         "libhidlbase",
diff --git a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
index 485571a..507e914 100644
--- a/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
+++ b/identity/support/include/android/hardware/identity/support/IdentityCredentialSupport.h
@@ -18,12 +18,12 @@
 #define IDENTITY_SUPPORT_INCLUDE_IDENTITY_CREDENTIAL_UTILS_H_
 
 #include <cstdint>
+#include <optional>
 #include <string>
 #include <tuple>
+#include <utility>
 #include <vector>
 
-#include <android/hardware/identity/1.0/types.h>
-
 namespace android {
 namespace hardware {
 namespace identity {
@@ -34,10 +34,6 @@
 using ::std::tuple;
 using ::std::vector;
 
-using ::android::hardware::identity::V1_0::Result;
-using ::android::hardware::identity::V1_0::ResultCode;
-using ::android::hardware::identity::V1_0::SecureAccessControlProfile;
-
 // ---------------------------------------------------------------------------
 // Miscellaneous utilities.
 // ---------------------------------------------------------------------------
@@ -111,6 +107,17 @@
 // ---------------------------------------------------------------------------
 // EC crypto functionality / abstraction (only supports P-256).
 // ---------------------------------------------------------------------------
+// Creates an 256-bit EC key using the NID_X9_62_prime256v1 curve, returns the
+// PKCS#8 encoded key-pair.  Also generates an attestation
+// certificate using the |challenge| and |applicationId|, and returns the generated
+// certificate in X.509 certificate chain format.
+//
+// The attestation time fields used will be the current time, and expires in one year.
+//
+// The first parameter of the return value is the keyPair generated, second return in
+// the pair is the attestation certificate generated.
+optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAndAttestation(
+        const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId);
 
 // Creates an 256-bit EC key using the NID_X9_62_prime256v1 curve, returns the
 // PKCS#8 encoded key-pair.
@@ -258,21 +265,11 @@
                                    const vector<uint8_t>& detachedContent);
 
 // ---------------------------------------------------------------------------
-// Platform abstraction.
-// ---------------------------------------------------------------------------
-
-// Returns the hardware-bound AES-128 key.
-const vector<uint8_t>& getHardwareBoundKey();
-
-// ---------------------------------------------------------------------------
 // Utility functions specific to IdentityCredential.
 // ---------------------------------------------------------------------------
 
-// Returns a reference to a Result with code OK and empty message.
-const Result& resultOK();
-
-// Returns a new Result with the given code and message.
-Result result(ResultCode code, const char* format, ...) __attribute__((format(printf, 2, 3)));
+// Returns the testing AES-128 key where all bits are set to 0.
+const vector<uint8_t>& getTestHardwareBoundKey();
 
 // Splits the given bytestring into chunks. If the given vector is smaller or equal to
 // |maxChunkSize| a vector with |content| as the only element is returned. Otherwise
@@ -280,21 +277,6 @@
 // may be smaller than |maxChunkSize|.
 vector<vector<uint8_t>> chunkVector(const vector<uint8_t>& content, size_t maxChunkSize);
 
-// Calculates the MAC for |profile| using |storageKey|.
-optional<vector<uint8_t>> secureAccessControlProfileCalcMac(
-        const SecureAccessControlProfile& profile, const vector<uint8_t>& storageKey);
-
-// Checks authenticity of the MAC in |profile| using |storageKey|.
-bool secureAccessControlProfileCheckMac(const SecureAccessControlProfile& profile,
-                                        const vector<uint8_t>& storageKey);
-
-// Returns the testing AES-128 key where all bits are set to 0.
-const vector<uint8_t>& getTestHardwareBoundKey();
-
-// Creates the AdditionalData CBOR used in the addEntryValue() HIDL method.
-vector<uint8_t> entryCreateAdditionalData(const string& nameSpace, const string& name,
-                                          const vector<uint16_t> accessControlProfileIds);
-
 }  // namespace support
 }  // namespace identity
 }  // namespace hardware
diff --git a/identity/support/src/IdentityCredentialSupport.cpp b/identity/support/src/IdentityCredentialSupport.cpp
index 7d93a4b..bf6a5c3 100644
--- a/identity/support/src/IdentityCredentialSupport.cpp
+++ b/identity/support/src/IdentityCredentialSupport.cpp
@@ -47,6 +47,13 @@
 #include <cppbor.h>
 #include <cppbor_parse.h>
 
+#include <android/hardware/keymaster/4.0/types.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>
+
 namespace android {
 namespace hardware {
 namespace identity {
@@ -816,6 +823,138 @@
     return hmac;
 }
 
+// Generates the attestation certificate with the parameters passed in.  Note
+// that the passed in |activeTimeMilliSeconds| |expireTimeMilliSeconds| are in
+// milli seconds since epoch.  We are setting them to milliseconds due to
+// requirement in AuthorizationSet KM_DATE fields.  The certificate created is
+// actually in seconds.
+optional<vector<vector<uint8_t>>> createAttestation(const EVP_PKEY* key,
+                                                    const vector<uint8_t>& applicationId,
+                                                    const vector<uint8_t>& challenge,
+                                                    uint64_t activeTimeMilliSeconds,
+                                                    uint64_t expireTimeMilliSeconds) {
+    ::keymaster::AuthorizationSet auth_set(
+            ::keymaster::AuthorizationSetBuilder()
+                    .Authorization(::keymaster::TAG_ATTESTATION_CHALLENGE, challenge.data(),
+                                   challenge.size())
+                    .Authorization(::keymaster::TAG_ACTIVE_DATETIME, activeTimeMilliSeconds)
+                    // Even though identity attestation hal said the application
+                    // id should be in software enforced authentication set,
+                    // keymaster portable lib expect the input in this
+                    // parameter because the software enforced in input to keymaster
+                    // refers to the key software enforced properties. And this
+                    // parameter refers to properties of the attestation which
+                    // includes app id.
+                    .Authorization(::keymaster::TAG_ATTESTATION_APPLICATION_ID,
+                                   applicationId.data(), applicationId.size())
+                    .Authorization(::keymaster::TAG_USAGE_EXPIRE_DATETIME, expireTimeMilliSeconds));
+
+    // Unique id and device id is not applicable for identity credential attestation,
+    // so we don't need to set those or application id.
+    ::keymaster::AuthorizationSet swEnforced(::keymaster::AuthorizationSetBuilder().Authorization(
+            ::keymaster::TAG_CREATION_DATETIME, activeTimeMilliSeconds));
+
+    ::keymaster::AuthorizationSet hwEnforced(
+            ::keymaster::AuthorizationSetBuilder()
+                    .Authorization(::keymaster::TAG_PURPOSE, KM_PURPOSE_SIGN)
+                    .Authorization(::keymaster::TAG_KEY_SIZE, 256)
+                    .Authorization(::keymaster::TAG_ALGORITHM, KM_ALGORITHM_EC)
+                    .Authorization(::keymaster::TAG_NO_AUTH_REQUIRED)
+                    .Authorization(::keymaster::TAG_DIGEST, KM_DIGEST_SHA_2_256)
+                    .Authorization(::keymaster::TAG_EC_CURVE, KM_EC_CURVE_P_256)
+                    .Authorization(::keymaster::TAG_IDENTITY_CREDENTIAL_KEY));
+
+    const keymaster_cert_chain_t* attestation_chain =
+            ::keymaster::getAttestationChain(KM_ALGORITHM_EC, nullptr);
+
+    if (attestation_chain == nullptr) {
+        LOG(ERROR) << "Error getting attestation chain";
+        return {};
+    }
+
+    const keymaster_key_blob_t* attestation_signing_key =
+            ::keymaster::getAttestationKey(KM_ALGORITHM_EC, nullptr);
+    if (attestation_signing_key == nullptr) {
+        LOG(ERROR) << "Error getting attestation key";
+        return {};
+    }
+
+    keymaster_error_t error;
+    ::keymaster::CertChainPtr cert_chain_out;
+    ::keymaster::PureSoftKeymasterContext context;
+
+    // set identity version to 10 per hal requirements specified in IWriteableCredential.hal
+    // For now, the identity version in the attestation is set in the keymaster
+    // version field in the portable keymaster lib, which is a bit misleading.
+    uint identity_version = 10;
+    error = generate_attestation_from_EVP(key, swEnforced, hwEnforced, auth_set, context,
+                                          identity_version, *attestation_chain,
+                                          *attestation_signing_key, &cert_chain_out);
+
+    if (KM_ERROR_OK != error || !cert_chain_out) {
+        LOG(ERROR) << "Error generate attestation from EVP key" << error;
+        return {};
+    }
+
+    // translate certificate format from keymaster_cert_chain_t to vector<uint8_t>.
+    vector<vector<uint8_t>> attestationCertificate;
+    for (int i = 0; i < cert_chain_out->entry_count; i++) {
+        attestationCertificate.insert(
+                attestationCertificate.end(),
+                vector<uint8_t>(
+                        cert_chain_out->entries[i].data,
+                        cert_chain_out->entries[i].data + cert_chain_out->entries[i].data_length));
+    }
+
+    return attestationCertificate;
+}
+
+optional<std::pair<vector<uint8_t>, vector<vector<uint8_t>>>> createEcKeyPairAndAttestation(
+        const vector<uint8_t>& challenge, const vector<uint8_t>& applicationId) {
+    auto ec_key = ::keymaster::EC_KEY_Ptr(EC_KEY_new());
+    auto pkey = ::keymaster::EVP_PKEY_Ptr(EVP_PKEY_new());
+    auto group = ::keymaster::EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
+
+    if (ec_key.get() == nullptr || pkey.get() == nullptr) {
+        LOG(ERROR) << "Memory allocation failed";
+        return {};
+    }
+
+    if (EC_KEY_set_group(ec_key.get(), group.get()) != 1 ||
+        EC_KEY_generate_key(ec_key.get()) != 1 || EC_KEY_check_key(ec_key.get()) < 0) {
+        LOG(ERROR) << "Error generating key";
+        return {};
+    }
+
+    if (EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get()) != 1) {
+        LOG(ERROR) << "Error getting private key";
+        return {};
+    }
+
+    uint64_t now = time(nullptr);
+    uint64_t secondsInOneYear = 365 * 24 * 60 * 60;
+    uint64_t expireTimeMs = (now + secondsInOneYear) * 1000;
+
+    optional<vector<vector<uint8_t>>> attestationCert =
+            createAttestation(pkey.get(), applicationId, challenge, now * 1000, expireTimeMs);
+    if (!attestationCert) {
+        LOG(ERROR) << "Error create attestation from key and challenge";
+        return {};
+    }
+
+    int size = i2d_PrivateKey(pkey.get(), nullptr);
+    if (size == 0) {
+        LOG(ERROR) << "Error generating public key encoding";
+        return {};
+    }
+
+    vector<uint8_t> keyPair(size);
+    unsigned char* p = keyPair.data();
+    i2d_PrivateKey(pkey.get(), &p);
+
+    return make_pair(keyPair, attestationCert.value());
+}
+
 optional<vector<uint8_t>> createEcKeyPair() {
     auto ec_key = EC_KEY_Ptr(EC_KEY_new());
     auto pkey = EVP_PKEY_Ptr(EVP_PKEY_new());
@@ -1682,36 +1821,9 @@
 }
 
 // ---------------------------------------------------------------------------
-// Platform abstraction.
-// ---------------------------------------------------------------------------
-
-// This is not a very random HBK but that's OK because this is the SW
-// implementation where it can't be kept secret.
-vector<uint8_t> hardwareBoundKey = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
-
-const vector<uint8_t>& getHardwareBoundKey() {
-    return hardwareBoundKey;
-}
-
-// ---------------------------------------------------------------------------
 // Utility functions specific to IdentityCredential.
 // ---------------------------------------------------------------------------
 
-Result okResult{ResultCode::OK, ""};
-
-const Result& resultOK() {
-    return okResult;
-}
-
-Result result(ResultCode code, const char* format, ...) {
-    va_list ap;
-    va_start(ap, format);
-    string str;
-    android::base::StringAppendV(&str, format, ap);
-    va_end(ap);
-    return Result{code, str};
-}
-
 vector<vector<uint8_t>> chunkVector(const vector<uint8_t>& content, size_t maxChunkSize) {
     vector<vector<uint8_t>> ret;
 
@@ -1738,56 +1850,6 @@
     return ret;
 }
 
-vector<uint8_t> secureAccessControlProfileEncodeCbor(const SecureAccessControlProfile& profile) {
-    cppbor::Map map;
-    map.add("id", profile.id);
-
-    if (profile.readerCertificate.size() > 0) {
-        map.add("readerCertificate", cppbor::Bstr(profile.readerCertificate));
-    }
-
-    if (profile.userAuthenticationRequired) {
-        map.add("userAuthenticationRequired", profile.userAuthenticationRequired);
-        map.add("timeoutMillis", profile.timeoutMillis);
-        map.add("secureUserId", profile.secureUserId);
-    }
-
-    return map.encode();
-}
-
-optional<vector<uint8_t>> secureAccessControlProfileCalcMac(
-        const SecureAccessControlProfile& profile, const vector<uint8_t>& storageKey) {
-    vector<uint8_t> cborData = secureAccessControlProfileEncodeCbor(profile);
-
-    optional<vector<uint8_t>> nonce = getRandom(12);
-    if (!nonce) {
-        return {};
-    }
-    optional<vector<uint8_t>> macO = encryptAes128Gcm(storageKey, nonce.value(), {}, cborData);
-    if (!macO) {
-        return {};
-    }
-    return macO.value();
-}
-
-bool secureAccessControlProfileCheckMac(const SecureAccessControlProfile& profile,
-                                        const vector<uint8_t>& storageKey) {
-    vector<uint8_t> cborData = secureAccessControlProfileEncodeCbor(profile);
-
-    if (profile.mac.size() < kAesGcmIvSize) {
-        return false;
-    }
-    vector<uint8_t> nonce =
-            vector<uint8_t>(profile.mac.begin(), profile.mac.begin() + kAesGcmIvSize);
-    optional<vector<uint8_t>> mac = encryptAes128Gcm(storageKey, nonce, {}, cborData);
-    if (!mac) {
-        return false;
-    }
-    if (mac.value() != vector<uint8_t>(profile.mac)) {
-        return false;
-    }
-    return true;
-}
 
 vector<uint8_t> testHardwareBoundKey = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
@@ -1795,20 +1857,6 @@
     return testHardwareBoundKey;
 }
 
-vector<uint8_t> entryCreateAdditionalData(const string& nameSpace, const string& name,
-                                          const vector<uint16_t> accessControlProfileIds) {
-    cppbor::Map map;
-    map.add("Namespace", nameSpace);
-    map.add("Name", name);
-
-    cppbor::Array acpIds;
-    for (auto id : accessControlProfileIds) {
-        acpIds.add(id);
-    }
-    map.add("AccessControlProfileIds", std::move(acpIds));
-    return map.encode();
-}
-
 }  // namespace support
 }  // namespace identity
 }  // namespace hardware
diff --git a/keymaster/4.0/support/Android.bp b/keymaster/4.0/support/Android.bp
index 2f40282..9c5fbab 100644
--- a/keymaster/4.0/support/Android.bp
+++ b/keymaster/4.0/support/Android.bp
@@ -27,11 +27,10 @@
         "authorization_set.cpp",
         "key_param_output.cpp",
         "keymaster_utils.cpp",
-        "Keymaster.cpp",
-        "Keymaster3.cpp",
-        "Keymaster4.cpp",
     ],
-    export_include_dirs: ["include"],
+    export_include_dirs: [
+        "include",
+    ],
     shared_libs: [
         "android.hardware.keymaster@3.0",
         "android.hardware.keymaster@4.0",
@@ -39,6 +38,5 @@
         "libcrypto",
         "libhardware",
         "libhidlbase",
-        "libutils",
-    ]
+    ],
 }
diff --git a/keymaster/4.0/support/Keymaster4.cpp b/keymaster/4.0/support/Keymaster4.cpp
deleted file mode 100644
index cc3d656..0000000
--- a/keymaster/4.0/support/Keymaster4.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-**
-** Copyright 2017, The Android Open Source Project
-**
-** Licensed under the Apache License, Version 2.0 (the "License");
-** you may not use this file except in compliance with the License.
-** You may obtain a copy of the License at
-**
-**     http://www.apache.org/licenses/LICENSE-2.0
-**
-** Unless required by applicable law or agreed to in writing, software
-** distributed under the License is distributed on an "AS IS" BASIS,
-** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-** See the License for the specific language governing permissions and
-** limitations under the License.
-*/
-
-#include <keymasterV4_0/Keymaster4.h>
-
-#include <android-base/logging.h>
-
-namespace android {
-namespace hardware {
-namespace keymaster {
-namespace V4_0 {
-namespace support {
-
-void Keymaster4::getVersionIfNeeded() {
-    if (haveVersion_) return;
-
-    auto rc =
-        dev_->getHardwareInfo([&](SecurityLevel securityLevel, const hidl_string& keymasterName,
-                                  const hidl_string& authorName) {
-            version_ = {keymasterName, authorName, 4 /* major version */, securityLevel,
-                        true /* supportsEc */};
-            haveVersion_ = true;
-        });
-
-    CHECK(rc.isOk()) << "Got error " << rc.description() << " trying to get hardware info";
-}
-
-}  // namespace support
-}  // namespace V4_0
-}  // namespace keymaster
-}  // namespace hardware
-}  // namespace android
diff --git a/keymaster/4.0/support/attestation_record.cpp b/keymaster/4.0/support/attestation_record.cpp
index 000d46e..27e00c1 100644
--- a/keymaster/4.0/support/attestation_record.cpp
+++ b/keymaster/4.0/support/attestation_record.cpp
@@ -321,19 +321,20 @@
         LOG(ERROR) << AT << "Failed record parsing";
         return ErrorCode::UNKNOWN_ERROR;
     }
-    if (!record->tee_enforced) {
-        LOG(ERROR) << AT << "Failed hardware characteristic parsing";
+
+    KM_ROOT_OF_TRUST* root_of_trust = nullptr;
+    if (record->tee_enforced && record->tee_enforced->root_of_trust) {
+        root_of_trust = record->tee_enforced->root_of_trust;
+    } else if (record->software_enforced && record->software_enforced->root_of_trust) {
+        root_of_trust = record->software_enforced->root_of_trust;
+    } else {
+        LOG(ERROR) << AT << " Failed root of trust parsing";
         return ErrorCode::INVALID_ARGUMENT;
     }
-    if (!record->tee_enforced->root_of_trust) {
-        LOG(ERROR) << AT << "Failed root of trust parsing";
+    if (!root_of_trust->verified_boot_key) {
+        LOG(ERROR) << AT << " Failed verified boot key parsing";
         return ErrorCode::INVALID_ARGUMENT;
     }
-    if (!record->tee_enforced->root_of_trust->verified_boot_key) {
-        LOG(ERROR) << AT << "Failed verified boot key parsing";
-        return ErrorCode::INVALID_ARGUMENT;
-    }
-    KM_ROOT_OF_TRUST* root_of_trust = record->tee_enforced->root_of_trust;
 
     auto& vb_key = root_of_trust->verified_boot_key;
     verified_boot_key->resize(vb_key->length);
@@ -342,19 +343,19 @@
     *verified_boot_state = static_cast<keymaster_verified_boot_t>(
             ASN1_ENUMERATED_get(root_of_trust->verified_boot_state));
     if (!verified_boot_state) {
-        LOG(ERROR) << AT << "Failed verified boot state parsing";
+        LOG(ERROR) << AT << " Failed verified boot state parsing";
         return ErrorCode::INVALID_ARGUMENT;
     }
 
     *device_locked = root_of_trust->device_locked;
     if (!device_locked) {
-        LOG(ERROR) << AT << "Failed device locked parsing";
+        LOG(ERROR) << AT << " Failed device locked parsing";
         return ErrorCode::INVALID_ARGUMENT;
     }
 
     auto& vb_hash = root_of_trust->verified_boot_hash;
     if (!vb_hash) {
-        LOG(ERROR) << AT << "Failed verified boot hash parsing";
+        LOG(ERROR) << AT << " Failed verified boot hash parsing";
         return ErrorCode::INVALID_ARGUMENT;
     }
     verified_boot_hash->resize(vb_hash->length);
diff --git a/keymaster/4.0/support/authorization_set.cpp b/keymaster/4.0/support/authorization_set.cpp
index d6b50f5..a024ff9 100644
--- a/keymaster/4.0/support/authorization_set.cpp
+++ b/keymaster/4.0/support/authorization_set.cpp
@@ -25,7 +25,7 @@
 namespace keymaster {
 namespace V4_0 {
 
-inline bool keyParamLess(const KeyParameter& a, const KeyParameter& b) {
+bool keyParamLess(const KeyParameter& a, const KeyParameter& b) {
     if (a.tag != b.tag) return a.tag < b.tag;
     int retval;
     switch (typeFromTag(a.tag)) {
@@ -58,7 +58,7 @@
     return false;
 }
 
-inline bool keyParamEqual(const KeyParameter& a, const KeyParameter& b) {
+bool keyParamEqual(const KeyParameter& a, const KeyParameter& b) {
     if (a.tag != b.tag) return false;
 
     switch (typeFromTag(a.tag)) {
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h
deleted file mode 100644
index dfd03ef..0000000
--- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- **
- ** Copyright 2017, The Android Open Source Project
- **
- ** Licensed under the Apache License, Version 2.0 (the "License");
- ** you may not use this file except in compliance with the License.
- ** You may obtain a copy of the License at
- **
- **     http://www.apache.org/licenses/LICENSE-2.0
- **
- ** Unless required by applicable law or agreed to in writing, software
- ** distributed under the License is distributed on an "AS IS" BASIS,
- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ** See the License for the specific language governing permissions and
- ** limitations under the License.
- */
-
-#ifndef HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_4_H_
-#define HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_4_H_
-
-#include "Keymaster.h"
-
-namespace android {
-namespace hardware {
-namespace keymaster {
-namespace V4_0 {
-namespace support {
-
-using android::sp;
-using IKeymaster4Device = ::android::hardware::keymaster::V4_0::IKeymasterDevice;
-
-class Keymaster4 : public Keymaster {
-   public:
-    using WrappedIKeymasterDevice = IKeymaster4Device;
-    Keymaster4(sp<IKeymasterDevice> km4_dev, const hidl_string& instanceName)
-        : Keymaster(IKeymaster4Device::descriptor, instanceName),
-          haveVersion_(false),
-          dev_(km4_dev) {}
-
-    const VersionResult& halVersion() const override {
-        const_cast<Keymaster4*>(this)->getVersionIfNeeded();
-        return version_;
-    }
-
-    Return<void> getHardwareInfo(getHardwareInfo_cb _hidl_cb) override {
-        return dev_->getHardwareInfo(_hidl_cb);
-    }
-
-    Return<void> getHmacSharingParameters(getHmacSharingParameters_cb _hidl_cb) override {
-        return dev_->getHmacSharingParameters(_hidl_cb);
-    }
-
-    Return<void> computeSharedHmac(const hidl_vec<HmacSharingParameters>& params,
-                                   computeSharedHmac_cb _hidl_cb) override {
-        return dev_->computeSharedHmac(params, _hidl_cb);
-    }
-
-    Return<void> verifyAuthorization(uint64_t operationHandle, const hidl_vec<KeyParameter>& params,
-                                     const HardwareAuthToken& authToken,
-                                     verifyAuthorization_cb _hidl_cb) override {
-        return dev_->verifyAuthorization(operationHandle, params, authToken, _hidl_cb);
-    }
-
-    Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override {
-        return dev_->addRngEntropy(data);
-    }
-
-    Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
-                             generateKey_cb _hidl_cb) override {
-        return dev_->generateKey(keyParams, _hidl_cb);
-    }
-
-    Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
-                                       const hidl_vec<uint8_t>& clientId,
-                                       const hidl_vec<uint8_t>& appData,
-                                       getKeyCharacteristics_cb _hidl_cb) override {
-        return dev_->getKeyCharacteristics(keyBlob, clientId, appData, _hidl_cb);
-    }
-
-    Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
-                           const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) override {
-        return dev_->importKey(params, keyFormat, keyData, _hidl_cb);
-    }
-
-    Return<void> importWrappedKey(const hidl_vec<uint8_t>& wrappedKeyData,
-                                  const hidl_vec<uint8_t>& wrappingKeyBlob,
-                                  const hidl_vec<uint8_t>& maskingKey,
-                                  const hidl_vec<KeyParameter>& unwrappingParams,
-                                  uint64_t passwordSid, uint64_t biometricSid,
-                                  importWrappedKey_cb _hidl_cb) {
-        return dev_->importWrappedKey(wrappedKeyData, wrappingKeyBlob, maskingKey, unwrappingParams,
-                                      passwordSid, biometricSid, _hidl_cb);
-    }
-
-    Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
-                           const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
-                           exportKey_cb _hidl_cb) override {
-        return dev_->exportKey(exportFormat, keyBlob, clientId, appData, _hidl_cb);
-    }
-
-    Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
-                           const hidl_vec<KeyParameter>& attestParams,
-                           attestKey_cb _hidl_cb) override {
-        return dev_->attestKey(keyToAttest, attestParams, _hidl_cb);
-    }
-
-    Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
-                            const hidl_vec<KeyParameter>& upgradeParams,
-                            upgradeKey_cb _hidl_cb) override {
-        return dev_->upgradeKey(keyBlobToUpgrade, upgradeParams, _hidl_cb);
-    }
-
-    Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override {
-        return dev_->deleteKey(keyBlob);
-    }
-
-    Return<ErrorCode> deleteAllKeys() override { return dev_->deleteAllKeys(); }
-
-    Return<ErrorCode> destroyAttestationIds() override { return dev_->destroyAttestationIds(); }
-
-    Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
-                       const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
-                       begin_cb _hidl_cb) override {
-        return dev_->begin(purpose, key, inParams, authToken, _hidl_cb);
-    }
-
-    Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
-                        const hidl_vec<uint8_t>& input, const HardwareAuthToken& authToken,
-                        const VerificationToken& verificationToken, update_cb _hidl_cb) override {
-        return dev_->update(operationHandle, inParams, input, authToken, verificationToken,
-                            _hidl_cb);
-    }
-
-    Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
-                        const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
-                        const HardwareAuthToken& authToken,
-                        const VerificationToken& verificationToken, finish_cb _hidl_cb) override {
-        return dev_->finish(operationHandle, inParams, input, signature, authToken,
-                            verificationToken, _hidl_cb);
-    }
-
-    Return<ErrorCode> abort(uint64_t operationHandle) override {
-        return dev_->abort(operationHandle);
-    }
-
-   private:
-    void getVersionIfNeeded();
-
-    bool haveVersion_;
-    VersionResult version_;
-    sp<IKeymaster4Device> dev_;
-};
-
-}  // namespace support
-}  // namespace V4_0
-}  // namespace keymaster
-}  // namespace hardware
-}  // namespace android
-
-#endif  // HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_4_H_
diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
index cb29c64..bc7f311 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
@@ -355,95 +355,61 @@
     return accessTagValue(ttag, param);
 }
 
+inline bool operator<(const KeyParameter& a, const KeyParameter& b) {
+    if (a.tag != b.tag) return a.tag < b.tag;
+    int retval;
+    switch (typeFromTag(a.tag)) {
+        case TagType::INVALID:
+        case TagType::BOOL:
+            return false;
+        case TagType::ENUM:
+        case TagType::ENUM_REP:
+        case TagType::UINT:
+        case TagType::UINT_REP:
+            return a.f.integer < b.f.integer;
+        case TagType::ULONG:
+        case TagType::ULONG_REP:
+            return a.f.longInteger < b.f.longInteger;
+        case TagType::DATE:
+            return a.f.dateTime < b.f.dateTime;
+        case TagType::BIGNUM:
+        case TagType::BYTES:
+            // Handle the empty cases.
+            if (a.blob.size() == 0) return b.blob.size() != 0;
+            if (b.blob.size() == 0) return false;
+
+            retval = memcmp(&a.blob[0], &b.blob[0], std::min(a.blob.size(), b.blob.size()));
+            // if one is the prefix of the other the longer wins
+            if (retval == 0) return a.blob.size() < b.blob.size();
+            // Otherwise a is less if a is less.
+            else
+                return retval < 0;
+    }
+    return false;
+}
+
 inline bool operator==(const KeyParameter& a, const KeyParameter& b) {
-    if (a.tag != b.tag) {
-        return false;
-    }
+    if (a.tag != b.tag) return false;
 
-    switch (a.tag) {
-        /* Boolean tags */
-        case Tag::INVALID:
-        case Tag::CALLER_NONCE:
-        case Tag::INCLUDE_UNIQUE_ID:
-        case Tag::BOOTLOADER_ONLY:
-        case Tag::NO_AUTH_REQUIRED:
-        case Tag::ALLOW_WHILE_ON_BODY:
-        case Tag::UNLOCKED_DEVICE_REQUIRED:
-        case Tag::ROLLBACK_RESISTANCE:
-        case Tag::RESET_SINCE_ID_ROTATION:
-        case Tag::TRUSTED_CONFIRMATION_REQUIRED:
-        case Tag::TRUSTED_USER_PRESENCE_REQUIRED:
+    switch (typeFromTag(a.tag)) {
+        case TagType::INVALID:
+        case TagType::BOOL:
             return true;
-
-        /* Integer tags */
-        case Tag::KEY_SIZE:
-        case Tag::MIN_MAC_LENGTH:
-        case Tag::MIN_SECONDS_BETWEEN_OPS:
-        case Tag::MAX_USES_PER_BOOT:
-        case Tag::OS_VERSION:
-        case Tag::OS_PATCHLEVEL:
-        case Tag::MAC_LENGTH:
-        case Tag::USER_ID:
-        case Tag::AUTH_TIMEOUT:
-        case Tag::VENDOR_PATCHLEVEL:
-        case Tag::BOOT_PATCHLEVEL:
+        case TagType::ENUM:
+        case TagType::ENUM_REP:
+        case TagType::UINT:
+        case TagType::UINT_REP:
             return a.f.integer == b.f.integer;
-
-        /* Long integer tags */
-        case Tag::RSA_PUBLIC_EXPONENT:
-        case Tag::USER_SECURE_ID:
+        case TagType::ULONG:
+        case TagType::ULONG_REP:
             return a.f.longInteger == b.f.longInteger;
-
-        /* Date-time tags */
-        case Tag::ACTIVE_DATETIME:
-        case Tag::ORIGINATION_EXPIRE_DATETIME:
-        case Tag::USAGE_EXPIRE_DATETIME:
-        case Tag::CREATION_DATETIME:
+        case TagType::DATE:
             return a.f.dateTime == b.f.dateTime;
-
-        /* Bytes tags */
-        case Tag::APPLICATION_ID:
-        case Tag::APPLICATION_DATA:
-        case Tag::ROOT_OF_TRUST:
-        case Tag::UNIQUE_ID:
-        case Tag::ATTESTATION_CHALLENGE:
-        case Tag::ATTESTATION_APPLICATION_ID:
-        case Tag::ATTESTATION_ID_BRAND:
-        case Tag::ATTESTATION_ID_DEVICE:
-        case Tag::ATTESTATION_ID_PRODUCT:
-        case Tag::ATTESTATION_ID_SERIAL:
-        case Tag::ATTESTATION_ID_IMEI:
-        case Tag::ATTESTATION_ID_MEID:
-        case Tag::ATTESTATION_ID_MANUFACTURER:
-        case Tag::ATTESTATION_ID_MODEL:
-        case Tag::ASSOCIATED_DATA:
-        case Tag::CONFIRMATION_TOKEN:
-        case Tag::NONCE:
-            return a.blob == b.blob;
-
-        /* Enum tags */
-        case Tag::PURPOSE:
-            return a.f.purpose == b.f.purpose;
-        case Tag::ALGORITHM:
-            return a.f.algorithm == b.f.algorithm;
-        case Tag::BLOCK_MODE:
-            return a.f.blockMode == b.f.blockMode;
-        case Tag::DIGEST:
-            return a.f.digest == b.f.digest;
-        case Tag::PADDING:
-            return a.f.paddingMode == b.f.paddingMode;
-        case Tag::EC_CURVE:
-            return a.f.ecCurve == b.f.ecCurve;
-        case Tag::BLOB_USAGE_REQUIREMENTS:
-            return a.f.keyBlobUsageRequirements == b.f.keyBlobUsageRequirements;
-        case Tag::USER_AUTH_TYPE:
-            return a.f.integer == b.f.integer;
-        case Tag::ORIGIN:
-            return a.f.origin == b.f.origin;
-        case Tag::HARDWARE_TYPE:
-            return a.f.hardwareType == b.f.hardwareType;
+        case TagType::BIGNUM:
+        case TagType::BYTES:
+            if (a.blob.size() != b.blob.size()) return false;
+            return a.blob.size() == 0 || memcmp(&a.blob[0], &b.blob[0], a.blob.size()) == 0;
     }
-
     return false;
 }
 
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 5e5ae8d..61645f8 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h
@@ -52,6 +52,9 @@
 HardwareAuthToken hidlVec2AuthToken(const hidl_vec<uint8_t>& buffer);
 hidl_vec<uint8_t> authToken2HidlVec(const HardwareAuthToken& token);
 
+uint32_t getOsVersion();
+uint32_t getOsPatchlevel();
+
 }  // namespace support
 }  // namespace V4_0
 }  // namespace keymaster
diff --git a/keymaster/4.0/support/include/keymasterV4_0/openssl_utils.h b/keymaster/4.0/support/include/keymasterV4_0/openssl_utils.h
index cc71dd1..b3869f4 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/openssl_utils.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/openssl_utils.h
@@ -18,6 +18,8 @@
 #define HARDWARE_INTERFACES_KEYMASTER_4_0_SUPPORT_OPENSSL_UTILS_H_
 
 #include <android/hardware/keymaster/4.0/types.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
 
 template <typename T, void (*F)(T*)>
 struct UniquePtrDeleter {
diff --git a/keymaster/4.0/support/keymaster_utils.cpp b/keymaster/4.0/support/keymaster_utils.cpp
index e35fdd3..850a776 100644
--- a/keymaster/4.0/support/keymaster_utils.cpp
+++ b/keymaster/4.0/support/keymaster_utils.cpp
@@ -14,11 +14,13 @@
  * limitations under the License.
  */
 
+#include <regex.h>
+
+#include <android-base/properties.h>
 #include <hardware/hw_auth_token.h>
 #include <keymasterV4_0/keymaster_utils.h>
 
-namespace android {
-namespace hardware {
+namespace android::hardware {
 
 inline static bool operator<(const hidl_vec<uint8_t>& a, const hidl_vec<uint8_t>& b) {
     auto result = memcmp(a.data(), b.data(), std::min(a.size(), b.size()));
@@ -32,8 +34,7 @@
     return memcmp(a.data(), b.data(), SIZE) == -1;
 }
 
-namespace keymaster {
-namespace V4_0 {
+namespace keymaster::V4_0 {
 
 bool operator<(const HmacSharingParameters& a, const HmacSharingParameters& b) {
     return std::tie(a.seed, a.nonce) < std::tie(b.seed, b.nonce);
@@ -58,9 +59,9 @@
 
 hidl_vec<uint8_t> authToken2HidlVec(const HardwareAuthToken& token) {
     static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) +
-                          sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
-                          sizeof(token.timestamp) + kHmacSize ==
-                      sizeof(hw_auth_token_t),
+                                  sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
+                                  sizeof(token.timestamp) + kHmacSize ==
+                          sizeof(hw_auth_token_t),
                   "HardwareAuthToken content size does not match hw_auth_token_t size");
 
     hidl_vec<uint8_t> result;
@@ -86,9 +87,9 @@
 HardwareAuthToken hidlVec2AuthToken(const hidl_vec<uint8_t>& buffer) {
     HardwareAuthToken token;
     static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) +
-                          sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
-                          sizeof(token.timestamp) + kHmacSize ==
-                      sizeof(hw_auth_token_t),
+                                  sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
+                                  sizeof(token.timestamp) + kHmacSize ==
+                          sizeof(hw_auth_token_t),
                   "HardwareAuthToken content size does not match hw_auth_token_t size");
 
     if (buffer.size() != sizeof(hw_auth_token_t)) return {};
@@ -100,7 +101,7 @@
     pos = copy_bytes_from_iterator(&token.authenticatorId, pos);
     pos = copy_bytes_from_iterator(&token.authenticatorType, pos);
     token.authenticatorType = static_cast<HardwareAuthenticatorType>(
-        ntohl(static_cast<uint32_t>(token.authenticatorType)));
+            ntohl(static_cast<uint32_t>(token.authenticatorType)));
     pos = copy_bytes_from_iterator(&token.timestamp, pos);
     token.timestamp = ntohq(token.timestamp);
     token.mac.resize(kHmacSize);
@@ -109,8 +110,93 @@
     return token;
 }
 
+namespace {
+
+constexpr char kPlatformVersionProp[] = "ro.build.version.release";
+constexpr char kPlatformVersionRegex[] = "^([0-9]{1,2})(\\.([0-9]{1,2}))?(\\.([0-9]{1,2}))?";
+constexpr size_t kMajorVersionMatch = 1;
+constexpr size_t kMinorVersionMatch = 3;
+constexpr size_t kSubminorVersionMatch = 5;
+constexpr size_t kPlatformVersionMatchCount = kSubminorVersionMatch + 1;
+
+constexpr char kPlatformPatchlevelProp[] = "ro.build.version.security_patch";
+constexpr char kPlatformPatchlevelRegex[] = "^([0-9]{4})-([0-9]{2})-[0-9]{2}$";
+constexpr size_t kYearMatch = 1;
+constexpr size_t kMonthMatch = 2;
+constexpr size_t kPlatformPatchlevelMatchCount = kMonthMatch + 1;
+
+uint32_t match_to_uint32(const char* expression, const regmatch_t& match) {
+    if (match.rm_so == -1) return 0;
+
+    size_t len = match.rm_eo - match.rm_so;
+    std::string s(expression + match.rm_so, len);
+    return std::stoul(s);
+}
+
+std::string wait_and_get_property(const char* prop) {
+    std::string prop_value;
+    while (!android::base::WaitForPropertyCreation(prop))
+        ;
+    prop_value = android::base::GetProperty(prop, "" /* default */);
+    return prop_value;
+}
+
+}  // anonymous namespace
+
+uint32_t getOsVersion(const char* version_str) {
+    regex_t regex;
+    if (regcomp(&regex, kPlatformVersionRegex, REG_EXTENDED)) {
+        return 0;
+    }
+
+    regmatch_t matches[kPlatformVersionMatchCount];
+    int not_match =
+            regexec(&regex, version_str, kPlatformVersionMatchCount, matches, 0 /* flags */);
+    regfree(&regex);
+    if (not_match) {
+        return 0;
+    }
+
+    uint32_t major = match_to_uint32(version_str, matches[kMajorVersionMatch]);
+    uint32_t minor = match_to_uint32(version_str, matches[kMinorVersionMatch]);
+    uint32_t subminor = match_to_uint32(version_str, matches[kSubminorVersionMatch]);
+
+    return (major * 100 + minor) * 100 + subminor;
+}
+
+uint32_t getOsVersion() {
+    std::string version = wait_and_get_property(kPlatformVersionProp);
+    return getOsVersion(version.c_str());
+}
+
+uint32_t getOsPatchlevel(const char* patchlevel_str) {
+    regex_t regex;
+    if (regcomp(&regex, kPlatformPatchlevelRegex, REG_EXTENDED) != 0) {
+        return 0;
+    }
+
+    regmatch_t matches[kPlatformPatchlevelMatchCount];
+    int not_match =
+            regexec(&regex, patchlevel_str, kPlatformPatchlevelMatchCount, matches, 0 /* flags */);
+    regfree(&regex);
+    if (not_match) {
+        return 0;
+    }
+
+    uint32_t year = match_to_uint32(patchlevel_str, matches[kYearMatch]);
+    uint32_t month = match_to_uint32(patchlevel_str, matches[kMonthMatch]);
+
+    if (month < 1 || month > 12) {
+        return 0;
+    }
+    return year * 100 + month;
+}
+
+uint32_t getOsPatchlevel() {
+    std::string patchlevel = wait_and_get_property(kPlatformPatchlevelProp);
+    return getOsPatchlevel(patchlevel.c_str());
+}
+
 }  // namespace support
-}  // namespace V4_0
-}  // namespace keymaster
-}  // namespace hardware
-}  // namespace android
+}  // namespace keymaster::V4_0
+}  // namespace android::hardware
diff --git a/keymaster/4.0/vts/functional/Android.bp b/keymaster/4.0/vts/functional/Android.bp
index 5649f20..db50080 100644
--- a/keymaster/4.0/vts/functional/Android.bp
+++ b/keymaster/4.0/vts/functional/Android.bp
@@ -19,7 +19,6 @@
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "HmacKeySharingTest.cpp",
-        "KeymasterHidlTest.cpp",
         "VerificationTokenTest.cpp",
         "keymaster_hidl_hal_test.cpp",
     ],
@@ -27,7 +26,25 @@
         "android.hardware.keymaster@4.0",
         "libcrypto_static",
         "libkeymaster4support",
-        "libsoftkeymasterdevice",
+        "libkeymaster4vtstest",
     ],
-    test_suites: ["general-tests", "vts-core"],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
+}
+
+cc_test_library {
+    name: "libkeymaster4vtstest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "KeymasterHidlTest.cpp",
+    ],
+    export_include_dirs: [
+        ".",
+    ],
+    static_libs: [
+        "android.hardware.keymaster@4.0",
+        "libkeymaster4support",
+    ],
 }
diff --git a/keymaster/4.0/vts/functional/HmacKeySharingTest.cpp b/keymaster/4.0/vts/functional/HmacKeySharingTest.cpp
index c228ef7..f57a668 100644
--- a/keymaster/4.0/vts/functional/HmacKeySharingTest.cpp
+++ b/keymaster/4.0/vts/functional/HmacKeySharingTest.cpp
@@ -28,6 +28,16 @@
  */
 class HmacKeySharingTest : public KeymasterHidlTest {
    protected:
+     const std::vector<sp<IKeymasterDevice>>& allKeymasters() {
+         if (all_keymasters_.empty()) {
+             auto names = android::hardware::getAllHalInstanceNames(IKeymasterDevice::descriptor);
+             for (const auto& name : names) {
+                 all_keymasters_.push_back(IKeymasterDevice::getService(name));
+             }
+         }
+         return all_keymasters_;
+     }
+
     struct GetParamsResult {
         ErrorCode error;
         HmacSharingParameters params;
@@ -99,8 +109,13 @@
             EXPECT_EQ(expected, response.sharing_check) << "Sharing check values should match.";
         }
     }
+
+  private:
+    static std::vector<sp<IKeymasterDevice>> all_keymasters_;
 };
 
+std::vector<sp<IKeymasterDevice>> HmacKeySharingTest::all_keymasters_;
+
 TEST_P(HmacKeySharingTest, GetParameters) {
     auto result1 = getHmacSharingParameters(keymaster());
     EXPECT_EQ(ErrorCode::OK, result1.error);
@@ -115,26 +130,26 @@
 }
 
 TEST_P(HmacKeySharingTest, ComputeSharedHmac) {
-    auto params = getHmacSharingParameters(all_keymasters());
-    ASSERT_EQ(all_keymasters().size(), params.size())
-        << "One or more keymasters failed to provide parameters.";
+    auto params = getHmacSharingParameters(allKeymasters());
+    ASSERT_EQ(allKeymasters().size(), params.size())
+            << "One or more keymasters failed to provide parameters.";
 
     auto nonces = copyNonces(params);
-    EXPECT_EQ(all_keymasters().size(), nonces.size());
+    EXPECT_EQ(allKeymasters().size(), nonces.size());
     std::sort(nonces.begin(), nonces.end());
     std::unique(nonces.begin(), nonces.end());
-    EXPECT_EQ(all_keymasters().size(), nonces.size());
+    EXPECT_EQ(allKeymasters().size(), nonces.size());
 
-    auto responses = computeSharedHmac(all_keymasters(), params);
+    auto responses = computeSharedHmac(allKeymasters(), params);
     ASSERT_GT(responses.size(), 0U);
     verifyResponses(responses[0].sharing_check, responses);
 
     // Do it a second time.  Should get the same answers.
-    params = getHmacSharingParameters(all_keymasters());
-    ASSERT_EQ(all_keymasters().size(), params.size())
-        << "One or more keymasters failed to provide parameters.";
+    params = getHmacSharingParameters(allKeymasters());
+    ASSERT_EQ(allKeymasters().size(), params.size())
+            << "One or more keymasters failed to provide parameters.";
 
-    responses = computeSharedHmac(all_keymasters(), params);
+    responses = computeSharedHmac(allKeymasters(), params);
     ASSERT_GT(responses.size(), 0U);
     ASSERT_EQ(32U, responses[0].sharing_check.size());
     verifyResponses(responses[0].sharing_check, responses);
@@ -160,15 +175,16 @@
     // sync with respect to the HMAC key.  Granted that VTS tests aren't run on in-use production
     // devices, this still has the potential to cause confusion.  To mitigate that, we always
     // (barring crashes :-/) re-run the unmodified agreement process on our way out.
-    auto fixup_hmac = finally(
-        [&]() { computeSharedHmac(all_keymasters(), getHmacSharingParameters(all_keymasters())); });
+    auto fixup_hmac = finally([&]() {
+        computeSharedHmac(allKeymasters(), getHmacSharingParameters(allKeymasters()));
+    });
 
-    auto params = getHmacSharingParameters(all_keymasters());
-    ASSERT_EQ(all_keymasters().size(), params.size())
-        << "One or more keymasters failed to provide parameters.";
+    auto params = getHmacSharingParameters(allKeymasters());
+    ASSERT_EQ(allKeymasters().size(), params.size())
+            << "One or more keymasters failed to provide parameters.";
 
     // All should be well in the normal case
-    auto responses = computeSharedHmac(all_keymasters(), params);
+    auto responses = computeSharedHmac(allKeymasters(), params);
 
     ASSERT_GT(responses.size(), 0U);
     HidlBuf correct_response = responses[0].sharing_check;
@@ -181,7 +197,7 @@
     uint8_t bit_to_tweak = rand() % 8;
     params[param_to_tweak].nonce[byte_to_tweak] ^= (1 << bit_to_tweak);
 
-    responses = computeSharedHmac(all_keymasters(), params);
+    responses = computeSharedHmac(allKeymasters(), params);
     for (size_t i = 0; i < responses.size(); ++i) {
         if (i == param_to_tweak) {
             EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error)
@@ -199,15 +215,16 @@
     // sync with respect to the HMAC key.  Granted that VTS tests aren't run on in-use production
     // devices, this still has the potential to cause confusion.  To mitigate that, we always
     // (barring crashes :-/) re-run the unmodified agreement process on our way out.
-    auto fixup_hmac = finally(
-        [&]() { computeSharedHmac(all_keymasters(), getHmacSharingParameters(all_keymasters())); });
+    auto fixup_hmac = finally([&]() {
+        computeSharedHmac(allKeymasters(), getHmacSharingParameters(allKeymasters()));
+    });
 
-    auto params = getHmacSharingParameters(all_keymasters());
-    ASSERT_EQ(all_keymasters().size(), params.size())
-        << "One or more keymasters failed to provide parameters.";
+    auto params = getHmacSharingParameters(allKeymasters());
+    ASSERT_EQ(allKeymasters().size(), params.size())
+            << "One or more keymasters failed to provide parameters.";
 
     // All should be well in the normal case
-    auto responses = computeSharedHmac(all_keymasters(), params);
+    auto responses = computeSharedHmac(allKeymasters(), params);
 
     ASSERT_GT(responses.size(), 0U);
     HidlBuf correct_response = responses[0].sharing_check;
@@ -223,7 +240,7 @@
     }
     to_tweak[0]++;
 
-    responses = computeSharedHmac(all_keymasters(), params);
+    responses = computeSharedHmac(allKeymasters(), params);
     for (size_t i = 0; i < responses.size(); ++i) {
         if (i == param_to_tweak) {
             EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error)
@@ -236,10 +253,7 @@
     }
 }
 
-INSTANTIATE_TEST_SUITE_P(
-        PerInstance, HmacKeySharingTest,
-        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IKeymasterDevice::descriptor)),
-        android::hardware::PrintInstanceNameToString);
+INSTANTIATE_KEYMASTER_HIDL_TEST(HmacKeySharingTest);
 
 }  // namespace test
 }  // namespace V4_0
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
index 7241984..d0ad433 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
@@ -23,6 +23,7 @@
 #include <android/hidl/manager/1.0/IServiceManager.h>
 
 #include <keymasterV4_0/key_param_output.h>
+#include <keymasterV4_0/keymaster_utils.h>
 
 namespace android {
 namespace hardware {
@@ -41,39 +42,26 @@
 
 namespace test {
 
-void KeymasterHidlTest::InitializeKeymaster() {
-    service_name_ = GetParam();
-    keymaster_ = IKeymasterDevice::getService(service_name_);
-    ASSERT_NE(keymaster_, nullptr);
+using namespace std::literals::chrono_literals;
 
+void KeymasterHidlTest::InitializeKeymaster(sp<IKeymasterDevice> keymaster) {
+    ASSERT_NE(keymaster, nullptr);
+    keymaster_ = keymaster;
     ASSERT_TRUE(keymaster_
-                    ->getHardwareInfo([&](SecurityLevel securityLevel, const hidl_string& name,
-                                          const hidl_string& author) {
-                        securityLevel_ = securityLevel;
-                        name_ = name;
-                        author_ = author;
-                    })
-                    .isOk());
+                        ->getHardwareInfo([&](SecurityLevel securityLevel, const hidl_string& name,
+                                              const hidl_string& author) {
+                            securityLevel_ = securityLevel;
+                            name_ = name;
+                            author_ = author;
+                        })
+                        .isOk());
+
+    os_version_ = support::getOsVersion();
+    os_patch_level_ = support::getOsPatchlevel();
 }
 
 void KeymasterHidlTest::SetUp() {
-    InitializeKeymaster();
-
-    os_version_ = ::keymaster::GetOsVersion();
-    os_patch_level_ = ::keymaster::GetOsPatchlevel();
-
-    auto service_manager = android::hidl::manager::V1_0::IServiceManager::getService();
-    ASSERT_NE(nullptr, service_manager.get());
-    all_keymasters_.push_back(keymaster_);
-    service_manager->listByInterface(
-        IKeymasterDevice::descriptor, [&](const hidl_vec<hidl_string>& names) {
-            for (auto& name : names) {
-                if (name == service_name_) continue;
-                auto keymaster = IKeymasterDevice::getService(name);
-                ASSERT_NE(keymaster, nullptr);
-                all_keymasters_.push_back(keymaster);
-            }
-        });
+    InitializeKeymaster(IKeymasterDevice::getService(GetParam()));
 }
 
 ErrorCode KeymasterHidlTest::GenerateKey(const AuthorizationSet& key_desc, HidlBuf* key_blob,
@@ -138,7 +126,7 @@
                                               string masking_key,
                                               const AuthorizationSet& unwrapping_params) {
     ErrorCode error;
-    ImportKey(wrapping_key_desc, KeyFormat::PKCS8, wrapping_key);
+    EXPECT_EQ(ErrorCode::OK, ImportKey(wrapping_key_desc, KeyFormat::PKCS8, wrapping_key));
     EXPECT_TRUE(keymaster_
                     ->importWrappedKey(HidlBuf(wrapped_key), key_blob_, HidlBuf(masking_key),
                                        unwrapping_params.hidl_data(), 0 /* passwordSid */,
@@ -207,7 +195,9 @@
     HidlBuf empty_buf = {};
     EXPECT_EQ(ErrorCode::OK,
               GetCharacteristics(key_blob, client_id, app_data, key_characteristics));
-    EXPECT_GT(key_characteristics->hardwareEnforced.size(), 0);
+    if (SecLevel() != SecurityLevel::SOFTWARE) {
+        EXPECT_GT(key_characteristics->hardwareEnforced.size(), 0);
+    }
     EXPECT_GT(key_characteristics->softwareEnforced.size(), 0);
 
     EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
@@ -647,23 +637,25 @@
     switch (algorithm) {
         case Algorithm::RSA:
             switch (SecLevel()) {
+                case SecurityLevel::SOFTWARE:
                 case SecurityLevel::TRUSTED_ENVIRONMENT:
                     return {2048, 3072, 4096};
                 case SecurityLevel::STRONGBOX:
                     return {2048};
                 default:
-                    CHECK(false) << "Invalid security level " << uint32_t(SecLevel());
+                    ADD_FAILURE() << "Invalid security level " << uint32_t(SecLevel());
                     break;
             }
             break;
         case Algorithm::EC:
             switch (SecLevel()) {
+                case SecurityLevel::SOFTWARE:
                 case SecurityLevel::TRUSTED_ENVIRONMENT:
                     return {224, 256, 384, 521};
                 case SecurityLevel::STRONGBOX:
                     return {256};
                 default:
-                    CHECK(false) << "Invalid security level " << uint32_t(SecLevel());
+                    ADD_FAILURE() << "Invalid security level " << uint32_t(SecLevel());
                     break;
             }
             break;
@@ -678,25 +670,27 @@
             return retval;
         }
         default:
-            CHECK(false) << "Invalid Algorithm: " << algorithm;
+            ADD_FAILURE() << "Invalid Algorithm: " << algorithm;
             return {};
     }
-    CHECK(false) << "Should be impossible to get here";
+    ADD_FAILURE() << "Should be impossible to get here";
     return {};
 }
+
 std::vector<uint32_t> KeymasterHidlTest::InvalidKeySizes(Algorithm algorithm) {
-    if (SecLevel() == SecurityLevel::TRUSTED_ENVIRONMENT) return {};
-    CHECK(SecLevel() == SecurityLevel::STRONGBOX);
-    switch (algorithm) {
-        case Algorithm::RSA:
-            return {3072, 4096};
-        case Algorithm::EC:
-            return {224, 384, 521};
-        case Algorithm::AES:
-            return {192};
-        default:
-            return {};
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        switch (algorithm) {
+            case Algorithm::RSA:
+                return {3072, 4096};
+            case Algorithm::EC:
+                return {224, 384, 521};
+            case Algorithm::AES:
+                return {192};
+            default:
+                return {};
+        }
     }
+    return {};
 }
 
 std::vector<EcCurve> KeymasterHidlTest::ValidCurves() {
@@ -715,6 +709,7 @@
 
 std::vector<Digest> KeymasterHidlTest::ValidDigests(bool withNone, bool withMD5) {
     switch (SecLevel()) {
+        case SecurityLevel::SOFTWARE:
         case SecurityLevel::TRUSTED_ENVIRONMENT:
             if (withNone) {
                 if (withMD5)
@@ -740,10 +735,10 @@
                 return {Digest::SHA_2_256};
             break;
         default:
-            CHECK(false) << "Invalid security level " << uint32_t(SecLevel());
+            ADD_FAILURE() << "Invalid security level " << uint32_t(SecLevel());
             break;
     }
-    CHECK(false) << "Should be impossible to get here";
+    ADD_FAILURE() << "Should be impossible to get here";
     return {};
 }
 
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.h b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
index 4bd8b26..f495516 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.h
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
@@ -21,7 +21,6 @@
 #include <gtest/gtest.h>
 #include <hidl/GtestPrinter.h>
 #include <hidl/ServiceManagement.h>
-#include <keymaster/keymaster_configuration.h>
 
 #include <keymasterV4_0/authorization_set.h>
 
@@ -35,16 +34,18 @@
 namespace test {
 
 using ::android::sp;
-using ::std::string;
 using hidl::base::V1_0::DebugInfo;
+using ::std::string;
 
 class HidlBuf : public hidl_vec<uint8_t> {
-    typedef hidl_vec<uint8_t> super;
+    using super = hidl_vec<uint8_t>;
 
-   public:
+  public:
     HidlBuf() {}
     HidlBuf(const super& other) : super(other) {}
-    HidlBuf(super&& other) : super(std::move(other)) {}
+    HidlBuf(super&& other) : super(std::move(other)) { other = {}; }
+    HidlBuf(const HidlBuf& other) : super(other) {}
+    HidlBuf(HidlBuf&& other) : super(std::move(other)) { other = HidlBuf(); }
     explicit HidlBuf(const std::string& other) : HidlBuf() { *this = other; }
 
     HidlBuf& operator=(const super& other) {
@@ -54,6 +55,18 @@
 
     HidlBuf& operator=(super&& other) {
         super::operator=(std::move(other));
+        other = {};
+        return *this;
+    }
+
+    HidlBuf& operator=(const HidlBuf& other) {
+        super::operator=(other);
+        return *this;
+    }
+
+    HidlBuf& operator=(HidlBuf&& other) {
+        super::operator=(std::move(other));
+        other.super::operator=({});
         return *this;
     }
 
@@ -70,20 +83,16 @@
 
 class KeymasterHidlTest : public ::testing::TestWithParam<std::string> {
   public:
-    void SetUp();
+    void SetUp() override;
     void TearDown() override {
         if (key_blob_.size()) {
             CheckedDeleteKey();
         }
         AbortIfNeeded();
-        keymaster_.clear();
-        all_keymasters_.clear();
     }
 
-    void InitializeKeymaster();
-
+    void InitializeKeymaster(sp<IKeymasterDevice> keymaster);
     IKeymasterDevice& keymaster() { return *keymaster_; }
-    const std::vector<sp<IKeymasterDevice>>& all_keymasters() { return all_keymasters_; }
     uint32_t os_version() { return os_version_; }
     uint32_t os_patch_level() { return os_patch_level_; }
 
@@ -209,18 +218,26 @@
     KeyCharacteristics key_characteristics_;
     OperationHandle op_handle_ = kOpHandleSentinel;
 
-   private:
-     sp<IKeymasterDevice> keymaster_;
-     std::vector<sp<IKeymasterDevice>> all_keymasters_;
-     uint32_t os_version_;
-     uint32_t os_patch_level_;
+    static std::vector<std::string> build_params() {
+        auto params = android::hardware::getAllHalInstanceNames(IKeymasterDevice::descriptor);
+        return params;
+    }
 
-     SecurityLevel securityLevel_;
-     hidl_string name_;
-     hidl_string author_;
-     string service_name_;
+  private:
+    sp<IKeymasterDevice> keymaster_;
+    uint32_t os_version_;
+    uint32_t os_patch_level_;
+
+    SecurityLevel securityLevel_;
+    hidl_string name_;
+    hidl_string author_;
 };
 
+#define INSTANTIATE_KEYMASTER_HIDL_TEST(name)                                      \
+    INSTANTIATE_TEST_SUITE_P(PerInstance, name,                                    \
+                             testing::ValuesIn(KeymasterHidlTest::build_params()), \
+                             android::hardware::PrintInstanceNameToString)
+
 }  // namespace test
 }  // namespace V4_0
 }  // namespace keymaster
diff --git a/keymaster/4.0/vts/functional/VerificationTokenTest.cpp b/keymaster/4.0/vts/functional/VerificationTokenTest.cpp
index 693f4ae..bab1439 100644
--- a/keymaster/4.0/vts/functional/VerificationTokenTest.cpp
+++ b/keymaster/4.0/vts/functional/VerificationTokenTest.cpp
@@ -185,10 +185,7 @@
               memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size()));
 }
 
-INSTANTIATE_TEST_SUITE_P(
-        PerInstance, VerificationTokenTest,
-        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IKeymasterDevice::descriptor)),
-        android::hardware::PrintInstanceNameToString);
+INSTANTIATE_KEYMASTER_HIDL_TEST(VerificationTokenTest);
 
 }  // namespace test
 }  // namespace V4_0
diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
index 66132ad..6cbe4da 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -352,11 +352,11 @@
     EXPECT_EQ(ErrorCode::OK, error);
     if (error != ErrorCode::OK) return false;
 
-    EXPECT_TRUE(att_attestation_version == 3);
+    EXPECT_GE(att_attestation_version, 3U);
 
     expected_sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID, HidlBuf(app_id));
 
-    EXPECT_EQ(att_keymaster_version, 4U);
+    EXPECT_GE(att_keymaster_version, 4U);
     EXPECT_EQ(security_level, att_keymaster_security_level);
     EXPECT_EQ(security_level, att_attestation_security_level);
 
@@ -397,10 +397,16 @@
     // true. A provided boolean tag that can be pulled back out of the certificate indicates correct
     // encoding. No need to check if it's in both lists, since the AuthorizationSet compare below
     // will handle mismatches of tags.
-    EXPECT_TRUE(expected_hw_enforced.Contains(TAG_NO_AUTH_REQUIRED));
+    if (security_level == SecurityLevel::SOFTWARE) {
+        EXPECT_TRUE(expected_sw_enforced.Contains(TAG_NO_AUTH_REQUIRED));
+    } else {
+        EXPECT_TRUE(expected_hw_enforced.Contains(TAG_NO_AUTH_REQUIRED));
+    }
 
     // Alternatively this checks the opposite - a false boolean tag (one that isn't provided in
     // the authorization list during key generation) isn't being attested to in the certificate.
+    EXPECT_FALSE(expected_sw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
+    EXPECT_FALSE(att_sw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
     EXPECT_FALSE(expected_hw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
     EXPECT_FALSE(att_hw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
 
@@ -461,10 +467,10 @@
                             verified_boot_key.size()));
     } else if (!strcmp(property_value, "red")) {
         EXPECT_EQ(verified_boot_state, KM_VERIFIED_BOOT_FAILED);
-        EXPECT_EQ(0, memcmp(verified_boot_key.data(), empty_boot_key.data(),
-                            verified_boot_key.size()));
     } else {
-        EXPECT_TRUE(false);
+        EXPECT_EQ(verified_boot_state, KM_VERIFIED_BOOT_UNVERIFIED);
+        EXPECT_NE(0, memcmp(verified_boot_key.data(), empty_boot_key.data(),
+                            verified_boot_key.size()));
     }
 
     att_sw_enforced.Sort();
@@ -840,6 +846,8 @@
                               .Authorization(TAG_MIN_MAC_LENGTH, 128)));
 }
 
+INSTANTIATE_KEYMASTER_HIDL_TEST(NewKeyGenerationTest);
+
 typedef KeymasterHidlTest SigningOperationsTest;
 
 /*
@@ -1509,6 +1517,8 @@
     }
 }
 
+INSTANTIATE_KEYMASTER_HIDL_TEST(SigningOperationsTest);
+
 typedef KeymasterHidlTest VerificationOperationsTest;
 
 /*
@@ -1749,6 +1759,8 @@
     CheckedDeleteKey(&verification_key);
 }
 
+INSTANTIATE_KEYMASTER_HIDL_TEST(VerificationOperationsTest);
+
 typedef KeymasterHidlTest ExportKeyTest;
 
 /*
@@ -1828,6 +1840,8 @@
     EXPECT_EQ(ErrorCode::UNSUPPORTED_KEY_FORMAT, ExportKey(KeyFormat::RAW, &export_data));
 }
 
+INSTANTIATE_KEYMASTER_HIDL_TEST(ExportKeyTest);
+
 class ImportKeyTest : public KeymasterHidlTest {
    public:
     template <TagType tag_type, Tag tag, typename ValueT>
@@ -2093,6 +2107,8 @@
     VerifyMessage(message, signature, AuthorizationSetBuilder().Digest(Digest::SHA_2_256));
 }
 
+INSTANTIATE_KEYMASTER_HIDL_TEST(ImportKeyTest);
+
 auto wrapped_key = hex2str(
     "3082017902010004820100934bf94e2aa28a3f83c9f79297250262fbe3276b5a1c91159bbfa3ef8957aac84b59b30b"
     "455a79c2973480823d8b3863c3deef4a8e243590268d80e18751a0e130f67ce6a1ace9f79b95e097474febc981195b"
@@ -2214,6 +2230,8 @@
                       .Padding(PaddingMode::RSA_OAEP)));
 }
 
+INSTANTIATE_KEYMASTER_HIDL_TEST(ImportWrappedKeyTest);
+
 typedef KeymasterHidlTest EncryptionOperationsTest;
 
 /*
@@ -4111,6 +4129,8 @@
     EXPECT_EQ(message, plaintext);
 }
 
+INSTANTIATE_KEYMASTER_HIDL_TEST(EncryptionOperationsTest);
+
 typedef KeymasterHidlTest MaxOperationsTest;
 
 /*
@@ -4166,6 +4186,8 @@
     EXPECT_EQ(ErrorCode::KEY_MAX_OPS_EXCEEDED, Begin(KeyPurpose::SIGN, params));
 }
 
+INSTANTIATE_KEYMASTER_HIDL_TEST(MaxOperationsTest);
+
 typedef KeymasterHidlTest AddEntropyTest;
 
 /*
@@ -4196,6 +4218,8 @@
     EXPECT_EQ(ErrorCode::OK, keymaster().addRngEntropy(HidlBuf(string(2 * 1024, 'a'))));
 }
 
+INSTANTIATE_KEYMASTER_HIDL_TEST(AddEntropyTest);
+
 typedef KeymasterHidlTest AttestationTest;
 
 /*
@@ -4373,6 +4397,8 @@
                         &cert_chain));
 }
 
+INSTANTIATE_KEYMASTER_HIDL_TEST(AttestationTest);
+
 typedef KeymasterHidlTest KeyDeletionTest;
 
 /**
@@ -4478,6 +4504,8 @@
     }
 }
 
+INSTANTIATE_KEYMASTER_HIDL_TEST(KeyDeletionTest);
+
 using UpgradeKeyTest = KeymasterHidlTest;
 
 /*
@@ -4497,6 +4525,8 @@
     EXPECT_EQ(result, std::make_pair(ErrorCode::OK, HidlBuf()));
 }
 
+INSTANTIATE_KEYMASTER_HIDL_TEST(UpgradeKeyTest);
+
 using ClearOperationsTest = KeymasterHidlTest;
 
 /*
@@ -4533,51 +4563,14 @@
     AbortIfNeeded();
 }
 
-/*
- * ClearSlotsTest.ServiceDeath
- *
- * Verifies that the service is restarted after death and the ongoing
- * operations are cleared.
- */
-TEST_P(ClearOperationsTest, ServiceDeath) {
-    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .RsaEncryptionKey(2048, 65537)
-                                             .Padding(PaddingMode::NONE)));
-
-    auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE);
-    int max_operations = SecLevel() == SecurityLevel::STRONGBOX ? 4 : 16;
-    OperationHandle op_handles[max_operations];
-    AuthorizationSet out_params;
-    for(int i=0; i<max_operations; i++) {
-        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &(op_handles[i])));
-    }
-    EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS,
-         Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &op_handle_));
-
-    DebugInfo debug_info;
-    GetDebugInfo(&debug_info);
-    kill(debug_info.pid, SIGKILL);
-    // wait 1 second for keymaster to restart
-    sleep(1);
-    InitializeKeymaster();
-
-    for(int i=0; i<max_operations; i++) {
-        EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &(op_handles[i])));
-    }
-    EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS,
-         Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &op_handle_));
-    for(int i=0; i<max_operations; i++) {
-        EXPECT_EQ(ErrorCode::OK, Abort(op_handles[i]));
-    }
-}
+INSTANTIATE_KEYMASTER_HIDL_TEST(ClearOperationsTest);
 
 typedef KeymasterHidlTest TransportLimitTest;
 
 /*
- * TransportLimitTest.LargeFinishInput
+ * TransportLimitTest.FinishInput
  *
- * Verifies that passing large input data to finish either succeeds or fails as expected.
+ * Verifies that passing input data to finish succeeds as expected.
  */
 TEST_P(TransportLimitTest, LargeFinishInput) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
@@ -4586,7 +4579,7 @@
                                                  .BlockMode(BlockMode::ECB)
                                                  .Padding(PaddingMode::NONE)));
 
-    for (int msg_size = 10 /*1KB*/; msg_size <= 17 /*128KB*/; msg_size++) {
+    for (int msg_size = 8 /* 256 bytes */; msg_size <= 11 /* 2 KiB */; msg_size++) {
         auto cipher_params =
                 AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE);
 
@@ -4597,71 +4590,22 @@
         string encrypted_message;
         auto rc = Finish(plain_message, &encrypted_message);
 
-        if (rc == ErrorCode::OK) {
-            EXPECT_EQ(plain_message.size(), encrypted_message.size())
-                    << "Encrypt finish returned OK, but did not consume all of the given input";
-        } else {
-            EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, rc)
-                    << "Encrypt finish failed in an unexpected way when given a large input";
-            continue;
-        }
+        EXPECT_EQ(ErrorCode::OK, rc);
+        EXPECT_EQ(plain_message.size(), encrypted_message.size())
+                << "Encrypt finish returned OK, but did not consume all of the given input";
         cipher_params.push_back(out_params);
 
         EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, cipher_params));
 
         string decrypted_message;
         rc = Finish(encrypted_message, &decrypted_message);
-
-        if (rc == ErrorCode::OK) {
-            EXPECT_EQ(plain_message.size(), decrypted_message.size())
-                    << "Decrypt finish returned OK, did not consume all of the given input";
-        } else {
-            EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, rc)
-                    << "Encrypt finish failed in an unexpected way when given a large input";
-        }
+        EXPECT_EQ(ErrorCode::OK, rc);
+        EXPECT_EQ(plain_message.size(), decrypted_message.size())
+                << "Decrypt finish returned OK, did not consume all of the given input";
     }
-
-    CheckedDeleteKey();
 }
 
-static const auto kKeymasterDeviceChoices =
-        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IKeymasterDevice::descriptor));
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, NewKeyGenerationTest, kKeymasterDeviceChoices,
-                         android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, ImportKeyTest, kKeymasterDeviceChoices,
-                         android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, ImportWrappedKeyTest, kKeymasterDeviceChoices,
-                         android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, SigningOperationsTest, kKeymasterDeviceChoices,
-                         android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, VerificationOperationsTest, kKeymasterDeviceChoices,
-                         android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, ExportKeyTest, kKeymasterDeviceChoices,
-                         android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, EncryptionOperationsTest, kKeymasterDeviceChoices,
-                         android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, MaxOperationsTest, kKeymasterDeviceChoices,
-                         android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, AddEntropyTest, kKeymasterDeviceChoices,
-                         android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, AttestationTest, kKeymasterDeviceChoices,
-                         android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, KeyDeletionTest, kKeymasterDeviceChoices,
-                         android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, TransportLimitTest, kKeymasterDeviceChoices,
-                         android::hardware::PrintInstanceNameToString);
+INSTANTIATE_KEYMASTER_HIDL_TEST(TransportLimitTest);
 
 }  // namespace test
 }  // namespace V4_0
diff --git a/keymaster/4.1/default/Android.bp b/keymaster/4.1/default/Android.bp
index b06878b..27297b9 100644
--- a/keymaster/4.1/default/Android.bp
+++ b/keymaster/4.1/default/Android.bp
@@ -31,6 +31,7 @@
         "libhidlbase",
         "libkeymaster4",
         "libkeymaster41",
+        "libkeymaster4_1support",
         "liblog",
         "libutils",
     ],
diff --git a/keymaster/4.1/support/Android.bp b/keymaster/4.1/support/Android.bp
index 34b6108..bdd0ca8 100644
--- a/keymaster/4.1/support/Android.bp
+++ b/keymaster/4.1/support/Android.bp
@@ -22,11 +22,25 @@
         "-Wextra",
         "-Werror",
     ],
+    srcs: [
+        "attestation_record.cpp",
+        "Keymaster.cpp",
+        "Keymaster3.cpp",
+        "Keymaster4.cpp",
+    ],
     export_include_dirs: ["include"],
     shared_libs: [
         "android.hardware.keymaster@3.0",
         "android.hardware.keymaster@4.0",
         "android.hardware.keymaster@4.1",
+        "libbase",
+        "libcrypto",
+        "libhidlbase",
         "libkeymaster4support",
-    ]
+        "libutils",
+    ],
+    export_shared_lib_headers: [
+        "android.hardware.keymaster@4.1",
+        "libkeymaster4support",
+    ],
 }
diff --git a/keymaster/4.0/support/Keymaster.cpp b/keymaster/4.1/support/Keymaster.cpp
similarity index 84%
rename from keymaster/4.0/support/Keymaster.cpp
rename to keymaster/4.1/support/Keymaster.cpp
index 1eb9a68..b55bfcc 100644
--- a/keymaster/4.0/support/Keymaster.cpp
+++ b/keymaster/4.1/support/Keymaster.cpp
@@ -14,19 +14,18 @@
  ** limitations under the License.
  */
 
-#include <keymasterV4_0/Keymaster.h>
+#include <keymasterV4_1/Keymaster.h>
 
 #include <iomanip>
 
 #include <android-base/logging.h>
 #include <android/hidl/manager/1.2/IServiceManager.h>
-#include <keymasterV4_0/Keymaster3.h>
-#include <keymasterV4_0/Keymaster4.h>
 #include <keymasterV4_0/key_param_output.h>
 #include <keymasterV4_0/keymaster_utils.h>
+#include <keymasterV4_1/Keymaster3.h>
+#include <keymasterV4_1/Keymaster4.h>
 
-namespace android {
-namespace hardware {
+namespace android::hardware {
 
 template <class T>
 std::ostream& operator<<(std::ostream& os, const hidl_vec<T>& vec) {
@@ -57,6 +56,7 @@
 }
 
 namespace keymaster {
+
 namespace V4_0 {
 
 std::ostream& operator<<(std::ostream& os, const HmacSharingParameters& params) {
@@ -66,7 +66,9 @@
     return os;
 }
 
-namespace support {
+}  // namespace V4_0
+
+namespace V4_1::support {
 
 using ::android::sp;
 using ::android::hidl::manager::V1_2::IServiceManager;
@@ -81,7 +83,7 @@
 
 template <typename Wrapper>
 std::vector<std::unique_ptr<Keymaster>> enumerateDevices(
-    const sp<IServiceManager>& serviceManager) {
+        const sp<IServiceManager>& serviceManager) {
     Keymaster::KeymasterSet result;
 
     bool foundDefault = false;
@@ -141,14 +143,14 @@
 }
 
 static hidl_vec<HmacSharingParameters> getHmacParameters(
-    const Keymaster::KeymasterSet& keymasters) {
+        const Keymaster::KeymasterSet& keymasters) {
     std::vector<HmacSharingParameters> params_vec;
     params_vec.reserve(keymasters.size());
     for (auto& keymaster : keymasters) {
         if (keymaster->halVersion().majorVersion < 4) continue;
         auto rc = keymaster->getHmacSharingParameters([&](auto error, auto& params) {
-            CHECK(error == ErrorCode::OK)
-                << "Failed to get HMAC parameters from " << *keymaster << " error " << error;
+            CHECK(error == V4_0::ErrorCode::OK)
+                    << "Failed to get HMAC parameters from " << *keymaster << " error " << error;
             params_vec.push_back(params);
         });
         CHECK(rc.isOk()) << "Failed to communicate with " << *keymaster
@@ -170,18 +172,18 @@
         if (keymaster->halVersion().majorVersion < 4) continue;
         LOG(DEBUG) << "Computing HMAC for " << *keymaster;
         auto rc = keymaster->computeSharedHmac(
-            params, [&](ErrorCode error, const hidl_vec<uint8_t>& curSharingCheck) {
-                CHECK(error == ErrorCode::OK)
-                    << "Failed to get HMAC parameters from " << *keymaster << " error " << error;
-                if (firstKeymaster) {
-                    sharingCheck = curSharingCheck;
-                    firstKeymaster = false;
-                }
-                if (curSharingCheck != sharingCheck)
-                    LOG(WARNING) << "HMAC computation failed for " << *keymaster  //
-                                 << " Expected: " << sharingCheck                 //
-                                 << " got: " << curSharingCheck;
-            });
+                params, [&](V4_0::ErrorCode error, const hidl_vec<uint8_t>& curSharingCheck) {
+                    CHECK(error == V4_0::ErrorCode::OK) << "Failed to get HMAC parameters from "
+                                                        << *keymaster << " error " << error;
+                    if (firstKeymaster) {
+                        sharingCheck = curSharingCheck;
+                        firstKeymaster = false;
+                    }
+                    if (curSharingCheck != sharingCheck)
+                        LOG(WARNING) << "HMAC computation failed for " << *keymaster  //
+                                     << " Expected: " << sharingCheck                 //
+                                     << " got: " << curSharingCheck;
+                });
         CHECK(rc.isOk()) << "Failed to communicate with " << *keymaster
                          << " error: " << rc.description();
     }
@@ -191,8 +193,6 @@
     computeHmac(keymasters, getHmacParameters(keymasters));
 }
 
-}  // namespace support
-}  // namespace V4_0
+}  // namespace V4_1::support
 }  // namespace keymaster
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware
diff --git a/keymaster/4.0/support/Keymaster3.cpp b/keymaster/4.1/support/Keymaster3.cpp
similarity index 81%
rename from keymaster/4.0/support/Keymaster3.cpp
rename to keymaster/4.1/support/Keymaster3.cpp
index b2cdbd9..b665689 100644
--- a/keymaster/4.0/support/Keymaster3.cpp
+++ b/keymaster/4.1/support/Keymaster3.cpp
@@ -15,23 +15,19 @@
  ** limitations under the License.
  */
 
-#include <keymasterV4_0/Keymaster3.h>
+#include <keymasterV4_1/Keymaster3.h>
 
 #include <android-base/logging.h>
 #include <keymasterV4_0/keymaster_utils.h>
 
-namespace android {
-namespace hardware {
-namespace keymaster {
-namespace V4_0 {
-namespace support {
+namespace android::hardware::keymaster::V4_1::support {
 
 using android::hardware::details::StatusOf;
 
 namespace {
 
-ErrorCode convert(V3_0::ErrorCode error) {
-    return static_cast<ErrorCode>(error);
+V4_0::ErrorCode convert(V3_0::ErrorCode error) {
+    return static_cast<V4_0::ErrorCode>(error);
 }
 
 V3_0::KeyPurpose convert(KeyPurpose purpose) {
@@ -53,7 +49,7 @@
 
 KeyParameter convert(const V3_0::KeyParameter& param) {
     KeyParameter converted;
-    converted.tag = static_cast<Tag>(param.tag);
+    converted.tag = static_cast<V4_0::Tag>(param.tag);
     static_assert(sizeof(converted.f) == sizeof(param.f), "This function assumes sizes match");
     memcpy(&converted.f, &param.f, sizeof(param.f));
     converted.blob = param.blob;
@@ -89,7 +85,7 @@
         converted[i] = convert(params[i]);
     }
     converted[params.size()].tag = V3_0::Tag::AUTH_TOKEN;
-    converted[params.size()].blob = authToken2HidlVec(authToken);
+    converted[params.size()].blob = V4_0::support::authToken2HidlVec(authToken);
 
     return converted;
 }
@@ -107,16 +103,19 @@
     if (haveVersion_) return;
 
     auto rc = km3_dev_->getHardwareFeatures(
-        [&](bool isSecure, bool supportsEllipticCurve, bool supportsSymmetricCryptography,
-            bool supportsAttestation, bool supportsAllDigests, const hidl_string& keymasterName,
-            const hidl_string& keymasterAuthorName) {
-            version_ = {keymasterName, keymasterAuthorName, 0 /* major version, filled below */,
-                        isSecure ? SecurityLevel::TRUSTED_ENVIRONMENT : SecurityLevel::SOFTWARE,
-                        supportsEllipticCurve};
-            supportsSymmetricCryptography_ = supportsSymmetricCryptography;
-            supportsAttestation_ = supportsAttestation;
-            supportsAllDigests_ = supportsAllDigests;
-        });
+            [&](bool isSecure, bool supportsEllipticCurve, bool supportsSymmetricCryptography,
+                bool supportsAttestation, bool supportsAllDigests, const hidl_string& keymasterName,
+                const hidl_string& keymasterAuthorName) {
+                version_ = {keymasterName,
+                            keymasterAuthorName,
+                            0 /* major version, filled below */,
+                            0 /* minor version */,
+                            isSecure ? SecurityLevel::TRUSTED_ENVIRONMENT : SecurityLevel::SOFTWARE,
+                            supportsEllipticCurve};
+                supportsSymmetricCryptography_ = supportsSymmetricCryptography;
+                supportsAttestation_ = supportsAttestation;
+                supportsAllDigests_ = supportsAllDigests;
+            });
 
     CHECK(rc.isOk()) << "Got error " << rc.description() << " trying to get hardware features";
 
@@ -139,10 +138,10 @@
     return Void();
 }
 
-Return<ErrorCode> Keymaster3::addRngEntropy(const hidl_vec<uint8_t>& data) {
+Return<V4_0::ErrorCode> Keymaster3::addRngEntropy(const hidl_vec<uint8_t>& data) {
     auto rc = km3_dev_->addRngEntropy(data);
     if (!rc.isOk()) {
-        return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+        return StatusOf<V3_0::ErrorCode, V4_0::ErrorCode>(rc);
     }
     return convert(rc);
 }
@@ -215,21 +214,21 @@
     return rc;
 }
 
-Return<ErrorCode> Keymaster3::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
+Return<V4_0::ErrorCode> Keymaster3::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
     auto rc = km3_dev_->deleteKey(keyBlob);
-    if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+    if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, V4_0::ErrorCode>(rc);
     return convert(rc);
 }
 
-Return<ErrorCode> Keymaster3::deleteAllKeys() {
+Return<V4_0::ErrorCode> Keymaster3::deleteAllKeys() {
     auto rc = km3_dev_->deleteAllKeys();
-    if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+    if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, V4_0::ErrorCode>(rc);
     return convert(rc);
 }
 
-Return<ErrorCode> Keymaster3::destroyAttestationIds() {
+Return<V4_0::ErrorCode> Keymaster3::destroyAttestationIds() {
     auto rc = km3_dev_->destroyAttestationIds();
-    if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+    if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, V4_0::ErrorCode>(rc);
     return convert(rc);
 }
 
@@ -242,7 +241,7 @@
     };
 
     auto rc =
-        km3_dev_->begin(convert(purpose), key, convertAndAddAuthToken(inParams, authToken), cb);
+            km3_dev_->begin(convert(purpose), key, convertAndAddAuthToken(inParams, authToken), cb);
     rc.isOk();  // move ctor prereq
     return rc;
 }
@@ -256,8 +255,8 @@
         _hidl_cb(convert(error), inputConsumed, convert(outParams), output);
     };
 
-    auto rc =
-        km3_dev_->update(operationHandle, convertAndAddAuthToken(inParams, authToken), input, cb);
+    auto rc = km3_dev_->update(operationHandle, convertAndAddAuthToken(inParams, authToken), input,
+                               cb);
     rc.isOk();  // move ctor prereq
     return rc;
 }
@@ -278,14 +277,10 @@
     return rc;
 }
 
-Return<ErrorCode> Keymaster3::abort(uint64_t operationHandle) {
+Return<V4_0::ErrorCode> Keymaster3::abort(uint64_t operationHandle) {
     auto rc = km3_dev_->abort(operationHandle);
-    if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+    if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, V4_0::ErrorCode>(rc);
     return convert(rc);
 }
 
-}  // namespace support
-}  // namespace V4_0
-}  // namespace keymaster
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::keymaster::V4_1::support
diff --git a/keymaster/4.1/support/Keymaster4.cpp b/keymaster/4.1/support/Keymaster4.cpp
new file mode 100644
index 0000000..33f4bb1
--- /dev/null
+++ b/keymaster/4.1/support/Keymaster4.cpp
@@ -0,0 +1,41 @@
+/*
+** Copyright 2017, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+#include <keymasterV4_1/Keymaster4.h>
+
+#include <android-base/logging.h>
+
+namespace android::hardware::keymaster::V4_1::support {
+
+void Keymaster4::getVersionIfNeeded() {
+    if (haveVersion_) return;
+
+    auto rc = km4_0_dev_->getHardwareInfo([&](SecurityLevel securityLevel,
+                                              const hidl_string& keymasterName,
+                                              const hidl_string& authorName) {
+        version_ = {keymasterName,
+                    authorName,
+                    4 /* major version */,
+                    static_cast<uint8_t>((km4_1_dev_) ? 1 : 0) /* minor version */,
+                    securityLevel,
+                    true /* supportsEc */};
+        haveVersion_ = true;
+    });
+
+    CHECK(rc.isOk()) << "Got error " << rc.description() << " trying to get hardware info";
+}
+
+}  // namespace android::hardware::keymaster::V4_1::support
diff --git a/keymaster/4.1/support/attestation_record.cpp b/keymaster/4.1/support/attestation_record.cpp
new file mode 100644
index 0000000..9eab1db
--- /dev/null
+++ b/keymaster/4.1/support/attestation_record.cpp
@@ -0,0 +1,387 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <keymasterV4_1/attestation_record.h>
+
+#include <android-base/logging.h>
+#include <assert.h>
+
+#include <openssl/asn1t.h>
+#include <openssl/bn.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
+
+#include <keymasterV4_0/authorization_set.h>
+#include <keymasterV4_0/openssl_utils.h>
+
+#define AT __FILE__ ":" << __LINE__
+
+/*
+ * NOTE: The contents of this file are *extremely* similar to the contents of the V4_0 copy of the
+ * same support file.  Unfortunately, small changes in the scheme mean that the schema types have to
+ * be distinct, which drives almost everything else to be different as well.  In the next version we
+ * plan to abandon not just this openssl mechanism for parsing ASN.1, but ASN.1 entirely, so
+ * eventually all of this duplication can be removed.
+ */
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_1 {
+
+struct stack_st_ASN1_TYPE_Delete {
+    void operator()(stack_st_ASN1_TYPE* p) { sk_ASN1_TYPE_free(p); }
+};
+
+struct ASN1_STRING_Delete {
+    void operator()(ASN1_STRING* p) { ASN1_STRING_free(p); }
+};
+
+struct ASN1_TYPE_Delete {
+    void operator()(ASN1_TYPE* p) { ASN1_TYPE_free(p); }
+};
+
+#define ASN1_INTEGER_SET STACK_OF(ASN1_INTEGER)
+
+typedef struct km_root_of_trust {
+    ASN1_OCTET_STRING* verified_boot_key;
+    ASN1_BOOLEAN* device_locked;
+    ASN1_ENUMERATED* verified_boot_state;
+    ASN1_OCTET_STRING* verified_boot_hash;
+} KM_ROOT_OF_TRUST;
+
+ASN1_SEQUENCE(KM_ROOT_OF_TRUST) = {
+        ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_key, ASN1_OCTET_STRING),
+        ASN1_SIMPLE(KM_ROOT_OF_TRUST, device_locked, ASN1_BOOLEAN),
+        ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_state, ASN1_ENUMERATED),
+        ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_hash, ASN1_OCTET_STRING),
+} ASN1_SEQUENCE_END(KM_ROOT_OF_TRUST);
+IMPLEMENT_ASN1_FUNCTIONS(KM_ROOT_OF_TRUST);
+
+typedef struct km_auth_list {
+    ASN1_INTEGER_SET* purpose;
+    ASN1_INTEGER* algorithm;
+    ASN1_INTEGER* key_size;
+    ASN1_INTEGER_SET* digest;
+    ASN1_INTEGER_SET* padding;
+    ASN1_INTEGER* ec_curve;
+    ASN1_INTEGER* rsa_public_exponent;
+    ASN1_INTEGER* active_date_time;
+    ASN1_INTEGER* origination_expire_date_time;
+    ASN1_INTEGER* usage_expire_date_time;
+    ASN1_NULL* no_auth_required;
+    ASN1_INTEGER* user_auth_type;
+    ASN1_INTEGER* auth_timeout;
+    ASN1_NULL* allow_while_on_body;
+    ASN1_NULL* all_applications;
+    ASN1_OCTET_STRING* application_id;
+    ASN1_INTEGER* creation_date_time;
+    ASN1_INTEGER* origin;
+    ASN1_NULL* rollback_resistance;
+    KM_ROOT_OF_TRUST* root_of_trust;
+    ASN1_INTEGER* os_version;
+    ASN1_INTEGER* os_patchlevel;
+    ASN1_OCTET_STRING* attestation_application_id;
+    ASN1_NULL* trusted_user_presence_required;
+    ASN1_NULL* trusted_confirmation_required;
+    ASN1_NULL* unlocked_device_required;
+    ASN1_INTEGER* vendor_patchlevel;
+    ASN1_INTEGER* boot_patchlevel;
+    ASN1_NULL* early_boot_only;
+    ASN1_NULL* device_unique_attestation;
+} KM_AUTH_LIST;
+
+ASN1_SEQUENCE(KM_AUTH_LIST) = {
+        ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, purpose, ASN1_INTEGER, TAG_PURPOSE.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, algorithm, ASN1_INTEGER, TAG_ALGORITHM.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, key_size, ASN1_INTEGER, TAG_KEY_SIZE.maskedTag()),
+        ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, digest, ASN1_INTEGER, TAG_DIGEST.maskedTag()),
+        ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, padding, ASN1_INTEGER, TAG_PADDING.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
+                     TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL,
+                     TAG_ROLLBACK_RESISTANCE.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
+                     TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
+                     TAG_USAGE_EXPIRE_DATETIME.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, allow_while_on_body, ASN1_NULL,
+                     TAG_ALLOW_WHILE_ON_BODY.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, trusted_user_presence_required, ASN1_NULL,
+                     TAG_TRUSTED_USER_PRESENCE_REQUIRED.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, trusted_confirmation_required, ASN1_NULL,
+                     TAG_TRUSTED_CONFIRMATION_REQUIRED.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, unlocked_device_required, ASN1_NULL,
+                     TAG_UNLOCKED_DEVICE_REQUIRED.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER,
+                     TAG_CREATION_DATETIME.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER,
+                     TAG_VENDOR_PATCHLEVEL.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, boot_patchlevel, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
+                     TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.maskedTag()),
+        ASN1_EXP_OPT(KM_AUTH_LIST, device_unique_attestation, ASN1_NULL,
+                     TAG_DEVICE_UNIQUE_ATTESTATION.maskedTag()),
+} ASN1_SEQUENCE_END(KM_AUTH_LIST);
+IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
+
+typedef struct km_key_description {
+    ASN1_INTEGER* attestation_version;
+    ASN1_ENUMERATED* attestation_security_level;
+    ASN1_INTEGER* keymaster_version;
+    ASN1_ENUMERATED* keymaster_security_level;
+    ASN1_OCTET_STRING* attestation_challenge;
+    KM_AUTH_LIST* software_enforced;
+    KM_AUTH_LIST* tee_enforced;
+    ASN1_INTEGER* unique_id;
+} KM_KEY_DESCRIPTION;
+
+ASN1_SEQUENCE(KM_KEY_DESCRIPTION) = {
+        ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_version, ASN1_INTEGER),
+        ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_security_level, ASN1_ENUMERATED),
+        ASN1_SIMPLE(KM_KEY_DESCRIPTION, keymaster_version, ASN1_INTEGER),
+        ASN1_SIMPLE(KM_KEY_DESCRIPTION, keymaster_security_level, ASN1_ENUMERATED),
+        ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_challenge, ASN1_OCTET_STRING),
+        ASN1_SIMPLE(KM_KEY_DESCRIPTION, unique_id, ASN1_OCTET_STRING),
+        ASN1_SIMPLE(KM_KEY_DESCRIPTION, software_enforced, KM_AUTH_LIST),
+        ASN1_SIMPLE(KM_KEY_DESCRIPTION, tee_enforced, KM_AUTH_LIST),
+} ASN1_SEQUENCE_END(KM_KEY_DESCRIPTION);
+IMPLEMENT_ASN1_FUNCTIONS(KM_KEY_DESCRIPTION);
+
+template <V4_0::Tag tag>
+void copyAuthTag(const stack_st_ASN1_INTEGER* stack, TypedTag<TagType::ENUM_REP, tag> ttag,
+                 AuthorizationSet* auth_list) {
+    typedef typename V4_0::TypedTag2ValueType<decltype(ttag)>::type ValueT;
+    for (size_t i = 0; i < sk_ASN1_INTEGER_num(stack); ++i) {
+        auth_list->push_back(
+                ttag, static_cast<ValueT>(ASN1_INTEGER_get(sk_ASN1_INTEGER_value(stack, i))));
+    }
+}
+
+template <V4_0::Tag tag>
+void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::ENUM, tag> ttag,
+                 AuthorizationSet* auth_list) {
+    typedef typename V4_0::TypedTag2ValueType<decltype(ttag)>::type ValueT;
+    if (!asn1_int) return;
+    auth_list->push_back(ttag, static_cast<ValueT>(ASN1_INTEGER_get(asn1_int)));
+}
+
+template <V4_0::Tag tag>
+void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::UINT, tag> ttag,
+                 AuthorizationSet* auth_list) {
+    if (!asn1_int) return;
+    auth_list->push_back(ttag, ASN1_INTEGER_get(asn1_int));
+}
+
+BIGNUM* construct_uint_max() {
+    BIGNUM* value = BN_new();
+    BIGNUM_Ptr one(BN_new());
+    BN_one(one.get());
+    BN_lshift(value, one.get(), 32);
+    return value;
+}
+
+uint64_t BignumToUint64(BIGNUM* num) {
+    static_assert((sizeof(BN_ULONG) == sizeof(uint32_t)) || (sizeof(BN_ULONG) == sizeof(uint64_t)),
+                  "This implementation only supports 32 and 64-bit BN_ULONG");
+    if (sizeof(BN_ULONG) == sizeof(uint32_t)) {
+        BIGNUM_Ptr uint_max(construct_uint_max());
+        BIGNUM_Ptr hi(BN_new()), lo(BN_new());
+        BN_CTX_Ptr ctx(BN_CTX_new());
+        BN_div(hi.get(), lo.get(), num, uint_max.get(), ctx.get());
+        return static_cast<uint64_t>(BN_get_word(hi.get())) << 32 | BN_get_word(lo.get());
+    } else if (sizeof(BN_ULONG) == sizeof(uint64_t)) {
+        return BN_get_word(num);
+    } else {
+        return 0;
+    }
+}
+
+template <V4_0::Tag tag>
+void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::ULONG, tag> ttag,
+                 AuthorizationSet* auth_list) {
+    if (!asn1_int) return;
+    BIGNUM_Ptr num(ASN1_INTEGER_to_BN(asn1_int, nullptr));
+    auth_list->push_back(ttag, BignumToUint64(num.get()));
+}
+
+template <V4_0::Tag tag>
+void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::DATE, tag> ttag,
+                 AuthorizationSet* auth_list) {
+    if (!asn1_int) return;
+    BIGNUM_Ptr num(ASN1_INTEGER_to_BN(asn1_int, nullptr));
+    auth_list->push_back(ttag, BignumToUint64(num.get()));
+}
+
+template <V4_0::Tag tag>
+void copyAuthTag(const ASN1_NULL* asn1_null, TypedTag<TagType::BOOL, tag> ttag,
+                 AuthorizationSet* auth_list) {
+    if (!asn1_null) return;
+    auth_list->push_back(ttag);
+}
+
+template <V4_0::Tag tag>
+void copyAuthTag(const ASN1_OCTET_STRING* asn1_string, TypedTag<TagType::BYTES, tag> ttag,
+                 AuthorizationSet* auth_list) {
+    if (!asn1_string) return;
+    hidl_vec<uint8_t> buf;
+    buf.setToExternal(asn1_string->data, asn1_string->length);
+    auth_list->push_back(ttag, buf);
+}
+
+// Extract the values from the specified ASN.1 record and place them in auth_list.
+static ErrorCode extract_auth_list(const KM_AUTH_LIST* record, AuthorizationSet* auth_list) {
+    if (!record) return ErrorCode::OK;
+
+    copyAuthTag(record->active_date_time, TAG_ACTIVE_DATETIME, auth_list);
+    copyAuthTag(record->algorithm, TAG_ALGORITHM, auth_list);
+    copyAuthTag(record->application_id, TAG_APPLICATION_ID, auth_list);
+    copyAuthTag(record->auth_timeout, TAG_AUTH_TIMEOUT, auth_list);
+    copyAuthTag(record->creation_date_time, TAG_CREATION_DATETIME, auth_list);
+    copyAuthTag(record->digest, TAG_DIGEST, auth_list);
+    copyAuthTag(record->ec_curve, TAG_EC_CURVE, auth_list);
+    copyAuthTag(record->key_size, TAG_KEY_SIZE, auth_list);
+    copyAuthTag(record->no_auth_required, TAG_NO_AUTH_REQUIRED, auth_list);
+    copyAuthTag(record->origin, TAG_ORIGIN, auth_list);
+    copyAuthTag(record->origination_expire_date_time, TAG_ORIGINATION_EXPIRE_DATETIME, auth_list);
+    copyAuthTag(record->os_patchlevel, TAG_OS_PATCHLEVEL, auth_list);
+    copyAuthTag(record->os_version, TAG_OS_VERSION, auth_list);
+    copyAuthTag(record->padding, TAG_PADDING, auth_list);
+    copyAuthTag(record->purpose, TAG_PURPOSE, auth_list);
+    copyAuthTag(record->rollback_resistance, TAG_ROLLBACK_RESISTANCE, auth_list);
+    copyAuthTag(record->rsa_public_exponent, TAG_RSA_PUBLIC_EXPONENT, auth_list);
+    copyAuthTag(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list);
+    copyAuthTag(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list);
+    copyAuthTag(record->attestation_application_id, TAG_ATTESTATION_APPLICATION_ID, auth_list);
+    copyAuthTag(record->vendor_patchlevel, TAG_VENDOR_PATCHLEVEL, auth_list);
+    copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
+    copyAuthTag(record->trusted_user_presence_required, TAG_TRUSTED_USER_PRESENCE_REQUIRED,
+                auth_list);
+    copyAuthTag(record->trusted_confirmation_required, TAG_TRUSTED_CONFIRMATION_REQUIRED,
+                auth_list);
+    copyAuthTag(record->unlocked_device_required, TAG_UNLOCKED_DEVICE_REQUIRED, auth_list);
+    copyAuthTag(record->early_boot_only, TAG_EARLY_BOOT_ONLY, auth_list);
+    copyAuthTag(record->device_unique_attestation, TAG_DEVICE_UNIQUE_ATTESTATION, auth_list);
+
+    return ErrorCode::OK;
+}
+
+MAKE_OPENSSL_PTR_TYPE(KM_KEY_DESCRIPTION)
+
+// Parse the DER-encoded attestation record, placing the results in keymaster_version,
+// attestation_challenge, software_enforced, tee_enforced and unique_id.
+std::tuple<ErrorCode, AttestationRecord> parse_attestation_record(const hidl_vec<uint8_t>& cert) {
+    const uint8_t* p = cert.data();
+    X509_Ptr x509(d2i_X509(nullptr, &p, cert.size()));
+
+    ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */));
+    if (!oid.get()) {
+        LOG(ERROR) << "Error parsing OID";
+        return {ErrorCode::UNKNOWN_ERROR, {}};
+    }
+
+    int location = X509_get_ext_by_OBJ(x509.get(), oid.get(), -1 /* search from beginning */);
+    if (location == -1) {
+        LOG(ERROR) << "Attestation extension not found in certificate";
+        return {ErrorCode::UNKNOWN_ERROR, {}};
+    }
+
+    X509_EXTENSION* attest_rec_ext = X509_get_ext(x509.get(), location);
+    if (!attest_rec_ext) {
+        LOG(ERROR) << "Found extension but couldn't retrieve it.  Probably BoringSSL bug.";
+        return {ErrorCode::UNKNOWN_ERROR, {}};
+    }
+
+    ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext);
+    if (!attest_rec_ext) {
+        LOG(ERROR) << "Attestation extension contained no data";
+        return {ErrorCode::UNKNOWN_ERROR, {}};
+    }
+
+    p = attest_rec->data;
+    KM_KEY_DESCRIPTION_Ptr record(d2i_KM_KEY_DESCRIPTION(nullptr, &p, attest_rec->length));
+    if (!record.get()) return {ErrorCode::UNKNOWN_ERROR, {}};
+
+    AttestationRecord result;
+
+    result.attestation_version = ASN1_INTEGER_get(record->attestation_version);
+    result.attestation_security_level =
+            static_cast<SecurityLevel>(ASN1_ENUMERATED_get(record->attestation_security_level));
+    result.keymaster_version = ASN1_INTEGER_get(record->keymaster_version);
+    result.keymaster_security_level =
+            static_cast<SecurityLevel>(ASN1_ENUMERATED_get(record->keymaster_security_level));
+
+    auto& chall = record->attestation_challenge;
+    result.attestation_challenge.resize(chall->length);
+    memcpy(result.attestation_challenge.data(), chall->data, chall->length);
+    auto& uid = record->unique_id;
+    result.unique_id.resize(uid->length);
+    memcpy(result.unique_id.data(), uid->data, uid->length);
+
+    ErrorCode error = extract_auth_list(record->software_enforced, &result.software_enforced);
+    if (error != ErrorCode::OK) return {error, {}};
+
+    error = extract_auth_list(record->tee_enforced, &result.hardware_enforced);
+    if (error != ErrorCode::OK) return {error, {}};
+
+    KM_ROOT_OF_TRUST* root_of_trust = nullptr;
+    if (record->tee_enforced && record->tee_enforced->root_of_trust) {
+        root_of_trust = record->tee_enforced->root_of_trust;
+    } else if (record->software_enforced && record->software_enforced->root_of_trust) {
+        root_of_trust = record->software_enforced->root_of_trust;
+    } else {
+        LOG(ERROR) << AT << " Failed root of trust parsing";
+        return {ErrorCode::INVALID_ARGUMENT, {}};
+    }
+    if (!root_of_trust->verified_boot_key) {
+        LOG(ERROR) << AT << " Failed verified boot key parsing";
+        return {ErrorCode::INVALID_ARGUMENT, {}};
+    }
+
+    RootOfTrust& rot = result.root_of_trust;
+    auto& vb_key = root_of_trust->verified_boot_key;
+    rot.verified_boot_key.resize(vb_key->length);
+    memcpy(rot.verified_boot_key.data(), vb_key->data, vb_key->length);
+
+    rot.verified_boot_state = static_cast<keymaster_verified_boot_t>(
+            ASN1_ENUMERATED_get(root_of_trust->verified_boot_state));
+    rot.device_locked = root_of_trust->device_locked;
+
+    auto& vb_hash = root_of_trust->verified_boot_hash;
+    if (!vb_hash) {
+        LOG(ERROR) << AT << " Failed verified boot hash parsing";
+        return {ErrorCode::INVALID_ARGUMENT, {}};
+    }
+    rot.verified_boot_hash.resize(vb_hash->length);
+    memcpy(rot.verified_boot_hash.data(), vb_hash->data, vb_hash->length);
+
+    return {ErrorCode::OK, result};
+}
+
+}  // namespace V4_1
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h b/keymaster/4.1/support/include/keymasterV4_1/Keymaster.h
similarity index 72%
rename from keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
rename to keymaster/4.1/support/include/keymasterV4_1/Keymaster.h
index 43a34b0..2266636 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
+++ b/keymaster/4.1/support/include/keymasterV4_1/Keymaster.h
@@ -15,31 +15,31 @@
  ** limitations under the License.
  */
 
-#ifndef HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_H_
-#define HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_H_
-
-#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#pragma once
 
 #include <memory>
 #include <vector>
 
-namespace android {
-namespace hardware {
-namespace keymaster {
-namespace V4_0 {
-namespace support {
+#include <android/hardware/keymaster/4.1/IKeymasterDevice.h>
+#include <keymasterV4_1/keymaster_tags.h>
+
+namespace android::hardware::keymaster::V4_1::support {
 
 /**
- * Keymaster abstracts the underlying V4_0::IKeymasterDevice.  There is one implementation
- * (Keymaster4) which is a trivial passthrough and one that wraps a V3_0::IKeymasterDevice.
+ * Keymaster abstracts the underlying V4_1::IKeymasterDevice.  There are two implementations,
+ * Keymaster3 which wraps a V3_0::IKeymasterDevice and Keymaster4, which wraps either a
+ * V4_0::IKeymasterDevice or a V4_1::IKeymasterDevice.  There is a V3_0::IKeymasterDevice
+ * implementation that is used to wrap pre-HIDL keymaster implementations, and Keymaster3 will wrap
+ * that.
  *
  * The reason for adding this additional layer, rather than simply using the latest HAL directly and
  * subclassing it to wrap any older HAL, is because this provides a place to put additional methods
  * which clients can use when they need to distinguish between different underlying HAL versions,
- * while still having to use only the latest interface.
+ * while still having to use only the latest interface.  Plus it's a handy place to keep some
+ * convenience methods.
  */
 class Keymaster : public IKeymasterDevice {
-   public:
+  public:
     using KeymasterSet = std::vector<std::unique_ptr<Keymaster>>;
 
     Keymaster(const hidl_string& descriptor, const hidl_string& instanceName)
@@ -50,12 +50,14 @@
         hidl_string keymasterName;
         hidl_string authorName;
         uint8_t majorVersion;
+        uint8_t minorVersion;
         SecurityLevel securityLevel;
         bool supportsEc;
 
         bool operator>(const VersionResult& other) const {
-            auto lhs = std::tie(securityLevel, majorVersion, supportsEc);
-            auto rhs = std::tie(other.securityLevel, other.majorVersion, other.supportsEc);
+            auto lhs = std::tie(securityLevel, majorVersion, minorVersion, supportsEc);
+            auto rhs = std::tie(other.securityLevel, other.majorVersion, other.minorVersion,
+                                other.supportsEc);
             return lhs > rhs;
         }
     };
@@ -69,6 +71,9 @@
      * There are no side effects otherwise.
      */
     void logIfKeymasterVendorError(ErrorCode ec) const;
+    void logIfKeymasterVendorError(V4_0::ErrorCode ec) const {
+        logIfKeymasterVendorError(static_cast<ErrorCode>(ec));
+    }
 
     /**
      * Returns all available Keymaster3 and Keymaster4 instances, in order of most secure to least
@@ -86,17 +91,11 @@
      */
     static void performHmacKeyAgreement(const KeymasterSet& keymasters);
 
-   private:
+  private:
     hidl_string descriptor_;
     hidl_string instanceName_;
 };
 
 std::ostream& operator<<(std::ostream& os, const Keymaster& keymaster);
 
-}  // namespace support
-}  // namespace V4_0
-}  // namespace keymaster
-}  // namespace hardware
-}  // namespace android
-
-#endif  // HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_H_
+}  // namespace android::hardware::keymaster::V4_1::support
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h b/keymaster/4.1/support/include/keymasterV4_1/Keymaster3.h
similarity index 72%
rename from keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h
rename to keymaster/4.1/support/include/keymasterV4_1/Keymaster3.h
index c40be7c..c201e8c 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h
+++ b/keymaster/4.1/support/include/keymasterV4_1/Keymaster3.h
@@ -1,5 +1,4 @@
 /*
- **
  ** Copyright 2017, The Android Open Source Project
  **
  ** Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,18 +14,14 @@
  ** limitations under the License.
  */
 
-#ifndef HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_3_H_
-#define HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_3_H_
+#pragma once
 
 #include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
 
 #include "Keymaster.h"
+#include "Operation.h"
 
-namespace android {
-namespace hardware {
-namespace keymaster {
-namespace V4_0 {
-namespace support {
+namespace android::hardware::keymaster::V4_1::support {
 
 using IKeymaster3Device = ::android::hardware::keymaster::V3_0::IKeymasterDevice;
 
@@ -38,8 +33,10 @@
 using ::android::hardware::details::return_status;
 
 class Keymaster3 : public Keymaster {
-   public:
+  public:
+    // This definition is used for device enumeration.
     using WrappedIKeymasterDevice = IKeymaster3Device;
+
     Keymaster3(sp<IKeymaster3Device> km3_dev, const hidl_string& instanceName)
         : Keymaster(IKeymaster3Device::descriptor, instanceName),
           km3_dev_(km3_dev),
@@ -53,24 +50,24 @@
     Return<void> getHardwareInfo(getHardwareInfo_cb _hidl_cb);
 
     Return<void> getHmacSharingParameters(getHmacSharingParameters_cb _hidl_cb) override {
-        _hidl_cb(ErrorCode::UNIMPLEMENTED, {});
+        _hidl_cb(V4_0::ErrorCode::UNIMPLEMENTED, {});
         return Void();
     }
 
     Return<void> computeSharedHmac(const hidl_vec<HmacSharingParameters>&,
                                    computeSharedHmac_cb _hidl_cb) override {
-        _hidl_cb(ErrorCode::UNIMPLEMENTED, {});
+        _hidl_cb(V4_0::ErrorCode::UNIMPLEMENTED, {});
         return Void();
     }
 
     Return<void> verifyAuthorization(uint64_t, const hidl_vec<KeyParameter>&,
                                      const HardwareAuthToken&,
                                      verifyAuthorization_cb _hidl_cb) override {
-        _hidl_cb(ErrorCode::UNIMPLEMENTED, {});
+        _hidl_cb(V4_0::ErrorCode::UNIMPLEMENTED, {});
         return Void();
     }
 
-    Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override;
+    Return<V4_0::ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override;
     Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
                              generateKey_cb _hidl_cb) override;
     Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
@@ -86,7 +83,7 @@
                                   const hidl_vec<KeyParameter>& /* unwrappingParams */,
                                   uint64_t /* passwordSid */, uint64_t /* biometricSid */,
                                   importWrappedKey_cb _hidl_cb) {
-        _hidl_cb(ErrorCode::UNIMPLEMENTED, {}, {});
+        _hidl_cb(V4_0::ErrorCode::UNIMPLEMENTED, {}, {});
         return Void();
     }
 
@@ -99,9 +96,9 @@
     Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
                             const hidl_vec<KeyParameter>& upgradeParams,
                             upgradeKey_cb _hidl_cb) override;
-    Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override;
-    Return<ErrorCode> deleteAllKeys() override;
-    Return<ErrorCode> destroyAttestationIds() override;
+    Return<V4_0::ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override;
+    Return<V4_0::ErrorCode> deleteAllKeys() override;
+    Return<V4_0::ErrorCode> destroyAttestationIds() override;
     Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
                        const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
                        begin_cb _hidl_cb) override;
@@ -112,9 +109,31 @@
                         const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
                         const HardwareAuthToken& authToken,
                         const VerificationToken& verificationToken, finish_cb _hidl_cb) override;
-    Return<ErrorCode> abort(uint64_t operationHandle) override;
+    Return<V4_0::ErrorCode> abort(uint64_t operationHandle) override;
 
-   private:
+    /**********************************
+     * V4_1::IKeymasterDevice methods *
+     *********************************/
+
+    Return<ErrorCode> deviceLocked(bool /* passwordOnly */,
+                                   const VerificationToken& /* verificationToken */) override {
+        return ErrorCode::UNIMPLEMENTED;
+    }
+
+    Return<ErrorCode> earlyBootEnded() override { return ErrorCode::UNIMPLEMENTED; }
+
+    Return<void> beginOp(KeyPurpose purpose, const hidl_vec<uint8_t>& keyBlob,
+                         const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
+                         beginOp_cb _hidl_cb) override {
+        return begin(purpose, keyBlob, inParams, authToken,
+                     [&_hidl_cb](V4_0::ErrorCode errorCode, const hidl_vec<KeyParameter>& outParams,
+                                 OperationHandle operationHandle) {
+                         _hidl_cb(static_cast<ErrorCode>(errorCode), outParams,
+                                  new Operation(operationHandle));
+                     });
+    }
+
+  private:
     void getVersionIfNeeded();
 
     sp<IKeymaster3Device> km3_dev_;
@@ -126,10 +145,4 @@
     bool supportsAllDigests_;
 };
 
-}  // namespace support
-}  // namespace V4_0
-}  // namespace keymaster
-}  // namespace hardware
-}  // namespace android
-
-#endif  // HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_3_H_
+}  // namespace android::hardware::keymaster::V4_1::support
diff --git a/keymaster/4.1/support/include/keymasterV4_1/Keymaster4.h b/keymaster/4.1/support/include/keymasterV4_1/Keymaster4.h
new file mode 100644
index 0000000..6d74d98
--- /dev/null
+++ b/keymaster/4.1/support/include/keymasterV4_1/Keymaster4.h
@@ -0,0 +1,197 @@
+/*
+ ** 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.
+ */
+
+#pragma once
+
+#include "Keymaster.h"
+#include "Operation.h"
+
+namespace android::hardware::keymaster::V4_1::support {
+
+using android::sp;
+
+/**
+ * This class can wrap either a V4_0 or V4_1 IKeymasterDevice.
+ */
+class Keymaster4 : public Keymaster {
+  public:
+    // This definition is used for device enumeration; enumerating 4.0 devices will also
+    // enumerate 4.1. devices.
+    using WrappedIKeymasterDevice = V4_0::IKeymasterDevice;
+
+    Keymaster4(sp<V4_1::IKeymasterDevice> km4_1_dev, const hidl_string& instanceName)
+        : Keymaster(V4_1::IKeymasterDevice::descriptor, instanceName),
+          haveVersion_(false),
+          km4_0_dev_(km4_1_dev),
+          km4_1_dev_(km4_1_dev) {}
+
+    Keymaster4(sp<V4_0::IKeymasterDevice> km4_0_dev, const hidl_string& instanceName)
+        : Keymaster(V4_1::IKeymasterDevice::descriptor, instanceName),
+          haveVersion_(false),
+          km4_0_dev_(km4_0_dev),
+          km4_1_dev_() {}
+
+    const VersionResult& halVersion() const override {
+        const_cast<Keymaster4*>(this)->getVersionIfNeeded();
+        return version_;
+    }
+
+    /**********************************
+     * V4_0::IKeymasterDevice methods *
+     *********************************/
+
+    Return<void> getHardwareInfo(getHardwareInfo_cb _hidl_cb) override {
+        return km4_0_dev_->getHardwareInfo(_hidl_cb);
+    }
+
+    Return<void> getHmacSharingParameters(getHmacSharingParameters_cb _hidl_cb) override {
+        return km4_0_dev_->getHmacSharingParameters(_hidl_cb);
+    }
+
+    Return<void> computeSharedHmac(const hidl_vec<HmacSharingParameters>& params,
+                                   computeSharedHmac_cb _hidl_cb) override {
+        return km4_0_dev_->computeSharedHmac(params, _hidl_cb);
+    }
+
+    Return<void> verifyAuthorization(uint64_t operationHandle, const hidl_vec<KeyParameter>& params,
+                                     const HardwareAuthToken& authToken,
+                                     verifyAuthorization_cb _hidl_cb) override {
+        return km4_0_dev_->verifyAuthorization(operationHandle, params, authToken, _hidl_cb);
+    }
+
+    Return<V4_0::ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override {
+        return km4_0_dev_->addRngEntropy(data);
+    }
+
+    Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
+                             generateKey_cb _hidl_cb) override {
+        return km4_0_dev_->generateKey(keyParams, _hidl_cb);
+    }
+
+    Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+                                       const hidl_vec<uint8_t>& clientId,
+                                       const hidl_vec<uint8_t>& appData,
+                                       getKeyCharacteristics_cb _hidl_cb) override {
+        return km4_0_dev_->getKeyCharacteristics(keyBlob, clientId, appData, _hidl_cb);
+    }
+
+    Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
+                           const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) override {
+        return km4_0_dev_->importKey(params, keyFormat, keyData, _hidl_cb);
+    }
+
+    Return<void> importWrappedKey(const hidl_vec<uint8_t>& wrappedKeyData,
+                                  const hidl_vec<uint8_t>& wrappingKeyBlob,
+                                  const hidl_vec<uint8_t>& maskingKey,
+                                  const hidl_vec<KeyParameter>& unwrappingParams,
+                                  uint64_t passwordSid, uint64_t biometricSid,
+                                  importWrappedKey_cb _hidl_cb) {
+        return km4_0_dev_->importWrappedKey(wrappedKeyData, wrappingKeyBlob, maskingKey,
+                                            unwrappingParams, passwordSid, biometricSid, _hidl_cb);
+    }
+
+    Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
+                           const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
+                           exportKey_cb _hidl_cb) override {
+        return km4_0_dev_->exportKey(exportFormat, keyBlob, clientId, appData, _hidl_cb);
+    }
+
+    Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
+                           const hidl_vec<KeyParameter>& attestParams,
+                           attestKey_cb _hidl_cb) override {
+        return km4_0_dev_->attestKey(keyToAttest, attestParams, _hidl_cb);
+    }
+
+    Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+                            const hidl_vec<KeyParameter>& upgradeParams,
+                            upgradeKey_cb _hidl_cb) override {
+        return km4_0_dev_->upgradeKey(keyBlobToUpgrade, upgradeParams, _hidl_cb);
+    }
+
+    Return<V4_0::ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override {
+        return km4_0_dev_->deleteKey(keyBlob);
+    }
+
+    Return<V4_0::ErrorCode> deleteAllKeys() override { return km4_0_dev_->deleteAllKeys(); }
+
+    Return<V4_0::ErrorCode> destroyAttestationIds() override {
+        return km4_0_dev_->destroyAttestationIds();
+    }
+
+    Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+                       const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
+                       begin_cb _hidl_cb) override {
+        return km4_0_dev_->begin(purpose, key, inParams, authToken, _hidl_cb);
+    }
+
+    Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, const HardwareAuthToken& authToken,
+                        const VerificationToken& verificationToken, update_cb _hidl_cb) override {
+        return km4_0_dev_->update(operationHandle, inParams, input, authToken, verificationToken,
+                                  _hidl_cb);
+    }
+
+    Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+                        const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
+                        const HardwareAuthToken& authToken,
+                        const VerificationToken& verificationToken, finish_cb _hidl_cb) override {
+        return km4_0_dev_->finish(operationHandle, inParams, input, signature, authToken,
+                                  verificationToken, _hidl_cb);
+    }
+
+    Return<V4_0::ErrorCode> abort(uint64_t operationHandle) override {
+        return km4_0_dev_->abort(operationHandle);
+    }
+
+    /**********************************
+     * V4_1::IKeymasterDevice methods *
+     *********************************/
+
+    Return<ErrorCode> deviceLocked(bool passwordOnly,
+                                   const VerificationToken& verificationToken) override {
+        if (km4_1_dev_) return km4_1_dev_->deviceLocked(passwordOnly, verificationToken);
+        return ErrorCode::UNIMPLEMENTED;
+    }
+
+    Return<ErrorCode> earlyBootEnded() override {
+        if (km4_1_dev_) return km4_1_dev_->earlyBootEnded();
+        return ErrorCode::UNIMPLEMENTED;
+    }
+
+    Return<void> beginOp(KeyPurpose purpose, const hidl_vec<uint8_t>& keyBlob,
+                         const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
+                         beginOp_cb _hidl_cb) override {
+        if (km4_1_dev_) return km4_1_dev_->beginOp(purpose, keyBlob, inParams, authToken, _hidl_cb);
+
+        return km4_0_dev_->begin(
+                purpose, keyBlob, inParams, authToken,
+                [&_hidl_cb](V4_0::ErrorCode errorCode, const hidl_vec<KeyParameter>& outParams,
+                            OperationHandle operationHandle) {
+                    _hidl_cb(static_cast<ErrorCode>(errorCode), outParams,
+                             new Operation(operationHandle));
+                });
+    }
+
+  private:
+    void getVersionIfNeeded();
+
+    bool haveVersion_;
+    VersionResult version_;
+    sp<V4_0::IKeymasterDevice> km4_0_dev_;
+    sp<V4_1::IKeymasterDevice> km4_1_dev_;
+};  // namespace android::hardware::keymaster::V4_1::support
+
+}  // namespace android::hardware::keymaster::V4_1::support
diff --git a/keymaster/4.1/support/include/keymasterV4_1/Operation.h b/keymaster/4.1/support/include/keymasterV4_1/Operation.h
new file mode 100644
index 0000000..902d49a
--- /dev/null
+++ b/keymaster/4.1/support/include/keymasterV4_1/Operation.h
@@ -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.
+ */
+
+#pragma once
+
+#include <android/hardware/keymaster/4.1/IOperation.h>
+
+#include <keymasterV4_1/keymaster_tags.h>
+
+namespace android::hardware::keymaster::V4_1::support {
+
+class Operation : public IOperation {
+  public:
+    Operation(OperationHandle handle) : handle_(handle) {}
+
+    Return<void> getOperationChallenge(getOperationChallenge_cb _hidl_cb) override {
+        _hidl_cb(V4_1::ErrorCode::OK, handle_);
+        return Void();
+    }
+
+  private:
+    OperationHandle handle_;
+};
+
+}  // namespace android::hardware::keymaster::V4_1::support
diff --git a/keymaster/4.1/support/include/keymasterV4_1/attestation_record.h b/keymaster/4.1/support/include/keymasterV4_1/attestation_record.h
new file mode 100644
index 0000000..b543bdd
--- /dev/null
+++ b/keymaster/4.1/support/include/keymasterV4_1/attestation_record.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/keymaster/4.1/IKeymasterDevice.h>
+#include <keymasterV4_0/attestation_record.h>
+#include <keymasterV4_0/openssl_utils.h>
+#include <keymasterV4_1/authorization_set.h>
+
+namespace android {
+namespace hardware {
+namespace keymaster {
+namespace V4_1 {
+
+using V4_0::kAttestionRecordOid;
+using V4_0::keymaster_verified_boot_t;
+
+struct RootOfTrust {
+    SecurityLevel security_level;
+    hidl_vec<uint8_t> verified_boot_key;
+    hidl_vec<uint8_t> verified_boot_hash;
+    keymaster_verified_boot_t verified_boot_state;
+    bool device_locked;
+};
+
+struct AttestationRecord {
+    RootOfTrust root_of_trust;
+    uint32_t attestation_version;
+    SecurityLevel attestation_security_level;
+    uint32_t keymaster_version;
+    SecurityLevel keymaster_security_level;
+    hidl_vec<uint8_t> attestation_challenge;
+    AuthorizationSet software_enforced;
+    AuthorizationSet hardware_enforced;
+    hidl_vec<uint8_t> unique_id;
+};
+
+std::tuple<ErrorCode, AttestationRecord> parse_attestation_record(const hidl_vec<uint8_t>& cert);
+
+}  // namespace V4_1
+}  // namespace keymaster
+}  // namespace hardware
+}  // namespace android
diff --git a/keymaster/4.1/support/include/keymasterV4_1/authorization_set.h b/keymaster/4.1/support/include/keymasterV4_1/authorization_set.h
index afc0eaf..01605b7 100644
--- a/keymaster/4.1/support/include/keymasterV4_1/authorization_set.h
+++ b/keymaster/4.1/support/include/keymasterV4_1/authorization_set.h
@@ -14,8 +14,7 @@
  * limitations under the License.
  */
 
-#ifndef HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_AUTHORIZATION_SET_H_
-#define HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_AUTHORIZATION_SET_H_
+#pragma once
 
 #include <keymasterV4_0/authorization_set.h>
 
@@ -28,5 +27,3 @@
 using V4_0::KeyParameter;
 
 }  // namespace android::hardware::keymaster::V4_1
-
-#endif  // HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_AUTHORIZATION_SET_H_
diff --git a/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
index 6ffe8e1..40eb142 100644
--- a/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
+++ b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
@@ -23,16 +23,26 @@
 
 namespace android::hardware::keymaster::V4_1 {
 
+using V4_0::Algorithm;
 using V4_0::BlockMode;
 using V4_0::Digest;
 using V4_0::EcCurve;
-using V4_0::ErrorCode;
+using V4_0::HardwareAuthenticatorType;
 using V4_0::HardwareAuthToken;
+using V4_0::HmacSharingParameters;
+using V4_0::KeyBlobUsageRequirements;
+using V4_0::KeyCharacteristics;
+using V4_0::KeyFormat;
+using V4_0::KeyOrigin;
 using V4_0::KeyParameter;
+using V4_0::KeyPurpose;
+using V4_0::OperationHandle;
 using V4_0::PaddingMode;
+using V4_0::SecurityLevel;
 using V4_0::TagType;
 using V4_0::VerificationToken;
 
+using V4_0::NullOr;
 using V4_0::TypedTag;
 
 using V4_0::TAG_ACTIVE_DATETIME;
@@ -90,6 +100,8 @@
 
 DECLARE_KM_4_1_TYPED_TAG(EARLY_BOOT_ONLY);
 DECLARE_KM_4_1_TYPED_TAG(DEVICE_UNIQUE_ATTESTATION);
+DECLARE_KM_4_1_TYPED_TAG(STORAGE_KEY);
+DECLARE_KM_4_1_TYPED_TAG(IDENTITY_CREDENTIAL_KEY);
 
 }  // namespace android::hardware::keymaster::V4_1
 
diff --git a/radio/config/1.3/IRadioConfigIndication.hal b/keymaster/4.1/support/include/keymasterV4_1/keymaster_utils.h
similarity index 64%
copy from radio/config/1.3/IRadioConfigIndication.hal
copy to keymaster/4.1/support/include/keymasterV4_1/keymaster_utils.h
index 9ef496c..2e28002 100644
--- a/radio/config/1.3/IRadioConfigIndication.hal
+++ b/keymaster/4.1/support/include/keymasterV4_1/keymaster_utils.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright (C) 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package android.hardware.radio.config@1.3;
+#pragma once
 
-import @1.2::IRadioConfigIndication;
+#include <keymasterV4_0/keymaster_utils.h>
 
-/**
- * Interface declaring unsolicited radio config indications.
- */
-interface IRadioConfigIndication extends @1.2::IRadioConfigIndication {
+namespace android::hardware::keymaster::V4_1::support {
 
-};
+using V4_0::support::blob2hidlVec;
+using V4_0::support::hidlVec2AuthToken;
+
+}  // namespace android::hardware::keymaster::V4_1::support
diff --git a/keymaster/4.1/types.hal b/keymaster/4.1/types.hal
index 9e8b30e..f3bdcc6 100644
--- a/keymaster/4.1/types.hal
+++ b/keymaster/4.1/types.hal
@@ -50,10 +50,29 @@
      * HAL attests to Credential Keys.  IIdentityCredential produces Keymaster-style attestations.
      */
     IDENTITY_CREDENTIAL_KEY = TagType:BOOL | 721,
+
+    /**
+     * To prevent keys from being compromised if an attacker acquires read access to system / kernel
+     * memory, some inline encryption hardware supports protecting storage encryption keys in hardware
+     * without software having access to or the ability to set the plaintext keys. Instead, software
+     * only sees wrapped version of these keys.
+     *
+     * STORAGE_KEY is used to denote that a key generated or imported is a key used for storage
+     * encryption. Keys of this type can either be generated or imported or secure imported using
+     * keymaster. exportKey() can be used to re-wrap storage key with a per-boot ephemeral key wrapped
+     * key once the key characteristics are enforced.
+     *
+     * Keys with this tag cannot be used for any operation within keymaster.
+     * ErrorCode::INVALID_OPERATION is returned when a key with Tag::STORAGE_KEY is provided to
+     * begin().
+     */
+    STORAGE_KEY = TagType:BOOL | 722,
 };
 
 enum ErrorCode : @4.0::ErrorCode {
     EARLY_BOOT_ENDED = -73,
     ATTESTATION_KEYS_NOT_PROVISIONED = -74,
     ATTESTATION_IDS_NOT_PROVISIONED = -75,
+    INVALID_OPERATION = -76,
+    STORAGE_KEY_UNSUPPORTED = -77,
 };
diff --git a/keymaster/4.1/vts/functional/Android.bp b/keymaster/4.1/vts/functional/Android.bp
index f5a0c9c..c2d7fa3 100644
--- a/keymaster/4.1/vts/functional/Android.bp
+++ b/keymaster/4.1/vts/functional/Android.bp
@@ -19,12 +19,24 @@
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "EarlyBootKeyTest.cpp",
+        "DeviceUniqueAttestationTest.cpp",
+        "Keymaster4_1HidlTest.cpp",
+        "UnlockedDeviceRequiredTest.cpp",
     ],
     static_libs: [
         "android.hardware.keymaster@4.0",
         "android.hardware.keymaster@4.1",
-        "libkeymaster4support",
+        "libcrypto_static",
         "libkeymaster4_1support",
+        "libkeymaster4support",
+        "libkeymaster4vtstest",
     ],
-    test_suites: ["vts-core"],
+    cflags: [
+        "-Wall",
+        "-O0",
+    ],
+    test_suites: [
+        "general-tests",
+        "vts-core",
+    ],
 }
diff --git a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
new file mode 100644
index 0000000..7ea3275
--- /dev/null
+++ b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Keymaster4_1HidlTest.h"
+
+#include <cutils/properties.h>
+
+#include <openssl/x509.h>
+
+#include <keymasterV4_1/attestation_record.h>
+#include <keymasterV4_1/authorization_set.h>
+
+namespace android::hardware::keymaster::V4_0 {
+
+bool operator==(const AuthorizationSet& a, const AuthorizationSet& b) {
+    return std::equal(a.begin(), a.end(), b.begin(), b.end());
+}
+
+}  // namespace android::hardware::keymaster::V4_0
+
+namespace android::hardware::keymaster::V4_1 {
+
+inline ::std::ostream& operator<<(::std::ostream& os, Tag tag) {
+    return os << toString(tag);
+}
+
+namespace test {
+
+using std::string;
+using std::tuple;
+
+namespace {
+
+char nibble2hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
+                       '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+string bin2hex(const hidl_vec<uint8_t>& data) {
+    string retval;
+    retval.reserve(data.size() * 2 + 1);
+    for (uint8_t byte : data) {
+        retval.push_back(nibble2hex[0x0F & (byte >> 4)]);
+        retval.push_back(nibble2hex[0x0F & byte]);
+    }
+    return retval;
+}
+
+struct AuthorizationSetDifferences {
+    string aName;
+    string bName;
+    AuthorizationSet aWhackB;
+    AuthorizationSet bWhackA;
+};
+
+std::ostream& operator<<(std::ostream& o, const AuthorizationSetDifferences& diffs) {
+    if (!diffs.aWhackB.empty()) {
+        o << "Set " << diffs.aName << " contains the following that " << diffs.bName << " does not"
+          << diffs.aWhackB;
+        if (!diffs.bWhackA.empty()) o << std::endl;
+    }
+
+    if (!diffs.bWhackA.empty()) {
+        o << "Set " << diffs.bName << " contains the following that " << diffs.aName << " does not"
+          << diffs.bWhackA;
+    }
+    return o;
+}
+
+// Computes and returns a \ b and b \ a ('\' is the set-difference operator, a \ b means all the
+// elements that are in a but not b, i.e. take a and whack all the elements in b) to the provided
+// stream.  The sets must be sorted.
+//
+// This provides a simple and clear view of how the two sets differ, generally much
+// easier than scrutinizing printouts of the two sets.
+AuthorizationSetDifferences difference(string aName, const AuthorizationSet& a, string bName,
+                                       const AuthorizationSet& b) {
+    AuthorizationSetDifferences diffs = {std::move(aName), std::move(bName), {}, {}};
+    std::set_difference(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(diffs.aWhackB));
+    std::set_difference(b.begin(), b.end(), a.begin(), a.end(), std::back_inserter(diffs.bWhackA));
+    return diffs;
+}
+
+#define DIFFERENCE(a, b) difference(#a, a, #b, b)
+
+void check_root_of_trust(const RootOfTrust& root_of_trust) {
+    char vb_meta_device_state[PROPERTY_VALUE_MAX];
+    if (property_get("ro.boot.vbmeta.device_state", vb_meta_device_state, "") == 0) return;
+
+    char vb_meta_digest[PROPERTY_VALUE_MAX];
+    EXPECT_GT(property_get("ro.boot.vbmeta.digest", vb_meta_digest, ""), 0);
+    EXPECT_EQ(vb_meta_digest, bin2hex(root_of_trust.verified_boot_hash));
+
+    // Verified boot key should be all 0's if the boot state is not verified or self signed
+    HidlBuf empty_boot_key(string(32, '\0'));
+
+    char vb_meta_bootstate[PROPERTY_VALUE_MAX];
+    auto& verified_boot_key = root_of_trust.verified_boot_key;
+    auto& verified_boot_state = root_of_trust.verified_boot_state;
+    EXPECT_GT(property_get("ro.boot.verifiedbootstate", vb_meta_bootstate, ""), 0);
+    if (!strcmp(vb_meta_bootstate, "green")) {
+        EXPECT_EQ(verified_boot_state, V4_0::KM_VERIFIED_BOOT_VERIFIED);
+        EXPECT_NE(verified_boot_key, empty_boot_key);
+    } else if (!strcmp(vb_meta_bootstate, "yellow")) {
+        EXPECT_EQ(verified_boot_state, V4_0::KM_VERIFIED_BOOT_SELF_SIGNED);
+        EXPECT_NE(verified_boot_key, empty_boot_key);
+    } else if (!strcmp(vb_meta_bootstate, "orange")) {
+        EXPECT_EQ(verified_boot_state, V4_0::KM_VERIFIED_BOOT_UNVERIFIED);
+        EXPECT_EQ(verified_boot_key, empty_boot_key);
+    } else if (!strcmp(vb_meta_bootstate, "red")) {
+        EXPECT_EQ(verified_boot_state, V4_0::KM_VERIFIED_BOOT_FAILED);
+    } else {
+        EXPECT_EQ(verified_boot_state, V4_0::KM_VERIFIED_BOOT_UNVERIFIED);
+        EXPECT_EQ(verified_boot_key, empty_boot_key);
+    }
+}
+
+void check_attestation_record(AttestationRecord attestation, const HidlBuf& challenge,
+                              AuthorizationSet expected_sw_enforced,
+                              AuthorizationSet expected_hw_enforced,
+                              SecurityLevel expected_security_level) {
+    EXPECT_EQ(41U, attestation.keymaster_version);
+    EXPECT_EQ(4U, attestation.attestation_version);
+    EXPECT_EQ(expected_security_level, attestation.attestation_security_level);
+    EXPECT_EQ(expected_security_level, attestation.keymaster_security_level);
+    EXPECT_EQ(challenge, attestation.attestation_challenge);
+
+    check_root_of_trust(attestation.root_of_trust);
+
+    // Sort all of the authorization lists, so that equality matching works.
+    expected_sw_enforced.Sort();
+    expected_hw_enforced.Sort();
+    attestation.software_enforced.Sort();
+    attestation.hardware_enforced.Sort();
+
+    EXPECT_EQ(expected_sw_enforced, attestation.software_enforced)
+            << DIFFERENCE(expected_sw_enforced, attestation.software_enforced);
+    EXPECT_EQ(expected_hw_enforced, attestation.hardware_enforced)
+            << DIFFERENCE(expected_hw_enforced, attestation.hardware_enforced);
+}
+
+}  // namespace
+
+using std::string;
+using DeviceUniqueAttestationTest = Keymaster4_1HidlTest;
+
+TEST_P(DeviceUniqueAttestationTest, StrongBoxOnly) {
+    if (SecLevel() != SecurityLevel::STRONGBOX) return;
+
+    ASSERT_EQ(ErrorCode::OK, convert(GenerateKey(AuthorizationSetBuilder()
+                                                         .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                         .RsaSigningKey(2048, 65537)
+                                                         .Digest(Digest::SHA_2_256)
+                                                         .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
+                                                         .Authorization(TAG_INCLUDE_UNIQUE_ID))));
+
+    hidl_vec<hidl_vec<uint8_t>> cert_chain;
+    EXPECT_EQ(ErrorCode::UNIMPLEMENTED,
+              convert(AttestKey(
+                      AuthorizationSetBuilder()
+                              .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+                              .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
+                              .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")),
+                      &cert_chain)));
+    CheckedDeleteKey();
+
+    ASSERT_EQ(ErrorCode::OK, convert(GenerateKey(AuthorizationSetBuilder()
+                                                         .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                         .EcdsaSigningKey(EcCurve::P_256)
+                                                         .Digest(Digest::SHA_2_256)
+                                                         .Authorization(TAG_INCLUDE_UNIQUE_ID))));
+
+    EXPECT_EQ(ErrorCode::UNIMPLEMENTED,
+              convert(AttestKey(
+                      AuthorizationSetBuilder()
+                              .Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
+                              .Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")),
+                      &cert_chain)));
+}
+
+TEST_P(DeviceUniqueAttestationTest, Rsa) {
+    if (SecLevel() != SecurityLevel::STRONGBOX) return;
+    ASSERT_EQ(ErrorCode::OK,
+              convert(GenerateKey(AuthorizationSetBuilder()
+                                          .Authorization(TAG_NO_AUTH_REQUIRED)
+                                          .RsaSigningKey(2048, 65537)
+                                          .Digest(Digest::SHA_2_256)
+                                          .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
+                                          .Authorization(TAG_CREATION_DATETIME, 1))));
+
+    hidl_vec<hidl_vec<uint8_t>> cert_chain;
+    HidlBuf challenge("challenge");
+    HidlBuf app_id("foo");
+    EXPECT_EQ(ErrorCode::OK,
+              convert(AttestKey(AuthorizationSetBuilder()
+                                        .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+                                        .Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
+                                        .Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id),
+                                &cert_chain)));
+
+    EXPECT_EQ(1U, cert_chain.size());
+    auto [err, attestation] = parse_attestation_record(cert_chain[0]);
+    EXPECT_EQ(ErrorCode::OK, err);
+
+    check_attestation_record(attestation, challenge,
+                             /* sw_enforced */
+                             AuthorizationSetBuilder()
+                                     .Authorization(TAG_CREATION_DATETIME, 1)
+                                     .Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id),
+                             /* hw_enforced */
+                             AuthorizationSetBuilder()
+                                     .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+                                     .Authorization(TAG_NO_AUTH_REQUIRED)
+                                     .RsaSigningKey(2048, 65537)
+                                     .Digest(Digest::SHA_2_256)
+                                     .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
+                                     .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
+                                     .Authorization(TAG_OS_VERSION, os_version())
+                                     .Authorization(TAG_OS_PATCHLEVEL, os_patch_level()),
+                             SecLevel());
+}
+
+TEST_P(DeviceUniqueAttestationTest, Ecdsa) {
+    if (SecLevel() != SecurityLevel::STRONGBOX) return;
+    ASSERT_EQ(ErrorCode::OK,
+              convert(GenerateKey(AuthorizationSetBuilder()
+                                          .Authorization(TAG_NO_AUTH_REQUIRED)
+                                          .EcdsaSigningKey(256)
+                                          .Digest(Digest::SHA_2_256)
+                                          .Authorization(TAG_CREATION_DATETIME, 1))));
+
+    hidl_vec<hidl_vec<uint8_t>> cert_chain;
+    HidlBuf challenge("challenge");
+    HidlBuf app_id("foo");
+    EXPECT_EQ(ErrorCode::OK,
+              convert(AttestKey(AuthorizationSetBuilder()
+                                        .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+                                        .Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
+                                        .Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id),
+                                &cert_chain)));
+
+    EXPECT_EQ(1U, cert_chain.size());
+    auto [err, attestation] = parse_attestation_record(cert_chain[0]);
+    EXPECT_EQ(ErrorCode::OK, err);
+
+    check_attestation_record(attestation, challenge,
+                             /* sw_enforced */
+                             AuthorizationSetBuilder()
+                                     .Authorization(TAG_CREATION_DATETIME, 1)
+                                     .Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id),
+                             /* hw_enforced */
+                             AuthorizationSetBuilder()
+                                     .Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
+                                     .Authorization(TAG_NO_AUTH_REQUIRED)
+                                     .EcdsaSigningKey(256)
+                                     .Digest(Digest::SHA_2_256)
+                                     .Authorization(TAG_EC_CURVE, EcCurve::P_256)
+                                     .Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
+                                     .Authorization(TAG_OS_VERSION, os_version())
+                                     .Authorization(TAG_OS_PATCHLEVEL, os_patch_level()),
+                             SecLevel());
+}
+
+INSTANTIATE_KEYMASTER_4_1_HIDL_TEST(DeviceUniqueAttestationTest);
+
+}  // namespace test
+}  // namespace android::hardware::keymaster::V4_1
diff --git a/keymaster/4.1/vts/functional/EarlyBootKeyTest.cpp b/keymaster/4.1/vts/functional/EarlyBootKeyTest.cpp
index 4a19010..a26c688 100644
--- a/keymaster/4.1/vts/functional/EarlyBootKeyTest.cpp
+++ b/keymaster/4.1/vts/functional/EarlyBootKeyTest.cpp
@@ -14,8 +14,78 @@
  * limitations under the License.
  */
 
+#include "Keymaster4_1HidlTest.h"
+
+#include <keymasterV4_1/authorization_set.h>
+
 namespace android::hardware::keymaster::V4_1::test {
 
-// TODO(swillden): Put tests here.
+using std::string;
+
+using EarlyBootKeyTest = Keymaster4_1HidlTest;
+
+// Because VTS tests are run on fully-booted machines, we can only run negative tests for early boot
+// keys, which cannot be created or used after /data is mounted.  This is the only test we can run
+// in the normal case.  The positive test will have to be done by the Android system, when it
+// creates/uses early boot keys during boot.  It should fail to boot if the early boot key usage
+// fails.
+TEST_P(EarlyBootKeyTest, CannotCreateEarlyBootKeys) {
+    auto [aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData] =
+            CreateTestKeys(TAG_EARLY_BOOT_ONLY, ErrorCode::EARLY_BOOT_ENDED);
+
+    CheckedDeleteKeyData(&aesKeyData);
+    CheckedDeleteKeyData(&hmacKeyData);
+    CheckedDeleteKeyData(&rsaKeyData);
+    CheckedDeleteKeyData(&ecdsaKeyData);
+}
+
+// This is a more comprenhensive test, but it can only be run on a machine which is still in early
+// boot stage, which no proper Android device is by the time we can run VTS.  To use this,
+// un-disable it and modify vold to remove the call to earlyBootEnded().  Running the test will end
+// early boot, so you'll have to reboot between runs.
+TEST_P(EarlyBootKeyTest, DISABLED_FullTest) {
+    // Should be able to create keys, since early boot has not ended
+    auto [aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData] =
+            CreateTestKeys(TAG_EARLY_BOOT_ONLY, ErrorCode::OK);
+
+    // TAG_EARLY_BOOT_ONLY should be in hw-enforced.
+    EXPECT_TRUE(contains(aesKeyData.characteristics.hardwareEnforced, TAG_EARLY_BOOT_ONLY));
+    EXPECT_TRUE(contains(hmacKeyData.characteristics.hardwareEnforced, TAG_EARLY_BOOT_ONLY));
+    EXPECT_TRUE(contains(rsaKeyData.characteristics.hardwareEnforced, TAG_EARLY_BOOT_ONLY));
+    EXPECT_TRUE(contains(ecdsaKeyData.characteristics.hardwareEnforced, TAG_EARLY_BOOT_ONLY));
+
+    // Should be able to use keys, since early boot has not ended
+    EXPECT_EQ(ErrorCode::OK, UseAesKey(aesKeyData.blob));
+    EXPECT_EQ(ErrorCode::OK, UseHmacKey(hmacKeyData.blob));
+    EXPECT_EQ(ErrorCode::OK, UseRsaKey(rsaKeyData.blob));
+    EXPECT_EQ(ErrorCode::OK, UseEcdsaKey(ecdsaKeyData.blob));
+
+    // End early boot
+    Return<ErrorCode> earlyBootResult = keymaster().earlyBootEnded();
+    EXPECT_TRUE(earlyBootResult.isOk());
+    EXPECT_EQ(earlyBootResult, ErrorCode::OK);
+
+    // Should not be able to use already-created keys.
+    EXPECT_EQ(ErrorCode::EARLY_BOOT_ENDED, UseAesKey(aesKeyData.blob));
+    EXPECT_EQ(ErrorCode::EARLY_BOOT_ENDED, UseHmacKey(hmacKeyData.blob));
+    EXPECT_EQ(ErrorCode::EARLY_BOOT_ENDED, UseRsaKey(rsaKeyData.blob));
+    EXPECT_EQ(ErrorCode::EARLY_BOOT_ENDED, UseEcdsaKey(ecdsaKeyData.blob));
+
+    CheckedDeleteKeyData(&aesKeyData);
+    CheckedDeleteKeyData(&hmacKeyData);
+    CheckedDeleteKeyData(&rsaKeyData);
+    CheckedDeleteKeyData(&ecdsaKeyData);
+
+    // Should not be able to create new keys
+    std::tie(aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData) =
+            CreateTestKeys(TAG_EARLY_BOOT_ONLY, ErrorCode::EARLY_BOOT_ENDED);
+
+    CheckedDeleteKeyData(&aesKeyData);
+    CheckedDeleteKeyData(&hmacKeyData);
+    CheckedDeleteKeyData(&rsaKeyData);
+    CheckedDeleteKeyData(&ecdsaKeyData);
+}
+
+INSTANTIATE_KEYMASTER_4_1_HIDL_TEST(EarlyBootKeyTest);
 
 }  // namespace android::hardware::keymaster::V4_1::test
diff --git a/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.cpp b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.cpp
new file mode 100644
index 0000000..efedf28
--- /dev/null
+++ b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Keymaster4_1HidlTest.h"
+
+namespace android::hardware::keymaster::V4_1::test {
+
+using std::string;
+
+void Keymaster4_1HidlTest::SetUp() {
+    keymaster41_ = IKeymasterDevice::getService(GetParam());
+    InitializeKeymaster(keymaster41_);
+}
+
+auto Keymaster4_1HidlTest::ProcessMessage(const HidlBuf& key_blob, KeyPurpose operation,
+                                          const string& message, const AuthorizationSet& in_params)
+        -> std::tuple<ErrorCode, string, AuthorizationSet /* out_params */> {
+    AuthorizationSet begin_out_params;
+    V4_0::ErrorCode result = Begin(operation, key_blob, in_params, &begin_out_params, &op_handle_);
+    AuthorizationSet out_params(std::move(begin_out_params));
+    if (result != V4_0::ErrorCode::OK) {
+        return {convert(result), {}, out_params};
+    }
+
+    string output;
+    size_t consumed = 0;
+    AuthorizationSet update_params;
+    AuthorizationSet update_out_params;
+    result = Update(op_handle_, update_params, message, &update_out_params, &output, &consumed);
+    out_params.push_back(update_out_params);
+    if (result != V4_0::ErrorCode::OK) {
+        return {convert(result), output, out_params};
+    }
+
+    string unused;
+    AuthorizationSet finish_params;
+    AuthorizationSet finish_out_params;
+    result = Finish(op_handle_, finish_params, message.substr(consumed), unused, &finish_out_params,
+                    &output);
+    op_handle_ = V4_0::test::kOpHandleSentinel;
+    out_params.push_back(finish_out_params);
+
+    return {convert(result), output, out_params};
+}
+
+}  // namespace android::hardware::keymaster::V4_1::test
diff --git a/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h
new file mode 100644
index 0000000..6332c43
--- /dev/null
+++ b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/hardware/keymaster/4.1/IKeymasterDevice.h>
+
+#include <KeymasterHidlTest.h>
+#include <keymasterV4_1/authorization_set.h>
+
+namespace android::hardware::keymaster::V4_1::test {
+
+using V4_0::test::HidlBuf;
+
+class Keymaster4_1HidlTest : public V4_0::test::KeymasterHidlTest {
+  public:
+    using super = V4_0::test::KeymasterHidlTest;
+
+    ErrorCode convert(V4_0::ErrorCode error_code) { return static_cast<ErrorCode>(error_code); }
+
+    // These methods hide the base class versions.
+    void SetUp();
+    IKeymasterDevice& keymaster() { return *keymaster41_; };
+
+    struct KeyData {
+        HidlBuf blob;
+        KeyCharacteristics characteristics;
+    };
+
+    std::tuple<ErrorCode, KeyData> GenerateKeyData(const AuthorizationSet& keyDescription) {
+        KeyData keyData;
+        ErrorCode errorCode = convert(
+                super::GenerateKey(keyDescription, &keyData.blob, &keyData.characteristics));
+        return {errorCode, keyData};
+    }
+
+    void CheckedDeleteKeyData(KeyData* keyData) { CheckedDeleteKey(&keyData->blob); }
+
+    template <typename TagType>
+    std::tuple<KeyData /* aesKey */, KeyData /* hmacKey */, KeyData /* rsaKey */,
+               KeyData /* ecdsaKey */>
+    CreateTestKeys(TagType tagToTest, ErrorCode expectedReturn) {
+        ErrorCode errorCode;
+
+        /* AES */
+        KeyData aesKeyData;
+        std::tie(errorCode, aesKeyData) =
+                GenerateKeyData(AuthorizationSetBuilder()
+                                        .AesEncryptionKey(128)
+                                        .Authorization(tagToTest)
+                                        .BlockMode(BlockMode::ECB)
+                                        .Padding(PaddingMode::NONE)
+                                        .Authorization(TAG_NO_AUTH_REQUIRED));
+        EXPECT_EQ(expectedReturn, errorCode);
+
+        /* HMAC */
+        KeyData hmacKeyData;
+        std::tie(errorCode, hmacKeyData) =
+                GenerateKeyData(AuthorizationSetBuilder()
+                                        .HmacKey(128)
+                                        .Authorization(tagToTest)
+                                        .Digest(Digest::SHA_2_256)
+                                        .Authorization(TAG_MIN_MAC_LENGTH, 128)
+                                        .Authorization(TAG_NO_AUTH_REQUIRED));
+        EXPECT_EQ(expectedReturn, errorCode);
+
+        /* RSA */
+        KeyData rsaKeyData;
+        std::tie(errorCode, rsaKeyData) =
+                GenerateKeyData(AuthorizationSetBuilder()
+                                        .RsaSigningKey(2048, 65537)
+                                        .Authorization(tagToTest)
+                                        .Digest(Digest::NONE)
+                                        .Padding(PaddingMode::NONE)
+                                        .Authorization(TAG_NO_AUTH_REQUIRED));
+        EXPECT_EQ(expectedReturn, errorCode);
+
+        /* ECDSA */
+        KeyData ecdsaKeyData;
+        std::tie(errorCode, ecdsaKeyData) =
+                GenerateKeyData(AuthorizationSetBuilder()
+                                        .EcdsaSigningKey(256)
+                                        .Authorization(tagToTest)
+                                        .Digest(Digest::SHA_2_256)
+                                        .Authorization(TAG_NO_AUTH_REQUIRED));
+        EXPECT_EQ(expectedReturn, errorCode);
+
+        return {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData};
+    }
+
+    std::tuple<ErrorCode, std::string /* processedMessage */, AuthorizationSet /* out_params */>
+    ProcessMessage(const HidlBuf& key_blob, KeyPurpose operation, const std::string& message,
+                   const AuthorizationSet& in_params);
+
+    ErrorCode UseAesKey(const HidlBuf& aesKeyBlob) {
+        auto [result, ciphertext, out_params] = ProcessMessage(
+                aesKeyBlob, KeyPurpose::ENCRYPT, "1234567890123456",
+                AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE));
+        return result;
+    }
+
+    ErrorCode UseHmacKey(const HidlBuf& hmacKeyBlob) {
+        auto [result, mac, out_params] =
+                ProcessMessage(hmacKeyBlob, KeyPurpose::SIGN, "1234567890123456",
+                               AuthorizationSetBuilder().Authorization(TAG_MAC_LENGTH, 128));
+        return result;
+    }
+
+    ErrorCode UseRsaKey(const HidlBuf& rsaKeyBlob) {
+        std::string message(2048 / 8, 'a');
+        auto [result, signature, out_params] = ProcessMessage(
+                rsaKeyBlob, KeyPurpose::SIGN, message,
+                AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE));
+        return result;
+    }
+
+    ErrorCode UseEcdsaKey(const HidlBuf& ecdsaKeyBlob) {
+        auto [result, signature, out_params] =
+                ProcessMessage(ecdsaKeyBlob, KeyPurpose::SIGN, "a",
+                               AuthorizationSetBuilder().Digest(Digest::SHA_2_256));
+        return result;
+    }
+
+    static std::vector<std::string> build_params() {
+        auto params = android::hardware::getAllHalInstanceNames(IKeymasterDevice::descriptor);
+        return params;
+    }
+
+  private:
+    sp<IKeymasterDevice> keymaster41_;
+};
+
+template <typename TypedTag>
+bool contains(hidl_vec<KeyParameter>& set, TypedTag typedTag) {
+    return std::find_if(set.begin(), set.end(), [&](const KeyParameter& param) {
+               return param.tag == static_cast<V4_0::Tag>(typedTag);
+           }) != set.end();
+}
+
+#define INSTANTIATE_KEYMASTER_4_1_HIDL_TEST(name)                                     \
+    INSTANTIATE_TEST_SUITE_P(PerInstance, name,                                       \
+                             testing::ValuesIn(Keymaster4_1HidlTest::build_params()), \
+                             android::hardware::PrintInstanceNameToString)
+
+}  // namespace android::hardware::keymaster::V4_1::test
diff --git a/keymaster/4.1/vts/functional/UnlockedDeviceRequiredTest.cpp b/keymaster/4.1/vts/functional/UnlockedDeviceRequiredTest.cpp
new file mode 100644
index 0000000..671bbbf
--- /dev/null
+++ b/keymaster/4.1/vts/functional/UnlockedDeviceRequiredTest.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Keymaster4_1HidlTest.h"
+
+#include <keymasterV4_1/authorization_set.h>
+
+namespace android::hardware::keymaster::V4_1::test {
+
+using UnlockedDeviceRequiredTest = Keymaster4_1HidlTest;
+
+// This may be a problematic test.  It can't be run repeatedly without unlocking the device in
+// between runs... and on most test devices there are no enrolled credentials so it can't be
+// unlocked at all, meaning the only way to get the test to pass again on a properly-functioning
+// device is to reboot it.  For that reason, this is disabled by default.  It can be used as part of
+// a manual test process, which includes unlocking between runs, which is why it's included here.
+// Well, that and the fact that it's the only test we can do without also making calls into the
+// Gatekeeper HAL.  We haven't written any cross-HAL tests, and don't know what all of the
+// implications might be, so that may or may not be a solution.
+//
+// TODO(swillden): Use the Gatekeeper HAL to enroll some test credentials which we can verify to get
+// an unlock auth token.  If that works, enable the improved test.
+TEST_P(UnlockedDeviceRequiredTest, DISABLED_KeysBecomeUnusable) {
+    auto [aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData] =
+            CreateTestKeys(TAG_UNLOCKED_DEVICE_REQUIRED, ErrorCode::OK);
+
+    EXPECT_EQ(ErrorCode::OK, UseAesKey(aesKeyData.blob));
+    EXPECT_EQ(ErrorCode::OK, UseHmacKey(hmacKeyData.blob));
+    EXPECT_EQ(ErrorCode::OK, UseRsaKey(rsaKeyData.blob));
+    EXPECT_EQ(ErrorCode::OK, UseEcdsaKey(ecdsaKeyData.blob));
+
+    Return<ErrorCode> rc =
+            keymaster().deviceLocked(false /* passwordOnly */, {} /* verificationToken */);
+    ASSERT_TRUE(rc.isOk());
+    ASSERT_EQ(ErrorCode::OK, static_cast<ErrorCode>(rc));
+
+    EXPECT_EQ(ErrorCode::DEVICE_LOCKED, UseAesKey(aesKeyData.blob));
+    EXPECT_EQ(ErrorCode::DEVICE_LOCKED, UseHmacKey(hmacKeyData.blob));
+    EXPECT_EQ(ErrorCode::DEVICE_LOCKED, UseRsaKey(rsaKeyData.blob));
+    EXPECT_EQ(ErrorCode::DEVICE_LOCKED, UseEcdsaKey(ecdsaKeyData.blob));
+
+    CheckedDeleteKeyData(&aesKeyData);
+    CheckedDeleteKeyData(&hmacKeyData);
+    CheckedDeleteKeyData(&rsaKeyData);
+    CheckedDeleteKeyData(&ecdsaKeyData);
+}
+
+INSTANTIATE_KEYMASTER_4_1_HIDL_TEST(UnlockedDeviceRequiredTest);
+
+}  // namespace android::hardware::keymaster::V4_1::test
diff --git a/keymaster/aidl/Android.bp b/keymaster/aidl/Android.bp
new file mode 100644
index 0000000..a2d73ead
--- /dev/null
+++ b/keymaster/aidl/Android.bp
@@ -0,0 +1,18 @@
+aidl_interface {
+    name: "android.hardware.keymaster",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/keymaster/*.aidl",
+    ],
+    stability: "vintf",
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
diff --git a/keymaster/aidl/android/hardware/keymaster/HardwareAuthToken.aidl b/keymaster/aidl/android/hardware/keymaster/HardwareAuthToken.aidl
new file mode 100644
index 0000000..58602aa
--- /dev/null
+++ b/keymaster/aidl/android/hardware/keymaster/HardwareAuthToken.aidl
@@ -0,0 +1,89 @@
+/*
+ * 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.Timestamp;
+import android.hardware.keymaster.HardwareAuthenticatorType;
+
+/**
+ * HardwareAuthToken is used to prove successful user authentication, to unlock the use of a key.
+ *
+ * HardwareAuthTokens are produced by other secure environment applications, notably GateKeeper and
+ * Fingerprint, in response to successful user authentication events.  These tokens are passed to
+ * begin(), update(), and finish() to prove that authentication occurred.  See those methods for
+ * more details.  It is up to the caller to determine which of the generated auth tokens is
+ * appropriate for a given key operation.
+ */
+@VintfStability
+parcelable HardwareAuthToken {
+
+    /**
+     * challenge is a value that's used to enable authentication tokens to authorize specific
+     * events.  The primary use case for challenge is to authorize an IKeymasterDevice cryptographic
+     * operation, for keys that require authentication per operation. See begin() for details.
+     */
+    long challenge;
+
+    /**
+     *  userId is the a "secure" user ID.  It is not related to any Android user ID or UID, but is
+     *  created in the Gatekeeper application in the secure environment.
+     */
+    long userId;
+
+    /**
+     *  authenticatorId is the a "secure" user ID.  It is not related to any Android user ID or UID,
+     *  but is created in an authentication application in the secure environment, such as the
+     *  Fingerprint application.
+     */
+    long authenticatorId;  // Secure authenticator ID.
+
+    /**
+     * authenticatorType describes the type of authentication that took place, e.g. password or
+     * fingerprint.
+     */
+    HardwareAuthenticatorType authenticatorType;
+
+    /**
+     * timestamp indicates when the user authentication took place, in milliseconds since some
+     * starting point (generally the most recent device boot) which all of the applications within
+     * one secure environment must agree upon.  This timestamp is used to determine whether or not
+     * the authentication occurred recently enough to unlock a key (see Tag::AUTH_TIMEOUT).
+     */
+    Timestamp timestamp;
+
+    /**
+     * MACs are computed with a backward-compatible method, used by Keymaster 3.0, Gatekeeper 1.0
+     * and Fingerprint 1.0, as well as pre-treble HALs.
+     *
+     * The MAC is Constants::AUTH_TOKEN_MAC_LENGTH bytes in length and is computed as follows:
+     *
+     *     HMAC_SHA256(
+     *         H, 0 || challenge || user_id || authenticator_id || authenticator_type || timestamp)
+     *
+     * where ``||'' represents concatenation, the leading zero is a single byte, and all integers
+     * are represented as unsigned values, the full width of the type.  The challenge, userId and
+     * authenticatorId values are in machine order, but authenticatorType and timestamp are in
+     * network order (big-endian).  This odd construction is compatible with the hw_auth_token_t
+     * structure,
+     *
+     * Note that mac is a vec rather than an array, not because it's actually variable-length but
+     * because it could be empty.  As documented in the IKeymasterDevice::begin,
+     * IKeymasterDevice::update and IKeymasterDevice::finish doc comments, an empty mac indicates
+     * that this auth token is empty.
+     */
+    byte[] mac;
+}
diff --git a/keymaster/aidl/android/hardware/keymaster/HardwareAuthenticatorType.aidl b/keymaster/aidl/android/hardware/keymaster/HardwareAuthenticatorType.aidl
new file mode 100644
index 0000000..3141858
--- /dev/null
+++ b/keymaster/aidl/android/hardware/keymaster/HardwareAuthenticatorType.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;
+
+/**
+ * Hardware authentication type, used by HardwareAuthTokens to specify the mechanism used to
+ * authentiate the user, and in KeyCharacteristics to specify the allowable mechanisms for
+ * authenticating to activate a key.
+ */
+@VintfStability
+@Backing(type="int")
+enum HardwareAuthenticatorType {
+    NONE = 0,
+    PASSWORD = 1 << 0,
+    FINGERPRINT = 1 << 1,
+    // Additional entries must be powers of 2.
+    ANY = 0xFFFFFFFF,
+}
diff --git a/radio/config/1.3/IRadioConfigIndication.hal b/keymaster/aidl/android/hardware/keymaster/Timestamp.aidl
similarity index 66%
rename from radio/config/1.3/IRadioConfigIndication.hal
rename to keymaster/aidl/android/hardware/keymaster/Timestamp.aidl
index 9ef496c..4b2f108 100644
--- a/radio/config/1.3/IRadioConfigIndication.hal
+++ b/keymaster/aidl/android/hardware/keymaster/Timestamp.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * Copyright 2020 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,13 +14,9 @@
  * limitations under the License.
  */
 
-package android.hardware.radio.config@1.3;
+package android.hardware.keymaster;
 
-import @1.2::IRadioConfigIndication;
-
-/**
- * Interface declaring unsolicited radio config indications.
- */
-interface IRadioConfigIndication extends @1.2::IRadioConfigIndication {
-
-};
+@VintfStability
+parcelable Timestamp {
+    long milliSeconds;
+}
diff --git a/light/aidl/Android.bp b/light/aidl/Android.bp
new file mode 100644
index 0000000..916a857
--- /dev/null
+++ b/light/aidl/Android.bp
@@ -0,0 +1,18 @@
+aidl_interface {
+    name: "android.hardware.light",
+    vendor_available: true,
+    srcs: [
+        "android/hardware/light/*.aidl",
+    ],
+    stability: "vintf",
+    backend: {
+        java: {
+            platform_apis: true,
+        },
+        ndk: {
+            vndk: {
+                enabled: true,
+            },
+        },
+    },
+}
diff --git a/light/aidl/android/hardware/light/BrightnessMode.aidl b/light/aidl/android/hardware/light/BrightnessMode.aidl
new file mode 100644
index 0000000..bc29699
--- /dev/null
+++ b/light/aidl/android/hardware/light/BrightnessMode.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.light;
+
+@VintfStability
+enum BrightnessMode {
+    /**
+     * Light brightness is managed by a user setting.
+     */
+    USER = 0,
+
+    /**
+     * Light brightness is managed by a light sensor. This is typically used
+     * to control the display backlight, but not limited to it. HALs and
+     * hardware implementations are free to support sensor for other lights or
+     * none whatsoever.
+     */
+    SENSOR = 1,
+
+    /**
+     * Use a low-persistence mode for display backlights, where the pixel
+     * color transition times are lowered.
+     *
+     * When set, the device driver must switch to a mode optimized for low display
+     * persistence that is intended to be used when the device is being treated as a
+     * head mounted display (HMD). The actual display brightness in this mode is
+     * implementation dependent, and any value set for color in LightState may be
+     * overridden by the HAL implementation.
+     *
+     * For an optimal HMD viewing experience, the display must meet the following
+     * criteria in this mode:
+     * - Gray-to-Gray, White-to-Black, and Black-to-White switching time must be ≤ 3 ms.
+     * - The display must support low-persistence with ≤ 3.5 ms persistence.
+     *   Persistence is defined as the amount of time for which a pixel is
+     *   emitting light for a single frame.
+     * - Any "smart panel" or other frame buffering options that increase display
+     *   latency are disabled.
+     * - Display brightness is set so that the display is still visible to the user
+     *   under normal indoor lighting.
+     * - The display must update at 60 Hz at least, but higher refresh rates are
+     *   recommended for low latency.
+     *
+     */
+    LOW_PERSISTENCE = 2,
+}
diff --git a/light/aidl/android/hardware/light/FlashMode.aidl b/light/aidl/android/hardware/light/FlashMode.aidl
new file mode 100644
index 0000000..00c6b6a
--- /dev/null
+++ b/light/aidl/android/hardware/light/FlashMode.aidl
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.light;
+
+@VintfStability
+enum FlashMode {
+    /**
+     * Keep the light steady on or off.
+     */
+    NONE = 0,
+    /**
+     * Flash the light at specified rate, potentially using a software-based
+     * implementation.
+     */
+    TIMED = 1,
+    /**
+     * Flash the light using hardware flashing support. This may or may not
+     * support a user-defined flashing rate or other features.
+     */
+    HARDWARE = 2,
+}
diff --git a/light/aidl/android/hardware/light/HwLight.aidl b/light/aidl/android/hardware/light/HwLight.aidl
new file mode 100644
index 0000000..43fdb4b
--- /dev/null
+++ b/light/aidl/android/hardware/light/HwLight.aidl
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.light;
+
+import android.hardware.light.LightType;
+
+/**
+ * A description of a single light. Multiple lights can map to the same physical
+ * LED. Separate physical LEDs are always represented by separate instances.
+ */
+@VintfStability
+parcelable HwLight {
+    /**
+     * Integer ID used for controlling this light
+     */
+    int id;
+
+    /**
+     * For a group of lights of the same logical type, sorting by ordinal should
+     * be give their physical order. No other meaning is carried by it.
+     */
+    int ordinal;
+
+    /**
+     * Logical type use of this light.
+     */
+    LightType type;
+}
diff --git a/light/aidl/android/hardware/light/HwLightState.aidl b/light/aidl/android/hardware/light/HwLightState.aidl
new file mode 100644
index 0000000..24d3250
--- /dev/null
+++ b/light/aidl/android/hardware/light/HwLightState.aidl
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.light;
+
+import android.hardware.light.BrightnessMode;
+import android.hardware.light.FlashMode;
+
+/**
+ * The parameters that can be set for a given light.
+ *
+ * Not all lights must support all parameters. If you
+ * can do something backward-compatible, do it.
+ */
+@VintfStability
+parcelable HwLightState {
+    /**
+     * The color of the LED in ARGB.
+     *
+     * The implementation of this in the HAL and hardware is a best-effort one.
+     *   - If a light can only do red or green and blue is requested, green
+     *     should be shown.
+     *   - If only a brightness ramp is supported, then this formula applies:
+     *      unsigned char brightness = ((77*((color>>16)&0x00ff))
+     *              + (150*((color>>8)&0x00ff)) + (29*(color&0x00ff))) >> 8;
+     *   - If only on and off are supported, 0 is off, anything else is on.
+     *
+     * The high byte should be ignored. Callers should set it to 0xff (which
+     * would correspond to 255 alpha).
+     */
+    int color;
+
+    /**
+     * To flash the light at a given rate, set flashMode to FLASH_TIMED.
+     */
+    FlashMode flashMode;
+
+    /**
+     * flashOnMs should be set to the number of milliseconds to turn the
+     * light on, before it's turned off.
+     */
+    int flashOnMs;
+
+    /**
+     * flashOfMs should be set to the number of milliseconds to turn the
+     * light off, before it's turned back on.
+     */
+    int flashOffMs;
+
+    BrightnessMode brightnessMode;
+}
diff --git a/light/aidl/android/hardware/light/ILights.aidl b/light/aidl/android/hardware/light/ILights.aidl
new file mode 100644
index 0000000..2253f73
--- /dev/null
+++ b/light/aidl/android/hardware/light/ILights.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.light;
+
+import android.hardware.light.HwLightState;
+import android.hardware.light.HwLight;
+
+/**
+ * Allows controlling logical lights/indicators, mapped to LEDs in a
+ * hardware-specific manner by the HAL implementation.
+ */
+@VintfStability
+interface ILights {
+    /**
+     * Set light identified by id to the provided state.
+     *
+     * If control over an invalid light is requested, this method exists with
+     * EX_UNSUPPORTED_OPERATION. Control over supported lights is done on a
+     * device-specific best-effort basis and unsupported sub-features will not
+     * be reported.
+     *
+     * @param id ID of logical light to set as returned by getLights()
+     * @param state describes what the light should look like.
+     */
+    void setLightState(in int id, in HwLightState state);
+
+    /**
+     * Discover what lights are supported by the HAL implementation.
+     *
+     * @return List of available lights
+     */
+    HwLight[] getLights();
+}
diff --git a/light/aidl/android/hardware/light/LightType.aidl b/light/aidl/android/hardware/light/LightType.aidl
new file mode 100644
index 0000000..9a7f656
--- /dev/null
+++ b/light/aidl/android/hardware/light/LightType.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.light;
+
+/**
+ * These light IDs correspond to logical lights, not physical.
+ * So for example, if your INDICATOR light is in line with your
+ * BUTTONS, it might make sense to also light the INDICATOR
+ * light to a reasonable color when the BUTTONS are lit.
+ */
+@VintfStability
+enum LightType {
+    BACKLIGHT = 0,
+    KEYBOARD = 1,
+    BUTTONS = 2,
+    BATTERY = 3,
+    NOTIFICATIONS = 4,
+    ATTENTION = 5,
+    BLUETOOTH = 6,
+    WIFI = 7,
+    MICROPHONE = 8,
+}
diff --git a/light/aidl/default/Android.bp b/light/aidl/default/Android.bp
new file mode 100644
index 0000000..ae3f463
--- /dev/null
+++ b/light/aidl/default/Android.bp
@@ -0,0 +1,16 @@
+cc_binary {
+    name: "android.hardware.lights-service.example",
+    relative_install_path: "hw",
+    init_rc: ["lights-default.rc"],
+    vintf_fragments: ["lights-default.xml"],
+    vendor: true,
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "android.hardware.light-ndk_platform",
+    ],
+    srcs: [
+        "Lights.cpp",
+        "main.cpp",
+    ],
+}
diff --git a/light/aidl/default/Lights.cpp b/light/aidl/default/Lights.cpp
new file mode 100644
index 0000000..74747d5
--- /dev/null
+++ b/light/aidl/default/Lights.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Lights.h"
+
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace light {
+
+ndk::ScopedAStatus Lights::setLightState(int id, const HwLightState& state) {
+    LOG(INFO) << "Lights setting state for id=" << id << " to color " << std::hex << state.color;
+    return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+ndk::ScopedAStatus Lights::getLights(std::vector<HwLight>* /*lights*/) {
+    LOG(INFO) << "Lights reporting supported lights";
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace light
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/light/aidl/default/Lights.h b/light/aidl/default/Lights.h
new file mode 100644
index 0000000..8cba5a1
--- /dev/null
+++ b/light/aidl/default/Lights.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/light/BnLights.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace light {
+
+// Default implementation that reports no supported lights.
+class Lights : public BnLights {
+    ndk::ScopedAStatus setLightState(int id, const HwLightState& state) override;
+    ndk::ScopedAStatus getLights(std::vector<HwLight>* types) override;
+};
+
+}  // namespace light
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/light/aidl/default/lights-default.rc b/light/aidl/default/lights-default.rc
new file mode 100644
index 0000000..687ec97
--- /dev/null
+++ b/light/aidl/default/lights-default.rc
@@ -0,0 +1,5 @@
+service vendor.light-default /vendor/bin/hw/android.hardware.lights-service.example
+    class hal
+    user nobody
+    group nobody
+    shutdown critical
diff --git a/light/aidl/default/lights-default.xml b/light/aidl/default/lights-default.xml
new file mode 100644
index 0000000..db604d6
--- /dev/null
+++ b/light/aidl/default/lights-default.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.light</name>
+        <fqname>ILights/default</fqname>
+    </hal>
+</manifest>
diff --git a/light/aidl/default/main.cpp b/light/aidl/default/main.cpp
new file mode 100644
index 0000000..a860bf4
--- /dev/null
+++ b/light/aidl/default/main.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Lights.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using ::aidl::android::hardware::light::Lights;
+
+int main() {
+    ABinderProcess_setThreadPoolMaxThreadCount(0);
+    std::shared_ptr<Lights> lights = ndk::SharedRefBase::make<Lights>();
+
+    const std::string instance = std::string() + Lights::descriptor + "/default";
+    binder_status_t status = AServiceManager_addService(lights->asBinder().get(), instance.c_str());
+    CHECK(status == STATUS_OK);
+
+    ABinderProcess_joinThreadPool();
+    return EXIT_FAILURE;  // should not reached
+}
diff --git a/identity/1.0/vts/functional/Android.bp b/light/aidl/vts/functional/Android.bp
similarity index 63%
rename from identity/1.0/vts/functional/Android.bp
rename to light/aidl/vts/functional/Android.bp
index 03b49de..3dd8cf6 100644
--- a/identity/1.0/vts/functional/Android.bp
+++ b/light/aidl/vts/functional/Android.bp
@@ -1,5 +1,5 @@
 //
-// Copyright (C) 2019 The Android Open Source Project
+// Copyright (C) 2020 The Android Open Source Project
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -15,22 +15,21 @@
 //
 
 cc_test {
-    name: "VtsHalIdentityCredentialTargetTest",
-    defaults: ["VtsHalTargetTestDefaults"],
-    srcs: [
-        "VtsHalIdentityCredentialTargetTest.cpp",
+    name: "VtsHalLightTargetTest",
+    defaults: [
+        "VtsHalTargetTestDefaults",
+        "use_libaidlvintf_gtest_helper_static",
     ],
-    static_libs: [
-        "android.hardware.identity@1.0",
-        "android.hardware.identity-support-lib",
-        "android.hardware.keymaster@4.0",
-        "libcppbor",
+    srcs: [
+        "VtsHalLightTargetTest.cpp",
     ],
     shared_libs: [
-        "libcrypto",
+        "libbinder",
+    ],
+    static_libs: [
+        "android.hardware.light-cpp",
     ],
     test_suites: [
-        "general-tests",
         "vts-core",
     ],
 }
diff --git a/light/aidl/vts/functional/VtsHalLightTargetTest.cpp b/light/aidl/vts/functional/VtsHalLightTargetTest.cpp
new file mode 100644
index 0000000..3c26278
--- /dev/null
+++ b/light/aidl/vts/functional/VtsHalLightTargetTest.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "light_aidl_hal_test"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+
+#include <android-base/logging.h>
+#include <android/hardware/light/ILights.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include <unistd.h>
+#include <set>
+
+using android::ProcessState;
+using android::sp;
+using android::String16;
+using android::binder::Status;
+using android::hardware::hidl_vec;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::light::BrightnessMode;
+using android::hardware::light::FlashMode;
+using android::hardware::light::HwLight;
+using android::hardware::light::HwLightState;
+using android::hardware::light::ILights;
+using android::hardware::light::LightType;
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+#define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
+
+const std::set<LightType> kAllTypes{android::enum_range<LightType>().begin(),
+                                    android::enum_range<LightType>().end()};
+
+class LightsAidl : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        lights = android::waitForDeclaredService<ILights>(String16(GetParam().c_str()));
+        ASSERT_NE(lights, nullptr);
+        ASSERT_TRUE(lights->getLights(&supportedLights).isOk());
+    }
+
+    sp<ILights> lights;
+    std::vector<HwLight> supportedLights;
+
+    virtual void TearDown() override {
+        for (const HwLight& light : supportedLights) {
+            HwLightState off;
+            off.color = 0x00000000;
+            off.flashMode = FlashMode::NONE;
+            off.brightnessMode = BrightnessMode::USER;
+            EXPECT_TRUE(lights->setLightState(light.id, off).isOk());
+        }
+
+        // must leave the device in a useable condition
+        for (const HwLight& light : supportedLights) {
+            if (light.type == LightType::BACKLIGHT) {
+                HwLightState backlightOn;
+                backlightOn.color = 0xFFFFFFFF;
+                backlightOn.flashMode = FlashMode::TIMED;
+                backlightOn.brightnessMode = BrightnessMode::USER;
+                EXPECT_TRUE(lights->setLightState(light.id, backlightOn).isOk());
+            }
+        }
+    }
+};
+
+/**
+ * Ensure all reported lights actually work.
+ */
+TEST_P(LightsAidl, TestSupported) {
+    HwLightState whiteFlashing;
+    whiteFlashing.color = 0xFFFFFFFF;
+    whiteFlashing.flashMode = FlashMode::TIMED;
+    whiteFlashing.flashOnMs = 100;
+    whiteFlashing.flashOffMs = 50;
+    whiteFlashing.brightnessMode = BrightnessMode::USER;
+    for (const HwLight& light : supportedLights) {
+        EXPECT_TRUE(lights->setLightState(light.id, whiteFlashing).isOk());
+    }
+}
+
+/**
+ * Ensure all reported lights have one of the supported types.
+ */
+TEST_P(LightsAidl, TestSupportedLightTypes) {
+    for (const HwLight& light : supportedLights) {
+        EXPECT_TRUE(kAllTypes.find(light.type) != kAllTypes.end());
+    }
+}
+
+/**
+ * Ensure all lights have a unique id.
+ */
+TEST_P(LightsAidl, TestUniqueIds) {
+    std::set<int> ids;
+    for (const HwLight& light : supportedLights) {
+        EXPECT_TRUE(ids.find(light.id) == ids.end());
+        ids.insert(light.id);
+    }
+}
+
+/**
+ * Ensure all lights have a unique ordinal for a given type.
+ */
+TEST_P(LightsAidl, TestUniqueOrdinalsForType) {
+    std::map<int, std::set<int>> ordinalsByType;
+    for (const HwLight& light : supportedLights) {
+        auto& ordinals = ordinalsByType[(int)light.type];
+        EXPECT_TRUE(ordinals.find(light.ordinal) == ordinals.end());
+        ordinals.insert(light.ordinal);
+    }
+}
+
+/**
+ * Ensure EX_UNSUPPORTED_OPERATION is returned if LOW_PERSISTENCE is not supported.
+ */
+TEST_P(LightsAidl, TestLowPersistence) {
+    HwLightState lowPersistence;
+    lowPersistence.color = 0xFF123456;
+    lowPersistence.flashMode = FlashMode::TIMED;
+    lowPersistence.flashOnMs = 100;
+    lowPersistence.flashOffMs = 50;
+    lowPersistence.brightnessMode = BrightnessMode::LOW_PERSISTENCE;
+    for (const HwLight& light : supportedLights) {
+        Status status = lights->setLightState(light.id, lowPersistence);
+        EXPECT_TRUE(status.isOk() || Status::EX_UNSUPPORTED_OPERATION == status.exceptionCode());
+    }
+}
+
+/**
+ * Ensure EX_UNSUPPORTED_OPERATION is returns for an invalid light id.
+ */
+TEST_P(LightsAidl, TestInvalidLightIdUnsupported) {
+    int maxId = INT_MIN;
+    for (const HwLight& light : supportedLights) {
+        maxId = std::max(maxId, light.id);
+    }
+
+    Status status = lights->setLightState(maxId + 1, HwLightState());
+    EXPECT_TRUE(status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION);
+}
+
+INSTANTIATE_TEST_SUITE_P(Lights, LightsAidl,
+                         testing::ValuesIn(android::getAidlHalInstanceNames(ILights::descriptor)),
+                         android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+    ::testing::InitGoogleTest(&argc, argv);
+    ProcessState::self()->setThreadPoolMaxThreadCount(1);
+    ProcessState::self()->startThreadPool();
+    return RUN_ALL_TESTS();
+}
diff --git a/light/utils/Android.bp b/light/utils/Android.bp
index 4c287e4..e901129 100644
--- a/light/utils/Android.bp
+++ b/light/utils/Android.bp
@@ -23,7 +23,11 @@
     shared_libs: [
         "android.hardware.light@2.0",
         "libbase",
+        "libbinder",
         "libhidlbase",
         "libutils",
     ],
+    static_libs: [
+        "android.hardware.light-cpp",
+    ],
 }
diff --git a/light/utils/main.cpp b/light/utils/main.cpp
index b834132..b9b6489 100644
--- a/light/utils/main.cpp
+++ b/light/utils/main.cpp
@@ -19,34 +19,23 @@
 
 #include <android-base/logging.h>
 #include <android/hardware/light/2.0/ILight.h>
+#include <android/hardware/light/ILights.h>
+#include <binder/IServiceManager.h>
+
+using android::sp;
+using android::waitForVintfService;
+using android::binder::Status;
+using android::hardware::hidl_vec;
+
+namespace V2_0 = android::hardware::light::V2_0;
+namespace aidl = android::hardware::light;
 
 void error(const std::string& msg) {
     LOG(ERROR) << msg;
     std::cerr << msg << std::endl;
 }
 
-int main(int argc, char* argv[]) {
-    using ::android::hardware::hidl_vec;
-    using ::android::hardware::light::V2_0::Brightness;
-    using ::android::hardware::light::V2_0::Flash;
-    using ::android::hardware::light::V2_0::ILight;
-    using ::android::hardware::light::V2_0::LightState;
-    using ::android::hardware::light::V2_0::Status;
-    using ::android::hardware::light::V2_0::Type;
-    using ::android::sp;
-
-    sp<ILight> service = ILight::getService();
-    if (service == nullptr) {
-        error("Could not retrieve light service.");
-        return -1;
-    }
-
-    static LightState off = {
-            .color = 0u,
-            .flashMode = Flash::NONE,
-            .brightnessMode = Brightness::USER,
-    };
-
+int parseArgs(int argc, char* argv[], unsigned int* color) {
     if (argc > 2) {
         error("Usage: blank_screen [color]");
         return -1;
@@ -54,25 +43,78 @@
 
     if (argc > 1) {
         char* col_ptr;
-        unsigned int col_new;
 
-        col_new = strtoul(argv[1], &col_ptr, 0);
+        *color = strtoul(argv[1], &col_ptr, 0);
         if (*col_ptr != '\0') {
             error("Failed to convert " + std::string(argv[1]) + " to number");
             return -1;
         }
-        off.color = col_new;
+
+        return 0;
     }
 
-    service->getSupportedTypes([&](const hidl_vec<Type>& types) {
-        for (Type type : types) {
-            Status ret = service->setLight(type, off);
-            if (ret != Status::SUCCESS) {
-                error("Failed to shut off screen for type " +
+    *color = 0u;
+    return 0;
+}
+
+void setToColorAidl(sp<aidl::ILights> hal, unsigned int color) {
+    static aidl::HwLightState off;
+    off.color = color;
+    off.flashMode = aidl::FlashMode::NONE;
+    off.brightnessMode = aidl::BrightnessMode::USER;
+
+    std::vector<aidl::HwLight> lights;
+    Status status = hal->getLights(&lights);
+    if (!status.isOk()) {
+        error("Failed to list lights");
+        return;
+    }
+
+    for (auto light : lights) {
+        Status setStatus = hal->setLightState(light.id, off);
+        if (!setStatus.isOk()) {
+            error("Failed to shut off light id " + std::to_string(light.id));
+        }
+    }
+}
+
+void setToColorHidl(sp<V2_0::ILight> hal, unsigned int color) {
+    static V2_0::LightState off = {
+            .color = color,
+            .flashMode = V2_0::Flash::NONE,
+            .brightnessMode = V2_0::Brightness::USER,
+    };
+
+    hal->getSupportedTypes([&](const hidl_vec<V2_0::Type>& types) {
+        for (auto type : types) {
+            V2_0::Status ret = hal->setLight(type, off);
+            if (ret != V2_0::Status::SUCCESS) {
+                error("Failed to shut off light for type " +
                       std::to_string(static_cast<int>(type)));
             }
         }
     });
+}
 
-    return 0;
+int main(int argc, char* argv[]) {
+    unsigned int inputColor;
+    int result = parseArgs(argc, argv, &inputColor);
+    if (result != 0) {
+        return result;
+    }
+
+    auto aidlHal = waitForVintfService<aidl::ILights>();
+    if (aidlHal != nullptr) {
+        setToColorAidl(aidlHal, inputColor);
+        return 0;
+    }
+
+    sp<V2_0::ILight> hidlHal = V2_0::ILight::getService();
+    if (hidlHal != nullptr) {
+        setToColorHidl(hidlHal, inputColor);
+        return 0;
+    }
+
+    error("Could not retrieve light service.");
+    return -1;
 }
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index ba9fb45..03af671 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -14,13 +14,30 @@
 // limitations under the License.
 //
 
+cc_defaults {
+    name: "neuralnetworks_vts_functional_defaults",
+    defaults: ["VtsHalTargetTestDefaults"],
+    arch: {
+        x86: {
+            cflags: [ "-D_Float16=__fp16",
+                      "-Xclang", "-fnative-half-type",
+                      "-Xclang", "-fallow-half-arguments-and-returns" ],
+        },
+        x86_64: {
+            cflags: [ "-D_Float16=__fp16",
+                      "-Xclang", "-fnative-half-type",
+                      "-Xclang", "-fallow-half-arguments-and-returns" ],
+        },
+    },
+}
+
 cc_library_static {
     name: "VtsHalNeuralNetworksV1_0_utils",
     srcs: [
         "Callbacks.cpp",
         "Utils.cpp",
     ],
-    defaults: ["VtsHalTargetTestDefaults"],
+    defaults: ["neuralnetworks_vts_functional_defaults"],
     export_include_dirs: ["include"],
     shared_libs: [
         "libfmq",
@@ -42,7 +59,7 @@
 
 cc_test {
     name: "VtsHalNeuralnetworksV1_0TargetTest",
-    defaults: ["VtsHalTargetTestDefaults"],
+    defaults: ["neuralnetworks_vts_functional_defaults"],
     srcs: [
         "BasicTests.cpp",
         "TestAssertions.cpp",
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index 595ad85..e28605d 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -42,10 +42,11 @@
 
 Model createModel(const TestModel& testModel) {
     // Model operands.
-    hidl_vec<Operand> operands(testModel.operands.size());
+    CHECK_EQ(testModel.referenced.size(), 0u);  // Not supported in 1.0.
+    hidl_vec<Operand> operands(testModel.main.operands.size());
     size_t constCopySize = 0, constRefSize = 0;
-    for (uint32_t i = 0; i < testModel.operands.size(); i++) {
-        const auto& op = testModel.operands[i];
+    for (uint32_t i = 0; i < testModel.main.operands.size(); i++) {
+        const auto& op = testModel.main.operands[i];
 
         DataLocation loc = {};
         if (op.lifetime == TestOperandLifeTime::CONSTANT_COPY) {
@@ -70,9 +71,9 @@
     }
 
     // Model operations.
-    hidl_vec<Operation> operations(testModel.operations.size());
-    std::transform(testModel.operations.begin(), testModel.operations.end(), operations.begin(),
-                   [](const TestOperation& op) -> Operation {
+    hidl_vec<Operation> operations(testModel.main.operations.size());
+    std::transform(testModel.main.operations.begin(), testModel.main.operations.end(),
+                   operations.begin(), [](const TestOperation& op) -> Operation {
                        return {.type = static_cast<OperationType>(op.type),
                                .inputs = op.inputs,
                                .outputs = op.outputs};
@@ -80,8 +81,8 @@
 
     // Constant copies.
     hidl_vec<uint8_t> operandValues(constCopySize);
-    for (uint32_t i = 0; i < testModel.operands.size(); i++) {
-        const auto& op = testModel.operands[i];
+    for (uint32_t i = 0; i < testModel.main.operands.size(); i++) {
+        const auto& op = testModel.main.operands[i];
         if (op.lifetime == TestOperandLifeTime::CONSTANT_COPY) {
             const uint8_t* begin = op.data.get<uint8_t>();
             const uint8_t* end = begin + op.data.size();
@@ -102,8 +103,8 @@
                 reinterpret_cast<uint8_t*>(static_cast<void*>(mappedMemory->getPointer()));
         CHECK(mappedPtr != nullptr);
 
-        for (uint32_t i = 0; i < testModel.operands.size(); i++) {
-            const auto& op = testModel.operands[i];
+        for (uint32_t i = 0; i < testModel.main.operands.size(); i++) {
+            const auto& op = testModel.main.operands[i];
             if (op.lifetime == TestOperandLifeTime::CONSTANT_REFERENCE) {
                 const uint8_t* begin = op.data.get<uint8_t>();
                 const uint8_t* end = begin + op.data.size();
@@ -114,8 +115,8 @@
 
     return {.operands = std::move(operands),
             .operations = std::move(operations),
-            .inputIndexes = testModel.inputIndexes,
-            .outputIndexes = testModel.outputIndexes,
+            .inputIndexes = testModel.main.inputIndexes,
+            .outputIndexes = testModel.main.outputIndexes,
             .operandValues = std::move(operandValues),
             .pools = std::move(pools)};
 }
diff --git a/neuralnetworks/1.0/vts/functional/Utils.cpp b/neuralnetworks/1.0/vts/functional/Utils.cpp
index 5b630fd..0dba85a 100644
--- a/neuralnetworks/1.0/vts/functional/Utils.cpp
+++ b/neuralnetworks/1.0/vts/functional/Utils.cpp
@@ -42,10 +42,10 @@
 
 Request createRequest(const TestModel& testModel) {
     // Model inputs.
-    hidl_vec<RequestArgument> inputs(testModel.inputIndexes.size());
+    hidl_vec<RequestArgument> inputs(testModel.main.inputIndexes.size());
     size_t inputSize = 0;
-    for (uint32_t i = 0; i < testModel.inputIndexes.size(); i++) {
-        const auto& op = testModel.operands[testModel.inputIndexes[i]];
+    for (uint32_t i = 0; i < testModel.main.inputIndexes.size(); i++) {
+        const auto& op = testModel.main.operands[testModel.main.inputIndexes[i]];
         if (op.data.size() == 0) {
             // Omitted input.
             inputs[i] = {.hasNoValue = true};
@@ -59,10 +59,10 @@
     }
 
     // Model outputs.
-    hidl_vec<RequestArgument> outputs(testModel.outputIndexes.size());
+    hidl_vec<RequestArgument> outputs(testModel.main.outputIndexes.size());
     size_t outputSize = 0;
-    for (uint32_t i = 0; i < testModel.outputIndexes.size(); i++) {
-        const auto& op = testModel.operands[testModel.outputIndexes[i]];
+    for (uint32_t i = 0; i < testModel.main.outputIndexes.size(); i++) {
+        const auto& op = testModel.main.operands[testModel.main.outputIndexes[i]];
 
         // In the case of zero-sized output, we should at least provide a one-byte buffer.
         // This is because zero-sized tensors are only supported internally to the driver, or
@@ -90,8 +90,8 @@
     CHECK(inputPtr != nullptr);
 
     // Copy input data to the memory pool.
-    for (uint32_t i = 0; i < testModel.inputIndexes.size(); i++) {
-        const auto& op = testModel.operands[testModel.inputIndexes[i]];
+    for (uint32_t i = 0; i < testModel.main.inputIndexes.size(); i++) {
+        const auto& op = testModel.main.operands[testModel.main.inputIndexes[i]];
         if (op.data.size() > 0) {
             const uint8_t* begin = op.data.get<uint8_t>();
             const uint8_t* end = begin + op.data.size();
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index 69e1761..9ba1925 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -16,7 +16,7 @@
 
 cc_test {
     name: "VtsHalNeuralnetworksV1_1TargetTest",
-    defaults: ["VtsHalTargetTestDefaults"],
+    defaults: ["neuralnetworks_vts_functional_defaults"],
     srcs: [
         "BasicTests.cpp",
         "TestAssertions.cpp",
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp
index 7a929d6..cee15a3 100644
--- a/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp
@@ -49,10 +49,11 @@
 
 Model createModel(const TestModel& testModel) {
     // Model operands.
-    hidl_vec<Operand> operands(testModel.operands.size());
+    CHECK_EQ(testModel.referenced.size(), 0u);  // Not supported in 1.1.
+    hidl_vec<Operand> operands(testModel.main.operands.size());
     size_t constCopySize = 0, constRefSize = 0;
-    for (uint32_t i = 0; i < testModel.operands.size(); i++) {
-        const auto& op = testModel.operands[i];
+    for (uint32_t i = 0; i < testModel.main.operands.size(); i++) {
+        const auto& op = testModel.main.operands[i];
 
         DataLocation loc = {};
         if (op.lifetime == TestOperandLifeTime::CONSTANT_COPY) {
@@ -77,9 +78,9 @@
     }
 
     // Model operations.
-    hidl_vec<Operation> operations(testModel.operations.size());
-    std::transform(testModel.operations.begin(), testModel.operations.end(), operations.begin(),
-                   [](const TestOperation& op) -> Operation {
+    hidl_vec<Operation> operations(testModel.main.operations.size());
+    std::transform(testModel.main.operations.begin(), testModel.main.operations.end(),
+                   operations.begin(), [](const TestOperation& op) -> Operation {
                        return {.type = static_cast<OperationType>(op.type),
                                .inputs = op.inputs,
                                .outputs = op.outputs};
@@ -87,8 +88,8 @@
 
     // Constant copies.
     hidl_vec<uint8_t> operandValues(constCopySize);
-    for (uint32_t i = 0; i < testModel.operands.size(); i++) {
-        const auto& op = testModel.operands[i];
+    for (uint32_t i = 0; i < testModel.main.operands.size(); i++) {
+        const auto& op = testModel.main.operands[i];
         if (op.lifetime == TestOperandLifeTime::CONSTANT_COPY) {
             const uint8_t* begin = op.data.get<uint8_t>();
             const uint8_t* end = begin + op.data.size();
@@ -109,8 +110,8 @@
                 reinterpret_cast<uint8_t*>(static_cast<void*>(mappedMemory->getPointer()));
         CHECK(mappedPtr != nullptr);
 
-        for (uint32_t i = 0; i < testModel.operands.size(); i++) {
-            const auto& op = testModel.operands[i];
+        for (uint32_t i = 0; i < testModel.main.operands.size(); i++) {
+            const auto& op = testModel.main.operands[i];
             if (op.lifetime == TestOperandLifeTime::CONSTANT_REFERENCE) {
                 const uint8_t* begin = op.data.get<uint8_t>();
                 const uint8_t* end = begin + op.data.size();
@@ -121,8 +122,8 @@
 
     return {.operands = std::move(operands),
             .operations = std::move(operations),
-            .inputIndexes = testModel.inputIndexes,
-            .outputIndexes = testModel.outputIndexes,
+            .inputIndexes = testModel.main.inputIndexes,
+            .outputIndexes = testModel.main.outputIndexes,
             .operandValues = std::move(operandValues),
             .pools = std::move(pools),
             .relaxComputationFloat32toFloat16 = testModel.isRelaxed};
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index e867120..f0fd769 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -2314,7 +2314,38 @@
     AXIS_ALIGNED_BBOX_TRANSFORM = 41,
 
     /**
-     * Performs a forward LSTM on the input followed by a backward LSTM.
+     * A recurrent neural network layer that applies an LSTM cell to a
+     * sequence of inputs in forward and backward directions.
+     *
+     * The op supports cross-linking via an auxiliary input. Regular cell feeds
+     * one input into the two RNN cells in the following way:
+     *
+     *       INPUT  (INPUT_REVERSED)
+     *         |         |
+     *    ---------------------
+     *    | FW_LSTM   BW_LSTM |
+     *    ---------------------
+     *         |         |
+     *      FW_OUT     BW_OUT
+     *
+     * An op with cross-linking takes two inputs and feeds them into the RNN
+     * cells in the following way:
+     *
+     *       AUX_INPUT   (AUX_INPUT_REVERSED)
+     *           |             |
+     *     INPUT | (INPUT_R'D.)|
+     *       |   |       |     |
+     *    -----------------------
+     *    |  \  /        \    / |
+     *    | FW_LSTM     BW_LSTM |
+     *    -----------------------
+     *         |           |
+     *      FW_OUT      BW_OUT
+     *
+     * The cross-linking mode is enabled iff auxiliary input and auxiliary
+     * weights are present. While stacking this op on top of itself, this
+     * allows to connect both forward and backward outputs from previous cell
+     * to the next cell's input.
      *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT16}
@@ -2324,7 +2355,6 @@
      *
      * All input and output tensors must be of the same type.
      *
-     *
      * Inputs:
      * * 0: The input.
      *      A 3-D tensor of shape:
@@ -2533,8 +2563,8 @@
      * * “activation” is the function passed as the “fused_activation_function”
      *   argument (if not “NONE”).
      *
-     * The op also supports an auxiliary input. Regular cell feeds one input
-     * into the two RNN cells in the following way:
+     * The op supports cross-linking via an auxiliary input. Regular cell feeds
+     * one input into the two RNN cells in the following way:
      *
      *       INPUT  (INPUT_REVERSED)
      *         |         |
@@ -2544,8 +2574,8 @@
      *         |         |
      *      FW_OUT     BW_OUT
      *
-     * An op with an auxiliary input takes two inputs and feeds them into the
-     * RNN cells in the following way:
+     * An op with cross-linking takes two inputs and feeds them into the RNN
+     * cells in the following way:
      *
      *       AUX_INPUT   (AUX_INPUT_REVERSED)
      *           |             |
@@ -2558,9 +2588,10 @@
      *         |           |
      *      FW_OUT      BW_OUT
      *
-     * While stacking this op on top of itself, this allows to connect both
-     * forward and backward outputs from previous cell to the next cell's
-     * inputs.
+     * The cross-linking mode is enabled iff auxiliary input and auxiliary
+     * weights are present. While stacking this op on top of itself, this
+     * allows to connect both forward and backward outputs from previous cell
+     * to the next cell's input.
      *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT16}
@@ -3165,7 +3196,7 @@
      * * 8: An {@link OperandType::INT32} scalar, specifying the stride when
      *      walking through input in the ‘height’ dimension.
      * * 9: An {@link OperandType::INT32} scalar, specifying the number of
-            groups.
+     *      groups.
      * * 10: An {@link OperandType::INT32} scalar, and has to be one of the
      *       {@link FusedActivationFunc} values. Specifies the activation to
      *       invoke on the result.
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index fc727b7..31a1a81 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -16,7 +16,7 @@
 
 cc_library_static {
     name: "VtsHalNeuralNetworksV1_2Callbacks",
-    defaults: ["VtsHalTargetTestDefaults"],
+    defaults: ["neuralnetworks_vts_functional_defaults"],
     export_include_dirs: ["include"],
     srcs: [
         "Callbacks.cpp",
@@ -33,7 +33,7 @@
 
 cc_test {
     name: "VtsHalNeuralnetworksV1_2TargetTest",
-    defaults: ["VtsHalTargetTestDefaults"],
+    defaults: ["neuralnetworks_vts_functional_defaults"],
     srcs: [
         "BasicTests.cpp",
         "CompilationCachingTests.cpp",
@@ -71,5 +71,5 @@
     header_libs: [
         "libneuralnetworks_headers",
     ],
-    test_suites: ["general-tests"],
+    test_suites: ["general-tests", "vts-core"],
 }
diff --git a/neuralnetworks/1.2/vts/functional/BasicTests.cpp b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
index 8e82c53..58d3c4a 100644
--- a/neuralnetworks/1.2/vts/functional/BasicTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
@@ -79,6 +79,18 @@
     EXPECT_TRUE(ret.isOk());
 }
 
+// device name test
+TEST_P(NeuralnetworksHidlTest, GetDeviceNameTest) {
+    const std::string deviceName = getName(GetParam());
+    auto pos = deviceName.find('-');
+    EXPECT_NE(pos, std::string::npos);
+    // The separator should not be the first or last character.
+    EXPECT_NE(pos, 0);
+    EXPECT_NE(pos, deviceName.length() - 1);
+    // There should only be 1 separator.
+    EXPECT_EQ(std::string::npos, deviceName.find('-', pos + 1));
+}
+
 // device supported extensions test
 TEST_P(NeuralnetworksHidlTest, GetDeviceSupportedExtensionsTest) {
     Return<void> ret = kDevice->getSupportedExtensions(
diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
index 2130a76..10dec79 100644
--- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
@@ -207,10 +207,10 @@
     };
 
     return {
-            .operands = std::move(operands),
-            .operations = std::move(operations),
-            .inputIndexes = {1},
-            .outputIndexes = {len * 2 + 1},
+            .main = {.operands = std::move(operands),
+                     .operations = std::move(operations),
+                     .inputIndexes = {1},
+                     .outputIndexes = {len * 2 + 1}},
             .isRelaxed = false,
     };
 }
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
index 599fd1d..4c8fede 100644
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
@@ -75,10 +75,11 @@
 
 Model createModel(const TestModel& testModel) {
     // Model operands.
-    hidl_vec<Operand> operands(testModel.operands.size());
+    CHECK_EQ(testModel.referenced.size(), 0u);  // Not supported in 1.1.
+    hidl_vec<Operand> operands(testModel.main.operands.size());
     size_t constCopySize = 0, constRefSize = 0;
-    for (uint32_t i = 0; i < testModel.operands.size(); i++) {
-        const auto& op = testModel.operands[i];
+    for (uint32_t i = 0; i < testModel.main.operands.size(); i++) {
+        const auto& op = testModel.main.operands[i];
 
         DataLocation loc = {};
         if (op.lifetime == TestOperandLifeTime::CONSTANT_COPY) {
@@ -110,9 +111,9 @@
     }
 
     // Model operations.
-    hidl_vec<Operation> operations(testModel.operations.size());
-    std::transform(testModel.operations.begin(), testModel.operations.end(), operations.begin(),
-                   [](const TestOperation& op) -> Operation {
+    hidl_vec<Operation> operations(testModel.main.operations.size());
+    std::transform(testModel.main.operations.begin(), testModel.main.operations.end(),
+                   operations.begin(), [](const TestOperation& op) -> Operation {
                        return {.type = static_cast<OperationType>(op.type),
                                .inputs = op.inputs,
                                .outputs = op.outputs};
@@ -120,8 +121,8 @@
 
     // Constant copies.
     hidl_vec<uint8_t> operandValues(constCopySize);
-    for (uint32_t i = 0; i < testModel.operands.size(); i++) {
-        const auto& op = testModel.operands[i];
+    for (uint32_t i = 0; i < testModel.main.operands.size(); i++) {
+        const auto& op = testModel.main.operands[i];
         if (op.lifetime == TestOperandLifeTime::CONSTANT_COPY) {
             const uint8_t* begin = op.data.get<uint8_t>();
             const uint8_t* end = begin + op.data.size();
@@ -142,8 +143,8 @@
                 reinterpret_cast<uint8_t*>(static_cast<void*>(mappedMemory->getPointer()));
         CHECK(mappedPtr != nullptr);
 
-        for (uint32_t i = 0; i < testModel.operands.size(); i++) {
-            const auto& op = testModel.operands[i];
+        for (uint32_t i = 0; i < testModel.main.operands.size(); i++) {
+            const auto& op = testModel.main.operands[i];
             if (op.lifetime == TestOperandLifeTime::CONSTANT_REFERENCE) {
                 const uint8_t* begin = op.data.get<uint8_t>();
                 const uint8_t* end = begin + op.data.size();
@@ -154,15 +155,15 @@
 
     return {.operands = std::move(operands),
             .operations = std::move(operations),
-            .inputIndexes = testModel.inputIndexes,
-            .outputIndexes = testModel.outputIndexes,
+            .inputIndexes = testModel.main.inputIndexes,
+            .outputIndexes = testModel.main.outputIndexes,
             .operandValues = std::move(operandValues),
             .pools = std::move(pools),
             .relaxComputationFloat32toFloat16 = testModel.isRelaxed};
 }
 
 static bool isOutputSizeGreaterThanOne(const TestModel& testModel, uint32_t index) {
-    const auto byteSize = testModel.operands[testModel.outputIndexes[index]].data.size();
+    const auto byteSize = testModel.main.operands[testModel.main.outputIndexes[index]].data.size();
     return byteSize > 1u;
 }
 
@@ -302,17 +303,17 @@
             // either empty, or have the same number of elements as the number of outputs.
             ASSERT_EQ(ErrorStatus::NONE, executionStatus);
             ASSERT_TRUE(outputShapes.size() == 0 ||
-                        outputShapes.size() == testModel.outputIndexes.size());
+                        outputShapes.size() == testModel.main.outputIndexes.size());
             break;
         case OutputType::UNSPECIFIED:
             // If the model output operands are not fully specified, outputShapes must have
             // the same number of elements as the number of outputs.
             ASSERT_EQ(ErrorStatus::NONE, executionStatus);
-            ASSERT_EQ(outputShapes.size(), testModel.outputIndexes.size());
+            ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
             break;
         case OutputType::INSUFFICIENT:
             ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
-            ASSERT_EQ(outputShapes.size(), testModel.outputIndexes.size());
+            ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
             ASSERT_FALSE(outputShapes[0].isSufficient);
             return;
     }
@@ -320,7 +321,7 @@
     // Go through all outputs, check returned output shapes.
     for (uint32_t i = 0; i < outputShapes.size(); i++) {
         EXPECT_TRUE(outputShapes[i].isSufficient);
-        const auto& expect = testModel.operands[testModel.outputIndexes[i]].dimensions;
+        const auto& expect = testModel.main.operands[testModel.main.outputIndexes[i]].dimensions;
         const std::vector<uint32_t> actual = outputShapes[i].dimensions;
         EXPECT_EQ(expect, actual);
     }
diff --git a/neuralnetworks/1.3/IDevice.hal b/neuralnetworks/1.3/IDevice.hal
index 610db79..79f9c32 100644
--- a/neuralnetworks/1.3/IDevice.hal
+++ b/neuralnetworks/1.3/IDevice.hal
@@ -260,11 +260,6 @@
      * the model, the callback object must be invoked with the appropriate
      * ErrorStatus value and nullptr for the IPreparedModel.
      *
-     * The model is prepared with a priority. This priority is relative to other
-     * prepared models owned by the same client. Higher priority executions may
-     * use more compute resources than lower priority executions, and may
-     * preempt or starve lower priority executions.
-     *
      * prepareModelFromCache_1_3 can be called with an optional deadline. If the
      * model is not able to prepared before the provided deadline, the model
      * preparation must be aborted, and either {@link
@@ -284,8 +279,6 @@
      * used with different shapes of inputs on different (possibly concurrent)
      * executions.
      *
-     * @param priority The priority of the prepared model relative to other
-     *     prepared models owned by the client.
      * @param deadline The time by which the model must be prepared. If the
      *     model cannot be prepared by the deadline, the preparation must be
      *     aborted.
@@ -318,7 +311,7 @@
      *       met
      *     - RESOURCE_EXHAUSTED_* if the task was aborted by the driver
      */
-    prepareModelFromCache_1_3(Priority priority, OptionalTimePoint deadline,
+    prepareModelFromCache_1_3(OptionalTimePoint deadline,
                               vec<handle> modelCache, vec<handle> dataCache,
                               uint8_t[Constant:BYTE_SIZE_OF_CACHE_TOKEN] token,
                               IPreparedModelCallback callback)
@@ -379,5 +372,5 @@
      */
     allocate(BufferDesc desc, vec<IPreparedModel> preparedModels, vec<BufferRole> inputRoles,
              vec<BufferRole> outputRoles)
-            generates (ErrorStatus status, IBuffer buffer, int32_t token);
+            generates (ErrorStatus status, IBuffer buffer, uint32_t token);
 };
diff --git a/neuralnetworks/1.3/IPreparedModel.hal b/neuralnetworks/1.3/IPreparedModel.hal
index d645de7..4ce3691 100644
--- a/neuralnetworks/1.3/IPreparedModel.hal
+++ b/neuralnetworks/1.3/IPreparedModel.hal
@@ -92,6 +92,17 @@
      * @param deadline The time by which the execution must complete. If the
      *                 execution cannot be finished by the deadline, the
      *                 execution must be aborted.
+     * @param loopTimeoutDuration The maximum amount of time that should be spent
+     *                            executing a {@link OperationType::WHILE}
+     *                            operation. If a loop condition model does not
+     *                            output false within this duration, the
+     *                            execution must be aborted. If the model
+     *                            contains a {@link OperationType::WHILE}
+     *                            operation and no loop timeout duration is
+     *                            provided, the maximum amount of time is {@link
+     *                            LoopTimeoutDurationNs::DEFAULT}. When
+     *                            provided, the duration must not exceed {@link
+     *                            LoopTimeoutDurationNs::MAXIMUM}.
      * @param callback A callback object used to return the error status of
      *                 the execution, shape information of model output operands, and
      *                 duration of execution. The callback object's notify function must
@@ -111,7 +122,7 @@
      *                  driver
      */
     execute_1_3(Request request, MeasureTiming measure, OptionalTimePoint deadline,
-                IExecutionCallback callback)
+                OptionalTimeoutDuration loopTimeoutDuration, IExecutionCallback callback)
         generates (ErrorStatus status);
 
     /**
@@ -163,6 +174,17 @@
      * @param deadline The time by which the execution must complete. If the
      *                 execution cannot be finished by the deadline, the
      *                 execution must be aborted.
+     * @param loopTimeoutDuration The maximum amount of time that should be spent
+     *                            executing a {@link OperationType::WHILE}
+     *                            operation. If a loop condition model does not
+     *                            output false within this duration, the
+     *                            execution must be aborted. If the model
+     *                            contains a {@link OperationType::WHILE}
+     *                            operation and no loop timeout duration is
+     *                            provided, the maximum amount of time is {@link
+     *                            LoopTimeoutDurationNs::DEFAULT}. When
+     *                            provided, the duration must not exceed {@link
+     *                            LoopTimeoutDurationNs::MAXIMUM}.
      * @return status Error status of the execution, must be:
      *                - NONE if execution is performed successfully
      *                - DEVICE_UNAVAILABLE if driver is offline or busy
@@ -187,7 +209,8 @@
      *                measurement is not available.
      */
     executeSynchronously_1_3(Request request, MeasureTiming measure,
-                             OptionalTimePoint deadline)
+                             OptionalTimePoint deadline,
+                             OptionalTimeoutDuration loopTimeoutDuration)
                   generates (ErrorStatus status, vec<OutputShape> outputShapes,
                              Timing timing);
 
@@ -243,6 +266,17 @@
      * @param deadline The time by which the execution must complete. If the
      *                 execution cannot be finished by the deadline, the
      *                 execution must be aborted.
+     * @param loopTimeoutDuration The maximum amount of time that should be spent
+     *                            executing a {@link OperationType::WHILE}
+     *                            operation. If a loop condition model does not
+     *                            output false within this duration, the
+     *                            execution must be aborted. If the model
+     *                            contains a {@link OperationType::WHILE}
+     *                            operation and no loop timeout duration is
+     *                            provided, the maximum amount of time is {@link
+     *                            LoopTimeoutDurationNs::DEFAULT}. When
+     *                            provided, the duration must not exceed {@link
+     *                            LoopTimeoutDurationNs::MAXIMUM}.
      * @param duration The length of time within which the execution must
      *                 complete after all sync fences in waitFor are signaled. If the
      *                 execution cannot be finished within the duration, the execution
@@ -264,6 +298,7 @@
      *                  and error status when the execution is completed.
      */
     executeFenced(Request request, vec<handle> waitFor, MeasureTiming measure,
-                  OptionalTimePoint deadline, OptionalTimeoutDuration duration)
+                  OptionalTimePoint deadline, OptionalTimeoutDuration loopTimeoutDuration,
+                  OptionalTimeoutDuration duration)
         generates (ErrorStatus status, handle syncFence, IFencedExecutionCallback callback);
 };
diff --git a/neuralnetworks/1.3/types.hal b/neuralnetworks/1.3/types.hal
index ed577e4..08d8e6b 100644
--- a/neuralnetworks/1.3/types.hal
+++ b/neuralnetworks/1.3/types.hal
@@ -22,9 +22,9 @@
 import @1.0::RequestArgument;
 import @1.2::Model.ExtensionNameAndPrefix;
 import @1.2::Model.ExtensionTypeEncoding;
+import @1.2::Operand.ExtraParams;
 import @1.2::OperandType;
 import @1.2::OperationType;
-import @1.2::SymmPerChannelQuantParams;
 
 import android.hidl.safe_union@1.0::Monostate;
 
@@ -2364,7 +2364,54 @@
     AXIS_ALIGNED_BBOX_TRANSFORM = @1.2::OperationType:AXIS_ALIGNED_BBOX_TRANSFORM,
 
     /**
-     * Performs a forward LSTM on the input followed by a backward LSTM.
+     * A recurrent neural network layer that applies an LSTM cell to a
+     * sequence of inputs in forward and backward directions.
+     *
+     * The op supports cross-linking via an auxiliary input. Regular cell feeds
+     * one input into the two RNN cells in the following way:
+     *
+     *       INPUT  (INPUT_REVERSED)
+     *         |         |
+     *    ---------------------
+     *    | FW_LSTM   BW_LSTM |
+     *    ---------------------
+     *         |         |
+     *      FW_OUT     BW_OUT
+     *
+     * An op with cross-linking takes two inputs and feeds them into the RNN
+     * cells in the following way:
+     *
+     *       AUX_INPUT   (AUX_INPUT_REVERSED)
+     *           |             |
+     *     INPUT | (INPUT_R'D.)|
+     *       |   |       |     |
+     *    -----------------------
+     *    |  \  /        \    / |
+     *    | FW_LSTM     BW_LSTM |
+     *    -----------------------
+     *         |           |
+     *      FW_OUT      BW_OUT
+     *
+     * The cross-linking mode is enabled iff auxiliary input and auxiliary
+     * weights are present. While stacking this op on top of itself, this
+     * allows to connect both forward and backward outputs from previous cell
+     * to the next cell's input.
+     *
+     * Since HAL version 1.3 parallel linking mode is supported. The mode is
+     * enabled if auxiliary input is present but auxiliary weights are omitted.
+     * In this case, the cell feeds inputs into the RNN in the following way:
+     *
+     *       INPUT (AUX_INPUT_REVERSED)
+     *         |         |
+     *    ---------------------
+     *    | FW_LSTM   BW_LSTM |
+     *    ---------------------
+     *         |         |
+     *      FW_OUT     BW_OUT
+     *
+     * While stacking this op on top of itself, this allows to connect both
+     * forward and backward outputs from previous cell to the next cell's
+     * corresponding inputs.
      *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT16}
@@ -2374,7 +2421,6 @@
      *
      * All input and output tensors must be of the same type.
      *
-     *
      * Inputs:
      * * 0: The input.
      *      A 3-D tensor of shape:
@@ -2466,25 +2512,34 @@
      * * 38: The backward input cell state.
      *       A 2-D tensor of shape [batch_size, bw_num_units].
      * * 39: The auxiliary input. Optional.
-     *       A 3-D tensor of shape [max_time, batch_size, input_size], where “batch_size”
-     *       corresponds to the batching dimension, and “input_size” is the size
-     *       of the input.
-     * * 40: The forward auxiliary input-to-input weights. Optional.
-     *       A 2-D tensor of shape [fw_num_units, input_size].
-     * * 41: The forward auxiliary input-to-forget weights. Optional.
-     *       A 2-D tensor of shape [fw_num_units, input_size].
-     * * 42: The forward auxiliary input-to-cell weights. Optional.
-     *       A 2-D tensor of shape [fw_num_units, input_size].
-     * * 43: The forward auxiliary input-to-output weights. Optional.
-     *       A 2-D tensor of shape [fw_num_units, input_size].
-     * * 44: The backward auxiliary input-to-input weights. Optional.
-     *       A 2-D tensor of shape [bw_num_units, input_size].
-     * * 45: The backward auxiliary input-to-forget weights. Optional.
-     *       A 2-D tensor of shape [bw_num_units, input_size].
-     * * 46: The backward auxiliary input-to-cell weights. Optional.
-     *       A 2-D tensor of shape [bw_num_units, input_size].
-     * * 47: The backward auxiliary input-to-output weights. Optional.
-     *       A 2-D tensor of shape [bw_num_units, input_size].
+     *       A 3-D tensor of shape [max_time, batch_size, aux_input_size],
+     *       where “batch_size” corresponds to the batching dimension, and
+     *       “aux_input_size” is the size of the auxiliary input. Optional. See
+     *       the docs above for the usage modes explanation.
+     * * 40: The forward auxiliary input-to-input weights.
+     *       Optional. See the docs above for the usage modes explanation.
+     *       A 2-D tensor of shape [fw_num_units, aux_input_size].
+     * * 41: The forward auxiliary input-to-forget weights.
+     *       Optional. See the docs above for the usage modes explanation.
+     *       A 2-D tensor of shape [fw_num_units, aux_input_size].
+     * * 42: The forward auxiliary input-to-cell weights.
+     *       Optional. See the docs above for the usage modes explanation.
+     *       A 2-D tensor of shape [fw_num_units, aux_input_size].
+     * * 43: The forward auxiliary input-to-output weights.
+     *       Optional. See the docs above for the usage modes explanation.
+     *       A 2-D tensor of shape [fw_num_units, aux_input_size].
+     * * 44: The backward auxiliary input-to-input weights.
+     *       Optional. See the docs above for the usage modes explanation.
+     *       A 2-D tensor of shape [bw_num_units, aux_input_size].
+     * * 45: The backward auxiliary input-to-forget weights.
+     *       Optional. See the docs above for the usage modes explanation.
+     *       A 2-D tensor of shape [bw_num_units, aux_input_size].
+     * * 46: The backward auxiliary input-to-cell weights.
+     *       Optional. See the docs above for the usage modes explanation.
+     *       A 2-D tensor of shape [bw_num_units, aux_input_size].
+     * * 47: The backward auxiliary input-to-output weights.
+     *       Optional. See the docs above for the usage modes explanation.
+     *       A 2-D tensor of shape [bw_num_units, aux_input_size].
      * * 48: The activation function.
      *       A value indicating the activation function:
      *       <ul>
@@ -2556,6 +2611,30 @@
      *      A 3-D tensor of shape:
      *        If time-major: [max_time, batch_size, bw_output_size]
      *        If batch-major: [batch_size, max_time, bw_output_size]
+     * * 2: The forward activation state output.
+     *      A 2-D tensor of shape [batch_size, fw_output_size] containing an
+     *      activation state from the last time step in the sequence. This
+     *      output is optional and can be omitted. If this output is present
+     *      then outputs 3-5 must be present as well.
+     *      Available since HAL version 1.3.
+     * * 3: The forward cell state output.
+     *      A tensor of shape [batch_size, fw_cell_size] containing a cell state
+     *      from the last time step in the sequence. This output is optional
+     *      and can be omitted. If this output is present
+     *      then outputs 2, 4, 5 must be present as well.
+     *      Available since HAL version 1.3.
+     * * 4: The backward activation state output.
+     *      A 2-D tensor of shape [batch_size, bw_output_size] containing an
+     *      activation state from the last time step in the sequence. This
+     *      output is optional and can be omitted. If this output is present
+     *      then outputs 2, 3, 5 must be present as well.
+     *      Available since HAL version 1.3.
+     * * 5: The backward cell state output.
+     *      A tensor of shape [batch_size, bw_cell_size] containing a cell state
+     *      from the last time step in the sequence. This output is optional
+     *      and can be omitted. If this output is present
+     *      then outputs 2-4 must be present as well.
+     *      Available since HAL version 1.3.
      */
     BIDIRECTIONAL_SEQUENCE_LSTM = @1.2::OperationType:BIDIRECTIONAL_SEQUENCE_LSTM,
 
@@ -2583,8 +2662,8 @@
      * * “activation” is the function passed as the “fused_activation_function”
      *   argument (if not “NONE”).
      *
-     * The op also supports an auxiliary input. Regular cell feeds one input
-     * into the two RNN cells in the following way:
+     * The op supports cross-linking via an auxiliary input. Regular cell feeds
+     * one input into the two RNN cells in the following way:
      *
      *       INPUT  (INPUT_REVERSED)
      *         |         |
@@ -2594,8 +2673,8 @@
      *         |         |
      *      FW_OUT     BW_OUT
      *
-     * An op with an auxiliary input takes two inputs and feeds them into the
-     * RNN cells in the following way:
+     * An op with cross-linking takes two inputs and feeds them into the RNN
+     * cells in the following way:
      *
      *       AUX_INPUT   (AUX_INPUT_REVERSED)
      *           |             |
@@ -2608,9 +2687,26 @@
      *         |           |
      *      FW_OUT      BW_OUT
      *
+     * The cross-linking mode is enabled iff auxiliary input and auxiliary
+     * weights are present. While stacking this op on top of itself, this
+     * allows to connect both forward and backward outputs from previous cell
+     * to the next cell's input.
+     *
+     * Since HAL version 1.3 parallel linking mode is supported. The mode is
+     * enabled if auxiliary input is present but auxiliary weights are omitted.
+     * In this case, the cell feeds inputs into the RNN in the following way:
+     *
+     *       INPUT (AUX_INPUT_REVERSED)
+     *         |         |
+     *    ---------------------
+     *    | FW_RNN     BW_RNN |
+     *    ---------------------
+     *         |         |
+     *      FW_OUT     BW_OUT
+     *
      * While stacking this op on top of itself, this allows to connect both
      * forward and backward outputs from previous cell to the next cell's
-     * inputs.
+     * corresponding inputs.
      *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT16}
@@ -2643,11 +2739,17 @@
      *      A 2-D tensor of shape [batchSize, bwNumUnits]. Specifies a hidden
      *      state input for the first time step of the computation.
      * * 9: auxInput.
-     *      A 3-D tensor. The shape is the same as of the input 0.
+     *      A 3-D tensor. The shape is defined by the input 6 (timeMajor). If
+     *      it is set to true, then the input has a shape [maxTime, batchSize,
+     *      auxInputSize], otherwise the input has a shape [batchSize, maxTime,
+     *      auxInputSize]. Can be omitted. See the docs above for the usage
+     *      modes explanation.
      * * 10:fwAuxWeights.
-     *      A 2-D tensor of shape [fwNumUnits, inputSize].
+     *      A 2-D tensor of shape [fwNumUnits, auxInputSize]. Can be omitted.
+     *      See the docs above for the usage modes explanation.
      * * 11:bwAuxWeights.
-     *      A 2-D tensor of shape [bwNumUnits, inputSize].
+     *      A 2-D tensor of shape [bwNumUnits, auxInputSize]. Can be omitted.
+     *      See the docs above for the usage modes explanation.
      * * 12:fusedActivationFunction.
      *      A {@link FusedActivationFunc} value indicating the activation function. If
      *      “NONE” is specified then it results in a linear activation.
@@ -2673,6 +2775,18 @@
      *      (timeMajor). If it is set to true, then the shape is set to
      *      [maxTime, batchSize, bwNumUnits], otherwise the shape is set to
      *      [batchSize, maxTime, bwNumUnits].
+     * * 2: The forward hidden state output.
+     *      A 2-D tensor of shape [batchSize, fwNumUnits] containing a hidden
+     *      state from the last time step in the sequence. This output is
+     *      optional and can be omitted. If this output is present then output
+     *      3 must be present as well.
+     *      Available since HAL version 1.3.
+     * * 3: The backward hidden state output.
+     *      A 2-D tensor of shape [batchSize, bwNumUnits] containing a hidden
+     *      state from the last time step in the sequence. This output is
+     *      optional and can be omitted. If this output is present then output
+     *      2 must be present as well.
+     *      Available since HAL version 1.3.
      */
     BIDIRECTIONAL_SEQUENCE_RNN = @1.2::OperationType:BIDIRECTIONAL_SEQUENCE_RNN,
 
@@ -3253,7 +3367,7 @@
      * * 8: An {@link OperandType::INT32} scalar, specifying the stride when
      *      walking through input in the ‘height’ dimension.
      * * 9: An {@link OperandType::INT32} scalar, specifying the number of
-            groups.
+     *      groups.
      * * 10: An {@link OperandType::INT32} scalar, and has to be one of the
      *       {@link FusedActivationFunc} values. Specifies the activation to
      *       invoke on the result.
@@ -4656,6 +4770,15 @@
      *      A 3-D tensor of shape:
      *        If time-major: [max_time, batch_size, output_size]
      *        If batch-major: [batch_size, max_time, output_size]
+     * * 1: A tensor of shape [batch_size, output_size] containing a hidden
+     *      state from the last time step in the sequence. This output is
+     *      optional and can be omitted. If this output is present then
+     *      output #2 must be present as well.
+     *      Available since HAL version 1.3.
+     * * 2: A tensor of shape [batch_size, cell_size] containing a cell state
+     *      from the last time step in the sequence. This output is optional
+     *      and can be omitted.
+     *      Available since HAL version 1.3.
      */
     UNIDIRECTIONAL_SEQUENCE_LSTM = @1.2::OperationType:UNIDIRECTIONAL_SEQUENCE_LSTM,
 
@@ -4711,6 +4834,10 @@
      *      it is set to 1, then the output has a shape [maxTime, batchSize,
      *      numUnits], otherwise the output has a shape [batchSize, maxTime,
      *      numUnits].
+     * * 1: A tensor of shape [batchSize, numUnits] containing hidden state
+     *      from the last time step in the sequence. This output is optional
+     *      and can be omitted.
+     *      Available since HAL version 1.3.
      */
     UNIDIRECTIONAL_SEQUENCE_RNN = @1.2::OperationType:UNIDIRECTIONAL_SEQUENCE_RNN,
 
@@ -5127,8 +5254,10 @@
 /**
  * The capabilities of a driver.
  *
- * Performance of an operation comes from the type of its first operand.
- * This represents performance for non extension operand types.
+ * This represents performance of non-extension operations.
+ *
+ * Performance of an operation other than {@link OperationType::IF} and
+ * {@link OperationType::WHILE} comes from the type of its first operand.
  */
 struct Capabilities {
     /**
@@ -5151,11 +5280,32 @@
 
     /**
      * Performance by operand type. Must be sorted by OperandType.
-     * If a particular OperandType is not present in operandPerformance,
+     *
+     * If a particular {@link OperandType} is not present in operandPerformance,
      * its performance is treated as
      * { .execTime = FLT_MAX, .powerUsage = FLT_MAX }.
+     *
+     * Performance does not apply to {@link OperandType::SUBGRAPH}, and a driver
+     * must not report operand performance for {@link OperandType::SUBGRAPH}.
      */
     vec<OperandPerformance> operandPerformance;
+
+    /**
+     * Performance of an {@link OperationType::IF} operation is the sum of
+     * {@link Capabilities::ifPerformance} and the mean of performance for the
+     * two branch subgraphs, where performance for a subgraph is the sum of the
+     * performance of all operations within the subgraph.
+     */
+    PerformanceInfo ifPerformance;
+
+    /**
+     * Performance of a {@link OperationType::WHILE} operation is the sum of
+     * {@link Capabilities::whilePerformance}, performance for the condition
+     * subgraph and performance for the body subgraph, where performance for a
+     * subgraph is the sum of the performance of all operations within the
+     * subgraph.
+     */
+    PerformanceInfo whilePerformance;
 };
 
 /**
@@ -5343,27 +5493,7 @@
     /**
      * Additional parameters specific to a particular operand type.
      */
-    safe_union ExtraParams {
-       /**
-        * No additional parameters.
-        */
-       Monostate none;
-
-       /**
-        * Symmetric per-channel quantization parameters.
-        *
-        * Only applicable to operands of type TENSOR_QUANT8_SYMM_PER_CHANNEL.
-        */
-       SymmPerChannelQuantParams channelQuant;
-
-       /**
-        * Extension operand parameters.
-        *
-        * The framework treats this as an opaque data blob.
-        * The format is up to individual extensions.
-        */
-       vec<uint8_t> extension;
-    } extraParams;
+    @1.2::Operand.ExtraParams extraParams;
 };
 
 /**
@@ -5551,7 +5681,7 @@
          * Specifies a driver-managed buffer. It is the token returned from IDevice::allocate,
          * and is specific to the IDevice object.
          */
-        int32_t token;
+        uint32_t token;
     };
 
     /**
@@ -5573,7 +5703,7 @@
      * Time point of the steady clock (as from std::chrono::steady_clock)
      * measured in nanoseconds.
      */
-    uint64_t nanoseconds;
+    uint64_t nanosecondsSinceEpoch;
 };
 
 /**
@@ -5619,3 +5749,14 @@
      */
     RESOURCE_EXHAUSTED_PERSISTENT,
 };
+
+/**
+ * Each {@link OperationType::WHILE} operation in the model has an implicit
+ * execution timeout duration associated with it ("loop timeout duration").
+ * This duration is configurable on a per-execution basis and must not exceed
+ * 15 seconds. The default value is 2 seconds.
+ */
+enum LoopTimeoutDurationNs : uint64_t {
+    DEFAULT = 2000000000,
+    MAXIMUM = 15000000000,
+};
diff --git a/neuralnetworks/1.3/types.t b/neuralnetworks/1.3/types.t
index a973923..0a6e45e 100644
--- a/neuralnetworks/1.3/types.t
+++ b/neuralnetworks/1.3/types.t
@@ -24,9 +24,9 @@
 import @1.0::RequestArgument;
 import @1.2::Model.ExtensionNameAndPrefix;
 import @1.2::Model.ExtensionTypeEncoding;
+import @1.2::Operand.ExtraParams;
 import @1.2::OperandType;
 import @1.2::OperationType;
-import @1.2::SymmPerChannelQuantParams;
 
 import android.hidl.safe_union@1.0::Monostate;
 
@@ -103,8 +103,10 @@
 /**
  * The capabilities of a driver.
  *
- * Performance of an operation comes from the type of its first operand.
- * This represents performance for non extension operand types.
+ * This represents performance of non-extension operations.
+ *
+ * Performance of an operation other than {@link OperationType::IF} and
+ * {@link OperationType::WHILE} comes from the type of its first operand.
  */
 struct Capabilities {
     /**
@@ -127,11 +129,32 @@
 
     /**
      * Performance by operand type. Must be sorted by OperandType.
-     * If a particular OperandType is not present in operandPerformance,
+     *
+     * If a particular {@link OperandType} is not present in operandPerformance,
      * its performance is treated as
      * { .execTime = FLT_MAX, .powerUsage = FLT_MAX }.
+     *
+     * Performance does not apply to {@link OperandType::SUBGRAPH}, and a driver
+     * must not report operand performance for {@link OperandType::SUBGRAPH}.
      */
     vec<OperandPerformance> operandPerformance;
+
+    /**
+     * Performance of an {@link OperationType::IF} operation is the sum of
+     * {@link Capabilities::ifPerformance} and the mean of performance for the
+     * two branch subgraphs, where performance for a subgraph is the sum of the
+     * performance of all operations within the subgraph.
+     */
+    PerformanceInfo ifPerformance;
+
+    /**
+     * Performance of a {@link OperationType::WHILE} operation is the sum of
+     * {@link Capabilities::whilePerformance}, performance for the condition
+     * subgraph and performance for the body subgraph, where performance for a
+     * subgraph is the sum of the performance of all operations within the
+     * subgraph.
+     */
+    PerformanceInfo whilePerformance;
 };
 
 /**
@@ -319,27 +342,7 @@
     /**
      * Additional parameters specific to a particular operand type.
      */
-    safe_union ExtraParams {
-       /**
-        * No additional parameters.
-        */
-       Monostate none;
-
-       /**
-        * Symmetric per-channel quantization parameters.
-        *
-        * Only applicable to operands of type TENSOR_QUANT8_SYMM_PER_CHANNEL.
-        */
-       SymmPerChannelQuantParams channelQuant;
-
-       /**
-        * Extension operand parameters.
-        *
-        * The framework treats this as an opaque data blob.
-        * The format is up to individual extensions.
-        */
-       vec<uint8_t> extension;
-    } extraParams;
+    @1.2::Operand.ExtraParams extraParams;
 };
 
 /**
@@ -527,7 +530,7 @@
          * Specifies a driver-managed buffer. It is the token returned from IDevice::allocate,
          * and is specific to the IDevice object.
          */
-        int32_t token;
+        uint32_t token;
     };
 
     /**
@@ -549,6 +552,19 @@
      * Time point of the steady clock (as from std::chrono::steady_clock)
      * measured in nanoseconds.
      */
+    uint64_t nanosecondsSinceEpoch;
+};
+
+/**
+ * Optional timeout duration measured in nanoseconds.
+ */
+safe_union OptionalTimeoutDuration {
+    /** No time point provided. */
+    Monostate none;
+
+    /**
+     * Timeout duration measured in nanoseconds.
+     */
     uint64_t nanoseconds;
 };
 
@@ -582,3 +598,14 @@
      */
     RESOURCE_EXHAUSTED_PERSISTENT,
 };
+
+/**
+ * Each {@link OperationType::WHILE} operation in the model has an implicit
+ * execution timeout duration associated with it ("loop timeout duration").
+ * This duration is configurable on a per-execution basis and must not exceed
+ * 15 seconds. The default value is 2 seconds.
+ */
+enum LoopTimeoutDurationNs : uint64_t {
+    DEFAULT = 2000000000,
+    MAXIMUM = 15000000000,
+};
diff --git a/neuralnetworks/1.3/vts/functional/Android.bp b/neuralnetworks/1.3/vts/functional/Android.bp
index 8e7e9b9..f936267 100644
--- a/neuralnetworks/1.3/vts/functional/Android.bp
+++ b/neuralnetworks/1.3/vts/functional/Android.bp
@@ -16,7 +16,7 @@
 
 cc_library_static {
     name: "VtsHalNeuralNetworksV1_3_utils",
-    defaults: ["VtsHalTargetTestDefaults"],
+    defaults: ["neuralnetworks_vts_functional_defaults"],
     export_include_dirs: ["include"],
     srcs: [
         "Callbacks.cpp",
@@ -35,7 +35,7 @@
 
 cc_test {
     name: "VtsHalNeuralnetworksV1_3TargetTest",
-    defaults: ["VtsHalTargetTestDefaults"],
+    defaults: ["neuralnetworks_vts_functional_defaults"],
     srcs: [
         "BasicTests.cpp",
         "CompilationCachingTests.cpp",
diff --git a/neuralnetworks/1.3/vts/functional/BasicTests.cpp b/neuralnetworks/1.3/vts/functional/BasicTests.cpp
index 891850c..1c25369 100644
--- a/neuralnetworks/1.3/vts/functional/BasicTests.cpp
+++ b/neuralnetworks/1.3/vts/functional/BasicTests.cpp
@@ -57,6 +57,11 @@
                                    [](const OperandPerformance& a, const OperandPerformance& b) {
                                        return a.type < b.type;
                                    }));
+        EXPECT_TRUE(std::all_of(opPerf.begin(), opPerf.end(), [](const OperandPerformance& a) {
+            return a.type != OperandType::SUBGRAPH;
+        }));
+        EXPECT_TRUE(isPositive(capabilities.ifPerformance));
+        EXPECT_TRUE(isPositive(capabilities.whilePerformance));
     });
     EXPECT_TRUE(ret.isOk());
 }
diff --git a/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
index 576e524..ac18c8f 100644
--- a/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/1.3/vts/functional/CompilationCachingTests.cpp
@@ -209,10 +209,10 @@
     };
 
     return {
-            .operands = std::move(operands),
-            .operations = std::move(operations),
-            .inputIndexes = {1},
-            .outputIndexes = {len * 2 + 1},
+            .main = {.operands = std::move(operands),
+                     .operations = std::move(operations),
+                     .inputIndexes = {1},
+                     .outputIndexes = {len * 2 + 1}},
             .isRelaxed = false,
     };
 }
@@ -370,7 +370,7 @@
         sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
         hidl_array<uint8_t, sizeof(mToken)> cacheToken(mToken);
         Return<ErrorStatus> prepareLaunchStatus = kDevice->prepareModelFromCache_1_3(
-                kDefaultPriority, {}, modelCache, dataCache, cacheToken, preparedModelCallback);
+                {}, modelCache, dataCache, cacheToken, preparedModelCallback);
         ASSERT_TRUE(prepareLaunchStatus.isOk());
         if (static_cast<ErrorStatus>(prepareLaunchStatus) != ErrorStatus::NONE) {
             *preparedModel = nullptr;
diff --git a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
index 8ea0b7e..89edfb7 100644
--- a/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.3/vts/functional/GeneratedTestHarness.cpp
@@ -122,15 +122,15 @@
     // Return {IBuffer object, token} if successful.
     // Return {nullptr, 0} if device memory is not supported.
     template <IOType ioType>
-    std::pair<sp<IBuffer>, int32_t> allocate(uint32_t index) {
-        std::pair<sp<IBuffer>, int32_t> buffer;
+    std::pair<sp<IBuffer>, uint32_t> allocate(uint32_t index) {
+        std::pair<sp<IBuffer>, uint32_t> buffer;
         allocateInternal<ioType>(index, &buffer);
         return buffer;
     }
 
   private:
     template <IOType ioType>
-    void allocateInternal(uint32_t index, std::pair<sp<IBuffer>, int32_t>* result) {
+    void allocateInternal(uint32_t index, std::pair<sp<IBuffer>, uint32_t>* result) {
         ASSERT_NE(result, nullptr);
 
         // Prepare arguments.
@@ -145,14 +145,14 @@
         // Allocate device memory.
         ErrorStatus status;
         sp<IBuffer> buffer;
-        int32_t token;
-        const auto ret = kDevice->allocate(
-                {}, {kPreparedModel}, inputRoles, outputRoles,
-                [&status, &buffer, &token](ErrorStatus error, const sp<IBuffer>& buf, int32_t tok) {
-                    status = error;
-                    buffer = buf;
-                    token = tok;
-                });
+        uint32_t token;
+        auto cb = [&status, &buffer, &token](ErrorStatus error, const sp<IBuffer>& buf,
+                                             uint32_t tok) {
+            status = error;
+            buffer = buf;
+            token = tok;
+        };
+        const auto ret = kDevice->allocate({}, {kPreparedModel}, inputRoles, outputRoles, cb);
 
         // Check allocation results.
         ASSERT_TRUE(ret.isOk());
@@ -169,7 +169,8 @@
         if constexpr (ioType == IOType::INPUT) {
             if (buffer != nullptr) {
                 // TestBuffer -> Shared memory.
-                const auto& testBuffer = kTestModel.operands[kTestModel.inputIndexes[index]].data;
+                const auto& testBuffer =
+                        kTestModel.main.operands[kTestModel.main.inputIndexes[index]].data;
                 ASSERT_GT(testBuffer.size(), 0);
                 hidl_memory tmp = nn::allocateSharedMemory(testBuffer.size());
                 sp<IMemory> inputMemory = mapMemory(tmp);
@@ -195,29 +196,45 @@
     const TestModel& kTestModel;
 };
 
-}  // namespace
+Subgraph createSubgraph(const TestSubgraph& testSubgraph, uint32_t* constCopySize,
+                        std::vector<const TestBuffer*>* constCopies, uint32_t* constRefSize,
+                        std::vector<const TestBuffer*>* constReferences) {
+    CHECK(constCopySize != nullptr);
+    CHECK(constCopies != nullptr);
+    CHECK(constRefSize != nullptr);
+    CHECK(constReferences != nullptr);
 
-Model createModel(const TestModel& testModel) {
-    // Model operands.
-    hidl_vec<Operand> operands(testModel.operands.size());
-    size_t constCopySize = 0, constRefSize = 0;
-    for (uint32_t i = 0; i < testModel.operands.size(); i++) {
-        const auto& op = testModel.operands[i];
+    // Operands.
+    hidl_vec<Operand> operands(testSubgraph.operands.size());
+    for (uint32_t i = 0; i < testSubgraph.operands.size(); i++) {
+        const auto& op = testSubgraph.operands[i];
 
         DataLocation loc = {};
         if (op.lifetime == TestOperandLifeTime::CONSTANT_COPY) {
-            loc = {.poolIndex = 0,
-                   .offset = static_cast<uint32_t>(constCopySize),
-                   .length = static_cast<uint32_t>(op.data.size())};
-            constCopySize += op.data.alignedSize();
+            loc = {
+                    .poolIndex = 0,
+                    .offset = *constCopySize,
+                    .length = static_cast<uint32_t>(op.data.size()),
+            };
+            constCopies->push_back(&op.data);
+            *constCopySize += op.data.alignedSize();
         } else if (op.lifetime == TestOperandLifeTime::CONSTANT_REFERENCE) {
-            loc = {.poolIndex = 0,
-                   .offset = static_cast<uint32_t>(constRefSize),
-                   .length = static_cast<uint32_t>(op.data.size())};
-            constRefSize += op.data.alignedSize();
+            loc = {
+                    .poolIndex = 0,
+                    .offset = *constRefSize,
+                    .length = static_cast<uint32_t>(op.data.size()),
+            };
+            constReferences->push_back(&op.data);
+            *constRefSize += op.data.alignedSize();
+        } else if (op.lifetime == TestOperandLifeTime::SUBGRAPH) {
+            loc = {
+                    .poolIndex = 0,
+                    .offset = *op.data.get<uint32_t>(),
+                    .length = 0,
+            };
         }
 
-        Operand::ExtraParams extraParams;
+        V1_2::Operand::ExtraParams extraParams;
         if (op.type == TestOperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL) {
             extraParams.channelQuant(SymmPerChannelQuantParams{
                     .scales = op.channelQuant.scales, .channelDim = op.channelQuant.channelDim});
@@ -233,25 +250,52 @@
                        .extraParams = std::move(extraParams)};
     }
 
-    // Model operations.
-    hidl_vec<Operation> operations(testModel.operations.size());
-    std::transform(testModel.operations.begin(), testModel.operations.end(), operations.begin(),
-                   [](const TestOperation& op) -> Operation {
+    // Operations.
+    hidl_vec<Operation> operations(testSubgraph.operations.size());
+    std::transform(testSubgraph.operations.begin(), testSubgraph.operations.end(),
+                   operations.begin(), [](const TestOperation& op) -> Operation {
                        return {.type = static_cast<OperationType>(op.type),
                                .inputs = op.inputs,
                                .outputs = op.outputs};
                    });
 
+    return {.operands = std::move(operands),
+            .operations = std::move(operations),
+            .inputIndexes = testSubgraph.inputIndexes,
+            .outputIndexes = testSubgraph.outputIndexes};
+}
+
+void copyTestBuffers(const std::vector<const TestBuffer*>& buffers, uint8_t* output) {
+    uint32_t offset = 0;
+    for (const TestBuffer* buffer : buffers) {
+        const uint8_t* begin = buffer->get<uint8_t>();
+        const uint8_t* end = begin + buffer->size();
+        std::copy(begin, end, output + offset);
+        offset += buffer->alignedSize();
+    }
+}
+
+}  // namespace
+
+Model createModel(const TestModel& testModel) {
+    uint32_t constCopySize = 0;
+    uint32_t constRefSize = 0;
+    std::vector<const TestBuffer*> constCopies;
+    std::vector<const TestBuffer*> constReferences;
+
+    Subgraph mainSubgraph = createSubgraph(testModel.main, &constCopySize, &constCopies,
+                                           &constRefSize, &constReferences);
+    hidl_vec<Subgraph> refSubgraphs(testModel.referenced.size());
+    std::transform(testModel.referenced.begin(), testModel.referenced.end(), refSubgraphs.begin(),
+                   [&constCopySize, &constCopies, &constRefSize,
+                    &constReferences](const TestSubgraph& testSubgraph) {
+                       return createSubgraph(testSubgraph, &constCopySize, &constCopies,
+                                             &constRefSize, &constReferences);
+                   });
+
     // Constant copies.
     hidl_vec<uint8_t> operandValues(constCopySize);
-    for (uint32_t i = 0; i < testModel.operands.size(); i++) {
-        const auto& op = testModel.operands[i];
-        if (op.lifetime == TestOperandLifeTime::CONSTANT_COPY) {
-            const uint8_t* begin = op.data.get<uint8_t>();
-            const uint8_t* end = begin + op.data.size();
-            std::copy(begin, end, operandValues.data() + operands[i].location.offset);
-        }
-    }
+    copyTestBuffers(constCopies, operandValues.data());
 
     // Shared memory.
     hidl_vec<hidl_memory> pools = {};
@@ -266,27 +310,18 @@
                 reinterpret_cast<uint8_t*>(static_cast<void*>(mappedMemory->getPointer()));
         CHECK(mappedPtr != nullptr);
 
-        for (uint32_t i = 0; i < testModel.operands.size(); i++) {
-            const auto& op = testModel.operands[i];
-            if (op.lifetime == TestOperandLifeTime::CONSTANT_REFERENCE) {
-                const uint8_t* begin = op.data.get<uint8_t>();
-                const uint8_t* end = begin + op.data.size();
-                std::copy(begin, end, mappedPtr + operands[i].location.offset);
-            }
-        }
+        copyTestBuffers(constReferences, mappedPtr);
     }
 
-    return {.main = {.operands = std::move(operands),
-                     .operations = std::move(operations),
-                     .inputIndexes = testModel.inputIndexes,
-                     .outputIndexes = testModel.outputIndexes},
+    return {.main = std::move(mainSubgraph),
+            .referenced = std::move(refSubgraphs),
             .operandValues = std::move(operandValues),
             .pools = std::move(pools),
             .relaxComputationFloat32toFloat16 = testModel.isRelaxed};
 }
 
 static bool isOutputSizeGreaterThanOne(const TestModel& testModel, uint32_t index) {
-    const auto byteSize = testModel.operands[testModel.outputIndexes[index]].data.size();
+    const auto byteSize = testModel.main.operands[testModel.main.outputIndexes[index]].data.size();
     return byteSize > 1u;
 }
 
@@ -317,13 +352,13 @@
     // - [2+i, 2+i+o): Output device memories
     DeviceMemoryAllocator allocator(device, preparedModel, testModel);
     std::vector<sp<IBuffer>> buffers;
-    std::vector<int32_t> tokens;
+    std::vector<uint32_t> tokens;
 
     // Model inputs.
-    hidl_vec<RequestArgument> inputs(testModel.inputIndexes.size());
+    hidl_vec<RequestArgument> inputs(testModel.main.inputIndexes.size());
     size_t inputSize = 0;
-    for (uint32_t i = 0; i < testModel.inputIndexes.size(); i++) {
-        const auto& op = testModel.operands[testModel.inputIndexes[i]];
+    for (uint32_t i = 0; i < testModel.main.inputIndexes.size(); i++) {
+        const auto& op = testModel.main.operands[testModel.main.inputIndexes[i]];
         if (op.data.size() == 0) {
             // Omitted input.
             inputs[i] = {.hasNoValue = true};
@@ -350,10 +385,10 @@
     }
 
     // Model outputs.
-    hidl_vec<RequestArgument> outputs(testModel.outputIndexes.size());
+    hidl_vec<RequestArgument> outputs(testModel.main.outputIndexes.size());
     size_t outputSize = 0;
-    for (uint32_t i = 0; i < testModel.outputIndexes.size(); i++) {
-        const auto& op = testModel.operands[testModel.outputIndexes[i]];
+    for (uint32_t i = 0; i < testModel.main.outputIndexes.size(); i++) {
+        const auto& op = testModel.main.operands[testModel.main.outputIndexes[i]];
         if (preferDeviceMemory) {
             SCOPED_TRACE("Output index = " + std::to_string(i));
             auto [buffer, token] = allocator.allocate<IOType::OUTPUT>(i);
@@ -398,9 +433,9 @@
     CHECK(inputMemory.get() != nullptr);
     uint8_t* inputPtr = static_cast<uint8_t*>(static_cast<void*>(inputMemory->getPointer()));
     CHECK(inputPtr != nullptr);
-    for (uint32_t i = 0; i < testModel.inputIndexes.size(); i++) {
+    for (uint32_t i = 0; i < testModel.main.inputIndexes.size(); i++) {
         if (!inputs[i].hasNoValue && inputs[i].location.poolIndex == kInputPoolIndex) {
-            const auto& op = testModel.operands[testModel.inputIndexes[i]];
+            const auto& op = testModel.main.operands[testModel.main.inputIndexes[i]];
             const uint8_t* begin = op.data.get<uint8_t>();
             const uint8_t* end = begin + op.data.size();
             std::copy(begin, end, inputPtr + inputs[i].location.offset);
@@ -443,7 +478,7 @@
         if (outputLoc.poolIndex == kOutputPoolIndex) {
             outputBuffers.emplace_back(outputLoc.length, outputPtr + outputLoc.offset);
         } else {
-            const auto& op = testModel.operands[testModel.outputIndexes[i]];
+            const auto& op = testModel.main.operands[testModel.main.outputIndexes[i]];
             if (op.data.size() == 0) {
                 outputBuffers.emplace_back();
             } else {
@@ -461,7 +496,7 @@
 static Return<ErrorStatus> ExecutePreparedModel(const sp<IPreparedModel>& preparedModel,
                                                 const Request& request, MeasureTiming measure,
                                                 sp<ExecutionCallback>& callback) {
-    return preparedModel->execute_1_3(request, measure, {}, callback);
+    return preparedModel->execute_1_3(request, measure, {}, {}, callback);
 }
 static Return<ErrorStatus> ExecutePreparedModel(const sp<IPreparedModel>& preparedModel,
                                                 const Request& request, MeasureTiming measure,
@@ -469,7 +504,7 @@
                                                 Timing* timing) {
     ErrorStatus result;
     Return<void> ret = preparedModel->executeSynchronously_1_3(
-            request, measure, {},
+            request, measure, {}, {},
             [&result, outputShapes, timing](ErrorStatus error, const hidl_vec<OutputShape>& shapes,
                                             const Timing& time) {
                 result = error;
@@ -577,7 +612,7 @@
             hidl_handle syncFenceHandle;
             sp<IFencedExecutionCallback> fencedCallback;
             Return<void> ret = preparedModel->executeFenced(
-                    request, {}, testConfig.measureTiming, {}, {},
+                    request, {}, testConfig.measureTiming, {}, {}, {},
                     [&result, &syncFenceHandle, &fencedCallback](
                             ErrorStatus error, const hidl_handle& handle,
                             const sp<IFencedExecutionCallback>& callback) {
@@ -638,17 +673,17 @@
             // either empty, or have the same number of elements as the number of outputs.
             ASSERT_EQ(ErrorStatus::NONE, executionStatus);
             ASSERT_TRUE(outputShapes.size() == 0 ||
-                        outputShapes.size() == testModel.outputIndexes.size());
+                        outputShapes.size() == testModel.main.outputIndexes.size());
             break;
         case OutputType::UNSPECIFIED:
             // If the model output operands are not fully specified, outputShapes must have
             // the same number of elements as the number of outputs.
             ASSERT_EQ(ErrorStatus::NONE, executionStatus);
-            ASSERT_EQ(outputShapes.size(), testModel.outputIndexes.size());
+            ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
             break;
         case OutputType::INSUFFICIENT:
             ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
-            ASSERT_EQ(outputShapes.size(), testModel.outputIndexes.size());
+            ASSERT_EQ(outputShapes.size(), testModel.main.outputIndexes.size());
             ASSERT_FALSE(outputShapes[0].isSufficient);
             return;
     }
@@ -656,7 +691,7 @@
     // Go through all outputs, check returned output shapes.
     for (uint32_t i = 0; i < outputShapes.size(); i++) {
         EXPECT_TRUE(outputShapes[i].isSufficient);
-        const auto& expect = testModel.operands[testModel.outputIndexes[i]].dimensions;
+        const auto& expect = testModel.main.operands[testModel.main.outputIndexes[i]].dimensions;
         const std::vector<uint32_t> actual = outputShapes[i].dimensions;
         EXPECT_EQ(expect, actual);
     }
@@ -862,7 +897,7 @@
                            [](const TestModel& testModel) { return !testModel.expectFailure; });
 
 INSTANTIATE_GENERATED_TEST(QuantizationCouplingTest, [](const TestModel& testModel) {
-    return testModel.hasQuant8CoupledOperands() && testModel.operations.size() == 1;
+    return testModel.hasQuant8CoupledOperands() && testModel.main.operations.size() == 1;
 });
 
 }  // namespace android::hardware::neuralnetworks::V1_3::vts::functional
diff --git a/neuralnetworks/1.3/vts/functional/QualityOfServiceTests.cpp b/neuralnetworks/1.3/vts/functional/QualityOfServiceTests.cpp
index 62ffcda..fccc612 100644
--- a/neuralnetworks/1.3/vts/functional/QualityOfServiceTests.cpp
+++ b/neuralnetworks/1.3/vts/functional/QualityOfServiceTests.cpp
@@ -64,11 +64,13 @@
                     std::chrono::time_point_cast<std::chrono::nanoseconds>(currentTime);
             const uint64_t nanosecondsSinceEpoch =
                     currentTimeInNanoseconds.time_since_epoch().count();
-            deadline.nanoseconds(nanosecondsSinceEpoch);
+            deadline.nanosecondsSinceEpoch(nanosecondsSinceEpoch);
         } break;
         case DeadlineBoundType::UNLIMITED: {
-            uint64_t unlimited = std::numeric_limits<uint64_t>::max();
-            deadline.nanoseconds(unlimited);
+            const auto maxTime = std::chrono::time_point<std::chrono::steady_clock,
+                                                         std::chrono::nanoseconds>::max();
+            const uint64_t nanosecondsSinceEpoch = maxTime.time_since_epoch().count();
+            deadline.nanosecondsSinceEpoch(nanosecondsSinceEpoch);
         } break;
     }
     return deadline;
@@ -169,7 +171,7 @@
 
     // launch execution
     const sp<ExecutionCallback> callback = new ExecutionCallback();
-    Return<ErrorStatus> ret = preparedModel->execute_1_3(request, measure, deadline, callback);
+    Return<ErrorStatus> ret = preparedModel->execute_1_3(request, measure, deadline, {}, callback);
     EXPECT_TRUE(ret.isOk());
     EXPECT_EQ(ErrorStatus::NONE, ret.withDefault(ErrorStatus::GENERAL_FAILURE));
     if (!ret.isOk() || ret != ErrorStatus::NONE) return std::nullopt;
@@ -196,7 +198,7 @@
 
     // run execution
     const Return<void> ret =
-            preparedModel->executeSynchronously_1_3(request, measure, deadline, cb);
+            preparedModel->executeSynchronously_1_3(request, measure, deadline, {}, cb);
     EXPECT_TRUE(ret.isOk());
     if (!ret.isOk()) return std::nullopt;
 
@@ -237,12 +239,13 @@
 
     // If the model output operands are fully specified, outputShapes must be either
     // either empty, or have the same number of elements as the number of outputs.
-    ASSERT_TRUE(outputShapes.size() == 0 || outputShapes.size() == testModel.outputIndexes.size());
+    ASSERT_TRUE(outputShapes.size() == 0 ||
+                outputShapes.size() == testModel.main.outputIndexes.size());
 
     // Go through all outputs, check returned output shapes.
     for (uint32_t i = 0; i < outputShapes.size(); i++) {
         EXPECT_TRUE(outputShapes[i].isSufficient);
-        const auto& expect = testModel.operands[testModel.outputIndexes[i]].dimensions;
+        const auto& expect = testModel.main.operands[testModel.main.outputIndexes[i]].dimensions;
         const std::vector<uint32_t> actual = outputShapes[i].dimensions;
         EXPECT_EQ(expect, actual);
     }
diff --git a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
index 1245432..09e9922 100644
--- a/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.3/vts/functional/ValidateModel.cpp
@@ -50,7 +50,7 @@
 
     OptionalTimePoint deadline;
     if (testDeadline) {
-        deadline.nanoseconds(std::numeric_limits<uint64_t>::max());
+        deadline.nanosecondsSinceEpoch(std::numeric_limits<uint64_t>::max());
     }
 
     sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
@@ -182,6 +182,7 @@
         case OperandType::TENSOR_FLOAT16:
         case OperandType::TENSOR_FLOAT32:
         case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
+        case OperandType::SUBGRAPH:
             return 1.0f;
         case OperandType::TENSOR_INT32:
             return -1.0f;
@@ -220,6 +221,7 @@
         case OperandType::TENSOR_FLOAT32:
         case OperandType::TENSOR_INT32:
         case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL:
+        case OperandType::SUBGRAPH:
             return {1};
         case OperandType::TENSOR_QUANT8_ASYMM:
             return {-1, 256};
@@ -527,9 +529,15 @@
                 }
             }
         }
-        // BIDIRECTIONAL_SEQUENCE_LSTM and BIDIRECTIONAL_SEQUENCE_RNN can have either one or two
-        // outputs depending on their mergeOutputs parameter.
-        if (operation.type == OperationType::BIDIRECTIONAL_SEQUENCE_LSTM ||
+        // BIDIRECTIONAL_SEQUENCE_LSTM and BIDIRECTIONAL_SEQUENCE_RNN can have
+        // either one, two, three or four outputs depending on their
+        // mergeOutputs parameter and if state outputs are provided.
+        // UNIDIRECTIONAL_SEQUENCE_LSTM and UNIDIRECTIONAL_SEQUENCE_RNN can have
+        // either one or three outputs depending on whether state outputs are
+        // provided.
+        if (operation.type == OperationType::UNIDIRECTIONAL_SEQUENCE_LSTM ||
+            operation.type == OperationType::UNIDIRECTIONAL_SEQUENCE_RNN ||
+            operation.type == OperationType::BIDIRECTIONAL_SEQUENCE_LSTM ||
             operation.type == OperationType::BIDIRECTIONAL_SEQUENCE_RNN) {
             for (const size_t outOprand : operation.outputs) {
                 if (operand == outOprand) {
diff --git a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
index 2fd9b64..20f4fe2 100644
--- a/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.3/vts/functional/ValidateRequest.cpp
@@ -61,7 +61,7 @@
 
     OptionalTimePoint deadline;
     if (testDeadline) {
-        deadline.nanoseconds(std::numeric_limits<uint64_t>::max());
+        deadline.nanosecondsSinceEpoch(std::numeric_limits<uint64_t>::max());
     }
 
     // asynchronous
@@ -70,7 +70,7 @@
 
         sp<ExecutionCallback> executionCallback = new ExecutionCallback();
         Return<ErrorStatus> executeLaunchStatus =
-                preparedModel->execute_1_3(request, measure, deadline, executionCallback);
+                preparedModel->execute_1_3(request, measure, deadline, {}, executionCallback);
         ASSERT_TRUE(executeLaunchStatus.isOk());
         ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
 
@@ -88,7 +88,7 @@
         SCOPED_TRACE(message + " [executeSynchronously_1_3]");
 
         Return<void> executeStatus = preparedModel->executeSynchronously_1_3(
-                request, measure, deadline,
+                request, measure, deadline, {},
                 [](ErrorStatus error, const hidl_vec<OutputShape>& outputShapes,
                    const Timing& timing) {
                     ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error);
@@ -142,16 +142,14 @@
     // dispatch
     {
         SCOPED_TRACE(message + " [executeFenced]");
-        Return<void> ret = preparedModel->executeFenced(
-                request, {}, MeasureTiming::NO, {}, {},
-                [](ErrorStatus error, const hidl_handle& handle,
-                   const sp<IFencedExecutionCallback>& callback) {
-                    if (error != ErrorStatus::DEVICE_UNAVAILABLE) {
-                        ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error);
-                    }
-                    ASSERT_EQ(handle.getNativeHandle(), nullptr);
-                    ASSERT_EQ(callback, nullptr);
-                });
+        Return<void> ret =
+                preparedModel->executeFenced(request, {}, MeasureTiming::NO, deadline, {}, {},
+                                             [](ErrorStatus error, const hidl_handle& handle,
+                                                const sp<IFencedExecutionCallback>& callback) {
+                                                 ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error);
+                                                 ASSERT_EQ(handle.getNativeHandle(), nullptr);
+                                                 ASSERT_EQ(callback, nullptr);
+                                             });
         ASSERT_TRUE(ret.isOk());
     }
 }
@@ -198,7 +196,7 @@
 void validateRequestFailure(const sp<IPreparedModel>& preparedModel, const Request& request) {
     SCOPED_TRACE("Expecting request to fail [executeSynchronously_1_3]");
     Return<void> executeStatus = preparedModel->executeSynchronously_1_3(
-            request, MeasureTiming::NO, {},
+            request, MeasureTiming::NO, {}, {},
             [](ErrorStatus error, const hidl_vec<OutputShape>& outputShapes, const Timing& timing) {
                 ASSERT_NE(ErrorStatus::NONE, error);
                 EXPECT_EQ(outputShapes.size(), 0);
diff --git a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
index 896ace6..16341da 100644
--- a/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.3/vts/functional/VtsHalNeuralnetworks.cpp
@@ -137,13 +137,10 @@
 void validateExecuteFenced(const sp<IPreparedModel>& preparedModel, const Request& request) {
     SCOPED_TRACE("Expecting request to fail [executeFenced]");
     Return<void> ret_null = preparedModel->executeFenced(
-            request, {hidl_handle(nullptr)}, V1_2::MeasureTiming::NO, {}, {},
+            request, {hidl_handle(nullptr)}, V1_2::MeasureTiming::NO, {}, {}, {},
             [](ErrorStatus error, const hidl_handle& handle,
                const sp<IFencedExecutionCallback>& callback) {
-                // TODO: fix this once sample driver impl is merged.
-                if (error != ErrorStatus::DEVICE_UNAVAILABLE) {
-                    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error);
-                }
+                ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, error);
                 ASSERT_EQ(handle.getNativeHandle(), nullptr);
                 ASSERT_EQ(callback, nullptr);
             });
diff --git a/power/aidl/android/hardware/power/Boost.aidl b/power/aidl/android/hardware/power/Boost.aidl
index 162a36a..c992fd3 100644
--- a/power/aidl/android/hardware/power/Boost.aidl
+++ b/power/aidl/android/hardware/power/Boost.aidl
@@ -29,6 +29,13 @@
     INTERACTION,
 
     /**
+     * This boost indicates that the framework is likely to provide a new
+     * display frame soon. This implies that the device should ensure that the
+     * display processing path is powered up and ready to receive that update.
+     */
+    DISPLAY_UPDATE_IMMINENT,
+
+    /**
      * Below hints are currently not sent in Android framework but OEM might choose to
      * implement for power/perf optimizations.
      */
diff --git a/power/aidl/android/hardware/power/IPower.aidl b/power/aidl/android/hardware/power/IPower.aidl
index 9fb3fc0..2c4bd86 100644
--- a/power/aidl/android/hardware/power/IPower.aidl
+++ b/power/aidl/android/hardware/power/IPower.aidl
@@ -43,7 +43,7 @@
      */
     boolean isModeSupported(in Mode type);
 
-   /**
+    /**
      * setBoost() indicates the device may need to boost some resources, as the
      * the load is likely to increase before the kernel governors can react.
      * Depending on the boost, it may be appropriate to raise the frequencies of
diff --git a/power/aidl/android/hardware/power/Mode.aidl b/power/aidl/android/hardware/power/Mode.aidl
index 9bb5b98..ae113e3 100644
--- a/power/aidl/android/hardware/power/Mode.aidl
+++ b/power/aidl/android/hardware/power/Mode.aidl
@@ -26,20 +26,64 @@
     DOUBLE_TAP_TO_WAKE,
 
     /**
-     * This mode indidates Low power mode is activated or not. Low power
+     * This mode indicates Low power mode is activated or not. Low power
      * mode is intended to save battery at the cost of performance.
      */
     LOW_POWER,
 
     /**
-     * This mode indidates Sustained Performance mode is activated or not.
+     * This mode indicates Sustained Performance mode is activated or not.
      * Sustained performance mode is intended to provide a consistent level of
      * performance for a prolonged amount of time.
      */
     SUSTAINED_PERFORMANCE,
 
     /**
-     * This mode indidates VR Mode is activated or not. VR mode is intended
+     * Sets the device to a fixed performance level which can be sustained under
+     * normal indoor conditions for at least 10 minutes.
+     *
+     * This is similar to sustained performance mode, except that whereas
+     * sustained performance mode puts an upper bound on performance in the
+     * interest of long-term stability, fixed performance mode puts both upper
+     * and lower bounds on performance such that any workload run while in a
+     * fixed performance mode should complete in a repeatable amount of time
+     * (except if the device is under thermal throttling).
+     *
+     * This mode is not intended for general purpose use, but rather to enable
+     * games and other performance-sensitive applications to reduce the number
+     * of variables during profiling and performance debugging. As such, while
+     * it is valid to set the device to minimum clocks for all subsystems in
+     * this mode, it is preferable to attempt to make the relative performance
+     * of the CPU, GPU, and other subsystems match typical usage, even if the
+     * frequencies have to be reduced to provide sustainability.
+     *
+     * To calibrate this mode, follow these steps:
+     *
+     * 1) Build and push the HWUI macrobench as described in
+     *    //frameworks/base/libs/hwui/tests/macrobench/how_to_run.txt
+     * 2) Run the macrobench as follows:
+     *    while true; do \
+     *      adb shell /data/benchmarktest/hwuimacro/hwuimacro shadowgrid2 -c 200 -r 10; \
+     *    done
+     * 3) Determine a fixed set of device clocks such that the loop in (2) can
+     *    run for at least 10 minutes, starting from an idle device on a desk
+     *    at room temperature (roughly 22 Celsius), without hitting thermal
+     *    throttling.
+     * 4) After setting those clocks, set the system property
+     *    ro.power.fixed_performance_scale_factor to a value N, where N is the
+     *    number of times the loop from (2) runs during the 10 minute test
+     *    cycle. It is expected that in FIXED_PERFORMANCE mode, unless there is
+     *    thermal throttling, the loop will run N to N+1 times (inclusive).
+     *
+     * After calibrating this, while in FIXED_PERFORMANCE mode, the macrobench
+     * results obtained while running the loop in (2) should be consistent both
+     * within a given run and from the first run in the 10 minute window through
+     * the last run in the window.
+     */
+    FIXED_PERFORMANCE,
+
+    /**
+     * This mode indicates VR Mode is activated or not. VR mode is intended
      * to provide minimum guarantee for performance for the amount of time the
      * device can sustain it.
      */
@@ -76,6 +120,18 @@
      */
     INTERACTIVE,
 
+    /**
+     * This mode indicates the device is in device idle, externally known as doze.
+     * More details on:
+     * https://developer.android.com/training/monitoring-device-state/doze-standby
+     */
+    DEVICE_IDLE,
+
+    /**
+     * This mode indicates that display is either off or still on but is optimized
+     * for low-power.
+     */
+    DISPLAY_INACTIVE,
 
     /**
      * Below hints are currently not sent in Android framework but OEM might choose to
diff --git a/power/aidl/vts/VtsHalPowerTargetTest.cpp b/power/aidl/vts/VtsHalPowerTargetTest.cpp
index c0e0858..25a385e 100644
--- a/power/aidl/vts/VtsHalPowerTargetTest.cpp
+++ b/power/aidl/vts/VtsHalPowerTargetTest.cpp
@@ -16,6 +16,7 @@
 #include <aidl/Gtest.h>
 #include <aidl/Vintf.h>
 
+#include <android-base/properties.h>
 #include <android/hardware/power/Boost.h>
 #include <android/hardware/power/IPower.h>
 #include <android/hardware/power/Mode.h>
@@ -27,6 +28,7 @@
 using android::ProcessState;
 using android::sp;
 using android::String16;
+using android::base::GetUintProperty;
 using android::binder::Status;
 using android::hardware::power::Boost;
 using android::hardware::power::IPower;
@@ -77,7 +79,7 @@
     for (const auto& mode : kInvalidModes) {
         bool supported;
         ASSERT_TRUE(power->isModeSupported(mode, &supported).isOk());
-        // Should return false for values outsides enum
+        // Should return false for values outside enum
         ASSERT_FALSE(supported);
     }
 }
@@ -103,11 +105,27 @@
     for (const auto& boost : kInvalidBoosts) {
         bool supported;
         ASSERT_TRUE(power->isBoostSupported(boost, &supported).isOk());
-        // Should return false for values outsides enum
+        // Should return false for values outside enum
         ASSERT_FALSE(supported);
     }
 }
 
+// FIXED_PERFORMANCE mode is required for all devices which ship on Android 11
+// or later
+TEST_P(PowerAidl, hasFixedPerformance) {
+    auto apiLevel = GetUintProperty<uint64_t>("ro.product.first_api_level", 0);
+    if (apiLevel == 0) {
+        apiLevel = GetUintProperty<uint64_t>("ro.build.version.sdk", 0);
+    }
+    ASSERT_NE(apiLevel, 0);
+
+    if (apiLevel >= 30) {
+        bool supported;
+        ASSERT_TRUE(power->isModeSupported(Mode::FIXED_PERFORMANCE, &supported).isOk());
+        ASSERT_TRUE(supported);
+    }
+}
+
 INSTANTIATE_TEST_SUITE_P(Power, PowerAidl,
                          testing::ValuesIn(android::getAidlHalInstanceNames(IPower::descriptor)),
                          android::PrintInstanceNameToString);
diff --git a/radio/1.5/IRadio.hal b/radio/1.5/IRadio.hal
index bc40500..6ebbcb4 100644
--- a/radio/1.5/IRadio.hal
+++ b/radio/1.5/IRadio.hal
@@ -18,10 +18,8 @@
 
 import @1.0::CdmaSmsMessage;
 import @1.2::DataRequestReason;
-import @1.4::DataProfileInfo;
 import @1.4::IRadio;
 import @1.5::AccessNetwork;
-import @1.5::BarringInfo;
 import @1.5::DataProfileInfo;
 import @1.5::IndicationFilter;
 import @1.5::LinkAddress;
@@ -71,6 +69,35 @@
             SignalThresholdInfo signalThresholdInfo, AccessNetwork accessNetwork);
 
     /**
+     * Sets the link capacity reporting criteria.
+     *
+     * The resulting reporting criteria are the AND of all the supplied criteria.
+     *
+     * Note: Reporting criteria must be individually set for each RAN. If unset, reporting criteria
+     * for that RAN are implementation-defined.
+     *
+     * Response callback is IRadioResponse.setLinkCapacityReportingCriteriaResponse_1_5().
+     *
+     * @param serial Serial number of request.
+     * @param hysteresisMs A hysteresis time in milliseconds to prevent flapping. A value of 0
+     *     disables hysteresis.
+     * @param hysteresisDlKbps An interval in kbps defining the required magnitude change between DL
+     *     reports. hysteresisDlKbps must be smaller than the smallest threshold delta. A value of 0
+     *     disables hysteresis.
+     * @param hysteresisUlKbps An interval in kbps defining the required magnitude change between UL
+     *     reports. hysteresisUlKbps must be smaller than the smallest threshold delta. A value of 0
+     *     disables hysteresis.
+     * @param thresholdsDownlinkKbps A vector of trigger thresholds in kbps for downlink reports. A
+     *     vector size of 0 disables the use of DL thresholds for reporting.
+     * @param thresholdsUplinkKbps A vector of trigger thresholds in kbps for uplink reports. A
+     *     vector size of 0 disables the use of UL thresholds for reporting.
+     * @param accessNetwork The type of network for which to apply these thresholds.
+     */
+    oneway setLinkCapacityReportingCriteria_1_5(int32_t serial, int32_t hysteresisMs,
+            int32_t hysteresisDlKbps, int32_t hysteresisUlKbps, vec<int32_t> thresholdsDownlinkKbps,
+            vec<int32_t> thresholdsUplinkKbps, AccessNetwork accessNetwork);
+
+    /**
      * Enable or disable UiccApplications on the SIM. If disabled:
      *  - Modem will not register on any network.
      *  - SIM must be PRESENT, and the IccId of the SIM must still be accessible.
@@ -118,13 +145,13 @@
             vec<RadioAccessSpecifier> specifiers);
 
     /**
-     * Starts a network scan
+     * Starts a network scan.
      *
      * @param serial Serial number of request.
      * @param request Defines the radio networks/bands/channels which need to be scanned.
      *
-     * Same API as @1.4::IRadio.startNetworkScan_1_4, except using
-     * 1.5 version of NetworkScanRequest
+     * Same API as @1.4::IRadio.startNetworkScan_1_4, except using the
+     * 1.5 NetworkScanRequest as the input param.
      */
     oneway startNetworkScan_1_5(int32_t serial, NetworkScanRequest request);
 
@@ -166,14 +193,14 @@
      * Response function is IRadioResponse.setupDataCallResponse_1_5()
      *
      * Note this API is the same as the 1.4 version except using the
-     * 1.5 AccessNetwork, DataProfileInto, and link addresses as the input param.
+     * 1.5 AccessNetwork, DataProfileInto, and LinkAddress as the input param.
      */
     oneway setupDataCall_1_5(int32_t serial, AccessNetwork accessNetwork,
             DataProfileInfo dataProfileInfo, bool roamingAllowed,
             DataRequestReason reason, vec<LinkAddress> addresses, vec<string> dnses);
 
     /**
-     * Set an apn to initial attach network
+     * Set an APN to initial attach network.
      *
      * @param serial Serial number of request.
      * @param dataProfileInfo data profile containing APN settings
@@ -189,7 +216,7 @@
      * Send data profiles of the current carrier to the modem.
      *
      * @param serial Serial number of request.
-     * @param profiles Array of DataProfile to set.
+     * @param profiles Array of DataProfileInfo to set.
      *
      * Response callback is IRadioResponse.setDataProfileResponse_1_5()
      *
@@ -230,7 +257,7 @@
      *
      * Prevents the reporting of specified unsolicited indications from the radio. This is used
      * for power saving in instances when those indications are not needed. If unset, defaults to
-     * @1.2::IndicationFilter:ALL.
+     * @1.5::IndicationFilter:ALL.
      *
      * @param serial Serial number of request.
      * @param indicationFilter 32-bit bitmap of IndicationFilter. Bits set to 1 indicate the
@@ -250,7 +277,7 @@
     oneway getBarringInfo(int32_t serial);
 
     /**
-     * Request current voice registration state
+     * Request current voice registration state.
      *
      * @param serial Serial number of request.
      *
@@ -259,7 +286,7 @@
     oneway getVoiceRegistrationState_1_5(int32_t serial);
 
     /**
-     * Request current data registration state
+     * Request current data registration state.
      *
      * @param serial Serial number of request.
      *
@@ -297,11 +324,15 @@
     oneway sendCdmaSmsExpectMore(int32_t serial, CdmaSmsMessage sms);
 
     /**
-     * Requests that deactivates one category of the device personalization.
+     * Request that deactivates one category of device personalization. Device personalization
+     * generally binds the device so it can only be used on one carrier or even one carrier subnet
+     * (See TS 22.022). When the user has gained the rights to unbind the device (at the end of a
+     * contract period or other event), the controlKey will be delivered to either the user for
+     * manual entry or to a carrier app on the device for automatic entry.
      *
      * @param serial Serial number of request.
      * @param persoType SIM personalization type.
-     * @param controlKey depersonalization code corresponding to persoType
+     * @param controlKey the unlock code for removing persoType personalization from this device
      *
      * Response function is IRadioResponse.supplySimDepersonalizationResponse()
      */
diff --git a/radio/1.5/IRadioResponse.hal b/radio/1.5/IRadioResponse.hal
index 6a2187f..84a455f 100644
--- a/radio/1.5/IRadioResponse.hal
+++ b/radio/1.5/IRadioResponse.hal
@@ -21,10 +21,9 @@
 import @1.4::IRadioResponse;
 import @1.5::BarringInfo;
 import @1.5::CellInfo;
+import @1.5::PersoSubstate;
 import @1.5::RegStateResult;
 import @1.5::SetupDataCallResult;
-import @1.4::SetupDataCallResult;
-import @1.5::PersoSubstate;
 
 /**
  * Interface declaring response functions to solicited radio requests.
@@ -45,6 +44,17 @@
      *
      * Valid errors returned:
      *   RadioError:NONE
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     */
+    oneway setLinkCapacityReportingCriteriaResponse_1_5(RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
      *   RadioError:SIM_ABSENT
      *   RadioError:RADIO_NOT_AVAILABLE
      *   RadioError:INTERNAL_ERR
@@ -177,6 +187,7 @@
     oneway getBarringInfoResponse(RadioResponseInfo info, vec<BarringInfo> barringInfos);
 
     /**
+     * @param info Response info struct containing response type, serial no. and error
      * @param voiceRegResponse Current Voice registration response as defined by RegStateResult
      *        in types.hal
      *
@@ -215,7 +226,6 @@
      */
     oneway getCellInfoListResponse_1_5(RadioResponseInfo info, vec<CellInfo> cellInfo);
 
-
     /**
      * @param info Response info struct containing response type, serial no. and error
      *
diff --git a/radio/1.5/types.hal b/radio/1.5/types.hal
index cf195cc..784f776 100644
--- a/radio/1.5/types.hal
+++ b/radio/1.5/types.hal
@@ -19,19 +19,15 @@
 import @1.0::ApnAuthType;
 import @1.0::DataProfileId;
 import @1.0::DataProfileInfoType;
-import @1.0::CdmaSignalStrength;
-import @1.0::EvdoSignalStrength;
 import @1.0::GsmSignalStrength;
 import @1.0::LteSignalStrength;
 import @1.0::PersoSubstate;
-import @1.0::RadioAccessFamily;
 import @1.0::RadioError;
 import @1.0::RegState;
 import @1.0::TimeStampType;
 import @1.1::EutranBands;
 import @1.1::GeranBands;
 import @1.1::RadioAccessNetworks;
-import @1.1::RadioAccessSpecifier;
 import @1.1::ScanStatus;
 import @1.1::ScanType;
 import @1.1::UtranBands;
@@ -43,7 +39,6 @@
 import @1.2::CellIdentityLte;
 import @1.2::CellInfoCdma;
 import @1.2::IndicationFilter;
-import @1.2::NetworkScanRequest;
 import @1.2::TdscdmaSignalStrength;
 import @1.2::WcdmaSignalStrength;
 import @1.4::AccessNetwork;
@@ -51,11 +46,11 @@
 import @1.4::CellIdentityNr;
 import @1.4::DataCallFailCause;
 import @1.4::DataConnActiveStatus;
-import @1.4::DataProfileInfo;
 import @1.4::LteVopsInfo;
 import @1.4::NrIndicators;
 import @1.4::NrSignalStrength;
 import @1.4::PdpProtocolType;
+import @1.4::RadioAccessFamily;
 import @1.4::RadioTechnology;
 
 import android.hidl.safe_union@1.0::Monostate;
@@ -131,7 +126,7 @@
     /** Signal Measurement Type */
     SignalMeasurementType signalMeasurement;
 
-    /** A hysteresis time in milliseconds to prevent flapping. A value of 0 disables hysteresis */
+    /** A hysteresis time in milliseconds to prevent flapping. A value of 0 disables hysteresis. */
     int32_t hysteresisMs;
 
     /**
@@ -161,7 +156,8 @@
 
 enum AccessNetwork : @1.4::AccessNetwork {
     /**
-     *  Next-Generation Radio Access Network (NGRAN)
+     * Next-Generation Radio Access Network (NGRAN).
+     * Note NGRAN is only for standalone mode. Non-standalone mode uses AccessNetwork EUTRAN.
      */
     NGRAN = 6,
 };
@@ -175,7 +171,7 @@
 };
 
 /**
- * Overwritten from @1.1::RadioAccessSpecifier to add NGRAN and NgranBands
+ * Overwritten from @1.1::RadioAccessSpecifier to add NGRAN and NgranBands.
  */
 struct RadioAccessSpecifier {
     /**
@@ -264,8 +260,7 @@
 };
 
 /**
- * Overwritten from @1.2::NetworkScanRequest to update
- * RadioAccessSpecifier to 1.5 version
+ * Overwritten from @1.2::NetworkScanRequest to update RadioAccessSpecifier to 1.5 version.
  */
 struct NetworkScanRequest {
     ScanType type;
@@ -328,11 +323,10 @@
 };
 
 /**
- * Extended from @1.4::DataProfileInfo to update ApnTypes to 1.5 version and replace mtu with
+ * Overwritten from @1.4::DataProfileInfo to update ApnTypes to 1.5 version and replace mtu with
  * mtuV4 and mtuV6. In the future, this must be extended instead of overwritten.
  */
 struct DataProfileInfo {
-
     /** ID of the data profile. */
     DataProfileId profileId;
 
@@ -445,8 +439,8 @@
 };
 
 /**
- * Overwritten from @1.4::SetupDataCallResult in order to update the addresses to 1.5
- * version. In 1.5 the type of addresses changes to vector of LinkAddress, and mtu is replaced by
+ * Overwritten from @1.4::SetupDataCallResult in order to update the addresses to 1.5 version.
+ * In 1.5 the type of addresses changes to vector of LinkAddress, and mtu is replaced by
  * mtuV4 and mtuV6.
  */
 struct SetupDataCallResult {
@@ -687,7 +681,7 @@
     } ratSpecificInfo;
 };
 
-/** A union representing the CellIdentity of a single cell */
+/** A union representing the CellIdentity of a single cell. */
 safe_union CellIdentity {
     Monostate noinit;
 
@@ -708,7 +702,7 @@
  * -NGRAN - 3gpp 38.331 Sec 6.3.2 UAC-BarringInfo and 22.261 Sec 6.22.2.[2-3]
  */
 enum BarringServiceType : int32_t {
-    /** Applicabe to UTRAN */
+    /** Applicable to UTRAN */
     /** Barring for all CS services, including registration */
     CS_SERVICE,
     /** Barring for all PS services, including registration */
@@ -963,14 +957,14 @@
     string registeredPlmn;
 
     /**
-     * Access-technology-specific registration information, such as for Cdma2000.
+     * Access-technology-specific registration information, such as for CDMA2000.
      */
     safe_union AccessTechnologySpecificInfo {
         Monostate noinit;
 
         struct Cdma2000RegistrationInfo {
             /**
-             * concurrent services support indicator. if registered on a CDMA system.
+             * Concurrent services support indicator. if registered on a CDMA system.
              * false - Concurrent services not supported,
              * true - Concurrent services supported
              */
@@ -999,10 +993,10 @@
         struct EutranRegistrationInfo {
             /**
              * Network capabilities for voice over PS services. This info is valid only on LTE
-             * network and must be present when device is camped on LTE. vopsInfo must be empty when
+             * network and must be present when device is camped on LTE. VopsInfo must be empty when
              * device is camped only on 2G/3G.
              */
-            LteVopsInfo lteVopsInfo; // LTE network capability
+            LteVopsInfo lteVopsInfo;
 
             /**
              * The parameters of NR 5G Non-Standalone. This value is only valid on E-UTRAN,
@@ -1032,17 +1026,20 @@
 };
 
 /**
- * Additional personalization categories in addition to those specified in 3GPP TS 22.022 and 3GPP2 C.S0068-0.
+ * Additional personalization categories in addition to those specified in 3GPP TS 22.022 and
+ * 3GPP2 C.S0068-0.
  */
 enum PersoSubstate : @1.0::PersoSubstate {
     SIM_SPN,
     SIM_SPN_PUK,
-    SIM_SP_EHPLMN,              // Equivalent Home PLMN
+    /** Equivalent Home PLMN */
+    SIM_SP_EHPLMN,
     SIM_SP_EHPLMN_PUK,
     SIM_ICCID,
     SIM_ICCID_PUK,
     SIM_IMPI,
     SIM_IMPI_PUK,
-    SIM_NS_SP,                  // Network subset service provider
+    /** Network subset service provider */
+    SIM_NS_SP,
     SIM_NS_SP_PUK,
 };
diff --git a/radio/1.5/vts/functional/Android.bp b/radio/1.5/vts/functional/Android.bp
index 182985e..85c4f99 100644
--- a/radio/1.5/vts/functional/Android.bp
+++ b/radio/1.5/vts/functional/Android.bp
@@ -34,7 +34,6 @@
         "android.hardware.radio@1.0",
         "android.hardware.radio.config@1.0",
         "android.hardware.radio.config@1.1",
-        "android.hardware.radio.config@1.3",
     ],
     header_libs: ["radio.util.header@1.0"],
     test_suites: ["general-tests"]
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
index 3913317..7294b9e 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_api.cpp
@@ -310,6 +310,99 @@
 }
 
 /*
+ * Test IRadio.setLinkCapacityReportingCriteria_1_5() invalid hysteresisDlKbps
+ */
+TEST_F(RadioHidlTest_v1_5, setLinkCapacityReportingCriteria_1_5_invalidHysteresisDlKbps) {
+    serial = GetRandomSerialNumber();
+
+    Return<void> res = radio_v1_5->setLinkCapacityReportingCriteria_1_5(
+            serial, 5000,
+            5000,  // hysteresisDlKbps too big for thresholds delta
+            100, {1000, 5000, 10000, 20000}, {500, 1000, 5000, 10000},
+            ::android::hardware::radio::V1_5::AccessNetwork::GERAN);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+
+    ALOGI("setLinkCapacityReportingCriteria_1_5_invalidHysteresisDlKbps, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+    // Allow REQUEST_NOT_SUPPORTED as setLinkCapacityReportingCriteria_1_5() may not be supported
+    // for GERAN
+    ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadio.setLinkCapacityReportingCriteria_1_5() invalid hysteresisUlKbps
+ */
+TEST_F(RadioHidlTest_v1_5, setLinkCapacityReportingCriteria_1_5_invalidHysteresisUlKbps) {
+    serial = GetRandomSerialNumber();
+
+    Return<void> res = radio_v1_5->setLinkCapacityReportingCriteria_1_5(
+            serial, 5000, 500,
+            1000,  // hysteresisUlKbps too big for thresholds delta
+            {1000, 5000, 10000, 20000}, {500, 1000, 5000, 10000},
+            ::android::hardware::radio::V1_5::AccessNetwork::GERAN);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+
+    ALOGI("setLinkCapacityReportingCriteria_1_5_invalidHysteresisUlKbps, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+    // Allow REQUEST_NOT_SUPPORTED as setLinkCapacityReportingCriteria_1_5() may not be supported
+    // for GERAN
+    ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                             {RadioError::INVALID_ARGUMENTS, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadio.setLinkCapacityReportingCriteria_1_5() empty params
+ */
+TEST_F(RadioHidlTest_v1_5, setLinkCapacityReportingCriteria_1_5_emptyParams) {
+    serial = GetRandomSerialNumber();
+
+    Return<void> res = radio_v1_5->setLinkCapacityReportingCriteria_1_5(
+            serial, 0, 0, 0, {}, {}, ::android::hardware::radio::V1_5::AccessNetwork::GERAN);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+
+    ALOGI("setLinkCapacityReportingCriteria_1_5_emptyParams, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+    // Allow REQUEST_NOT_SUPPORTED as setLinkCapacityReportingCriteria_1_5() may not be supported
+    // for GERAN
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
+ * Test IRadio.setLinkCapacityReportingCriteria_1_5() for GERAN
+ */
+TEST_F(RadioHidlTest_v1_5, setLinkCapacityReportingCriteria_1_5_Geran) {
+    serial = GetRandomSerialNumber();
+
+    Return<void> res = radio_v1_5->setLinkCapacityReportingCriteria_1_5(
+            serial, 5000, 500, 100, {1000, 5000, 10000, 20000}, {500, 1000, 5000, 10000},
+            ::android::hardware::radio::V1_5::AccessNetwork::GERAN);
+    ASSERT_OK(res);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_5->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
+
+    ALOGI("setLinkCapacityReportingCriteria_1_5_Geran, rspInfo.error = %s\n",
+          toString(radioRsp_v1_5->rspInfo.error).c_str());
+    // Allow REQUEST_NOT_SUPPORTED as setLinkCapacityReportingCriteria_1_5() may not be supported
+    // for GERAN
+    ASSERT_TRUE(CheckAnyOfErrors(radioRsp_v1_5->rspInfo.error,
+                                 {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED}));
+}
+
+/*
  * Test IRadio.enableUiccApplications() for the response returned.
  * For SIM ABSENT case.
  */
@@ -969,7 +1062,10 @@
     }
 }
 
-TEST_F(RadioHidlTest_v1_5, setRadioPower_1_5_emergencyCall_cancalled) {
+/*
+ * Test IRadio.setRadioPower_1_5() for the response returned.
+ */
+TEST_F(RadioHidlTest_v1_5, setRadioPower_1_5_emergencyCall_cancelled) {
     // Set radio power to off.
     serial = GetRandomSerialNumber();
     radio_v1_5->setRadioPower_1_5(serial, false, false, false);
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_test.cpp b/radio/1.5/vts/functional/radio_hidl_hal_test.cpp
index c29ebf9..a5d236d 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_test.cpp
+++ b/radio/1.5/vts/functional/radio_hidl_hal_test.cpp
@@ -47,9 +47,9 @@
     EXPECT_EQ(serial, radioRsp_v1_5->rspInfo.serial);
     EXPECT_EQ(RadioError::NONE, radioRsp_v1_5->rspInfo.error);
 
-    sp<::android::hardware::radio::config::V1_3::IRadioConfig> radioConfig =
+    sp<::android::hardware::radio::config::V1_1::IRadioConfig> radioConfig =
             ::testing::VtsHalHidlTargetTestBase::getService<
-                    ::android::hardware::radio::config::V1_3::IRadioConfig>();
+                    ::android::hardware::radio::config::V1_1::IRadioConfig>();
 
     /* Enforce Vts tesing with RadioConfig is existed. */
     ASSERT_NE(nullptr, radioConfig.get());
diff --git a/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h b/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
index d1c17e6..77ec01e 100644
--- a/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
+++ b/radio/1.5/vts/functional/radio_hidl_hal_utils_v1_5.h
@@ -22,7 +22,7 @@
 #include <condition_variable>
 #include <mutex>
 
-#include <android/hardware/radio/config/1.3/IRadioConfig.h>
+#include <android/hardware/radio/config/1.1/IRadioConfig.h>
 
 #include <android/hardware/radio/1.5/IRadio.h>
 #include <android/hardware/radio/1.5/IRadioIndication.h>
@@ -114,9 +114,6 @@
     Return<void> supplyNetworkDepersonalizationResponse(const RadioResponseInfo& info,
                                                         int32_t remainingRetries);
 
-    Return<void> supplySimDepersonalizationResponse(const RadioResponseInfo& info,
-            ::android::hardware::radio::V1_5::PersoSubstate persoType, int32_t remainingRetries);
-
     Return<void> getCurrentCallsResponse(
             const RadioResponseInfo& info,
             const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::Call>& calls);
@@ -534,6 +531,8 @@
     /* 1.5 Api */
     Return<void> setSignalStrengthReportingCriteriaResponse_1_5(const RadioResponseInfo& info);
 
+    Return<void> setLinkCapacityReportingCriteriaResponse_1_5(const RadioResponseInfo& info);
+
     Return<void> enableUiccApplicationsResponse(const RadioResponseInfo& info);
 
     Return<void> areUiccApplicationsEnabledResponse(const RadioResponseInfo& info, bool enabled);
@@ -579,6 +578,10 @@
 
     Return<void> sendCdmaSmsExpectMoreResponse(const RadioResponseInfo& info,
                                                const SendSmsResult& sms);
+
+    Return<void> supplySimDepersonalizationResponse(
+            const RadioResponseInfo& info,
+            ::android::hardware::radio::V1_5::PersoSubstate persoType, int32_t remainingRetries);
 };
 
 /* Callback class for radio indication */
diff --git a/radio/1.5/vts/functional/radio_response.cpp b/radio/1.5/vts/functional/radio_response.cpp
index a62d086..ce14af5 100644
--- a/radio/1.5/vts/functional/radio_response.cpp
+++ b/radio/1.5/vts/functional/radio_response.cpp
@@ -62,13 +62,6 @@
     return Void();
 }
 
-Return<void> RadioResponse_v1_5::supplySimDepersonalizationResponse(
-        const RadioResponseInfo& /*info*/,
-        ::android::hardware::radio::V1_5::PersoSubstate /*persoType*/,
-        int32_t /*remainingRetries*/) {
-    return Void();
-}
-
 Return<void> RadioResponse_v1_5::getCurrentCallsResponse(
         const RadioResponseInfo& /*info*/,
         const ::android::hardware::hidl_vec<::android::hardware::radio::V1_0::Call>& /*calls*/) {
@@ -901,6 +894,13 @@
     return Void();
 }
 
+Return<void> RadioResponse_v1_5::setLinkCapacityReportingCriteriaResponse_1_5(
+        const RadioResponseInfo& info) {
+    rspInfo = info;
+    parent_v1_5.notify(info.serial);
+    return Void();
+}
+
 Return<void> RadioResponse_v1_5::enableUiccApplicationsResponse(const RadioResponseInfo& info) {
     rspInfo = info;
     parent_v1_5.notify(info.serial);
@@ -1011,3 +1011,10 @@
                                                                const SendSmsResult& /*sms*/) {
     return Void();
 }
+
+Return<void> RadioResponse_v1_5::supplySimDepersonalizationResponse(
+        const RadioResponseInfo& /*info*/,
+        ::android::hardware::radio::V1_5::PersoSubstate /*persoType*/,
+        int32_t /*remainingRetries*/) {
+    return Void();
+}
diff --git a/radio/config/1.3/Android.bp b/radio/config/1.3/Android.bp
deleted file mode 100644
index 7360270..0000000
--- a/radio/config/1.3/Android.bp
+++ /dev/null
@@ -1,26 +0,0 @@
-// This file is autogenerated by hidl-gen -Landroidbp.
-
-hidl_interface {
-    name: "android.hardware.radio.config@1.3",
-    root: "android.hardware",
-    vndk: {
-        enabled: true,
-    },
-    srcs: [
-        "types.hal",
-        "IRadioConfig.hal",
-        "IRadioConfigIndication.hal",
-        "IRadioConfigResponse.hal",
-    ],
-    interfaces: [
-        "android.hardware.radio.config@1.0",
-        "android.hardware.radio.config@1.1",
-        "android.hardware.radio.config@1.2",
-        "android.hardware.radio@1.0",
-        "android.hardware.radio@1.1",
-        "android.hardware.radio@1.4",
-        "android.hardware.radio@1.5",
-        "android.hidl.base@1.0",
-    ],
-    gen_java: true,
-}
diff --git a/radio/config/1.3/IRadioConfig.hal b/radio/config/1.3/IRadioConfig.hal
deleted file mode 100644
index d01f54b..0000000
--- a/radio/config/1.3/IRadioConfig.hal
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.radio.config@1.3;
-
-import @1.1::IRadioConfig;
-
-/**
- * This interface is used by telephony and telecom to talk to cellular radio for the purpose of
- * radio configuration, and it is not associated with any specific modem or slot.
- * All the functions have minimum one parameter:
- * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
- * duration of a method call. If clients provide colliding serials (including passing the same
- * serial to different methods), multiple responses (one for each method call) must still be served.
- */
-interface IRadioConfig extends @1.1::IRadioConfig {
-    /**
-     * Request current phone capability.
-     *
-     * @param serial Serial number of request.
-     *
-     * Response callback is IRadioResponse.getPhoneCapabilityResponse_1_3() which
-     * will return <@1.3::PhoneCapability>.
-     */
-    oneway getPhoneCapability_1_3(int32_t serial);
-};
diff --git a/radio/config/1.3/IRadioConfigResponse.hal b/radio/config/1.3/IRadioConfigResponse.hal
deleted file mode 100644
index e13aa1e..0000000
--- a/radio/config/1.3/IRadioConfigResponse.hal
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.radio.config@1.3;
-
-import android.hardware.radio@1.0::RadioResponseInfo;
-import @1.2::IRadioConfigResponse;
-import @1.3::PhoneCapability;
-
-/**
- * Interface declaring response functions to solicited radio config requests.
- */
-interface IRadioConfigResponse extends @1.2::IRadioConfigResponse {
-    /**
-     * @param info Response info struct containing response type, serial no. and error
-     * @param phoneCapability <@1.3::PhoneCapability> it defines modem's capability for example
-     *        how many logical modems it has, how many data connections it supports.
-     *
-     * Valid errors returned:
-     *   RadioError:NONE
-     *   RadioError:RADIO_NOT_AVAILABLE
-     */
-    oneway getPhoneCapabilityResponse_1_3(RadioResponseInfo info, PhoneCapability phoneCapability);
-};
diff --git a/radio/config/1.3/default/Android.bp b/radio/config/1.3/default/Android.bp
deleted file mode 100644
index 163c5c5..0000000
--- a/radio/config/1.3/default/Android.bp
+++ /dev/null
@@ -1,28 +0,0 @@
-cc_binary {
-    name: "android.hardware.radio.config@1.3-service",
-    init_rc: ["android.hardware.radio.config@1.3-service.rc"],
-    relative_install_path: "hw",
-    vintf_fragments: ["radio-config-default.xml"],
-    vendor: true,
-    srcs: [
-        "RadioConfig.cpp",
-        "RadioConfigIndication.cpp",
-        "RadioConfigResponse.cpp",
-        "service.cpp",
-    ],
-    shared_libs: [
-        "libhidlbase",
-        "liblog",
-        "libutils",
-        "android.hardware.radio.config@1.0",
-        "android.hardware.radio.config@1.1",
-        "android.hardware.radio.config@1.2",
-        "android.hardware.radio.config@1.3",
-        "android.hardware.radio@1.0",
-        "android.hardware.radio@1.1",
-        "android.hardware.radio@1.2",
-        "android.hardware.radio@1.3",
-        "android.hardware.radio@1.4",
-        "android.hardware.radio@1.5",
-    ],
-}
diff --git a/radio/config/1.3/default/RadioConfig.cpp b/radio/config/1.3/default/RadioConfig.cpp
deleted file mode 100644
index 01e98f1..0000000
--- a/radio/config/1.3/default/RadioConfig.cpp
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.1
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "RadioConfig.h"
-
-namespace android {
-namespace hardware {
-namespace radio {
-namespace config {
-namespace V1_3 {
-namespace implementation {
-
-using namespace ::android::hardware::radio::V1_0;
-
-// Methods from ::android::hardware::radio::config::V1_0::IRadioConfig follow.
-Return<void> RadioConfig::setResponseFunctions(
-        const sp<V1_0::IRadioConfigResponse>& radioConfigResponse,
-        const sp<V1_0::IRadioConfigIndication>& radioConfigIndication) {
-    mRadioConfigResponse = radioConfigResponse;
-    mRadioConfigIndication = radioConfigIndication;
-
-    mRadioConfigResponseV1_3 =
-            V1_3::IRadioConfigResponse::castFrom(mRadioConfigResponse).withDefault(nullptr);
-    mRadioConfigIndicationV1_3 =
-            V1_3::IRadioConfigIndication::castFrom(mRadioConfigIndication).withDefault(nullptr);
-    if (mRadioConfigResponseV1_3 == nullptr || mRadioConfigIndicationV1_3 == nullptr) {
-        mRadioConfigResponseV1_3 = nullptr;
-        mRadioConfigIndicationV1_3 = nullptr;
-    }
-
-    mRadioConfigResponseV1_2 =
-            V1_2::IRadioConfigResponse::castFrom(mRadioConfigResponse).withDefault(nullptr);
-    mRadioConfigIndicationV1_2 =
-            V1_2::IRadioConfigIndication::castFrom(mRadioConfigIndication).withDefault(nullptr);
-    if (mRadioConfigResponseV1_2 == nullptr || mRadioConfigIndicationV1_2 == nullptr) {
-        mRadioConfigResponseV1_2 = nullptr;
-        mRadioConfigIndicationV1_2 = nullptr;
-    }
-
-    mRadioConfigResponseV1_1 =
-            V1_1::IRadioConfigResponse::castFrom(mRadioConfigResponse).withDefault(nullptr);
-    mRadioConfigIndicationV1_1 =
-            V1_1::IRadioConfigIndication::castFrom(mRadioConfigIndication).withDefault(nullptr);
-    if (mRadioConfigResponseV1_1 == nullptr || mRadioConfigIndicationV1_1 == nullptr) {
-        mRadioConfigResponseV1_1 = nullptr;
-        mRadioConfigIndicationV1_1 = nullptr;
-    }
-
-    return Void();
-}
-
-Return<void> RadioConfig::getSimSlotsStatus(int32_t /* serial */) {
-    hidl_vec<V1_0::SimSlotStatus> slotStatus;
-    RadioResponseInfo info;
-    mRadioConfigResponse->getSimSlotsStatusResponse(info, slotStatus);
-    return Void();
-}
-
-Return<void> RadioConfig::setSimSlotsMapping(int32_t /* serial */,
-                                             const hidl_vec<uint32_t>& /* slotMap */) {
-    RadioResponseInfo info;
-    mRadioConfigResponse->setSimSlotsMappingResponse(info);
-    return Void();
-}
-
-// Methods from ::android::hardware::radio::config::V1_1::IRadioConfig follow.
-Return<void> RadioConfig::getPhoneCapability(int32_t /* serial */) {
-    V1_1::PhoneCapability phoneCapability;
-    RadioResponseInfo info;
-    mRadioConfigResponseV1_1->getPhoneCapabilityResponse(info, phoneCapability);
-    return Void();
-}
-
-Return<void> RadioConfig::setPreferredDataModem(int32_t /* serial */, uint8_t /* modemId */) {
-    RadioResponseInfo info;
-    mRadioConfigResponseV1_1->setPreferredDataModemResponse(info);
-    return Void();
-}
-
-Return<void> RadioConfig::setModemsConfig(int32_t /* serial */,
-                                          const V1_1::ModemsConfig& /* modemsConfig */) {
-    RadioResponseInfo info;
-    mRadioConfigResponseV1_1->setModemsConfigResponse(info);
-    return Void();
-}
-
-Return<void> RadioConfig::getModemsConfig(int32_t /* serial */) {
-    V1_1::ModemsConfig modemsConfig;
-    RadioResponseInfo info;
-    mRadioConfigResponseV1_1->getModemsConfigResponse(info, modemsConfig);
-    return Void();
-}
-
-// Methods from ::android::hardware::radio::config::V1_3::IRadioConfig follow.
-Return<void> RadioConfig::getPhoneCapability_1_3(int32_t /* serial */) {
-    V1_3::PhoneCapability phoneCapability;
-    RadioResponseInfo info;
-    mRadioConfigResponseV1_3->getPhoneCapabilityResponse_1_3(info, phoneCapability);
-    return Void();
-}
-
-}  // namespace implementation
-}  // namespace V1_3
-}  // namespace config
-}  // namespace radio
-}  // namespace hardware
-}  // namespace android
diff --git a/radio/config/1.3/default/RadioConfig.h b/radio/config/1.3/default/RadioConfig.h
deleted file mode 100644
index 57ff368..0000000
--- a/radio/config/1.3/default/RadioConfig.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.1
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_RADIO_CONFIG_V1_3_RADIOCONFIG_H
-#define ANDROID_HARDWARE_RADIO_CONFIG_V1_3_RADIOCONFIG_H
-
-#include <android/hardware/radio/config/1.3/IRadioConfig.h>
-#include <android/hardware/radio/config/1.3/IRadioConfigIndication.h>
-#include <android/hardware/radio/config/1.3/IRadioConfigResponse.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-
-namespace android {
-namespace hardware {
-namespace radio {
-namespace config {
-namespace V1_3 {
-namespace implementation {
-
-using namespace ::android::hardware::radio::config;
-
-using ::android::sp;
-using ::android::hardware::hidl_array;
-using ::android::hardware::hidl_memory;
-using ::android::hardware::hidl_string;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-
-struct RadioConfig : public V1_3::IRadioConfig {
-    sp<V1_0::IRadioConfigResponse> mRadioConfigResponse;
-    sp<V1_0::IRadioConfigIndication> mRadioConfigIndication;
-    sp<V1_1::IRadioConfigResponse> mRadioConfigResponseV1_1;
-    sp<V1_1::IRadioConfigIndication> mRadioConfigIndicationV1_1;
-    sp<V1_2::IRadioConfigResponse> mRadioConfigResponseV1_2;
-    sp<V1_2::IRadioConfigIndication> mRadioConfigIndicationV1_2;
-    sp<V1_3::IRadioConfigResponse> mRadioConfigResponseV1_3;
-    sp<V1_3::IRadioConfigIndication> mRadioConfigIndicationV1_3;
-
-    // Methods from ::android::hardware::radio::config::V1_0::IRadioConfig follow.
-    Return<void> setResponseFunctions(
-            const sp<V1_0::IRadioConfigResponse>& radioConfigResponse,
-            const sp<V1_0::IRadioConfigIndication>& radioConfigIndication);
-    Return<void> getSimSlotsStatus(int32_t serial);
-    Return<void> setSimSlotsMapping(int32_t serial, const hidl_vec<uint32_t>& slotMap);
-
-    // Methods from ::android::hardware::radio::config::V1_1::IRadioConfig follow.
-    Return<void> getPhoneCapability(int32_t serial);
-    Return<void> setPreferredDataModem(int32_t serial, uint8_t modemId);
-    Return<void> setModemsConfig(int32_t serial, const V1_1::ModemsConfig& modemsConfig);
-    Return<void> getModemsConfig(int32_t serial);
-
-    // Methods from ::android::hardware::radio::config::V1_3::IRadioConfig follow.
-    Return<void> getPhoneCapability_1_3(int32_t serial);
-};
-
-}  // namespace implementation
-}  // namespace V1_3
-}  // namespace config
-}  // namespace radio
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_RADIO_CONFIG_V1_3_RADIOCONFIG_H
diff --git a/radio/config/1.3/default/RadioConfigIndication.cpp b/radio/config/1.3/default/RadioConfigIndication.cpp
deleted file mode 100644
index 608fa1c..0000000
--- a/radio/config/1.3/default/RadioConfigIndication.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.1
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "RadioConfigIndication.h"
-
-namespace android {
-namespace hardware {
-namespace radio {
-namespace config {
-namespace V1_3 {
-namespace implementation {
-
-// Methods from ::android::hardware::radio::config::V1_0::IRadioConfigIndication follow.
-Return<void> RadioConfigIndication::simSlotsStatusChanged(
-        RadioIndicationType /* type */, const hidl_vec<V1_0::SimSlotStatus>& /* slotStatus */) {
-    // TODO implement
-    return Void();
-}
-
-// Methods from ::android::hardware::radio::config::V1_2::IRadioConfigIndication follow.
-Return<void> RadioConfigIndication::simSlotsStatusChanged_1_2(
-        RadioIndicationType /* type */, const hidl_vec<V1_2::SimSlotStatus>& /* slotStatus */) {
-    // TODO implement
-    return Void();
-}
-
-}  // namespace implementation
-}  // namespace V1_3
-}  // namespace config
-}  // namespace radio
-}  // namespace hardware
-}  // namespace android
diff --git a/radio/config/1.3/default/RadioConfigIndication.h b/radio/config/1.3/default/RadioConfigIndication.h
deleted file mode 100644
index c92446c..0000000
--- a/radio/config/1.3/default/RadioConfigIndication.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.1
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_RADIO_CONFIG_V1_3_RADIOCONFIGINDICATION_H
-#define ANDROID_HARDWARE_RADIO_CONFIG_V1_3_RADIOCONFIGINDICATION_H
-
-#include <android/hardware/radio/config/1.3/IRadioConfigIndication.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-
-namespace android {
-namespace hardware {
-namespace radio {
-namespace config {
-namespace V1_3 {
-namespace implementation {
-
-using namespace ::android::hardware::radio::V1_0;
-using namespace ::android::hardware::radio::config;
-
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-
-struct RadioConfigIndication : public IRadioConfigIndication {
-    // Methods from ::android::hardware::radio::config::V1_0::IRadioConfigIndication follow.
-    Return<void> simSlotsStatusChanged(RadioIndicationType type,
-                                       const hidl_vec<V1_0::SimSlotStatus>& slotStatus) override;
-
-    // Methods from ::android::hardware::radio::config::V1_2::IRadioConfigIndication follow.
-    Return<void> simSlotsStatusChanged_1_2(
-            RadioIndicationType type, const hidl_vec<V1_2::SimSlotStatus>& slotStatus) override;
-};
-
-}  // namespace implementation
-}  // namespace V1_3
-}  // namespace config
-}  // namespace radio
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_RADIO_CONFIG_V1_3_RADIOCONFIGINDICATION_H
diff --git a/radio/config/1.3/default/RadioConfigResponse.cpp b/radio/config/1.3/default/RadioConfigResponse.cpp
deleted file mode 100644
index 1d48a13..0000000
--- a/radio/config/1.3/default/RadioConfigResponse.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.1
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "RadioConfigResponse.h"
-
-namespace android {
-namespace hardware {
-namespace radio {
-namespace config {
-namespace V1_3 {
-namespace implementation {
-
-// Methods from ::android::hardware::radio::config::V1_0::IRadioConfigResponse follow.
-Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
-        const RadioResponseInfo& /* info */,
-        const hidl_vec<V1_0::SimSlotStatus>& /* slotStatus */) {
-    // TODO implement
-    return Void();
-}
-
-Return<void> RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponseInfo& /* info */) {
-    // TODO implement
-    return Void();
-}
-
-// Methods from ::android::hardware::radio::config::V1_1::IRadioConfigResponse follow.
-Return<void> RadioConfigResponse::getPhoneCapabilityResponse(
-        const RadioResponseInfo& /* info */, const V1_1::PhoneCapability& /* phoneCapability */) {
-    // TODO implement
-    return Void();
-}
-
-Return<void> RadioConfigResponse::setPreferredDataModemResponse(
-        const RadioResponseInfo& /* info */) {
-    // TODO implement
-    return Void();
-}
-
-Return<void> RadioConfigResponse::setModemsConfigResponse(const RadioResponseInfo& /* info */) {
-    // TODO implement
-    return Void();
-}
-
-Return<void> RadioConfigResponse::getModemsConfigResponse(
-        const RadioResponseInfo& /* info */, const V1_1::ModemsConfig& /* modemsConfig */) {
-    // TODO implement
-    return Void();
-}
-
-// Methods from ::android::hardware::radio::config::V1_2::IRadioConfigResponse follow.
-Return<void> RadioConfigResponse::getSimSlotsStatusResponse_1_2(
-        const RadioResponseInfo& /* info */,
-        const hidl_vec<V1_2::SimSlotStatus>& /* slotStatus */) {
-    // TODO implement
-    return Void();
-}
-
-// Methods from ::android::hardware::radio::config::V1_3::IRadioConfigResponse follow.
-Return<void> RadioConfigResponse::getPhoneCapabilityResponse_1_3(
-        const RadioResponseInfo& /* info */, const V1_3::PhoneCapability& /* phoneCapability */) {
-    // TODO implement
-    return Void();
-}
-
-}  // namespace implementation
-}  // namespace V1_3
-}  // namespace config
-}  // namespace radio
-}  // namespace hardware
-}  // namespace android
diff --git a/radio/config/1.3/default/RadioConfigResponse.h b/radio/config/1.3/default/RadioConfigResponse.h
deleted file mode 100644
index dc169bb..0000000
--- a/radio/config/1.3/default/RadioConfigResponse.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.1
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_RADIO_CONFIG_V1_3_RADIOCONFIGRESPONSE_H
-#define ANDROID_HARDWARE_RADIO_CONFIG_V1_3_RADIOCONFIGRESPONSE_H
-
-#include <android/hardware/radio/config/1.3/IRadioConfigResponse.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-
-namespace android {
-namespace hardware {
-namespace radio {
-namespace config {
-namespace V1_3 {
-namespace implementation {
-
-using namespace ::android::hardware::radio::config;
-
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-
-using ::android::hardware::radio::V1_0::RadioResponseInfo;
-
-struct RadioConfigResponse : public IRadioConfigResponse {
-    // Methods from ::android::hardware::radio::config::V1_0::IRadioConfigResponse follow.
-    Return<void> getSimSlotsStatusResponse(
-            const RadioResponseInfo& info,
-            const hidl_vec<V1_0::SimSlotStatus>& slotStatus) override;
-    Return<void> setSimSlotsMappingResponse(const RadioResponseInfo& info) override;
-
-    // Methods from ::android::hardware::radio::config::V1_1::IRadioConfigResponse follow.
-    Return<void> getPhoneCapabilityResponse(const RadioResponseInfo& info,
-                                            const V1_1::PhoneCapability& phoneCapability) override;
-    Return<void> setPreferredDataModemResponse(const RadioResponseInfo& info) override;
-    Return<void> setModemsConfigResponse(const RadioResponseInfo& info) override;
-    Return<void> getModemsConfigResponse(const RadioResponseInfo& info,
-                                         const V1_1::ModemsConfig& modemsConfig) override;
-
-    // Methods from ::android::hardware::radio::config::V1_2::IRadioConfigResponse follow.
-    Return<void> getSimSlotsStatusResponse_1_2(
-            const RadioResponseInfo& info,
-            const hidl_vec<V1_2::SimSlotStatus>& slotStatus) override;
-
-    // Methods from ::android::hardware::radio::config::V1_3::IRadioConfigResponse follow.
-    Return<void> getPhoneCapabilityResponse_1_3(
-            const RadioResponseInfo& info, const V1_3::PhoneCapability& phoneCapability) override;
-};
-
-}  // namespace implementation
-}  // namespace V1_3
-}  // namespace config
-}  // namespace radio
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_RADIO_CONFIG_V1_3_RADIOCONFIGRESPONSE_H
diff --git a/radio/config/1.3/default/android.hardware.radio.config@1.3-service.rc b/radio/config/1.3/default/android.hardware.radio.config@1.3-service.rc
deleted file mode 100644
index 6df9b52..0000000
--- a/radio/config/1.3/default/android.hardware.radio.config@1.3-service.rc
+++ /dev/null
@@ -1,7 +0,0 @@
-service vendor.radio-config-hal-1-3 /vendor/bin/hw/android.hardware.radio.config@1.3-service
-    interface android.hardware.radio.config@1.0::IRadioConfig default
-    interface android.hardware.radio.config@1.1::IRadioConfig default
-    interface android.hardware.radio.config@1.3::IRadioConfig default
-    class hal
-    user system
-    group system
diff --git a/radio/config/1.3/default/radio-config-default.xml b/radio/config/1.3/default/radio-config-default.xml
deleted file mode 100644
index 72f363e..0000000
--- a/radio/config/1.3/default/radio-config-default.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** 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.
-*/
--->
-<manifest version="1.0" type="device">
-    <hal format="hidl">
-        <name>android.hardware.radio.config</name>
-        <transport>hwbinder</transport>
-        <version>1.3</version>
-        <interface>
-            <name>IRadioConfig</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
-</manifest>
diff --git a/radio/config/1.3/default/service.cpp b/radio/config/1.3/default/service.cpp
deleted file mode 100644
index b1e6736..0000000
--- a/radio/config/1.3/default/service.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.1 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.1
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "android.hardware.radio.config@1.3-service"
-
-#include <android/hardware/radio/config/1.3/IRadioConfig.h>
-#include <hidl/HidlTransportSupport.h>
-
-#include "RadioConfig.h"
-
-using android::OK;
-using android::sp;
-using android::status_t;
-using android::hardware::configureRpcThreadpool;
-using android::hardware::joinRpcThreadpool;
-using android::hardware::radio::config::V1_3::IRadioConfig;
-using android::hardware::radio::config::V1_3::implementation::RadioConfig;
-
-int main() {
-    configureRpcThreadpool(1, true);
-    sp<IRadioConfig> radioConfig = new RadioConfig;
-    const status_t status = radioConfig->registerAsService();
-    ALOGW_IF(status != OK, "Could not register IRadioConfig 1.3");
-    ALOGD("Default service is ready.");
-
-    joinRpcThreadpool();
-    return 1;
-}
diff --git a/radio/config/1.3/types.hal b/radio/config/1.3/types.hal
deleted file mode 100644
index 7860006..0000000
--- a/radio/config/1.3/types.hal
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.radio.config@1.3;
-
-import android.hardware.radio@1.1::GeranBands;
-import android.hardware.radio@1.1::EutranBands;
-import android.hardware.radio@1.4::RadioAccessFamily;
-import android.hardware.radio@1.5::NgranBands;
-import android.hardware.radio@1.5::UtranBands;
-
-/** Type for the SIM slot. */
-enum SlotType : int32_t {
-    /** Slot type for UICC/pSIM (physical SIM). */
-    UICC       = 1,
-    /** Slot type for iUICC/iSIM (integrated SIM). */
-    IUICC      = 2,
-    /** Slot type for eUICC/eSIM (embedded SIM). */
-    EUICC      = 3,
-    /** Slot type for soft SIM (no physical SIM). */
-    SOFT_SIM   = 4,
-};
-
-/** A field in PhoneCapability that holds information about the SIM slot. */
-struct SimSlotCapability {
-    /** Corresponds to physicalSlotId in Radio@1.2::CardStatus. */
-    uint32_t physicalSlotId;
-
-    /** Type of slot. */
-    SlotType slotType;
-};
-
-/** Bitmask of features that can be supported by a single modem. */
-enum ModemFeatures : int32_t {
-    /** 3GPP2 capability. */
-    THREE_GPP2_REG            = 1 << 0,
-    /** 3GPP capability. */
-    THREE_GPP_REG             = 1 << 1,
-    /** CDMA 2000 with EHRPD capability. */
-    CDMA2000_EHRPD_REG        = 1 << 2,
-    /** GSM capability. */
-    GERAN_REG                 = 1 << 3,
-    /** UMTS capability. */
-    UTRAN_REG                 = 1 << 4,
-    /** LTE capability. */
-    EUTRAN_REG                = 1 << 5,
-    /** 5G capability. */
-    NGRAN_REG                 = 1 << 6,
-    /** Dual Connectivity capability. */
-    EN_DC_REG                 = 1 << 7,
-    /** VoLTE capability (IMS registered). */
-    PS_VOICE_REG              = 1 << 8,
-    /** CS voice call capability. */
-    CS_VOICE_SESSION          = 1 << 9,
-    /** Internet connection capability. */
-    INTERACTIVE_DATA_SESSION  = 1 << 10,
-    /** Dedicated bearer capability. */
-    DEDICATED_BEARER          = 1 << 11,
-    /** Network scanning capability. */
-    NETWORK_SCAN              = 1 << 12,
-    /** CDMA capability for SIM associated with modem. */
-    CSIM                      = 1 << 13,
-};
-
-struct ConcurrentModemFeatures {
-    /**
-     * A vector of concurrently supportable modem features across all modems.
-     * Each entry in the vector is a bitfield of ModemFeatures that can be used
-     * concurrently with the other ModemFeatures in that list.
-     * Each bitfield must be the full set of features for a single modem.
-     *
-     * On a Dual-SIM device, each entry will be a vector of length 2.
-     * The examples below depict the modemFeatures for four Dual-SIM setups:
-     * 1. Only one modem can PS attach (IMS registered).
-     *    {
-     *        (GERAN_REG | UTRAN_REG | EUTRAN_REG | PS_VOICE_REG |
-     *            CS_VOICE_SESSION | INTERACTIVE_DATA_SESSION | DEDICATED_BEARER),
-     *        (GERAN_REG | UTRAN_REG)
-     *    }
-     *    or
-     *    {
-     *        (GERAN_REG | UTRAN_REG | EUTRAN_REG | PS_VOICE_REG |
-     *            INTERACTIVE_DATA_SESSION),
-     *        (GERAN_REG | UTRAN_REG | CS_VOICE_SESSION)
-     *    }
-     * 2. Both modems can PS attach (dual VoLTE).
-     *    {
-     *        (GERAN_REG | UTRAN_REG | EUTRAN_REG | PS_VOICE_REG |
-     *            CS_VOICE_SESSION | INTERACTIVE_DATA_SESSION | DEDICATED_BEARER),
-     *        (GERAN_REG | UTRAN_REG | EUTRAN_REG | PS_VOICE_REG)
-     *    }
-     * 3. Both modems can maintain an Internet connection, but they share
-     *    one RF hardware.
-     *    {
-     *        (GERAN_REG | UTRAN_REG | EUTRAN_REG | PS_VOICE_REG |
-     *            CS_VOICE_SESSION | INTERACTIVE_DATA_SESSION | DEDICATED_BEARER),
-     *        (GERAN_REG | UTRAN_REG | EUTRAN_REG | PS_VOICE_REG |
-     *            INTERACTIVE_DATA_SESSION)
-     *    }
-     * 4. Both modems can maintain an Internet connection, and they have
-     *    their own RF hardware.
-     *    {
-     *        (GERAN_REG | UTRAN_REG | EUTRAN_REG | PS_VOICE_REG |
-     *            CS_VOICE_SESSION | INTERACTIVE_DATA_SESSION | DEDICATED_BEARER),
-     *        (GERAN_REG | UTRAN_REG | EUTRAN_REG | PS_VOICE_REG |
-     *            INTERACTIVE_DATA_SESSION | DEDICATED_BEARER)
-     *    }
-     */
-    vec<bitfield<ModemFeatures>> modemFeatures;
-};
-
-/**
- * Overwritten from @1.1::PhoneCapability to add new capabilities and deprecate
- * maxActiveData, maxActiveInternetData, isInternetLingeringSupported, logicalModemList.
- * Replaces RadioConfig@1.1::ModemInfo and should replace Radio@1.4::RadioCapabilities
- * in the next major version upgrade. In the future, this should be extended instead of overwritten.
- */
-struct PhoneCapability {
-    /**
-     * 3GPP UE category for UTRAN downlink direction.
-     * 25.306 Table 5.1a
-     */
-    uint8_t utranUeCategoryDl;
-    /**
-     * 3GPP UE category for UTRAN uplink direction.
-     * 25.306 Table 5.1g
-     */
-    uint8_t utranUeCategoryUl;
-    /**
-     * 3GPP UE category for EUTRAN downlink direction.
-     * 25.306 Table 4.1a
-     */
-    uint8_t eutranUeCategoryDl;
-    /**
-     * 3GPP UE category for EUTRAN uplink direction.
-     * 25.306 Table 4.1a-2
-     */
-    uint8_t eutranUeCategoryUl;
-
-    /**
-     * Length of grace period for switching between logical modems, in milliseconds.
-     * Used only when the number of logical modems is greater than the number of
-     * Internet connections the device can support, otherwise must be 0.
-     */
-    uint64_t psDataConnectionLingerTimeMillis;
-
-    vec<GeranBands> geranBands;
-    vec<UtranBands> utranBands;
-    vec<EutranBands> eutranBands;
-    vec<NgranBands> ngranBands;
-
-    /**
-     * 32-bit bitmap of supported Radio@1.4::RadioAccessFamily types.
-     * Note that RadioAccessFamily is actually the radio access technologies, so it should be
-     * renamed in the next major version upgrade.
-     */
-    bitfield<RadioAccessFamily> supportedRats;
-
-    /**
-     * List of unique logical modem UUIDs from Radio@1.4::RadioCapabilities.
-     * A UUID is typically "com.xxxx.lmX" where X is the logical modem ID.
-     * Must be equal to the number of logical modems in the device.
-     * Radio@1.2::RadioConst::MAX_UUID_LENGTH is the max length of each UUID.
-     */
-    vec<string> logicalModemUuids;
-
-    /**
-     * List of SIM slot capabilities. The order of physical slot IDs must correspond to
-     * the order of modems in logicalModemUuids.
-     */
-    vec<SimSlotCapability> simSlotCapabilities;
-
-    /**
-     * A vector of all sets of concurrently supportable modem feature sets. The order of modems
-     * in modemFeatures must correspond to the order of modems in logicalModemUuids.
-     * Each entry in concurrentFeatureSupport is independent of others in the list
-     * and represents a set of concurrently supportable features across all modems.
-     * Each entry in ConcurrentModemFeatures::modemFeatures is a bitfield of
-     * concurrently supported ModemFeatures for one modem.
-     */
-    vec<ConcurrentModemFeatures> concurrentFeatureSupport;
-};
diff --git a/radio/config/1.3/vts/functional/Android.bp b/radio/config/1.3/vts/functional/Android.bp
deleted file mode 100644
index 6b28faf..0000000
--- a/radio/config/1.3/vts/functional/Android.bp
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// Copyright (C) 2019 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-cc_test {
-    name: "VtsHalRadioConfigV1_3TargetTest",
-    defaults: ["VtsHalTargetTestDefaults"],
-    srcs: [
-        "radio_config_hidl_hal_api.cpp",
-        "radio_config_hidl_hal_test.cpp",
-        "radio_config_response.cpp",
-        "VtsHalRadioConfigV1_3TargetTest.cpp",
-    ],
-    static_libs: [
-        "RadioVtsTestUtilBase",
-        "android.hardware.radio.config@1.0",
-        "android.hardware.radio.config@1.1",
-        "android.hardware.radio.config@1.2",
-        "android.hardware.radio.config@1.3",
-    ],
-    header_libs: ["radio.util.header@1.0"],
-    test_suites: ["general-tests", "vts-core"],
-}
diff --git a/radio/config/1.3/vts/functional/VtsHalRadioConfigV1_3TargetTest.cpp b/radio/config/1.3/vts/functional/VtsHalRadioConfigV1_3TargetTest.cpp
deleted file mode 100644
index 3bacacf..0000000
--- a/radio/config/1.3/vts/functional/VtsHalRadioConfigV1_3TargetTest.cpp
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <radio_config_hidl_hal_utils.h>
-
-INSTANTIATE_TEST_SUITE_P(
-        PerInstance, RadioConfigHidlTest,
-        testing::ValuesIn(android::hardware::getAllHalInstanceNames(
-                ::android::hardware::radio::config::V1_3::IRadioConfig::descriptor)),
-        android::hardware::PrintInstanceNameToString);
diff --git a/radio/config/1.3/vts/functional/radio_config_hidl_hal_api.cpp b/radio/config/1.3/vts/functional/radio_config_hidl_hal_api.cpp
deleted file mode 100644
index 7f90023..0000000
--- a/radio/config/1.3/vts/functional/radio_config_hidl_hal_api.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <radio_config_hidl_hal_utils.h>
-
-#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
-
-/*
- * Test IRadioConfig.getPhoneCapability_1_3()
- */
-TEST_P(RadioConfigHidlTest, getPhoneCapability_1_3) {
-    serial = GetRandomSerialNumber();
-    Return<void> res = radioConfig->getPhoneCapability_1_3(serial);
-    ASSERT_OK(res);
-    EXPECT_EQ(std::cv_status::no_timeout, wait());
-    EXPECT_EQ(RadioResponseType::SOLICITED, radioConfigRsp->rspInfo.type);
-    EXPECT_EQ(serial, radioConfigRsp->rspInfo.serial);
-    ALOGI("getPhoneCapability_1_3, rspInfo.error = %s\n",
-          toString(radioConfigRsp->rspInfo.error).c_str());
-
-    ASSERT_TRUE(CheckAnyOfErrors(
-            radioConfigRsp->rspInfo.error,
-            {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::INTERNAL_ERR}));
-
-    if (radioConfigRsp->rspInfo.error == RadioError ::NONE) {
-        int numModems = radioConfigRsp->phoneCap_1_3.logicalModemUuids.size();
-        EXPECT_GE(numModems, 0);
-        // length of simSlotCapabilities should be equal to length of logicalModemUuids.
-        EXPECT_EQ(numModems, radioConfigRsp->phoneCap_1_3.simSlotCapabilities.size());
-        // length of modemFeatures in each ConcurrentModemFeatures should be
-        // equal to length of logicalModemUuids.
-        for (V1_3::ConcurrentModemFeatures cmf :
-             radioConfigRsp->phoneCap_1_3.concurrentFeatureSupport) {
-            EXPECT_EQ(numModems, cmf.modemFeatures.size());
-        }
-    }
-}
diff --git a/radio/config/1.3/vts/functional/radio_config_hidl_hal_test.cpp b/radio/config/1.3/vts/functional/radio_config_hidl_hal_test.cpp
deleted file mode 100644
index cd48b25..0000000
--- a/radio/config/1.3/vts/functional/radio_config_hidl_hal_test.cpp
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <radio_config_hidl_hal_utils.h>
-
-void RadioConfigHidlTest::SetUp() {
-    radioConfig = V1_3::IRadioConfig::getService(GetParam());
-    ASSERT_NE(nullptr, radioConfig.get());
-
-    radioConfigRsp = new (std::nothrow) RadioConfigResponse(*this);
-    ASSERT_NE(nullptr, radioConfigRsp.get());
-
-    count_ = 0;
-
-    radioConfig->setResponseFunctions(radioConfigRsp, nullptr);
-}
-
-/*
- * Notify that the response message is received.
- */
-void RadioConfigHidlTest::notify(int receivedSerial) {
-    std::unique_lock<std::mutex> lock(mtx_);
-    if (serial == receivedSerial) {
-        count_++;
-        cv_.notify_one();
-    }
-}
-
-/*
- * Wait till the response message is notified or till TIMEOUT_PERIOD.
- */
-std::cv_status RadioConfigHidlTest::wait() {
-    std::unique_lock<std::mutex> lock(mtx_);
-
-    std::cv_status status = std::cv_status::no_timeout;
-    auto now = std::chrono::system_clock::now();
-    while (count_ == 0) {
-        status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
-        if (status == std::cv_status::timeout) {
-            return status;
-        }
-    }
-    count_--;
-    return status;
-}
diff --git a/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h b/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h
deleted file mode 100644
index b21c7c0..0000000
--- a/radio/config/1.3/vts/functional/radio_config_hidl_hal_utils.h
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-
-#include <chrono>
-#include <condition_variable>
-#include <mutex>
-
-#include <android/hardware/radio/config/1.3/IRadioConfig.h>
-#include <android/hardware/radio/config/1.3/IRadioConfigIndication.h>
-#include <android/hardware/radio/config/1.3/IRadioConfigResponse.h>
-#include <android/hardware/radio/config/1.3/types.h>
-
-#include <gtest/gtest.h>
-#include <hidl/GtestPrinter.h>
-#include <hidl/ServiceManagement.h>
-#include <log/log.h>
-
-#include "vts_test_util.h"
-
-using namespace ::android::hardware::radio::config;
-
-using ::android::sp;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-
-using ::android::hardware::radio::V1_0::RadioIndicationType;
-using ::android::hardware::radio::V1_0::RadioResponseInfo;
-using ::android::hardware::radio::V1_0::RadioResponseType;
-
-#define TIMEOUT_PERIOD 75
-
-class RadioConfigHidlTest;
-
-/* Callback class for radio config response */
-class RadioConfigResponse : public V1_3::IRadioConfigResponse {
-  protected:
-    RadioConfigHidlTest& parent;
-
-  public:
-    RadioResponseInfo rspInfo;
-    V1_1::PhoneCapability phoneCap_1_1;
-    V1_3::PhoneCapability phoneCap_1_3;
-
-    RadioConfigResponse(RadioConfigHidlTest& parent);
-    virtual ~RadioConfigResponse() = default;
-
-    /* 1.0 Api */
-    Return<void> getSimSlotsStatusResponse(const RadioResponseInfo& info,
-                                           const hidl_vec<V1_0::SimSlotStatus>& slotStatus);
-
-    Return<void> setSimSlotsMappingResponse(const RadioResponseInfo& info);
-
-    /* 1.1 Api */
-    Return<void> getPhoneCapabilityResponse(const RadioResponseInfo& info,
-                                            const V1_1::PhoneCapability& phoneCapability);
-
-    Return<void> setPreferredDataModemResponse(const RadioResponseInfo& info);
-
-    Return<void> getModemsConfigResponse(const RadioResponseInfo& info,
-                                         const V1_1::ModemsConfig& mConfig);
-
-    Return<void> setModemsConfigResponse(const RadioResponseInfo& info);
-
-    /* 1.2 Api */
-    Return<void> getSimSlotsStatusResponse_1_2(const RadioResponseInfo& info,
-                                               const hidl_vec<V1_2::SimSlotStatus>& slotStatus);
-
-    /* 1.3 Api */
-    Return<void> getPhoneCapabilityResponse_1_3(const RadioResponseInfo& info,
-                                                const V1_3::PhoneCapability& phoneCapability);
-};
-
-/* Callback class for radio config indication */
-class RadioConfigIndication : public V1_3::IRadioConfigIndication {
-  protected:
-    RadioConfigHidlTest& parent;
-
-  public:
-    RadioConfigIndication(RadioConfigHidlTest& parent);
-    virtual ~RadioConfigIndication() = default;
-
-    /* 1.2 Api */
-    Return<void> simSlotsStatusChanged_1_2(RadioIndicationType type,
-                                           const hidl_vec<V1_2::SimSlotStatus>& slotStatus);
-};
-
-// The main test class for Radio config HIDL.
-class RadioConfigHidlTest : public ::testing::TestWithParam<std::string> {
-  protected:
-    std::mutex mtx_;
-    std::condition_variable cv_;
-    int count_;
-
-  public:
-    virtual void SetUp() override;
-
-    /* Used as a mechanism to inform the test about data/event callback */
-    void notify(int receivedSerial);
-
-    /* Test code calls this function to wait for response */
-    std::cv_status wait();
-
-    void updateSimCardStatus();
-
-    /* Serial number for radio request */
-    int serial;
-
-    /* radio config service handle */
-    sp<V1_3::IRadioConfig> radioConfig;
-
-    /* radio config response handle */
-    sp<RadioConfigResponse> radioConfigRsp;
-};
diff --git a/radio/config/1.3/vts/functional/radio_config_response.cpp b/radio/config/1.3/vts/functional/radio_config_response.cpp
deleted file mode 100644
index 22098d3..0000000
--- a/radio/config/1.3/vts/functional/radio_config_response.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <radio_config_hidl_hal_utils.h>
-
-using namespace ::android::hardware::radio::config;
-
-using ::android::hardware::hidl_vec;
-
-using ::android::hardware::radio::V1_0::RadioResponseInfo;
-
-RadioConfigResponse::RadioConfigResponse(RadioConfigHidlTest& parent) : parent(parent) {}
-
-/* 1.0 Apis */
-Return<void> RadioConfigResponse::getSimSlotsStatusResponse(
-        const RadioResponseInfo& /* info */,
-        const hidl_vec<V1_0::SimSlotStatus>& /* slotStatus */) {
-    return Void();
-}
-
-Return<void> RadioConfigResponse::setSimSlotsMappingResponse(const RadioResponseInfo& /* info */) {
-    return Void();
-}
-
-/* 1.1 Apis */
-Return<void> RadioConfigResponse::getPhoneCapabilityResponse(
-        const RadioResponseInfo& info, const V1_1::PhoneCapability& phoneCapability) {
-    rspInfo = info;
-    phoneCap_1_1 = phoneCapability;
-    parent.notify(info.serial);
-    return Void();
-}
-
-Return<void> RadioConfigResponse::setPreferredDataModemResponse(
-        const RadioResponseInfo& /* info */) {
-    return Void();
-}
-
-Return<void> RadioConfigResponse::getModemsConfigResponse(const RadioResponseInfo& /* info */,
-                                                          const V1_1::ModemsConfig& /* mConfig */) {
-    return Void();
-}
-
-Return<void> RadioConfigResponse::setModemsConfigResponse(const RadioResponseInfo& /* info */) {
-    return Void();
-}
-
-/* 1.2 Apis */
-Return<void> RadioConfigResponse::getSimSlotsStatusResponse_1_2(
-        const RadioResponseInfo& /* info */,
-        const hidl_vec<V1_2::SimSlotStatus>& /* slotStatus */) {
-    return Void();
-}
-
-/* 1.3 Apis */
-Return<void> RadioConfigResponse::getPhoneCapabilityResponse_1_3(
-        const RadioResponseInfo& info, const V1_3::PhoneCapability& phoneCapability) {
-    rspInfo = info;
-    phoneCap_1_3 = phoneCapability;
-    parent.notify(info.serial);
-    return Void();
-}
diff --git a/sensors/2.0/multihal/Android.bp b/sensors/2.0/multihal/Android.bp
index 811c455..b7fa15a 100644
--- a/sensors/2.0/multihal/Android.bp
+++ b/sensors/2.0/multihal/Android.bp
@@ -46,7 +46,7 @@
     ],
     init_rc: ["android.hardware.sensors@2.0-service-multihal.rc"],
     vintf_fragments: ["android.hardware.sensors@2.0-multihal.xml"],
-    shared_libs: ["android.hardware.sensors@2.0-ScopedWakelock"]
+    shared_libs: ["android.hardware.sensors@2.0-ScopedWakelock"],
 }
 
 cc_library_headers {
@@ -66,8 +66,8 @@
     ],
     vendor_available: true,
     export_header_lib_headers: [
-        "android.hardware.sensors@2.0-multihal.header"
-    ]
+        "android.hardware.sensors@2.0-multihal.header",
+    ],
 }
 
 // The below targets should only be used for testing.
@@ -85,10 +85,25 @@
         "android.hardware.sensors@2.0-multihal.header",
     ],
     export_shared_lib_headers: [
-	"android.hardware.sensors@2.0-ScopedWakelock",
+        "android.hardware.sensors@2.0-ScopedWakelock",
     ],
     shared_libs: [
         "libutils",
         "android.hardware.sensors@2.0-ScopedWakelock",
     ],
 }
+
+cc_test_library {
+    name: "android.hardware.sensors@2.0-ScopedWakelock.testlib",
+    defaults: [
+        "hidl_defaults",
+        "android.hardware.sensors@2.0-multihal-defaults",
+    ],
+    srcs: [
+        "ScopedWakelock.cpp",
+    ],
+    vendor_available: true,
+    export_header_lib_headers: [
+        "android.hardware.sensors@2.0-multihal.header",
+    ],
+}
diff --git a/sensors/2.0/multihal/tests/Android.bp b/sensors/2.0/multihal/tests/Android.bp
index 1637312..472f3f3 100644
--- a/sensors/2.0/multihal/tests/Android.bp
+++ b/sensors/2.0/multihal/tests/Android.bp
@@ -25,7 +25,7 @@
     shared_libs: [
         "android.hardware.sensors@1.0",
         "android.hardware.sensors@2.0",
-	"android.hardware.sensors@2.0-ScopedWakelock",
+        "android.hardware.sensors@2.0-ScopedWakelock",
         "libcutils",
         "libfmq",
         "libhardware",
@@ -38,7 +38,7 @@
         "android.hardware.sensors@2.0-HalProxy",
     ],
     cflags: [
-        "-DLOG_TAG=\"FakeSubHal\""
+        "-DLOG_TAG=\"FakeSubHal\"",
     ],
 }
 
@@ -80,11 +80,11 @@
     static_libs: [
         "android.hardware.sensors@2.0-HalProxy",
         "android.hardware.sensors@2.0-fakesubhal-unittest",
+        "android.hardware.sensors@2.0-ScopedWakelock.testlib",
     ],
     shared_libs: [
         "android.hardware.sensors@1.0",
         "android.hardware.sensors@2.0",
-        "android.hardware.sensors@2.0-ScopedWakelock",
         "libbase",
         "libcutils",
         "libfmq",
diff --git a/sensors/2.0/multihal/tests/HalProxy_test.cpp b/sensors/2.0/multihal/tests/HalProxy_test.cpp
index 1fd35d1..4633a75 100644
--- a/sensors/2.0/multihal/tests/HalProxy_test.cpp
+++ b/sensors/2.0/multihal/tests/HalProxy_test.cpp
@@ -724,6 +724,45 @@
     EXPECT_EQ(eventOut.sensorHandle, (subhal2Index << 24) | sensorHandleToPost);
 }
 
+TEST(HalProxyTest, FillAndDrainPendingQueueTest) {
+    constexpr size_t kQueueSize = 5;
+    // TODO: Make this constant linked to same limit in HalProxy.h
+    constexpr size_t kMaxPendingQueueSize = 100000;
+    AllSensorsSubHal subhal;
+    std::vector<ISensorsSubHal*> subHals{&subhal};
+
+    std::unique_ptr<EventMessageQueue> eventQueue = makeEventFMQ(kQueueSize);
+    std::unique_ptr<WakeupMessageQueue> wakeLockQueue = makeWakelockFMQ(kQueueSize);
+    ::android::sp<ISensorsCallback> callback = new SensorsCallback();
+    EventFlag* eventQueueFlag;
+    EventFlag::createEventFlag(eventQueue->getEventFlagWord(), &eventQueueFlag);
+    HalProxy proxy(subHals);
+    proxy.initialize(*eventQueue->getDesc(), *wakeLockQueue->getDesc(), callback);
+
+    // Fill pending queue
+    std::vector<Event> events = makeMultipleAccelerometerEvents(kQueueSize);
+    subhal.postEvents(events, false);
+    events = makeMultipleAccelerometerEvents(kMaxPendingQueueSize);
+    subhal.postEvents(events, false);
+
+    // Drain pending queue
+    for (int i = 0; i < kMaxPendingQueueSize + kQueueSize; i += kQueueSize) {
+        ASSERT_TRUE(readEventsOutOfQueue(kQueueSize, eventQueue, eventQueueFlag));
+    }
+
+    // Put one event on pending queue
+    events = makeMultipleAccelerometerEvents(kQueueSize);
+    subhal.postEvents(events, false);
+    events = {makeAccelerometerEvent()};
+    subhal.postEvents(events, false);
+
+    // Read out to make room for one event on pending queue to write to FMQ
+    ASSERT_TRUE(readEventsOutOfQueue(kQueueSize, eventQueue, eventQueueFlag));
+
+    // Should be able to read that last event off queue
+    EXPECT_TRUE(readEventsOutOfQueue(1, eventQueue, eventQueueFlag));
+}
+
 // Helper implementations follow
 void testSensorsListFromProxyAndSubHal(const std::vector<SensorInfo>& proxySensorsList,
                                        const std::vector<SensorInfo>& subHalSensorsList) {
diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
index c5eb442..540529d 100644
--- a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
+++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
@@ -303,7 +303,7 @@
     // Find a sensor handle that does not exist in the sensor list
     int32_t maxHandle = 0;
     for (const SensorInfo& sensor : getSensorsList()) {
-        maxHandle = max(maxHandle, sensor.sensorHandle);
+        maxHandle = std::max(maxHandle, sensor.sensorHandle);
     }
     return maxHandle + 1;
 }
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
index 5fb6c5c..54e899b 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
@@ -20,7 +20,6 @@
 #include "sensors-vts-utils/SensorEventsChecker.h"
 #include "sensors-vts-utils/SensorsHidlEnvironmentBase.h"
 
-#include <VtsHalHidlTargetTestBase.h>
 #include <android/hardware/sensors/1.0/ISensors.h>
 #include <android/hardware/sensors/1.0/types.h>
 #include <gtest/gtest.h>
@@ -130,4 +129,4 @@
     std::unordered_set<int32_t> mDirectChannelHandles;
 };
 
-#endif  // ANDROID_SENSORS_HIDL_TEST_BASE_H
\ No newline at end of file
+#endif  // ANDROID_SENSORS_HIDL_TEST_BASE_H
diff --git a/tv/tuner/1.0/IFilter.hal b/tv/tuner/1.0/IFilter.hal
index 94e3c0c..567971f 100644
--- a/tv/tuner/1.0/IFilter.hal
+++ b/tv/tuner/1.0/IFilter.hal
@@ -120,12 +120,13 @@
      * presented by file descripor in the handle as released.
      *
      * @param avMemory A handle associated to the memory for audio or video.
+     * @param avDataId An Id provides additional information for AV data.
      * @return result Result status of the operation.
      *         SUCCESS if successful,
      *         INVALID_ARGUMENT if failed for wrong parameter.
      *         UNKNOWN_ERROR if failed for other reasons.
      */
-    releaseAvHandle(handle avMemory) generates (Result result);
+    releaseAvHandle(handle avMemory, uint64_t avDataId) generates (Result result);
 
     /**
      * Set the filter's data source.
diff --git a/tv/tuner/1.0/ITuner.hal b/tv/tuner/1.0/ITuner.hal
index 2712c13..ba183f1 100644
--- a/tv/tuner/1.0/ITuner.hal
+++ b/tv/tuner/1.0/ITuner.hal
@@ -123,4 +123,21 @@
      * @return lnb the newly created Lnb interface.
      */
     openLnbById(LnbId lnbId) generates (Result result, ILnb lnb);
+
+    /**
+     * Create a new instance of Lnb given a LNB name.
+     *
+     * It is used by the client to create a LNB instance for external device.
+     *
+     * @param lnbName the name for an external LNB to be opened. The app
+     *        provides the name. Frammework doesn't depend on the name, instead
+     *        use lnbId return from this call.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNAVAILABLE if no resource.
+     *         UNKNOWN_ERROR if creation failed for other reasons.
+     * @return lnbId the id of the LNB to be opened.
+     * @return lnb the newly created Lnb interface.
+     */
+    openLnbByName(string lnbName) generates (Result result, LnbId lnbId, ILnb lnb);
 };
diff --git a/tv/tuner/1.0/default/Filter.cpp b/tv/tuner/1.0/default/Filter.cpp
index b3160fc..54d0952 100644
--- a/tv/tuner/1.0/default/Filter.cpp
+++ b/tv/tuner/1.0/default/Filter.cpp
@@ -120,7 +120,7 @@
     return Result::SUCCESS;
 }
 
-Return<Result> Filter::releaseAvHandle(const hidl_handle& /*avMemory*/) {
+Return<Result> Filter::releaseAvHandle(const hidl_handle& /*avMemory*/, uint64_t /*avDataId*/) {
     ALOGV("%s", __FUNCTION__);
 
     return Result::SUCCESS;
diff --git a/tv/tuner/1.0/default/Filter.h b/tv/tuner/1.0/default/Filter.h
index d397f73..0dc992a 100644
--- a/tv/tuner/1.0/default/Filter.h
+++ b/tv/tuner/1.0/default/Filter.h
@@ -70,7 +70,7 @@
 
     virtual Return<Result> flush() override;
 
-    virtual Return<Result> releaseAvHandle(const hidl_handle& avMemory) override;
+    virtual Return<Result> releaseAvHandle(const hidl_handle& avMemory, uint64_t avDataId) override;
 
     virtual Return<Result> close() override;
 
diff --git a/tv/tuner/1.0/default/Tuner.cpp b/tv/tuner/1.0/default/Tuner.cpp
index c143d61..c6017f0 100644
--- a/tv/tuner/1.0/default/Tuner.cpp
+++ b/tv/tuner/1.0/default/Tuner.cpp
@@ -139,6 +139,15 @@
     return mFrontends[frontendId];
 }
 
+Return<void> Tuner::openLnbByName(const hidl_string& /*lnbName*/, openLnbByName_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    sp<ILnb> lnb = new Lnb();
+
+    _hidl_cb(Result::SUCCESS, 1234, lnb);
+    return Void();
+}
+
 void Tuner::setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId) {
     mFrontendToDemux[frontendId] = demuxId;
 }
diff --git a/tv/tuner/1.0/default/Tuner.h b/tv/tuner/1.0/default/Tuner.h
index 96da257..7a8a919 100644
--- a/tv/tuner/1.0/default/Tuner.h
+++ b/tv/tuner/1.0/default/Tuner.h
@@ -55,6 +55,9 @@
 
     virtual Return<void> openLnbById(LnbId lnbId, openLnbById_cb _hidl_cb) override;
 
+    virtual Return<void> openLnbByName(const hidl_string& lnbName,
+                                       openLnbByName_cb _hidl_cb) override;
+
     sp<Frontend> getFrontendById(uint32_t frontendId);
 
     void setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId);
diff --git a/tv/tuner/1.0/default/service.cpp b/tv/tuner/1.0/default/service.cpp
index 581d269..0858d8f 100644
--- a/tv/tuner/1.0/default/service.cpp
+++ b/tv/tuner/1.0/default/service.cpp
@@ -21,7 +21,6 @@
 #define LOG_TAG "android.hardware.tv.tuner@1.0-service"
 #endif
 
-#include <binder/ProcessState.h>
 #include <hidl/HidlTransportSupport.h>
 #include <hidl/LegacySupport.h>
 
diff --git a/tv/tuner/1.0/types.hal b/tv/tuner/1.0/types.hal
index 944da5a..71db109 100644
--- a/tv/tuner/1.0/types.hal
+++ b/tv/tuner/1.0/types.hal
@@ -537,6 +537,16 @@
 };
 
 /**
+ *   VCM mode in DVBS.
+ */
+@export
+enum FrontendDvbsVcmMode : uint32_t {
+    UNDEFINED,
+    AUTO,
+    MANUAL,
+};
+
+/**
  *  Signal Settings for an DVBS Frontend.
  */
 struct FrontendDvbsSettings {
@@ -561,6 +571,8 @@
     uint32_t inputStreamId;
 
     FrontendDvbsStandard standard;
+
+    FrontendDvbsVcmMode vcmMode;
 };
 
 /**
@@ -773,6 +785,7 @@
 /**
  *   Physical Layer Pipe (PLP) Mode for DVBT.
  */
+@export
 enum FrontendDvbtPlpMode : uint32_t {
     UNDEFINED,
     AUTO,
@@ -960,7 +973,7 @@
     /**
      * hardware is able to detect and set Modulation automatically
      */
-    AUTO = 1 << 5,
+    AUTO = 1 << 0,
     MOD_BPSK = 1 << 1,
     MOD_QPSK = 1 << 2,
     MOD_8PSK = 1 << 3,
@@ -1105,7 +1118,7 @@
 
     bitfield<FrontendIsdbtBandwidth> bandwidthCap;
 
-    bitfield<FrontendIsdbtModulation> constellationCap;
+    bitfield<FrontendIsdbtModulation> modulationCap;
 
     bitfield<FrontendIsdbtCoderate> coderateCap;
 
@@ -1118,9 +1131,14 @@
 @export
 enum FrontendAnalogType : uint32_t {
     UNDEFINED = 0,
-    PAL = 1 << 0,
-    SECAM = 1 << 1,
-    NTSC = 1 << 2,
+    AUTO = 1 << 0,
+    PAL = 1 << 1,
+    PAL_M = 1 << 2,
+    PAL_N = 1 << 3,
+    PAL_60 = 1 << 4,
+    NTSC = 1 << 5,
+    NTSC_443 = 1 << 6,
+    SECAM = 1 << 7,
 };
 
 /**
@@ -1129,23 +1147,24 @@
 @export
 enum FrontendAnalogSifStandard : uint32_t {
     UNDEFINED = 0,
-    BG = 1 << 0,
-    BG_A2 = 1 << 1,
-    BG_NICAM = 1 << 2,
-    I = 1 << 3,
-    DK = 1 << 4,
-    DK1 = 1 << 5,
-    DK2 = 1 << 6,
-    DK3 = 1 << 7,
-    DK_NICAM = 1 << 8,
-    L = 1 << 9,
-    M = 1 << 10,
-    M_BTSC = 1 << 11,
-    M_A2 = 1 << 12,
-    M_EIA_J = 1 << 13,
-    I_NICAM = 1 << 14,
-    L_NICAM = 1 << 15,
-    L_PRIME = 1 << 16,
+    AUTO = 1 << 0,
+    BG = 1 << 1,
+    BG_A2 = 1 << 2,
+    BG_NICAM = 1 << 3,
+    I = 1 << 4,
+    DK = 1 << 5,
+    DK1_A2 = 1 << 6,
+    DK2_A2 = 1 << 7,
+    DK3_A2 = 1 << 8,
+    DK_NICAM = 1 << 9,
+    L = 1 << 10,
+    M = 1 << 11,
+    M_BTSC = 1 << 12,
+    M_A2 = 1 << 13,
+    M_EIAJ = 1 << 14,
+    I_NICAM = 1 << 15,
+    L_NICAM = 1 << 16,
+    L_PRIME = 1 << 17,
 };
 
 /**
@@ -1197,6 +1216,7 @@
 /**
  *  Scan type for Frontend.
  */
+@export
 enum FrontendScanType : uint32_t {
     SCAN_UNDEFINED = 0,
     SCAN_AUTO = 1 << 0,
@@ -1206,6 +1226,7 @@
 /**
  *  Scan Message Type for Frontend.
  */
+@export
 enum FrontendScanMessageType : uint32_t {
     /**
      * Scan locked the signal.
@@ -1228,6 +1249,11 @@
      */
     SYMBOL_RATE,
     /**
+     * Locked HIERARCHY for DVBT2 frontend.
+     */
+    HIERARCHY,
+    ANALOG_TYPE,
+    /**
      * Locked Plp Ids for DVBT2 frontend.
      */
     PLP_IDS,
@@ -1272,14 +1298,18 @@
     uint8_t progressPercent;
 
     /**
-     * Signal frequency in Hertz
+     * Signal frequencies in Hertz
      */
-    uint32_t frequency;
+    vec<uint32_t> frequencies;
 
     /**
      * Symbols per second
      */
-    uint32_t symbolRate;
+    vec<uint32_t> symbolRates;
+
+    FrontendDvbtHierarchy hierarchy;
+
+    FrontendAnalogType analogType;
 
     vec<uint8_t> plpIds;
 
@@ -1287,10 +1317,12 @@
 
     vec<uint16_t> inputStreamIds;
 
-    safe_union standard {
+    safe_union Standard {
         FrontendDvbsStandard sStd;
 
         FrontendDvbtStandard tStd;
+
+        FrontendAnalogSifStandard sifStd;
     } std;
 
     /**
@@ -1396,18 +1428,6 @@
      */
     LAYER_ERROR,
     /**
-     * CN value by VBER.
-     */
-    VBER_CN,
-    /**
-     * CN value by LBER.
-     */
-    LBER_CN,
-    /**
-     * CN value by XER.
-     */
-    XER_CN,
-    /**
      * Moduration Error Ratio.
      */
     MER,
@@ -1530,21 +1550,6 @@
     vec<bool> isLayerError;
 
     /**
-     * CN value by VBER measured by 0.001 dB
-     */
-    int32_t vberCn;
-
-    /**
-     * CN value by LBER measured by 0.001 dB
-     */
-    int32_t lberCn;
-
-    /**
-     * CN value by XER measured by 0.001 dB
-     */
-    int32_t xerCn;
-
-    /**
      * MER value measured by 0.001 dB
      */
     int32_t mer;
@@ -1922,7 +1927,7 @@
 };
 
 @export
-enum Constant : uint16_t {
+enum Constant : uint32_t {
     /**
      * An invalid packet ID in transport stream according to ISO/IEC 13818-1.
      */
@@ -1931,6 +1936,14 @@
      * An invalid Stream ID.
      */
     INVALID_STREAM_ID = 0xFFFF,
+    /**
+     * An invalid Filter ID.
+     */
+    INVALID_FILTER_ID = 0xFFFFFFFF,
+    /**
+     * An invalid AV sync hardware ID.
+     */
+    INVALID_AV_SYNC_ID = 0xFFFFFFFF,
 };
 
 /**
@@ -2020,19 +2033,15 @@
 };
 
 /**
- * Index type to be used in the filter for record
+ * Start Code Index type to be used in the filter for record
  */
 @export
-enum DemuxRecordIndexType : uint32_t {
+enum DemuxRecordScIndexType : uint32_t {
     /**
-     * Don't use index
+     * Don't use SC index
      */
     NONE,
     /**
-     * Use TS index
-     */
-    TS,
-    /**
      * Use Start Code index
      */
     SC,
@@ -2046,15 +2055,16 @@
  *  Filter Settings for Record data.
  */
 struct DemuxFilterRecordSettings {
-    DemuxRecordIndexType indexType;
+    bitfield<DemuxTsIndex> tsIndexMask;
 
-    safe_union IndexMask {
-        bitfield<DemuxTsIndex> tsIndexMask;
+    DemuxRecordScIndexType scIndexType;
 
-        bitfield<DemuxScIndex> scIndexMask;
+    safe_union ScIndexMask {
 
-        bitfield<DemuxScHevcIndex> scHevcIndexMask;
-    } indexMask;
+        bitfield<DemuxScIndex> sc;
+
+        bitfield<DemuxScHevcIndex> scHevc;
+    } scIndexMask;
 };
 
 /**
@@ -2152,19 +2162,37 @@
  */
 struct DemuxIpAddress {
     safe_union SrcIpAddress {
+        /**
+         * 0.0.0.0 is invalid. should be ignored.
+         */
         uint8_t[4] v4;
 
+        /**
+         * 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 is invalid. should be ignored.
+         */
         uint8_t[16] v6;
     } srcIpAddress;
 
     safe_union DstIpAddress {
+        /**
+         * 0.0.0.0 is invalid. should be ignored.
+         */
         uint8_t[4] v4;
 
+        /**
+         * 0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0 is invalid. should be ignored.
+         */
         uint8_t[16] v6;
     } dstIpAddress;
 
+    /**
+     * 0 is invalid. should be ignored.
+     */
     uint16_t srcPort;
 
+    /**
+     * 0 is invalid. should be ignored.
+     */
     uint16_t dstPort;
 };
 
@@ -2399,6 +2427,12 @@
     uint32_t dataLength;
 
     /**
+     *  The offset in the memory block which is shared among multiple
+     *  MediaEvents.
+     */
+    uint32_t offset;
+
+    /**
      * A handle associated to the memory where audio or video data stays.
      */
     handle avMemory;
@@ -2409,6 +2443,12 @@
     bool isSecureMemory;
 
     /**
+     * An Id is used by HAL to provide additional information for AV data.
+     * For secure audio, it's the audio handle used by Audio Track.
+     */
+    uint64_t avDataId;
+
+    /**
      * MPU sequence number of filtered data (only for MMTP)
      */
     uint32_t mpuSequenceNumber;
@@ -2448,16 +2488,17 @@
 struct DemuxFilterTsRecordEvent {
     DemuxPid pid;
 
+    bitfield<DemuxTsIndex> tsIndexMask;
+
     /**
      * Indexes of record output
      */
-    safe_union IndexMask {
-        bitfield<DemuxTsIndex> tsIndexMask;
+    safe_union ScIndexMask {
 
-        bitfield<DemuxScIndex> scIndexMask;
+        bitfield<DemuxScIndex> sc;
 
-        bitfield<DemuxScHevcIndex> scHevcIndexMask;
-    } indexMask;
+        bitfield<DemuxScHevcIndex> scHevc;
+    } scIndexMask;
 
     /**
      * Byte number from beginning of the filter's output
diff --git a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_call_util.h b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_call_util.h
index 2f71ccb..ec7ebee 100644
--- a/wifi/hostapd/1.0/vts/functional/hostapd_hidl_call_util.h
+++ b/wifi/hostapd/1.0/vts/functional/hostapd_hidl_call_util.h
@@ -25,8 +25,6 @@
 #include <type_traits>
 #include <utility>
 
-#include <VtsHalHidlTargetTestBase.h>
-
 namespace {
 namespace detail {
 template <typename>