Merge "Revert "Audio HAL: Add missing device to XSD"" into pie-vts-dev am: 75cfcfd3e2 am: 08880e6745 am: 803b7d9f18
am: 6800e0a846

Change-Id: Idc5ae3680349cb0c2a96fd81cc8c7bb104387eca
diff --git a/Android.bp b/Android.bp
index 927e227..dd84737 100644
--- a/Android.bp
+++ b/Android.bp
@@ -24,6 +24,11 @@
         "VtsHalHidlTargetTestBase",
         "libhidl-gen-utils",
     ],
+
+    header_libs: [
+        "libhidl_gtest_helpers",
+    ],
+
     group_static_libs: true,
 
     // Lists all system dependencies that can be expected on the device.
@@ -33,8 +38,6 @@
         "libcutils",
         "liblog",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "libutils",
     ],
     cflags: [
diff --git a/OWNERS b/OWNERS
index 1d7a8e1..433bbb7 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,3 +1,6 @@
+per-file *.hal,*.aidl,OWNERS = set noparent
+per-file *.hal,*.aidl,OWNERS = elsk@google.com,malchev@google.com,smoreland@google.com
+
 elsk@google.com
 maco@google.com
 malchev@google.com
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 213c93a..0140275 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -3,3 +3,8 @@
 
 [Builtin Hooks]
 clang_format = true
+
+[Hook Scripts]
+aosp_hook_confirmationui = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} confirmationui
+aosp_hook_gatekeeper = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} gatekeeper
+aosp_hook_keymaster = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} keymaster
diff --git a/atrace/1.0/Android.bp b/atrace/1.0/Android.bp
index 4d73cfd..c7e8d04 100644
--- a/atrace/1.0/Android.bp
+++ b/atrace/1.0/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/atrace/1.0/default/Android.bp b/atrace/1.0/default/Android.bp
index bcaf064..4bbbdb3 100644
--- a/atrace/1.0/default/Android.bp
+++ b/atrace/1.0/default/Android.bp
@@ -29,7 +29,6 @@
         "libbase",
         "libutils",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.atrace@1.0",
     ],
 }
diff --git a/atrace/1.0/default/AtraceDevice.cpp b/atrace/1.0/default/AtraceDevice.cpp
index 35d11e9..4e82b0a 100644
--- a/atrace/1.0/default/AtraceDevice.cpp
+++ b/atrace/1.0/default/AtraceDevice.cpp
@@ -94,7 +94,7 @@
     for (auto& c : kTracingMap) {
         for (auto& p : c.second.paths) {
             if (!android::base::WriteStringToFile("0", p.first)) {
-                LOG(ERROR) << "Failed to enable tracing on: " << p.first;
+                LOG(ERROR) << "Failed to disable tracing on: " << p.first;
                 if (p.second) {
                     ret = Status::ERROR_TRACING_POINT;
                 }
diff --git a/audio/2.0/Android.bp b/audio/2.0/Android.bp
index 3495b1a..02f8b40 100644
--- a/audio/2.0/Android.bp
+++ b/audio/2.0/Android.bp
@@ -24,4 +24,3 @@
     gen_java: false,
     gen_java_constants: true,
 }
-
diff --git a/audio/4.0/Android.bp b/audio/4.0/Android.bp
index b97fe01..862c711 100644
--- a/audio/4.0/Android.bp
+++ b/audio/4.0/Android.bp
@@ -24,4 +24,3 @@
     gen_java: false,
     gen_java_constants: true,
 }
-
diff --git a/audio/5.0/Android.bp b/audio/5.0/Android.bp
index f6ac2eb..9b28497 100644
--- a/audio/5.0/Android.bp
+++ b/audio/5.0/Android.bp
@@ -25,4 +25,3 @@
     gen_java: false,
     gen_java_constants: true,
 }
-
diff --git a/audio/common/2.0/Android.bp b/audio/common/2.0/Android.bp
index a64548f..475b309 100644
--- a/audio/common/2.0/Android.bp
+++ b/audio/common/2.0/Android.bp
@@ -12,4 +12,3 @@
     gen_java: false,
     gen_java_constants: true,
 }
-
diff --git a/audio/common/4.0/Android.bp b/audio/common/4.0/Android.bp
index cd504e5..83f5aad 100644
--- a/audio/common/4.0/Android.bp
+++ b/audio/common/4.0/Android.bp
@@ -12,4 +12,3 @@
     gen_java: false,
     gen_java_constants: true,
 }
-
diff --git a/audio/common/5.0/Android.bp b/audio/common/5.0/Android.bp
index 66c6fe8..be0f59e 100644
--- a/audio/common/5.0/Android.bp
+++ b/audio/common/5.0/Android.bp
@@ -15,4 +15,3 @@
     gen_java: false,
     gen_java_constants: true,
 }
-
diff --git a/audio/common/all-versions/default/service/Android.mk b/audio/common/all-versions/default/service/Android.mk
index b57a1ae..236f1fd 100644
--- a/audio/common/all-versions/default/service/Android.mk
+++ b/audio/common/all-versions/default/service/Android.mk
@@ -34,11 +34,9 @@
     libcutils \
     libbinder \
     libhidlbase \
-    libhidltransport \
     liblog \
     libutils \
     libhardware \
-    libhwbinder \
     android.hardware.audio@2.0 \
     android.hardware.audio@4.0 \
     android.hardware.audio@5.0 \
diff --git a/audio/common/all-versions/default/service/android.hardware.audio@2.0-service.rc b/audio/common/all-versions/default/service/android.hardware.audio@2.0-service.rc
index 6e91bcc..72b4d19 100644
--- a/audio/common/all-versions/default/service/android.hardware.audio@2.0-service.rc
+++ b/audio/common/all-versions/default/service/android.hardware.audio@2.0-service.rc
@@ -6,9 +6,4 @@
     capabilities BLOCK_SUSPEND
     ioprio rt 4
     writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
-    # audioflinger restarts itself when it loses connection with the hal
-    # and its .rc file has an "onrestart restart audio-hal" rule, thus
-    # an additional auto-restart from the init process isn't needed.
-    oneshot
-    interface android.hardware.audio@4.0::IDevicesFactory default
-    interface android.hardware.audio@2.0::IDevicesFactory default
+    onrestart restart audioserver
diff --git a/audio/core/all-versions/default/Android.bp b/audio/core/all-versions/default/Android.bp
index a1af3c4..000ce18 100644
--- a/audio/core/all-versions/default/Android.bp
+++ b/audio/core/all-versions/default/Android.bp
@@ -24,7 +24,6 @@
         "libfmq",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
         "android.hardware.audio.common-util",
diff --git a/audio/core/all-versions/default/Device.cpp b/audio/core/all-versions/default/Device.cpp
index bec22df..1a9df21 100644
--- a/audio/core/all-versions/default/Device.cpp
+++ b/audio/core/all-versions/default/Device.cpp
@@ -378,7 +378,7 @@
 }
 
 Return<Result> Device::setConnectedState(const DeviceAddress& address, bool connected) {
-    auto key = connected ? AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect;
+    auto key = connected ? AudioParameter::keyDeviceConnect : AudioParameter::keyDeviceDisconnect;
     return setParam(key, address);
 }
 #endif
diff --git a/audio/core/all-versions/default/Stream.cpp b/audio/core/all-versions/default/Stream.cpp
index b995657..e62f6d3 100644
--- a/audio/core/all-versions/default/Stream.cpp
+++ b/audio/core/all-versions/default/Stream.cpp
@@ -243,8 +243,8 @@
 
 Return<Result> Stream::setConnectedState(const DeviceAddress& address, bool connected) {
     return setParam(
-        connected ? AudioParameter::keyStreamConnect : AudioParameter::keyStreamDisconnect,
-        address);
+            connected ? AudioParameter::keyDeviceConnect : AudioParameter::keyDeviceDisconnect,
+            address);
 }
 #elif MAJOR_VERSION >= 4
 Return<void> Stream::getDevices(getDevices_cb _hidl_cb) {
diff --git a/audio/effect/2.0/Android.bp b/audio/effect/2.0/Android.bp
index 2dd1a0c..d4482c2 100644
--- a/audio/effect/2.0/Android.bp
+++ b/audio/effect/2.0/Android.bp
@@ -30,4 +30,3 @@
     gen_java: false,
     gen_java_constants: true,
 }
-
diff --git a/audio/effect/4.0/Android.bp b/audio/effect/4.0/Android.bp
index 2c32bcb..8c1900f 100644
--- a/audio/effect/4.0/Android.bp
+++ b/audio/effect/4.0/Android.bp
@@ -30,4 +30,3 @@
     gen_java: false,
     gen_java_constants: true,
 }
-
diff --git a/audio/effect/5.0/Android.bp b/audio/effect/5.0/Android.bp
index 32fe652..b7dad8d 100644
--- a/audio/effect/5.0/Android.bp
+++ b/audio/effect/5.0/Android.bp
@@ -31,4 +31,3 @@
     gen_java: false,
     gen_java_constants: true,
 }
-
diff --git a/audio/effect/all-versions/default/Android.bp b/audio/effect/all-versions/default/Android.bp
index f23a463..653b30c 100644
--- a/audio/effect/all-versions/default/Android.bp
+++ b/audio/effect/all-versions/default/Android.bp
@@ -28,7 +28,6 @@
         "libfmq",
         "libhidlbase",
         "libhidlmemory",
-        "libhidltransport",
         "liblog",
         "libutils",
         "android.hardware.audio.common-util",
diff --git a/authsecret/1.0/Android.bp b/authsecret/1.0/Android.bp
index 9cde99a..3b84c3b 100644
--- a/authsecret/1.0/Android.bp
+++ b/authsecret/1.0/Android.bp
@@ -14,4 +14,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/authsecret/1.0/default/Android.bp b/authsecret/1.0/default/Android.bp
index 5c3234f..b6ea3c4 100644
--- a/authsecret/1.0/default/Android.bp
+++ b/authsecret/1.0/default/Android.bp
@@ -13,7 +13,6 @@
     ],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
         "android.hardware.authsecret@1.0",
diff --git a/authsecret/1.0/default/android.hardware.authsecret@1.0-service.rc b/authsecret/1.0/default/android.hardware.authsecret@1.0-service.rc
index e82da7e..1a95cd0 100644
--- a/authsecret/1.0/default/android.hardware.authsecret@1.0-service.rc
+++ b/authsecret/1.0/default/android.hardware.authsecret@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.authsecret-1-0 /vendor/bin/hw/android.hardware.authsecret@1.0-service
+    interface android.hardware.authsecret@1.0::IAuthSecret default
     class hal
     user system
     group system
diff --git a/automotive/audiocontrol/1.0/Android.bp b/automotive/audiocontrol/1.0/Android.bp
index 7c51cf7..7ef7909 100644
--- a/automotive/audiocontrol/1.0/Android.bp
+++ b/automotive/audiocontrol/1.0/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/automotive/audiocontrol/1.0/default/Android.bp b/automotive/audiocontrol/1.0/default/Android.bp
index 0e074dd..314830b 100644
--- a/automotive/audiocontrol/1.0/default/Android.bp
+++ b/automotive/audiocontrol/1.0/default/Android.bp
@@ -26,7 +26,6 @@
     shared_libs: [
         "android.hardware.automotive.audiocontrol@1.0",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
     ],
diff --git a/automotive/evs/1.0/Android.bp b/automotive/evs/1.0/Android.bp
index 3ac67ea..51f8e20 100644
--- a/automotive/evs/1.0/Android.bp
+++ b/automotive/evs/1.0/Android.bp
@@ -18,4 +18,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/automotive/evs/1.0/default/Android.bp b/automotive/evs/1.0/default/Android.bp
index 7286478..69bb721 100644
--- a/automotive/evs/1.0/default/Android.bp
+++ b/automotive/evs/1.0/default/Android.bp
@@ -18,7 +18,6 @@
         "libcutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libui",
         "libutils",
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index 4163879..0e73d85 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/automotive/vehicle/2.0/default/Android.bp b/automotive/vehicle/2.0/default/Android.bp
index a11d452..3fd0539 100644
--- a/automotive/vehicle/2.0/default/Android.bp
+++ b/automotive/vehicle/2.0/default/Android.bp
@@ -16,7 +16,6 @@
     name: "vhal_v2_0_defaults",
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
         "android.hardware.automotive.vehicle@2.0",
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index a46de24..fc441ed 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -671,7 +671,7 @@
      .initialValue = {.int32Values = {toInt(VehicleApPowerStateReq::ON), 0}}},
 
     {.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
-                .access = VehiclePropertyAccess::WRITE,
+                .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
      .initialValue = {.int32Values = {toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL), 0}}},
 
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index f6ebcdd..0f20dd1 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -1282,7 +1282,7 @@
 
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VehiclePropertyAccess:WRITE
+     * @access VehiclePropertyAccess:READ_WRITE
      */
     AP_POWER_STATE_REPORT = (
         0x0A01
diff --git a/biometrics/face/1.0/Android.bp b/biometrics/face/1.0/Android.bp
index 222a09e..ebb8668 100644
--- a/biometrics/face/1.0/Android.bp
+++ b/biometrics/face/1.0/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/biometrics/fingerprint/2.1/Android.bp b/biometrics/fingerprint/2.1/Android.bp
index cff43c4..c8cc0f1 100644
--- a/biometrics/fingerprint/2.1/Android.bp
+++ b/biometrics/fingerprint/2.1/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/biometrics/fingerprint/2.1/default/Android.bp b/biometrics/fingerprint/2.1/default/Android.bp
index b12ce61..497fa3f 100644
--- a/biometrics/fingerprint/2.1/default/Android.bp
+++ b/biometrics/fingerprint/2.1/default/Android.bp
@@ -13,7 +13,6 @@
         "libcutils",
         "liblog",
         "libhidlbase",
-        "libhidltransport",
         "libhardware",
         "libutils",
         "android.hardware.biometrics.fingerprint@2.1",
diff --git a/bluetooth/1.0/Android.bp b/bluetooth/1.0/Android.bp
index 67f1a4f..7036d6e 100644
--- a/bluetooth/1.0/Android.bp
+++ b/bluetooth/1.0/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/bluetooth/1.0/default/Android.bp b/bluetooth/1.0/default/Android.bp
index f4b1e7b..f66c25e 100644
--- a/bluetooth/1.0/default/Android.bp
+++ b/bluetooth/1.0/default/Android.bp
@@ -29,7 +29,6 @@
         "libcutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
     ],
@@ -130,7 +129,6 @@
         "libutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.bluetooth@1.0",
     ],
 }
diff --git a/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc b/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
index b615227..9fa128d 100644
--- a/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
+++ b/bluetooth/1.0/default/android.hardware.bluetooth@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.bluetooth-1-0 /vendor/bin/hw/android.hardware.bluetooth@1.0-service
+    interface android.hardware.bluetooth@1.0::IBluetoothHci default
     class hal
     capabilities BLOCK_SUSPEND NET_ADMIN SYS_NICE
     user bluetooth
diff --git a/bluetooth/a2dp/1.0/Android.bp b/bluetooth/a2dp/1.0/Android.bp
index fa46a1c..02f224a 100644
--- a/bluetooth/a2dp/1.0/Android.bp
+++ b/bluetooth/a2dp/1.0/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/bluetooth/a2dp/1.0/default/Android.bp b/bluetooth/a2dp/1.0/default/Android.bp
index 8e6f32d..5264899 100644
--- a/bluetooth/a2dp/1.0/default/Android.bp
+++ b/bluetooth/a2dp/1.0/default/Android.bp
@@ -1,5 +1,5 @@
 cc_library_shared {
-    name: "android.hardware.bluetooth.a2dp@1.0-impl",
+    name: "android.hardware.bluetooth.a2dp@1.0-impl.mock",
     relative_install_path: "hw",
     vendor: true,
     srcs: [
@@ -7,7 +7,6 @@
     ],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "android.hardware.bluetooth.a2dp@1.0",
     ],
diff --git a/bluetooth/audio/2.0/Android.bp b/bluetooth/audio/2.0/Android.bp
index a020f22..6bf0070 100644
--- a/bluetooth/audio/2.0/Android.bp
+++ b/bluetooth/audio/2.0/Android.bp
@@ -19,4 +19,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/bluetooth/audio/2.0/default/Android.bp b/bluetooth/audio/2.0/default/Android.bp
index 1dfc05d..0db0028 100644
--- a/bluetooth/audio/2.0/default/Android.bp
+++ b/bluetooth/audio/2.0/default/Android.bp
@@ -19,7 +19,6 @@
         "libcutils",
         "libfmq",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
     ],
@@ -41,7 +40,6 @@
         "libcutils",
         "libfmq",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
     ],
diff --git a/boot/1.0/Android.bp b/boot/1.0/Android.bp
index b580cac..5568436 100644
--- a/boot/1.0/Android.bp
+++ b/boot/1.0/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/boot/1.0/default/Android.bp b/boot/1.0/default/Android.bp
index 397c56d..fdf7a1e 100644
--- a/boot/1.0/default/Android.bp
+++ b/boot/1.0/default/Android.bp
@@ -9,7 +9,6 @@
     shared_libs: [
         "liblog",
         "libhidlbase",
-        "libhidltransport",
         "libhardware",
         "libutils",
         "android.hardware.boot@1.0",
@@ -29,7 +28,6 @@
         "liblog",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "android.hardware.boot@1.0",
     ],
diff --git a/boot/1.0/default/Android.mk b/boot/1.0/default/Android.mk
deleted file mode 100644
index 7ccc4c8..0000000
--- a/boot/1.0/default/Android.mk
+++ /dev/null
@@ -1,30 +0,0 @@
-# TODO(connoro): Remove this file once we eliminate existing usage of
-# PRODUCT_STATIC_BOOT_CONTROL_HAL
-
-LOCAL_PATH := $(call my-dir)
-
-ifneq ($(strip $(PRODUCT_STATIC_BOOT_CONTROL_HAL)),)
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := android.hardware.boot@1.0-impl-wrapper.recovery
-LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-LOCAL_MULTILIB := first
-ifeq ($(TARGET_IS_64_BIT),true)
-LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/lib64/hw
-else
-LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/lib/hw
-endif
-LOCAL_SRC_FILES := BootControl.cpp
-LOCAL_CFLAGS := -DBOOT_CONTROL_RECOVERY
-LOCAL_SHARED_LIBRARIES := \
-    libbase.recovery \
-    liblog.recovery \
-    libhidlbase.recovery \
-    libhidltransport.recovery \
-    libhardware.recovery \
-    libutils.recovery \
-    android.hardware.boot@1.0.recovery
-LOCAL_STATIC_LIBRARIES := $(PRODUCT_STATIC_BOOT_CONTROL_HAL)
-include $(BUILD_SHARED_LIBRARY)
-
-endif
diff --git a/boot/1.0/default/android.hardware.boot@1.0-service.rc b/boot/1.0/default/android.hardware.boot@1.0-service.rc
index 32f3a45..b8125e1 100644
--- a/boot/1.0/default/android.hardware.boot@1.0-service.rc
+++ b/boot/1.0/default/android.hardware.boot@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.boot-hal-1-0 /vendor/bin/hw/android.hardware.boot@1.0-service
+    interface android.hardware.boot@1.0::IBootControl default
     class early_hal
     user root
     group root
diff --git a/boot/1.1/Android.bp b/boot/1.1/Android.bp
new file mode 100644
index 0000000..6a8d57a
--- /dev/null
+++ b/boot/1.1/Android.bp
@@ -0,0 +1,18 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.boot@1.1",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IBootControl.hal",
+    ],
+    interfaces: [
+        "android.hardware.boot@1.0",
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
diff --git a/boot/1.1/IBootControl.hal b/boot/1.1/IBootControl.hal
new file mode 100644
index 0000000..939dfb3
--- /dev/null
+++ b/boot/1.1/IBootControl.hal
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+package android.hardware.boot@1.1;
+
+import @1.0::IBootControl;
+
+interface IBootControl extends @1.0::IBootControl {
+    /**
+     * Sets whether a snapshot-merge of any dynamic partition is in progress.
+     *
+     * After the merge status is set to a given value, subsequent calls to
+     * getSnapshotMergeStatus must return the set value.
+     *
+     * The merge status must be persistent across reboots. That is, getSnapshotMergeStatus
+     * must return the same value after a reboot if the merge status is not altered in any way
+     * (e.g. set by setSnapshotMergeStatus or set to CANCELLED by bootloader).
+     *
+     * Read/write access to the merge status must be atomic. When the HAL is processing a
+     * setSnapshotMergeStatus call, all subsequent calls to getSnapshotMergeStatus must block until
+     * setSnapshotMergeStatus has returned.
+     *
+     * A MERGING state indicates that dynamic partitions are partially comprised by blocks in the
+     * userdata partition.
+     *
+     * When the merge status is set to MERGING, the following operations must be prohibited from the
+     * bootloader:
+     *  - Flashing or erasing "userdata" or "metadata".
+     *
+     * The following operations may be prohibited when the status is set to MERGING. If not
+     * prohibited, it is recommended that the user receive a warning.
+     *  - Changing the active slot (e.g. via "fastboot set_active")
+     *
+     * @param status Merge status.
+     *
+     * @return success True on success, false otherwise.
+     */
+    setSnapshotMergeStatus(MergeStatus status) generates (bool success);
+
+    /**
+     * Returns whether a snapshot-merge of any dynamic partition is in progress.
+     *
+     * This function must return the merge status set by the last setSnapshotMergeStatus call and
+     * recorded by the bootloader with one exception. If the partitions are being flashed from the
+     * bootloader such that the pending merge must be canceled (for example, if the super partition
+     * is being flashed), this function must return CANCELLED.
+     *
+     * @return success True if the merge status is read successfully, false otherwise.
+     * @return status Merge status.
+     */
+    getSnapshotMergeStatus() generates (MergeStatus status);
+};
+
diff --git a/boot/1.1/default/Android.bp b/boot/1.1/default/Android.bp
new file mode 100644
index 0000000..dca5c26
--- /dev/null
+++ b/boot/1.1/default/Android.bp
@@ -0,0 +1,43 @@
+cc_library_shared {
+    name: "android.hardware.boot@1.1-impl",
+    defaults: [
+        "hidl_defaults",
+        "libboot_control_defaults",
+    ],
+    relative_install_path: "hw",
+    vendor: true,
+    recovery_available: true,
+    srcs: ["BootControl.cpp"],
+
+    shared_libs: [
+        "liblog",
+        "libhidlbase",
+        "libhardware",
+        "libutils",
+        "android.hardware.boot@1.0",
+        "android.hardware.boot@1.1",
+    ],
+    static_libs: [
+        "libboot_control",
+        "libfstab",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.boot@1.1-service",
+    defaults: ["hidl_defaults"],
+    relative_install_path: "hw",
+    vendor: true,
+    init_rc: ["android.hardware.boot@1.1-service.rc"],
+    srcs: ["service.cpp"],
+
+    shared_libs: [
+        "liblog",
+        "libhardware",
+        "libhidlbase",
+        "libutils",
+        "android.hardware.boot@1.0",
+        "android.hardware.boot@1.1",
+    ],
+
+}
diff --git a/boot/1.1/default/BootControl.cpp b/boot/1.1/default/BootControl.cpp
new file mode 100644
index 0000000..c9c62a4
--- /dev/null
+++ b/boot/1.1/default/BootControl.cpp
@@ -0,0 +1,129 @@
+/*
+ * 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 "android.hardware.boot@1.1-impl"
+
+#include <memory>
+
+#include <log/log.h>
+
+#include "BootControl.h"
+
+namespace android {
+namespace hardware {
+namespace boot {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::boot::V1_0::CommandResult;
+
+bool BootControl::Init() {
+    return impl_.Init();
+}
+
+// Methods from ::android::hardware::boot::V1_0::IBootControl follow.
+Return<uint32_t> BootControl::getNumberSlots() {
+    return impl_.GetNumberSlots();
+}
+
+Return<uint32_t> BootControl::getCurrentSlot() {
+    return impl_.GetCurrentSlot();
+}
+
+Return<void> BootControl::markBootSuccessful(markBootSuccessful_cb _hidl_cb) {
+    struct CommandResult cr;
+    if (impl_.MarkBootSuccessful()) {
+        cr.success = true;
+        cr.errMsg = "Success";
+    } else {
+        cr.success = false;
+        cr.errMsg = "Operation failed";
+    }
+    _hidl_cb(cr);
+    return Void();
+}
+
+Return<void> BootControl::setActiveBootSlot(uint32_t slot, setActiveBootSlot_cb _hidl_cb) {
+    struct CommandResult cr;
+    if (impl_.SetActiveBootSlot(slot)) {
+        cr.success = true;
+        cr.errMsg = "Success";
+    } else {
+        cr.success = false;
+        cr.errMsg = "Operation failed";
+    }
+    _hidl_cb(cr);
+    return Void();
+}
+
+Return<void> BootControl::setSlotAsUnbootable(uint32_t slot, setSlotAsUnbootable_cb _hidl_cb) {
+    struct CommandResult cr;
+    if (impl_.SetSlotAsUnbootable(slot)) {
+        cr.success = true;
+        cr.errMsg = "Success";
+    } else {
+        cr.success = false;
+        cr.errMsg = "Operation failed";
+    }
+    _hidl_cb(cr);
+    return Void();
+}
+
+Return<BoolResult> BootControl::isSlotBootable(uint32_t slot) {
+    if (!impl_.IsValidSlot(slot)) {
+        return BoolResult::INVALID_SLOT;
+    }
+    return impl_.IsSlotBootable(slot) ? BoolResult::TRUE : BoolResult::FALSE;
+}
+
+Return<BoolResult> BootControl::isSlotMarkedSuccessful(uint32_t slot) {
+    if (!impl_.IsValidSlot(slot)) {
+        return BoolResult::INVALID_SLOT;
+    }
+    return impl_.IsSlotMarkedSuccessful(slot) ? BoolResult::TRUE : BoolResult::FALSE;
+}
+
+Return<void> BootControl::getSuffix(uint32_t slot, getSuffix_cb _hidl_cb) {
+    hidl_string ans;
+    const char* suffix = impl_.GetSuffix(slot);
+    if (suffix) {
+        ans = suffix;
+    }
+    _hidl_cb(ans);
+    return Void();
+}
+
+Return<bool> BootControl::setSnapshotMergeStatus(MergeStatus status) {
+    return impl_.SetSnapshotMergeStatus(status);
+}
+
+Return<MergeStatus> BootControl::getSnapshotMergeStatus() {
+    return impl_.GetSnapshotMergeStatus();
+}
+
+IBootControl* HIDL_FETCH_IBootControl(const char* /* hal */) {
+    auto module = std::make_unique<BootControl>();
+    if (!module->Init()) {
+        ALOGE("Could not initialize BootControl module");
+        return nullptr;
+    }
+    return module.release();
+}
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace boot
+}  // namespace hardware
+}  // namespace android
diff --git a/boot/1.1/default/BootControl.h b/boot/1.1/default/BootControl.h
new file mode 100644
index 0000000..75511b6
--- /dev/null
+++ b/boot/1.1/default/BootControl.h
@@ -0,0 +1,64 @@
+/*
+ * 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/boot/1.1/IBootControl.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <libboot_control/libboot_control.h>
+
+namespace android {
+namespace hardware {
+namespace boot {
+namespace V1_1 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::boot::V1_0::BoolResult;
+using ::android::hardware::boot::V1_1::IBootControl;
+using ::android::hardware::boot::V1_1::MergeStatus;
+
+class BootControl : public IBootControl {
+  public:
+    bool Init();
+
+    // Methods from ::android::hardware::boot::V1_0::IBootControl follow.
+    Return<uint32_t> getNumberSlots() override;
+    Return<uint32_t> getCurrentSlot() override;
+    Return<void> markBootSuccessful(markBootSuccessful_cb _hidl_cb) override;
+    Return<void> setActiveBootSlot(uint32_t slot, setActiveBootSlot_cb _hidl_cb) override;
+    Return<void> setSlotAsUnbootable(uint32_t slot, setSlotAsUnbootable_cb _hidl_cb) override;
+    Return<BoolResult> isSlotBootable(uint32_t slot) override;
+    Return<BoolResult> isSlotMarkedSuccessful(uint32_t slot) override;
+    Return<void> getSuffix(uint32_t slot, getSuffix_cb _hidl_cb) override;
+
+    // Methods from ::android::hardware::boot::V1_1::IBootControl follow.
+    Return<bool> setSnapshotMergeStatus(MergeStatus status) override;
+    Return<MergeStatus> getSnapshotMergeStatus() override;
+
+  private:
+    android::bootable::BootControl impl_;
+};
+
+extern "C" IBootControl* HIDL_FETCH_IBootControl(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_1
+}  // namespace boot
+}  // namespace hardware
+}  // namespace android
diff --git a/boot/1.1/default/android.hardware.boot@1.1-service.rc b/boot/1.1/default/android.hardware.boot@1.1-service.rc
new file mode 100644
index 0000000..83fa9d0
--- /dev/null
+++ b/boot/1.1/default/android.hardware.boot@1.1-service.rc
@@ -0,0 +1,6 @@
+service vendor.boot-hal-1-1 /vendor/bin/hw/android.hardware.boot@1.1-service
+    interface android.hardware.boot@1.0::IBootControl default
+    interface android.hardware.boot@1.1::IBootControl default
+    class early_hal
+    user root
+    group root
diff --git a/boot/1.1/default/service.cpp b/boot/1.1/default/service.cpp
new file mode 100644
index 0000000..b24b464
--- /dev/null
+++ b/boot/1.1/default/service.cpp
@@ -0,0 +1,26 @@
+/*
+ * 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 "android.hardware.boot@1.1-service"
+
+#include <android/hardware/boot/1.1/IBootControl.h>
+#include <hidl/LegacySupport.h>
+
+using android::hardware::defaultPassthroughServiceImplementation;
+using ::android::hardware::boot::V1_1::IBootControl;
+
+int main(int /* argc */, char* /* argv */[]) {
+    return defaultPassthroughServiceImplementation<IBootControl>();
+}
diff --git a/boot/1.1/types.hal b/boot/1.1/types.hal
new file mode 100644
index 0000000..6346078
--- /dev/null
+++ b/boot/1.1/types.hal
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+package android.hardware.boot@1.1;
+
+enum MergeStatus : int32_t {
+    /**
+     * No snapshot or merge is in progress.
+     */
+    NONE = 0,
+
+    /**
+     * The merge status could not be determined.
+     */
+    UNKNOWN,
+
+    /**
+     * Partitions are being snapshotted, but no merge has been started.
+     */
+    SNAPSHOTTED,
+
+    /**
+     * At least one partition has merge is in progress.
+     */
+    MERGING,
+
+    /**
+     * A merge was in progress, but it was canceled by the bootloader.
+     */
+    CANCELLED,
+};
diff --git a/boot/1.1/vts/functional/Android.bp b/boot/1.1/vts/functional/Android.bp
new file mode 100644
index 0000000..49ea09a
--- /dev/null
+++ b/boot/1.1/vts/functional/Android.bp
@@ -0,0 +1,28 @@
+//
+// 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: "VtsHalBootV1_1TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalBootV1_1TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.boot@1.0",
+        "android.hardware.boot@1.1",
+        "libgmock",
+    ],
+    test_suites: ["device-tests"],
+}
+
diff --git a/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp b/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp
new file mode 100644
index 0000000..fba9a5e
--- /dev/null
+++ b/boot/1.1/vts/functional/VtsHalBootV1_1TargetTest.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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 "boot_hidl_hal_test"
+
+#include <vector>
+
+#include <android-base/logging.h>
+#include <android/hardware/boot/1.1/IBootControl.h>
+#include <android/hardware/boot/1.1/types.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
+#include <unistd.h>
+
+using ::android::sp;
+using ::android::hardware::hidl_enum_range;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::boot::V1_1::IBootControl;
+using ::android::hardware::boot::V1_1::MergeStatus;
+using ::testing::Contains;
+
+class BootHidlTest : public testing::TestWithParam<std::string> {
+  public:
+    virtual void SetUp() override {
+        boot = IBootControl::getService(GetParam());
+        ASSERT_NE(boot, nullptr);
+
+        LOG(INFO) << "Test is remote " << boot->isRemote();
+    }
+
+    sp<IBootControl> boot;
+};
+
+static std::vector<MergeStatus> ValidMergeStatusValues() {
+    std::vector<MergeStatus> values;
+    for (const auto value : hidl_enum_range<MergeStatus>()) {
+        if (value == MergeStatus::UNKNOWN) {
+            continue;
+        }
+        values.push_back(value);
+    }
+    return values;
+}
+
+/**
+ * Ensure merge status can be retrieved.
+ */
+TEST_P(BootHidlTest, GetSnapshotMergeStatus) {
+    auto values = ValidMergeStatusValues();
+    auto status = (MergeStatus)boot->getSnapshotMergeStatus();
+    EXPECT_THAT(values, Contains(status));
+}
+
+/**
+ * Ensure merge status can be set to arbitrary value.
+ */
+TEST_P(BootHidlTest, SetSnapshotMergeStatus) {
+    for (const auto value : ValidMergeStatusValues()) {
+        EXPECT_TRUE(boot->setSnapshotMergeStatus(value).withDefault(false));
+        auto status = boot->getSnapshotMergeStatus();
+        EXPECT_EQ(status, value);
+    }
+}
+
+INSTANTIATE_TEST_SUITE_P(
+        , BootHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(IBootControl::descriptor)),
+        android::hardware::PrintInstanceNameToString);
diff --git a/broadcastradio/1.0/Android.bp b/broadcastradio/1.0/Android.bp
index 76e580e..8239d74 100644
--- a/broadcastradio/1.0/Android.bp
+++ b/broadcastradio/1.0/Android.bp
@@ -18,4 +18,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/broadcastradio/1.0/default/Android.bp b/broadcastradio/1.0/default/Android.bp
index f961dfd..2c96e2a 100644
--- a/broadcastradio/1.0/default/Android.bp
+++ b/broadcastradio/1.0/default/Android.bp
@@ -31,7 +31,6 @@
     ],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "liblog",
         "libhardware",
diff --git a/broadcastradio/1.1/Android.bp b/broadcastradio/1.1/Android.bp
index 2186b9a..1cc9b62 100644
--- a/broadcastradio/1.1/Android.bp
+++ b/broadcastradio/1.1/Android.bp
@@ -19,4 +19,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/broadcastradio/1.1/default/Android.bp b/broadcastradio/1.1/default/Android.bp
index 52fb45b..3659cb9 100644
--- a/broadcastradio/1.1/default/Android.bp
+++ b/broadcastradio/1.1/default/Android.bp
@@ -41,7 +41,6 @@
         "android.hardware.broadcastradio@1.1",
         "libbase",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
     ],
diff --git a/broadcastradio/1.1/default/android.hardware.broadcastradio@1.1-service.rc b/broadcastradio/1.1/default/android.hardware.broadcastradio@1.1-service.rc
index 7c57135..6fcbfa6 100644
--- a/broadcastradio/1.1/default/android.hardware.broadcastradio@1.1-service.rc
+++ b/broadcastradio/1.1/default/android.hardware.broadcastradio@1.1-service.rc
@@ -1,4 +1,6 @@
 service broadcastradio-hal /vendor/bin/hw/android.hardware.broadcastradio@1.1-service
+    interface android.hardware.broadcastradio@1.0::IBroadcastRadioFactory default
+    interface android.hardware.broadcastradio@1.1::IBroadcastRadioFactory default
     class hal
     user audioserver
     group audio
diff --git a/broadcastradio/2.0/Android.bp b/broadcastradio/2.0/Android.bp
index 93afc02..1040ba1 100644
--- a/broadcastradio/2.0/Android.bp
+++ b/broadcastradio/2.0/Android.bp
@@ -19,4 +19,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/broadcastradio/2.0/default/Android.bp b/broadcastradio/2.0/default/Android.bp
index 840c4b8..83eedb1 100644
--- a/broadcastradio/2.0/default/Android.bp
+++ b/broadcastradio/2.0/default/Android.bp
@@ -42,7 +42,6 @@
         "android.hardware.broadcastradio@2.0",
         "libbase",
         "libhidlbase",
-        "libhidltransport",
         "libutils",
     ],
 }
diff --git a/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc
index 7d68b6c..dd8c9c6 100644
--- a/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc
+++ b/broadcastradio/2.0/default/android.hardware.broadcastradio@2.0-service.rc
@@ -1,4 +1,5 @@
 service broadcastradio-hal2 /vendor/bin/hw/android.hardware.broadcastradio@2.0-service
+    interface android.hardware.broadcastradio@2.0::IBroadcastRadio default
     class hal
     user audioserver
     group audio
diff --git a/camera/common/1.0/Android.bp b/camera/common/1.0/Android.bp
index fe29774..ed64060 100644
--- a/camera/common/1.0/Android.bp
+++ b/camera/common/1.0/Android.bp
@@ -11,4 +11,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/camera/device/1.0/Android.bp b/camera/device/1.0/Android.bp
index a8df1ec..668884d 100644
--- a/camera/device/1.0/Android.bp
+++ b/camera/device/1.0/Android.bp
@@ -19,4 +19,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/camera/device/1.0/default/Android.bp b/camera/device/1.0/default/Android.bp
index aa3b941..97d0b5f 100644
--- a/camera/device/1.0/default/Android.bp
+++ b/camera/device/1.0/default/Android.bp
@@ -8,8 +8,6 @@
     shared_libs: [
         "libhidlbase",
         "libhidlmemory",
-        "libhidltransport",
-        "libhwbinder",
         "libutils",
         "android.hardware.camera.device@1.0",
         "android.hardware.camera.common@1.0",
diff --git a/camera/device/3.2/Android.bp b/camera/device/3.2/Android.bp
index e7546de..2e5349f 100644
--- a/camera/device/3.2/Android.bp
+++ b/camera/device/3.2/Android.bp
@@ -19,4 +19,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/camera/device/3.2/default/Android.bp b/camera/device/3.2/default/Android.bp
index edb008e..e4d9e85 100644
--- a/camera/device/3.2/default/Android.bp
+++ b/camera/device/3.2/default/Android.bp
@@ -7,7 +7,6 @@
            "convert.cpp"],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "libcutils",
         "android.hardware.camera.device@3.2",
diff --git a/camera/device/3.3/Android.bp b/camera/device/3.3/Android.bp
index e21824f..679fad6 100644
--- a/camera/device/3.3/Android.bp
+++ b/camera/device/3.3/Android.bp
@@ -18,4 +18,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/camera/device/3.3/default/Android.bp b/camera/device/3.3/default/Android.bp
index 39d379d..d964f3d 100644
--- a/camera/device/3.3/default/Android.bp
+++ b/camera/device/3.3/default/Android.bp
@@ -7,7 +7,6 @@
            "convert.cpp"],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "libcutils",
         "camera.device@3.2-impl",
diff --git a/camera/device/3.4/Android.bp b/camera/device/3.4/Android.bp
index 6a2eac5..e6f42d6 100644
--- a/camera/device/3.4/Android.bp
+++ b/camera/device/3.4/Android.bp
@@ -20,4 +20,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/camera/device/3.4/default/Android.bp b/camera/device/3.4/default/Android.bp
index c22b13c..71a9e77 100644
--- a/camera/device/3.4/default/Android.bp
+++ b/camera/device/3.4/default/Android.bp
@@ -38,7 +38,6 @@
     ],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "libcutils",
         "camera.device@3.2-impl",
@@ -75,7 +74,6 @@
     ],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "libcutils",
         "camera.device@3.2-impl",
diff --git a/camera/device/3.5/Android.bp b/camera/device/3.5/Android.bp
index d51fd0e..362a5e6 100644
--- a/camera/device/3.5/Android.bp
+++ b/camera/device/3.5/Android.bp
@@ -22,4 +22,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/camera/device/3.5/default/Android.bp b/camera/device/3.5/default/Android.bp
index 26b3b67..43362fd 100644
--- a/camera/device/3.5/default/Android.bp
+++ b/camera/device/3.5/default/Android.bp
@@ -37,7 +37,6 @@
     ],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "libcutils",
         "camera.device@3.2-impl",
@@ -71,7 +70,6 @@
     ],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "libcutils",
         "camera.device@3.2-impl",
diff --git a/camera/metadata/3.2/Android.bp b/camera/metadata/3.2/Android.bp
index 3271d91..f58fb28 100644
--- a/camera/metadata/3.2/Android.bp
+++ b/camera/metadata/3.2/Android.bp
@@ -11,4 +11,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/camera/metadata/3.3/Android.bp b/camera/metadata/3.3/Android.bp
index 4dddfad..885f4f9 100644
--- a/camera/metadata/3.3/Android.bp
+++ b/camera/metadata/3.3/Android.bp
@@ -14,4 +14,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/camera/metadata/3.4/Android.bp b/camera/metadata/3.4/Android.bp
index 2b75eba..6a92458 100644
--- a/camera/metadata/3.4/Android.bp
+++ b/camera/metadata/3.4/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/camera/provider/2.4/Android.bp b/camera/provider/2.4/Android.bp
index 63d7fd5..876814d 100644
--- a/camera/provider/2.4/Android.bp
+++ b/camera/provider/2.4/Android.bp
@@ -18,4 +18,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index cb78fcb..95e27fd 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -24,7 +24,6 @@
         "libcutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
     ],
@@ -63,7 +62,6 @@
         "libcutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libtinyxml2",
         "libutils",
@@ -108,7 +106,6 @@
         "libcutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libtinyxml2",
         "libutils",
@@ -146,7 +143,6 @@
         "libcamera_metadata",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
     ],
@@ -211,7 +207,6 @@
         "android.hardware.camera.provider@2.4",
         "libbinder",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libtinyxml2",
         "libutils",
diff --git a/camera/provider/2.5/Android.bp b/camera/provider/2.5/Android.bp
index a4af07e..4ca1efb 100644
--- a/camera/provider/2.5/Android.bp
+++ b/camera/provider/2.5/Android.bp
@@ -19,4 +19,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/camera/provider/2.5/default/Android.bp b/camera/provider/2.5/default/Android.bp
index cd1caeb..4563362 100644
--- a/camera/provider/2.5/default/Android.bp
+++ b/camera/provider/2.5/default/Android.bp
@@ -24,7 +24,6 @@
         "libcutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
     ],
@@ -64,7 +63,6 @@
         "libcutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libtinyxml2",
         "libutils",
@@ -103,7 +101,6 @@
         "libcamera_metadata",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
     ],
@@ -170,7 +167,6 @@
         "android.hardware.graphics.mapper@2.0",
         "libbinder",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libtinyxml2",
         "libutils",
diff --git a/camera/provider/2.5/default/service.cpp b/camera/provider/2.5/default/service.cpp
index 604215d..ec30cbc 100644
--- a/camera/provider/2.5/default/service.cpp
+++ b/camera/provider/2.5/default/service.cpp
@@ -49,8 +49,8 @@
 
     status_t status;
     if (kLazyService) {
-        auto serviceRegistrar = std::make_shared<::android::hardware::LazyServiceRegistrar>();
-        status = serviceRegistrar->registerService(provider, "legacy/0");
+        auto serviceRegistrar = ::android::hardware::LazyServiceRegistrar::getInstance();
+        status = serviceRegistrar.registerService(provider, "legacy/0");
     } else {
         status = provider->registerAsService("legacy/0");
     }
diff --git a/cas/1.0/Android.bp b/cas/1.0/Android.bp
index 8d8e946..4982e20 100644
--- a/cas/1.0/Android.bp
+++ b/cas/1.0/Android.bp
@@ -18,4 +18,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/cas/1.0/default/Android.bp b/cas/1.0/default/Android.bp
index aa080f4..f9977ff 100644
--- a/cas/1.0/default/Android.bp
+++ b/cas/1.0/default/Android.bp
@@ -21,7 +21,6 @@
       "libbinder",
       "libhidlbase",
       "libhidlmemory",
-      "libhidltransport",
       "liblog",
       "libstagefright_foundation",
       "libutils",
diff --git a/cas/1.0/default/service.cpp b/cas/1.0/default/service.cpp
index 516acfb..754c0c5 100644
--- a/cas/1.0/default/service.cpp
+++ b/cas/1.0/default/service.cpp
@@ -46,8 +46,8 @@
     android::sp<IMediaCasService> service = new MediaCasService();
     android::status_t status;
     if (kLazyService) {
-        auto serviceRegistrar = std::make_shared<LazyServiceRegistrar>();
-        status = serviceRegistrar->registerService(service);
+        auto serviceRegistrar = LazyServiceRegistrar::getInstance();
+        status = serviceRegistrar.registerService(service);
     } else {
         status = service->registerAsService();
     }
diff --git a/cas/1.1/Android.bp b/cas/1.1/Android.bp
index bb0edb9..13217b6 100644
--- a/cas/1.1/Android.bp
+++ b/cas/1.1/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/cas/1.1/default/Android.bp b/cas/1.1/default/Android.bp
index 68a49cf..66a1eb8 100644
--- a/cas/1.1/default/Android.bp
+++ b/cas/1.1/default/Android.bp
@@ -22,7 +22,6 @@
       "libbinder",
       "libhidlbase",
       "libhidlmemory",
-      "libhidltransport",
       "liblog",
       "libutils",
     ],
diff --git a/cas/1.1/default/service.cpp b/cas/1.1/default/service.cpp
index 9625303..bf0e159 100644
--- a/cas/1.1/default/service.cpp
+++ b/cas/1.1/default/service.cpp
@@ -46,8 +46,8 @@
     android::sp<IMediaCasService> service = new MediaCasService();
     android::status_t status;
     if (kLazyService) {
-        auto serviceRegistrar = std::make_shared<LazyServiceRegistrar>();
-        status = serviceRegistrar->registerService(service);
+        auto serviceRegistrar = LazyServiceRegistrar::getInstance();
+        status = serviceRegistrar.registerService(service);
     } else {
         status = service->registerAsService();
     }
diff --git a/cas/native/1.0/Android.bp b/cas/native/1.0/Android.bp
index 880eccd..633ceb9 100644
--- a/cas/native/1.0/Android.bp
+++ b/cas/native/1.0/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index 7a779b9..799ab07 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -75,3 +75,16 @@
         "kernel_config_q_4.19",
     ]
 }
+
+vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.current.xml",
+    stem: "compatibility_matrix.current.xml",
+    srcs: [
+        "compatibility_matrix.current.xml",
+    ],
+    kernel_configs: [
+        "kernel_config_current_4.9",
+        "kernel_config_current_4.14",
+        "kernel_config_current_4.19",
+    ]
+}
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index b0caa7c..7c7f87f 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -97,6 +97,7 @@
     framework_compatibility_matrix.2.xml \
     framework_compatibility_matrix.3.xml \
     framework_compatibility_matrix.4.xml \
+    framework_compatibility_matrix.current.xml \
     framework_compatibility_matrix.device.xml \
 
 my_framework_matrix_deps += \
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
new file mode 100644
index 0000000..82bb941
--- /dev/null
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -0,0 +1,516 @@
+<compatibility-matrix version="1.0" type="framework" level="5">
+    <hal format="hidl" optional="true">
+        <name>android.hardware.atrace</name>
+        <version>1.0</version>
+        <interface>
+            <name>IAtraceDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.audio</name>
+        <version>5.0</version>
+        <interface>
+            <name>IDevicesFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.audio.effect</name>
+        <version>5.0</version>
+        <interface>
+            <name>IEffectsFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.authsecret</name>
+        <version>1.0</version>
+        <interface>
+            <name>IAuthSecret</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.audiocontrol</name>
+        <version>1.0</version>
+        <interface>
+            <name>IAudioControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.evs</name>
+        <version>1.0</version>
+        <interface>
+            <name>IEvsEnumerator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.automotive.vehicle</name>
+        <version>2.0</version>
+        <interface>
+            <name>IVehicle</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.biometrics.face</name>
+        <version>1.0</version>
+        <interface>
+            <name>IBiometricsFace</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.biometrics.fingerprint</name>
+        <version>2.1</version>
+        <interface>
+            <name>IBiometricsFingerprint</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.bluetooth</name>
+        <version>1.0</version>
+        <interface>
+            <name>IBluetoothHci</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.bluetooth.audio</name>
+        <version>2.0</version>
+        <interface>
+            <name>IBluetoothAudioProvidersFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.boot</name>
+        <version>1.1</version>
+        <interface>
+            <name>IBootControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.broadcastradio</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IBroadcastRadioFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.broadcastradio</name>
+        <version>2.0</version>
+        <interface>
+            <name>IBroadcastRadio</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.camera.provider</name>
+        <version>2.4-5</version>
+        <interface>
+            <name>ICameraProvider</name>
+            <regex-instance>[^/]+/[0-9]+</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.cas</name>
+        <version>1.1</version>
+        <interface>
+            <name>IMediaCasService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.configstore</name>
+        <version>1.1</version>
+        <interface>
+            <name>ISurfaceFlingerConfigs</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.confirmationui</name>
+        <version>1.0</version>
+        <interface>
+            <name>IConfirmationUI</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.contexthub</name>
+        <version>1.0</version>
+        <interface>
+            <name>IContexthub</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.drm</name>
+        <version>1.0-2</version>
+        <interface>
+            <name>ICryptoFactory</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+        <interface>
+            <name>IDrmFactory</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.dumpstate</name>
+        <version>1.0</version>
+        <interface>
+            <name>IDumpstateDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.gatekeeper</name>
+        <version>1.0</version>
+        <interface>
+            <name>IGatekeeper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.gnss</name>
+        <!--
+         - Both versions are listed here as a workaround for libvintf since 2.0 extends 1.1.
+         - Devices launched with Q must support gnss@2.0, see VtsTrebleVendorVintfTest
+         - test DeviceManifestTest#GnssHalVersionCompatibility.
+        -->
+        <version>1.1</version>
+        <version>2.0</version>
+        <interface>
+            <name>IGnss</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.allocator</name>
+        <version>2.0</version>
+        <version>3.0</version>
+        <interface>
+            <name>IAllocator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.composer</name>
+        <version>2.1-3</version>
+        <interface>
+            <name>IComposer</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.mapper</name>
+        <version>2.1</version>
+        <version>3.0</version>
+        <interface>
+            <name>IMapper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.health</name>
+        <version>2.0</version>
+        <interface>
+            <name>IHealth</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.health.storage</name>
+        <version>1.0</version>
+        <interface>
+            <name>IStorage</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.ir</name>
+        <version>1.0</version>
+        <interface>
+            <name>IConsumerIr</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.input.classifier</name>
+        <version>1.0</version>
+        <interface>
+            <name>IInputClassifier</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.keymaster</name>
+        <version>3.0</version>
+        <version>4.0</version>
+        <interface>
+            <name>IKeymasterDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.keymaster</name>
+        <version>4.0</version>
+        <interface>
+            <name>IKeymasterDevice</name>
+            <instance>strongbox</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.light</name>
+        <version>2.0</version>
+        <interface>
+            <name>ILight</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.media.c2</name>
+        <version>1.0</version>
+        <interface>
+            <name>IComponentStore</name>
+            <regex-instance>default[0-9]*</regex-instance>
+            <regex-instance>vendor[0-9]*_software</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.media.omx</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOmx</name>
+            <instance>default</instance>
+        </interface>
+        <interface>
+            <name>IOmxStore</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.memtrack</name>
+        <version>1.0</version>
+        <interface>
+            <name>IMemtrack</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.neuralnetworks</name>
+        <version>1.0-2</version>
+        <interface>
+            <name>IDevice</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.nfc</name>
+        <version>1.2</version>
+        <interface>
+            <name>INfc</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.oemlock</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOemLock</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.power</name>
+        <version>1.0-3</version>
+        <interface>
+            <name>IPower</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.power.stats</name>
+        <version>1.0</version>
+        <interface>
+            <name>IPowerStats</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.radio</name>
+        <version>1.4</version>
+        <interface>
+            <name>IRadio</name>
+            <instance>slot1</instance>
+            <instance>slot2</instance>
+            <instance>slot3</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.radio</name>
+        <version>1.2</version>
+        <interface>
+            <name>ISap</name>
+            <instance>slot1</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.radio.config</name>
+        <!--
+        See compatibility_matrix.4.xml on versioning of radio config HAL.
+        -->
+        <version>1.1</version>
+        <interface>
+            <name>IRadioConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.renderscript</name>
+        <version>1.0</version>
+        <interface>
+            <name>IDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.secure_element</name>
+        <version>1.0</version>
+        <interface>
+            <name>ISecureElement</name>
+            <regex-instance>eSE[1-9][0-9]*</regex-instance>
+            <regex-instance>SIM[1-9][0-9]*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.sensors</name>
+        <version>1.0</version>
+        <version>2.0</version>
+        <interface>
+            <name>ISensors</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.soundtrigger</name>
+        <version>2.0-2</version>
+        <interface>
+            <name>ISoundTriggerHw</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.config</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadConfig</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.control</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffloadControl</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.thermal</name>
+        <version>1.0</version>
+        <version>2.0</version>
+        <interface>
+            <name>IThermal</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tv.cec</name>
+        <version>1.0</version>
+        <interface>
+            <name>IHdmiCec</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tv.input</name>
+        <version>1.0</version>
+        <interface>
+            <name>ITvInput</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.usb</name>
+        <version>1.0-2</version>
+        <interface>
+            <name>IUsb</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.usb.gadget</name>
+        <version>1.0</version>
+        <interface>
+            <name>IUsbGadget</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.vibrator</name>
+        <version>1.0-3</version>
+        <interface>
+            <name>IVibrator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.vr</name>
+        <version>1.0</version>
+        <interface>
+            <name>IVr</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.weaver</name>
+        <version>1.0</version>
+        <interface>
+            <name>IWeaver</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi</name>
+        <version>1.0-3</version>
+        <interface>
+            <name>IWifi</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.hostapd</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>IHostapd</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.supplicant</name>
+        <version>1.0-2</version>
+        <interface>
+            <name>ISupplicant</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</compatibility-matrix>
diff --git a/configstore/1.0/Android.bp b/configstore/1.0/Android.bp
index a6fd656..d92f252 100644
--- a/configstore/1.0/Android.bp
+++ b/configstore/1.0/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/configstore/1.1/Android.bp b/configstore/1.1/Android.bp
index 3900d9b..7c5f3f7 100644
--- a/configstore/1.1/Android.bp
+++ b/configstore/1.1/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/configstore/1.1/default/Android.mk b/configstore/1.1/default/Android.mk
index 104e15e..e7edc34 100644
--- a/configstore/1.1/default/Android.mk
+++ b/configstore/1.1/default/Android.mk
@@ -17,7 +17,6 @@
 
 LOCAL_SHARED_LIBRARIES := \
     libhidlbase \
-    libhidltransport \
     libbase \
     libhwminijail \
     liblog \
diff --git a/configstore/1.1/default/android.hardware.configstore@1.1-service.rc b/configstore/1.1/default/android.hardware.configstore@1.1-service.rc
index 105678a..d62c4a8 100644
--- a/configstore/1.1/default/android.hardware.configstore@1.1-service.rc
+++ b/configstore/1.1/default/android.hardware.configstore@1.1-service.rc
@@ -1,4 +1,6 @@
 service vendor.configstore-hal /vendor/bin/hw/android.hardware.configstore@1.1-service
+    interface android.hardware.configstore@1.0::ISurfaceFlingerConfigs default
+    interface android.hardware.configstore@1.1::ISurfaceFlingerConfigs default
     class hal animation
     user system
     group system
diff --git a/confirmationui/1.0/Android.bp b/confirmationui/1.0/Android.bp
index e6b0414..a22067a 100644
--- a/confirmationui/1.0/Android.bp
+++ b/confirmationui/1.0/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/confirmationui/1.0/default/Android.bp b/confirmationui/1.0/default/Android.bp
index 10018e8..ecba064 100644
--- a/confirmationui/1.0/default/Android.bp
+++ b/confirmationui/1.0/default/Android.bp
@@ -36,7 +36,6 @@
         "libcrypto",
         "libbase",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
     ],
diff --git a/confirmationui/1.0/default/android.hardware.confirmationui@1.0-service.rc b/confirmationui/1.0/default/android.hardware.confirmationui@1.0-service.rc
index c04e55e..adc7222 100644
--- a/confirmationui/1.0/default/android.hardware.confirmationui@1.0-service.rc
+++ b/confirmationui/1.0/default/android.hardware.confirmationui@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.confirmationui-1-0 /vendor/bin/hw/android.hardware.confirmationui@1.0-service
+    interface android.hardware.confirmationui@1.0::IConfirmationUI default
     class hal
     user nobody
     group drmrpc
diff --git a/confirmationui/1.0/vts/functional/Android.bp b/confirmationui/1.0/vts/functional/Android.bp
index d19d702..fd088cd 100644
--- a/confirmationui/1.0/vts/functional/Android.bp
+++ b/confirmationui/1.0/vts/functional/Android.bp
@@ -23,7 +23,7 @@
     static_libs: [
         "android.hardware.confirmationui@1.0",
         "android.hardware.keymaster@4.0",
-        "libcrypto",
+        "libcrypto_static",
         "libcn-cbor",
         "android.hardware.confirmationui-support-lib",
     ],
diff --git a/confirmationui/support/include/ConfirmationUITranslations.h b/confirmationui/support/include/ConfirmationUITranslations.h
new file mode 100644
index 0000000..a55dc08
--- /dev/null
+++ b/confirmationui/support/include/ConfirmationUITranslations.h
@@ -0,0 +1,27 @@
+/*
+**
+** 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.
+*/
+
+/* Generated by generate-translations.py - DO NOT EDIT */
+
+#ifndef ConfirmationUITranslations_H
+#define ConfirmationUITranslations_H
+
+const char* ConfirmationUITranslations_select_lang_id(const char* lang_id);
+
+const char* ConfirmationUITranslations_lookup(const char* translation_id);
+
+#endif // ConfirmationUITranslations_H
diff --git a/confirmationui/support/src/ConfirmationUITranslations.c b/confirmationui/support/src/ConfirmationUITranslations.c
new file mode 100644
index 0000000..4d616ae
--- /dev/null
+++ b/confirmationui/support/src/ConfirmationUITranslations.c
@@ -0,0 +1,1158 @@
+/*
+**
+** 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.
+*/
+
+/* Generated by generate-translations.py - DO NOT EDIT */
+
+#include "ConfirmationUITranslations.h"
+#include "string.h"
+
+static const char* ConfirmationUITranslations_language_ids[] = {
+  "en", /* untranslated */
+  "af",
+  "am",
+  "ar",
+  "ar-EG",
+  "ar-JO",
+  "ar-MA",
+  "ar-SA",
+  "ar-XB",
+  "as",
+  "az",
+  "be",
+  "bg",
+  "bn",
+  "bs",
+  "ca",
+  "cs",
+  "da",
+  "de",
+  "de-AT",
+  "de-CH",
+  "el",
+  "en-AU",
+  "en-CA",
+  "en-GB",
+  "en-IE",
+  "en-IN",
+  "en-SG",
+  "en-XA",
+  "en-XC",
+  "en-ZA",
+  "es",
+  "es-419",
+  "es-AR",
+  "es-BO",
+  "es-CL",
+  "es-CO",
+  "es-CR",
+  "es-DO",
+  "es-EC",
+  "es-GT",
+  "es-HN",
+  "es-MX",
+  "es-NI",
+  "es-PA",
+  "es-PE",
+  "es-PR",
+  "es-PY",
+  "es-SV",
+  "es-US",
+  "es-UY",
+  "es-VE",
+  "et",
+  "eu",
+  "fa",
+  "fi",
+  "fil",
+  "fr",
+  "fr-CA",
+  "fr-CH",
+  "gl",
+  "gsw",
+  "gu",
+  "he",
+  "hi",
+  "hr",
+  "hu",
+  "hy",
+  "id",
+  "in",
+  "is",
+  "it",
+  "iw",
+  "ja",
+  "ka",
+  "kk",
+  "km",
+  "kn",
+  "ko",
+  "ky",
+  "ln",
+  "lo",
+  "lt",
+  "lv",
+  "mk",
+  "ml",
+  "mn",
+  "mo",
+  "mr",
+  "ms",
+  "my",
+  "nb",
+  "ne",
+  "nl",
+  "no",
+  "or",
+  "pa",
+  "pl",
+  "pt",
+  "pt-BR",
+  "pt-PT",
+  "ro",
+  "ru",
+  "si",
+  "sk",
+  "sl",
+  "sq",
+  "sr",
+  "sr-Latn",
+  "sv",
+  "sw",
+  "ta",
+  "te",
+  "th",
+  "tl",
+  "tr",
+  "uk",
+  "ur",
+  "uz",
+  "vi",
+  "zh",
+  "zh-CN",
+  "zh-HK",
+  "zh-TW",
+  "zu",
+  NULL,
+};
+
+#define ARRAY_ELEMENTS(arr) \
+    (sizeof(arr)/sizeof(arr[0]))
+
+#define ConfirmationUITranslations_NUM_LANGUAGE_IDS \
+    (ARRAY_ELEMENTS(ConfirmationUITranslations_language_ids) - 1)
+
+static const struct {
+  const char* translation_id;
+  const char* translations[ConfirmationUITranslations_NUM_LANGUAGE_IDS];
+} ConfirmationUITranslations_translation_ids[] = {
+  {
+    "1424834532030812203",
+    {
+      "Double-press power to confirm", /* en (untranslated) */
+      "Dubbeldruk aan/af-skakelaar om te bevestig", /* af */
+      "ለማረጋገጥ ኃይልን ሁለቴ ይጫኑ", /* am */
+      "اضغط على زر التشغيل مرتين لتأكيد الإجراء.", /* ar */
+      "اضغط على زر التشغيل مرتين لتأكيد الإجراء.", /* ar-EG */
+      "اضغط على زر التشغيل مرتين لتأكيد الإجراء.", /* ar-JO */
+      "اضغط على زر التشغيل مرتين لتأكيد الإجراء.", /* ar-MA */
+      "اضغط على زر التشغيل مرتين لتأكيد الإجراء.", /* ar-SA */
+      "‏‮Double‬‏-‏‮press‬‏ ‏‮power‬‏ ‏‮to‬‏ ‏‮confirm‬‏", /* ar-XB */
+      "নিশ্চিত কৰিবলৈ পাৱাৰ বুটামটো দুবাৰ হেঁচক", /* as */
+      "Təsdiqləmək üçün iki dəfə yandırıb-söndürmək düyməsinə basın", /* az */
+      "Двойчы націсніце кнопку сілкавання, каб пацвердзіць", /* be */
+      "Натиснете два пъти бутона за захранване, за да потвърдите", /* bg */
+      "নিশ্চিত করতে পাওয়ার বোতাম দুবার টিপুন", /* bn */
+      "Dva puta pritisnite dugme za napajanje da potvrdite", /* bs */
+      "Prem dos cops el botó d'engegada per confirmar", /* ca */
+      "Potvrďte dvojitým stisknutím vypínače", /* cs */
+      "Tryk to gange på afbryderknappen for at bekræfte", /* da */
+      "Zum Bestätigen die Ein-/Aus-Taste zweimal drücken", /* de */
+      "Zum Bestätigen die Ein-/Aus-Taste zweimal drücken", /* de-AT */
+      "Zum Bestätigen die Ein-/Aus-Taste zweimal drücken", /* de-CH */
+      "Πατήστε δύο φορές το κουμπί λειτουργίας για επιβεβαίωση", /* el */
+      "Double-press power to confirm", /* en-AU */
+      "Double-press power to confirm", /* en-CA */
+      "Double-press power to confirm", /* en-GB */
+      "Double-press power to confirm", /* en-IE */
+      "Double-press power to confirm", /* en-IN */
+      "Double-press power to confirm", /* en-SG */
+      "[Ðöûбļé-þŕéšš þöŵéŕ ţö çöñƒîŕm one two three four five six seven]", /* en-XA */
+      "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎‎‎‏‏‏‎‏‏‏‎‏‎‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎‎‎‎‎‏‎‎‎‎‎‎‏‎‏‎‏‏‎Double-press power to confirm‎‏‎‎‏‎", /* en-XC */
+      "Double-press power to confirm", /* en-ZA */
+      "Pulsa dos veces el botón de encendido para confirmar", /* es */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-419 */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-AR */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-BO */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-CL */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-CO */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-CR */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-DO */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-EC */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-GT */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-HN */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-MX */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-NI */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-PA */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-PE */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-PR */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-PY */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-SV */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-US */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-UY */
+      "Presiona dos veces el botón de encendido para confirmar", /* es-VE */
+      "Kinnitamiseks topeltvajutage toitenuppu", /* et */
+      "Berresteko, sakatu birritan pizteko botoia", /* eu */
+      "برای تأیید، دکمه روشن/خاموش را دوبار فشار دهید", /* fa */
+      "Vahvista painamalla virtapainiketta kahdesti", /* fi */
+      "Pindutin nang dalawang beses ang power para kumpirmahin", /* fil */
+      "Appuyez deux fois sur le bouton Marche/Arrêt pour confirmer l'opération", /* fr */
+      "Appuyez deux fois sur l'interrupteur pour confirmer", /* fr-CA */
+      "Appuyez deux fois sur le bouton Marche/Arrêt pour confirmer l'opération", /* fr-CH */
+      "Preme o botón de acendido dúas veces para confirmar", /* gl */
+      "Zum Bestätigen die Ein-/Aus-Taste zweimal drücken", /* gsw */
+      "કન્ફર્મ કરવા માટે પાવર પર બે વાર ટૅપ કરો", /* gu */
+      "יש ללחוץ פעמיים על לחצן ההפעלה כדי לאשר", /* he */
+      "पुष्टि करने के लिए पावर बटन दो बार दबाएं", /* hi */
+      "Dvaput pritisnite tipku za uključivanje/isključivanje da biste potvrdili", /* hr */
+      "A megerősítéshez nyomja meg duplán a bekapcsológombot", /* hu */
+      "Հաստատելու համար կրկնակի սեղմեք սնուցման կոճակը", /* hy */
+      "Tekan dua kali tombol power untuk mengonfirmasi", /* id */
+      "Tekan dua kali tombol power untuk mengonfirmasi", /* in */
+      "Ýttu tvisvar á aflrofann til að staðfesta", /* is */
+      "Premi due volte il tasto di accensione per confermare", /* it */
+      "יש ללחוץ פעמיים על לחצן ההפעלה כדי לאשר", /* iw */
+      "確認するには、電源を 2 回押します", /* ja */
+      "დასადასტურებლად ორმაგად დააჭირეთ ჩართვის ღილაკს", /* ka */
+      "Растау үшін қуат түймесін екі рет басыңыз", /* kk */
+      "ចុច​ប៊ូតុង​ថាមពល​ពីរដង​ដើម្បី​បញ្ជាក់", /* km */
+      "ದೃಢೀಕರಿಸಲು ಪವರ್‌ ಬಟನ್‌ ಅನ್ನು ಎರಡು ಬಾರಿ ಒತ್ತಿರಿ", /* kn */
+      "확인하려면 전원 버튼을 두 번 누르세요.", /* ko */
+      "Ырастоо үчүн \"Кубат\" баскычын эки жолу басыңыз", /* ky */
+      "Appuyez deux fois sur le bouton Marche/Arrêt pour confirmer l'opération", /* ln */
+      "ກົດປຸ່ມປິດເປີດເຄື່ອງສອງຄັ້ງເພື່ອຢືນຢັນ", /* lo */
+      "Dukart paspauskite maitinimo mygtuką, kad patvirtintumėte", /* lt */
+      "Lai apstiprinātu, divreiz nospiediet barošanas pogu", /* lv */
+      "Притиснете на копчето за напојување двапати за да потврдите", /* mk */
+      "സ്ഥിരീകരിക്കാൻ പവർ രണ്ടുതവണ അമർത്തുക", /* ml */
+      "Баталгаажуулахын тулд унтраах/асаахыг хоёр удаа дарах", /* mn */
+      "Apăsați de două ori butonul de pornire pentru a confirma", /* mo */
+      "खात्री करण्‍यासाठी पॉवर बटण दोनदा दाबा", /* mr */
+      "Tekan dua kali butang kuasa untuk mengesahkan", /* ms */
+      "အတည်ပြုရန် ပါဝါခလုတ်ကို နှစ်ချက်နှိပ်ပါ", /* my */
+      "Dobbelttrykk på av/på-knappen for å bekrefte", /* nb */
+      "पुष्टि गर्न पावर बटनमा दुई पटक थिच्नुहोस्", /* ne */
+      "Druk twee keer op de aan/uit-knop om te bevestigen", /* nl */
+      "Dobbelttrykk på av/på-knappen for å bekrefte", /* no */
+      "ସୁନିଶ୍ଚିତ କରିବା ପାଇଁ ପାୱାର୍‍ ବଟନ୍‍କୁ ଦୁଇଥର ଦବାନ୍ତୁ", /* or */
+      "ਪੁਸ਼ਟੀ ਕਰਨ ਲਈ ਪਾਵਰ ਬਟਨ ਨੂੰ ਦੋ ਬਾਰ ਦੱਬੋ", /* pa */
+      "Kliknij dwukrotnie przycisk zasilania, by potwierdzić", /* pl */
+      "Pressione o botão liga/desliga duas vezes para confirmar", /* pt */
+      "Pressione o botão liga/desliga duas vezes para confirmar", /* pt-BR */
+      "Prima duas vezes ligar/desligar para confirmar.", /* pt-PT */
+      "Apăsați de două ori butonul de pornire pentru a confirma", /* ro */
+      "Для подтверждения дважды нажмите кнопку питания.", /* ru */
+      "තහවුරු කිරීමට බල බොත්තම දෙවරක් ඔබන්න", /* si */
+      "Potvrďte dvojitým stlačením vypínača", /* sk */
+      "Dvakrat pritisnite za potrditev", /* sl */
+      "Shtyp dy herë butonin e energjisë për të konfirmuar", /* sq */
+      "Двапут притисните дугме за напајање да бисте потврдили", /* sr */
+      "Dvaput pritisnite dugme za napajanje da biste potvrdili", /* sr-Latn */
+      "Bekräfta genom att trycka två gånger på avstängningsknappen", /* sv */
+      "Bonyeza kitufe cha kuwasha mara mbili ili uthibitishe", /* sw */
+      "உறுதிப்படுத்த, பவர் பட்டனை இருமுறை அழுத்தவும்", /* ta */
+      "నిర్ధారించడానికి పవర్ బటన్‌ని రెండు సార్లు నొక్కండి", /* te */
+      "กดปุ่มเปิด/ปิด 2 ครั้งเพื่อยืนยัน", /* th */
+      "Pindutin nang dalawang beses ang power para kumpirmahin", /* tl */
+      "Onaylamak için güç düğmesine iki kez basın", /* tr */
+      "Двічі натисніть кнопку живлення, щоб підтвердити", /* uk */
+      "تصدیق کرنے کے لئے پاور بٹن دوبار دبائیں", /* ur */
+      "Tasdiqlash uchun quvvat tugmasini ikki marta bosing", /* uz */
+      "Nhấn hai lần vào nút nguồn để xác nhận", /* vi */
+      "连按两次电源按钮即可确认", /* zh */
+      "连按两次电源按钮即可确认", /* zh-CN */
+      "按兩下電源按鈕即可確認", /* zh-HK */
+      "按兩下電源按鈕即可確認操作", /* zh-TW */
+      "Cindezela kabili ukuze uqinisekise", /* zu */
+    }
+  },
+  {
+    "1796282799666106567",
+    {
+      "Cancel", /* en (untranslated) */
+      "Kanselleer", /* af */
+      "ይቅር", /* am */
+      "إلغاء", /* ar */
+      "إلغاء", /* ar-EG */
+      "إلغاء", /* ar-JO */
+      "إلغاء", /* ar-MA */
+      "إلغاء", /* ar-SA */
+      "‏‮Cancel‬‏", /* ar-XB */
+      "বাতিল কৰক", /* as */
+      "Ləğv edin", /* az */
+      "Скасаваць", /* be */
+      "Отказ", /* bg */
+      "বাতিল করুন", /* bn */
+      "Otkaži", /* bs */
+      "Cancel·la", /* ca */
+      "Zrušit", /* cs */
+      "Annuller", /* da */
+      "Abbrechen", /* de */
+      "Abbrechen", /* de-AT */
+      "Abbrechen", /* de-CH */
+      "Ακύρωση", /* el */
+      "Cancel", /* en-AU */
+      "Cancel", /* en-CA */
+      "Cancel", /* en-GB */
+      "Cancel", /* en-IE */
+      "Cancel", /* en-IN */
+      "Cancel", /* en-SG */
+      "[Çåñçéļ one]", /* en-XA */
+      "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‏‏‏‏‏‎‎‎‎‏‎‎‎‎‏‏‎‎‎‏‏‏‎Cancel‎‏‎‎‏‎", /* en-XC */
+      "Cancel", /* en-ZA */
+      "Cancelar", /* es */
+      "Cancelar", /* es-419 */
+      "Cancelar", /* es-AR */
+      "Cancelar", /* es-BO */
+      "Cancelar", /* es-CL */
+      "Cancelar", /* es-CO */
+      "Cancelar", /* es-CR */
+      "Cancelar", /* es-DO */
+      "Cancelar", /* es-EC */
+      "Cancelar", /* es-GT */
+      "Cancelar", /* es-HN */
+      "Cancelar", /* es-MX */
+      "Cancelar", /* es-NI */
+      "Cancelar", /* es-PA */
+      "Cancelar", /* es-PE */
+      "Cancelar", /* es-PR */
+      "Cancelar", /* es-PY */
+      "Cancelar", /* es-SV */
+      "Cancelar", /* es-US */
+      "Cancelar", /* es-UY */
+      "Cancelar", /* es-VE */
+      "Tühista", /* et */
+      "Utzi", /* eu */
+      "لغو", /* fa */
+      "Peruuta", /* fi */
+      "Kanselahin", /* fil */
+      "Annuler", /* fr */
+      "Annuler", /* fr-CA */
+      "Annuler", /* fr-CH */
+      "Cancelar", /* gl */
+      "Abbrechen", /* gsw */
+      "રદ કરો", /* gu */
+      "ביטול", /* he */
+      "रद्द करें", /* hi */
+      "Otkaži", /* hr */
+      "Mégse", /* hu */
+      "Չեղարկել", /* hy */
+      "Batal", /* id */
+      "Batal", /* in */
+      "Hætta við", /* is */
+      "Annulla", /* it */
+      "ביטול", /* iw */
+      "キャンセル", /* ja */
+      "გაუქმება", /* ka */
+      "Бас тарту", /* kk */
+      "បោះបង់", /* km */
+      "ರದ್ದು", /* kn */
+      "취소", /* ko */
+      "Жокко чыгаруу", /* ky */
+      "Annuler", /* ln */
+      "ຍົກເລີກ", /* lo */
+      "Atšaukti", /* lt */
+      "Atcelt", /* lv */
+      "Откажи", /* mk */
+      "റദ്ദാക്കുക", /* ml */
+      "Болих", /* mn */
+      "Anulați", /* mo */
+      "रद्द करा", /* mr */
+      "Batal", /* ms */
+      "မလုပ်တော့", /* my */
+      "Avbryt", /* nb */
+      "रद्द गर्नुहोस्", /* ne */
+      "Annuleren", /* nl */
+      "Avbryt", /* no */
+      "କ୍ୟାନ୍ସଲ୍‍ କରନ୍ତୁ", /* or */
+      "ਰੱਦ ਕਰੋ", /* pa */
+      "Anuluj", /* pl */
+      "Cancelar", /* pt */
+      "Cancelar", /* pt-BR */
+      "Cancelar", /* pt-PT */
+      "Anulați", /* ro */
+      "Отмена", /* ru */
+      "අවලංගු කරන්න", /* si */
+      "Zrušiť", /* sk */
+      "Prekliči", /* sl */
+      "Anulo", /* sq */
+      "Откажи", /* sr */
+      "Otkaži", /* sr-Latn */
+      "Avbryt", /* sv */
+      "Ghairi", /* sw */
+      "ரத்துசெய்", /* ta */
+      "రద్దు చేయండి", /* te */
+      "ยกเลิก", /* th */
+      "Kanselahin", /* tl */
+      "İptal", /* tr */
+      "Скасувати", /* uk */
+      "منسوخ کریں", /* ur */
+      "Bekor qilish", /* uz */
+      "Hủy", /* vi */
+      "取消", /* zh */
+      "取消", /* zh-CN */
+      "取消", /* zh-HK */
+      "取消", /* zh-TW */
+      "Khansela", /* zu */
+    }
+  },
+  {
+    "217688588483778177",
+    {
+      "This confirmation provides an extra layer of security for the action you're about to take.", /* en (untranslated) */
+      "Hierdie bevestiging verskaf 'n ekstra laag sekuriteit vir die handeling wat jy op die punt is om uit te voer.", /* af */
+      "ይህ ማረጋገጫ እርስዎ ለሚወስዱት እርምጃ ተጨማሪ ትርፍ ጥበቃን ይሰጣል።", /* am */
+      "يتيح هذا التأكيد تفعيل طبقة أمان إضافية للإجراء الذي توشك على اتخاذه.", /* ar */
+      "يتيح هذا التأكيد تفعيل طبقة أمان إضافية للإجراء الذي توشك على اتخاذه.", /* ar-EG */
+      "يتيح هذا التأكيد تفعيل طبقة أمان إضافية للإجراء الذي توشك على اتخاذه.", /* ar-JO */
+      "يتيح هذا التأكيد تفعيل طبقة أمان إضافية للإجراء الذي توشك على اتخاذه.", /* ar-MA */
+      "يتيح هذا التأكيد تفعيل طبقة أمان إضافية للإجراء الذي توشك على اتخاذه.", /* ar-SA */
+      "‏‮This‬‏ ‏‮confirmation‬‏ ‏‮provides‬‏ ‏‮an‬‏ ‏‮extra‬‏ ‏‮layer‬‏ ‏‮of‬‏ ‏‮security‬‏ ‏‮for‬‏ ‏‮the‬‏ ‏‮action‬‏ ‏‮you‬‏'‏‮re‬‏ ‏‮about‬‏ ‏‮to‬‏ ‏‮take‬‏.", /* ar-XB */
+      "এই প্ৰতিশ্ৰুতিয়ে আপুনি কৰিব বিচৰা কোনো কাৰ্যৰ বাবে অতিৰিক্ত সুৰক্ষা প্ৰদান কৰে।", /* as */
+      "Bu təsdiq etmək üzrə olduğunuz əməliyyat üçün əlavə təhlükəsizlik qatı təmin edir.", /* az */
+      "Гэта пацвярджэнне забяспечвае дадатковы ўзровень бяспекі для дзеянняў, якія вы збіраецеся выконваць.", /* be */
+      "Това потвърждение осигурява допълнителна защита за действието, което сте напът да предприемете.", /* bg */
+      "আপনি যে কাজটি করতে চলেছেন, এই কনফার্মেশনের ফলে সেটির জন্য অতিরিক্ত সুরক্ষার ব্যবস্থা করা হয়।", /* bn */
+      "Ova potvrda pruža dodatni sloj zaštite za radnju koju namjeravate preduzeti.", /* bs */
+      "Aquesta confirmació proporciona una capa de seguretat addicional per a l'acció que estàs a punt de dur a terme.", /* ca */
+      "Toto potvrzení tvoří dodatečnou úroveň zabezpečení akce, kterou se chystáte podniknout.", /* cs */
+      "Denne bekræftelse giver et ekstra beskyttelsesniveau for den handling, du er ved at foretage.", /* da */
+      "Durch die Bestätigung wird bei der Aktion, die du durchführen möchtest, eine zusätzliche Sicherheitsmaßnahme angewandt.", /* de */
+      "Durch die Bestätigung wird bei der Aktion, die du durchführen möchtest, eine zusätzliche Sicherheitsmaßnahme angewandt.", /* de-AT */
+      "Durch die Bestätigung wird bei der Aktion, die du durchführen möchtest, eine zusätzliche Sicherheitsmassnahme angewandt.", /* de-CH */
+      "Αυτή η επιβεβαίωση παρέχει ένα επιπλέον επίπεδο ασφάλειας για την ενέργεια που πρόκειται να εκτελέσετε.", /* el */
+      "This confirmation provides an extra layer of security for the action that you're about to take.", /* en-AU */
+      "This confirmation provides an extra layer of security for the action that you're about to take.", /* en-CA */
+      "This confirmation provides an extra layer of security for the action that you're about to take.", /* en-GB */
+      "This confirmation provides an extra layer of security for the action that you're about to take.", /* en-IE */
+      "This confirmation provides an extra layer of security for the action that you're about to take.", /* en-IN */
+      "This confirmation provides an extra layer of security for the action that you're about to take.", /* en-SG */
+      "[Ţĥîš çöñƒîŕmåţîöñ þŕövîðéš åñ éxţŕå ļåýéŕ öƒ šéçûŕîţý ƒöŕ ţĥé åçţîöñ ýöû'ŕé åбöûţ ţö ţåķé. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen]", /* en-XA */
+      "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‏‎‎‎‏‎‏‎‎‏‏‏‏‎‎‎‏‎‏‏‎‎‎‎‏‏‏‎‏‏‎‏‎‏‎‏‏‎‏‎‎‎‎‎‎‏‎This confirmation provides an extra layer of security for the action you're about to take.‎‏‎‎‏‎", /* en-XC */
+      "This confirmation provides an extra layer of security for the action that you're about to take.", /* en-ZA */
+      "Esta confirmación proporciona una capa de seguridad adicional a la acción que vas a realizar.", /* es */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-419 */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-AR */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-BO */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-CL */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-CO */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-CR */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-DO */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-EC */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-GT */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-HN */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-MX */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-NI */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-PA */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-PE */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-PR */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-PY */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-SV */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-US */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-UY */
+      "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.", /* es-VE */
+      "See kinnitus annab veel ühe turvakihi toimingu puhul, mille nüüd teete.", /* et */
+      "Berrespen honek segurtasun handiagoa ematen dizu hurrengo ekintza gauzatzeko.", /* eu */
+      "این تأیید یک لایه امنیتی اضافی برای کنشی که می‌خواهید انجام دهید فراهم می‌کند.", /* fa */
+      "Tämä vahvistus tarkoittaa, että seuraava toimintosi on entistä paremmin suojattu.", /* fi */
+      "Ang pagkumpirmang ito ay nagbibigay ng karagdagang layer ng seguridad para sa pagkilos na gagawin mo.", /* fil */
+      "Cette confirmation ajoute un niveau de sécurité supplémentaire à l'action que vous êtes sur le point d'effectuer.", /* fr */
+      "Cette confirmation fournit une couche supplémentaire de sécurité pour l'action que vous êtes sur le point d'effectuer.", /* fr-CA */
+      "Cette confirmation ajoute un niveau de sécurité supplémentaire à l'action que vous êtes sur le point d'effectuer.", /* fr-CH */
+      "Esta confirmación proporciona unha capa adicional de seguranza para a acción que estás a piques de levar a cabo.", /* gl */
+      "Durch die Bestätigung wird bei der Aktion, die du durchführen möchtest, eine zusätzliche Sicherheitsmaßnahme angewandt.", /* gsw */
+      "તમે જે ક્રિયા કરવાના છો તેના માટે આ કન્ફર્મેશન એક અતિરિક્ત સુરક્ષાનું સ્તર પ્રદાન કરે છે.", /* gu */
+      "אישור זה מספק שכבת אבטחה נוספת לפעולה שאתה עומד לבצע.", /* he */
+      "यह पुष्टि मिलने पर आप जो काम करने वाले हैं, उसके लिए सुरक्षा और बढ़ जाती है.", /* hi */
+      "Ta potvrda pruža dodatan sloj zaštite za radnju koju ćete izvršiti.", /* hr */
+      "Ez a megerősítés extra réteg biztonságot nyújt a végrehajtani kívánt művelet számára.", /* hu */
+      "Այս հաստատումն ապահովում է պաշտպանության լրացուցիչ մակարդակ՝ նախքան գործողություն կատարելը", /* hy */
+      "Konfirmasi ini memberikan lapisan keamanan tambahan untuk tindakan yang akan Anda ambil.", /* id */
+      "Konfirmasi ini memberikan lapisan keamanan tambahan untuk tindakan yang akan Anda ambil.", /* in */
+      "Þessi staðfesting veitir aukið öryggi fyrir aðgerðina sem þú ert að fara að framkvæma.", /* is */
+      "Questa conferma garantisce un ulteriore livello di sicurezza per l'azione che stai per compiere.", /* it */
+      "אישור זה מספק שכבת אבטחה נוספת לפעולה שאתה עומד לבצע.", /* iw */
+      "この確認により、これから行う操作のセキュリティが強化されます。", /* ja */
+      "დადასტურება უსაფრთხოების დამატებით შრეს უზრუნველყოფს იმ ქმედების განსახორციელებლად, რომელსაც აპირებთ.", /* ka */
+      "Бұл растау функциясы орындағалы тұрған әрекеттің қауіпсіздігін қосымша күшейтеді.", /* kk */
+      "ការបញ្ជាក់នេះ​ផ្ដល់ស្រទាប់​សុវត្ថិភាព​បន្ថែម​សម្រាប់​សកម្មភាព​ដែលអ្នកហៀប​នឹងធ្វើ។", /* km */
+      "ಈ ದೃಢೀಕರಣವು ನೀವು ನಿರ್ವಹಿಸಲು ಬಯಸುವ ಕ್ರಿಯೆಗೆ ಹೆಚ್ಚುವರಿ ಸುರಕ್ಷತೆಯನ್ನು ಒದಗಿಸುತ್ತದೆ.", /* kn */
+      "이 확인 단계를 사용하면 실행하려는 작업의 보안을 한층 강화할 수 있습니다.", /* ko */
+      "Бул ырастоо сиз аткара турган аракеттин коопсуздугун коргоонун дагы бир катмарын камсыздайт.", /* ky */
+      "Cette confirmation ajoute un niveau de sécurité supplémentaire à l'action que vous êtes sur le point d'effectuer.", /* ln */
+      "ການຢືນຢັນນີ້ຈະເພີ່ມຄວາມປອດໄພເພີ່ມເຕີມອີກໜຶ່ງຊັ້ນໃຫ້ກັບຄຳສັ່ງທີ່ທ່ານກຳລັງຈະໃຊ້.", /* lo */
+      "Naudojant šį patvirtinimą, veiksmui, kurį ketinate atlikti, taikomas papildomas saugos lygmuo.", /* lt */
+      "Šis apstiprinājums sniedz papildu aizsardzību darbībai, kuru veiksiet.", /* lv */
+      "Оваа потврда обезбедува дополнителен слој на безбедност за дејството што ќе го преземете.", /* mk */
+      "നിങ്ങൾ സ്വീകരിക്കാൻ പോകുന്ന നടപടിക്കായി, ഈ സ്ഥിരീകരണം ഒരു അധിക സുരക്ഷാ പാളി നൽകുന്നു.", /* ml */
+      "Энэ баталгаажуулалт нь таны авах гэж буй арга хэмжээнд хамгаалалтын нэмэлт давхаргыг олгодог.", /* mn */
+      "Această confirmare oferă un nivel suplimentar de securitate pentru acțiunea pe care urmează să o faceți.", /* mo */
+      "हे निश्चित झाल्‍यावर, तुम्‍ही जे काम करणार आहात, त्‍यासाठी सुरक्षा आणखी वाढते.", /* mr */
+      "Pengesahan ini memberikan lapisan keselamatan tambahan untuk tindakan yang akan anda ambil.", /* ms */
+      "ဤအတည်ပြုချက်က သင်ပြုလုပ်တော့မည့် လုပ်ဆောင်ချက်အတွက် အပိုဆောင်းလုံခြုံရေးကို ပေးထားသည်။", /* my */
+      "Denne bekreftelsen gir et ekstra sikkerhetslag for handlingen du er i ferd med å utføre.", /* nb */
+      "यो पुष्टिले तपाईंले गर्न ऑंट्नुभएको कारबाहीका लागि सुरक्षाको अतिरिक्त तह प्रदान गर्छ।", /* ne */
+      "Deze bevestiging biedt een extra beveiligingslaag voor de actie die je wilt uitvoeren.", /* nl */
+      "Denne bekreftelsen gir et ekstra sikkerhetslag for handlingen du er i ferd med å utføre.", /* no */
+      "ଏହି ସୁନିଶ୍ଚିତତା, ଆପଣ କରିବାକୁ ଯାଉଥିବା କାର୍ଯ୍ୟ ପାଇଁ ଅତିରିକ୍ତ ସୁରକ୍ଷା ପରତ ପ୍ରଦାନ କରିଥାଏ।", /* or */
+      "ਇਹ ਪੁਸ਼ਟੀਕਰਨ ਤੁਹਾਡੇ ਵੱਲੋਂ ਕਾਰਵਾਈ ਨੂੰ ਕੀਤੇ ਜਾਣ ਲਈ ਸੁਰੱਖਿਆ ਦੇ ਇੱਕ ਵਾਧੂ ਪੱਧਰ ਮੁਹੱਈਆ ਕਰਦੀ ਹੈ।", /* pa */
+      "To potwierdzenie stanowi dodatkowe zabezpieczenie czynności, którą zamierzasz wykonać.", /* pl */
+      "Essa confirmação oferece uma camada adicional de segurança para a ação que você está prestes a realizar.", /* pt */
+      "Essa confirmação oferece uma camada adicional de segurança para a ação que você está prestes a realizar.", /* pt-BR */
+      "Esta confirmação oferece um nível extra de segurança para a ação que está prestes a realizar.", /* pt-PT */
+      "Această confirmare oferă un nivel suplimentar de securitate pentru acțiunea pe care urmează să o faceți.", /* ro */
+      "Дополнительный уровень защиты для действия, которое вы собираетесь выполнить.", /* ru */
+      "මෙම තහවුරු කිරිම ඔබ ගැනීමට යන ක්‍රියාමාර්ගය සඳහා ආරක්ෂාව පිළිබඳ අමතර ස්තරයක් සපයයි.", /* si */
+      "Toto potvrdenie zaistí dodatočnú úroveň zabezpečenia akcie, ktorú sa chystáte vykonať.", /* sk */
+      "Ta potrditev zagotavlja dodatno plast zaščite za dejanje, ki ga boste izvedli.", /* sl */
+      "Konfirmim ofron një shtresë sigurie shtesë për veprimin që je gati për të ndërmarrë.", /* sq */
+      "Ова потврда пружа додатни слој безбедности за радњу коју се спремате да извршите.", /* sr */
+      "Ova potvrda pruža dodatni sloj bezbednosti za radnju koju se spremate da izvršite.", /* sr-Latn */
+      "Bekräftelsen ger extra skydd för åtgärden du ska vidta.", /* sv */
+      "Uthibitishaji huu hutoa ulinzi zaidi wa usalama kwa hatua unayotaka kuchukua.", /* sw */
+      "நீங்கள் மேற்கொள்ளவிருக்கும் செயலுக்கு, கூடுதல் பாதுகாப்பை இந்த உறுதிப்படுத்தல் வழங்கும்.", /* ta */
+      "ఈ నిర్ధారణ మీరు తీసుకోబోయే చర్య కోసం అదనపు భద్రతా లేయర్‌ను అందిస్తుంది.", /* te */
+      "การยืนยันนี้จะช่วยเพิ่มความปลอดภัยอีกขั้นสำหรับสิ่งที่คุณกำลังจะดำเนินการ", /* th */
+      "Ang pagkumpirmang ito ay nagbibigay ng karagdagang layer ng seguridad para sa pagkilos na gagawin mo.", /* tl */
+      "Bu onay, yapmak üzere olduğunuz işlem için ek güvenlik katmanı sağlar.", /* tr */
+      "Це підтвердження є додатковим рівнем захисту, коли ви збираєтеся виконати дію.", /* uk */
+      "آپ جو کارروائی کرنے والے ہیں اس کے لئے یہ تصدیق ایک اضافی پرت فراہم کرتی ہے۔", /* ur */
+      "Tasdiqlangandan keyin bajarilayotgan amal uchun qo‘shimcha xavfsizlik qatlami taqdim etiladi.", /* uz */
+      "Xác nhận này cung cấp thêm một lớp bảo mật cho hành động bạn sắp thực hiện.", /* vi */
+      "这项确认可为您即将执行的操作增添一层额外的安全保障。", /* zh */
+      "这项确认可为您即将执行的操作增添一层额外的安全保障。", /* zh-CN */
+      "此確認可為你即將執行的操作提供額外安全保障。", /* zh-HK */
+      "這項確認作業可為你即將執行的動作提供多一層安全保障。", /* zh-TW */
+      "Lokhu kuqinisekiswa kunikeza isendlalelo esingeziwe sokuvikelwa sesenzo osuzosithatha.", /* zu */
+    }
+  },
+  {
+    "2181224373757710937",
+    {
+      "Press power to confirm", /* en (untranslated) */
+      "Druk aan/af-skakelaar om te bevestig", /* af */
+      "ለማረጋገጥ ኃይልን ይጫኑ", /* am */
+      "اضغط على زر التشغيل لتأكيد الإجراء.", /* ar */
+      "اضغط على زر التشغيل لتأكيد الإجراء.", /* ar-EG */
+      "اضغط على زر التشغيل لتأكيد الإجراء.", /* ar-JO */
+      "اضغط على زر التشغيل لتأكيد الإجراء.", /* ar-MA */
+      "اضغط على زر التشغيل لتأكيد الإجراء.", /* ar-SA */
+      "‏‮Press‬‏ ‏‮power‬‏ ‏‮to‬‏ ‏‮confirm‬‏", /* ar-XB */
+      "নিশ্চিত কৰিবলৈ পাৱাৰ বুটাম হেঁচক", /* as */
+      "Təsdiq etmək üçün yandırıb-söndürmə düyməsinə basın", /* az */
+      "Націсніце кнопку сілкавання, каб пацвердзіць", /* be */
+      "Натиснете бутона за захранване, за да потвърдите", /* bg */
+      "নিশ্চিত করতে পাওয়ার বোতাম টিপুন", /* bn */
+      "Pritisnite dugme za napajanje za potvrdu", /* bs */
+      "Prem el botó d'engegada per confirmar", /* ca */
+      "Potvrďte stisknutím vypínače", /* cs */
+      "Tryk på afbryderknappen for at bekræfte", /* da */
+      "Drücke zum Bestätigen die Ein-/Aus-Taste", /* de */
+      "Drücke zum Bestätigen die Ein-/Aus-Taste", /* de-AT */
+      "Drücke zum Bestätigen die Ein-/Aus-Taste", /* de-CH */
+      "Πατήστε το κουμπί λειτουργίας για επιβεβαίωση", /* el */
+      "Press power to confirm", /* en-AU */
+      "Press power to confirm", /* en-CA */
+      "Press power to confirm", /* en-GB */
+      "Press power to confirm", /* en-IE */
+      "Press power to confirm", /* en-IN */
+      "Press power to confirm", /* en-SG */
+      "[Þŕéšš þöŵéŕ ţö çöñƒîŕm one two three four five]", /* en-XA */
+      "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‎‏‎‏‎‏‎‎‎‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‎‎‎‎‏‎‎‏‎‎‏‎‎‏‎‏‏‎‎‏‎Press power to confirm‎‏‎‎‏‎", /* en-XC */
+      "Press power to confirm", /* en-ZA */
+      "Pulsa el botón de encendido para confirmar", /* es */
+      "Presiona el botón de encendido para confirmar", /* es-419 */
+      "Presiona el botón de encendido para confirmar", /* es-AR */
+      "Presiona el botón de encendido para confirmar", /* es-BO */
+      "Presiona el botón de encendido para confirmar", /* es-CL */
+      "Presiona el botón de encendido para confirmar", /* es-CO */
+      "Presiona el botón de encendido para confirmar", /* es-CR */
+      "Presiona el botón de encendido para confirmar", /* es-DO */
+      "Presiona el botón de encendido para confirmar", /* es-EC */
+      "Presiona el botón de encendido para confirmar", /* es-GT */
+      "Presiona el botón de encendido para confirmar", /* es-HN */
+      "Presiona el botón de encendido para confirmar", /* es-MX */
+      "Presiona el botón de encendido para confirmar", /* es-NI */
+      "Presiona el botón de encendido para confirmar", /* es-PA */
+      "Presiona el botón de encendido para confirmar", /* es-PE */
+      "Presiona el botón de encendido para confirmar", /* es-PR */
+      "Presiona el botón de encendido para confirmar", /* es-PY */
+      "Presiona el botón de encendido para confirmar", /* es-SV */
+      "Presiona el botón de encendido para confirmar", /* es-US */
+      "Presiona el botón de encendido para confirmar", /* es-UY */
+      "Presiona el botón de encendido para confirmar", /* es-VE */
+      "Kinnitamiseks vajutage toitenuppu", /* et */
+      "Berresteko, sakatu etengailua", /* eu */
+      "برای تأیید، دکمه روشن/خاموش را فشار دهید", /* fa */
+      "Vahvista painamalla virtapainiketta", /* fi */
+      "Pindutin ang power para kumpirmahin", /* fil */
+      "Appuyez sur le bouton Marche/Arrêt pour confirmer l'opération", /* fr */
+      "Appuyez sur l'interrupteur pour confirmer", /* fr-CA */
+      "Appuyez sur le bouton Marche/Arrêt pour confirmer l'opération", /* fr-CH */
+      "Preme o botón de acendido para confirmar", /* gl */
+      "Drücke zum Bestätigen die Ein-/Aus-Taste", /* gsw */
+      "કન્ફર્મ કરવા માટે પાવર બટન દબાવો", /* gu */
+      "יש ללחוץ על לחצן ההפעלה כדי לאשר", /* he */
+      "पुष्टि करने के लिए पावर बटन दबाएं", /* hi */
+      "Pritisnite tipku za uključivanje/isključivanje da biste potvrdili", /* hr */
+      "Nyomja meg a bekapcsológombot a megerősítéshez", /* hu */
+      "Հաստատելու համար սեղմեք սնուցման կոճակը", /* hy */
+      "Tekan tombol power untuk mengonfirmasi", /* id */
+      "Tekan tombol power untuk mengonfirmasi", /* in */
+      "Ýttu á aflrofann til að staðfesta", /* is */
+      "Premi il tasto di accensione per confermare", /* it */
+      "יש ללחוץ על לחצן ההפעלה כדי לאשר", /* iw */
+      "確認するには、電源を押します", /* ja */
+      "დასადასტურებლად დააჭირეთ ჩართვის ღილაკს", /* ka */
+      "Растау үшін қуат түймесін басыңыз", /* kk */
+      "ចុច​ប៊ូតុង​ថាមពល​ដើម្បី​បញ្ជាក់", /* km */
+      "ದೃಢೀಕರಿಸಲು ಪವರ್ ಬಟನ್ ಒತ್ತಿರಿ", /* kn */
+      "확인하려면 전원 버튼을 누르세요.", /* ko */
+      "Ырастоо үчүн \"Кубат\" баскычын басыңыз", /* ky */
+      "Appuyez sur le bouton Marche/Arrêt pour confirmer l'opération", /* ln */
+      "ກົດປຸ່ມເປີດປິດເພື່ອຢືນຢັນ", /* lo */
+      "Paspauskite maitinimo mygtuką, kad patvirtintumėte", /* lt */
+      "Lai apstiprinātu, nospiediet barošanas pogu", /* lv */
+      "Притиснете на копчето за напојување за да потврдите", /* mk */
+      "സ്ഥിരീകരിക്കാൻ പവർ അമർത്തുക", /* ml */
+      "Баталгаажуулахын тулд унтраах/асаахыг дарах", /* mn */
+      "Apăsați butonul de pornire pentru a confirma", /* mo */
+      "निश्चित करण्‍यासाठी पॉवर दाबा", /* mr */
+      "Tekan kuasa untuk mengesahkan", /* ms */
+      "အတည်ပြုရန် ပါဝါခလုတ်နှိပ်ပါ", /* my */
+      "Trykk på av/på-knappen for å bekrefte", /* nb */
+      "पुष्टि गर्न पावर बटनमा थिच्नुहोस्", /* ne */
+      "Druk op de aan/uit-knop om te bevestigen", /* nl */
+      "Trykk på av/på-knappen for å bekrefte", /* no */
+      "ସୁନିଶ୍ଚିତ କରିବା ପାଇଁ ପାୱର୍‌ ବଟନ୍‌କୁ ଦାବନ୍ତୁ", /* or */
+      "ਪੁਸ਼ਟੀ ਕਰਨ ਲਈ ਪਾਵਰ ਬਟਨ ਦਬਾਓ", /* pa */
+      "Naciśnij przycisk zasilania, aby potwierdzić", /* pl */
+      "Pressione o botão liga/desliga para confirmar", /* pt */
+      "Pressione o botão liga/desliga para confirmar", /* pt-BR */
+      "Prima ligar/desligar para confirmar.", /* pt-PT */
+      "Apăsați butonul de pornire pentru a confirma", /* ro */
+      "Для подтверждения нажмите кнопку питания.", /* ru */
+      "තහවුරු කිරීමට බල බොත්තම ඔබන්න", /* si */
+      "Potvrďte stlačením vypínača", /* sk */
+      "Za potrditev pritisnite gumb za vklop", /* sl */
+      "Shtyp butonin e energjisë për të konfirmuar", /* sq */
+      "Притисните дугме за напајање да бисте потврдили", /* sr */
+      "Pritisnite dugme za napajanje da biste potvrdili", /* sr-Latn */
+      "Bekräfta genom att trycka på strömbrytaren", /* sv */
+      "Bonyeza kitufe cha kuwasha ili uthibitishe", /* sw */
+      "உறுதிப்படுத்த, பவரை அழுத்தவும்", /* ta */
+      "నిర్ధారించడానికి పవర్‌ను నొక్కండి", /* te */
+      "กดปุ่มเปิด/ปิดเพื่อยืนยัน", /* th */
+      "Pindutin ang power para kumpirmahin", /* tl */
+      "Onaylamak için güç düğmesine basın", /* tr */
+      "Натисніть кнопку живлення, щоб підтвердити", /* uk */
+      "تصدیق کرنے کے لئے پاور بٹن دبائیں", /* ur */
+      "Tasdiqlash uchun quvvat tugmasini bosing", /* uz */
+      "Nhấn vào nút nguồn để xác nhận", /* vi */
+      "按电源按钮即可确认", /* zh */
+      "按电源按钮即可确认", /* zh-CN */
+      "按下電源按鈕即可確認", /* zh-HK */
+      "按下電源按鈕即可確認操作", /* zh-TW */
+      "Cindezela amandla ukuze uqinisekise", /* zu */
+    }
+  },
+  {
+    "2213954494039981979",
+    {
+      "Press any volume button to cancel", /* en (untranslated) */
+      "Druk enige volumeknoppie om te kanselleer", /* af */
+      "ለመሰረዝ ማናቸውንም የድምፅ አዝራር ይጫኑ", /* am */
+      "اضغط على أي زر من أزرار مستوى الصوت لإلغاء الإجراء.", /* ar */
+      "اضغط على أي زر من أزرار مستوى الصوت لإلغاء الإجراء.", /* ar-EG */
+      "اضغط على أي زر من أزرار مستوى الصوت لإلغاء الإجراء.", /* ar-JO */
+      "اضغط على أي زر من أزرار مستوى الصوت لإلغاء الإجراء.", /* ar-MA */
+      "اضغط على أي زر من أزرار مستوى الصوت لإلغاء الإجراء.", /* ar-SA */
+      "‏‮Press‬‏ ‏‮any‬‏ ‏‮volume‬‏ ‏‮button‬‏ ‏‮to‬‏ ‏‮cancel‬‏", /* ar-XB */
+      "বাতিল কৰিবলৈ যিকোনো ভলিউম বুটাম হেঁচক", /* as */
+      "Ləğv etmək üçün istənilən səs düyməsinə basın", /* az */
+      "Націсніце любую кнопку гучнасці, каб cкасаваць", /* be */
+      "Натиснете някой от бутоните за силата на звука, за да анулирате", /* bg */
+      "বাতিল করতে ভলিউমের যেকোনও বোতাম টিপুন", /* bn */
+      "Pritisnite bilo koje dugme za podešavanje jačine zvuka da otkažete", /* bs */
+      "Prem qualsevol botó de volum per cancel·lar", /* ca */
+      "Zrušte stisknutím tlačítka hlasitosti", /* cs */
+      "Tryk på en af lydstyrkeknapperne for at annullere", /* da */
+      "Zum Abbrechen eine beliebige Lautstärketaste drücken", /* de */
+      "Zum Abbrechen eine beliebige Lautstärketaste drücken", /* de-AT */
+      "Zum Abbrechen eine beliebige Lautstärketaste drücken", /* de-CH */
+      "Πατήστε οποιοδήποτε κουμπί έντασης ήχου για ακύρωση", /* el */
+      "Press any volume button to cancel", /* en-AU */
+      "Press any volume button to cancel", /* en-CA */
+      "Press any volume button to cancel", /* en-GB */
+      "Press any volume button to cancel", /* en-IE */
+      "Press any volume button to cancel", /* en-IN */
+      "Press any volume button to cancel", /* en-SG */
+      "[Þŕéšš åñý vöļûmé бûţţöñ ţö çåñçéļ one two three four five six seven]", /* en-XA */
+      "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‎‎‏‏‎‎‎‏‎‏‏‏‏‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎Press any volume button to cancel‎‏‎‎‏‎", /* en-XC */
+      "Press any volume button to cancel", /* en-ZA */
+      "Pulsa cualquier botón de volumen para cancelar", /* es */
+      "Presiona cualquier botón de volumen para cancelar", /* es-419 */
+      "Presiona cualquier botón de volumen para cancelar", /* es-AR */
+      "Presiona cualquier botón de volumen para cancelar", /* es-BO */
+      "Presiona cualquier botón de volumen para cancelar", /* es-CL */
+      "Presiona cualquier botón de volumen para cancelar", /* es-CO */
+      "Presiona cualquier botón de volumen para cancelar", /* es-CR */
+      "Presiona cualquier botón de volumen para cancelar", /* es-DO */
+      "Presiona cualquier botón de volumen para cancelar", /* es-EC */
+      "Presiona cualquier botón de volumen para cancelar", /* es-GT */
+      "Presiona cualquier botón de volumen para cancelar", /* es-HN */
+      "Presiona cualquier botón de volumen para cancelar", /* es-MX */
+      "Presiona cualquier botón de volumen para cancelar", /* es-NI */
+      "Presiona cualquier botón de volumen para cancelar", /* es-PA */
+      "Presiona cualquier botón de volumen para cancelar", /* es-PE */
+      "Presiona cualquier botón de volumen para cancelar", /* es-PR */
+      "Presiona cualquier botón de volumen para cancelar", /* es-PY */
+      "Presiona cualquier botón de volumen para cancelar", /* es-SV */
+      "Presiona cualquier botón de volumen para cancelar", /* es-US */
+      "Presiona cualquier botón de volumen para cancelar", /* es-UY */
+      "Presiona cualquier botón de volumen para cancelar", /* es-VE */
+      "Tühistamiseks vajutage mis tahes helitugevuse nuppu", /* et */
+      "Bertan behera uzteko, sakatu bolumen-tekla bat", /* eu */
+      "برای لغو، یکی از دکمه‌های میزان صدا را فشار دهید", /* fa */
+      "Peruuta painamalla äänenvoimakkuuspainiketta", /* fi */
+      "Pindutin ang anumang button ng volume para kanselahin", /* fil */
+      "Appuyez sur l'un des boutons de volume pour annuler l'opération", /* fr */
+      "Appuyez sur un bouton de volume pour annuler l'action", /* fr-CA */
+      "Appuyez sur l'un des boutons de volume pour annuler l'opération", /* fr-CH */
+      "Preme calquera botón de volume para cancelar", /* gl */
+      "Zum Abbrechen eine beliebige Lautstärketaste drücken", /* gsw */
+      "રદ કરવા માટે કોઈપણ વૉલ્યૂમનું બટન દબાવો", /* gu */
+      "יש ללחוץ על לחצן כלשהו של עוצמת הקול כדי לבטל", /* he */
+      "रद्द करने के लिए कोई भी वॉल्यूम बटन दबाएं", /* hi */
+      "Pritisnite bilo koju tipku za glasnoću da biste otkazali", /* hr */
+      "Nyomja meg valamelyik hangerőgombot az elvetéshez", /* hu */
+      "Չեղարկելու համար սեղմեք ձայնի կագավորման որևէ կոճակ", /* hy */
+      "Tekan tombol volume apa saja untuk membatalkan", /* id */
+      "Tekan tombol volume apa saja untuk membatalkan", /* in */
+      "Ýttu á hvaða hljóðstyrkshnapp sem er til að hætta við", /* is */
+      "Premi qualsiasi pulsante del volume per annullare", /* it */
+      "יש ללחוץ על לחצן כלשהו של עוצמת הקול כדי לבטל", /* iw */
+      "キャンセルするには、いずれかの音量ボタンを押します", /* ja */
+      "გასაუქმებლად დააჭირეთ ხმის რეგულირების ნებისმიერ ღილაკს", /* ka */
+      "Бас тарту үшін кез келген дыбыс деңгейі түймесін басыңыз", /* kk */
+      "ចុចប៊ូតុង​កម្រិតសំឡេង​ណាមួយ​ដើម្បីបោះបង់", /* km */
+      "ರದ್ದುಗೊಳಿಸಲು ಯಾವುದೇ ವಾಲ್ಯೂಮ್‌ ಬಟನ್ ಒತ್ತಿರಿ", /* kn */
+      "취소하려면 볼륨 버튼 중 하나를 누르세요.", /* ko */
+      "Жокко чыгаруу үчүн үн көлөмүнүн баскычтарынын бирин басыңыз", /* ky */
+      "Appuyez sur l'un des boutons de volume pour annuler l'opération", /* ln */
+      "ກົດປຸ່ມສຽງຂຶ້ນ ຫຼື ລົງເພື່ອຍົກເລີກ", /* lo */
+      "Paspauskite bet kurį garsumo mygtuką, kad atšauktumėte", /* lt */
+      "Lai atceltu, nospiediet jebkuru skaļuma pogu", /* lv */
+      "Притиснете на кое било копче за јачина на звук за да откажете", /* mk */
+      "റദ്ദാക്കാൻ എതെങ്കിലും വോളിയം ബട്ടൺ അമർത്തുക", /* ml */
+      "Болихын тулд дууны түвшний товчлуурын аль нэгийг нь дарах", /* mn */
+      "Apăsați orice buton de volum pentru a anula", /* mo */
+      "रद्द करण्‍यासाठी कोणतेही व्‍हॉल्‍यूम बटण दाबा", /* mr */
+      "Tekan sebarang butang kelantangan untuk membatalkan tindakan", /* ms */
+      "ပယ်ဖျက်ရန် အသံအတိုးအကျယ်ခလုတ် တစ်ခုခုကိုနှိပ်ပါ", /* my */
+      "Trykk på en volumknapp for å avbryte", /* nb */
+      "रद्द गर्नका लागि कुनै भोल्युम बटन थिच्नुहोस्", /* ne */
+      "Druk op een volumeknop om te annuleren", /* nl */
+      "Trykk på en volumknapp for å avbryte", /* no */
+      "କ୍ୟାନ୍ସଲ୍ କରିବା ପାଇଁ ଯେକୌଣସି ଭଲ୍ୟୁମ୍ ବଟନ୍‌କୁ ଦାବନ୍ତୁ", /* or */
+      "ਰੱਦ ਕਰਨ ਲਈ ਕਿਸੇ ਵੀ ਵੌਲਿਊਮ ਬਟਨ ਨੂੰ ਦਬਾਓ", /* pa */
+      "Naciśnij dowolny przycisk głośności, aby anulować", /* pl */
+      "Pressione um dos botões de volume para cancelar", /* pt */
+      "Pressione um dos botões de volume para cancelar", /* pt-BR */
+      "Prima qualquer botão de volume para cancelar.", /* pt-PT */
+      "Apăsați orice buton de volum pentru a anula", /* ro */
+      "Для отмены нажмите на любую кнопку регулировки громкости.", /* ru */
+      "අවලංගු කිරීමට ඕනෑම හඬ පරිමා බොත්තමක් ඔබන්න", /* si */
+      "Zrušte stlačením ľubovoľného tlačidla hlasitosti", /* sk */
+      "Za preklic pritisnite poljuben gumb za glasnost", /* sl */
+      "Shtyp çdo buton volumi për ta anuluar", /* sq */
+      "Притисните било које дугме за јачину звука да бисте отказали", /* sr */
+      "Pritisnite bilo koje dugme za jačinu zvuka da biste otkazali", /* sr-Latn */
+      "Avbryt genom att trycka på valfri volymknapp", /* sv */
+      "Bonyeza kitufe chochote cha sauti ili ughairi", /* sw */
+      "ரத்துசெய்ய, ஏதேனும் ஒலியளவு பட்டனை அழுத்தவும்", /* ta */
+      "రద్దు చేయడానికి ఏదైనా వాల్యూమ్ బటన్‌ను నొక్కండి", /* te */
+      "กดปุ่มปรับระดับเสียงเพื่อยกเลิก", /* th */
+      "Pindutin ang anumang button ng volume para kanselahin", /* tl */
+      "İptal etmek için herhangi bir ses düğmesine basın", /* tr */
+      "Натисніть будь-яку клавішу гучності, щоб скасувати", /* uk */
+      "منسوخ کرنے کے لئے کوئی بھی والیوم بٹن دبائیں", /* ur */
+      "Bekor qilish uchun istalgan tovush tugmasini bosing", /* uz */
+      "Nhấn vào nút âm lượng bất kỳ để hủy", /* vi */
+      "按任意音量按钮即可取消", /* zh */
+      "按任意音量按钮即可取消", /* zh-CN */
+      "按下任何音量按鈕即可取消", /* zh-HK */
+      "按下任一音量按鈕即可取消操作", /* zh-TW */
+      "Cindezela noma iyiphi inkinobho yevolumu ukuze ukhansele", /* zu */
+    }
+  },
+  {
+    "3999296476990449149",
+    {
+      "Cancel", /* en (untranslated) */
+      "Kanselleer", /* af */
+      "ይቅር", /* am */
+      "إلغاء", /* ar */
+      "إلغاء", /* ar-EG */
+      "إلغاء", /* ar-JO */
+      "إلغاء", /* ar-MA */
+      "إلغاء", /* ar-SA */
+      "‏‮Cancel‬‏", /* ar-XB */
+      "বাতিল কৰক", /* as */
+      "Ləğv edin", /* az */
+      "Скасаваць", /* be */
+      "Отказ", /* bg */
+      "বাতিল করুন", /* bn */
+      "Otkaži", /* bs */
+      "Cancel·la", /* ca */
+      "Zrušit", /* cs */
+      "Annuller", /* da */
+      "Abbrechen", /* de */
+      "Abbrechen", /* de-AT */
+      "Abbrechen", /* de-CH */
+      "Ακύρωση", /* el */
+      "Cancel", /* en-AU */
+      "Cancel", /* en-CA */
+      "Cancel", /* en-GB */
+      "Cancel", /* en-IE */
+      "Cancel", /* en-IN */
+      "Cancel", /* en-SG */
+      "[Çåñçéļ one]", /* en-XA */
+      "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‎‎‎‎‎‎‎‎‏‎‏‏‎‏‎‏‏‏‏‎‏‎‎‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎Cancel‎‏‎‎‏‎", /* en-XC */
+      "Cancel", /* en-ZA */
+      "Cancelar", /* es */
+      "Cancelar", /* es-419 */
+      "Cancelar", /* es-AR */
+      "Cancelar", /* es-BO */
+      "Cancelar", /* es-CL */
+      "Cancelar", /* es-CO */
+      "Cancelar", /* es-CR */
+      "Cancelar", /* es-DO */
+      "Cancelar", /* es-EC */
+      "Cancelar", /* es-GT */
+      "Cancelar", /* es-HN */
+      "Cancelar", /* es-MX */
+      "Cancelar", /* es-NI */
+      "Cancelar", /* es-PA */
+      "Cancelar", /* es-PE */
+      "Cancelar", /* es-PR */
+      "Cancelar", /* es-PY */
+      "Cancelar", /* es-SV */
+      "Cancelar", /* es-US */
+      "Cancelar", /* es-UY */
+      "Cancelar", /* es-VE */
+      "Tühista", /* et */
+      "Utzi", /* eu */
+      "لغو", /* fa */
+      "Peruuta", /* fi */
+      "Kanselahin", /* fil */
+      "Annuler", /* fr */
+      "Annuler", /* fr-CA */
+      "Annuler", /* fr-CH */
+      "Cancelar", /* gl */
+      "Abbrechen", /* gsw */
+      "રદ કરો", /* gu */
+      "ביטול", /* he */
+      "रद्द करें", /* hi */
+      "Otkaži", /* hr */
+      "Mégse", /* hu */
+      "Չեղարկել", /* hy */
+      "Batal", /* id */
+      "Batal", /* in */
+      "Hætta við", /* is */
+      "Annulla", /* it */
+      "ביטול", /* iw */
+      "キャンセル", /* ja */
+      "გაუქმება", /* ka */
+      "Бас тарту", /* kk */
+      "បោះបង់", /* km */
+      "ರದ್ದು", /* kn */
+      "취소", /* ko */
+      "Жокко чыгаруу", /* ky */
+      "Annuler", /* ln */
+      "ຍົກເລີກ", /* lo */
+      "Atšaukti", /* lt */
+      "Atcelt", /* lv */
+      "Откажи", /* mk */
+      "റദ്ദാക്കുക", /* ml */
+      "Болих", /* mn */
+      "Anulați", /* mo */
+      "रद्द करा", /* mr */
+      "Batal", /* ms */
+      "မလုပ်တော့", /* my */
+      "Avbryt", /* nb */
+      "रद्द गर्नुहोस्", /* ne */
+      "Annuleren", /* nl */
+      "Avbryt", /* no */
+      "କ୍ୟାନ୍ସଲ୍‍ କରନ୍ତୁ", /* or */
+      "ਰੱਦ ਕਰੋ", /* pa */
+      "Anuluj", /* pl */
+      "Cancelar", /* pt */
+      "Cancelar", /* pt-BR */
+      "Cancelar", /* pt-PT */
+      "Anulați", /* ro */
+      "Отмена", /* ru */
+      "අවලංගු කරන්න", /* si */
+      "Zrušiť", /* sk */
+      "Prekliči", /* sl */
+      "Anulo", /* sq */
+      "Откажи", /* sr */
+      "Otkaži", /* sr-Latn */
+      "Avbryt", /* sv */
+      "Ghairi", /* sw */
+      "ரத்துசெய்", /* ta */
+      "రద్దు చేయండి", /* te */
+      "ยกเลิก", /* th */
+      "Kanselahin", /* tl */
+      "İptal", /* tr */
+      "Скасувати", /* uk */
+      "منسوخ کریں", /* ur */
+      "Bekor qilish", /* uz */
+      "Hủy", /* vi */
+      "取消", /* zh */
+      "取消", /* zh-CN */
+      "取消", /* zh-HK */
+      "取消", /* zh-TW */
+      "Khansela", /* zu */
+    }
+  },
+  {
+    "6973195374358399966",
+    {
+      "Android Protected Confirmation", /* en (untranslated) */
+      "Android se Beskermde Bevestiging", /* af */
+      "በAndroid ጥበቃ የሚደረግለት ማረጋገጫ", /* am */
+      "تأكيد حماية Android", /* ar */
+      "تأكيد حماية Android", /* ar-EG */
+      "تأكيد حماية Android", /* ar-JO */
+      "تأكيد حماية Android", /* ar-MA */
+      "تأكيد حماية Android", /* ar-SA */
+      "‏‮Android‬‏ ‏‮Protected‬‏ ‏‮Confirmation‬‏", /* ar-XB */
+      "Androidৰ সুৰক্ষা সম্পৰ্কীয় প্ৰতিশ্ৰুতি", /* as */
+      "Qorunan Android Təsdiqi", /* az */
+      "Пацвярджэнне Android Protected", /* be */
+      "Защитно потвърждение за Android", /* bg */
+      "Android প্রোটেক্টেড কনফার্মেশন", /* bn */
+      "Potvrda zaštite na Androidu", /* bs */
+      "Confirmació de protecció d'Android", /* ca */
+      "Potvrzení ochrany Androidu", /* cs */
+      "Beskyttet bekræftelse i Android", /* da */
+      "Bestätigung für Android Protected", /* de */
+      "Bestätigung für Android Protected", /* de-AT */
+      "Bestätigung für Android Protected", /* de-CH */
+      "Επιβεβαίωση προστασίας Android", /* el */
+      "Android Protected Confirmation", /* en-AU */
+      "Android Protected Confirmation", /* en-CA */
+      "Android Protected Confirmation", /* en-GB */
+      "Android Protected Confirmation", /* en-IE */
+      "Android Protected Confirmation", /* en-IN */
+      "Android Protected Confirmation", /* en-SG */
+      "[Åñðŕöîð Þŕöţéçţéð Çöñƒîŕmåţîöñ one two three four]", /* en-XA */
+      "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎Android Protected Confirmation‎‏‎‎‏‎", /* en-XC */
+      "Android Protected Confirmation", /* en-ZA */
+      "Confirmación protegida por Android", /* es */
+      "Confirmación de protección de Android", /* es-419 */
+      "Confirmación de protección de Android", /* es-AR */
+      "Confirmación de protección de Android", /* es-BO */
+      "Confirmación de protección de Android", /* es-CL */
+      "Confirmación de protección de Android", /* es-CO */
+      "Confirmación de protección de Android", /* es-CR */
+      "Confirmación de protección de Android", /* es-DO */
+      "Confirmación de protección de Android", /* es-EC */
+      "Confirmación de protección de Android", /* es-GT */
+      "Confirmación de protección de Android", /* es-HN */
+      "Confirmación de protección de Android", /* es-MX */
+      "Confirmación de protección de Android", /* es-NI */
+      "Confirmación de protección de Android", /* es-PA */
+      "Confirmación de protección de Android", /* es-PE */
+      "Confirmación de protección de Android", /* es-PR */
+      "Confirmación de protección de Android", /* es-PY */
+      "Confirmación de protección de Android", /* es-SV */
+      "Confirmación de protección de Android", /* es-US */
+      "Confirmación de protección de Android", /* es-UY */
+      "Confirmación de protección de Android", /* es-VE */
+      "Androidi kaitstud kinnitus", /* et */
+      "Android-en babesa izatearen berrespena", /* eu */
+      "تأیید محافظت‌شده Android", /* fa */
+      "Vahvistus Android-suojauksesta", /* fi */
+      "Pagkumpirmang Pinoprotektahan ng Android", /* fil */
+      "Confirmation de protection Android", /* fr */
+      "Confirmation protégée Android", /* fr-CA */
+      "Confirmation de protection Android", /* fr-CH */
+      "Android Protected Confirmation", /* gl */
+      "Bestätigung für Android Protected", /* gsw */
+      "Android પ્રોટેક્ટેડ કન્ફર્મેશન", /* gu */
+      "Android Protected Confirmation", /* he */
+      "Android की ओर से सुरक्षा की पुष्टि", /* hi */
+      "Potvrda zaštite na Androidu", /* hr */
+      "Android – védett megerősítés", /* hu */
+      "Android Protected-ի հաստատում", /* hy */
+      "Konfirmasi yang Dilindungi Android", /* id */
+      "Konfirmasi yang Dilindungi Android", /* in */
+      "Varin staðfesting Android", /* is */
+      "Conferma Android Protected", /* it */
+      "Android Protected Confirmation", /* iw */
+      "Android Protected の確認", /* ja */
+      "Android-ის დაცული დადასტურება", /* ka */
+      "Android қорғалған растау", /* kk */
+      "ការ​បញ្ជាក់​ដែលបាន​ការពារ Android", /* km */
+      "Android ಸಂರಕ್ಷಿತ ದೃಢೀಕರಣ", /* kn */
+      "Android 보안 확인", /* ko */
+      "Android Protected ырастоосу", /* ky */
+      "Confirmation de protection Android", /* ln */
+      "ການຢືນຢັນ Android ທີ່ໄດ້ຮັບການປົກປ້ອງ", /* lo */
+      "„Android Protected“ patvirtinimas", /* lt */
+      "Android aizsargātā informācija", /* lv */
+      "Потврда за заштита на Android", /* mk */
+      "Android സംരക്ഷിത സ്ഥിരീകരണം", /* ml */
+      "Андройдоор хамгаалсан баталгаажуулалт", /* mn */
+      "Confirmare protecție pentru Android", /* mo */
+      "Android कडून सुरक्षा निश्चित करणे", /* mr */
+      "Pengesahan Dilindungi Android", /* ms */
+      "Android ကာကွယ်မှု အတည်ပြုချက်", /* my */
+      "Android-beskyttet bekreftelse", /* nb */
+      "Android द्वारा संरक्षण गरिएको पुष्टि", /* ne */
+      "Bevestiging van Android-beveiliging", /* nl */
+      "Android-beskyttet bekreftelse", /* no */
+      "Android ଦ୍ୱାରା ସୁରକ୍ଷିତ ହୋଇଥିବାର ସୁନିଶ୍ଚିତତା", /* or */
+      "Android ਵੱਲੋਂ ਸੁਰੱਖਿਆ ਦੀ ਪੁਸ਼ਟੀ", /* pa */
+      "Zabezpieczone potwierdzenie w Androidzie", /* pl */
+      "Confirmação protegida pelo Android", /* pt */
+      "Confirmação protegida pelo Android", /* pt-BR */
+      "Confirmação protegida do Android", /* pt-PT */
+      "Confirmare protecție pentru Android", /* ro */
+      "Подтверждение Android Protected", /* ru */
+      "Android ආරක්ෂිත තහවුරු කිරීම", /* si */
+      "Chránené potvrdenie Androidu", /* sk */
+      "Zaščitena potrditev v Androidu", /* sl */
+      "Android Protected Confirmation", /* sq */
+      "Потврда заштите на Android-у", /* sr */
+      "Potvrda zaštite na Android-u", /* sr-Latn */
+      "Bekräftelseskydd för Android", /* sv */
+      "Uthibitishaji Unaolindwa wa Android", /* sw */
+      "Android பாதுகாப்பு தொடர்பான உறுதிப்படுத்தல்", /* ta */
+      "Android సురక్షిత నిర్ధారణ", /* te */
+      "ยืนยันการป้องกัน Android", /* th */
+      "Pagkumpirmang Pinoprotektahan ng Android", /* tl */
+      "Android Korumalı Onayı", /* tr */
+      "Підтвердження Android Protected", /* uk */
+      "Android کی تحفظ یافتہ تصدیق", /* ur */
+      "Android Protected nomli tasdiq", /* uz */
+      "Xác nhận bảo vệ Android", /* vi */
+      "Android 保护确认", /* zh */
+      "Android 保护确认", /* zh-CN */
+      "Android 保護確認", /* zh-HK */
+      "Android Protected 確認", /* zh-TW */
+      "Ukuqinisekiswa okuvikelwe i-Android", /* zu */
+    }
+  },
+};
+
+#define ConfirmationUITranslations_NUM_TRANSLATION_IDS \
+    (ARRAY_ELEMENTS(ConfirmationUITranslations_translation_ids))
+
+static int ConfirmationUITranslations_selected_lang_id_index = 0;
+
+static int ConfirmationUITranslations_find_str(const char** haystack, const char* needle) {
+    for (int n = 0; haystack[n] != NULL; n++) {
+        if (strcmp(needle, haystack[n]) == 0) {
+            return n;
+        }
+    }
+    return -1;
+}
+
+#define MAX_LANG_ID_SIZE 256
+
+/* Non-static linkage to allow calling by the test. */
+int ConfirmationUITranslations_lang_id_match(const char** lang_ids, const char* lang_id) {
+    int ret;
+    char lang_id_buf[MAX_LANG_ID_SIZE + 1];
+    size_t n;
+
+    ret = ConfirmationUITranslations_find_str(lang_ids, lang_id);
+    if (ret >= 0) {
+        return ret;
+    }
+
+    /* strncpy.. */
+    for (n = 0; lang_id[n] != '\0' && n < MAX_LANG_ID_SIZE; n++) {
+        lang_id_buf[n] = lang_id[n];
+    }
+    lang_id_buf[n] = '\0';
+
+    while (n >= 1) {
+        /* Remove last component */
+        while (n >= 1 && lang_id_buf[n - 1] != '-') {
+            n--;
+        }
+        if (n < 1) {
+            return -1;
+        }
+        lang_id_buf[n - 1] = '\0';
+        n--;
+        ret = ConfirmationUITranslations_find_str(lang_ids, lang_id_buf);
+        if (ret >= 0) {
+            return ret;
+        }
+    }
+    return -1;
+}
+
+const char* ConfirmationUITranslations_select_lang_id(const char* lang_id) {
+    ConfirmationUITranslations_selected_lang_id_index = 0;
+    if (lang_id == NULL) {
+        return ConfirmationUITranslations_language_ids[0];
+    }
+
+    int ret = ConfirmationUITranslations_lang_id_match(ConfirmationUITranslations_language_ids, lang_id);
+    if (ret < 0) {
+        return ConfirmationUITranslations_language_ids[0];
+    }
+    ConfirmationUITranslations_selected_lang_id_index = ret;
+    return ConfirmationUITranslations_language_ids[ConfirmationUITranslations_selected_lang_id_index];
+}
+
+const char* ConfirmationUITranslations_lookup(const char* translation_id) {
+    for (size_t n = 0; n < ConfirmationUITranslations_NUM_TRANSLATION_IDS; n++) {
+        if (strcmp(translation_id, ConfirmationUITranslations_translation_ids[n].translation_id) == 0) {
+            const char* result;
+            if (ConfirmationUITranslations_selected_lang_id_index < 0 || ConfirmationUITranslations_selected_lang_id_index >= ConfirmationUITranslations_NUM_LANGUAGE_IDS) {
+                return ConfirmationUITranslations_translation_ids[n].translations[0];
+            }
+            result = ConfirmationUITranslations_translation_ids[n].translations[ConfirmationUITranslations_selected_lang_id_index];
+            if (result != NULL) {
+                return result;
+            }
+            return ConfirmationUITranslations_translation_ids[n].translations[0];
+        }
+    }
+    return NULL;
+}
+
+const char* const* ConfirmationUITranslations_get_languages(void) {
+    return (const char* const*) (ConfirmationUITranslations_language_ids);
+}
diff --git a/confirmationui/support/test/ConfirmationUITranslations-test.c b/confirmationui/support/test/ConfirmationUITranslations-test.c
new file mode 100644
index 0000000..a73a8af
--- /dev/null
+++ b/confirmationui/support/test/ConfirmationUITranslations-test.c
@@ -0,0 +1,1338 @@
+/*
+**
+** 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.
+*/
+
+/* Generated by generate-translations.py - DO NOT EDIT */
+
+#include "ConfirmationUITranslations.h"
+#include "string.h"
+
+#include <stdio.h>
+
+#define ASSERT_STR(str1, str2) \
+    do { \
+        if (strcmp(str1, str2) != 0) { \
+            printf("%s:%d: Assertion failed: '%s' != '%s'\n", \
+                    __FILE__, __LINE__, str1, str2); \
+            return 1; \
+        } \
+    } while (0)
+
+extern int ConfirmationUITranslations_lang_id_match(const char** lang_ids,
+                                                    const char* lang_id);
+
+static const char* test_lang_id_match(const char* lang_ids[], const char* lang_id) {
+    int ret = ConfirmationUITranslations_lang_id_match(lang_ids, lang_id);
+    if (ret < 0) {
+        return "";
+    }
+    return lang_ids[ret];
+}
+
+int main(int argc, char* argv[]) {
+    /* Tests for untranslated languages */
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Double-press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "This confirmation provides an extra layer of security for the action you're about to take.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Press any volume button to cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected Confirmation");
+
+    /* Tests for languages without translation */
+    ConfirmationUITranslations_select_lang_id("nosuch-LA");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Double-press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "This confirmation provides an extra layer of security for the action you're about to take.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Press any volume button to cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected Confirmation");
+
+    /* Tests for untranslated language (en) */
+    ConfirmationUITranslations_select_lang_id("en");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Double-press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "This confirmation provides an extra layer of security for the action you're about to take.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Press any volume button to cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected Confirmation");
+
+    /* Tests for language af */
+    ConfirmationUITranslations_select_lang_id("af");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Dubbeldruk aan/af-skakelaar om te bevestig");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Kanselleer");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Hierdie bevestiging verskaf 'n ekstra laag sekuriteit vir die handeling wat jy op die punt is om uit te voer.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Druk aan/af-skakelaar om te bevestig");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Druk enige volumeknoppie om te kanselleer");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Kanselleer");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android se Beskermde Bevestiging");
+
+    /* Tests for language am */
+    ConfirmationUITranslations_select_lang_id("am");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "ለማረጋገጥ ኃይልን ሁለቴ ይጫኑ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "ይቅር");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "ይህ ማረጋገጫ እርስዎ ለሚወስዱት እርምጃ ተጨማሪ ትርፍ ጥበቃን ይሰጣል።");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "ለማረጋገጥ ኃይልን ይጫኑ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "ለመሰረዝ ማናቸውንም የድምፅ አዝራር ይጫኑ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "ይቅር");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "በAndroid ጥበቃ የሚደረግለት ማረጋገጫ");
+
+    /* Tests for language ar */
+    ConfirmationUITranslations_select_lang_id("ar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "اضغط على زر التشغيل مرتين لتأكيد الإجراء.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "إلغاء");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "يتيح هذا التأكيد تفعيل طبقة أمان إضافية للإجراء الذي توشك على اتخاذه.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "اضغط على زر التشغيل لتأكيد الإجراء.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "اضغط على أي زر من أزرار مستوى الصوت لإلغاء الإجراء.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "إلغاء");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "تأكيد حماية Android");
+
+    /* Tests for language ar-EG */
+    ConfirmationUITranslations_select_lang_id("ar-EG");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "اضغط على زر التشغيل مرتين لتأكيد الإجراء.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "إلغاء");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "يتيح هذا التأكيد تفعيل طبقة أمان إضافية للإجراء الذي توشك على اتخاذه.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "اضغط على زر التشغيل لتأكيد الإجراء.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "اضغط على أي زر من أزرار مستوى الصوت لإلغاء الإجراء.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "إلغاء");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "تأكيد حماية Android");
+
+    /* Tests for language ar-JO */
+    ConfirmationUITranslations_select_lang_id("ar-JO");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "اضغط على زر التشغيل مرتين لتأكيد الإجراء.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "إلغاء");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "يتيح هذا التأكيد تفعيل طبقة أمان إضافية للإجراء الذي توشك على اتخاذه.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "اضغط على زر التشغيل لتأكيد الإجراء.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "اضغط على أي زر من أزرار مستوى الصوت لإلغاء الإجراء.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "إلغاء");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "تأكيد حماية Android");
+
+    /* Tests for language ar-MA */
+    ConfirmationUITranslations_select_lang_id("ar-MA");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "اضغط على زر التشغيل مرتين لتأكيد الإجراء.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "إلغاء");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "يتيح هذا التأكيد تفعيل طبقة أمان إضافية للإجراء الذي توشك على اتخاذه.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "اضغط على زر التشغيل لتأكيد الإجراء.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "اضغط على أي زر من أزرار مستوى الصوت لإلغاء الإجراء.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "إلغاء");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "تأكيد حماية Android");
+
+    /* Tests for language ar-SA */
+    ConfirmationUITranslations_select_lang_id("ar-SA");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "اضغط على زر التشغيل مرتين لتأكيد الإجراء.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "إلغاء");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "يتيح هذا التأكيد تفعيل طبقة أمان إضافية للإجراء الذي توشك على اتخاذه.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "اضغط على زر التشغيل لتأكيد الإجراء.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "اضغط على أي زر من أزرار مستوى الصوت لإلغاء الإجراء.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "إلغاء");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "تأكيد حماية Android");
+
+    /* Tests for language ar-XB */
+    ConfirmationUITranslations_select_lang_id("ar-XB");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "‏‮Double‬‏-‏‮press‬‏ ‏‮power‬‏ ‏‮to‬‏ ‏‮confirm‬‏");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "‏‮Cancel‬‏");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "‏‮This‬‏ ‏‮confirmation‬‏ ‏‮provides‬‏ ‏‮an‬‏ ‏‮extra‬‏ ‏‮layer‬‏ ‏‮of‬‏ ‏‮security‬‏ ‏‮for‬‏ ‏‮the‬‏ ‏‮action‬‏ ‏‮you‬‏'‏‮re‬‏ ‏‮about‬‏ ‏‮to‬‏ ‏‮take‬‏.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "‏‮Press‬‏ ‏‮power‬‏ ‏‮to‬‏ ‏‮confirm‬‏");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "‏‮Press‬‏ ‏‮any‬‏ ‏‮volume‬‏ ‏‮button‬‏ ‏‮to‬‏ ‏‮cancel‬‏");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "‏‮Cancel‬‏");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "‏‮Android‬‏ ‏‮Protected‬‏ ‏‮Confirmation‬‏");
+
+    /* Tests for language as */
+    ConfirmationUITranslations_select_lang_id("as");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "নিশ্চিত কৰিবলৈ পাৱাৰ বুটামটো দুবাৰ হেঁচক");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "বাতিল কৰক");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "এই প্ৰতিশ্ৰুতিয়ে আপুনি কৰিব বিচৰা কোনো কাৰ্যৰ বাবে অতিৰিক্ত সুৰক্ষা প্ৰদান কৰে।");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "নিশ্চিত কৰিবলৈ পাৱাৰ বুটাম হেঁচক");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "বাতিল কৰিবলৈ যিকোনো ভলিউম বুটাম হেঁচক");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "বাতিল কৰক");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Androidৰ সুৰক্ষা সম্পৰ্কীয় প্ৰতিশ্ৰুতি");
+
+    /* Tests for language az */
+    ConfirmationUITranslations_select_lang_id("az");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Təsdiqləmək üçün iki dəfə yandırıb-söndürmək düyməsinə basın");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Ləğv edin");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Bu təsdiq etmək üzrə olduğunuz əməliyyat üçün əlavə təhlükəsizlik qatı təmin edir.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Təsdiq etmək üçün yandırıb-söndürmə düyməsinə basın");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Ləğv etmək üçün istənilən səs düyməsinə basın");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Ləğv edin");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Qorunan Android Təsdiqi");
+
+    /* Tests for language be */
+    ConfirmationUITranslations_select_lang_id("be");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Двойчы націсніце кнопку сілкавання, каб пацвердзіць");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Скасаваць");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Гэта пацвярджэнне забяспечвае дадатковы ўзровень бяспекі для дзеянняў, якія вы збіраецеся выконваць.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Націсніце кнопку сілкавання, каб пацвердзіць");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Націсніце любую кнопку гучнасці, каб cкасаваць");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Скасаваць");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Пацвярджэнне Android Protected");
+
+    /* Tests for language bg */
+    ConfirmationUITranslations_select_lang_id("bg");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Натиснете два пъти бутона за захранване, за да потвърдите");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Отказ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Това потвърждение осигурява допълнителна защита за действието, което сте напът да предприемете.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Натиснете бутона за захранване, за да потвърдите");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Натиснете някой от бутоните за силата на звука, за да анулирате");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Отказ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Защитно потвърждение за Android");
+
+    /* Tests for language bn */
+    ConfirmationUITranslations_select_lang_id("bn");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "নিশ্চিত করতে পাওয়ার বোতাম দুবার টিপুন");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "বাতিল করুন");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "আপনি যে কাজটি করতে চলেছেন, এই কনফার্মেশনের ফলে সেটির জন্য অতিরিক্ত সুরক্ষার ব্যবস্থা করা হয়।");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "নিশ্চিত করতে পাওয়ার বোতাম টিপুন");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "বাতিল করতে ভলিউমের যেকোনও বোতাম টিপুন");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "বাতিল করুন");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android প্রোটেক্টেড কনফার্মেশন");
+
+    /* Tests for language bs */
+    ConfirmationUITranslations_select_lang_id("bs");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Dva puta pritisnite dugme za napajanje da potvrdite");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Otkaži");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Ova potvrda pruža dodatni sloj zaštite za radnju koju namjeravate preduzeti.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Pritisnite dugme za napajanje za potvrdu");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Pritisnite bilo koje dugme za podešavanje jačine zvuka da otkažete");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Otkaži");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Potvrda zaštite na Androidu");
+
+    /* Tests for language ca */
+    ConfirmationUITranslations_select_lang_id("ca");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Prem dos cops el botó d'engegada per confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancel·la");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Aquesta confirmació proporciona una capa de seguretat addicional per a l'acció que estàs a punt de dur a terme.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Prem el botó d'engegada per confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Prem qualsevol botó de volum per cancel·lar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancel·la");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmació de protecció d'Android");
+
+    /* Tests for language cs */
+    ConfirmationUITranslations_select_lang_id("cs");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Potvrďte dvojitým stisknutím vypínače");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Zrušit");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Toto potvrzení tvoří dodatečnou úroveň zabezpečení akce, kterou se chystáte podniknout.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Potvrďte stisknutím vypínače");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Zrušte stisknutím tlačítka hlasitosti");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Zrušit");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Potvrzení ochrany Androidu");
+
+    /* Tests for language da */
+    ConfirmationUITranslations_select_lang_id("da");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Tryk to gange på afbryderknappen for at bekræfte");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Annuller");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Denne bekræftelse giver et ekstra beskyttelsesniveau for den handling, du er ved at foretage.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Tryk på afbryderknappen for at bekræfte");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Tryk på en af lydstyrkeknapperne for at annullere");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Annuller");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Beskyttet bekræftelse i Android");
+
+    /* Tests for language de */
+    ConfirmationUITranslations_select_lang_id("de");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Zum Bestätigen die Ein-/Aus-Taste zweimal drücken");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Abbrechen");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Durch die Bestätigung wird bei der Aktion, die du durchführen möchtest, eine zusätzliche Sicherheitsmaßnahme angewandt.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Drücke zum Bestätigen die Ein-/Aus-Taste");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Zum Abbrechen eine beliebige Lautstärketaste drücken");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Abbrechen");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Bestätigung für Android Protected");
+
+    /* Tests for language de-AT */
+    ConfirmationUITranslations_select_lang_id("de-AT");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Zum Bestätigen die Ein-/Aus-Taste zweimal drücken");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Abbrechen");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Durch die Bestätigung wird bei der Aktion, die du durchführen möchtest, eine zusätzliche Sicherheitsmaßnahme angewandt.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Drücke zum Bestätigen die Ein-/Aus-Taste");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Zum Abbrechen eine beliebige Lautstärketaste drücken");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Abbrechen");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Bestätigung für Android Protected");
+
+    /* Tests for language de-CH */
+    ConfirmationUITranslations_select_lang_id("de-CH");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Zum Bestätigen die Ein-/Aus-Taste zweimal drücken");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Abbrechen");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Durch die Bestätigung wird bei der Aktion, die du durchführen möchtest, eine zusätzliche Sicherheitsmassnahme angewandt.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Drücke zum Bestätigen die Ein-/Aus-Taste");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Zum Abbrechen eine beliebige Lautstärketaste drücken");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Abbrechen");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Bestätigung für Android Protected");
+
+    /* Tests for language el */
+    ConfirmationUITranslations_select_lang_id("el");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Πατήστε δύο φορές το κουμπί λειτουργίας για επιβεβαίωση");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Ακύρωση");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Αυτή η επιβεβαίωση παρέχει ένα επιπλέον επίπεδο ασφάλειας για την ενέργεια που πρόκειται να εκτελέσετε.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Πατήστε το κουμπί λειτουργίας για επιβεβαίωση");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Πατήστε οποιοδήποτε κουμπί έντασης ήχου για ακύρωση");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Ακύρωση");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Επιβεβαίωση προστασίας Android");
+
+    /* Tests for language en-AU */
+    ConfirmationUITranslations_select_lang_id("en-AU");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Double-press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "This confirmation provides an extra layer of security for the action that you're about to take.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Press any volume button to cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected Confirmation");
+
+    /* Tests for language en-CA */
+    ConfirmationUITranslations_select_lang_id("en-CA");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Double-press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "This confirmation provides an extra layer of security for the action that you're about to take.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Press any volume button to cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected Confirmation");
+
+    /* Tests for language en-GB */
+    ConfirmationUITranslations_select_lang_id("en-GB");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Double-press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "This confirmation provides an extra layer of security for the action that you're about to take.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Press any volume button to cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected Confirmation");
+
+    /* Tests for language en-IE */
+    ConfirmationUITranslations_select_lang_id("en-IE");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Double-press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "This confirmation provides an extra layer of security for the action that you're about to take.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Press any volume button to cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected Confirmation");
+
+    /* Tests for language en-IN */
+    ConfirmationUITranslations_select_lang_id("en-IN");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Double-press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "This confirmation provides an extra layer of security for the action that you're about to take.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Press any volume button to cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected Confirmation");
+
+    /* Tests for language en-SG */
+    ConfirmationUITranslations_select_lang_id("en-SG");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Double-press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "This confirmation provides an extra layer of security for the action that you're about to take.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Press any volume button to cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected Confirmation");
+
+    /* Tests for language en-XA */
+    ConfirmationUITranslations_select_lang_id("en-XA");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "[Ðöûбļé-þŕéšš þöŵéŕ ţö çöñƒîŕm one two three four five six seven]");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "[Çåñçéļ one]");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "[Ţĥîš çöñƒîŕmåţîöñ þŕövîðéš åñ éxţŕå ļåýéŕ öƒ šéçûŕîţý ƒöŕ ţĥé åçţîöñ ýöû'ŕé åбöûţ ţö ţåķé. one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen]");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "[Þŕéšš þöŵéŕ ţö çöñƒîŕm one two three four five]");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "[Þŕéšš åñý vöļûmé бûţţöñ ţö çåñçéļ one two three four five six seven]");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "[Çåñçéļ one]");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "[Åñðŕöîð Þŕöţéçţéð Çöñƒîŕmåţîöñ one two three four]");
+
+    /* Tests for language en-XC */
+    ConfirmationUITranslations_select_lang_id("en-XC");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‎‏‏‎‎‎‎‎‎‏‏‏‎‏‏‏‎‏‎‏‎‎‏‏‎‎‎‏‎‏‏‎‏‎‎‎‎‎‎‏‎‎‎‎‎‎‏‎‏‎‏‏‎Double-press power to confirm‎‏‎‎‏‎");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‏‎‏‎‏‏‎‏‏‎‏‏‎‎‎‎‎‏‏‎‏‏‏‎‎‎‏‏‏‏‏‎‎‎‎‏‎‎‎‎‏‏‎‎‎‏‏‏‎Cancel‎‏‎‎‏‎");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‏‎‎‎‏‎‏‎‎‏‏‏‏‎‎‎‏‎‏‏‎‎‎‎‏‏‏‎‏‏‎‏‎‏‎‏‏‎‏‎‎‎‎‎‎‏‎This confirmation provides an extra layer of security for the action you're about to take.‎‏‎‎‏‎");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‏‏‏‎‎‏‎‎‎‏‎‏‎‏‎‎‎‏‎‎‎‎‎‎‎‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‎‎‎‎‏‎‎‏‎‎‏‎‎‏‎‏‏‎‎‏‎Press power to confirm‎‏‎‎‏‎");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‎‏‏‏‏‏‎‏‎‏‏‏‎‎‏‏‎‎‎‏‎‏‏‏‏‏‎‎‎‎‏‏‏‎‏‏‏‏‎‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‎Press any volume button to cancel‎‏‎‎‏‎");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‏‎‏‏‎‏‏‏‏‎‎‎‎‎‎‎‎‏‎‏‏‎‏‎‏‏‏‏‎‏‎‎‏‏‏‎‎‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‎‏‎‏‏‏‏‏‏‏‎‏‎Cancel‎‏‎‎‏‎");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‏‏‏‎‏‏‎‎‏‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‎‏‎‏‏‏‎‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‎‎‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‎‎Android Protected Confirmation‎‏‎‎‏‎");
+
+    /* Tests for language en-ZA */
+    ConfirmationUITranslations_select_lang_id("en-ZA");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Double-press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "This confirmation provides an extra layer of security for the action that you're about to take.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Press power to confirm");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Press any volume button to cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancel");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected Confirmation");
+
+    /* Tests for language es */
+    ConfirmationUITranslations_select_lang_id("es");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Pulsa dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona una capa de seguridad adicional a la acción que vas a realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Pulsa el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Pulsa cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación protegida por Android");
+
+    /* Tests for language es-419 */
+    ConfirmationUITranslations_select_lang_id("es-419");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-AR */
+    ConfirmationUITranslations_select_lang_id("es-AR");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-BO */
+    ConfirmationUITranslations_select_lang_id("es-BO");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-CL */
+    ConfirmationUITranslations_select_lang_id("es-CL");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-CO */
+    ConfirmationUITranslations_select_lang_id("es-CO");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-CR */
+    ConfirmationUITranslations_select_lang_id("es-CR");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-DO */
+    ConfirmationUITranslations_select_lang_id("es-DO");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-EC */
+    ConfirmationUITranslations_select_lang_id("es-EC");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-GT */
+    ConfirmationUITranslations_select_lang_id("es-GT");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-HN */
+    ConfirmationUITranslations_select_lang_id("es-HN");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-MX */
+    ConfirmationUITranslations_select_lang_id("es-MX");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-NI */
+    ConfirmationUITranslations_select_lang_id("es-NI");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-PA */
+    ConfirmationUITranslations_select_lang_id("es-PA");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-PE */
+    ConfirmationUITranslations_select_lang_id("es-PE");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-PR */
+    ConfirmationUITranslations_select_lang_id("es-PR");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-PY */
+    ConfirmationUITranslations_select_lang_id("es-PY");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-SV */
+    ConfirmationUITranslations_select_lang_id("es-SV");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-US */
+    ConfirmationUITranslations_select_lang_id("es-US");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-UY */
+    ConfirmationUITranslations_select_lang_id("es-UY");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language es-VE */
+    ConfirmationUITranslations_select_lang_id("es-VE");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Presiona dos veces el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona un nivel de seguridad adicional para la acción que estás por realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Presiona el botón de encendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Presiona cualquier botón de volumen para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmación de protección de Android");
+
+    /* Tests for language et */
+    ConfirmationUITranslations_select_lang_id("et");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Kinnitamiseks topeltvajutage toitenuppu");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Tühista");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "See kinnitus annab veel ühe turvakihi toimingu puhul, mille nüüd teete.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Kinnitamiseks vajutage toitenuppu");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Tühistamiseks vajutage mis tahes helitugevuse nuppu");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Tühista");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Androidi kaitstud kinnitus");
+
+    /* Tests for language eu */
+    ConfirmationUITranslations_select_lang_id("eu");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Berresteko, sakatu birritan pizteko botoia");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Utzi");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Berrespen honek segurtasun handiagoa ematen dizu hurrengo ekintza gauzatzeko.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Berresteko, sakatu etengailua");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Bertan behera uzteko, sakatu bolumen-tekla bat");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Utzi");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android-en babesa izatearen berrespena");
+
+    /* Tests for language fa */
+    ConfirmationUITranslations_select_lang_id("fa");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "برای تأیید، دکمه روشن/خاموش را دوبار فشار دهید");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "لغو");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "این تأیید یک لایه امنیتی اضافی برای کنشی که می‌خواهید انجام دهید فراهم می‌کند.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "برای تأیید، دکمه روشن/خاموش را فشار دهید");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "برای لغو، یکی از دکمه‌های میزان صدا را فشار دهید");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "لغو");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "تأیید محافظت‌شده Android");
+
+    /* Tests for language fi */
+    ConfirmationUITranslations_select_lang_id("fi");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Vahvista painamalla virtapainiketta kahdesti");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Peruuta");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Tämä vahvistus tarkoittaa, että seuraava toimintosi on entistä paremmin suojattu.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Vahvista painamalla virtapainiketta");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Peruuta painamalla äänenvoimakkuuspainiketta");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Peruuta");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Vahvistus Android-suojauksesta");
+
+    /* Tests for language fil */
+    ConfirmationUITranslations_select_lang_id("fil");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Pindutin nang dalawang beses ang power para kumpirmahin");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Kanselahin");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Ang pagkumpirmang ito ay nagbibigay ng karagdagang layer ng seguridad para sa pagkilos na gagawin mo.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Pindutin ang power para kumpirmahin");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Pindutin ang anumang button ng volume para kanselahin");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Kanselahin");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Pagkumpirmang Pinoprotektahan ng Android");
+
+    /* Tests for language fr */
+    ConfirmationUITranslations_select_lang_id("fr");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Appuyez deux fois sur le bouton Marche/Arrêt pour confirmer l'opération");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Annuler");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Cette confirmation ajoute un niveau de sécurité supplémentaire à l'action que vous êtes sur le point d'effectuer.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Appuyez sur le bouton Marche/Arrêt pour confirmer l'opération");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Appuyez sur l'un des boutons de volume pour annuler l'opération");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Annuler");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmation de protection Android");
+
+    /* Tests for language fr-CA */
+    ConfirmationUITranslations_select_lang_id("fr-CA");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Appuyez deux fois sur l'interrupteur pour confirmer");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Annuler");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Cette confirmation fournit une couche supplémentaire de sécurité pour l'action que vous êtes sur le point d'effectuer.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Appuyez sur l'interrupteur pour confirmer");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Appuyez sur un bouton de volume pour annuler l'action");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Annuler");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmation protégée Android");
+
+    /* Tests for language fr-CH */
+    ConfirmationUITranslations_select_lang_id("fr-CH");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Appuyez deux fois sur le bouton Marche/Arrêt pour confirmer l'opération");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Annuler");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Cette confirmation ajoute un niveau de sécurité supplémentaire à l'action que vous êtes sur le point d'effectuer.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Appuyez sur le bouton Marche/Arrêt pour confirmer l'opération");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Appuyez sur l'un des boutons de volume pour annuler l'opération");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Annuler");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmation de protection Android");
+
+    /* Tests for language gl */
+    ConfirmationUITranslations_select_lang_id("gl");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Preme o botón de acendido dúas veces para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmación proporciona unha capa adicional de seguranza para a acción que estás a piques de levar a cabo.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Preme o botón de acendido para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Preme calquera botón de volume para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected Confirmation");
+
+    /* Tests for language gsw */
+    ConfirmationUITranslations_select_lang_id("gsw");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Zum Bestätigen die Ein-/Aus-Taste zweimal drücken");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Abbrechen");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Durch die Bestätigung wird bei der Aktion, die du durchführen möchtest, eine zusätzliche Sicherheitsmaßnahme angewandt.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Drücke zum Bestätigen die Ein-/Aus-Taste");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Zum Abbrechen eine beliebige Lautstärketaste drücken");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Abbrechen");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Bestätigung für Android Protected");
+
+    /* Tests for language gu */
+    ConfirmationUITranslations_select_lang_id("gu");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "કન્ફર્મ કરવા માટે પાવર પર બે વાર ટૅપ કરો");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "રદ કરો");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "તમે જે ક્રિયા કરવાના છો તેના માટે આ કન્ફર્મેશન એક અતિરિક્ત સુરક્ષાનું સ્તર પ્રદાન કરે છે.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "કન્ફર્મ કરવા માટે પાવર બટન દબાવો");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "રદ કરવા માટે કોઈપણ વૉલ્યૂમનું બટન દબાવો");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "રદ કરો");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android પ્રોટેક્ટેડ કન્ફર્મેશન");
+
+    /* Tests for language he */
+    ConfirmationUITranslations_select_lang_id("he");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "יש ללחוץ פעמיים על לחצן ההפעלה כדי לאשר");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "ביטול");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "אישור זה מספק שכבת אבטחה נוספת לפעולה שאתה עומד לבצע.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "יש ללחוץ על לחצן ההפעלה כדי לאשר");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "יש ללחוץ על לחצן כלשהו של עוצמת הקול כדי לבטל");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "ביטול");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected Confirmation");
+
+    /* Tests for language hi */
+    ConfirmationUITranslations_select_lang_id("hi");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "पुष्टि करने के लिए पावर बटन दो बार दबाएं");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "रद्द करें");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "यह पुष्टि मिलने पर आप जो काम करने वाले हैं, उसके लिए सुरक्षा और बढ़ जाती है.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "पुष्टि करने के लिए पावर बटन दबाएं");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "रद्द करने के लिए कोई भी वॉल्यूम बटन दबाएं");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "रद्द करें");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android की ओर से सुरक्षा की पुष्टि");
+
+    /* Tests for language hr */
+    ConfirmationUITranslations_select_lang_id("hr");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Dvaput pritisnite tipku za uključivanje/isključivanje da biste potvrdili");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Otkaži");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Ta potvrda pruža dodatan sloj zaštite za radnju koju ćete izvršiti.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Pritisnite tipku za uključivanje/isključivanje da biste potvrdili");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Pritisnite bilo koju tipku za glasnoću da biste otkazali");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Otkaži");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Potvrda zaštite na Androidu");
+
+    /* Tests for language hu */
+    ConfirmationUITranslations_select_lang_id("hu");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "A megerősítéshez nyomja meg duplán a bekapcsológombot");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Mégse");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Ez a megerősítés extra réteg biztonságot nyújt a végrehajtani kívánt művelet számára.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Nyomja meg a bekapcsológombot a megerősítéshez");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Nyomja meg valamelyik hangerőgombot az elvetéshez");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Mégse");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android – védett megerősítés");
+
+    /* Tests for language hy */
+    ConfirmationUITranslations_select_lang_id("hy");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Հաստատելու համար կրկնակի սեղմեք սնուցման կոճակը");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Չեղարկել");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Այս հաստատումն ապահովում է պաշտպանության լրացուցիչ մակարդակ՝ նախքան գործողություն կատարելը");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Հաստատելու համար սեղմեք սնուցման կոճակը");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Չեղարկելու համար սեղմեք ձայնի կագավորման որևէ կոճակ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Չեղարկել");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected-ի հաստատում");
+
+    /* Tests for language id */
+    ConfirmationUITranslations_select_lang_id("id");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Tekan dua kali tombol power untuk mengonfirmasi");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Batal");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Konfirmasi ini memberikan lapisan keamanan tambahan untuk tindakan yang akan Anda ambil.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Tekan tombol power untuk mengonfirmasi");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Tekan tombol volume apa saja untuk membatalkan");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Batal");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Konfirmasi yang Dilindungi Android");
+
+    /* Tests for language in */
+    ConfirmationUITranslations_select_lang_id("in");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Tekan dua kali tombol power untuk mengonfirmasi");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Batal");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Konfirmasi ini memberikan lapisan keamanan tambahan untuk tindakan yang akan Anda ambil.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Tekan tombol power untuk mengonfirmasi");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Tekan tombol volume apa saja untuk membatalkan");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Batal");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Konfirmasi yang Dilindungi Android");
+
+    /* Tests for language is */
+    ConfirmationUITranslations_select_lang_id("is");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Ýttu tvisvar á aflrofann til að staðfesta");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Hætta við");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Þessi staðfesting veitir aukið öryggi fyrir aðgerðina sem þú ert að fara að framkvæma.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Ýttu á aflrofann til að staðfesta");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Ýttu á hvaða hljóðstyrkshnapp sem er til að hætta við");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Hætta við");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Varin staðfesting Android");
+
+    /* Tests for language it */
+    ConfirmationUITranslations_select_lang_id("it");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Premi due volte il tasto di accensione per confermare");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Annulla");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Questa conferma garantisce un ulteriore livello di sicurezza per l'azione che stai per compiere.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Premi il tasto di accensione per confermare");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Premi qualsiasi pulsante del volume per annullare");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Annulla");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Conferma Android Protected");
+
+    /* Tests for language iw */
+    ConfirmationUITranslations_select_lang_id("iw");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "יש ללחוץ פעמיים על לחצן ההפעלה כדי לאשר");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "ביטול");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "אישור זה מספק שכבת אבטחה נוספת לפעולה שאתה עומד לבצע.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "יש ללחוץ על לחצן ההפעלה כדי לאשר");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "יש ללחוץ על לחצן כלשהו של עוצמת הקול כדי לבטל");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "ביטול");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected Confirmation");
+
+    /* Tests for language ja */
+    ConfirmationUITranslations_select_lang_id("ja");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "確認するには、電源を 2 回押します");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "キャンセル");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "この確認により、これから行う操作のセキュリティが強化されます。");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "確認するには、電源を押します");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "キャンセルするには、いずれかの音量ボタンを押します");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "キャンセル");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected の確認");
+
+    /* Tests for language ka */
+    ConfirmationUITranslations_select_lang_id("ka");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "დასადასტურებლად ორმაგად დააჭირეთ ჩართვის ღილაკს");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "გაუქმება");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "დადასტურება უსაფრთხოების დამატებით შრეს უზრუნველყოფს იმ ქმედების განსახორციელებლად, რომელსაც აპირებთ.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "დასადასტურებლად დააჭირეთ ჩართვის ღილაკს");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "გასაუქმებლად დააჭირეთ ხმის რეგულირების ნებისმიერ ღილაკს");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "გაუქმება");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android-ის დაცული დადასტურება");
+
+    /* Tests for language kk */
+    ConfirmationUITranslations_select_lang_id("kk");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Растау үшін қуат түймесін екі рет басыңыз");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Бас тарту");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Бұл растау функциясы орындағалы тұрған әрекеттің қауіпсіздігін қосымша күшейтеді.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Растау үшін қуат түймесін басыңыз");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Бас тарту үшін кез келген дыбыс деңгейі түймесін басыңыз");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Бас тарту");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android қорғалған растау");
+
+    /* Tests for language km */
+    ConfirmationUITranslations_select_lang_id("km");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "ចុច​ប៊ូតុង​ថាមពល​ពីរដង​ដើម្បី​បញ្ជាក់");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "បោះបង់");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "ការបញ្ជាក់នេះ​ផ្ដល់ស្រទាប់​សុវត្ថិភាព​បន្ថែម​សម្រាប់​សកម្មភាព​ដែលអ្នកហៀប​នឹងធ្វើ។");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "ចុច​ប៊ូតុង​ថាមពល​ដើម្បី​បញ្ជាក់");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "ចុចប៊ូតុង​កម្រិតសំឡេង​ណាមួយ​ដើម្បីបោះបង់");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "បោះបង់");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "ការ​បញ្ជាក់​ដែលបាន​ការពារ Android");
+
+    /* Tests for language kn */
+    ConfirmationUITranslations_select_lang_id("kn");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "ದೃಢೀಕರಿಸಲು ಪವರ್‌ ಬಟನ್‌ ಅನ್ನು ಎರಡು ಬಾರಿ ಒತ್ತಿರಿ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "ರದ್ದು");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "ಈ ದೃಢೀಕರಣವು ನೀವು ನಿರ್ವಹಿಸಲು ಬಯಸುವ ಕ್ರಿಯೆಗೆ ಹೆಚ್ಚುವರಿ ಸುರಕ್ಷತೆಯನ್ನು ಒದಗಿಸುತ್ತದೆ.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "ದೃಢೀಕರಿಸಲು ಪವರ್ ಬಟನ್ ಒತ್ತಿರಿ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "ರದ್ದುಗೊಳಿಸಲು ಯಾವುದೇ ವಾಲ್ಯೂಮ್‌ ಬಟನ್ ಒತ್ತಿರಿ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "ರದ್ದು");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android ಸಂರಕ್ಷಿತ ದೃಢೀಕರಣ");
+
+    /* Tests for language ko */
+    ConfirmationUITranslations_select_lang_id("ko");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "확인하려면 전원 버튼을 두 번 누르세요.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "취소");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "이 확인 단계를 사용하면 실행하려는 작업의 보안을 한층 강화할 수 있습니다.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "확인하려면 전원 버튼을 누르세요.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "취소하려면 볼륨 버튼 중 하나를 누르세요.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "취소");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android 보안 확인");
+
+    /* Tests for language ky */
+    ConfirmationUITranslations_select_lang_id("ky");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Ырастоо үчүн \"Кубат\" баскычын эки жолу басыңыз");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Жокко чыгаруу");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Бул ырастоо сиз аткара турган аракеттин коопсуздугун коргоонун дагы бир катмарын камсыздайт.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Ырастоо үчүн \"Кубат\" баскычын басыңыз");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Жокко чыгаруу үчүн үн көлөмүнүн баскычтарынын бирин басыңыз");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Жокко чыгаруу");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected ырастоосу");
+
+    /* Tests for language ln */
+    ConfirmationUITranslations_select_lang_id("ln");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Appuyez deux fois sur le bouton Marche/Arrêt pour confirmer l'opération");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Annuler");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Cette confirmation ajoute un niveau de sécurité supplémentaire à l'action que vous êtes sur le point d'effectuer.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Appuyez sur le bouton Marche/Arrêt pour confirmer l'opération");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Appuyez sur l'un des boutons de volume pour annuler l'opération");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Annuler");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmation de protection Android");
+
+    /* Tests for language lo */
+    ConfirmationUITranslations_select_lang_id("lo");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "ກົດປຸ່ມປິດເປີດເຄື່ອງສອງຄັ້ງເພື່ອຢືນຢັນ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "ຍົກເລີກ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "ການຢືນຢັນນີ້ຈະເພີ່ມຄວາມປອດໄພເພີ່ມເຕີມອີກໜຶ່ງຊັ້ນໃຫ້ກັບຄຳສັ່ງທີ່ທ່ານກຳລັງຈະໃຊ້.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "ກົດປຸ່ມເປີດປິດເພື່ອຢືນຢັນ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "ກົດປຸ່ມສຽງຂຶ້ນ ຫຼື ລົງເພື່ອຍົກເລີກ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "ຍົກເລີກ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "ການຢືນຢັນ Android ທີ່ໄດ້ຮັບການປົກປ້ອງ");
+
+    /* Tests for language lt */
+    ConfirmationUITranslations_select_lang_id("lt");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Dukart paspauskite maitinimo mygtuką, kad patvirtintumėte");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Atšaukti");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Naudojant šį patvirtinimą, veiksmui, kurį ketinate atlikti, taikomas papildomas saugos lygmuo.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Paspauskite maitinimo mygtuką, kad patvirtintumėte");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Paspauskite bet kurį garsumo mygtuką, kad atšauktumėte");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Atšaukti");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "„Android Protected“ patvirtinimas");
+
+    /* Tests for language lv */
+    ConfirmationUITranslations_select_lang_id("lv");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Lai apstiprinātu, divreiz nospiediet barošanas pogu");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Atcelt");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Šis apstiprinājums sniedz papildu aizsardzību darbībai, kuru veiksiet.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Lai apstiprinātu, nospiediet barošanas pogu");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Lai atceltu, nospiediet jebkuru skaļuma pogu");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Atcelt");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android aizsargātā informācija");
+
+    /* Tests for language mk */
+    ConfirmationUITranslations_select_lang_id("mk");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Притиснете на копчето за напојување двапати за да потврдите");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Откажи");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Оваа потврда обезбедува дополнителен слој на безбедност за дејството што ќе го преземете.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Притиснете на копчето за напојување за да потврдите");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Притиснете на кое било копче за јачина на звук за да откажете");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Откажи");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Потврда за заштита на Android");
+
+    /* Tests for language ml */
+    ConfirmationUITranslations_select_lang_id("ml");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "സ്ഥിരീകരിക്കാൻ പവർ രണ്ടുതവണ അമർത്തുക");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "റദ്ദാക്കുക");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "നിങ്ങൾ സ്വീകരിക്കാൻ പോകുന്ന നടപടിക്കായി, ഈ സ്ഥിരീകരണം ഒരു അധിക സുരക്ഷാ പാളി നൽകുന്നു.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "സ്ഥിരീകരിക്കാൻ പവർ അമർത്തുക");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "റദ്ദാക്കാൻ എതെങ്കിലും വോളിയം ബട്ടൺ അമർത്തുക");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "റദ്ദാക്കുക");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android സംരക്ഷിത സ്ഥിരീകരണം");
+
+    /* Tests for language mn */
+    ConfirmationUITranslations_select_lang_id("mn");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Баталгаажуулахын тулд унтраах/асаахыг хоёр удаа дарах");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Болих");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Энэ баталгаажуулалт нь таны авах гэж буй арга хэмжээнд хамгаалалтын нэмэлт давхаргыг олгодог.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Баталгаажуулахын тулд унтраах/асаахыг дарах");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Болихын тулд дууны түвшний товчлуурын аль нэгийг нь дарах");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Болих");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Андройдоор хамгаалсан баталгаажуулалт");
+
+    /* Tests for language mo */
+    ConfirmationUITranslations_select_lang_id("mo");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Apăsați de două ori butonul de pornire pentru a confirma");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Anulați");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Această confirmare oferă un nivel suplimentar de securitate pentru acțiunea pe care urmează să o faceți.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Apăsați butonul de pornire pentru a confirma");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Apăsați orice buton de volum pentru a anula");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Anulați");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmare protecție pentru Android");
+
+    /* Tests for language mr */
+    ConfirmationUITranslations_select_lang_id("mr");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "खात्री करण्‍यासाठी पॉवर बटण दोनदा दाबा");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "रद्द करा");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "हे निश्चित झाल्‍यावर, तुम्‍ही जे काम करणार आहात, त्‍यासाठी सुरक्षा आणखी वाढते.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "निश्चित करण्‍यासाठी पॉवर दाबा");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "रद्द करण्‍यासाठी कोणतेही व्‍हॉल्‍यूम बटण दाबा");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "रद्द करा");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android कडून सुरक्षा निश्चित करणे");
+
+    /* Tests for language ms */
+    ConfirmationUITranslations_select_lang_id("ms");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Tekan dua kali butang kuasa untuk mengesahkan");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Batal");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Pengesahan ini memberikan lapisan keselamatan tambahan untuk tindakan yang akan anda ambil.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Tekan kuasa untuk mengesahkan");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Tekan sebarang butang kelantangan untuk membatalkan tindakan");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Batal");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Pengesahan Dilindungi Android");
+
+    /* Tests for language my */
+    ConfirmationUITranslations_select_lang_id("my");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "အတည်ပြုရန် ပါဝါခလုတ်ကို နှစ်ချက်နှိပ်ပါ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "မလုပ်တော့");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "ဤအတည်ပြုချက်က သင်ပြုလုပ်တော့မည့် လုပ်ဆောင်ချက်အတွက် အပိုဆောင်းလုံခြုံရေးကို ပေးထားသည်။");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "အတည်ပြုရန် ပါဝါခလုတ်နှိပ်ပါ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "ပယ်ဖျက်ရန် အသံအတိုးအကျယ်ခလုတ် တစ်ခုခုကိုနှိပ်ပါ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "မလုပ်တော့");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android ကာကွယ်မှု အတည်ပြုချက်");
+
+    /* Tests for language nb */
+    ConfirmationUITranslations_select_lang_id("nb");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Dobbelttrykk på av/på-knappen for å bekrefte");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Avbryt");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Denne bekreftelsen gir et ekstra sikkerhetslag for handlingen du er i ferd med å utføre.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Trykk på av/på-knappen for å bekrefte");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Trykk på en volumknapp for å avbryte");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Avbryt");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android-beskyttet bekreftelse");
+
+    /* Tests for language ne */
+    ConfirmationUITranslations_select_lang_id("ne");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "पुष्टि गर्न पावर बटनमा दुई पटक थिच्नुहोस्");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "रद्द गर्नुहोस्");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "यो पुष्टिले तपाईंले गर्न ऑंट्नुभएको कारबाहीका लागि सुरक्षाको अतिरिक्त तह प्रदान गर्छ।");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "पुष्टि गर्न पावर बटनमा थिच्नुहोस्");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "रद्द गर्नका लागि कुनै भोल्युम बटन थिच्नुहोस्");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "रद्द गर्नुहोस्");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android द्वारा संरक्षण गरिएको पुष्टि");
+
+    /* Tests for language nl */
+    ConfirmationUITranslations_select_lang_id("nl");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Druk twee keer op de aan/uit-knop om te bevestigen");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Annuleren");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Deze bevestiging biedt een extra beveiligingslaag voor de actie die je wilt uitvoeren.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Druk op de aan/uit-knop om te bevestigen");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Druk op een volumeknop om te annuleren");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Annuleren");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Bevestiging van Android-beveiliging");
+
+    /* Tests for language no */
+    ConfirmationUITranslations_select_lang_id("no");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Dobbelttrykk på av/på-knappen for å bekrefte");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Avbryt");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Denne bekreftelsen gir et ekstra sikkerhetslag for handlingen du er i ferd med å utføre.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Trykk på av/på-knappen for å bekrefte");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Trykk på en volumknapp for å avbryte");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Avbryt");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android-beskyttet bekreftelse");
+
+    /* Tests for language or */
+    ConfirmationUITranslations_select_lang_id("or");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "ସୁନିଶ୍ଚିତ କରିବା ପାଇଁ ପାୱାର୍‍ ବଟନ୍‍କୁ ଦୁଇଥର ଦବାନ୍ତୁ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "କ୍ୟାନ୍ସଲ୍‍ କରନ୍ତୁ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "ଏହି ସୁନିଶ୍ଚିତତା, ଆପଣ କରିବାକୁ ଯାଉଥିବା କାର୍ଯ୍ୟ ପାଇଁ ଅତିରିକ୍ତ ସୁରକ୍ଷା ପରତ ପ୍ରଦାନ କରିଥାଏ।");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "ସୁନିଶ୍ଚିତ କରିବା ପାଇଁ ପାୱର୍‌ ବଟନ୍‌କୁ ଦାବନ୍ତୁ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "କ୍ୟାନ୍ସଲ୍ କରିବା ପାଇଁ ଯେକୌଣସି ଭଲ୍ୟୁମ୍ ବଟନ୍‌କୁ ଦାବନ୍ତୁ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "କ୍ୟାନ୍ସଲ୍‍ କରନ୍ତୁ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android ଦ୍ୱାରା ସୁରକ୍ଷିତ ହୋଇଥିବାର ସୁନିଶ୍ଚିତତା");
+
+    /* Tests for language pa */
+    ConfirmationUITranslations_select_lang_id("pa");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "ਪੁਸ਼ਟੀ ਕਰਨ ਲਈ ਪਾਵਰ ਬਟਨ ਨੂੰ ਦੋ ਬਾਰ ਦੱਬੋ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "ਰੱਦ ਕਰੋ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "ਇਹ ਪੁਸ਼ਟੀਕਰਨ ਤੁਹਾਡੇ ਵੱਲੋਂ ਕਾਰਵਾਈ ਨੂੰ ਕੀਤੇ ਜਾਣ ਲਈ ਸੁਰੱਖਿਆ ਦੇ ਇੱਕ ਵਾਧੂ ਪੱਧਰ ਮੁਹੱਈਆ ਕਰਦੀ ਹੈ।");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "ਪੁਸ਼ਟੀ ਕਰਨ ਲਈ ਪਾਵਰ ਬਟਨ ਦਬਾਓ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "ਰੱਦ ਕਰਨ ਲਈ ਕਿਸੇ ਵੀ ਵੌਲਿਊਮ ਬਟਨ ਨੂੰ ਦਬਾਓ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "ਰੱਦ ਕਰੋ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android ਵੱਲੋਂ ਸੁਰੱਖਿਆ ਦੀ ਪੁਸ਼ਟੀ");
+
+    /* Tests for language pl */
+    ConfirmationUITranslations_select_lang_id("pl");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Kliknij dwukrotnie przycisk zasilania, by potwierdzić");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Anuluj");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "To potwierdzenie stanowi dodatkowe zabezpieczenie czynności, którą zamierzasz wykonać.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Naciśnij przycisk zasilania, aby potwierdzić");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Naciśnij dowolny przycisk głośności, aby anulować");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Anuluj");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Zabezpieczone potwierdzenie w Androidzie");
+
+    /* Tests for language pt */
+    ConfirmationUITranslations_select_lang_id("pt");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Pressione o botão liga/desliga duas vezes para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Essa confirmação oferece uma camada adicional de segurança para a ação que você está prestes a realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Pressione o botão liga/desliga para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Pressione um dos botões de volume para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmação protegida pelo Android");
+
+    /* Tests for language pt-BR */
+    ConfirmationUITranslations_select_lang_id("pt-BR");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Pressione o botão liga/desliga duas vezes para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Essa confirmação oferece uma camada adicional de segurança para a ação que você está prestes a realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Pressione o botão liga/desliga para confirmar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Pressione um dos botões de volume para cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmação protegida pelo Android");
+
+    /* Tests for language pt-PT */
+    ConfirmationUITranslations_select_lang_id("pt-PT");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Prima duas vezes ligar/desligar para confirmar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Esta confirmação oferece um nível extra de segurança para a ação que está prestes a realizar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Prima ligar/desligar para confirmar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Prima qualquer botão de volume para cancelar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Cancelar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmação protegida do Android");
+
+    /* Tests for language ro */
+    ConfirmationUITranslations_select_lang_id("ro");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Apăsați de două ori butonul de pornire pentru a confirma");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Anulați");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Această confirmare oferă un nivel suplimentar de securitate pentru acțiunea pe care urmează să o faceți.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Apăsați butonul de pornire pentru a confirma");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Apăsați orice buton de volum pentru a anula");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Anulați");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Confirmare protecție pentru Android");
+
+    /* Tests for language ru */
+    ConfirmationUITranslations_select_lang_id("ru");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Для подтверждения дважды нажмите кнопку питания.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Отмена");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Дополнительный уровень защиты для действия, которое вы собираетесь выполнить.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Для подтверждения нажмите кнопку питания.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Для отмены нажмите на любую кнопку регулировки громкости.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Отмена");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Подтверждение Android Protected");
+
+    /* Tests for language si */
+    ConfirmationUITranslations_select_lang_id("si");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "තහවුරු කිරීමට බල බොත්තම දෙවරක් ඔබන්න");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "අවලංගු කරන්න");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "මෙම තහවුරු කිරිම ඔබ ගැනීමට යන ක්‍රියාමාර්ගය සඳහා ආරක්ෂාව පිළිබඳ අමතර ස්තරයක් සපයයි.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "තහවුරු කිරීමට බල බොත්තම ඔබන්න");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "අවලංගු කිරීමට ඕනෑම හඬ පරිමා බොත්තමක් ඔබන්න");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "අවලංගු කරන්න");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android ආරක්ෂිත තහවුරු කිරීම");
+
+    /* Tests for language sk */
+    ConfirmationUITranslations_select_lang_id("sk");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Potvrďte dvojitým stlačením vypínača");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Zrušiť");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Toto potvrdenie zaistí dodatočnú úroveň zabezpečenia akcie, ktorú sa chystáte vykonať.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Potvrďte stlačením vypínača");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Zrušte stlačením ľubovoľného tlačidla hlasitosti");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Zrušiť");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Chránené potvrdenie Androidu");
+
+    /* Tests for language sl */
+    ConfirmationUITranslations_select_lang_id("sl");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Dvakrat pritisnite za potrditev");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Prekliči");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Ta potrditev zagotavlja dodatno plast zaščite za dejanje, ki ga boste izvedli.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Za potrditev pritisnite gumb za vklop");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Za preklic pritisnite poljuben gumb za glasnost");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Prekliči");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Zaščitena potrditev v Androidu");
+
+    /* Tests for language sq */
+    ConfirmationUITranslations_select_lang_id("sq");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Shtyp dy herë butonin e energjisë për të konfirmuar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Anulo");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Konfirmim ofron një shtresë sigurie shtesë për veprimin që je gati për të ndërmarrë.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Shtyp butonin e energjisë për të konfirmuar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Shtyp çdo buton volumi për ta anuluar");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Anulo");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected Confirmation");
+
+    /* Tests for language sr */
+    ConfirmationUITranslations_select_lang_id("sr");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Двапут притисните дугме за напајање да бисте потврдили");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Откажи");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Ова потврда пружа додатни слој безбедности за радњу коју се спремате да извршите.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Притисните дугме за напајање да бисте потврдили");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Притисните било које дугме за јачину звука да бисте отказали");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Откажи");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Потврда заштите на Android-у");
+
+    /* Tests for language sr-Latn */
+    ConfirmationUITranslations_select_lang_id("sr-Latn");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Dvaput pritisnite dugme za napajanje da biste potvrdili");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Otkaži");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Ova potvrda pruža dodatni sloj bezbednosti za radnju koju se spremate da izvršite.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Pritisnite dugme za napajanje da biste potvrdili");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Pritisnite bilo koje dugme za jačinu zvuka da biste otkazali");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Otkaži");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Potvrda zaštite na Android-u");
+
+    /* Tests for language sv */
+    ConfirmationUITranslations_select_lang_id("sv");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Bekräfta genom att trycka två gånger på avstängningsknappen");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Avbryt");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Bekräftelsen ger extra skydd för åtgärden du ska vidta.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Bekräfta genom att trycka på strömbrytaren");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Avbryt genom att trycka på valfri volymknapp");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Avbryt");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Bekräftelseskydd för Android");
+
+    /* Tests for language sw */
+    ConfirmationUITranslations_select_lang_id("sw");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Bonyeza kitufe cha kuwasha mara mbili ili uthibitishe");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Ghairi");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Uthibitishaji huu hutoa ulinzi zaidi wa usalama kwa hatua unayotaka kuchukua.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Bonyeza kitufe cha kuwasha ili uthibitishe");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Bonyeza kitufe chochote cha sauti ili ughairi");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Ghairi");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Uthibitishaji Unaolindwa wa Android");
+
+    /* Tests for language ta */
+    ConfirmationUITranslations_select_lang_id("ta");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "உறுதிப்படுத்த, பவர் பட்டனை இருமுறை அழுத்தவும்");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "ரத்துசெய்");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "நீங்கள் மேற்கொள்ளவிருக்கும் செயலுக்கு, கூடுதல் பாதுகாப்பை இந்த உறுதிப்படுத்தல் வழங்கும்.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "உறுதிப்படுத்த, பவரை அழுத்தவும்");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "ரத்துசெய்ய, ஏதேனும் ஒலியளவு பட்டனை அழுத்தவும்");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "ரத்துசெய்");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android பாதுகாப்பு தொடர்பான உறுதிப்படுத்தல்");
+
+    /* Tests for language te */
+    ConfirmationUITranslations_select_lang_id("te");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "నిర్ధారించడానికి పవర్ బటన్‌ని రెండు సార్లు నొక్కండి");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "రద్దు చేయండి");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "ఈ నిర్ధారణ మీరు తీసుకోబోయే చర్య కోసం అదనపు భద్రతా లేయర్‌ను అందిస్తుంది.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "నిర్ధారించడానికి పవర్‌ను నొక్కండి");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "రద్దు చేయడానికి ఏదైనా వాల్యూమ్ బటన్‌ను నొక్కండి");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "రద్దు చేయండి");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android సురక్షిత నిర్ధారణ");
+
+    /* Tests for language th */
+    ConfirmationUITranslations_select_lang_id("th");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "กดปุ่มเปิด/ปิด 2 ครั้งเพื่อยืนยัน");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "ยกเลิก");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "การยืนยันนี้จะช่วยเพิ่มความปลอดภัยอีกขั้นสำหรับสิ่งที่คุณกำลังจะดำเนินการ");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "กดปุ่มเปิด/ปิดเพื่อยืนยัน");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "กดปุ่มปรับระดับเสียงเพื่อยกเลิก");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "ยกเลิก");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "ยืนยันการป้องกัน Android");
+
+    /* Tests for language tl */
+    ConfirmationUITranslations_select_lang_id("tl");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Pindutin nang dalawang beses ang power para kumpirmahin");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Kanselahin");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Ang pagkumpirmang ito ay nagbibigay ng karagdagang layer ng seguridad para sa pagkilos na gagawin mo.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Pindutin ang power para kumpirmahin");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Pindutin ang anumang button ng volume para kanselahin");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Kanselahin");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Pagkumpirmang Pinoprotektahan ng Android");
+
+    /* Tests for language tr */
+    ConfirmationUITranslations_select_lang_id("tr");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Onaylamak için güç düğmesine iki kez basın");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "İptal");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Bu onay, yapmak üzere olduğunuz işlem için ek güvenlik katmanı sağlar.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Onaylamak için güç düğmesine basın");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "İptal etmek için herhangi bir ses düğmesine basın");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "İptal");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Korumalı Onayı");
+
+    /* Tests for language uk */
+    ConfirmationUITranslations_select_lang_id("uk");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Двічі натисніть кнопку живлення, щоб підтвердити");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Скасувати");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Це підтвердження є додатковим рівнем захисту, коли ви збираєтеся виконати дію.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Натисніть кнопку живлення, щоб підтвердити");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Натисніть будь-яку клавішу гучності, щоб скасувати");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Скасувати");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Підтвердження Android Protected");
+
+    /* Tests for language ur */
+    ConfirmationUITranslations_select_lang_id("ur");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "تصدیق کرنے کے لئے پاور بٹن دوبار دبائیں");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "منسوخ کریں");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "آپ جو کارروائی کرنے والے ہیں اس کے لئے یہ تصدیق ایک اضافی پرت فراہم کرتی ہے۔");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "تصدیق کرنے کے لئے پاور بٹن دبائیں");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "منسوخ کرنے کے لئے کوئی بھی والیوم بٹن دبائیں");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "منسوخ کریں");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android کی تحفظ یافتہ تصدیق");
+
+    /* Tests for language uz */
+    ConfirmationUITranslations_select_lang_id("uz");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Tasdiqlash uchun quvvat tugmasini ikki marta bosing");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Bekor qilish");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Tasdiqlangandan keyin bajarilayotgan amal uchun qo‘shimcha xavfsizlik qatlami taqdim etiladi.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Tasdiqlash uchun quvvat tugmasini bosing");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Bekor qilish uchun istalgan tovush tugmasini bosing");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Bekor qilish");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected nomli tasdiq");
+
+    /* Tests for language vi */
+    ConfirmationUITranslations_select_lang_id("vi");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Nhấn hai lần vào nút nguồn để xác nhận");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Hủy");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Xác nhận này cung cấp thêm một lớp bảo mật cho hành động bạn sắp thực hiện.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Nhấn vào nút nguồn để xác nhận");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Nhấn vào nút âm lượng bất kỳ để hủy");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Hủy");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Xác nhận bảo vệ Android");
+
+    /* Tests for language zh */
+    ConfirmationUITranslations_select_lang_id("zh");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "连按两次电源按钮即可确认");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "取消");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "这项确认可为您即将执行的操作增添一层额外的安全保障。");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "按电源按钮即可确认");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "按任意音量按钮即可取消");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "取消");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android 保护确认");
+
+    /* Tests for language zh-CN */
+    ConfirmationUITranslations_select_lang_id("zh-CN");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "连按两次电源按钮即可确认");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "取消");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "这项确认可为您即将执行的操作增添一层额外的安全保障。");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "按电源按钮即可确认");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "按任意音量按钮即可取消");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "取消");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android 保护确认");
+
+    /* Tests for language zh-HK */
+    ConfirmationUITranslations_select_lang_id("zh-HK");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "按兩下電源按鈕即可確認");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "取消");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "此確認可為你即將執行的操作提供額外安全保障。");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "按下電源按鈕即可確認");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "按下任何音量按鈕即可取消");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "取消");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android 保護確認");
+
+    /* Tests for language zh-TW */
+    ConfirmationUITranslations_select_lang_id("zh-TW");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "按兩下電源按鈕即可確認操作");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "取消");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "這項確認作業可為你即將執行的動作提供多一層安全保障。");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "按下電源按鈕即可確認操作");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "按下任一音量按鈕即可取消操作");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "取消");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Android Protected 確認");
+
+    /* Tests for language zu */
+    ConfirmationUITranslations_select_lang_id("zu");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1424834532030812203"), "Cindezela kabili ukuze uqinisekise");
+    ASSERT_STR(ConfirmationUITranslations_lookup("1796282799666106567"), "Khansela");
+    ASSERT_STR(ConfirmationUITranslations_lookup("217688588483778177"), "Lokhu kuqinisekiswa kunikeza isendlalelo esingeziwe sokuvikelwa sesenzo osuzosithatha.");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2181224373757710937"), "Cindezela amandla ukuze uqinisekise");
+    ASSERT_STR(ConfirmationUITranslations_lookup("2213954494039981979"), "Cindezela noma iyiphi inkinobho yevolumu ukuze ukhansele");
+    ASSERT_STR(ConfirmationUITranslations_lookup("3999296476990449149"), "Khansela");
+    ASSERT_STR(ConfirmationUITranslations_lookup("6973195374358399966"), "Ukuqinisekiswa okuvikelwe i-Android");
+
+    /* Check language tag fallback mechanism works
+       (chop off components until a match has been found) */
+    const char* lang_ids[] = {
+        "de",
+        "da",
+        "da-GL",
+        "es-419",
+        "es-AR",
+        NULL
+    };
+    ASSERT_STR(test_lang_id_match(lang_ids, "de"), "de");
+    ASSERT_STR(test_lang_id_match(lang_ids, "de-DE"), "de");
+    ASSERT_STR(test_lang_id_match(lang_ids, "de-CH-1901"), "de");
+    ASSERT_STR(test_lang_id_match(lang_ids, "de-AT"), "de");
+    ASSERT_STR(test_lang_id_match(lang_ids, "da-DK"), "da");
+    ASSERT_STR(test_lang_id_match(lang_ids, "da-GL"), "da-GL");
+    ASSERT_STR(test_lang_id_match(lang_ids, "zh"), "");
+    ASSERT_STR(test_lang_id_match(lang_ids, "es-419"), "es-419");
+    ASSERT_STR(test_lang_id_match(lang_ids, "es-AR"), "es-AR");
+    ASSERT_STR(test_lang_id_match(lang_ids, "es"), "");
+
+    printf("All unit tests passed.\n");
+    return 0;
+}
diff --git a/contexthub/1.0/Android.bp b/contexthub/1.0/Android.bp
index 730adcb..71dd978 100644
--- a/contexthub/1.0/Android.bp
+++ b/contexthub/1.0/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/contexthub/1.0/default/Android.bp b/contexthub/1.0/default/Android.bp
index d1db6a6..8384037 100644
--- a/contexthub/1.0/default/Android.bp
+++ b/contexthub/1.0/default/Android.bp
@@ -28,7 +28,6 @@
         "libcutils",
         "libutils",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.contexthub@1.0",
     ],
 }
@@ -47,7 +46,6 @@
         "libdl",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
         "android.hardware.contexthub@1.0",
diff --git a/contexthub/1.0/default/OWNERS b/contexthub/1.0/default/OWNERS
index 5373073..90c2330 100644
--- a/contexthub/1.0/default/OWNERS
+++ b/contexthub/1.0/default/OWNERS
@@ -1,4 +1,3 @@
-aarossig@google.com
 arthuri@google.com
 bduddie@google.com
-bstack@google.com
+stange@google.com
diff --git a/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc b/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
index a8c9487..b659be8 100644
--- a/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
+++ b/contexthub/1.0/default/android.hardware.contexthub@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.contexthub-hal-1-0 /vendor/bin/hw/android.hardware.contexthub@1.0-service
+    interface android.hardware.contexthub@1.0::IContexthub default
     class hal
     user system
     group system
diff --git a/contexthub/1.0/vts/functional/OWNERS b/contexthub/1.0/vts/functional/OWNERS
index ee01441..045cc4e 100644
--- a/contexthub/1.0/vts/functional/OWNERS
+++ b/contexthub/1.0/vts/functional/OWNERS
@@ -1,8 +1,7 @@
 #Context Hub team
-aarossig@google.com
 arthuri@google.com
 bduddie@google.com
-bstack@google.com
+stange@google.com
 
 #VTS team
 yim@google.com
diff --git a/current.txt b/current.txt
index 47e7d72..972fe16 100644
--- a/current.txt
+++ b/current.txt
@@ -570,3 +570,19 @@
 09e08b5d12b109562ecdd8882532fd1f2c4639588e07769d5c7396b7c5b9f34f android.hardware.wifi.supplicant@1.2::ISupplicantStaIfaceCallback
 efbb061c969fa9553d243da6ee23b83fe5d4aa663a7b8896adc52e2b015bc2f3 android.hardware.wifi.supplicant@1.2::ISupplicantStaNetwork
 cfa81f229b69f9011c58f48264fcb552447430fe68610eac514e811e65bc306a android.hardware.wifi.supplicant@1.2::types
+
+# ABI preserving changes to HALs during Android R
+b69a7615c508acf5c5201efd1bfa3262167874fc3594e2db5a3ff93addd8ac75 android.hardware.keymaster@4.0::IKeymasterDevice
+eb2fa0c883c2185d514be0b84c179b283753ef0c1b77b45b4f359bd23bba8b75 android.hardware.neuralnetworks@1.0::IPreparedModel
+f1109cbb10297b7429a11fab42afa912710b303c9bf20bd5cdb8bd57b9c84186 android.hardware.neuralnetworks@1.0::types
+9d8ee57c490ffeaa28f702eaea8d198cb510e4bbfb99e6cb5f63e73341057c7c android.hardware.neuralnetworks@1.1::types
+fb382e986c10b8fbb797a8546e8f9ea6d1107bfe6f3fb7e57f6bbbf1f807a906 android.hardware.neuralnetworks@1.2::IDevice
+40e71cd693de5b832325c5d8f081f2ff20a7ba2b89d401cee5b4b3eb0e241681 android.hardware.neuralnetworks@1.2::IPreparedModel
+71c0f7127335e5b74d1615d5e7f129831b43ffbae5318ad0924d7d8d8910a859 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
+
+# HALs released in Android R
+07d0a252b2d8fa35887908a996ba395cf392968395fc30afab791f46e0c22a52 android.hardware.boot@1.1::IBootControl
+74049a402be913963edfdd80828a53736570e9d8124a1bf18166b6ed46a6b0ab android.hardware.boot@1.1::types
diff --git a/drm/1.0/Android.bp b/drm/1.0/Android.bp
index fea851f..a950c57 100644
--- a/drm/1.0/Android.bp
+++ b/drm/1.0/Android.bp
@@ -19,4 +19,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/drm/1.0/default/Android.mk b/drm/1.0/default/Android.mk
index d66f377..9016dc3 100644
--- a/drm/1.0/default/Android.mk
+++ b/drm/1.0/default/Android.mk
@@ -59,7 +59,6 @@
     libcutils \
     libhidlbase \
     libhidlmemory \
-    libhidltransport \
     liblog \
     libstagefright_foundation \
     libutils \
diff --git a/drm/1.0/default/common_default_service.mk b/drm/1.0/default/common_default_service.mk
index 28db567..1b5a975 100644
--- a/drm/1.0/default/common_default_service.mk
+++ b/drm/1.0/default/common_default_service.mk
@@ -21,7 +21,6 @@
   android.hardware.drm@1.0 \
   android.hidl.memory@1.0 \
   libhidlbase \
-  libhidltransport \
   libhardware \
   liblog \
   libutils \
diff --git a/drm/1.0/vts/functional/Android.bp b/drm/1.0/vts/functional/Android.bp
index d6ebfdd..61d4d58 100644
--- a/drm/1.0/vts/functional/Android.bp
+++ b/drm/1.0/vts/functional/Android.bp
@@ -30,7 +30,7 @@
         "libhidlmemory",
         "libnativehelper",
         "libssl",
-        "libcrypto",
+        "libcrypto_static",
     ],
     test_suites: ["general-tests"],
 }
diff --git a/drm/1.1/Android.bp b/drm/1.1/Android.bp
index 739b470..16010a6 100644
--- a/drm/1.1/Android.bp
+++ b/drm/1.1/Android.bp
@@ -18,4 +18,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/drm/1.1/vts/functional/Android.bp b/drm/1.1/vts/functional/Android.bp
index 1090b69..47b02bf 100644
--- a/drm/1.1/vts/functional/Android.bp
+++ b/drm/1.1/vts/functional/Android.bp
@@ -29,7 +29,6 @@
         "libhidlmemory",
         "libnativehelper",
         "libssl",
-        "libcrypto",
     ],
     test_suites: ["general-tests"],
 }
diff --git a/drm/1.2/Android.bp b/drm/1.2/Android.bp
index 2d54302..9104aa9 100644
--- a/drm/1.2/Android.bp
+++ b/drm/1.2/Android.bp
@@ -21,4 +21,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/drm/1.2/vts/functional/Android.bp b/drm/1.2/vts/functional/Android.bp
index 6b4a4c0..95883bf 100644
--- a/drm/1.2/vts/functional/Android.bp
+++ b/drm/1.2/vts/functional/Android.bp
@@ -34,7 +34,7 @@
         "libhidlmemory",
         "libnativehelper",
         "libssl",
-        "libcrypto",
+        "libcrypto_static",
     ],
     test_suites: ["general-tests"],
 }
diff --git a/dumpstate/1.0/Android.bp b/dumpstate/1.0/Android.bp
index 29be116..3d47550 100644
--- a/dumpstate/1.0/Android.bp
+++ b/dumpstate/1.0/Android.bp
@@ -14,4 +14,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/dumpstate/1.0/default/Android.bp b/dumpstate/1.0/default/Android.bp
index 3ca19e8..6b02715 100644
--- a/dumpstate/1.0/default/Android.bp
+++ b/dumpstate/1.0/default/Android.bp
@@ -1,5 +1,5 @@
 cc_binary {
-    name: "android.hardware.dumpstate@1.0-service",
+    name: "android.hardware.dumpstate@1.0-service.example",
     init_rc: ["android.hardware.dumpstate@1.0-service.rc"],
     relative_install_path: "hw",
     vendor: true,
@@ -18,7 +18,6 @@
         "libcutils",
         "libdumpstateutil",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
     ],
diff --git a/dumpstate/1.0/default/DumpstateDevice.cpp b/dumpstate/1.0/default/DumpstateDevice.cpp
index 25d92b0..c57bf43 100644
--- a/dumpstate/1.0/default/DumpstateDevice.cpp
+++ b/dumpstate/1.0/default/DumpstateDevice.cpp
@@ -37,11 +37,6 @@
     // NOTE: this is just an example on how to use the DumpstateUtil.h functions to implement
     // this interface.
 
-    // Exit when dump is completed since this is a lazy HAL.
-    addPostCommandTask([]() {
-        exit(0);
-    });
-
     if (handle == nullptr || handle->numFds < 1) {
         ALOGE("no FDs\n");
         return Void();
diff --git a/dumpstate/1.0/default/android.hardware.dumpstate@1.0-service.rc b/dumpstate/1.0/default/android.hardware.dumpstate@1.0-service.rc
index 062a291..03298dc 100644
--- a/dumpstate/1.0/default/android.hardware.dumpstate@1.0-service.rc
+++ b/dumpstate/1.0/default/android.hardware.dumpstate@1.0-service.rc
@@ -1,4 +1,4 @@
-service vendor.dumpstate-1-0 /vendor/bin/hw/android.hardware.dumpstate@1.0-service
+service vendor.dumpstate-1-0 /vendor/bin/hw/android.hardware.dumpstate@1.0-service.example
     class hal
     user system
     group system
diff --git a/dumpstate/1.0/default/service.cpp b/dumpstate/1.0/default/service.cpp
index 4f276b7..76c72b5 100644
--- a/dumpstate/1.0/default/service.cpp
+++ b/dumpstate/1.0/default/service.cpp
@@ -15,22 +15,26 @@
  */
 #define LOG_TAG "android.hardware.dumpstate@1.0-service"
 
+#include <hidl/HidlLazyUtils.h>
 #include <hidl/HidlSupport.h>
 #include <hidl/HidlTransportSupport.h>
 
 #include "DumpstateDevice.h"
 
-using ::android::hardware::configureRpcThreadpool;
-using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
-using ::android::hardware::dumpstate::V1_0::implementation::DumpstateDevice;
-using ::android::hardware::joinRpcThreadpool;
 using ::android::OK;
 using ::android::sp;
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::joinRpcThreadpool;
+using ::android::hardware::LazyServiceRegistrar;
+using ::android::hardware::dumpstate::V1_0::IDumpstateDevice;
+using ::android::hardware::dumpstate::V1_0::implementation::DumpstateDevice;
 
 int main(int /* argc */, char* /* argv */ []) {
     sp<IDumpstateDevice> dumpstate = new DumpstateDevice;
     configureRpcThreadpool(1, true /* will join */);
-    if (dumpstate->registerAsService() != OK) {
+
+    auto registrar = LazyServiceRegistrar::getInstance();
+    if (registrar.registerService(dumpstate) != OK) {
         ALOGE("Could not register service.");
         return 1;
     }
diff --git a/fastboot/1.0/Android.bp b/fastboot/1.0/Android.bp
index ea3566f..ec447b8 100644
--- a/fastboot/1.0/Android.bp
+++ b/fastboot/1.0/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/fastboot/1.0/default/Android.bp b/fastboot/1.0/default/Android.bp
index fde7efa..f7b3635 100644
--- a/fastboot/1.0/default/Android.bp
+++ b/fastboot/1.0/default/Android.bp
@@ -23,7 +23,6 @@
     shared_libs: [
         "libbase",
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "libcutils",
         "android.hardware.fastboot@1.0",
diff --git a/gatekeeper/1.0/Android.bp b/gatekeeper/1.0/Android.bp
index 7eff2e8..5d63eaf 100644
--- a/gatekeeper/1.0/Android.bp
+++ b/gatekeeper/1.0/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/gatekeeper/1.0/default/Android.bp b/gatekeeper/1.0/default/Android.bp
index ae3b91c..2be4f4d 100644
--- a/gatekeeper/1.0/default/Android.bp
+++ b/gatekeeper/1.0/default/Android.bp
@@ -10,7 +10,6 @@
         "android.hardware.gatekeeper@1.0",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "liblog",
     ],
@@ -30,7 +29,6 @@
         "android.hardware.gatekeeper@1.0",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "liblog",
     ],
diff --git a/gatekeeper/1.0/default/OWNERS b/gatekeeper/1.0/default/OWNERS
new file mode 100644
index 0000000..335660d
--- /dev/null
+++ b/gatekeeper/1.0/default/OWNERS
@@ -0,0 +1,2 @@
+jdanis@google.com
+swillden@google.com
diff --git a/gatekeeper/1.0/default/android.hardware.gatekeeper@1.0-service.rc b/gatekeeper/1.0/default/android.hardware.gatekeeper@1.0-service.rc
index da332c7..b13a9ba 100644
--- a/gatekeeper/1.0/default/android.hardware.gatekeeper@1.0-service.rc
+++ b/gatekeeper/1.0/default/android.hardware.gatekeeper@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.gatekeeper-1-0 /vendor/bin/hw/android.hardware.gatekeeper@1.0-service
+    interface android.hardware.gatekeeper@1.0::IGatekeeper default
     class hal
     user system
     group system
diff --git a/gatekeeper/1.0/software/Android.bp b/gatekeeper/1.0/software/Android.bp
new file mode 100644
index 0000000..24c81f6
--- /dev/null
+++ b/gatekeeper/1.0/software/Android.bp
@@ -0,0 +1,27 @@
+cc_binary {
+    name: "android.hardware.gatekeeper@1.0-service.software",
+    defaults: ["hidl_defaults"],
+    relative_install_path: "hw",
+    vendor: true,
+    init_rc: ["android.hardware.gatekeeper@1.0-service.software.rc"],
+
+    srcs: [
+        "service.cpp",
+        "SoftGateKeeperDevice.cpp",
+    ],
+
+    shared_libs: [
+        "android.hardware.gatekeeper@1.0",
+        "libbase",
+        "libhardware",
+        "libhidlbase",
+        "libutils",
+        "liblog",
+        "libcrypto",
+        "libgatekeeper",
+    ],
+
+    static_libs: ["libscrypt_static"],
+
+    vintf_fragments: ["android.hardware.gatekeeper@1.0-service.software.xml"],
+}
diff --git a/gatekeeper/1.0/software/OWNERS b/gatekeeper/1.0/software/OWNERS
new file mode 100644
index 0000000..335660d
--- /dev/null
+++ b/gatekeeper/1.0/software/OWNERS
@@ -0,0 +1,2 @@
+jdanis@google.com
+swillden@google.com
diff --git a/gatekeeper/1.0/software/SoftGateKeeper.h b/gatekeeper/1.0/software/SoftGateKeeper.h
new file mode 100644
index 0000000..3276d1e
--- /dev/null
+++ b/gatekeeper/1.0/software/SoftGateKeeper.h
@@ -0,0 +1,171 @@
+/*
+ * Copyright 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.
+ *
+ */
+
+#ifndef SOFT_GATEKEEPER_H_
+#define SOFT_GATEKEEPER_H_
+
+extern "C" {
+#include <openssl/rand.h>
+#include <openssl/sha.h>
+
+#include <crypto_scrypt.h>
+}
+
+#include <android-base/memory.h>
+#include <gatekeeper/gatekeeper.h>
+
+#include <iostream>
+#include <memory>
+#include <unordered_map>
+
+namespace gatekeeper {
+
+struct fast_hash_t {
+    uint64_t salt;
+    uint8_t digest[SHA256_DIGEST_LENGTH];
+};
+
+class SoftGateKeeper : public GateKeeper {
+  public:
+    static const uint32_t SIGNATURE_LENGTH_BYTES = 32;
+
+    // scrypt params
+    static const uint64_t N = 16384;
+    static const uint32_t r = 8;
+    static const uint32_t p = 1;
+
+    static const int MAX_UINT_32_CHARS = 11;
+
+    SoftGateKeeper() {
+        key_.reset(new uint8_t[SIGNATURE_LENGTH_BYTES]);
+        memset(key_.get(), 0, SIGNATURE_LENGTH_BYTES);
+    }
+
+    virtual ~SoftGateKeeper() {}
+
+    virtual bool GetAuthTokenKey(const uint8_t** auth_token_key, uint32_t* length) const {
+        if (auth_token_key == NULL || length == NULL) return false;
+        *auth_token_key = key_.get();
+        *length = SIGNATURE_LENGTH_BYTES;
+        return true;
+    }
+
+    virtual void GetPasswordKey(const uint8_t** password_key, uint32_t* length) {
+        if (password_key == NULL || length == NULL) return;
+        *password_key = key_.get();
+        *length = SIGNATURE_LENGTH_BYTES;
+    }
+
+    virtual void ComputePasswordSignature(uint8_t* signature, uint32_t signature_length,
+                                          const uint8_t*, uint32_t, const uint8_t* password,
+                                          uint32_t password_length, salt_t salt) const {
+        if (signature == NULL) return;
+        crypto_scrypt(password, password_length, reinterpret_cast<uint8_t*>(&salt), sizeof(salt), N,
+                      r, p, signature, signature_length);
+    }
+
+    virtual void GetRandom(void* random, uint32_t requested_length) const {
+        if (random == NULL) return;
+        RAND_pseudo_bytes((uint8_t*)random, requested_length);
+    }
+
+    virtual void ComputeSignature(uint8_t* signature, uint32_t signature_length, const uint8_t*,
+                                  uint32_t, const uint8_t*, const uint32_t) const {
+        if (signature == NULL) return;
+        memset(signature, 0, signature_length);
+    }
+
+    virtual uint64_t GetMillisecondsSinceBoot() const {
+        struct timespec time;
+        int res = clock_gettime(CLOCK_BOOTTIME, &time);
+        if (res < 0) return 0;
+        return (time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000);
+    }
+
+    virtual bool IsHardwareBacked() const { return false; }
+
+    virtual bool GetFailureRecord(uint32_t uid, secure_id_t user_id, failure_record_t* record,
+                                  bool /* secure */) {
+        failure_record_t* stored = &failure_map_[uid];
+        if (user_id != stored->secure_user_id) {
+            stored->secure_user_id = user_id;
+            stored->last_checked_timestamp = 0;
+            stored->failure_counter = 0;
+        }
+        memcpy(record, stored, sizeof(*record));
+        return true;
+    }
+
+    virtual bool ClearFailureRecord(uint32_t uid, secure_id_t user_id, bool /* secure */) {
+        failure_record_t* stored = &failure_map_[uid];
+        stored->secure_user_id = user_id;
+        stored->last_checked_timestamp = 0;
+        stored->failure_counter = 0;
+        return true;
+    }
+
+    virtual bool WriteFailureRecord(uint32_t uid, failure_record_t* record, bool /* secure */) {
+        failure_map_[uid] = *record;
+        return true;
+    }
+
+    fast_hash_t ComputeFastHash(const SizedBuffer& password, uint64_t salt) {
+        fast_hash_t fast_hash;
+        size_t digest_size = password.size() + sizeof(salt);
+        std::unique_ptr<uint8_t[]> digest(new uint8_t[digest_size]);
+        memcpy(digest.get(), &salt, sizeof(salt));
+        memcpy(digest.get() + sizeof(salt), password.Data<uint8_t>(), password.size());
+
+        SHA256(digest.get(), digest_size, (uint8_t*)&fast_hash.digest);
+
+        fast_hash.salt = salt;
+        return fast_hash;
+    }
+
+    bool VerifyFast(const fast_hash_t& fast_hash, const SizedBuffer& password) {
+        fast_hash_t computed = ComputeFastHash(password, fast_hash.salt);
+        return memcmp(computed.digest, fast_hash.digest, SHA256_DIGEST_LENGTH) == 0;
+    }
+
+    bool DoVerify(const password_handle_t* expected_handle, const SizedBuffer& password) {
+        uint64_t user_id = android::base::get_unaligned<secure_id_t>(&expected_handle->user_id);
+        FastHashMap::const_iterator it = fast_hash_map_.find(user_id);
+        if (it != fast_hash_map_.end() && VerifyFast(it->second, password)) {
+            return true;
+        } else {
+            if (GateKeeper::DoVerify(expected_handle, password)) {
+                uint64_t salt;
+                GetRandom(&salt, sizeof(salt));
+                fast_hash_map_[user_id] = ComputeFastHash(password, salt);
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+  private:
+    typedef std::unordered_map<uint32_t, failure_record_t> FailureRecordMap;
+    typedef std::unordered_map<uint64_t, fast_hash_t> FastHashMap;
+
+    std::unique_ptr<uint8_t[]> key_;
+    FailureRecordMap failure_map_;
+    FastHashMap fast_hash_map_;
+};
+}  // namespace gatekeeper
+
+#endif  // SOFT_GATEKEEPER_H_
diff --git a/gatekeeper/1.0/software/SoftGateKeeperDevice.cpp b/gatekeeper/1.0/software/SoftGateKeeperDevice.cpp
new file mode 100644
index 0000000..d7a0b46
--- /dev/null
+++ b/gatekeeper/1.0/software/SoftGateKeeperDevice.cpp
@@ -0,0 +1,114 @@
+/*
+ * 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 "SoftGateKeeperDevice.h"
+#include "SoftGateKeeper.h"
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::gatekeeper::V1_0::GatekeeperStatusCode;
+using ::gatekeeper::EnrollRequest;
+using ::gatekeeper::EnrollResponse;
+using ::gatekeeper::ERROR_INVALID;
+using ::gatekeeper::ERROR_MEMORY_ALLOCATION_FAILED;
+using ::gatekeeper::ERROR_NONE;
+using ::gatekeeper::ERROR_RETRY;
+using ::gatekeeper::SizedBuffer;
+using ::gatekeeper::VerifyRequest;
+using ::gatekeeper::VerifyResponse;
+
+#include <limits>
+
+namespace android {
+
+inline SizedBuffer hidl_vec2sized_buffer(const hidl_vec<uint8_t>& vec) {
+    if (vec.size() == 0 || vec.size() > std::numeric_limits<uint32_t>::max()) return {};
+    auto dummy = new uint8_t[vec.size()];
+    std::copy(vec.begin(), vec.end(), dummy);
+    return {dummy, static_cast<uint32_t>(vec.size())};
+}
+
+Return<void> SoftGateKeeperDevice::enroll(uint32_t uid,
+                                          const hidl_vec<uint8_t>& currentPasswordHandle,
+                                          const hidl_vec<uint8_t>& currentPassword,
+                                          const hidl_vec<uint8_t>& desiredPassword,
+                                          enroll_cb _hidl_cb) {
+    if (desiredPassword.size() == 0) {
+        _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+        return {};
+    }
+
+    EnrollRequest request(uid, hidl_vec2sized_buffer(currentPasswordHandle),
+                          hidl_vec2sized_buffer(desiredPassword),
+                          hidl_vec2sized_buffer(currentPassword));
+    EnrollResponse response;
+    impl_->Enroll(request, &response);
+
+    if (response.error == ERROR_RETRY) {
+        _hidl_cb({GatekeeperStatusCode::ERROR_RETRY_TIMEOUT, response.retry_timeout, {}});
+    } else if (response.error != ERROR_NONE) {
+        _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+    } else {
+        hidl_vec<uint8_t> new_handle(response.enrolled_password_handle.Data<uint8_t>(),
+                                     response.enrolled_password_handle.Data<uint8_t>() +
+                                             response.enrolled_password_handle.size());
+        _hidl_cb({GatekeeperStatusCode::STATUS_OK, response.retry_timeout, new_handle});
+    }
+    return {};
+}
+
+Return<void> SoftGateKeeperDevice::verify(
+        uint32_t uid, uint64_t challenge,
+        const ::android::hardware::hidl_vec<uint8_t>& enrolledPasswordHandle,
+        const ::android::hardware::hidl_vec<uint8_t>& providedPassword, verify_cb _hidl_cb) {
+    if (enrolledPasswordHandle.size() == 0) {
+        _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+        return {};
+    }
+
+    VerifyRequest request(uid, challenge, hidl_vec2sized_buffer(enrolledPasswordHandle),
+                          hidl_vec2sized_buffer(providedPassword));
+    VerifyResponse response;
+
+    impl_->Verify(request, &response);
+
+    if (response.error == ERROR_RETRY) {
+        _hidl_cb({GatekeeperStatusCode::ERROR_RETRY_TIMEOUT, response.retry_timeout, {}});
+    } else if (response.error != ERROR_NONE) {
+        _hidl_cb({GatekeeperStatusCode::ERROR_GENERAL_FAILURE, 0, {}});
+    } else {
+        hidl_vec<uint8_t> auth_token(
+                response.auth_token.Data<uint8_t>(),
+                response.auth_token.Data<uint8_t>() + response.auth_token.size());
+
+        _hidl_cb({response.request_reenroll ? GatekeeperStatusCode::STATUS_REENROLL
+                                            : GatekeeperStatusCode::STATUS_OK,
+                  response.retry_timeout, auth_token});
+    }
+    return {};
+}
+
+Return<void> SoftGateKeeperDevice::deleteUser(uint32_t /*uid*/, deleteUser_cb _hidl_cb) {
+    _hidl_cb({GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED, 0, {}});
+    return {};
+}
+
+Return<void> SoftGateKeeperDevice::deleteAllUsers(deleteAllUsers_cb _hidl_cb) {
+    _hidl_cb({GatekeeperStatusCode::ERROR_NOT_IMPLEMENTED, 0, {}});
+    return {};
+}
+
+}  // namespace android
diff --git a/gatekeeper/1.0/software/SoftGateKeeperDevice.h b/gatekeeper/1.0/software/SoftGateKeeperDevice.h
new file mode 100644
index 0000000..17b474e
--- /dev/null
+++ b/gatekeeper/1.0/software/SoftGateKeeperDevice.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright 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.
+ */
+
+#ifndef SOFT_GATEKEEPER_DEVICE_H_
+#define SOFT_GATEKEEPER_DEVICE_H_
+
+#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
+#include <hidl/Status.h>
+
+#include <memory>
+#include "SoftGateKeeper.h"
+
+namespace android {
+
+/**
+ * Software based GateKeeper implementation
+ */
+class SoftGateKeeperDevice : public ::android::hardware::gatekeeper::V1_0::IGatekeeper {
+  public:
+    SoftGateKeeperDevice() { impl_.reset(new ::gatekeeper::SoftGateKeeper()); }
+
+    // Wrappers to translate the gatekeeper HAL API to the Kegyuard Messages API.
+
+    /**
+     * Enrolls password_payload, which should be derived from a user selected pin or password,
+     * with the authentication factor private key used only for enrolling authentication
+     * factor data.
+     *
+     * Returns: 0 on success or an error code less than 0 on error.
+     * On error, enrolled_password_handle will not be allocated.
+     */
+    ::android::hardware::Return<void> enroll(
+            uint32_t uid, const ::android::hardware::hidl_vec<uint8_t>& currentPasswordHandle,
+            const ::android::hardware::hidl_vec<uint8_t>& currentPassword,
+            const ::android::hardware::hidl_vec<uint8_t>& desiredPassword,
+            enroll_cb _hidl_cb) override;
+
+    /**
+     * Verifies provided_password matches enrolled_password_handle.
+     *
+     * Implementations of this module may retain the result of this call
+     * to attest to the recency of authentication.
+     *
+     * On success, writes the address of a verification token to auth_token,
+     * usable to attest password verification to other trusted services. Clients
+     * may pass NULL for this value.
+     *
+     * Returns: 0 on success or an error code less than 0 on error
+     * On error, verification token will not be allocated
+     */
+    ::android::hardware::Return<void> verify(
+            uint32_t uid, uint64_t challenge,
+            const ::android::hardware::hidl_vec<uint8_t>& enrolledPasswordHandle,
+            const ::android::hardware::hidl_vec<uint8_t>& providedPassword,
+            verify_cb _hidl_cb) override;
+
+    ::android::hardware::Return<void> deleteUser(uint32_t uid, deleteUser_cb _hidl_cb) override;
+
+    ::android::hardware::Return<void> deleteAllUsers(deleteAllUsers_cb _hidl_cb) override;
+
+  private:
+    std::unique_ptr<::gatekeeper::SoftGateKeeper> impl_;
+};
+
+}  // namespace android
+
+#endif  // SOFT_GATEKEEPER_DEVICE_H_
diff --git a/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.rc b/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.rc
new file mode 100644
index 0000000..60cb96c
--- /dev/null
+++ b/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.rc
@@ -0,0 +1,4 @@
+service vendor.gatekeeper-1-0 /vendor/bin/hw/android.hardware.gatekeeper@1.0-service.software
+    class hal
+    user system
+    group system
diff --git a/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.xml b/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.xml
new file mode 100644
index 0000000..19714a8
--- /dev/null
+++ b/gatekeeper/1.0/software/android.hardware.gatekeeper@1.0-service.software.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.gatekeeper</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+        <name>IGatekeeper</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/gatekeeper/1.0/software/service.cpp b/gatekeeper/1.0/software/service.cpp
new file mode 100644
index 0000000..a48a964
--- /dev/null
+++ b/gatekeeper/1.0/software/service.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.
+ */
+#define LOG_TAG "android.hardware.gatekeeper@1.0-service"
+
+#include <android-base/logging.h>
+#include <android/hardware/gatekeeper/1.0/IGatekeeper.h>
+
+#include <hidl/LegacySupport.h>
+
+#include "SoftGateKeeperDevice.h"
+
+// Generated HIDL files
+using android::SoftGateKeeperDevice;
+using android::hardware::gatekeeper::V1_0::IGatekeeper;
+
+int main() {
+    ::android::hardware::configureRpcThreadpool(1, true /* willJoinThreadpool */);
+    android::sp<SoftGateKeeperDevice> gatekeeper(new SoftGateKeeperDevice());
+    auto status = gatekeeper->registerAsService();
+    if (status != android::OK) {
+        LOG(FATAL) << "Could not register service for Gatekeeper 1.0 (software) (" << status << ")";
+    }
+
+    android::hardware::joinRpcThreadpool();
+    return -1;  // Should never get here.
+}
diff --git a/gatekeeper/1.0/software/tests/Android.bp b/gatekeeper/1.0/software/tests/Android.bp
new file mode 100644
index 0000000..3f0300d
--- /dev/null
+++ b/gatekeeper/1.0/software/tests/Android.bp
@@ -0,0 +1,34 @@
+//
+// 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.
+//
+
+cc_test {
+    name: "gatekeeper-software-device-unit-tests",
+
+    cflags: [
+        "-g",
+        "-Wall",
+        "-Werror",
+        "-Wno-missing-field-initializers",
+    ],
+    shared_libs: [
+        "libgatekeeper",
+        "libcrypto",
+        "libbase",
+    ],
+    static_libs: ["libscrypt_static"],
+
+    srcs: ["gatekeeper_test.cpp"],
+}
diff --git a/gatekeeper/1.0/software/tests/gatekeeper_test.cpp b/gatekeeper/1.0/software/tests/gatekeeper_test.cpp
new file mode 100644
index 0000000..bf4a8bc
--- /dev/null
+++ b/gatekeeper/1.0/software/tests/gatekeeper_test.cpp
@@ -0,0 +1,178 @@
+/*
+ * Copyright 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 <arpa/inet.h>
+#include <iostream>
+
+#include <gtest/gtest.h>
+#include <hardware/hw_auth_token.h>
+
+#include "../SoftGateKeeper.h"
+
+using ::gatekeeper::EnrollRequest;
+using ::gatekeeper::EnrollResponse;
+using ::gatekeeper::secure_id_t;
+using ::gatekeeper::SizedBuffer;
+using ::gatekeeper::SoftGateKeeper;
+using ::gatekeeper::VerifyRequest;
+using ::gatekeeper::VerifyResponse;
+using ::testing::Test;
+
+static SizedBuffer makePasswordBuffer(int init = 0) {
+    constexpr const uint32_t pw_buffer_size = 16;
+    auto pw_buffer = new uint8_t[pw_buffer_size];
+    memset(pw_buffer, init, pw_buffer_size);
+
+    return {pw_buffer, pw_buffer_size};
+}
+
+static SizedBuffer makeAndInitializeSizedBuffer(const uint8_t* data, uint32_t size) {
+    auto buffer = new uint8_t[size];
+    memcpy(buffer, data, size);
+    return {buffer, size};
+}
+
+static SizedBuffer copySizedBuffer(const SizedBuffer& rhs) {
+    return makeAndInitializeSizedBuffer(rhs.Data<uint8_t>(), rhs.size());
+}
+
+static void do_enroll(SoftGateKeeper& gatekeeper, EnrollResponse* response) {
+    EnrollRequest request(0, {}, makePasswordBuffer(), {});
+
+    gatekeeper.Enroll(request, response);
+}
+
+TEST(GateKeeperTest, EnrollSuccess) {
+    SoftGateKeeper gatekeeper;
+    EnrollResponse response;
+    do_enroll(gatekeeper, &response);
+    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
+}
+
+TEST(GateKeeperTest, EnrollBogusData) {
+    SoftGateKeeper gatekeeper;
+    EnrollResponse response;
+
+    EnrollRequest request(0, {}, {}, {});
+
+    gatekeeper.Enroll(request, &response);
+
+    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_INVALID, response.error);
+}
+
+TEST(GateKeeperTest, VerifySuccess) {
+    SoftGateKeeper gatekeeper;
+    EnrollResponse enroll_response;
+
+    do_enroll(gatekeeper, &enroll_response);
+    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);
+    VerifyRequest request(0, 1, std::move(enroll_response.enrolled_password_handle),
+                          makePasswordBuffer());
+    VerifyResponse response;
+
+    gatekeeper.Verify(request, &response);
+
+    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
+
+    auto auth_token = response.auth_token.Data<hw_auth_token_t>();
+
+    ASSERT_NE(nullptr, auth_token);
+    ASSERT_EQ((uint32_t)HW_AUTH_PASSWORD, ntohl(auth_token->authenticator_type));
+    ASSERT_EQ((uint64_t)1, auth_token->challenge);
+    ASSERT_NE(~((uint32_t)0), auth_token->timestamp);
+    ASSERT_NE((uint64_t)0, auth_token->user_id);
+    ASSERT_NE((uint64_t)0, auth_token->authenticator_id);
+}
+
+TEST(GateKeeperTest, TrustedReEnroll) {
+    SoftGateKeeper gatekeeper;
+    EnrollResponse enroll_response;
+
+    // do_enroll enrolls an all 0 password
+    do_enroll(gatekeeper, &enroll_response);
+    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);
+
+    // verify first password
+    VerifyRequest request(0, 0, copySizedBuffer(enroll_response.enrolled_password_handle),
+                          makePasswordBuffer());
+    VerifyResponse response;
+    gatekeeper.Verify(request, &response);
+    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
+    auto auth_token = response.auth_token.Data<hw_auth_token_t>();
+    ASSERT_NE(nullptr, auth_token);
+
+    secure_id_t secure_id = auth_token->user_id;
+
+    // enroll new password
+    EnrollRequest enroll_request(0, std::move(enroll_response.enrolled_password_handle),
+                                 makePasswordBuffer(1) /* new password */,
+                                 makePasswordBuffer() /* old password */);
+    gatekeeper.Enroll(enroll_request, &enroll_response);
+    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);
+
+    // verify new password
+    VerifyRequest new_request(0, 0, std::move(enroll_response.enrolled_password_handle),
+                              makePasswordBuffer(1));
+    gatekeeper.Verify(new_request, &response);
+    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
+    ASSERT_NE(nullptr, response.auth_token.Data<hw_auth_token_t>());
+    ASSERT_EQ(secure_id, response.auth_token.Data<hw_auth_token_t>()->user_id);
+}
+
+TEST(GateKeeperTest, UntrustedReEnroll) {
+    SoftGateKeeper gatekeeper;
+    SizedBuffer provided_password;
+    EnrollResponse enroll_response;
+
+    // do_enroll enrolls an all 0 password
+    provided_password = makePasswordBuffer();
+    do_enroll(gatekeeper, &enroll_response);
+    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);
+
+    // verify first password
+    VerifyRequest request(0, 0, std::move(enroll_response.enrolled_password_handle),
+                          std::move(provided_password));
+    VerifyResponse response;
+    gatekeeper.Verify(request, &response);
+    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
+    auto auth_token = response.auth_token.Data<hw_auth_token_t>();
+    ASSERT_NE(nullptr, auth_token);
+
+    secure_id_t secure_id = auth_token->user_id;
+
+    EnrollRequest enroll_request(0, {}, makePasswordBuffer(1), {});
+    gatekeeper.Enroll(enroll_request, &enroll_response);
+    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);
+
+    // verify new password
+    VerifyRequest new_request(0, 0, std::move(enroll_response.enrolled_password_handle),
+                              makePasswordBuffer(1));
+    gatekeeper.Verify(new_request, &response);
+    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
+    ASSERT_NE(nullptr, response.auth_token.Data<hw_auth_token_t>());
+    ASSERT_NE(secure_id, response.auth_token.Data<hw_auth_token_t>()->user_id);
+}
+
+TEST(GateKeeperTest, VerifyBogusData) {
+    SoftGateKeeper gatekeeper;
+    VerifyResponse response;
+
+    VerifyRequest request(0, 0, {}, {});
+
+    gatekeeper.Verify(request, &response);
+
+    ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_INVALID, response.error);
+}
diff --git a/gatekeeper/1.0/vts/OWNERS b/gatekeeper/1.0/vts/OWNERS
new file mode 100644
index 0000000..738c710
--- /dev/null
+++ b/gatekeeper/1.0/vts/OWNERS
@@ -0,0 +1,3 @@
+jdanis@google.com
+swillden@google.com
+guangzhu@google.com
diff --git a/gnss/1.0/Android.bp b/gnss/1.0/Android.bp
index 2e3e6fd..d97588c 100644
--- a/gnss/1.0/Android.bp
+++ b/gnss/1.0/Android.bp
@@ -35,4 +35,3 @@
     gen_java: true,
     gen_java_constants: true,
 }
-
diff --git a/gnss/1.0/default/Android.bp b/gnss/1.0/default/Android.bp
index ca495e6..57d8903 100644
--- a/gnss/1.0/default/Android.bp
+++ b/gnss/1.0/default/Android.bp
@@ -22,7 +22,6 @@
     shared_libs: [
         "liblog",
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "android.hardware.gnss@1.0",
         "libhardware",
@@ -47,7 +46,6 @@
         "libhardware",
         "libbinder",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.gnss@1.0",
     ],
 
diff --git a/gnss/1.0/default/android.hardware.gnss@1.0-service.rc b/gnss/1.0/default/android.hardware.gnss@1.0-service.rc
index 1a44d34..1300d81 100644
--- a/gnss/1.0/default/android.hardware.gnss@1.0-service.rc
+++ b/gnss/1.0/default/android.hardware.gnss@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.gnss_service /vendor/bin/hw/android.hardware.gnss@1.0-service
+    interface android.hardware.gnss@1.0::IGnss default
     class hal
     user gps
     group system gps radio
diff --git a/gnss/1.1/Android.bp b/gnss/1.1/Android.bp
index 4ae4439..5294a6b 100644
--- a/gnss/1.1/Android.bp
+++ b/gnss/1.1/Android.bp
@@ -19,4 +19,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/gnss/1.1/default/Android.bp b/gnss/1.1/default/Android.bp
index 8c3aac4..95bd7f3 100644
--- a/gnss/1.1/default/Android.bp
+++ b/gnss/1.1/default/Android.bp
@@ -12,7 +12,6 @@
     ],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "liblog",
         "android.hardware.gnss@1.1",
diff --git a/gnss/1.1/default/android.hardware.gnss@1.1-service.rc b/gnss/1.1/default/android.hardware.gnss@1.1-service.rc
index 0cf7c49..73901bf 100644
--- a/gnss/1.1/default/android.hardware.gnss@1.1-service.rc
+++ b/gnss/1.1/default/android.hardware.gnss@1.1-service.rc
@@ -1,4 +1,6 @@
 service gnss-1-1 /vendor/bin/hw/android.hardware.gnss@1.1-service
+    interface android.hardware.gnss@1.0::IGnss default
+    interface android.hardware.gnss@1.1::IGnss default
     class hal
     user system
     group system
diff --git a/gnss/2.0/Android.bp b/gnss/2.0/Android.bp
index 6cfd346..db5075f 100644
--- a/gnss/2.0/Android.bp
+++ b/gnss/2.0/Android.bp
@@ -30,4 +30,3 @@
     gen_java: true,
     gen_java_constants: true,
 }
-
diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp
index 0fcd764..3ba89da 100644
--- a/gnss/2.0/default/Android.bp
+++ b/gnss/2.0/default/Android.bp
@@ -33,7 +33,6 @@
     ],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "liblog",
         "android.hardware.gnss@2.0",
diff --git a/gnss/measurement_corrections/1.0/Android.bp b/gnss/measurement_corrections/1.0/Android.bp
index 456b55c..837cc7a 100644
--- a/gnss/measurement_corrections/1.0/Android.bp
+++ b/gnss/measurement_corrections/1.0/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/gnss/visibility_control/1.0/Android.bp b/gnss/visibility_control/1.0/Android.bp
index 40a28c9..e58e932 100644
--- a/gnss/visibility_control/1.0/Android.bp
+++ b/gnss/visibility_control/1.0/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/graphics/allocator/2.0/Android.bp b/graphics/allocator/2.0/Android.bp
index 50b474e..37d9dfc 100644
--- a/graphics/allocator/2.0/Android.bp
+++ b/graphics/allocator/2.0/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/graphics/allocator/2.0/default/Android.bp b/graphics/allocator/2.0/default/Android.bp
index 9980ae0..59229b0 100644
--- a/graphics/allocator/2.0/default/Android.bp
+++ b/graphics/allocator/2.0/default/Android.bp
@@ -13,7 +13,6 @@
         "libcutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
     ],
@@ -31,7 +30,6 @@
     shared_libs: [
         "android.hardware.graphics.allocator@2.0",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
     ],
diff --git a/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc b/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc
index a2a881a..038e87c 100644
--- a/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc
+++ b/graphics/allocator/2.0/default/android.hardware.graphics.allocator@2.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.gralloc-2-0 /vendor/bin/hw/android.hardware.graphics.allocator@2.0-service
+    interface android.hardware.graphics.allocator@2.0::IAllocator default
     class hal animation
     interface android.hardware.graphics.allocator@2.0::IAllocator default
     user system
diff --git a/graphics/allocator/3.0/Android.bp b/graphics/allocator/3.0/Android.bp
index fa3e2ce..2cfa1d0 100644
--- a/graphics/allocator/3.0/Android.bp
+++ b/graphics/allocator/3.0/Android.bp
@@ -18,4 +18,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/graphics/bufferqueue/1.0/Android.bp b/graphics/bufferqueue/1.0/Android.bp
index e23ca59..7fca354 100644
--- a/graphics/bufferqueue/1.0/Android.bp
+++ b/graphics/bufferqueue/1.0/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/graphics/bufferqueue/2.0/Android.bp b/graphics/bufferqueue/2.0/Android.bp
index 97c05fa..fd08079 100644
--- a/graphics/bufferqueue/2.0/Android.bp
+++ b/graphics/bufferqueue/2.0/Android.bp
@@ -19,4 +19,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/graphics/common/1.0/Android.bp b/graphics/common/1.0/Android.bp
index 175166d..089fe14 100644
--- a/graphics/common/1.0/Android.bp
+++ b/graphics/common/1.0/Android.bp
@@ -13,4 +13,3 @@
     gen_java: true,
     gen_java_constants: true,
 }
-
diff --git a/graphics/common/1.1/Android.bp b/graphics/common/1.1/Android.bp
index 0647d12d..899fe03 100644
--- a/graphics/common/1.1/Android.bp
+++ b/graphics/common/1.1/Android.bp
@@ -16,4 +16,3 @@
     gen_java: true,
     gen_java_constants: true,
 }
-
diff --git a/graphics/common/1.2/Android.bp b/graphics/common/1.2/Android.bp
index 088bc37..2c4d93b 100644
--- a/graphics/common/1.2/Android.bp
+++ b/graphics/common/1.2/Android.bp
@@ -17,4 +17,3 @@
     gen_java: true,
     gen_java_constants: true,
 }
-
diff --git a/graphics/composer/2.1/Android.bp b/graphics/composer/2.1/Android.bp
index 38786fd..4e4b81c 100644
--- a/graphics/composer/2.1/Android.bp
+++ b/graphics/composer/2.1/Android.bp
@@ -18,4 +18,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/graphics/composer/2.1/default/Android.bp b/graphics/composer/2.1/default/Android.bp
index 63accff..6157719 100644
--- a/graphics/composer/2.1/default/Android.bp
+++ b/graphics/composer/2.1/default/Android.bp
@@ -16,7 +16,6 @@
         "libfmq",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libsync",
         "libutils",
@@ -39,7 +38,6 @@
         "android.hardware.graphics.composer@2.1",
         "libbinder",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libsync",
         "libutils",
diff --git a/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc b/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
index 5a5b51e..cbd589a 100644
--- a/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
+++ b/graphics/composer/2.1/default/android.hardware.graphics.composer@2.1-service.rc
@@ -1,4 +1,5 @@
 service vendor.hwcomposer-2-1 /vendor/bin/hw/android.hardware.graphics.composer@2.1-service
+    interface android.hardware.graphics.composer@2.1::IComposer default
     class hal animation
     user system
     group graphics drmrpc
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp b/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp
index 420a1f6..0af9745 100644
--- a/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/Android.bp
@@ -20,7 +20,6 @@
     cflags: [
         "-Wall",
         "-Werror",
-        "-Wno-user-defined-warnings",
     ],
     cppflags: [
         "-Weverything",
@@ -56,6 +55,7 @@
         "-Wno-shorten-64-to-32",
         "-Wno-sign-compare",
         "-Wno-missing-prototypes",
+        "-Wno-format-pedantic",
     ],
 
     srcs: [
diff --git a/graphics/composer/2.2/Android.bp b/graphics/composer/2.2/Android.bp
index fe71e9e..930cadc 100644
--- a/graphics/composer/2.2/Android.bp
+++ b/graphics/composer/2.2/Android.bp
@@ -18,4 +18,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/graphics/composer/2.2/default/Android.mk b/graphics/composer/2.2/default/Android.mk
index 7dedf61..4916557 100644
--- a/graphics/composer/2.2/default/Android.mk
+++ b/graphics/composer/2.2/default/Android.mk
@@ -19,7 +19,6 @@
         libfmq \
         libhardware \
         libhidlbase \
-        libhidltransport \
         libhwc2on1adapter \
         libhwc2onfbadapter \
         liblog \
diff --git a/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
index efe6dad..0d7e86f 100644
--- a/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
+++ b/graphics/composer/2.2/default/android.hardware.graphics.composer@2.2-service.rc
@@ -1,4 +1,6 @@
 service vendor.hwcomposer-2-2 /vendor/bin/hw/android.hardware.graphics.composer@2.2-service
+    interface android.hardware.graphics.composer@2.1::IComposer default
+    interface android.hardware.graphics.composer@2.2::IComposer default
     class hal animation
     user system
     group graphics drmrpc
diff --git a/graphics/composer/2.3/Android.bp b/graphics/composer/2.3/Android.bp
index 6d29348..a777556 100644
--- a/graphics/composer/2.3/Android.bp
+++ b/graphics/composer/2.3/Android.bp
@@ -20,4 +20,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/graphics/composer/2.3/default/Android.bp b/graphics/composer/2.3/default/Android.bp
index 07afd6c..59b9436 100644
--- a/graphics/composer/2.3/default/Android.bp
+++ b/graphics/composer/2.3/default/Android.bp
@@ -36,7 +36,6 @@
         "libfmq",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "libhwc2on1adapter",
         "libhwc2onfbadapter",
         "liblog",
diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp
index 2766638..e421889 100644
--- a/graphics/composer/2.3/vts/functional/Android.bp
+++ b/graphics/composer/2.3/vts/functional/Android.bp
@@ -23,7 +23,6 @@
     shared_libs: [
         "libfmq",
         "libhidlbase",
-        "libhidltransport",
         "libsync",
     ],
     static_libs: [
diff --git a/graphics/mapper/2.0/Android.bp b/graphics/mapper/2.0/Android.bp
index 96e812b..4459bdc 100644
--- a/graphics/mapper/2.0/Android.bp
+++ b/graphics/mapper/2.0/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/graphics/mapper/2.0/default/Android.bp b/graphics/mapper/2.0/default/Android.bp
index 8874799..4f64184 100644
--- a/graphics/mapper/2.0/default/Android.bp
+++ b/graphics/mapper/2.0/default/Android.bp
@@ -28,7 +28,6 @@
         "libcutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libsync",
         "libutils",
diff --git a/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h
index 5ad2a65..8134174 100644
--- a/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h
+++ b/graphics/mapper/2.0/utils/hal/include/mapper-hal/2.0/Mapper.h
@@ -80,17 +80,21 @@
     }
 
     Return<Error> freeBuffer(void* buffer) override {
-        native_handle_t* bufferHandle = removeImportedBuffer(buffer);
+        native_handle_t* bufferHandle = getImportedBuffer(buffer);
         if (!bufferHandle) {
             return Error::BAD_BUFFER;
         }
 
-        return mHal->freeBuffer(bufferHandle);
+        Error error = mHal->freeBuffer(bufferHandle);
+        if (error == Error::NONE) {
+            removeImportedBuffer(buffer);
+        }
+        return error;
     }
 
     Return<void> lock(void* buffer, uint64_t cpuUsage, const V2_0::IMapper::Rect& accessRegion,
                       const hidl_handle& acquireFence, IMapper::lock_cb hidl_cb) override {
-        const native_handle_t* bufferHandle = getImportedBuffer(buffer);
+        const native_handle_t* bufferHandle = getConstImportedBuffer(buffer);
         if (!bufferHandle) {
             hidl_cb(Error::BAD_BUFFER, nullptr);
             return Void();
@@ -112,7 +116,7 @@
     Return<void> lockYCbCr(void* buffer, uint64_t cpuUsage, const V2_0::IMapper::Rect& accessRegion,
                            const hidl_handle& acquireFence,
                            IMapper::lockYCbCr_cb hidl_cb) override {
-        const native_handle_t* bufferHandle = getImportedBuffer(buffer);
+        const native_handle_t* bufferHandle = getConstImportedBuffer(buffer);
         if (!bufferHandle) {
             hidl_cb(Error::BAD_BUFFER, YCbCrLayout{});
             return Void();
@@ -132,7 +136,7 @@
     }
 
     Return<void> unlock(void* buffer, IMapper::unlock_cb hidl_cb) override {
-        const native_handle_t* bufferHandle = getImportedBuffer(buffer);
+        const native_handle_t* bufferHandle = getConstImportedBuffer(buffer);
         if (!bufferHandle) {
             hidl_cb(Error::BAD_BUFFER, nullptr);
             return Void();
@@ -160,7 +164,11 @@
         return static_cast<native_handle_t*>(buffer);
     }
 
-    virtual const native_handle_t* getImportedBuffer(void* buffer) const {
+    virtual native_handle_t* getImportedBuffer(void* buffer) const {
+        return static_cast<native_handle_t*>(buffer);
+    }
+
+    virtual const native_handle_t* getConstImportedBuffer(void* buffer) const {
         return static_cast<const native_handle_t*>(buffer);
     }
 
diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h
index d9beb4f..db7e67d 100644
--- a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/Gralloc1Hal.h
@@ -282,14 +282,16 @@
         }
 
         if (flex.planes[0].component != FLEX_COMPONENT_Y ||
-            flex.planes[1].component != FLEX_COMPONENT_Cb ||
-            flex.planes[2].component != FLEX_COMPONENT_Cr) {
+           ((flex.planes[1].component != FLEX_COMPONENT_Cb || flex.planes[2].component != FLEX_COMPONENT_Cr) &&
+           (flex.planes[2].component != FLEX_COMPONENT_Cb || flex.planes[1].component != FLEX_COMPONENT_Cr))) {
             return false;
         }
 
         const auto& y = flex.planes[0];
-        const auto& cb = flex.planes[1];
-        const auto& cr = flex.planes[2];
+        const auto& cb = (flex.planes[1].component == FLEX_COMPONENT_Cb)?
+                          flex.planes[1] : flex.planes[2];
+        const auto& cr = (flex.planes[2].component == FLEX_COMPONENT_Cr)?
+                          flex.planes[2] : flex.planes[1];
 
         if (cb.h_increment != cr.h_increment || cb.v_increment != cr.v_increment) {
             return false;
diff --git a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h
index e8b1b4b..85a91c3 100644
--- a/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h
+++ b/graphics/mapper/2.0/utils/passthrough/include/mapper-passthrough/2.0/GrallocLoader.h
@@ -68,7 +68,14 @@
         return mBufferHandles.erase(bufferHandle) == 1 ? bufferHandle : nullptr;
     }
 
-    const native_handle_t* get(void* buffer) {
+    native_handle_t* get(void* buffer) {
+        auto bufferHandle = static_cast<native_handle_t*>(buffer);
+
+        std::lock_guard<std::mutex> lock(mMutex);
+        return mBufferHandles.count(bufferHandle) == 1 ? bufferHandle : nullptr;
+    }
+
+    const native_handle_t* getConst(void* buffer) {
         auto bufferHandle = static_cast<const native_handle_t*>(buffer);
 
         std::lock_guard<std::mutex> lock(mMutex);
@@ -92,9 +99,13 @@
         return GrallocImportedBufferPool::getInstance().remove(buffer);
     }
 
-    const native_handle_t* getImportedBuffer(void* buffer) const override {
+    native_handle_t* getImportedBuffer(void* buffer) const override {
         return GrallocImportedBufferPool::getInstance().get(buffer);
     }
+
+    const native_handle_t* getConstImportedBuffer(void* buffer) const override {
+        return GrallocImportedBufferPool::getInstance().getConst(buffer);
+    }
 };
 
 class GrallocLoader {
diff --git a/graphics/mapper/2.1/Android.bp b/graphics/mapper/2.1/Android.bp
index 8527d3d..e5a5ae4 100644
--- a/graphics/mapper/2.1/Android.bp
+++ b/graphics/mapper/2.1/Android.bp
@@ -18,4 +18,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/graphics/mapper/2.1/default/Android.bp b/graphics/mapper/2.1/default/Android.bp
index aa204a0..2ea7f94 100644
--- a/graphics/mapper/2.1/default/Android.bp
+++ b/graphics/mapper/2.1/default/Android.bp
@@ -29,7 +29,6 @@
         "libcutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libsync",
         "libutils",
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 18fbb6d..8540068 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
@@ -37,6 +37,10 @@
      Error validateBufferSize(const native_handle_t* bufferHandle,
                               const IMapper::BufferDescriptorInfo& descriptorInfo,
                               uint32_t stride) override {
+         if (descriptorInfo.layerCount != 1) {
+             return Error::BAD_VALUE;
+         }
+
          if (!mModule->validateBufferSize) {
              return Error::NONE;
          }
diff --git a/graphics/mapper/3.0/Android.bp b/graphics/mapper/3.0/Android.bp
index e348296..a143243 100644
--- a/graphics/mapper/3.0/Android.bp
+++ b/graphics/mapper/3.0/Android.bp
@@ -19,4 +19,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/health/1.0/Android.bp b/health/1.0/Android.bp
index e03b142..ea6b0c8 100644
--- a/health/1.0/Android.bp
+++ b/health/1.0/Android.bp
@@ -16,4 +16,3 @@
     gen_java: true,
     gen_java_constants: true,
 }
-
diff --git a/health/1.0/default/Android.bp b/health/1.0/default/Android.bp
index 8fbb8c3..049e393 100644
--- a/health/1.0/default/Android.bp
+++ b/health/1.0/default/Android.bp
@@ -12,7 +12,6 @@
     shared_libs: [
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "android.hardware.health@1.0",
     ],
diff --git a/health/1.0/default/Android.mk b/health/1.0/default/Android.mk
index 199ab41..bbf37af 100644
--- a/health/1.0/default/Android.mk
+++ b/health/1.0/default/Android.mk
@@ -13,7 +13,6 @@
 LOCAL_SHARED_LIBRARIES := \
     libcutils \
     libhidlbase \
-    libhidltransport \
     liblog \
     libutils \
     android.hardware.health@1.0 \
@@ -39,7 +38,6 @@
     libbase \
     libutils \
     libhidlbase \
-    libhidltransport \
     android.hardware.health@1.0 \
 
 include $(BUILD_EXECUTABLE)
diff --git a/health/2.0/Android.bp b/health/2.0/Android.bp
index f472b27..b8323b6 100644
--- a/health/2.0/Android.bp
+++ b/health/2.0/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/health/2.0/README.md b/health/2.0/README.md
index 58ea9e3..4ecfb9a 100644
--- a/health/2.0/README.md
+++ b/health/2.0/README.md
@@ -44,7 +44,6 @@
             "libbase",
             "libcutils",
             "libhidlbase",
-            "libhidltransport",
             "libutils",
             "android.hardware.health@2.0",
         ],
diff --git a/health/2.0/default/Android.bp b/health/2.0/default/Android.bp
index a85a704..1c455d3 100644
--- a/health/2.0/default/Android.bp
+++ b/health/2.0/default/Android.bp
@@ -10,8 +10,6 @@
     shared_libs: [
         "libbase",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libutils",
         "libcutils",
diff --git a/health/storage/1.0/Android.bp b/health/storage/1.0/Android.bp
index 45fa01f..e4620f8 100644
--- a/health/storage/1.0/Android.bp
+++ b/health/storage/1.0/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/health/storage/1.0/default/Android.bp b/health/storage/1.0/default/Android.bp
index 4723443..3156dfe 100644
--- a/health/storage/1.0/default/Android.bp
+++ b/health/storage/1.0/default/Android.bp
@@ -33,7 +33,6 @@
     shared_libs: [
         "libbase",
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "android.hardware.health.storage@1.0",
     ],
diff --git a/health/storage/1.0/default/service.cpp b/health/storage/1.0/default/service.cpp
index f4296f1..6f6ebc8 100644
--- a/health/storage/1.0/default/service.cpp
+++ b/health/storage/1.0/default/service.cpp
@@ -32,7 +32,7 @@
     configureRpcThreadpool(1, true);
 
     sp<IStorage> service = new Storage();
-    LazyServiceRegistrar registrar;
+    auto registrar = LazyServiceRegistrar::getInstance();
     status_t result = registrar.registerService(service);
 
     if (result != OK) {
diff --git a/health/storage/1.0/vts/functional/Android.bp b/health/storage/1.0/vts/functional/Android.bp
index b18e36f..87502f8 100644
--- a/health/storage/1.0/vts/functional/Android.bp
+++ b/health/storage/1.0/vts/functional/Android.bp
@@ -21,7 +21,6 @@
     static_libs: ["android.hardware.health.storage@1.0"],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
     ],
     test_suites: ["general-tests"],
 }
diff --git a/input/classifier/1.0/Android.bp b/input/classifier/1.0/Android.bp
index 6815a51..11e0f52 100644
--- a/input/classifier/1.0/Android.bp
+++ b/input/classifier/1.0/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/input/classifier/1.0/default/Android.bp b/input/classifier/1.0/default/Android.bp
index ceb2aca..3379a76 100644
--- a/input/classifier/1.0/default/Android.bp
+++ b/input/classifier/1.0/default/Android.bp
@@ -11,7 +11,6 @@
     shared_libs: [
         "android.hardware.input.classifier@1.0",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
     ],
diff --git a/input/common/1.0/Android.bp b/input/common/1.0/Android.bp
index 07b38cf..2c7c517 100644
--- a/input/common/1.0/Android.bp
+++ b/input/common/1.0/Android.bp
@@ -11,4 +11,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/ir/1.0/Android.bp b/ir/1.0/Android.bp
index 5f25172..5fca96d 100644
--- a/ir/1.0/Android.bp
+++ b/ir/1.0/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/ir/1.0/default/Android.bp b/ir/1.0/default/Android.bp
index 2b15387..80e0f3c 100644
--- a/ir/1.0/default/Android.bp
+++ b/ir/1.0/default/Android.bp
@@ -20,7 +20,6 @@
     srcs: ["ConsumerIr.cpp"],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "libhardware",
         "liblog",
         "libutils",
@@ -40,7 +39,6 @@
         "liblog",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "android.hardware.ir@1.0",
     ],
diff --git a/ir/1.0/default/android.hardware.ir@1.0-service.rc b/ir/1.0/default/android.hardware.ir@1.0-service.rc
index 0d06967..b2f1f7d 100644
--- a/ir/1.0/default/android.hardware.ir@1.0-service.rc
+++ b/ir/1.0/default/android.hardware.ir@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.ir-hal-1-0 /vendor/bin/hw/android.hardware.ir@1.0-service
+    interface android.hardware.ir@1.0::IConsumerIr default
     class hal
     user system
     group system
diff --git a/keymaster/3.0/Android.bp b/keymaster/3.0/Android.bp
index ca17a9b..0fdc32c 100644
--- a/keymaster/3.0/Android.bp
+++ b/keymaster/3.0/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/keymaster/3.0/default/Android.mk b/keymaster/3.0/default/Android.mk
index 9e7d04a..208cb66 100644
--- a/keymaster/3.0/default/Android.mk
+++ b/keymaster/3.0/default/Android.mk
@@ -15,7 +15,6 @@
     libpuresoftkeymasterdevice \
     libkeymaster3device \
     libhidlbase \
-    libhidltransport \
     libutils \
     libhardware \
     android.hardware.keymaster@3.0
@@ -38,7 +37,6 @@
     libutils \
     libhardware \
     libhidlbase \
-    libhidltransport \
     android.hardware.keymaster@3.0
 
 include $(BUILD_EXECUTABLE)
diff --git a/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc b/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc
index ea8d490..dffaca5 100644
--- a/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc
+++ b/keymaster/3.0/default/android.hardware.keymaster@3.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.keymaster-3-0 /vendor/bin/hw/android.hardware.keymaster@3.0-service
+    interface android.hardware.keymaster@3.0::IKeymasterDevice default
     class early_hal
     user nobody
     group drmrpc
diff --git a/keymaster/3.0/vts/functional/Android.bp b/keymaster/3.0/vts/functional/Android.bp
index b0371c7..69aa56d 100644
--- a/keymaster/3.0/vts/functional/Android.bp
+++ b/keymaster/3.0/vts/functional/Android.bp
@@ -26,7 +26,7 @@
     ],
     static_libs: [
         "android.hardware.keymaster@3.0",
-        "libcrypto",
+        "libcrypto_static",
         "libsoftkeymasterdevice",
     ],
     test_suites: ["general-tests"],
diff --git a/keymaster/4.0/Android.bp b/keymaster/4.0/Android.bp
index cd46fd9..ea328f4 100644
--- a/keymaster/4.0/Android.bp
+++ b/keymaster/4.0/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/keymaster/4.0/IKeymasterDevice.hal b/keymaster/4.0/IKeymasterDevice.hal
index c867ab0..3475f79 100644
--- a/keymaster/4.0/IKeymasterDevice.hal
+++ b/keymaster/4.0/IKeymasterDevice.hal
@@ -624,7 +624,7 @@
     /**
      * Exports a public key, returning the key in the specified format.
      *
-     * @parm keyFormat The format used for export.  See KeyFormat in types.hal.
+     * @parm keyFormat The format used for export.  Must be KeyFormat::X509.
      *
      * @param keyBlob The opaque descriptor returned by generateKey() or importKey().  The
      *        referenced key must be asymmetric.
@@ -639,7 +639,7 @@
      *        value, it must be computationally infeasible for the secure hardware to obtain the key
      *        material.
      *
-     * @return keyMaterial The public key material in PKCS#8 format.
+     * @return keyMaterial The public key material in X.509 format.
      */
     exportKey(KeyFormat keyFormat, vec<uint8_t> keyBlob, vec<uint8_t> clientId,
               vec<uint8_t> appData) generates (ErrorCode error, vec<uint8_t> keyMaterial);
@@ -1005,13 +1005,11 @@
      *
      * -- EC Keys --
      *
-     * EC key operations must specify exactly one padding mode in inParams.  If unspecified or
-     * specified more than once, begin() must return ErrorCode::UNSUPPORTED_PADDING_MODE.
-     *
-     * Private key operations (KeyPurpose::SIGN) need authorization of digest and padding, which
-     * means that the key authorizations must contain the specified values.  If not, begin() must
-     * return ErrorCode::INCOMPATIBLE_DIGEST.  Public key operations (KeyPurpose::VERIFY) are
-     * permitted with unauthorized digest or padding.
+     * EC private key operations must specify exactly one digest in inParams.  If unspecified or
+     * specified more than once, begin() must return ErrorCode::UNSUPPORTED_DIGEST.  For private key
+     * operations, (KeyPurpose::SIGN), if the specified digest is not in the key's authorization
+     * list, begin() must return ErrorCode::INCOMPATIBLE_DIGEST.  Public key operations
+     * (KeyPurpose::VERIFY) are permitted with unauthorized digest.
      *
      * -- AES Keys --
      *
diff --git a/keymaster/4.0/default/Android.bp b/keymaster/4.0/default/Android.bp
index 0cede50..f9e3986 100644
--- a/keymaster/4.0/default/Android.bp
+++ b/keymaster/4.0/default/Android.bp
@@ -28,7 +28,6 @@
         "libcutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "libkeymaster4",
         "liblog",
         "libutils",
diff --git a/keymaster/4.0/default/android.hardware.keymaster@4.0-service.rc b/keymaster/4.0/default/android.hardware.keymaster@4.0-service.rc
index 2ce439e..2adfd88 100644
--- a/keymaster/4.0/default/android.hardware.keymaster@4.0-service.rc
+++ b/keymaster/4.0/default/android.hardware.keymaster@4.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.keymaster-4-0 /vendor/bin/hw/android.hardware.keymaster@4.0-service
+    interface android.hardware.keymaster@4.0::IKeymasterDevice default
     class early_hal
     user system
     group system drmrpc
diff --git a/keymaster/4.0/support/Android.bp b/keymaster/4.0/support/Android.bp
index ccd1b56..2f40282 100644
--- a/keymaster/4.0/support/Android.bp
+++ b/keymaster/4.0/support/Android.bp
@@ -39,7 +39,6 @@
         "libcrypto",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "libutils",
     ]
 }
diff --git a/keymaster/4.0/support/Keymaster.cpp b/keymaster/4.0/support/Keymaster.cpp
index e8db074..1eb9a68 100644
--- a/keymaster/4.0/support/Keymaster.cpp
+++ b/keymaster/4.0/support/Keymaster.cpp
@@ -19,7 +19,7 @@
 #include <iomanip>
 
 #include <android-base/logging.h>
-#include <android/hidl/manager/1.0/IServiceManager.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>
@@ -69,7 +69,7 @@
 namespace support {
 
 using ::android::sp;
-using ::android::hidl::manager::V1_0::IServiceManager;
+using ::android::hidl::manager::V1_2::IServiceManager;
 
 std::ostream& operator<<(std::ostream& os, const Keymaster& keymaster) {
     auto& version = keymaster.halVersion();
@@ -86,7 +86,7 @@
 
     bool foundDefault = false;
     auto& descriptor = Wrapper::WrappedIKeymasterDevice::descriptor;
-    serviceManager->listByInterface(descriptor, [&](const hidl_vec<hidl_string>& names) {
+    serviceManager->listManifestByInterface(descriptor, [&](const hidl_vec<hidl_string>& names) {
         for (auto& name : names) {
             if (name == "default") foundDefault = true;
             auto device = Wrapper::WrappedIKeymasterDevice::getService(name);
@@ -97,7 +97,7 @@
     });
 
     if (!foundDefault) {
-        // "default" wasn't provided by listByInterface.  Maybe there's a passthrough
+        // "default" wasn't provided by listManifestByInterface.  Maybe there's a passthrough
         // implementation.
         auto device = Wrapper::WrappedIKeymasterDevice::getService("default");
         if (device) result.push_back(std::unique_ptr<Keymaster>(new Wrapper(device, "default")));
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 97dab68..cb29c64 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h
@@ -280,39 +280,50 @@
  */
 template <typename ValueT>
 class NullOr {
-    template <typename T>
-    struct reference_initializer {
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wnull-dereference"
-        static T&& init() { return *static_cast<std::remove_reference_t<T>*>(nullptr); }
-#pragma GCC diagnostic pop
-    };
-    template <typename T>
-    struct pointer_initializer {
-        static T init() { return nullptr; }
-    };
-    template <typename T>
-    struct value_initializer {
-        static T init() { return T(); }
-    };
-    template <typename T>
-    using initializer_t =
-        std::conditional_t<std::is_lvalue_reference<T>::value, reference_initializer<T>,
-                           std::conditional_t<std::is_pointer<T>::value, pointer_initializer<T>,
-                                              value_initializer<T>>>;
+    using internal_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value,
+                                          std::remove_reference_t<ValueT>*, ValueT>;
 
-   public:
-    NullOr() : value_(initializer_t<ValueT>::init()), null_(true) {}
-    NullOr(ValueT&& value) : value_(std::forward<ValueT>(value)), null_(false) {}
+    struct pointer_initializer {
+        static std::nullptr_t init() { return nullptr; }
+    };
+    struct value_initializer {
+        static ValueT init() { return ValueT(); }
+    };
+    struct value_pointer_deref_t {
+        static ValueT& deref(ValueT& v) { return v; }
+    };
+    struct reference_deref_t {
+        static auto& deref(internal_t v) { return *v; }
+    };
+    using initializer_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value ||
+                                                     std::is_pointer<ValueT>::value,
+                                             pointer_initializer, value_initializer>;
+    using deref_t = std::conditional_t<std::is_lvalue_reference<ValueT>::value, reference_deref_t,
+                                       value_pointer_deref_t>;
+
+  public:
+    NullOr() : value_(initializer_t::init()), null_(true) {}
+    template <typename T>
+    NullOr(T&& value, typename std::enable_if<
+                              !std::is_lvalue_reference<ValueT>::value &&
+                                      std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value,
+                              int>::type = 0)
+        : value_(std::forward<ValueT>(value)), null_(false) {}
+    template <typename T>
+    NullOr(T& value, typename std::enable_if<
+                             std::is_lvalue_reference<ValueT>::value &&
+                                     std::is_same<std::decay_t<ValueT>, std::decay_t<T>>::value,
+                             int>::type = 0)
+        : value_(&value), null_(false) {}
 
     bool isOk() const { return !null_; }
 
-    const ValueT& value() const & { return value_; }
-    ValueT& value() & { return value_; }
-    ValueT&& value() && { return std::move(value_); }
+    const ValueT& value() const& { return deref_t::deref(value_); }
+    ValueT& value() & { return deref_t::deref(value_); }
+    ValueT&& value() && { return std::move(deref_t::deref(value_)); }
 
-   private:
-    ValueT value_;
+  private:
+    internal_t value_;
     bool null_;
 };
 
diff --git a/keymaster/4.0/vts/functional/Android.bp b/keymaster/4.0/vts/functional/Android.bp
index 333e408..0401362 100644
--- a/keymaster/4.0/vts/functional/Android.bp
+++ b/keymaster/4.0/vts/functional/Android.bp
@@ -25,7 +25,7 @@
     ],
     static_libs: [
         "android.hardware.keymaster@4.0",
-        "libcrypto",
+        "libcrypto_static",
         "libkeymaster4support",
         "libsoftkeymasterdevice",
     ],
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
index 3af1df3..4838e7e 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
@@ -48,10 +48,11 @@
 SecurityLevel KeymasterHidlTest::securityLevel_;
 hidl_string KeymasterHidlTest::name_;
 hidl_string KeymasterHidlTest::author_;
+string KeymasterHidlTest::service_name_;
 
-void KeymasterHidlTest::SetUpTestCase() {
-    string service_name = KeymasterHidlEnvironment::Instance()->getServiceName<IKeymasterDevice>();
-    keymaster_ = ::testing::VtsHalHidlTargetTestBase::getService<IKeymasterDevice>(service_name);
+void KeymasterHidlTest::InitializeKeymaster() {
+    service_name_ = KeymasterHidlEnvironment::Instance()->getServiceName<IKeymasterDevice>();
+    keymaster_ = ::testing::VtsHalHidlTargetTestBase::getService<IKeymasterDevice>(service_name_);
     ASSERT_NE(keymaster_, nullptr);
 
     ASSERT_TRUE(keymaster_
@@ -62,18 +63,22 @@
                         author_ = author;
                     })
                     .isOk());
+}
+
+void KeymasterHidlTest::SetUpTestCase() {
+
+    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;
+                if (name == service_name_) continue;
                 auto keymaster =
                     ::testing::VtsHalHidlTargetTestBase::getService<IKeymasterDevice>(name);
                 ASSERT_NE(keymaster, nullptr);
@@ -269,6 +274,13 @@
     return GetCharacteristics(key_blob, client_id, app_data, key_characteristics);
 }
 
+ErrorCode KeymasterHidlTest::GetDebugInfo(DebugInfo* debug_info) {
+    EXPECT_TRUE(keymaster_->getDebugInfo([&](const DebugInfo& hidl_debug_info) {
+      *debug_info = hidl_debug_info;
+    }).isOk());
+    return ErrorCode::OK;
+}
+
 ErrorCode KeymasterHidlTest::Begin(KeyPurpose purpose, const HidlBuf& key_blob,
                                    const AuthorizationSet& in_params, AuthorizationSet* out_params,
                                    OperationHandle* op_handle) {
@@ -611,6 +623,20 @@
     return ciphertext;
 }
 
+string KeymasterHidlTest::EncryptMessage(const string& message, BlockMode block_mode,
+                                         PaddingMode padding, uint8_t mac_length_bits,
+                                         const HidlBuf& iv_in) {
+    SCOPED_TRACE("EncryptMessage");
+    auto params = AuthorizationSetBuilder()
+                          .BlockMode(block_mode)
+                          .Padding(padding)
+                          .Authorization(TAG_MAC_LENGTH, mac_length_bits)
+                          .Authorization(TAG_NONCE, iv_in);
+    AuthorizationSet out_params;
+    string ciphertext = EncryptMessage(message, params, &out_params);
+    return ciphertext;
+}
+
 string KeymasterHidlTest::DecryptMessage(const HidlBuf& key_blob, const string& ciphertext,
                                          const AuthorizationSet& params) {
     SCOPED_TRACE("DecryptMessage");
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.h b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
index 015fc43..b09da45 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.h
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
@@ -37,6 +37,7 @@
 
 using ::android::sp;
 using ::std::string;
+using hidl::base::V1_0::DebugInfo;
 
 class HidlBuf : public hidl_vec<uint8_t> {
     typedef hidl_vec<uint8_t> super;
@@ -95,6 +96,7 @@
 
     // SetUpTestCase runs only once per test case, not once per test.
     static void SetUpTestCase();
+    static void InitializeKeymaster();
     static void TearDownTestCase() {
         keymaster_.clear();
         all_keymasters_.clear();
@@ -140,6 +142,8 @@
                                  const HidlBuf& app_data, KeyCharacteristics* key_characteristics);
     ErrorCode GetCharacteristics(const HidlBuf& key_blob, KeyCharacteristics* key_characteristics);
 
+    ErrorCode GetDebugInfo(DebugInfo* debug_info);
+
     ErrorCode Begin(KeyPurpose purpose, const HidlBuf& key_blob, const AuthorizationSet& in_params,
                     AuthorizationSet* out_params, OperationHandle* op_handle);
     ErrorCode Begin(KeyPurpose purpose, const AuthorizationSet& in_params,
@@ -201,6 +205,8 @@
                           HidlBuf* iv_out);
     string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding,
                           const HidlBuf& iv_in);
+    string EncryptMessage(const string& message, BlockMode block_mode, PaddingMode padding,
+                          uint8_t mac_length_bits, const HidlBuf& iv_in);
 
     string DecryptMessage(const HidlBuf& key_blob, const string& ciphertext,
                           const AuthorizationSet& params);
@@ -235,6 +241,7 @@
     static SecurityLevel securityLevel_;
     static hidl_string name_;
     static hidl_string author_;
+    static string service_name_;
 };
 
 }  // namespace test
diff --git a/keymaster/4.0/vts/functional/VerificationTokenTest.cpp b/keymaster/4.0/vts/functional/VerificationTokenTest.cpp
index 3876b16..de28683 100644
--- a/keymaster/4.0/vts/functional/VerificationTokenTest.cpp
+++ b/keymaster/4.0/vts/functional/VerificationTokenTest.cpp
@@ -124,6 +124,65 @@
     // report if times aren't nearly always <1ms apart.
     EXPECT_LE(host_time_delta, km_time_delta + 2);
     EXPECT_LE(km_time_delta, host_time_delta + 2);
+    ASSERT_EQ(result1.token.mac.size(), result2.token.mac.size());
+    ASSERT_NE(0,
+              memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size()));
+}
+
+/*
+ * Test that the mac changes when the time stamp changes. This is does not guarantee that the time
+ * stamp is included in the mac but on failure we know that it is not. Other than in the test
+ * case above we call verifyAuthorization with the exact same set of parameters.
+ */
+TEST_F(VerificationTokenTest, MacChangesOnChangingTimestamp) {
+    auto result1 =
+            verifyAuthorization(0 /* operation handle */,
+                                AuthorizationSet() /* paramtersToVerify */, HardwareAuthToken());
+    ASSERT_TRUE(result1.callSuccessful);
+    auto result1_time = getTime();
+
+    if (SecLevel() == SecurityLevel::STRONGBOX) {
+        // StrongBox should not implement verifyAuthorization.
+        EXPECT_EQ(ErrorCode::UNIMPLEMENTED, result1.error);
+        return;
+    }
+
+    EXPECT_EQ(ErrorCode::OK, result1.error);
+    EXPECT_EQ(0U, result1.token.challenge);
+    EXPECT_EQ(SecLevel(), result1.token.securityLevel);
+    EXPECT_EQ(0U, result1.token.parametersVerified.size())
+            << "We didn't supply any parameters to verify";
+    EXPECT_GT(result1.token.timestamp, 0U);
+
+    constexpr uint32_t time_to_sleep = 200;
+    sleep_ms(time_to_sleep);
+
+    auto result2 =
+            verifyAuthorization(0 /* operation handle */,
+                                AuthorizationSet() /* paramtersToVerify */, HardwareAuthToken());
+    ASSERT_TRUE(result2.callSuccessful);
+    auto result2_time = getTime();
+    EXPECT_EQ(ErrorCode::OK, result2.error);
+    EXPECT_EQ(0U, result2.token.challenge);
+    EXPECT_EQ(SecLevel(), result2.token.securityLevel);
+    EXPECT_EQ(0U, result2.token.parametersVerified.size())
+            << "We didn't supply any parameters to verify";
+
+    auto host_time_delta = result2_time - result1_time;
+
+    EXPECT_GE(host_time_delta, time_to_sleep)
+            << "We slept for " << time_to_sleep << " ms, the clock must have advanced by that much";
+    EXPECT_LE(host_time_delta, time_to_sleep + 20)
+            << "The verifyAuthorization call took " << (host_time_delta - time_to_sleep)
+            << " ms?  That's awful!";
+
+    auto km_time_delta = result2.token.timestamp - result1.token.timestamp;
+
+    EXPECT_LE(host_time_delta, km_time_delta + 2);
+    EXPECT_LE(km_time_delta, host_time_delta + 2);
+    ASSERT_EQ(result1.token.mac.size(), result2.token.mac.size());
+    ASSERT_NE(0,
+              memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size()));
 }
 
 }  // namespace test
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 728bf69..0ac7e48 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -18,6 +18,7 @@
 #include <cutils/log.h>
 
 #include <iostream>
+#include <signal.h>
 
 #include <openssl/evp.h>
 #include <openssl/mem.h>
@@ -2207,26 +2208,26 @@
 }
 
 auto wrapped_key = hex2str(
-    "3082017902010004820100A0E69B1395D382354FC0E7F74AC068C5818279D76D46745C7274997D045BAA8B9763B3F3"
-    "09E5E59ECA99273AAAE0A37449DA9B1E67B66EC4E42BB62C25346683A43A9F2ACBCA6D350B25551CC53CE0721D29BE"
-    "90F60686877478F82B3BB111C5EAC0BAE9310D7AD11F5A82948B31C322820F24E20DDB0FBD07D1566DAEAA058D4645"
-    "2607352699E1F631D2ABAF60B13E41ED5EDBB90D252331BDB9CDB1B672E871F37CAC009FE9028B3B1E0ACE8F6F0678"
-    "3F581B860620BDD478969EDE3101AAEFF65C6DB03E143E586167DC87D0CCE39E9119782F7B60A7A1CF2B7EE234E013"
-    "E3DE6C56F0D51F30C389D31FA37C5F2875ACB44434E82EF40B316C93DE129BA0040CD796B02C370F1FA4CC0124F130"
-    "2E0201033029A1083106020100020101A203020120A30402020100A4053103020101A6053103020140BF8377020500"
-    "0420CCD540855F833A5E1480BFD2D36FAF3AEEE15DF5BEABE2691BC82DDE2A7AA910041064C9F689C60FF6223AB6E6"
-    "999E0EB6E5");
+    "3082017902010004820100934bf94e2aa28a3f83c9f79297250262fbe3276b5a1c91159bbfa3ef8957aac84b59b30b"
+    "455a79c2973480823d8b3863c3deef4a8e243590268d80e18751a0e130f67ce6a1ace9f79b95e097474febc981195b"
+    "1d13a69086c0863f66a7b7fdb48792227b1ac5e2489febdf087ab5486483033a6f001ca5d1ec1e27f5c30f4cec2642"
+    "074a39ae68aee552e196627a8e3d867e67a8c01b11e75f13cca0a97ab668b50cda07a8ecb7cd8e3dd7009c9636534f"
+    "6f239cffe1fc8daa466f78b676c7119efb96bce4e69ca2a25d0b34ed9c3ff999b801597d5220e307eaa5bee507fb94"
+    "d1fa69f9e519b2de315bac92c36f2ea1fa1df4478c0ddedeae8c70e0233cd098040cd796b02c370f1fa4cc0124f130"
+    "2e0201033029a1083106020100020101a203020120a30402020100a4053103020101a6053103020140bf8377020500"
+    "0420ccd540855f833a5e1480bfd2d36faf3aeee15df5beabe2691bc82dde2a7aa910041064c9f689c60ff6223ab6e6"
+    "999e0eb6e5");
 
 auto wrapped_key_masked = hex2str(
-    "30820179020100048201001EF5320D3C920D7614688A439409ACE4318C48395ABB7247A68671BD4B7156A7773B31A4"
-    "4459B73858625988A312E4D8855138F555678F525E4C52D91444FDC936BE6AEB63FD73FD84201EF46F88A0B622F528"
-    "956C92C9C731EB65BCBC6A03BEAB45959B54A768E2842D2CE174EE542EF2A15DCAA7542F3574BEEB1A991F95439466"
-    "E1960A9CE9E4CBC77DB23765191E4758C850908BCC74E158B77AB774141F171262C1AC771FDFA2E942F2F7633E97E8"
-    "0BD492C3E821361AC6B4F568DE351C816C8C997212C707F728FB3BCAAA796EA6B8E7A80BE010970B380122940277E9"
-    "4C5E9288F7CB6878A4C4CC1E83AB85A81FD68E43B14F1F81AD21E0D3545D70EE040C6D9721D08589581AB49204A330"
-    "2E0201033029A1083106020100020101A203020120A30402020100A4053103020101A6053103020140BF8377020500"
-    "0420A61C6E247E25B3E6E69AA78EB03C2D4AC20D1F99A9A024A76F35C8E2CAB9B68D04102560C70109AE67C030F00B"
-    "98B512A670");
+    "3082017902010004820100aad93ed5924f283b4bb5526fbe7a1412f9d9749ec30db9062b29e574a8546f33c8873245"
+    "2f5b8e6a391ee76c39ed1712c61d8df6213dec1cffbc17a8c6d04c7b30893d8daa9b2015213e21946821553207f8f9"
+    "931c4caba23ed3bee28b36947e47f10e0a5c3dc51c988a628daad3e5e1f4005e79c2d5a96c284b4b8d7e4948f331e5"
+    "b85dd5a236f85579f3ea1d1b848487470bdb0ab4f81a12bee42c99fe0df4bee3759453e69ad1d68a809ce06b949f76"
+    "94a990429b2fe81e066ff43e56a21602db70757922a4bcc23ab89f1e35da77586775f423e519c2ea394caf48a28d0c"
+    "8020f1dcf6b3a68ec246f615ae96dae9a079b1f6eb959033c1af5c125fd94168040c6d9721d08589581ab49204a330"
+    "2e0201033029a1083106020100020101a203020120a30402020100a4053103020101a6053103020140bf8377020500"
+    "0420a61c6e247e25b3e6e69aa78eb03c2d4ac20d1f99a9a024a76f35c8e2cab9b68d04102560c70109ae67c030f00b"
+    "98b512a670");
 
 auto wrapping_key = hex2str(
     "308204be020100300d06092a864886f70d0101010500048204a8308204a40201000282010100aec367931d8900ce56"
@@ -2265,14 +2266,16 @@
 TEST_F(ImportWrappedKeyTest, Success) {
     auto wrapping_key_desc = AuthorizationSetBuilder()
                                  .RsaEncryptionKey(2048, 65537)
-                                 .Digest(Digest::SHA1)
+                                 .Digest(Digest::SHA_2_256)
                                  .Padding(PaddingMode::RSA_OAEP)
                                  .Authorization(TAG_PURPOSE, KeyPurpose::WRAP_KEY);
 
     ASSERT_EQ(ErrorCode::OK,
               ImportWrappedKey(
                   wrapped_key, wrapping_key, wrapping_key_desc, zero_masking_key,
-                  AuthorizationSetBuilder().Digest(Digest::SHA1).Padding(PaddingMode::RSA_OAEP)));
+                  AuthorizationSetBuilder()
+                      .Digest(Digest::SHA_2_256)
+                      .Padding(PaddingMode::RSA_OAEP)));
 
     string message = "Hello World!";
     auto params = AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
@@ -2284,39 +2287,45 @@
 TEST_F(ImportWrappedKeyTest, SuccessMasked) {
     auto wrapping_key_desc = AuthorizationSetBuilder()
                                  .RsaEncryptionKey(2048, 65537)
-                                 .Digest(Digest::SHA1)
+                                 .Digest(Digest::SHA_2_256)
                                  .Padding(PaddingMode::RSA_OAEP)
                                  .Authorization(TAG_PURPOSE, KeyPurpose::WRAP_KEY);
 
     ASSERT_EQ(ErrorCode::OK,
               ImportWrappedKey(
                   wrapped_key_masked, wrapping_key, wrapping_key_desc, masking_key,
-                  AuthorizationSetBuilder().Digest(Digest::SHA1).Padding(PaddingMode::RSA_OAEP)));
+                  AuthorizationSetBuilder()
+                      .Digest(Digest::SHA_2_256)
+                      .Padding(PaddingMode::RSA_OAEP)));
 }
 
 TEST_F(ImportWrappedKeyTest, WrongMask) {
     auto wrapping_key_desc = AuthorizationSetBuilder()
                                  .RsaEncryptionKey(2048, 65537)
-                                 .Digest(Digest::SHA1)
+                                 .Digest(Digest::SHA_2_256)
                                  .Padding(PaddingMode::RSA_OAEP)
                                  .Authorization(TAG_PURPOSE, KeyPurpose::WRAP_KEY);
 
     ASSERT_EQ(ErrorCode::VERIFICATION_FAILED,
               ImportWrappedKey(
                   wrapped_key_masked, wrapping_key, wrapping_key_desc, zero_masking_key,
-                  AuthorizationSetBuilder().Digest(Digest::SHA1).Padding(PaddingMode::RSA_OAEP)));
+                  AuthorizationSetBuilder()
+                      .Digest(Digest::SHA_2_256)
+                      .Padding(PaddingMode::RSA_OAEP)));
 }
 
 TEST_F(ImportWrappedKeyTest, WrongPurpose) {
     auto wrapping_key_desc = AuthorizationSetBuilder()
                                  .RsaEncryptionKey(2048, 65537)
-                                 .Digest(Digest::SHA1)
+                                 .Digest(Digest::SHA_2_256)
                                  .Padding(PaddingMode::RSA_OAEP);
 
     ASSERT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
               ImportWrappedKey(
                   wrapped_key_masked, wrapping_key, wrapping_key_desc, zero_masking_key,
-                  AuthorizationSetBuilder().Digest(Digest::SHA1).Padding(PaddingMode::RSA_OAEP)));
+                  AuthorizationSetBuilder()
+                      .Digest(Digest::SHA_2_256)
+                      .Padding(PaddingMode::RSA_OAEP)));
 }
 
 typedef KeymasterHidlTest EncryptionOperationsTest;
@@ -2550,7 +2559,8 @@
               Begin(KeyPurpose::ENCRYPT,
                     AuthorizationSetBuilder().Padding(PaddingMode::RSA_OAEP).Digest(Digest::SHA_2_256)));
     string result;
-    EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(message, &result));
+    auto error = Finish(message, &result);
+    EXPECT_TRUE(error == ErrorCode::INVALID_INPUT_LENGTH || error == ErrorCode::INVALID_ARGUMENT);
     EXPECT_EQ(0U, result.size());
 }
 
@@ -2608,7 +2618,8 @@
     auto params = AuthorizationSetBuilder().Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT);
     EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
     string result;
-    EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, Finish(message, &result));
+    auto error = Finish(message, &result);
+    EXPECT_TRUE(error == ErrorCode::INVALID_INPUT_LENGTH || error == ErrorCode::INVALID_ARGUMENT);
     EXPECT_EQ(0U, result.size());
 }
 
@@ -2696,6 +2707,40 @@
 }
 
 /*
+ * EncryptionOperationsTest.AesWrongPurpose
+ *
+ * Verifies that AES encryption fails in the correct way when an unauthorized purpose is specified.
+ */
+TEST_F(EncryptionOperationsTest, AesWrongPurpose) {
+    auto err = GenerateKey(AuthorizationSetBuilder()
+                                   .Authorization(TAG_NO_AUTH_REQUIRED)
+                                   .AesKey(128)
+                                   .Authorization(TAG_PURPOSE, KeyPurpose::ENCRYPT)
+                                   .Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
+                                   .Authorization(TAG_MIN_MAC_LENGTH, 128)
+                                   .Padding(PaddingMode::NONE));
+    ASSERT_EQ(ErrorCode::OK, err) << "Got " << err;
+
+    err = Begin(KeyPurpose::DECRYPT,
+                AuthorizationSetBuilder().BlockMode(BlockMode::GCM).Padding(PaddingMode::NONE));
+    EXPECT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE, err) << "Got " << err;
+
+    CheckedDeleteKey();
+
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .AesKey(128)
+                                                 .Authorization(TAG_PURPOSE, KeyPurpose::DECRYPT)
+                                                 .Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
+                                                 .Authorization(TAG_MIN_MAC_LENGTH, 128)
+                                                 .Padding(PaddingMode::NONE)));
+
+    err = Begin(KeyPurpose::ENCRYPT,
+                AuthorizationSetBuilder().BlockMode(BlockMode::GCM).Padding(PaddingMode::NONE));
+    EXPECT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE, err) << "Got " << err;
+}
+
+/*
  * EncryptionOperationsTest.AesEcbNoPaddingWrongInputSize
  *
  * Verifies that AES encryption fails in the correct way when provided an input that is not a
@@ -3215,6 +3260,92 @@
 }
 
 /*
+ * EncryptionOperationsTest.AesGcmRoundTripWithDelaySuccess
+ *
+ * Verifies that AES GCM mode works, even when there's a long delay
+ * between operations.
+ */
+TEST_F(EncryptionOperationsTest, AesGcmRoundTripWithDelaySuccess) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                             .Authorization(TAG_NO_AUTH_REQUIRED)
+                                             .AesEncryptionKey(128)
+                                             .Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
+                                             .Padding(PaddingMode::NONE)
+                                             .Authorization(TAG_MIN_MAC_LENGTH, 128)));
+
+    string aad = "foobar";
+    string message = "123456789012345678901234567890123456";
+
+    auto begin_params = AuthorizationSetBuilder()
+                            .BlockMode(BlockMode::GCM)
+                            .Padding(PaddingMode::NONE)
+                            .Authorization(TAG_MAC_LENGTH, 128);
+
+    auto update_params =
+        AuthorizationSetBuilder().Authorization(TAG_ASSOCIATED_DATA, aad.data(), aad.size());
+
+    // Encrypt
+    AuthorizationSet begin_out_params;
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, begin_params, &begin_out_params))
+        << "Begin encrypt";
+    string ciphertext;
+    AuthorizationSet update_out_params;
+    sleep(5);
+    ASSERT_EQ(ErrorCode::OK,
+              Finish(op_handle_, update_params, message, "", &update_out_params, &ciphertext));
+
+    ASSERT_EQ(ciphertext.length(), message.length() + 16);
+
+    // Grab nonce
+    begin_params.push_back(begin_out_params);
+
+    // Decrypt.
+    ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, begin_params)) << "Begin decrypt";
+    string plaintext;
+    size_t input_consumed;
+    sleep(5);
+    ASSERT_EQ(ErrorCode::OK, Update(op_handle_, update_params, ciphertext, &update_out_params,
+                                    &plaintext, &input_consumed));
+    EXPECT_EQ(ciphertext.size(), input_consumed);
+    sleep(5);
+    EXPECT_EQ(ErrorCode::OK, Finish("", &plaintext));
+    EXPECT_EQ(message.length(), plaintext.length());
+    EXPECT_EQ(message, plaintext);
+}
+
+/*
+ * EncryptionOperationsTest.AesGcmDifferentNonces
+ *
+ * Verifies that encrypting the same data with different nonces produces different outputs.
+ */
+TEST_F(EncryptionOperationsTest, AesGcmDifferentNonces) {
+    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
+                                                 .Authorization(TAG_NO_AUTH_REQUIRED)
+                                                 .AesEncryptionKey(128)
+                                                 .Authorization(TAG_BLOCK_MODE, BlockMode::GCM)
+                                                 .Padding(PaddingMode::NONE)
+                                                 .Authorization(TAG_MIN_MAC_LENGTH, 128)
+                                                 .Authorization(TAG_CALLER_NONCE)));
+
+    string aad = "foobar";
+    string message = "123456789012345678901234567890123456";
+    string nonce1 = "000000000000";
+    string nonce2 = "111111111111";
+    string nonce3 = "222222222222";
+
+    string ciphertext1 =
+            EncryptMessage(message, BlockMode::GCM, PaddingMode::NONE, 128, HidlBuf(nonce1));
+    string ciphertext2 =
+            EncryptMessage(message, BlockMode::GCM, PaddingMode::NONE, 128, HidlBuf(nonce2));
+    string ciphertext3 =
+            EncryptMessage(message, BlockMode::GCM, PaddingMode::NONE, 128, HidlBuf(nonce3));
+
+    ASSERT_NE(ciphertext1, ciphertext2);
+    ASSERT_NE(ciphertext1, ciphertext3);
+    ASSERT_NE(ciphertext2, ciphertext3);
+}
+
+/*
  * EncryptionOperationsTest.AesGcmTooShortTag
  *
  * Verifies that AES GCM mode fails correctly when a too-short tag length is specified.
@@ -4329,75 +4460,61 @@
  *
  * This test checks that if rollback protection is implemented, DeleteKey invalidates a formerly
  * valid key blob.
- *
- * TODO(swillden):  Update to incorporate changes in rollback resistance semantics.
  */
 TEST_F(KeyDeletionTest, DeleteKey) {
-    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .RsaSigningKey(2048, 65537)
-                                             .Digest(Digest::NONE)
-                                             .Padding(PaddingMode::NONE)
-                                             .Authorization(TAG_NO_AUTH_REQUIRED)));
+    auto error = GenerateKey(AuthorizationSetBuilder()
+                                     .RsaSigningKey(2048, 65537)
+                                     .Digest(Digest::NONE)
+                                     .Padding(PaddingMode::NONE)
+                                     .Authorization(TAG_NO_AUTH_REQUIRED)
+                                     .Authorization(TAG_ROLLBACK_RESISTANCE));
+    ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK);
 
     // Delete must work if rollback protection is implemented
-    AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
-    bool rollback_protected = hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE);
+    if (error == ErrorCode::OK) {
+        AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
+        ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
 
-    if (rollback_protected) {
         ASSERT_EQ(ErrorCode::OK, DeleteKey(true /* keep key blob */));
-    } else {
-        auto delete_result = DeleteKey(true /* keep key blob */);
-        ASSERT_TRUE(delete_result == ErrorCode::OK | delete_result == ErrorCode::UNIMPLEMENTED);
-    }
 
-    string message = "12345678901234567890123456789012";
-    AuthorizationSet begin_out_params;
-
-    if (rollback_protected) {
+        string message = "12345678901234567890123456789012";
+        AuthorizationSet begin_out_params;
         EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
                   Begin(KeyPurpose::SIGN, key_blob_,
                         AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
                         &begin_out_params, &op_handle_));
-    } else {
-        EXPECT_EQ(ErrorCode::OK,
-                  Begin(KeyPurpose::SIGN, key_blob_,
-                        AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
-                        &begin_out_params, &op_handle_));
+        AbortIfNeeded();
+        key_blob_ = HidlBuf();
     }
-    AbortIfNeeded();
-    key_blob_ = HidlBuf();
 }
 
 /**
  * KeyDeletionTest.DeleteInvalidKey
  *
- * This test checks that the HAL excepts invalid key blobs.
- *
- * TODO(swillden):  Update to incorporate changes in rollback resistance semantics.
+ * This test checks that the HAL excepts invalid key blobs..
  */
 TEST_F(KeyDeletionTest, DeleteInvalidKey) {
     // Generate key just to check if rollback protection is implemented
-    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .RsaSigningKey(2048, 65537)
-                                             .Digest(Digest::NONE)
-                                             .Padding(PaddingMode::NONE)
-                                             .Authorization(TAG_NO_AUTH_REQUIRED)));
+    auto error = GenerateKey(AuthorizationSetBuilder()
+                                     .RsaSigningKey(2048, 65537)
+                                     .Digest(Digest::NONE)
+                                     .Padding(PaddingMode::NONE)
+                                     .Authorization(TAG_NO_AUTH_REQUIRED)
+                                     .Authorization(TAG_ROLLBACK_RESISTANCE));
+    ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK);
 
     // Delete must work if rollback protection is implemented
-    AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
-    bool rollback_protected = hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE);
+    if (error == ErrorCode::OK) {
+        AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
+        ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
 
-    // Delete the key we don't care about the result at this point.
-    DeleteKey();
+        // Delete the key we don't care about the result at this point.
+        DeleteKey();
 
-    // Now create an invalid key blob and delete it.
-    key_blob_ = HidlBuf("just some garbage data which is not a valid key blob");
+        // Now create an invalid key blob and delete it.
+        key_blob_ = HidlBuf("just some garbage data which is not a valid key blob");
 
-    if (rollback_protected) {
         ASSERT_EQ(ErrorCode::OK, DeleteKey());
-    } else {
-        auto delete_result = DeleteKey();
-        ASSERT_TRUE(delete_result == ErrorCode::OK | delete_result == ErrorCode::UNIMPLEMENTED);
     }
 }
 
@@ -4411,39 +4528,34 @@
  * device has been wiped manually (e.g., fastboot flashall -w), and new FBE/FDE keys have
  * been provisioned. Use this test only on dedicated testing devices that have no valuable
  * credentials stored in Keystore/Keymaster.
- *
- * TODO(swillden):  Update to incorporate changes in rollback resistance semantics.
  */
 TEST_F(KeyDeletionTest, DeleteAllKeys) {
     if (!arm_deleteAllKeys) return;
-    ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .RsaSigningKey(2048, 65537)
-                                             .Digest(Digest::NONE)
-                                             .Padding(PaddingMode::NONE)
-                                             .Authorization(TAG_NO_AUTH_REQUIRED)));
+    auto error = GenerateKey(AuthorizationSetBuilder()
+                                     .RsaSigningKey(2048, 65537)
+                                     .Digest(Digest::NONE)
+                                     .Padding(PaddingMode::NONE)
+                                     .Authorization(TAG_NO_AUTH_REQUIRED)
+                                     .Authorization(TAG_ROLLBACK_RESISTANCE));
+    ASSERT_TRUE(error == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE || error == ErrorCode::OK);
 
     // Delete must work if rollback protection is implemented
-    AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
-    bool rollback_protected = hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE);
+    if (error == ErrorCode::OK) {
+        AuthorizationSet hardwareEnforced(key_characteristics_.hardwareEnforced);
+        ASSERT_TRUE(hardwareEnforced.Contains(TAG_ROLLBACK_RESISTANCE));
 
-    ASSERT_EQ(ErrorCode::OK, DeleteAllKeys());
+        ASSERT_EQ(ErrorCode::OK, DeleteAllKeys());
 
-    string message = "12345678901234567890123456789012";
-    AuthorizationSet begin_out_params;
+        string message = "12345678901234567890123456789012";
+        AuthorizationSet begin_out_params;
 
-    if (rollback_protected) {
         EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
                   Begin(KeyPurpose::SIGN, key_blob_,
                         AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
                         &begin_out_params, &op_handle_));
-    } else {
-        EXPECT_EQ(ErrorCode::OK,
-                  Begin(KeyPurpose::SIGN, key_blob_,
-                        AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE),
-                        &begin_out_params, &op_handle_));
+        AbortIfNeeded();
+        key_blob_ = HidlBuf();
     }
-    AbortIfNeeded();
-    key_blob_ = HidlBuf();
 }
 
 using UpgradeKeyTest = KeymasterHidlTest;
@@ -4465,6 +4577,84 @@
     EXPECT_EQ(result, std::make_pair(ErrorCode::OK, HidlBuf()));
 }
 
+
+using ClearOperationsTest = KeymasterHidlTest;
+
+/*
+ * ClearSlotsTest.TooManyOperations
+ *
+ * Verifies that TOO_MANY_OPERATIONS is returned after the max number of
+ * operations are started without being finished or aborted. Also verifies
+ * that aborting the operations clears the operations.
+ *
+ */
+TEST_F(ClearOperationsTest, TooManyOperations) {
+    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_));
+    // Try again just in case there's a weird overflow bug
+    EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS,
+         Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &op_handle_));
+    for(int i=0; i<max_operations; i++) {
+        EXPECT_EQ(ErrorCode::OK, Abort(op_handles[i]));
+    }
+    EXPECT_EQ(ErrorCode::OK,
+         Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &op_handle_));
+    AbortIfNeeded();
+}
+
+/*
+ * ClearSlotsTest.ServiceDeath
+ *
+ * Verifies that the service is restarted after death and the ongoing
+ * operations are cleared.
+ */
+TEST_F(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]));
+    }
+}
+
+
 }  // namespace test
 }  // namespace V4_0
 }  // namespace keymaster
diff --git a/light/2.0/Android.bp b/light/2.0/Android.bp
index 6068752..d51f10d 100644
--- a/light/2.0/Android.bp
+++ b/light/2.0/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/light/2.0/default/Android.bp b/light/2.0/default/Android.bp
index 72cc873..ed48825 100644
--- a/light/2.0/default/Android.bp
+++ b/light/2.0/default/Android.bp
@@ -23,7 +23,6 @@
         "libbase",
         "liblog",
         "libhidlbase",
-        "libhidltransport",
         "libhardware",
         "libutils",
         "android.hardware.light@2.0",
@@ -44,7 +43,6 @@
         "libutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.light@2.0",
     ],
 }
diff --git a/light/2.0/vts/functional/VtsHalLightV2_0TargetTest.cpp b/light/2.0/vts/functional/VtsHalLightV2_0TargetTest.cpp
index 13290d9..6fcecd2 100644
--- a/light/2.0/vts/functional/VtsHalLightV2_0TargetTest.cpp
+++ b/light/2.0/vts/functional/VtsHalLightV2_0TargetTest.cpp
@@ -16,11 +16,13 @@
 
 #define LOG_TAG "light_hidl_hal_test"
 
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
 #include <android-base/logging.h>
 #include <android/hardware/light/2.0/ILight.h>
 #include <android/hardware/light/2.0/types.h>
+#include <gtest/gtest.h>
+#include <hidl/GtestPrinter.h>
+#include <hidl/ServiceManagement.h>
+
 #include <unistd.h>
 #include <set>
 
@@ -73,25 +75,10 @@
     Type::WIFI
 };
 
-// Test environment for Light HIDL HAL.
-class LightHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static LightHidlEnvironment* Instance() {
-        static LightHidlEnvironment* instance = new LightHidlEnvironment;
-        return instance;
-    }
-
-    virtual void registerTestServices() override { registerTestService<ILight>(); }
-   private:
-    LightHidlEnvironment() {}
-};
-
-class LightHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-public:
+class LightHidlTest : public testing::TestWithParam<std::string> {
+  public:
     virtual void SetUp() override {
-        light = ::testing::VtsHalHidlTargetTestBase::getService<ILight>(
-            LightHidlEnvironment::Instance()->getServiceName<ILight>());
+        light = ILight::getService(GetParam());
 
         ASSERT_NE(light, nullptr);
         LOG(INFO) << "Test is remote " << light->isRemote();
@@ -120,13 +107,12 @@
             EXPECT_EQ(Status::SUCCESS, static_cast<Status>(ret));
         }
     }
-
 };
 
 /**
  * Ensure all lights which are reported as supported work.
  */
-TEST_F(LightHidlTest, TestSupported) {
+TEST_P(LightHidlTest, TestSupported) {
     for (const Type& type: supportedTypes) {
         Return<Status> ret = light->setLight(type, kWhite);
         EXPECT_OK(ret);
@@ -137,7 +123,7 @@
 /**
  * Ensure BRIGHTNESS_NOT_SUPPORTED is returned if LOW_PERSISTANCE is not supported.
  */
-TEST_F(LightHidlTest, TestLowPersistance) {
+TEST_P(LightHidlTest, TestLowPersistance) {
     for (const Type& type: supportedTypes) {
         Return<Status> ret = light->setLight(type, kLowPersistance);
         EXPECT_OK(ret);
@@ -151,7 +137,7 @@
 /**
  * Ensure lights which are not supported return LIGHT_NOT_SUPPORTED
  */
-TEST_F(LightHidlTest, TestUnsupported) {
+TEST_P(LightHidlTest, TestUnsupported) {
     std::set<Type> unsupportedTypes = kAllTypes;
     for (const Type& type: supportedTypes) {
         unsupportedTypes.erase(type);
@@ -164,11 +150,7 @@
     }
 }
 
-int main(int argc, char **argv) {
-    ::testing::AddGlobalTestEnvironment(LightHidlEnvironment::Instance());
-    ::testing::InitGoogleTest(&argc, argv);
-    LightHidlEnvironment::Instance()->init(&argc, argv);
-    int status = RUN_ALL_TESTS();
-    LOG(INFO) << "Test result = " << status;
-    return status;
-}
+INSTANTIATE_TEST_SUITE_P(
+        PerInstance, LightHidlTest,
+        testing::ValuesIn(android::hardware::getAllHalInstanceNames(ILight::descriptor)),
+        android::hardware::PrintInstanceNameToString);
diff --git a/light/utils/Android.bp b/light/utils/Android.bp
index ebcbfa2..4c287e4 100644
--- a/light/utils/Android.bp
+++ b/light/utils/Android.bp
@@ -24,7 +24,6 @@
         "android.hardware.light@2.0",
         "libbase",
         "libhidlbase",
-        "libhidltransport",
         "libutils",
     ],
 }
diff --git a/light/utils/main.cpp b/light/utils/main.cpp
index d07e799..b834132 100644
--- a/light/utils/main.cpp
+++ b/light/utils/main.cpp
@@ -25,7 +25,7 @@
     std::cerr << msg << std::endl;
 }
 
-int main() {
+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;
@@ -41,10 +41,29 @@
         return -1;
     }
 
-    const static LightState off = {
-        .color = 0u, .flashMode = Flash::NONE, .brightnessMode = Brightness::USER,
+    static LightState off = {
+            .color = 0u,
+            .flashMode = Flash::NONE,
+            .brightnessMode = Brightness::USER,
     };
 
+    if (argc > 2) {
+        error("Usage: blank_screen [color]");
+        return -1;
+    }
+
+    if (argc > 1) {
+        char* col_ptr;
+        unsigned int col_new;
+
+        col_new = 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;
+    }
+
     service->getSupportedTypes([&](const hidl_vec<Type>& types) {
         for (Type type : types) {
             Status ret = service->setLight(type, off);
diff --git a/media/1.0/Android.bp b/media/1.0/Android.bp
index 844cfa2..2dbe466 100644
--- a/media/1.0/Android.bp
+++ b/media/1.0/Android.bp
@@ -14,4 +14,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/media/bufferpool/1.0/Android.bp b/media/bufferpool/1.0/Android.bp
index 86297d3..079e47f 100644
--- a/media/bufferpool/1.0/Android.bp
+++ b/media/bufferpool/1.0/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/media/bufferpool/2.0/Android.bp b/media/bufferpool/2.0/Android.bp
index 0faa00e..6a82616 100644
--- a/media/bufferpool/2.0/Android.bp
+++ b/media/bufferpool/2.0/Android.bp
@@ -18,4 +18,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/media/c2/1.0/Android.bp b/media/c2/1.0/Android.bp
index 895e9db..391e6c4 100644
--- a/media/c2/1.0/Android.bp
+++ b/media/c2/1.0/Android.bp
@@ -31,4 +31,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/media/omx/1.0/Android.bp b/media/omx/1.0/Android.bp
index ee51d5d..5fe73ab 100644
--- a/media/omx/1.0/Android.bp
+++ b/media/omx/1.0/Android.bp
@@ -23,4 +23,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/memtrack/1.0/Android.bp b/memtrack/1.0/Android.bp
index 0f24977..a50195e 100644
--- a/memtrack/1.0/Android.bp
+++ b/memtrack/1.0/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/memtrack/1.0/default/Android.bp b/memtrack/1.0/default/Android.bp
index 76d7fc8..8aa33ee 100644
--- a/memtrack/1.0/default/Android.bp
+++ b/memtrack/1.0/default/Android.bp
@@ -23,7 +23,6 @@
         "libbase",
         "liblog",
         "libhidlbase",
-        "libhidltransport",
         "libhardware",
         "libutils",
         "android.hardware.memtrack@1.0",
@@ -46,7 +45,6 @@
         "libutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.memtrack@1.0",
     ],
 
diff --git a/memtrack/1.0/default/android.hardware.memtrack@1.0-service.rc b/memtrack/1.0/default/android.hardware.memtrack@1.0-service.rc
index 4327a20..f5eee54 100644
--- a/memtrack/1.0/default/android.hardware.memtrack@1.0-service.rc
+++ b/memtrack/1.0/default/android.hardware.memtrack@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.memtrack-hal-1-0 /vendor/bin/hw/android.hardware.memtrack@1.0-service
+    interface android.hardware.memtrack@1.0::IMemtrack default
     class hal
     user system
     group system
diff --git a/neuralnetworks/1.0/Android.bp b/neuralnetworks/1.0/Android.bp
index 63b5b98..3e740c4 100644
--- a/neuralnetworks/1.0/Android.bp
+++ b/neuralnetworks/1.0/Android.bp
@@ -18,4 +18,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/neuralnetworks/1.0/IPreparedModel.hal b/neuralnetworks/1.0/IPreparedModel.hal
index ecaa7f8..3dc3202 100644
--- a/neuralnetworks/1.0/IPreparedModel.hal
+++ b/neuralnetworks/1.0/IPreparedModel.hal
@@ -42,11 +42,21 @@
      * execute function. This callback must be provided with the ErrorStatus of
      * the execution.
      *
-     * If the prepared model was prepared from a model wherein all
-     * tensor operands have fully specified dimensions, and the inputs
-     * to the function are valid, then the execution should launch
-     * and complete successfully (ErrorStatus::NONE). There must be
-     * no failure unless the device itself is in a bad state.
+     * If the launch is successful, the caller must not change the content of
+     * any data object referenced by 'request' (described by the
+     * {@link DataLocation} of a {@link RequestArgument}) until the
+     * asynchronous task has invoked the callback object. The asynchronous task
+     * must not change the content of any of the data objects corresponding to
+     * 'request' inputs.
+     *
+     * If the prepared model was prepared from a model wherein all tensor
+     * operands have fully specified dimensions, and the inputs to the function
+     * are valid, then:
+     * - the execution should launch successfully (ErrorStatus::NONE): There
+     *   must be no failure unless the device itself is in a bad state.
+     * - if at execution time every operation's input operands have legal
+     *   values, the execution should complete successfully (ErrorStatus::NONE):
+     *   There must be no failure unless the device itself is in a bad state.
      *
      * Multiple threads can call the execute function on the same IPreparedModel
      * object concurrently with different requests.
diff --git a/neuralnetworks/1.0/types.hal b/neuralnetworks/1.0/types.hal
index 02db063..ba9d068 100644
--- a/neuralnetworks/1.0/types.hal
+++ b/neuralnetworks/1.0/types.hal
@@ -25,25 +25,24 @@
  * with at least one dimension). Types not prefaced by TENSOR_* represent
  * scalar values and must have no dimensions.
  *
- * Although many types are defined, most operators accept just a few
+ * Although we define many types, most operators accept just a few
  * types. Most used are {@link OperandType::TENSOR_FLOAT32},
  * {@link OperandType::TENSOR_QUANT8_ASYMM},
  * and {@link OperandType::INT32}.
  */
 enum OperandType : int32_t {
     /** A 32 bit floating point scalar value. */
-    FLOAT32             = 0,
+    FLOAT32 = 0,
     /** A signed 32 bit integer scalar value. */
-    INT32               = 1,
+    INT32 = 1,
     /** An unsigned 32 bit integer scalar value. */
-    UINT32              = 2,
-
+    UINT32 = 2,
     /** A tensor of 32 bit floating point values. */
-    TENSOR_FLOAT32      = 3,
+    TENSOR_FLOAT32 = 3,
     /** A tensor of 32 bit integer values. */
-    TENSOR_INT32        = 4,
+    TENSOR_INT32 = 4,
     /**
-     * A tensor of 8 bit integers that represent real numbers.
+     * A tensor of 8 bit unsigned integers that represent real numbers.
      *
      * Attached to this tensor are two numbers that can be used to convert the
      * 8 bit integer to the real value and vice versa. These two numbers are:
@@ -51,21 +50,21 @@
      * - zeroPoint: a 32 bit integer, in range [0, 255].
      *
      * The formula is:
-     * real_value = (integer_value - zeroPoint) * scale.
+     *   real_value = (integer_value - zeroPoint) * scale.
      */
     TENSOR_QUANT8_ASYMM = 5,
 
     /**
-     * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to
-     * OEM operation and data types.
+     * DEPRECATED. Since HAL version 1.2, extensions are the preferred
+     * alternative to OEM operation and data types.
      *
      * OEM specific scalar value.
      */
     OEM                 = 10000,
 
     /**
-     * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to
-     * OEM operation and data types.
+     * DEPRECATED. Since HAL version 1.2, extensions are the preferred
+     * alternative to OEM operation and data types.
      *
      * A tensor of OEM specific values.
      */
@@ -78,7 +77,6 @@
  * The type of an operation in a model.
  */
 enum OperationType : int32_t {
-
     /**
      * Adds two tensors, element-wise.
      *
@@ -110,14 +108,16 @@
      * * 0: A tensor.
      * * 1: A tensor of the same {@link OperandType}, and compatible dimensions
      *      as input0.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scales and zeroPoint can be different from input0 scale and zeroPoint.
      * * 2: An {@link OperandType::INT32} scalar, and has to be one of the
      *      {@link FusedActivationFunc} values. Specifies the activation to
      *      invoke on the result.
      *
      * Outputs:
      * * 0: The sum, a tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      */
     ADD = 0,
 
@@ -187,8 +187,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, out_height, out_width, depth].
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     AVERAGE_POOL_2D = 1,
 
@@ -206,22 +206,23 @@
      *
      * Inputs:
      * * 0 ~ n-1: The list of n input tensors, of shape
-     *            [D0, D1, ..., Daxis(i), ..., Dm]. For inputs of
-     *            {@link OperandType::TENSOR_QUANT8_ASYMM}, all input tensors
-     *            must have the same scale and zeroPoint.
+     *            [D0, D1, ..., Daxis(i), ..., Dm].
+     *            All input tensors of
+     *            {@link OperandType::TENSOR_QUANT8_ASYMM}
+     *            must have the same scale and zeroPoint as the output tensor.
      * * n: An {@link OperandType::INT32} scalar, specifying the
      *      concatenation axis.
      *
      * Outputs:
      * * 0: The output, a tensor of the same {@link OperandType} as the input
      *      tensors. The output shape is [D0, D1, ..., sum(Daxis(i)), ..., Dm].
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor, the scale and zeroPoint
+     *      values must be the same as the input tensors'.
      */
     CONCATENATION = 2,
 
     /**
-     * Performs an 2-D convolution operation.
+     * Performs a 2-D convolution operation.
      *
      * The CONV_2D op sweeps a 2-D filter that can mix channels together over a
      * batch of images, applying the filter to each window of each image of the
@@ -238,11 +239,17 @@
      *             filter[channel, di, dj, k]
      *         ) + bias[channel]
      *
-     * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT32}
-     * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor {@link OperandType} configurations:
+     * * 32 bit floating point:
+     * * * {@link OperandType::TENSOR_FLOAT32} for input, filter, output, and bias.
      *
-     * Supported tensor rank: 4, with "NHWC" data layout.
+     * * Quantized:
+     * * * {@link OperandType::TENSOR_QUANT8_ASYMM} for input, filter, and output.
+     * * * {@link OperandType::TENSOR_INT32} for bias (with scale set to
+     * * * input.scale * filter.scale).
+     *
+     * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+     * and Channels) data layout.
      *
      * Both explicit padding and implicit padding are supported.
      *
@@ -252,12 +259,12 @@
      * * 1: A 4-D tensor, of shape
      *      [depth_out, filter_height, filter_width, depth_in], specifying the
      *      filter.
-     * * 2: A 1-D tensor, of shape [depth_out], specifying the bias.
-     *      For input tensor of {@link OperandType::TENSOR_FLOAT32}, the bias
-     *      should also be of {@link OperandType::TENSOR_FLOAT32}. For input
-     *      tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the bias
-     *      should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of
-     *      0 and bias_scale == input_scale * filter_scale.
+     * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
+     *      tensor of type {@link OperandType::TENSOR_FLOAT32}
+     *      the bias must be of the same
+     *      type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
+     *      the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
+     *      of 0 and bias_scale == input_scale * filter_scale.
      * * 3: An {@link OperandType::INT32} scalar, specifying the padding on
      *      the left, in the ‘width’ dimension.
      * * 4: An {@link OperandType::INT32} scalar, specifying the padding on
@@ -281,11 +288,11 @@
      *      [depth_out, filter_height, filter_width, depth_in], specifying the
      *      filter.
      * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
-     *      tensor of {@link OperandType::TENSOR_FLOAT32}, the bias should
-     *      also be of {@link OperandType::TENSOR_FLOAT32}. For input tensor
-     *      of {@link OperandType::TENSOR_QUANT8_ASYMM}, the bias should be
-     *      of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0 and
-     *      bias_scale == input_scale * filter_scale.
+     *      tensor of type {@link OperandType::TENSOR_FLOAT32}
+     *      the bias must be of the same
+     *      type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
+     *      the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
+     *      of 0 and bias_scale == input_scale * filter_scale.
      * * 3: An {@link OperandType::INT32} scalar, specifying the implicit
      *      padding scheme, has to be one of the
      *      following values: {0 (NONE), 1 (SAME), 2 (VALID)}.
@@ -299,11 +306,9 @@
      *
      * Outputs:
      * * 0: The output 4-D tensor, of shape
-     *      [batches, out_height, out_width, depth_out]. For output tensor of
-     *      {@link OperandType::TENSOR_QUANT8_ASYMM}, the following condition
-     *      must be satisfied: output_scale > input_scale * filter_scale.
-     *
-     * Available since API level 27.
+     *      [batches, out_height, out_width, depth_out].
+     *      For output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
+     *      the following condition must be satisfied: output_scale > input_scale * filter_scale
      */
     CONV_2D = 3,
 
@@ -329,11 +334,17 @@
      *             filter[1, di, dj, k * channel_multiplier + q]
      *         ) + bias[k * channel_multiplier + q]
      *
-     * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT32}
-     * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     * Supported tensor {@link OperandType} configurations:
+     * * 32 bit floating point:
+     * * * {@link OperandType::TENSOR_FLOAT32} for input, filter, output, and bias.
      *
-     * Supported tensor rank: 4, with "NHWC" data layout.
+     * * Quantized:
+     * * * {@link OperandType::TENSOR_QUANT8_ASYMM} for input, filter, and output.
+     * * * {@link OperandType::TENSOR_INT32} for bias (with scale set to
+     * * * input.scale * filter.scale).
+     *
+     * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+     * and Channels) data layout.
      *
      * Both explicit padding and implicit padding are supported.
      *
@@ -343,11 +354,11 @@
      * * 1: A 4-D tensor, of shape [1, filter_height, filter_width, depth_out],
      *      specifying the filter.
      * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
-     *      tensor of {@link OperandType::TENSOR_FLOAT32}, the bias should
-     *      also be of {@link OperandType::TENSOR_FLOAT32}. For input tensor
-     *      of {@link OperandType::TENSOR_QUANT8_ASYMM}, the bias should be
-     *      of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0 and
-     *      bias_scale == input_scale * filter_scale.
+     *      tensor of type {@link OperandType::TENSOR_FLOAT32}
+     *      the bias must be of the same
+     *      type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
+     *      the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
+     *      of 0 and bias_scale == input_scale * filter_scale.
      * * 3: An {@link OperandType::INT32} scalar, specifying the padding on
      *      the left, in the ‘width’ dimension.
      * * 4: An {@link OperandType::INT32} scalar, specifying the padding on
@@ -372,11 +383,11 @@
      * * 1: A 4-D tensor, of shape [1, filter_height, filter_width, depth_out],
      *      specifying the filter.
      * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
-     *      tensor of {@link OperandType::TENSOR_FLOAT32}, the bias should
-     *      also be of {@link OperandType::TENSOR_FLOAT32}. For input tensor
-     *      of {@link OperandType::TENSOR_QUANT8_ASYMM}, the bias should be
-     *      of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0 and
-     *      bias_scale == input_scale * filter_scale.
+     *      tensor of type {@link OperandType::TENSOR_FLOAT32}
+     *      the bias must be of the same
+     *      type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
+     *      the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
+     *      of 0 and bias_scale == input_scale * filter_scale.
      * * 3: An {@link OperandType::INT32} scalar, specifying the implicit
      *      padding scheme, has to be one of the
      *      following values: {0 (NONE), 1 (SAME), 2 (VALID)}.
@@ -392,11 +403,10 @@
      *
      * Outputs:
      * * 0: The output 4-D tensor, of shape
-     *      [batches, out_height, out_width, depth_out]. For output tensor of
-     *      {@link OperandType::TENSOR_QUANT8_ASYMM}, the following condition
-     *      must be satisfied: output_scale > input_scale * filter_scale.
-     *
-     * Available since API level 27.
+     *      [batches, out_height, out_width, depth_out]. For
+     *      output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
+     *      the following condition must be satisfied:
+     *      output_scale > input_scale * filter_scale
      */
     DEPTHWISE_CONV_2D = 4,
 
@@ -419,7 +429,8 @@
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
-     * Supported tensor rank: 4, with "NHWC" data layout.
+     * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+     * and Channels) data layout.
      *
      * Inputs:
      * * 0: A 4-D tensor, of shape [batches, height, width, depth_in],
@@ -431,8 +442,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape [batch, height*block_size,
      *      width*block_size, depth/(block_size*block_size)].
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     DEPTH_TO_SPACE = 5,
 
@@ -443,19 +454,19 @@
      *
      *     output = (input - zeroPoint) * scale.
      *
-     * Supported tensor {@link OperandType}:
+     * Supported input tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
+     * Supported output tensor {@link OperandType}:
+     * * {@link OperandType::TENSOR_FLOAT32}.
+     *
      * Supported tensor rank: up to 4
      *
      * Inputs:
-     * * 0: A tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}.
+     * * 0: A tensor.
      *
      * Outputs:
-     * * 0: The output tensor of same shape as input0, but with
-     *      {@link OperandType::TENSOR_FLOAT32}.
-     *
-     * Available since API level 27.
+     * * 0: A tensor with the same shape as input0.
      */
     DEQUANTIZE = 6,
 
@@ -479,6 +490,13 @@
      * If a value in Lookups is out of bounds, the operation must fail
      * and an error must be reported.
      *
+     * Supported value tensor {@link OperandType}:
+     * * {@link OperandType::TENSOR_FLOAT32}
+     * * {@link OperandType::TENSOR_INT32}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     *
+     * Supported value tensor rank: from 2
+     *
      * Inputs:
      * * 0: Lookups. A 1-D tensor of {@link OperandType::TENSOR_INT32}.
      *      The values are indices into the first dimension of Values.
@@ -489,8 +507,8 @@
      * * 0: A n-D tensor with the same rank and shape as the Values
      *      tensor, except for the first dimension which has the same size
      *      as Lookups' only dimension.
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input1.
      */
     EMBEDDING_LOOKUP = 7,
 
@@ -508,8 +526,6 @@
      * Outputs:
      * * 0: The output tensor, of the same {@link OperandType} and dimensions as
      *      the input tensor.
-     *
-     * Available since API level 27.
      */
     FLOOR = 8,
 
@@ -549,12 +565,9 @@
      *      invoke on the result.
      *
      * Outputs:
-     * * 0: The output tensor, of shape [batch_size, num_units]. For output
-     *      tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the following
-     *      condition must be satisfied:
-     *      output_scale > input_scale * filter_scale.
-     *
-     * Available since API level 27.
+     * * 0: The output tensor, of shape [batch_size, num_units]. For
+     *      output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the following
+     *      condition must be satisfied: output_scale > input_scale * filter_scale.
      */
     FULLY_CONNECTED = 9,
 
@@ -585,6 +598,13 @@
      * must be selected. If no entry in Keys has 123456, a slice of zeroes
      * must be concatenated.
      *
+     * Supported value tensor {@link OperandType}:
+     * * {@link OperandType::TENSOR_FLOAT32}
+     * * {@link OperandType::TENSOR_INT32}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     *
+     * Supported value tensor rank: from 2
+     *
      * Inputs:
      * * 0: Lookups. A 1-D {@link OperandType::TENSOR_INT32} tensor with
      *      shape [ k ].
@@ -598,13 +618,13 @@
      *
      * Outputs:
      * * 0: Output. A tensor with shape [ k …].
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input2.
      * * 1: Hits. A boolean tensor with shape [ k ] indicates whether the lookup
      *      hits (True) or not (False).
      *      Stored as {@link OperandType::TENSOR_QUANT8_ASYMM} with offset 0
      *      and scale 1.0f.
      *      A non-zero byte represents True, a hit. A zero indicates otherwise.
-     *
-     * Available since API level 27.
      */
     HASHTABLE_LOOKUP = 10,
 
@@ -617,9 +637,6 @@
      *         input[batch, row, col, channel] /
      *         sqrt(sum_{c} pow(input[batch, row, col, c], 2))
      *
-     * For input tensor with more dimensions, independently normalizes each 1-D
-     * slice along dimension dim.
-     *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT32}
      *
@@ -627,13 +644,10 @@
      * Height, Width, and Channels).
      *
      * Inputs:
-     * * 0: A 4-D tensor, of shape [batches, height, width, depth].
+     * * 0: A 4-D tensor, specifying the tensor to be normalized.
      *
      * Outputs:
-     * * 0: The output 4-D tensor, of the same shape as input
-     *      [batches, height, width, depth].
-     *
-     * Available since API level 27.
+     * * 0: A tensor of the same {@link OperandType} and same shape as input0.
      */
     L2_NORMALIZATION = 11,
 
@@ -652,7 +666,8 @@
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT32}
      *
-     * Supported tensor rank: 4, with "NHWC" data layout.
+     * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+     * and Channels) data layout.
      *
      * Both explicit padding and implicit padding are supported.
      *
@@ -700,8 +715,6 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, out_height, out_width, depth].
-     *
-     * Available since API level 27.
      */
     L2_POOL_2D = 12,
 
@@ -729,17 +742,18 @@
      *      the input.
      * * 1: An {@link OperandType::INT32} scalar, specifying the radius of
      *      the normalization window.
-     * * 2: An {@link OperandType::FLOAT32} scalar, specifying the bias, must
-     *      not be zero.
-     * * 3: An {@link OperandType::FLOAT32} scalar, specifying the scale
-     *      factor, alpha.
-     * * 4: An {@link OperandType::FLOAT32} scalar, specifying the exponent,
-     *      beta.
+     * * 2: A scalar, specifying the bias, must not be zero.
+     *      For input tensor of {@link OperandType::TENSOR_FLOAT32}, the bias
+     *      value must be of {@link OperandType::FLOAT32}.
+     * * 3: A scalar, specifying the scale factor, alpha.
+     *      For input tensor of {@link OperandType::TENSOR_FLOAT32}, the
+     *      alpha value must be of {@link OperandType::FLOAT32}.
+     * * 4: A scalar, specifying the exponent, beta.
+     *      For input tensor of {@link OperandType::TENSOR_FLOAT32}, the beta
+     *      value must be of {@link OperandType::FLOAT32}.
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
-     *
-     * Available since API level 27.
      */
     LOCAL_RESPONSE_NORMALIZATION = 13,
 
@@ -763,45 +777,53 @@
      * * 0: The output tensor of same shape as input0.
      *      For {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the scale must be 1.f / 256 and the zeroPoint must be 0.
-     *
-     * Available since API level 27.
      */
     LOGISTIC = 14,
 
     /**
      * Projects an input to a bit vector via locality senstive hashing.
      *
+     * Supported input tensor {@link OperandType}:
+     * * {@link OperandType::TENSOR_FLOAT32}
+     * * {@link OperandType::TENSOR_INT32}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     *
+     * Supported input tensor rank: from 1
+     *
      * Inputs:
      * * 0: Hash functions. Dim.size == 2, DataType: Float.
-     *            Tensor[0].Dim[0]: Number of hash functions.
-     *            Tensor[0].Dim[1]: Number of seeds per hash functions.
-     *            Tensor[0].Dim[1] <= 32 in sparse case.
+     *      Tensor[0].Dim[0]: Number of hash functions.
+     *      Tensor[0].Dim[1]: Number of projected output bits generated by each
+     *      hash function.
+     *      If the projection type is Sparse:
+     *      Tensor[0].Dim[1] + ceil(log2(Tensor[0].Dim[0])) <= 32
      *
      * * 1: Input. Dim.size >= 1, no restriction on DataType.
      * * 2: Weight. Optional. Dim.size == 1, DataType: Float.
-     *     If not set, each input element is considered to have the same weight
-     *     of 1.0.
-     *     Tensor[1].Dim[0] == Tensor[2].Dim[0]
+     *      If not set, each input element is considered to have the same weight
+     *      of 1.0.
+     *      Tensor[1].Dim[0] == Tensor[2].Dim[0]
      * * 3: Type:
-     *        Sparse: Value LSHProjectionType_SPARSE(=1).
+     *        Sparse:
+     *          Value LSHProjectionType_SPARSE(=1).
      *          Computed bit vector is considered to be sparse.
      *          Each output element is an int32 made up of multiple bits
      *          computed from hash functions.
      *
-     *        Dense: Value LSHProjectionType_DENSE(=2).
+     *        Dense:
+     *          Value LSHProjectionType_DENSE(=2).
      *          Computed bit vector is considered to be dense. Each output
      *          element represents a bit and can take the value of either
      *          0 or 1.
      *
      * Outputs:
-     * * 0: If the projection type is sparse:
-     *        Output.Dim == { Tensor[0].Dim[0] }
-     *        A tensor of int32 that represents hash signatures.
-     *      If the projection type is Dense:
-     *        Output.Dim == { Tensor[0].Dim[0] * Tensor[0].Dim[1] }
-     *        A flattened tensor that represents projected bit vectors.
+     * * 0: If the projection type is Sparse:
+     *      Output.Dim == { Tensor[0].Dim[0] }
+     *      A tensor of int32 that represents hash signatures.
      *
-     * Available since API level 27.
+     *      If the projection type is Dense:
+     *      Output.Dim == { Tensor[0].Dim[0] * Tensor[0].Dim[1] }
+     *      A flattened tensor that represents projected bit vectors.
      */
     LSH_PROJECTION = 15,
 
@@ -901,71 +923,54 @@
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT32}
      *
+     * All input and output tensors must be of the same type.
+     *
      * Inputs:
      * * 0: The input (\f$x_t\f$).
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [batch_size, input_size], where “batch_size” corresponds to the
-     *      batching dimension, and “input_size” is the size of the input.
+     *      A 2-D tensor of shape [batch_size, input_size], where “batch_size”
+     *      corresponds to the batching dimension, and “input_size” is the size
+     *      of the input.
      * * 1: The input-to-input weights (\f$W_{xi}\f$). Optional.
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units, input_size], where “num_units” corresponds to the
-     *      number of cell units.
+     *      A 2-D tensor of shape [num_units, input_size], where “num_units”
+     *      corresponds to the number of cell units.
      * * 2: The input-to-forget weights (\f$W_{xf}\f$).
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units, input_size].
+     *      A 2-D tensor of shape [num_units, input_size].
      * * 3: The input-to-cell weights (\f$W_{xc}\f$).
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units, input_size].
+     *      A 2-D tensor of shape [num_units, input_size].
      * * 4: The input-to-output weights (\f$W_{xo}\f$).
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units, input_size].
+     *      A 2-D tensor of shape [num_units, input_size].
      * * 5: The recurrent-to-input weights (\f$W_{hi}\f$). Optional.
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units, output_size], where “output_size” corresponds to either
-     *      the number of cell units (i.e., “num_units”), or the second
-     *      dimension of the “projection_weights”, if defined.
+     *      A 2-D tensor of shape [num_units, output_size], where “output_size”
+     *      corresponds to either the number of cell units (i.e., “num_units”),
+     *      or the second dimension of the “projection_weights”, if defined.
      * * 6: The recurrent-to-forget weights (\f$W_{hf}\f$).
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units, output_size].
+     *      A 2-D tensor of shape [num_units, output_size].
      * * 7: The recurrent-to-cell weights (\f$W_{hc}\f$).
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units, output_size].
+     *      A 2-D tensor of shape [num_units, output_size].
      * * 8: The recurrent-to-output weights (\f$W_{ho}\f$).
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units, output_size].
+     *      A 2-D tensor of shape [num_units, output_size].
      * * 9: The cell-to-input weights (\f$W_{ci}\f$). Optional.
-     *      A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units].
+     *      A 1-D tensor of shape [num_units].
      * * 10:The cell-to-forget weights (\f$W_{cf}\f$). Optional.
-     *      A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units].
+     *      A 1-D tensor of shape [num_units].
      * * 11:The cell-to-output weights (\f$W_{co}\f$). Optional.
-     *      A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units].
+     *      A 1-D tensor of shape [num_units].
      * * 12:The input gate bias (\f$b_i\f$). Optional.
-     *      A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units].
+     *      A 1-D tensor of shape [num_units].
      * * 13:The forget gate bias (\f$b_f\f$).
-     *      A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units].
+     *      A 1-D tensor of shape [num_units].
      * * 14:The cell bias (\f$b_c\f$).
-     *      A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units].
+     *      A 1-D tensor of shape [num_units].
      * * 15:The output gate bias (\f$b_o\f$).
-     *      A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units].
+     *      A 1-D tensor of shape [num_units].
      * * 16:The projection weights (\f$W_{proj}\f$). Optional.
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [output_size, num_units].
+     *      A 2-D tensor of shape [output_size, num_units].
      * * 17:The projection bias (\f$b_{proj}\f$). Optional.
-     *      A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [output_size].
+     *      A 1-D tensor of shape [output_size].
      * * 18:The output state (in) (\f$h_{t-1}\f$).
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [batch_size, output_size].
+     *      A 2-D tensor of shape [batch_size, output_size].
      * * 19:The cell state (in) (\f$C_{t-1}\f$).
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [batch_size, num_units].
+     *      A 2-D tensor of shape [batch_size, num_units].
      * * 20:The activation function (\f$g\f$).
      *      A value indicating the activation function:
      *      <ul>
@@ -984,21 +989,15 @@
      *
      * Outputs:
      * * 0: The scratch buffer.
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [batch_size, num_units * 3] with CIFG, or
+     *      A 2-D tensor of shape [batch_size, num_units * 3] with CIFG, or
      *      [batch_size, num_units * 4] without CIFG.
      * * 1: The output state (out) (\f$h_t\f$).
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [batch_size, output_size].
+     *      A 2-D tensor of shape [batch_size, output_size].
      * * 2: The cell state (out) (\f$C_t\f$).
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [batch_size, num_units].
+     *      A 2-D tensor of shape [batch_size, num_units].
      * * 3: The output (\f$o_t\f$).
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [batch_size, output_size]. This is effectively the same as the
-     *      current “output state (out)” value.
-     *
-     * Available since API level 27.
+     *      A 2-D tensor of shape [batch_size, output_size]. This is effectively
+     *      the same as the current “output state (out)” value.
      */
     LSTM = 16,
 
@@ -1019,7 +1018,8 @@
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
-     * Supported tensor rank: 4, with "NHWC" data layout.
+     * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+     * and Channels) data layout.
      *
      * Both explicit padding and implicit padding are supported.
      *
@@ -1067,8 +1067,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, out_height, out_width, depth].
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     MAX_POOL_2D = 17,
 
@@ -1106,8 +1106,6 @@
      *      For output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the following condition must be satisfied:
      *      output_scale > input1_scale * input2_scale.
-     *
-     * Available since API level 27.
      */
     MUL = 18,
 
@@ -1129,8 +1127,8 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     RELU = 19,
 
@@ -1151,9 +1149,9 @@
      * * 0: A tensor, specifying the input.
      *
      * Outputs:
-     * * 0: The output tensor of same shape as input0.
-     *
-     * Available since API level 27.
+     * * 0: The output tensor of the same shape as input0.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     RELU1 = 20,
 
@@ -1175,8 +1173,8 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     RELU6 = 21,
 
@@ -1205,8 +1203,8 @@
      *
      * Outputs:
      * * 0: The output tensor, of shape specified by the input shape.
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     RESHAPE = 22,
 
@@ -1220,9 +1218,10 @@
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT32}
      *
-     * Supported tensor rank: 4, with "NHWC" data layout.
+     * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+     * and Channels) data layout.
      *
-     * Inputs:
+     * Inputs (resizing by shape):
      * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
      *      the input.
      * * 1: An {@link OperandType::INT32} scalar, specifying the output
@@ -1233,8 +1232,6 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, new_height, new_width, depth].
-     *
-     * Available since API level 27.
      */
     RESIZE_BILINEAR = 23,
 
@@ -1257,25 +1254,23 @@
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT32}
      *
+     * The input tensors must all be the same type.
+     *
      * Inputs:
      * * 0: input.
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32} of shape
-     *      [batch_size, input_size], where “batch_size” corresponds to the
-     *      batching dimension, and “input_size” is the size of the input.
+     *      A 2-D tensor of shape [batch_size, input_size], where “batch_size”
+     *      corresponds to the batching dimension, and “input_size” is the size
+     *      of the input.
      * * 1: weights.
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units, input_size], where “num_units” corresponds to the
-     *      number of units.
+     *      A 2-D tensor of shape [num_units, input_size], where “num_units”
+     *      corresponds to the number of units.
      * * 2: recurrent_weights.
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units, num_units], with columns corresponding to the weights
-     *      from each unit.
+     *      A 2-D tensor of shape [num_units, num_units], with columns
+     *      corresponding to the weights from each unit.
      * * 3: bias.
-     *      A 1-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units].
+     *      A 1-D tensor of shape [num_units].
      * * 4: hidden state (in).
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [batch_size, num_units].
+     *      A 2-D tensor of shape [batch_size, num_units].
      * * 5: fused_activation_function.
      *      An optional {@link FusedActivationFunc} value indicating the
      *      activation function. If “NONE” is specified then it results in a
@@ -1283,15 +1278,11 @@
      *
      * Outputs:
      * * 0: hidden state (out).
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [batch_size, num_units].
+     *      A 2-D tensor of shape [batch_size, num_units].
      *
      * * 1: output.
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [batch_size, num_units]. This is effectively the same as the
-     *      current state value.
-     *
-     * Available since API level 27.
+     *      A 2-D tensor of shape [batch_size, num_units]. This is effectively
+     *      the same as the current state value.
      */
     RNN = 24,
 
@@ -1306,6 +1297,9 @@
      *         exp((input[batch, i] - max(input[batch, :])) * beta) /
      *         sum_{k}{exp((input[batch, k] - max(input[batch, :])) * beta)}
      *
+     * For input tensor with rank other than 2, the activation will be applied
+     * independently on each 1-D slice along specified dimension.
+     *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
@@ -1314,15 +1308,15 @@
      *
      * Inputs:
      * * 0: A 2-D or 4-D tensor, specifying the tensor to be reshaped.
-     * * 1: An {@link OperandType::FLOAT32} scalar, specifying the positive
-     *      scaling factor for the exponent, beta.
+     * * 1: A scalar, specifying the positive scaling factor for the exponent,
+     *      beta. If input0 is of {@link OperandType::TENSOR_FLOAT32} or
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM}, the scalar must be of
+     *      {@link OperandType::FLOAT32}.
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
      *      For {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the scale must be 1.f / 256 and the zeroPoint must be 0.
-     *
-     * Available since API level 27.
      */
     SOFTMAX = 25,
 
@@ -1344,7 +1338,8 @@
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
-     * Supported tensor rank: 4, with "NHWC" data layout.
+     * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+     * and Channels) data layout.
      *
      * Inputs:
      * * 0: A 4-D tensor, of shape [batches, height, width, depth_in],
@@ -1356,8 +1351,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape [batches, height/block_size,
      *      width/block_size, depth_in*block_size*block_size].
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     SPACE_TO_DEPTH = 26,
 
@@ -1403,25 +1398,23 @@
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT32}
      *
+     * All input tensors must be the same type.
+     *
      * Inputs:
      * * 0: input.
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [batch_size, input_size], where “batch_size” corresponds to the
-     *      batching dimension, and “input_size” is the size of the input.
+     *      A 2-D tensor of shape [batch_size, input_size], where “batch_size”
+     *      corresponds to the batching dimension, and “input_size” is the size
+     *      of the input.
      * * 1: weights_feature.
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units, input_size], where “num_units” corresponds to the
-     *      number of units.
+     *      A 2-D tensor of shape [num_units, input_size], where “num_units”
+     *      corresponds to the number of units.
      * * 2: weights_time.
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [num_units, memory_size], where “memory_size” corresponds to the
-     *      fixed-size of the memory.
+     *      A 2-D tensor of shape [num_units, memory_size], where “memory_size”
+     *      corresponds to the fixed-size of the memory.
      * * 3: bias.
-     *      An optional 1-D tensor of {@link OperandType::TENSOR_FLOAT32},
-     *      of shape [num_units].
+     *      An optional 1-D tensor of shape [num_units].
      * * 4: state (in).
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-     *      [batch_size, (memory_size - 1) * num_units * rank].
+     *      A 2-D tensor of shape [batch_size, (memory_size - 1) * num_units * rank].
      * * 5: rank.
      *      The rank of the SVD approximation.
      * * 6: fused_activation_function.
@@ -1431,13 +1424,11 @@
      *
      * Outputs:
      * * 0: state (out).
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
+     *      A 2-D tensor of the same {@link OperandType} as the inputs, with shape
      *      [batch_size, (memory_size - 1) * num_units * rank].
      * * 1: output.
-     *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
+     *      A 2-D tensor of the same {@link OperandType} as the inputs, with shape
      *      [batch_size, num_units].
-     *
-     * Available since API level 27.
      */
     SVDF = 27,
 
@@ -1458,8 +1449,6 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
-     *
-     * Available since API level 27.
      */
     TANH = 28,
 
diff --git a/neuralnetworks/1.0/types.t b/neuralnetworks/1.0/types.t
new file mode 100644
index 0000000..d7b26aa
--- /dev/null
+++ b/neuralnetworks/1.0/types.t
@@ -0,0 +1,431 @@
+%% template file for generating types.hal.
+%% see frameworks/ml/nn/tools/api/README.md.
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.neuralnetworks@1.0;
+
+%insert Operand_1.0_Comment
+enum OperandType : int32_t {
+%insert Operand_1.0
+
+    /**
+     * DEPRECATED. Since HAL version 1.2, extensions are the preferred
+     * alternative to OEM operation and data types.
+     *
+     * OEM specific scalar value.
+     */
+    OEM                 = 10000,
+
+    /**
+     * DEPRECATED. Since HAL version 1.2, extensions are the preferred
+     * alternative to OEM operation and data types.
+     *
+     * A tensor of OEM specific values.
+     */
+    TENSOR_OEM_BYTE     = 10001,
+};
+
+%insert Operation_1.0_Comment
+enum OperationType : int32_t {
+%insert Operation_1.0
+
+    /**
+     * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to
+     * OEM operation and data types.
+     *
+     * This operation is OEM specific. It should only be used for OEM
+     * applications.
+     */
+    OEM_OPERATION = 10000,
+};
+
+/**
+ * Fused activation function types.
+ */
+enum FusedActivationFunc : int32_t {
+    NONE  = 0,
+    RELU  = 1,
+    RELU1 = 2,
+    RELU6 = 3,
+};
+
+/**
+ * How an operand is used.
+ */
+enum OperandLifeTime : int32_t {
+    /**
+     * The operand is internal to the model. It's created by an operation and
+     * consumed by other operations. It must be an output operand of
+     * exactly one operation.
+     */
+    TEMPORARY_VARIABLE,
+
+    /**
+     * The operand is an input of the model. It must not be an output
+     * operand of any operation.
+     *
+     * An operand can't be both input and output of a model.
+     */
+    MODEL_INPUT,
+
+    /**
+     * The operand is an output of the model. It must be an output
+     * operand of exactly one operation.
+     *
+     * An operand can't be both input and output of a model.
+     */
+    MODEL_OUTPUT,
+
+    /**
+     * The operand is a constant found in Model.operandValues. It must
+     * not be an output operand of any operation.
+     */
+    CONSTANT_COPY,
+
+    /**
+     * The operand is a constant that was specified via a Memory
+     * object. It must not be an output operand of any operation.
+     */
+    CONSTANT_REFERENCE,
+
+    /**
+     * The operand does not have a value. This is valid only for optional
+     * arguments of operations.
+     */
+    NO_VALUE,
+};
+
+/**
+ * Status of a device.
+ */
+enum DeviceStatus : int32_t {
+    AVAILABLE,
+    BUSY,
+    OFFLINE,
+    UNKNOWN,
+};
+
+/**
+ * Performance information for the reference workload.
+ *
+ * Used by a driver to report its performance characteristics.
+ */
+struct PerformanceInfo {
+    /**
+     * Ratio of the time taken by the driver to execute the
+     * workload compared to the time the CPU would take for the
+     * same workload. A lower number is better.
+     */
+    float execTime;
+
+    /**
+     * Ratio of the energy used by the driver compared to what
+     * the CPU would use for doing the same workload. A lower number
+     * is better.
+     */
+    float powerUsage;
+};
+
+/**
+ * The capabilities of a driver.
+ */
+struct Capabilities {
+    /**
+     * Driver performance when operating on float32 data.
+     */
+    PerformanceInfo float32Performance;
+
+    /**
+     * Driver performance when operating on asymmetric 8-bit quantized data.
+     */
+    PerformanceInfo quantized8Performance;
+};
+
+/**
+ * Describes the location of a data object.
+ */
+struct DataLocation {
+    /**
+     * The index of the memory pool where this location is found.
+     */
+    uint32_t poolIndex;
+
+    /**
+     * Offset in bytes from the start of the pool.
+     */
+    uint32_t offset;
+
+    /**
+     * The length of the data in bytes.
+     */
+    uint32_t length;
+};
+
+/**
+ * Describes one operand of the model's graph.
+ */
+struct Operand {
+    /**
+     * Data type of the operand.
+     */
+    OperandType type;
+
+    /**
+     * Dimensions of the operand.
+     *
+     * For a scalar operand, dimensions.size() must be 0.
+     *
+     * For a tensor operand, dimensions.size() must be at least 1;
+     * however, any of the dimensions may be unspecified.
+     *
+     * A tensor operand with all dimensions specified has "fully
+     * specified" dimensions. Whenever possible (i.e., whenever the
+     * dimensions are known at model construction time), a tensor
+     * operand should have (but is not required to have) fully
+     * specified dimensions, in order to enable the best possible
+     * performance.
+     *
+     * If a tensor operand's dimensions are not fully specified, the
+     * dimensions of the operand are deduced from the operand
+     * dimensions and values of the operation for which that operand
+     * is an output.
+     *
+     * In the following situations, a tensor operand's dimensions must
+     * be fully specified:
+     *
+     *     . The operand has lifetime CONSTANT_COPY or
+     *       CONSTANT_REFERENCE.
+     *
+     *     . The operand has lifetime MODEL_INPUT or MODEL_OUTPUT. Fully
+     *       specified dimensions must either be present in the
+     *       Operand or they must be provided in the corresponding
+     *       RequestArgument.
+     *       EXCEPTION: If the input or output is optional and omitted
+     *       (by setting the hasNoValue field of the corresponding
+     *       RequestArgument to true) then it need not have fully
+     *       specified dimensions.
+     *
+     * A tensor operand with some number of unspecified dimensions is
+     * represented by setting each unspecified dimension to 0.
+     */
+    vec<uint32_t> dimensions;
+
+    /**
+     * The number of times this operand appears as an operation input.
+     *
+     * (For example, if this operand appears once in one operation's
+     * input list, and three times in another operation's input list,
+     * then numberOfConsumers = 4.)
+     */
+    uint32_t numberOfConsumers;
+
+    /**
+     * Quantized scale of the operand.
+     *
+     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM or
+     * TENSOR_INT32.
+     */
+    float scale;
+
+    /**
+     * Quantized zero-point offset of the operand.
+     *
+     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
+     */
+    int32_t zeroPoint;
+
+    /**
+     * How the operand is used.
+     */
+    OperandLifeTime lifetime;
+
+    /**
+     * Where to find the data for this operand.
+     * If the lifetime is TEMPORARY_VARIABLE, MODEL_INPUT, MODEL_OUTPUT, or
+     * NO_VALUE:
+     * - All the fields must be 0.
+     * If the lifetime is CONSTANT_COPY:
+     * - location.poolIndex is 0.
+     * - location.offset is the offset in bytes into Model.operandValues.
+     * - location.length is set.
+     * If the lifetime is CONSTANT_REFERENCE:
+     * - location.poolIndex is set.
+     * - location.offset is the offset in bytes into the specified pool.
+     * - location.length is set.
+     */
+    DataLocation location;
+};
+
+/**
+ * Describes one operation of the model's graph.
+ */
+struct Operation {
+    /**
+     * The operation type.
+     */
+    OperationType type;
+
+    /**
+     * Describes the table that contains the indexes of the inputs of the
+     * operation. The offset is the index in the operandIndexes table.
+     */
+    vec<uint32_t> inputs;
+
+    /**
+     * Describes the table that contains the indexes of the outputs of the
+     * operation. The offset is the index in the operandIndexes table.
+     */
+    vec<uint32_t> outputs;
+};
+
+/**
+ * A Neural Network Model.
+ *
+ * This includes not only the execution graph, but also constant data such as
+ * weights or scalars added at construction time. The only information that
+ * might not be known is the shape of the input tensors.
+ */
+struct Model {
+    /**
+     * All operands included in the model.
+     */
+    vec<Operand> operands;
+
+    /**
+     * All operations included in the model.
+     *
+     * The operations are sorted into execution order. Every operand
+     * with lifetime MODEL_OUTPUT or TEMPORARY_VARIABLE must be
+     * written before it is read.
+     */
+    vec<Operation> operations;
+
+    /**
+     * Input indexes of the model. There must be at least one.
+     *
+     * Each value corresponds to the index of the operand in "operands".
+     */
+    vec<uint32_t> inputIndexes;
+
+    /**
+     * Output indexes of the model. There must be at least one.
+     *
+     * Each value corresponds to the index of the operand in "operands".
+     */
+    vec<uint32_t> outputIndexes;
+
+    /**
+     * A byte buffer containing operand data that were copied into the model.
+     *
+     * An operand's value must be located here if and only if Operand::lifetime
+     * equals OperandLifeTime::CONSTANT_COPY.
+     */
+    vec<uint8_t> operandValues;
+
+    /**
+     * A collection of shared memory pools containing operand values.
+     *
+     * An operand's value must be located here if and only if Operand::lifetime
+     * equals OperandLifeTime::CONSTANT_REFERENCE.
+     */
+    vec<memory> pools;
+};
+
+/**
+ * Metadata information specifying the location of the input or output data and
+ * any updates to the input or output operand.
+ */
+struct RequestArgument {
+    /**
+     * If true, the argument does not have a value. This can be used for
+     * operations that take optional arguments. If true, the fields of location
+     * are set to 0 and the dimensions vector is left empty.
+     */
+    bool hasNoValue;
+
+    /**
+     * The location within one of the memory pools passed in the Request.
+     */
+    DataLocation location;
+
+    /**
+     * Updated dimension information.
+     *
+     * If dimensions.size() > 0, dimension information was provided
+     * along with the argument. This can be the case for models that
+     * accept inputs of varying size. This can't change the rank, just
+     * the value of the dimensions that were unspecified in the
+     * model. If dimensions.size() > 0, then all dimensions must be
+     * specified here; and any dimension that was specified in the
+     * model must have the same value here.
+     *
+     * If the dimensions in the model are not fully specified, then
+     * they must be fully specified here, unless hasNoValue is set to
+     * true. If the dimensions in the model are fully specified, then
+     * either dimensions.size() may be 0, or the dimensions in the
+     * model must be identical to the dimensions here.
+     */
+    vec<uint32_t> dimensions;
+};
+
+/**
+ * Inputs to be sent to and outputs to be retrieved from a prepared model.
+ *
+ * A Request serves two primary tasks:
+ * 1) Provides the input and output data to be used when executing the model.
+ * 2) Specifies any updates to the input operand metadata that were left
+ *    unspecified at model preparation time.
+ *
+ * An output must not overlap with any other output, with an input, or
+ * with an operand of lifetime CONSTANT_REFERENCE.
+ */
+struct Request {
+    /**
+     * Input data and information to be used in the execution of a prepared
+     * model.
+     *
+     * The index of the input corresponds to the index in Model.inputIndexes.
+     *   E.g., input[i] corresponds to Model.inputIndexes[i].
+     */
+    vec<RequestArgument> inputs;
+
+    /**
+     * Output data and information to be used in the execution of a prepared
+     * model.
+     *
+     * The index of the output corresponds to the index in Model.outputIndexes.
+     *   E.g., output[i] corresponds to Model.outputIndexes[i].
+     */
+    vec<RequestArgument> outputs;
+
+    /**
+     * A collection of shared memory pools containing operand data for both the
+     * inputs and the outputs to a model.
+     */
+    vec<memory> pools;
+};
+
+/**
+ * Return status of a function.
+ */
+enum ErrorStatus : int32_t {
+    NONE,
+    DEVICE_UNAVAILABLE,
+    GENERAL_FAILURE,
+    OUTPUT_INSUFFICIENT_SIZE,
+    INVALID_ARGUMENT,
+};
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index 9057695..3e9d5f7 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -15,91 +15,61 @@
 //
 
 cc_library_static {
-    name: "VtsHalNeuralnetworksTest_utils",
+    name: "VtsHalNeuralNetworksV1_0_utils",
     srcs: [
         "Callbacks.cpp",
-        "GeneratedTestHarness.cpp",
+        "Utils.cpp",
     ],
     defaults: ["VtsHalTargetTestDefaults"],
-    export_include_dirs: ["."],
+    export_include_dirs: ["include"],
     shared_libs: [
         "libfmq",
         "libnativewindow",
     ],
     static_libs: [
         "android.hardware.neuralnetworks@1.0",
-        "android.hardware.neuralnetworks@1.1",
-        "android.hardware.neuralnetworks@1.2",
         "android.hidl.allocator@1.0",
         "android.hidl.memory@1.0",
         "libgmock",
         "libhidlmemory",
+        "libneuralnetworks_generated_test_harness",
         "libneuralnetworks_utils",
     ],
     header_libs: [
         "libneuralnetworks_headers",
-        "libneuralnetworks_generated_test_harness_headers",
-        "libneuralnetworks_generated_tests",
     ],
 }
 
-cc_defaults {
-    name: "VtsHalNeuralNetworksTargetTestDefaults",
-    defaults: ["VtsHalTargetTestDefaults"],
-    srcs: [
-        "ValidateModel.cpp",
-        "ValidateRequest.cpp",
-        "VtsHalNeuralnetworks.cpp",
-    ],
-    shared_libs: [
-        "libfmq",
-        "libnativewindow",
-    ],
-    static_libs: [
-        "android.hardware.neuralnetworks@1.0",
-        "android.hardware.neuralnetworks@1.1",
-        "android.hardware.neuralnetworks@1.2",
-        "android.hidl.allocator@1.0",
-        "android.hidl.memory@1.0",
-        "libgmock",
-        "libhidlmemory",
-        "libneuralnetworks_utils",
-        "VtsHalNeuralnetworksTest_utils",
-    ],
-    header_libs: [
-        "libneuralnetworks_headers",
-        "libneuralnetworks_generated_test_harness_headers",
-        "libneuralnetworks_generated_tests",
-    ],
-    // Bug: http://b/74200014 - Disable arm32 asan since it triggers internal
-    // error in ld.gold.
-    arch: {
-        arm: {
-            sanitize: {
-                never: true,
-            },
-        },
-    },
-    test_suites: ["general-tests"],
-}
-
 cc_test {
     name: "VtsHalNeuralnetworksV1_0TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "BasicTests.cpp",
-        "GeneratedTests.cpp",
+        "TestAssertions.cpp",
+        "ValidateModel.cpp",
+        "ValidateRequest.cpp",
+        "VtsHalNeuralnetworks.cpp",
+        "GeneratedTestHarness.cpp",
     ],
-}
-
-cc_test {
-    name: "PresubmitHalNeuralnetworksV1_0TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
-    srcs: [
-        "BasicTests.cpp",
-        "GeneratedTests.cpp",
+    shared_libs: [
+        "libfmq",
+        "libnativewindow",
     ],
-    cflags: [
-        "-DPRESUBMIT_NOT_VTS",
+    static_libs: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libgmock",
+        "libhidlmemory",
+        "libneuralnetworks_generated_test_harness",
+        "libneuralnetworks_utils",
+        "VtsHalNeuralNetworksV1_0_utils",
     ],
+    whole_static_libs: [
+        "neuralnetworks_generated_V1_0_example",
+    ],
+    header_libs: [
+        "libneuralnetworks_headers",
+    ],
+    test_suites: ["general-tests"],
 }
diff --git a/neuralnetworks/1.0/vts/functional/BasicTests.cpp b/neuralnetworks/1.0/vts/functional/BasicTests.cpp
index 945c406..cc44c9e 100644
--- a/neuralnetworks/1.0/vts/functional/BasicTests.cpp
+++ b/neuralnetworks/1.0/vts/functional/BasicTests.cpp
@@ -18,39 +18,29 @@
 
 #include "VtsHalNeuralnetworks.h"
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
+namespace android::hardware::neuralnetworks::V1_0::vts::functional {
 
 // create device test
-TEST_F(NeuralnetworksHidlTest, CreateDevice) {}
+TEST_P(NeuralnetworksHidlTest, CreateDevice) {}
 
 // status test
-TEST_F(NeuralnetworksHidlTest, StatusTest) {
-    Return<DeviceStatus> status = device->getStatus();
+TEST_P(NeuralnetworksHidlTest, StatusTest) {
+    Return<DeviceStatus> status = kDevice->getStatus();
     ASSERT_TRUE(status.isOk());
     EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status));
 }
 
 // initialization
-TEST_F(NeuralnetworksHidlTest, GetCapabilitiesTest) {
+TEST_P(NeuralnetworksHidlTest, GetCapabilitiesTest) {
     Return<void> ret =
-        device->getCapabilities([](ErrorStatus status, const Capabilities& capabilities) {
-            EXPECT_EQ(ErrorStatus::NONE, status);
-            EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
-            EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
-            EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
-            EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
-        });
+            kDevice->getCapabilities([](ErrorStatus status, const Capabilities& capabilities) {
+                EXPECT_EQ(ErrorStatus::NONE, status);
+                EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
+                EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
+                EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
+                EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
+            });
     EXPECT_TRUE(ret.isOk());
 }
 
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_0
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::neuralnetworks::V1_0::vts::functional
diff --git a/neuralnetworks/1.0/vts/functional/Callbacks.cpp b/neuralnetworks/1.0/vts/functional/Callbacks.cpp
index c30702c..37afcf0 100644
--- a/neuralnetworks/1.0/vts/functional/Callbacks.cpp
+++ b/neuralnetworks/1.0/vts/functional/Callbacks.cpp
@@ -14,160 +14,78 @@
  * limitations under the License.
  */
 
-#include "Callbacks.h"
+#define LOG_TAG "Callbacks"
+
+#include "1.0/Callbacks.h"
+
 #include <android-base/logging.h>
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace implementation {
+namespace android::hardware::neuralnetworks::V1_0::implementation {
 
-CallbackBase::CallbackBase() : mNotified(false) {}
-
-CallbackBase::~CallbackBase() {
-    // Note that we cannot call CallbackBase::join_thread from here:
-    // CallbackBase is intended to be reference counted, and it is possible that
-    // the reference count drops to zero in the bound thread, causing the
-    // bound thread to call this destructor. If a thread tries to join
-    // itself, it throws an exception, producing a message like the
-    // following:
-    //
-    //     terminating with uncaught exception of type std::__1::system_error:
-    //     thread::join failed: Resource deadlock would occur
-}
-
-void CallbackBase::wait() {
-    std::unique_lock<std::mutex> lock(mMutex);
-    mCondition.wait(lock, [this]{return mNotified;});
-    join_thread_locked();
-}
-
-bool CallbackBase::on_finish(std::function<bool(void)> post_work) {
-    std::lock_guard<std::mutex> lock(mMutex);
-    if (mPostWork != nullptr) {
-        LOG(ERROR) << "CallbackBase::on_finish -- a post-work function has already been bound to "
-                   "this callback object";
-        return false;
-    }
-    if (post_work == nullptr) {
-        LOG(ERROR) << "CallbackBase::on_finish -- the new post-work function is invalid";
-        return false;
-    }
-    mPostWork = std::move(post_work);
-    return true;
-}
-
-bool CallbackBase::bind_thread(std::thread&& asyncThread) {
-    std::lock_guard<std::mutex> lock(mMutex);
-    if (mThread.joinable()) {
-        LOG(ERROR) << "CallbackBase::bind_thread -- a thread has already been bound to this "
-                   "callback object";
-        return false;
-    }
-    if (!asyncThread.joinable()) {
-        LOG(ERROR) << "CallbackBase::bind_thread -- the new thread is not joinable";
-        return false;
-    }
-    mThread = std::move(asyncThread);
-    return true;
-}
-
-void CallbackBase::join_thread() {
-    std::lock_guard<std::mutex> lock(mMutex);
-    join_thread_locked();
-}
-
-void CallbackBase::notify() {
-    {
-        std::lock_guard<std::mutex> lock(mMutex);
-        mNotified = true;
-        if (mPostWork != nullptr) {
-            bool success = mPostWork();
-            if (!success) {
-                LOG(ERROR) << "CallbackBase::notify -- post work failed";
-            }
-        }
-    }
-    mCondition.notify_all();
-}
-
-void CallbackBase::join_thread_locked() {
-    if (mThread.joinable()) {
-        mThread.join();
-    }
-}
-
-PreparedModelCallback::PreparedModelCallback() :
-        mErrorStatus(ErrorStatus::GENERAL_FAILURE), mPreparedModel(nullptr) {}
-
-PreparedModelCallback::~PreparedModelCallback() {}
+// PreparedModelCallback methods begin here
 
 Return<void> PreparedModelCallback::notify(ErrorStatus errorStatus,
-                                           const sp<V1_0::IPreparedModel>& preparedModel) {
-    mErrorStatus = errorStatus;
-    mPreparedModel = preparedModel;
-    CallbackBase::notify();
+                                           const sp<IPreparedModel>& preparedModel) {
+    {
+        std::lock_guard<std::mutex> hold(mMutex);
+
+        // quick-return if object has already been notified
+        if (mNotified) {
+            return Void();
+        }
+
+        // store results and mark as notified
+        mErrorStatus = errorStatus;
+        mPreparedModel = preparedModel;
+        mNotified = true;
+    }
+
+    mCondition.notify_all();
     return Void();
 }
 
-Return<void> PreparedModelCallback::notify_1_2(ErrorStatus errorStatus,
-                                               const sp<V1_2::IPreparedModel>& preparedModel) {
-    mErrorStatus = errorStatus;
-    mPreparedModel = preparedModel;
-    CallbackBase::notify();
-    return Void();
+void PreparedModelCallback::wait() const {
+    std::unique_lock<std::mutex> lock(mMutex);
+    mCondition.wait(lock, [this] { return mNotified; });
 }
 
-ErrorStatus PreparedModelCallback::getStatus() {
+ErrorStatus PreparedModelCallback::getStatus() const {
     wait();
     return mErrorStatus;
 }
 
-sp<V1_0::IPreparedModel> PreparedModelCallback::getPreparedModel() {
+sp<IPreparedModel> PreparedModelCallback::getPreparedModel() const {
     wait();
     return mPreparedModel;
 }
 
-ExecutionCallback::ExecutionCallback() : mErrorStatus(ErrorStatus::GENERAL_FAILURE) {}
-
-ExecutionCallback::~ExecutionCallback() {}
+// ExecutionCallback methods begin here
 
 Return<void> ExecutionCallback::notify(ErrorStatus errorStatus) {
-    mErrorStatus = errorStatus;
-    mOutputShapes = {};
-    mTiming = {.timeOnDevice = UINT64_MAX, .timeInDriver = UINT64_MAX};
-    CallbackBase::notify();
+    {
+        std::lock_guard<std::mutex> hold(mMutex);
+
+        // quick-return if object has already been notified
+        if (mNotified) {
+            return Void();
+        }
+
+        mErrorStatus = errorStatus;
+        mNotified = true;
+    }
+    mCondition.notify_all();
+
     return Void();
 }
 
-Return<void> ExecutionCallback::notify_1_2(ErrorStatus errorStatus,
-                                           const hidl_vec<OutputShape>& outputShapes,
-                                           const Timing& timing) {
-    mErrorStatus = errorStatus;
-    mOutputShapes = outputShapes;
-    mTiming = timing;
-    CallbackBase::notify();
-    return Void();
+void ExecutionCallback::wait() const {
+    std::unique_lock<std::mutex> lock(mMutex);
+    mCondition.wait(lock, [this] { return mNotified; });
 }
 
-ErrorStatus ExecutionCallback::getStatus() {
+ErrorStatus ExecutionCallback::getStatus() const {
     wait();
     return mErrorStatus;
 }
 
-const std::vector<OutputShape>& ExecutionCallback::getOutputShapes() {
-    wait();
-    return mOutputShapes;
-}
-
-Timing ExecutionCallback::getTiming() {
-    wait();
-    return mTiming;
-}
-
-}  // namespace implementation
-}  // namespace V1_2
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::neuralnetworks::V1_0::implementation
diff --git a/neuralnetworks/1.0/vts/functional/Callbacks.h b/neuralnetworks/1.0/vts/functional/Callbacks.h
deleted file mode 100644
index 4707d0a..0000000
--- a/neuralnetworks/1.0/vts/functional/Callbacks.h
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_0_CALLBACKS_H
-#define ANDROID_HARDWARE_NEURALNETWORKS_V1_0_CALLBACKS_H
-
-#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
-#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
-#include <hidl/MQDescriptor.h>
-#include <hidl/Status.h>
-#include <chrono>
-#include <condition_variable>
-#include <functional>
-#include <mutex>
-#include <thread>
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace implementation {
-
-using V1_0::ErrorStatus;
-
-/**
- * The CallbackBase class is used internally by the NeuralNetworks runtime to
- * synchronize between different threads. An asynchronous task is launched
- * paired with a callback object. When a client thread requires the output being
- * generated by the asynchronous task, the client thread can wait for the result
- * and be blocked until it has completed or a timeout condition has been
- * reached. Any wait* may safely be called concurrently, even on the same
- * callback object. When the asynchronous task has finished its workload, it
- * must immediately call "notify". If the asynchronous task has failed to launch,
- * the function that tried to launch the asynchronous task must immediately call
- * "notify". This "notify" call awakens any client threads waiting on the
- * callback object.
- *
- * The CallbackBase class implements some of the base synchronization common to
- * both PrepareModelCallback and ExecutionCallback. For consistency, any HIDL
- * callback class must inherit from CallbackBase as well as the HIDL callback
- * interface it implements.
- *
- * This class exists to enable synchronization across HIDL. When synchronization
- * is only required in the same process, consider using std::future, std::mutex,
- * std::condition_variable, or std::experimental::latch instead.
- */
-class CallbackBase {
- public:
-    CallbackBase();
-    ~CallbackBase();
-
-    /**
-     * CallbackBase::wait blocks until notify has been called on the callback
-     * object.
-     */
-    void wait();
-
-    /**
-     * CallbackBase::wait_for blocks until notify has been called on the
-     * callback object or the time duration from the time the wait_for function
-     * was called has expired, whichever comes first.
-     *
-     * @return Status std::cv_status::no_timeout if the callback was notified
-     *                before the time duration expired, std::cv_status::timeout
-     *                otherwise.
-     */
-    template<class Rep, class Period>
-    std::cv_status wait_for(const std::chrono::duration<Rep,Period>& timeout_duration);
-
-    /**
-     * CallbackBase::on_finish binds a function to the callback object. This
-     * bound function will be executed when CallbackBase::notify is called,
-     * before any calls to wait* return. (Note that CallbackBase::wait_for can
-     * return std::cv_status::timeout before CallbackBase::notify is called for
-     * the first time, and hence before the bound function is executed.)
-     *
-     * The bound function must not synchronize with or otherwise access the
-     * callback object it is bound to, as this could cause a deadlock.
-     *
-     * CallbackBase::on_finish can be called at most once on a given callback
-     * object, and the call to CallbackBase::on_finish must finish before
-     * CallbackBase::notify is called.
-     *
-     * @param post_work Function to be invoked the first time
-     *                  CallbackBase::notify is called. Must have a target --
-     *                  i.e., must not compare equal to nullptr. post_work
-     *                  returns true if it successfully completes, false if it
-     *                  fails.
-     * @return bool True if the function was successfully bound, false if
-     *              unsuccessful.
-     *
-     * TODO: Why does the return value of the callback matter?
-     */
-    bool on_finish(std::function<bool(void)> post_work);
-
-    /**
-     * CallbackBase::bind_thread binds a thread to the event for later use by
-     * CallbackBase::join_thread.
-     *
-     * The thread must be passed using std::move.
-     *
-     * Once a thread is bound with CallbackBase::bind_thread, the client code
-     * should ensure that one of the following occurs before the event is
-     * destroyed:
-     * - CallbackBase::join_thread has been called.
-     * - CallbackBase::wait has been called.
-     * - CallbackBase::wait_for has been called and returned other than
-     *   std::cv_status::no_timeout.
-     *
-     * The bound thread shall not call any CallbackBase method with the
-     * exception of CallbackBase::notify, which it must call when the thread has
-     * finished its computation.
-     *
-     * CallbackBase::bind_thread can be called at most once on a given callback
-     * object.
-     *
-     * @param asyncThread Thread to be bound to the callback object. The thread
-     *                    object must represent a thread of execution -- i.e.,
-     *                    asyncThread.joinable() must be true.
-     * @return bool True if successful, false if thread was not properly bound.
-     */
-    bool bind_thread(std::thread&& asyncThread);
-
-    /**
-     * CallbackBase::join_thread ensures that the thread (if any) bound to this
-     * event with CallbackBase::bind_thread has fully finished and cleaned its
-     * resources. It is legal to call this function multiple times, concurrently
-     * or sequentially.
-     */
-    void join_thread();
-
- protected:
-    /**
-     * CallbackBase::notify enables all prior and future wait* calls on the
-     * callback object to proceed. The call to CallbackBase::notify happens
-     * before any wait* calls on this callback object return (except in the case
-     * of wait_for timing out). The asynchronous call the callback object is
-     * paired with must ensure that any update to state that should be visible
-     * to the caller of wait* happens before the call to CallbackBase::notify.
-     *
-     * CallbackBase::notify must be called exactly once on a given callback
-     * object.
-     */
-    void notify();
-
- private:
-    // Same as CallbackBase::join_thread but assumes we already hold a lock on
-    // mMutex.
-    void join_thread_locked();
-
-    bool                      mNotified;
-    std::mutex                mMutex;
-    std::condition_variable   mCondition;
-    std::function<bool(void)> mPostWork;
-    std::thread               mThread;
-};
-
-/**
- * The PreparedModelCallback class is used to receive the error status of
- * preparing a model as well as the prepared model from a task executing
- * asynchronously with respect to the runtime. If a calling thread calls wait*
- * or get* on a PreparedModelCallback object and the corresponding asynchronous
- * task has not finished preparing the model, the calling thread will block
- * until the asynchronous task has either called notify or notify_1_2. For more
- * information on the synchronization behavior, refer to the CallbackBase class.
- *
- * This class inherits the basic blocking and signaling calls from
- * CallbackBase, and implements the HIDL notify and notify_1_2 calls from
- * IPreparedModelCallback. This callback object is passed as an argument to
- * IDevice::prepareModel.
- */
-class PreparedModelCallback : public CallbackBase, public IPreparedModelCallback {
- public:
-    PreparedModelCallback();
-    ~PreparedModelCallback() override;
-
-    /**
-     * IPreparedModelCallback::notify and IPreparedModelCallback::notify_1_2
-     * mark the callback object with the return status of the asynchronous
-     * model preparation along with the prepared model, and call
-     * CallbackBase::notify, enabling all prior and future wait* calls on the
-     * PreparedModelCallback object to proceed. For more information on the
-     * synchronization behavior, refer to the CallbackBase class.
-     *
-     * Either IPreparedModelCallback::notify or IPreparedModelCallback::notify_1_2
-     * must be called exactly once on a given PreparedModelCallback object.
-     *
-     * @param status Error status returned from asynchronously preparing the
-     *               model; will be:
-     *               - NONE if the asynchronous preparation was successful
-     *               - DEVICE_UNAVAILABLE if driver is offline or busy
-     *               - GENERAL_FAILURE if there is an unspecified error
-     *               - INVALID_ARGUMENT if the input model is invalid
-     * @param preparedModel Returned model that has been prepared for execution,
-     *                      nullptr if the model was unable to be prepared.
-     */
-    Return<void> notify(ErrorStatus status, const sp<V1_0::IPreparedModel>& preparedModel) override;
-    Return<void> notify_1_2(ErrorStatus status,
-                            const sp<V1_2::IPreparedModel>& preparedModel) override;
-
-    /**
-     * Retrieves the error status returned from the asynchronous task launched
-     * by IDevice::prepareModel. If IDevice::prepareModel has not finished
-     * asynchronously preparing the model, this call will block until the
-     * asynchronous task notifies the object.
-     *
-     * @return status Error status returned from asynchronously preparing the
-     *                model; will be:
-     *                - NONE if the asynchronous preparation was successful
-     *                - DEVICE_UNAVAILABLE if driver is offline or busy
-     *                - GENERAL_FAILURE if there is an unspecified error
-     *                - INVALID_ARGUMENT if the input model is invalid
-     */
-    ErrorStatus getStatus();
-
-    /**
-     * Retrieves the model that has been prepared for execution from the
-     * asynchronous task launched by IDevice::prepareModel. If
-     * IDevice::prepareModel has not finished asynchronously preparing the
-     * model, this call will block until the asynchronous task notifies the
-     * object.
-     *
-     * @return preparedModel Returned model that has been prepared for
-     *                       execution, nullptr if the model was unable to be
-     *                       prepared.
-     */
-    sp<V1_0::IPreparedModel> getPreparedModel();
-
-   private:
-    ErrorStatus        mErrorStatus;
-    sp<V1_0::IPreparedModel> mPreparedModel;
-};
-
-/**
- * The ExecutionCallback class is used to receive the error status of the
- * execution from a task executing asynchronously with respect to the runtime.
- * If a calling thread calls wait* or get* on a PreparedModelCallback object and
- * the corresponding asynchronous task has not finished the execution, the
- * calling thread will block until the asynchronous task has either called notify
- * or notify_1_2. For more information on the synchronization behavior, refer to
- * the CallbackBase class.
- *
- * This class inherits the basic blocking and signaling calls from
- * CallbackBase, and implements the HIDL notify and notify_1_2 calls from
- * IExecutionCallback. This callback object is passed as an argument to
- * IPreparedModel::execute.
- */
-class ExecutionCallback : public CallbackBase,  public IExecutionCallback {
- public:
-    ExecutionCallback();
-    ~ExecutionCallback() override;
-
-    /**
-     * IExecutionCallback::notify and IExecutionCallback::notify_1_2 mark the
-     * callback object with the return status of the asynchronous execution that
-     * held this callback and enable all prior and future wait* calls on the
-     * ExecutionCallback object to proceed. For more information on the
-     * synchronization behavior, refer to the CallbackBase class.
-     *
-     * Either IExecutionCallback::notify or IExecutionCallback::notify_1_2 must
-     * be called exactly once on a given ExecutionCallback object.
-     *
-     * @param status Error status returned from launching the asynchronous task
-     *               (if the launch fails) or from the asynchronous task itself
-     *               (if the launch succeeds). Must be:
-     *               - NONE if the asynchronous execution was successful
-     *               - DEVICE_UNAVAILABLE if driver is offline or busy
-     *               - GENERAL_FAILURE if there is an unspecified error
-     *               - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is
-     *                 not large enough to store the resultant values
-     *               - INVALID_ARGUMENT if the input request is invalid
-     */
-    Return<void> notify(ErrorStatus status) override;
-
-    /**
-     * Similar to IExecutionCallback::notify, but for V1_2::IPreparedModel to
-     * also notify output shapes along with error status.
-     *
-     * @param status Error status returned from launching the asynchronous task
-     *               (if the launch fails) or from the asynchronous task itself
-     *               (if the launch succeeds). Must be:
-     *               - NONE if the asynchronous execution was successful
-     *               - DEVICE_UNAVAILABLE if driver is offline or busy
-     *               - GENERAL_FAILURE if the asynchronous task resulted in an
-     *                 unspecified error
-     *               - OUTPUT_INSUFFICIENT_SIZE if at least one output
-     *                 operand buffer is not large enough to store the
-     *                 corresponding output
-     *               - INVALID_ARGUMENT if one of the input arguments to
-     *                 prepareModel is invalid
-     * @param outputShapes A list of shape information of model output operands.
-     *                     The index into "outputShapes" corresponds to the index
-     *                     of the output operand in the Request outputs vector.
-     *                     outputShapes must be empty unless the status is either
-     *                     NONE or OUTPUT_INSUFFICIENT_SIZE.
-     * @return Timing Duration of execution. Unless MeasureTiming::YES was passed when
-     *                launching the execution and status is NONE, all times must
-     *                be reported as UINT64_MAX. A driver may choose to report
-     *                any time as UINT64_MAX, indicating that particular measurement is
-     *                not available.
-     */
-    Return<void> notify_1_2(ErrorStatus status, const hidl_vec<OutputShape>& outputShapes,
-                            const Timing& timing) override;
-
-    // An overload of the latest notify interface to hide the version from ExecutionBuilder.
-    Return<void> notify(ErrorStatus status, const hidl_vec<OutputShape>& outputShapes,
-                        const Timing& timing) {
-        return notify_1_2(status, outputShapes, timing);
-    }
-
-    /**
-     * Retrieves the error status returned from the asynchronous task launched
-     * by either IPreparedModel::execute or IPreparedModel::execute_1_2. If
-     * IPreparedModel::execute or IPreparedModel::execute_1_2 has not finished
-     * asynchronously executing, this call will block until the asynchronous task
-     * notifies the object.
-     *
-     * @return status Error status returned from launching the asynchronous task
-     *                (if the launch fails) or from the asynchronous task itself
-     *                (if the launch succeeds). Must be:
-     *                - NONE if the asynchronous execution was successful
-     *                - DEVICE_UNAVAILABLE if driver is offline or busy
-     *                - GENERAL_FAILURE if the asynchronous task resulted in an
-     *                  unspecified error
-     *                - OUTPUT_INSUFFICIENT_SIZE if at least one output
-     *                  operand buffer is not large enough to store the
-     *                  corresponding output
-     *                - INVALID_ARGUMENT if one of the input arguments to
-     *                  prepareModel is invalid
-     */
-    ErrorStatus getStatus();
-
-    /**
-     * Retrieves the output shapes returned from the asynchronous task launched
-     * by IPreparedModel::execute_1_2. If IPreparedModel::execute_1_2 has not finished
-     * asynchronously executing, this call will block until the asynchronous task
-     * notifies the object.
-     *
-     * If the asynchronous task was launched by IPreparedModel::execute, an empty vector
-     * will be returned.
-     *
-     * @return outputShapes A list of shape information of model output operands.
-     *                      The index into "outputShapes" corresponds to the index
-     *                      of the output operand in the Request outputs vector.
-     *                      outputShapes must be empty unless the status is either
-     *                      NONE or OUTPUT_INSUFFICIENT_SIZE.
-     */
-    const std::vector<OutputShape>& getOutputShapes();
-
-    /**
-     * Retrieves the duration of execution ofthe asynchronous task launched
-     * by IPreparedModel::execute_1_2. If IPreparedModel::execute_1_2 has not finished
-     * asynchronously executing, this call will block until the asynchronous task
-     * notifies the object.
-     *
-     * If the asynchronous task was launched by IPreparedModel::execute, every time
-     * must be UINT64_MAX.
-     *
-     * @return timing Duration of the execution. Every time must be UINT64_MAX unless
-     *                the status is NONE.
-     */
-    Timing getTiming();
-
-   private:
-    ErrorStatus mErrorStatus = ErrorStatus::GENERAL_FAILURE;
-    std::vector<OutputShape> mOutputShapes = {};
-    Timing mTiming = {};
-};
-
-
-// template function implementation(s) below this point
-
-template<class Rep, class Period>
-std::cv_status CallbackBase::wait_for(const std::chrono::duration<Rep,Period>& timeout_duration) {
-    std::unique_lock<std::mutex> lock(mMutex);
-    std::cv_status status = mCondition.wait_for(lock, timeout_duration, [this]{return mNotified;});
-    if (status != std::cv_status::timeout) {
-        join_thread_locked();
-    }
-    return status;
-}
-
-}  // namespace implementation
-}  // namespace V1_2
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_0_CALLBACKS_H
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index c819b52..595ad85 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -15,572 +15,161 @@
  */
 
 #include "GeneratedTestHarness.h"
-#include "Callbacks.h"
-#include "ExecutionBurstController.h"
+
+#include "1.0/Callbacks.h"
+#include "1.0/Utils.h"
+#include "MemoryUtils.h"
 #include "TestHarness.h"
-#include "Utils.h"
+#include "VtsHalNeuralnetworks.h"
 
 #include <android-base/logging.h>
 #include <android/hardware/neuralnetworks/1.0/IDevice.h>
-#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
 #include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
-#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
 #include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.1/IDevice.h>
-#include <android/hardware/neuralnetworks/1.2/IDevice.h>
-#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
-#include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
-#include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
 #include <android/hidl/allocator/1.0/IAllocator.h>
 #include <android/hidl/memory/1.0/IMemory.h>
 #include <hidlmemory/mapping.h>
+
+#include <gtest/gtest.h>
 #include <iostream>
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
+namespace android::hardware::neuralnetworks::V1_0::vts::functional {
 
-namespace generated_tests {
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
-using ::test_helper::bool8;
-using ::test_helper::compare;
-using ::test_helper::expectMultinomialDistributionWithinTolerance;
-using ::test_helper::filter;
-using ::test_helper::for_all;
-using ::test_helper::for_each;
-using ::test_helper::MixedTyped;
-using ::test_helper::MixedTypedExample;
-using ::test_helper::resize_accordingly;
-using HidlToken = hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
+using namespace test_helper;
+using hidl::memory::V1_0::IMemory;
+using implementation::ExecutionCallback;
+using implementation::PreparedModelCallback;
 
-template <typename T>
-void copy_back_(std::map<int, std::vector<T>>* dst, const std::vector<RequestArgument>& ra,
-                char* src) {
-    for_each<T>(*dst, [&ra, src](int index, std::vector<T>& m) {
-        ASSERT_EQ(m.size(), ra[index].location.length / sizeof(T));
-        char* begin = src + ra[index].location.offset;
-        memcpy(m.data(), begin, ra[index].location.length);
-    });
-}
+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];
 
-void copy_back(MixedTyped* dst, const std::vector<RequestArgument>& ra, char* src) {
-    copy_back_(&dst->float32Operands, ra, src);
-    copy_back_(&dst->int32Operands, ra, src);
-    copy_back_(&dst->quant8AsymmOperands, ra, src);
-    copy_back_(&dst->quant16SymmOperands, ra, src);
-    copy_back_(&dst->float16Operands, ra, src);
-    copy_back_(&dst->bool8Operands, ra, src);
-    copy_back_(&dst->quant8ChannelOperands, ra, src);
-    copy_back_(&dst->quant16AsymmOperands, ra, src);
-    copy_back_(&dst->quant8SymmOperands, ra, src);
-    static_assert(9 == MixedTyped::kNumTypes,
-                  "Number of types in MixedTyped changed, but copy_back function wasn't updated");
-}
+        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();
+        } 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();
+        }
 
-static bool isZeroSized(const MixedTyped& example, uint32_t index) {
-    for (auto i : example.operandDimensions.at(index)) {
-        if (i == 0) return true;
+        operands[i] = {.type = static_cast<OperandType>(op.type),
+                       .dimensions = op.dimensions,
+                       .numberOfConsumers = op.numberOfConsumers,
+                       .scale = op.scale,
+                       .zeroPoint = op.zeroPoint,
+                       .lifetime = static_cast<OperandLifeTime>(op.lifetime),
+                       .location = loc};
     }
-    return false;
+
+    // Model operations.
+    hidl_vec<Operation> operations(testModel.operations.size());
+    std::transform(testModel.operations.begin(), testModel.operations.end(), operations.begin(),
+                   [](const TestOperation& op) -> Operation {
+                       return {.type = static_cast<OperationType>(op.type),
+                               .inputs = op.inputs,
+                               .outputs = op.outputs};
+                   });
+
+    // 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);
+        }
+    }
+
+    // Shared memory.
+    hidl_vec<hidl_memory> pools;
+    if (constRefSize > 0) {
+        hidl_vec_push_back(&pools, nn::allocateSharedMemory(constRefSize));
+        CHECK_NE(pools[0].size(), 0u);
+
+        // load data
+        sp<IMemory> mappedMemory = mapMemory(pools[0]);
+        CHECK(mappedMemory.get() != nullptr);
+        uint8_t* mappedPtr =
+                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);
+            }
+        }
+    }
+
+    return {.operands = std::move(operands),
+            .operations = std::move(operations),
+            .inputIndexes = testModel.inputIndexes,
+            .outputIndexes = testModel.outputIndexes,
+            .operandValues = std::move(operandValues),
+            .pools = std::move(pools)};
 }
 
 // Top level driver for models and examples generated by test_generator.py
 // Test driver for those generated from ml/nn/runtime/test/spec
-static Return<ErrorStatus> ExecutePreparedModel(sp<V1_0::IPreparedModel>& preparedModel,
-                                                const Request& request, MeasureTiming,
-                                                sp<ExecutionCallback>& callback) {
-    return preparedModel->execute(request, callback);
-}
-static Return<ErrorStatus> ExecutePreparedModel(sp<V1_2::IPreparedModel>& preparedModel,
-                                                const Request& request, MeasureTiming measure,
-                                                sp<ExecutionCallback>& callback) {
-    return preparedModel->execute_1_2(request, measure, callback);
-}
-static Return<ErrorStatus> ExecutePreparedModel(sp<V1_0::IPreparedModel>&, const Request&,
-                                                MeasureTiming, hidl_vec<OutputShape>*, Timing*) {
-    ADD_FAILURE() << "asking for synchronous execution at V1_0";
-    return ErrorStatus::GENERAL_FAILURE;
-}
-static Return<ErrorStatus> ExecutePreparedModel(sp<V1_2::IPreparedModel>& preparedModel,
-                                                const Request& request, MeasureTiming measure,
-                                                hidl_vec<OutputShape>* outputShapes,
-                                                Timing* timing) {
-    ErrorStatus result;
-    Return<void> ret = preparedModel->executeSynchronously(
-            request, measure,
-            [&result, outputShapes, timing](ErrorStatus error, const hidl_vec<OutputShape>& shapes,
-                                            const Timing& time) {
-                result = error;
-                *outputShapes = shapes;
-                *timing = time;
-            });
-    if (!ret.isOk()) {
-        return ErrorStatus::GENERAL_FAILURE;
-    }
-    return result;
-}
-static std::unique_ptr<::android::nn::ExecutionBurstController> CreateBurst(
-        const sp<V1_0::IPreparedModel>&) {
-    ADD_FAILURE() << "asking for burst execution at V1_0";
-    return nullptr;
-}
-static std::shared_ptr<::android::nn::ExecutionBurstController> CreateBurst(
-        const sp<V1_2::IPreparedModel>& preparedModel) {
-    return ::android::nn::ExecutionBurstController::create(preparedModel, /*blocking=*/true);
-}
-enum class Executor { ASYNC, SYNC, BURST };
-enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT };
-const float kDefaultAtol = 1e-5f;
-const float kDefaultRtol = 1e-5f;
-template <typename T_IPreparedModel>
-void EvaluatePreparedModel(sp<T_IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
-                           const std::vector<MixedTypedExample>& examples,
-                           bool hasRelaxedFloat32Model, float fpAtol, float fpRtol,
-                           Executor executor, MeasureTiming measure, OutputType outputType) {
-    const uint32_t INPUT = 0;
-    const uint32_t OUTPUT = 1;
+void Execute(const sp<IDevice>& device, const TestModel& testModel) {
+    const Model model = createModel(testModel);
+    const Request request = createRequest(testModel);
 
-    int example_no = 1;
-    for (auto& example : examples) {
-        SCOPED_TRACE(example_no++);
-        const MixedTyped& inputs = example.operands.first;
-        const MixedTyped& golden = example.operands.second;
+    // Create IPreparedModel.
+    sp<IPreparedModel> preparedModel;
+    createPreparedModel(device, model, &preparedModel);
+    if (preparedModel == nullptr) return;
 
-        const bool hasFloat16Inputs = !inputs.float16Operands.empty();
-        if (hasRelaxedFloat32Model || hasFloat16Inputs) {
-            // TODO: Adjust the error limit based on testing.
-            // If in relaxed mode, set the absolute tolerance to be 5ULP of FP16.
-            fpAtol = 5.0f * 0.0009765625f;
-            // Set the relative tolerance to be 5ULP of the corresponding FP precision.
-            fpRtol = 5.0f * 0.0009765625f;
-        }
+    // Launch execution.
+    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+    Return<ErrorStatus> executionLaunchStatus = preparedModel->execute(request, executionCallback);
+    ASSERT_TRUE(executionLaunchStatus.isOk());
+    EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
 
-        std::vector<RequestArgument> inputs_info, outputs_info;
-        uint32_t inputSize = 0, outputSize = 0;
-        // This function only partially specifies the metadata (vector of RequestArguments).
-        // The contents are copied over below.
-        for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
-            if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
-            RequestArgument arg = {
-                .location = {.poolIndex = INPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
-                .dimensions = {},
-            };
-            RequestArgument arg_empty = {
-                .hasNoValue = true,
-            };
-            inputs_info[index] = s ? arg : arg_empty;
-            inputSize += s;
-        });
-        // Compute offset for inputs 1 and so on
-        {
-            size_t offset = 0;
-            for (auto& i : inputs_info) {
-                if (!i.hasNoValue) i.location.offset = offset;
-                offset += i.location.length;
-            }
-        }
+    // Retrieve execution status.
+    executionCallback->wait();
+    ASSERT_EQ(ErrorStatus::NONE, executionCallback->getStatus());
 
-        MixedTyped test;  // holding test results
+    // Retrieve execution results.
+    const std::vector<TestBuffer> outputs = getOutputBuffers(request);
 
-        // Go through all outputs, initialize RequestArgument descriptors
-        resize_accordingly(golden, test);
-        bool sizeLargerThanOne = true;
-        for_all(golden, [&golden, &outputs_info, &outputSize, &outputType, &sizeLargerThanOne](
-                                int index, auto, auto s) {
-            if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
-            if (index == 0) {
-                // On OutputType::INSUFFICIENT, set the output operand with index 0 with
-                // buffer size one byte less than needed.
-                if (outputType == OutputType::INSUFFICIENT) {
-                    if (s > 1 && !isZeroSized(golden, index)) {
-                        s -= 1;
-                    } else {
-                        sizeLargerThanOne = false;
-                    }
-                }
-            }
-            RequestArgument arg = {
-                .location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
-                .dimensions = {},
-            };
-            outputs_info[index] = arg;
-            outputSize += s;
-        });
-        // If output0 does not have size larger than one byte,
-        // we can not provide an insufficient buffer
-        if (!sizeLargerThanOne && outputType == OutputType::INSUFFICIENT) return;
-        // Compute offset for outputs 1 and so on
-        {
-            size_t offset = 0;
-            for (auto& i : outputs_info) {
-                i.location.offset = offset;
-                offset += i.location.length;
-            }
-        }
-        std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
-                                          nn::allocateSharedMemory(outputSize)};
-        ASSERT_NE(0ull, pools[INPUT].size());
-        ASSERT_NE(0ull, pools[OUTPUT].size());
-
-        // load data
-        sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
-        sp<IMemory> outputMemory = mapMemory(pools[OUTPUT]);
-        ASSERT_NE(nullptr, inputMemory.get());
-        ASSERT_NE(nullptr, outputMemory.get());
-        char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
-        char* outputPtr = reinterpret_cast<char*>(static_cast<void*>(outputMemory->getPointer()));
-        ASSERT_NE(nullptr, inputPtr);
-        ASSERT_NE(nullptr, outputPtr);
-        inputMemory->update();
-        outputMemory->update();
-
-        // Go through all inputs, copy the values
-        for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) {
-            char* begin = (char*)p;
-            char* end = begin + s;
-            // TODO: handle more than one input
-            std::copy(begin, end, inputPtr + inputs_info[index].location.offset);
-        });
-
-        inputMemory->commit();
-        outputMemory->commit();
-
-        const Request request = {.inputs = inputs_info, .outputs = outputs_info, .pools = pools};
-
-        ErrorStatus executionStatus;
-        hidl_vec<OutputShape> outputShapes;
-        Timing timing;
-        switch (executor) {
-            case Executor::ASYNC: {
-                SCOPED_TRACE("asynchronous");
-
-                // launch execution
-                sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-                ASSERT_NE(nullptr, executionCallback.get());
-                Return<ErrorStatus> executionLaunchStatus =
-                        ExecutePreparedModel(preparedModel, request, measure, executionCallback);
-                ASSERT_TRUE(executionLaunchStatus.isOk());
-                EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
-
-                // retrieve execution status
-                executionCallback->wait();
-                executionStatus = executionCallback->getStatus();
-                outputShapes = executionCallback->getOutputShapes();
-                timing = executionCallback->getTiming();
-
-                break;
-            }
-            case Executor::SYNC: {
-                SCOPED_TRACE("synchronous");
-
-                // execute
-                Return<ErrorStatus> executionReturnStatus = ExecutePreparedModel(
-                        preparedModel, request, measure, &outputShapes, &timing);
-                ASSERT_TRUE(executionReturnStatus.isOk());
-                executionStatus = static_cast<ErrorStatus>(executionReturnStatus);
-
-                break;
-            }
-            case Executor::BURST: {
-                SCOPED_TRACE("burst");
-
-                // create burst
-                const std::shared_ptr<::android::nn::ExecutionBurstController> controller =
-                        CreateBurst(preparedModel);
-                ASSERT_NE(nullptr, controller.get());
-
-                // create memory keys
-                std::vector<intptr_t> keys(request.pools.size());
-                for (size_t i = 0; i < keys.size(); ++i) {
-                    keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
-                }
-
-                // execute burst
-                std::tie(executionStatus, outputShapes, timing) =
-                        controller->compute(request, measure, keys);
-
-                break;
-            }
-        }
-
-        if (outputType != OutputType::FULLY_SPECIFIED &&
-            executionStatus == ErrorStatus::GENERAL_FAILURE) {
-            LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
-                         "execute model that it does not support.";
-            std::cout << "[          ]   Early termination of test because vendor service cannot "
-                         "execute model that it does not support."
-                      << std::endl;
-            GTEST_SKIP();
-        }
-        if (measure == MeasureTiming::NO) {
-            EXPECT_EQ(UINT64_MAX, timing.timeOnDevice);
-            EXPECT_EQ(UINT64_MAX, timing.timeInDriver);
-        } else {
-            if (timing.timeOnDevice != UINT64_MAX && timing.timeInDriver != UINT64_MAX) {
-                EXPECT_LE(timing.timeOnDevice, timing.timeInDriver);
-            }
-        }
-
-        switch (outputType) {
-            case OutputType::FULLY_SPECIFIED:
-                // If the model output operands are fully specified, outputShapes must be either
-                // either empty, or have the same number of elements as the number of outputs.
-                ASSERT_EQ(ErrorStatus::NONE, executionStatus);
-                ASSERT_TRUE(outputShapes.size() == 0 ||
-                            outputShapes.size() == test.operandDimensions.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(), test.operandDimensions.size());
-                break;
-            case OutputType::INSUFFICIENT:
-                ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
-                ASSERT_EQ(outputShapes.size(), test.operandDimensions.size());
-                ASSERT_FALSE(outputShapes[0].isSufficient);
-                return;
-        }
-        // Go through all outputs, overwrite output dimensions with returned output shapes
-        if (outputShapes.size() > 0) {
-            for_each<uint32_t>(test.operandDimensions,
-                               [&outputShapes](int idx, std::vector<uint32_t>& dim) {
-                                   dim = outputShapes[idx].dimensions;
-                               });
-        }
-
-        // validate results
-        outputMemory->read();
-        copy_back(&test, outputs_info, outputPtr);
-        outputMemory->commit();
-        // Filter out don't cares
-        MixedTyped filtered_golden = filter(golden, is_ignored);
-        MixedTyped filtered_test = filter(test, is_ignored);
-
-        // We want "close-enough" results for float
-        compare(filtered_golden, filtered_test, fpAtol, fpRtol);
-
-        if (example.expectedMultinomialDistributionTolerance > 0) {
-            expectMultinomialDistributionWithinTolerance(test, example);
-        }
-    }
-}
-template <typename T_IPreparedModel>
-void EvaluatePreparedModel(sp<T_IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
-                           const std::vector<MixedTypedExample>& examples,
-                           bool hasRelaxedFloat32Model, Executor executor, MeasureTiming measure,
-                           OutputType outputType) {
-    EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model, kDefaultAtol,
-                          kDefaultRtol, executor, measure, outputType);
+    // We want "close-enough" results.
+    checkResults(testModel, outputs);
 }
 
-void EvaluatePreparedModel(sp<V1_2::IPreparedModel>& preparedModel,
-                           std::function<bool(int)> is_ignored,
-                           const std::vector<MixedTypedExample>& examples,
-                           bool hasRelaxedFloat32Model, bool testDynamicOutputShape) {
-    if (testDynamicOutputShape) {
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::ASYNC, MeasureTiming::NO, OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::SYNC, MeasureTiming::NO, OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::BURST, MeasureTiming::NO, OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::ASYNC, MeasureTiming::YES, OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::SYNC, MeasureTiming::YES, OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::BURST, MeasureTiming::YES, OutputType::UNSPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::ASYNC, MeasureTiming::NO, OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::SYNC, MeasureTiming::NO, OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::BURST, MeasureTiming::NO, OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::ASYNC, MeasureTiming::YES, OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::SYNC, MeasureTiming::YES, OutputType::INSUFFICIENT);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::BURST, MeasureTiming::YES, OutputType::INSUFFICIENT);
-    } else {
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::ASYNC, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::SYNC, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::BURST, MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::ASYNC, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::SYNC, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
-        EvaluatePreparedModel(preparedModel, is_ignored, examples, hasRelaxedFloat32Model,
-                              Executor::BURST, MeasureTiming::YES, OutputType::FULLY_SPECIFIED);
-    }
+void GeneratedTestBase::SetUp() {
+    testing::TestWithParam<GeneratedTestParam>::SetUp();
+    ASSERT_NE(kDevice, nullptr);
 }
 
-static void getPreparedModel(sp<PreparedModelCallback> callback,
-                             sp<V1_0::IPreparedModel>* preparedModel) {
-    *preparedModel = callback->getPreparedModel();
-}
-static void getPreparedModel(sp<PreparedModelCallback> callback,
-                             sp<V1_2::IPreparedModel>* preparedModel) {
-    sp<V1_0::IPreparedModel> preparedModelV1_0 = callback->getPreparedModel();
-    *preparedModel = V1_2::IPreparedModel::castFrom(preparedModelV1_0).withDefault(nullptr);
+std::vector<NamedModel> getNamedModels(const FilterFn& filter) {
+    return TestModelManager::get().getTestModels(filter);
 }
 
-void Execute(const sp<V1_0::IDevice>& device, std::function<V1_0::Model(void)> create_model,
-             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples) {
-    V1_0::Model model = create_model();
-
-    // see if service can handle model
-    bool fullySupportsModel = false;
-    Return<void> supportedCall = device->getSupportedOperations(
-        model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
-            ASSERT_EQ(ErrorStatus::NONE, status);
-            ASSERT_NE(0ul, supported.size());
-            fullySupportsModel =
-                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
-        });
-    ASSERT_TRUE(supportedCall.isOk());
-
-    // launch prepare model
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-    ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
-
-    // retrieve prepared model
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    sp<V1_0::IPreparedModel> preparedModel;
-    getPreparedModel(preparedModelCallback, &preparedModel);
-
-    // early termination if vendor service cannot fully prepare model
-    if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
-        ASSERT_EQ(nullptr, preparedModel.get());
-        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
-                     "prepare model that it does not support.";
-        std::cout << "[          ]   Early termination of test because vendor service cannot "
-                     "prepare model that it does not support."
-                  << std::endl;
-        GTEST_SKIP();
-    }
-    EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
-    ASSERT_NE(nullptr, preparedModel.get());
-
-    float fpAtol = 1e-5f, fpRtol = 5.0f * 1.1920928955078125e-7f;
-    EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          /*hasRelaxedFloat32Model=*/false, fpAtol, fpRtol, Executor::ASYNC,
-                          MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
+std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info) {
+    const auto& [namedDevice, namedModel] = info.param;
+    return gtestCompliantName(getName(namedDevice) + "_" + getName(namedModel));
 }
 
-void Execute(const sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
-             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples) {
-    V1_1::Model model = create_model();
+// Tag for the generated tests
+class GeneratedTest : public GeneratedTestBase {};
 
-    // see if service can handle model
-    bool fullySupportsModel = false;
-    Return<void> supportedCall = device->getSupportedOperations_1_1(
-        model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
-            ASSERT_EQ(ErrorStatus::NONE, status);
-            ASSERT_NE(0ul, supported.size());
-            fullySupportsModel =
-                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
-        });
-    ASSERT_TRUE(supportedCall.isOk());
-
-    // launch prepare model
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_1(
-        model, ExecutionPreference::FAST_SINGLE_ANSWER, preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-    ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
-
-    // retrieve prepared model
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    sp<V1_0::IPreparedModel> preparedModel;
-    getPreparedModel(preparedModelCallback, &preparedModel);
-
-    // early termination if vendor service cannot fully prepare model
-    if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
-        ASSERT_EQ(nullptr, preparedModel.get());
-        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
-                     "prepare model that it does not support.";
-        std::cout << "[          ]   Early termination of test because vendor service cannot "
-                     "prepare model that it does not support."
-                  << std::endl;
-        GTEST_SKIP();
-    }
-    EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
-    ASSERT_NE(nullptr, preparedModel.get());
-
-    EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          model.relaxComputationFloat32toFloat16, 1e-5f, 1e-5f, Executor::ASYNC,
-                          MeasureTiming::NO, OutputType::FULLY_SPECIFIED);
+TEST_P(GeneratedTest, Test) {
+    Execute(kDevice, kTestModel);
 }
 
-void PrepareModel(const sp<V1_2::IDevice>& device, const V1_2::Model& model,
-                  sp<V1_2::IPreparedModel>* preparedModel) {
-    // see if service can handle model
-    bool fullySupportsModel = false;
-    Return<void> supportedCall = device->getSupportedOperations_1_2(
-        model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
-            ASSERT_EQ(ErrorStatus::NONE, status);
-            ASSERT_NE(0ul, supported.size());
-            fullySupportsModel =
-                std::all_of(supported.begin(), supported.end(), [](bool valid) { return valid; });
-        });
-    ASSERT_TRUE(supportedCall.isOk());
+INSTANTIATE_GENERATED_TEST(GeneratedTest,
+                           [](const TestModel& testModel) { return !testModel.expectFailure; });
 
-    // launch prepare model
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_2(
-            model, ExecutionPreference::FAST_SINGLE_ANSWER, hidl_vec<hidl_handle>(),
-            hidl_vec<hidl_handle>(), HidlToken(), preparedModelCallback);
-    ASSERT_TRUE(prepareLaunchStatus.isOk());
-    ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
-
-    // retrieve prepared model
-    preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
-    getPreparedModel(preparedModelCallback, preparedModel);
-
-    // early termination if vendor service cannot fully prepare model
-    if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
-        ASSERT_EQ(nullptr, preparedModel->get());
-        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
-                     "prepare model that it does not support.";
-        std::cout << "[          ]   Early termination of test because vendor service cannot "
-                     "prepare model that it does not support."
-                  << std::endl;
-        return;
-    }
-    EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
-    ASSERT_NE(nullptr, preparedModel->get());
-}
-
-// TODO: Reduce code duplication.
-void Execute(const sp<V1_2::IDevice>& device, std::function<V1_2::Model(void)> create_model,
-             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples,
-             bool testDynamicOutputShape) {
-    V1_2::Model model = create_model();
-    sp<V1_2::IPreparedModel> preparedModel = nullptr;
-    PrepareModel(device, model, &preparedModel);
-    if (preparedModel == nullptr) {
-        GTEST_SKIP();
-    }
-    EvaluatePreparedModel(preparedModel, is_ignored, examples,
-                          model.relaxComputationFloat32toFloat16, testDynamicOutputShape);
-}
-
-}  // namespace generated_tests
-
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::neuralnetworks::V1_0::vts::functional
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
index c7d2399..f230a02 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.h
@@ -14,44 +14,43 @@
  * limitations under the License.
  */
 
-#ifndef VTS_HAL_NEURALNETWORKS_GENERATED_TEST_HARNESS_H
-#define VTS_HAL_NEURALNETWORKS_GENERATED_TEST_HARNESS_H
-
-#include "TestHarness.h"
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_0_GENERATED_TEST_HARNESS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_0_GENERATED_TEST_HARNESS_H
 
 #include <android/hardware/neuralnetworks/1.0/IDevice.h>
-#include <android/hardware/neuralnetworks/1.1/IDevice.h>
-#include <android/hardware/neuralnetworks/1.2/IDevice.h>
+#include <functional>
+#include "TestHarness.h"
+#include "VtsHalNeuralnetworks.h"
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
+namespace android::hardware::neuralnetworks::V1_0::vts::functional {
 
-namespace generated_tests {
-using ::test_helper::MixedTypedExample;
+using NamedModel = Named<const test_helper::TestModel*>;
+using GeneratedTestParam = std::tuple<NamedDevice, NamedModel>;
 
-void PrepareModel(const sp<V1_2::IDevice>& device, const V1_2::Model& model,
-                  sp<V1_2::IPreparedModel>* preparedModel);
+class GeneratedTestBase : public testing::TestWithParam<GeneratedTestParam> {
+  protected:
+    void SetUp() override;
+    const sp<IDevice> kDevice = getData(std::get<NamedDevice>(GetParam()));
+    const test_helper::TestModel& kTestModel = *getData(std::get<NamedModel>(GetParam()));
+};
 
-void EvaluatePreparedModel(sp<V1_2::IPreparedModel>& preparedModel,
-                           std::function<bool(int)> is_ignored,
-                           const std::vector<MixedTypedExample>& examples,
-                           bool hasRelaxedFloat32Model, bool testDynamicOutputShape);
+using FilterFn = std::function<bool(const test_helper::TestModel&)>;
+std::vector<NamedModel> getNamedModels(const FilterFn& filter);
 
-void Execute(const sp<V1_0::IDevice>& device, std::function<V1_0::Model(void)> create_model,
-             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples);
+std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info);
 
-void Execute(const sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
-             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples);
+#define INSTANTIATE_GENERATED_TEST(TestSuite, filter)                                     \
+    INSTANTIATE_TEST_SUITE_P(TestGenerated, TestSuite,                                    \
+                             testing::Combine(testing::ValuesIn(getNamedDevices()),       \
+                                              testing::ValuesIn(getNamedModels(filter))), \
+                             printGeneratedTest)
 
-void Execute(const sp<V1_2::IDevice>& device, std::function<V1_2::Model(void)> create_model,
-             std::function<bool(int)> is_ignored, const std::vector<MixedTypedExample>& examples,
-             bool testDynamicOutputShape = false);
+// Tag for the validation tests, instantiated in VtsHalNeuralnetworks.cpp.
+// TODO: Clean up the hierarchy for ValidationTest.
+class ValidationTest : public GeneratedTestBase {};
 
-}  // namespace generated_tests
+Model createModel(const test_helper::TestModel& testModel);
 
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::neuralnetworks::V1_0::vts::functional
 
-#endif  // VTS_HAL_NEURALNETWORKS_GENERATED_TEST_HARNESS_H
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_0_GENERATED_TEST_HARNESS_H
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
deleted file mode 100644
index d1c7de3..0000000
--- a/neuralnetworks/1.0/vts/functional/GeneratedTests.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "neuralnetworks_hidl_hal_test"
-
-#include "VtsHalNeuralnetworks.h"
-
-#include "Callbacks.h"
-#include "GeneratedTestHarness.h"
-#include "TestHarness.h"
-#include "Utils.h"
-
-#include <android-base/logging.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
-
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
-using ::android::nn::allocateSharedMemory;
-using ::test_helper::MixedTypedExample;
-
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
-
-// in frameworks/ml/nn/runtime/tests/generated/
-#include "all_generated_V1_0_vts_tests.cpp"
-
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_0
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
diff --git a/neuralnetworks/1.0/vts/functional/TestAssertions.cpp b/neuralnetworks/1.0/vts/functional/TestAssertions.cpp
new file mode 100644
index 0000000..8fdc98d
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/TestAssertions.cpp
@@ -0,0 +1,74 @@
+/*
+ * 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/hardware/neuralnetworks/1.0/types.h>
+#include "TestHarness.h"
+
+namespace android::hardware::neuralnetworks::V1_0 {
+
+// Make sure that the HIDL enums are compatible with the values defined in
+// frameworks/ml/nn/tools/test_generator/test_harness/include/TestHarness.h.
+using namespace test_helper;
+#define CHECK_TEST_ENUM(EnumType, enumValue) \
+    static_assert(static_cast<EnumType>(Test##EnumType::enumValue) == EnumType::enumValue)
+
+CHECK_TEST_ENUM(OperandType, FLOAT32);
+CHECK_TEST_ENUM(OperandType, INT32);
+CHECK_TEST_ENUM(OperandType, UINT32);
+CHECK_TEST_ENUM(OperandType, TENSOR_FLOAT32);
+CHECK_TEST_ENUM(OperandType, TENSOR_INT32);
+CHECK_TEST_ENUM(OperandType, TENSOR_QUANT8_ASYMM);
+
+CHECK_TEST_ENUM(OperandLifeTime, TEMPORARY_VARIABLE);
+CHECK_TEST_ENUM(OperandLifeTime, MODEL_INPUT);
+CHECK_TEST_ENUM(OperandLifeTime, MODEL_OUTPUT);
+CHECK_TEST_ENUM(OperandLifeTime, CONSTANT_COPY);
+CHECK_TEST_ENUM(OperandLifeTime, CONSTANT_REFERENCE);
+CHECK_TEST_ENUM(OperandLifeTime, NO_VALUE);
+
+CHECK_TEST_ENUM(OperationType, ADD);
+CHECK_TEST_ENUM(OperationType, AVERAGE_POOL_2D);
+CHECK_TEST_ENUM(OperationType, CONCATENATION);
+CHECK_TEST_ENUM(OperationType, CONV_2D);
+CHECK_TEST_ENUM(OperationType, DEPTHWISE_CONV_2D);
+CHECK_TEST_ENUM(OperationType, DEPTH_TO_SPACE);
+CHECK_TEST_ENUM(OperationType, DEQUANTIZE);
+CHECK_TEST_ENUM(OperationType, EMBEDDING_LOOKUP);
+CHECK_TEST_ENUM(OperationType, FLOOR);
+CHECK_TEST_ENUM(OperationType, FULLY_CONNECTED);
+CHECK_TEST_ENUM(OperationType, HASHTABLE_LOOKUP);
+CHECK_TEST_ENUM(OperationType, L2_NORMALIZATION);
+CHECK_TEST_ENUM(OperationType, L2_POOL_2D);
+CHECK_TEST_ENUM(OperationType, LOCAL_RESPONSE_NORMALIZATION);
+CHECK_TEST_ENUM(OperationType, LOGISTIC);
+CHECK_TEST_ENUM(OperationType, LSH_PROJECTION);
+CHECK_TEST_ENUM(OperationType, LSTM);
+CHECK_TEST_ENUM(OperationType, MAX_POOL_2D);
+CHECK_TEST_ENUM(OperationType, MUL);
+CHECK_TEST_ENUM(OperationType, RELU);
+CHECK_TEST_ENUM(OperationType, RELU1);
+CHECK_TEST_ENUM(OperationType, RELU6);
+CHECK_TEST_ENUM(OperationType, RESHAPE);
+CHECK_TEST_ENUM(OperationType, RESIZE_BILINEAR);
+CHECK_TEST_ENUM(OperationType, RNN);
+CHECK_TEST_ENUM(OperationType, SOFTMAX);
+CHECK_TEST_ENUM(OperationType, SPACE_TO_DEPTH);
+CHECK_TEST_ENUM(OperationType, SVDF);
+CHECK_TEST_ENUM(OperationType, TANH);
+
+#undef CHECK_TEST_ENUM
+
+}  // namespace android::hardware::neuralnetworks::V1_0
diff --git a/neuralnetworks/1.0/vts/functional/Utils.cpp b/neuralnetworks/1.0/vts/functional/Utils.cpp
new file mode 100644
index 0000000..5b630fd
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/Utils.cpp
@@ -0,0 +1,139 @@
+/*
+ * 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 "1.0/Utils.h"
+
+#include "MemoryUtils.h"
+#include "TestHarness.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+#include <algorithm>
+#include <iostream>
+#include <vector>
+
+namespace android::hardware::neuralnetworks {
+
+using namespace test_helper;
+using hidl::memory::V1_0::IMemory;
+using V1_0::DataLocation;
+using V1_0::Request;
+using V1_0::RequestArgument;
+
+constexpr uint32_t kInputPoolIndex = 0;
+constexpr uint32_t kOutputPoolIndex = 1;
+
+Request createRequest(const TestModel& testModel) {
+    // Model inputs.
+    hidl_vec<RequestArgument> inputs(testModel.inputIndexes.size());
+    size_t inputSize = 0;
+    for (uint32_t i = 0; i < testModel.inputIndexes.size(); i++) {
+        const auto& op = testModel.operands[testModel.inputIndexes[i]];
+        if (op.data.size() == 0) {
+            // Omitted input.
+            inputs[i] = {.hasNoValue = true};
+        } else {
+            DataLocation loc = {.poolIndex = kInputPoolIndex,
+                                .offset = static_cast<uint32_t>(inputSize),
+                                .length = static_cast<uint32_t>(op.data.size())};
+            inputSize += op.data.alignedSize();
+            inputs[i] = {.hasNoValue = false, .location = loc, .dimensions = {}};
+        }
+    }
+
+    // Model outputs.
+    hidl_vec<RequestArgument> outputs(testModel.outputIndexes.size());
+    size_t outputSize = 0;
+    for (uint32_t i = 0; i < testModel.outputIndexes.size(); i++) {
+        const auto& op = testModel.operands[testModel.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
+        // reported in output shapes. It is illegal for the client to pre-specify a zero-sized
+        // tensor as model output. Otherwise, we will have two semantic conflicts:
+        // - "Zero dimension" conflicts with "unspecified dimension".
+        // - "Omitted operand buffer" conflicts with "zero-sized operand buffer".
+        size_t bufferSize = std::max<size_t>(op.data.size(), 1);
+
+        DataLocation loc = {.poolIndex = kOutputPoolIndex,
+                            .offset = static_cast<uint32_t>(outputSize),
+                            .length = static_cast<uint32_t>(bufferSize)};
+        outputSize += op.data.size() == 0 ? TestBuffer::kAlignment : op.data.alignedSize();
+        outputs[i] = {.hasNoValue = false, .location = loc, .dimensions = {}};
+    }
+
+    // Allocate memory pools.
+    hidl_vec<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
+                                   nn::allocateSharedMemory(outputSize)};
+    CHECK_NE(pools[kInputPoolIndex].size(), 0u);
+    CHECK_NE(pools[kOutputPoolIndex].size(), 0u);
+    sp<IMemory> inputMemory = mapMemory(pools[kInputPoolIndex]);
+    CHECK(inputMemory.get() != nullptr);
+    uint8_t* inputPtr = static_cast<uint8_t*>(static_cast<void*>(inputMemory->getPointer()));
+    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]];
+        if (op.data.size() > 0) {
+            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);
+        }
+    }
+
+    return {.inputs = std::move(inputs), .outputs = std::move(outputs), .pools = std::move(pools)};
+}
+
+std::vector<TestBuffer> getOutputBuffers(const Request& request) {
+    sp<IMemory> outputMemory = mapMemory(request.pools[kOutputPoolIndex]);
+    CHECK(outputMemory.get() != nullptr);
+    uint8_t* outputPtr = static_cast<uint8_t*>(static_cast<void*>(outputMemory->getPointer()));
+    CHECK(outputPtr != nullptr);
+
+    // Copy out output results.
+    std::vector<TestBuffer> outputBuffers;
+    for (const auto& output : request.outputs) {
+        outputBuffers.emplace_back(output.location.length, outputPtr + output.location.offset);
+    }
+
+    return outputBuffers;
+}
+
+std::string gtestCompliantName(std::string name) {
+    // gtest test names must only contain alphanumeric characters
+    std::replace_if(
+            name.begin(), name.end(), [](char c) { return !std::isalnum(c); }, '_');
+    return name;
+}
+
+}  // namespace android::hardware::neuralnetworks
+
+namespace android::hardware::neuralnetworks::V1_0 {
+
+::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus) {
+    return os << toString(errorStatus);
+}
+
+::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus) {
+    return os << toString(deviceStatus);
+}
+
+}  // namespace android::hardware::neuralnetworks::V1_0
diff --git a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
index 5d24fb5..cc15263 100644
--- a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
@@ -16,39 +16,32 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
+#include "1.0/Callbacks.h"
+#include "GeneratedTestHarness.h"
 #include "VtsHalNeuralnetworks.h"
 
-#include "Callbacks.h"
+namespace android::hardware::neuralnetworks::V1_0::vts::functional {
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
-
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
+using implementation::PreparedModelCallback;
 
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
 static void validateGetSupportedOperations(const sp<IDevice>& device, const std::string& message,
-                                           const V1_0::Model& model) {
+                                           const Model& model) {
     SCOPED_TRACE(message + " [getSupportedOperations]");
 
     Return<void> ret =
-        device->getSupportedOperations(model, [&](ErrorStatus status, const hidl_vec<bool>&) {
-            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
-        });
+            device->getSupportedOperations(model, [&](ErrorStatus status, const hidl_vec<bool>&) {
+                EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
+            });
     EXPECT_TRUE(ret.isOk());
 }
 
 static void validatePrepareModel(const sp<IDevice>& device, const std::string& message,
-                                 const V1_0::Model& model) {
+                                 const Model& model) {
     SCOPED_TRACE(message + " [prepareModel]");
 
     sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
     Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
     ASSERT_TRUE(prepareLaunchStatus.isOk());
     ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
@@ -64,7 +57,7 @@
 // mutation to it to invalidate the model, then pass it to interface calls that
 // use the model. Note that the model here is passed by value, and any mutation
 // to the model does not leave this function.
-static void validate(const sp<IDevice>& device, const std::string& message, V1_0::Model model,
+static void validate(const sp<IDevice>& device, const std::string& message, Model model,
                      const std::function<void(Model*)>& mutation) {
     mutation(&model);
     validateGetSupportedOperations(device, message, model);
@@ -94,13 +87,13 @@
 static uint32_t addOperand(Model* model) {
     return hidl_vec_push_back(&model->operands,
                               {
-                                  .type = OperandType::INT32,
-                                  .dimensions = {},
-                                  .numberOfConsumers = 0,
-                                  .scale = 0.0f,
-                                  .zeroPoint = 0,
-                                  .lifetime = OperandLifeTime::MODEL_INPUT,
-                                  .location = {.poolIndex = 0, .offset = 0, .length = 0},
+                                      .type = OperandType::INT32,
+                                      .dimensions = {},
+                                      .numberOfConsumers = 0,
+                                      .scale = 0.0f,
+                                      .zeroPoint = 0,
+                                      .lifetime = OperandLifeTime::MODEL_INPUT,
+                                      .location = {.poolIndex = 0, .offset = 0, .length = 0},
                               });
 }
 
@@ -114,13 +107,13 @@
 ///////////////////////// VALIDATE MODEL OPERAND TYPE /////////////////////////
 
 static const int32_t invalidOperandTypes[] = {
-    static_cast<int32_t>(OperandType::FLOAT32) - 1,              // lower bound fundamental
-    static_cast<int32_t>(OperandType::TENSOR_QUANT8_ASYMM) + 1,  // upper bound fundamental
-    static_cast<int32_t>(OperandType::OEM) - 1,                  // lower bound OEM
-    static_cast<int32_t>(OperandType::TENSOR_OEM_BYTE) + 1,      // upper bound OEM
+        static_cast<int32_t>(OperandType::FLOAT32) - 1,              // lower bound fundamental
+        static_cast<int32_t>(OperandType::TENSOR_QUANT8_ASYMM) + 1,  // upper bound fundamental
+        static_cast<int32_t>(OperandType::OEM) - 1,                  // lower bound OEM
+        static_cast<int32_t>(OperandType::TENSOR_OEM_BYTE) + 1,      // upper bound OEM
 };
 
-static void mutateOperandTypeTest(const sp<IDevice>& device, const V1_0::Model& model) {
+static void mutateOperandTypeTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operand = 0; operand < model.operands.size(); ++operand) {
         for (int32_t invalidOperandType : invalidOperandTypes) {
             const std::string message = "mutateOperandTypeTest: operand " +
@@ -150,7 +143,7 @@
     }
 }
 
-static void mutateOperandRankTest(const sp<IDevice>& device, const V1_0::Model& model) {
+static void mutateOperandRankTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operand = 0; operand < model.operands.size(); ++operand) {
         const uint32_t invalidRank = getInvalidRank(model.operands[operand].type);
         const std::string message = "mutateOperandRankTest: operand " + std::to_string(operand) +
@@ -179,7 +172,7 @@
     }
 }
 
-static void mutateOperandScaleTest(const sp<IDevice>& device, const V1_0::Model& model) {
+static void mutateOperandScaleTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operand = 0; operand < model.operands.size(); ++operand) {
         const float invalidScale = getInvalidScale(model.operands[operand].type);
         const std::string message = "mutateOperandScaleTest: operand " + std::to_string(operand) +
@@ -207,10 +200,10 @@
     }
 }
 
-static void mutateOperandZeroPointTest(const sp<IDevice>& device, const V1_0::Model& model) {
+static void mutateOperandZeroPointTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operand = 0; operand < model.operands.size(); ++operand) {
         const std::vector<int32_t> invalidZeroPoints =
-            getInvalidZeroPoints(model.operands[operand].type);
+                getInvalidZeroPoints(model.operands[operand].type);
         for (int32_t invalidZeroPoint : invalidZeroPoints) {
             const std::string message = "mutateOperandZeroPointTest: operand " +
                                         std::to_string(operand) + " has zero point of " +
@@ -242,18 +235,18 @@
             break;
         case OperandType::TENSOR_FLOAT32:
             newOperand.dimensions =
-                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+                    operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.scale = 0.0f;
             newOperand.zeroPoint = 0;
             break;
         case OperandType::TENSOR_INT32:
             newOperand.dimensions =
-                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+                    operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.zeroPoint = 0;
             break;
         case OperandType::TENSOR_QUANT8_ASYMM:
             newOperand.dimensions =
-                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+                    operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.scale = operand->scale != 0.0f ? operand->scale : 1.0f;
             break;
         case OperandType::OEM:
@@ -264,7 +257,7 @@
     *operand = newOperand;
 }
 
-static bool mutateOperationOperandTypeSkip(size_t operand, const V1_0::Model& model) {
+static bool mutateOperationOperandTypeSkip(size_t operand, const Model& model) {
     // LSH_PROJECTION's second argument is allowed to have any type. This is the
     // only operation that currently has a type that can be anything independent
     // from any other type. Changing the operand type to any other type will
@@ -278,7 +271,7 @@
     return false;
 }
 
-static void mutateOperationOperandTypeTest(const sp<IDevice>& device, const V1_0::Model& model) {
+static void mutateOperationOperandTypeTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operand = 0; operand < model.operands.size(); ++operand) {
         if (mutateOperationOperandTypeSkip(operand, model)) {
             continue;
@@ -303,13 +296,13 @@
 ///////////////////////// VALIDATE MODEL OPERATION TYPE /////////////////////////
 
 static const int32_t invalidOperationTypes[] = {
-    static_cast<int32_t>(OperationType::ADD) - 1,            // lower bound fundamental
-    static_cast<int32_t>(OperationType::TANH) + 1,           // upper bound fundamental
-    static_cast<int32_t>(OperationType::OEM_OPERATION) - 1,  // lower bound OEM
-    static_cast<int32_t>(OperationType::OEM_OPERATION) + 1,  // upper bound OEM
+        static_cast<int32_t>(OperationType::ADD) - 1,            // lower bound fundamental
+        static_cast<int32_t>(OperationType::TANH) + 1,           // upper bound fundamental
+        static_cast<int32_t>(OperationType::OEM_OPERATION) - 1,  // lower bound OEM
+        static_cast<int32_t>(OperationType::OEM_OPERATION) + 1,  // upper bound OEM
 };
 
-static void mutateOperationTypeTest(const sp<IDevice>& device, const V1_0::Model& model) {
+static void mutateOperationTypeTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         for (int32_t invalidOperationType : invalidOperationTypes) {
             const std::string message = "mutateOperationTypeTest: operation " +
@@ -317,7 +310,7 @@
                                         std::to_string(invalidOperationType);
             validate(device, message, model, [operation, invalidOperationType](Model* model) {
                 model->operations[operation].type =
-                    static_cast<OperationType>(invalidOperationType);
+                        static_cast<OperationType>(invalidOperationType);
             });
         }
     }
@@ -325,8 +318,7 @@
 
 ///////////////////////// VALIDATE MODEL OPERATION INPUT OPERAND INDEX /////////////////////////
 
-static void mutateOperationInputOperandIndexTest(const sp<IDevice>& device,
-                                                 const V1_0::Model& model) {
+static void mutateOperationInputOperandIndexTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const uint32_t invalidOperand = model.operands.size();
         for (size_t input = 0; input < model.operations[operation].inputs.size(); ++input) {
@@ -342,8 +334,7 @@
 
 ///////////////////////// VALIDATE MODEL OPERATION OUTPUT OPERAND INDEX /////////////////////////
 
-static void mutateOperationOutputOperandIndexTest(const sp<IDevice>& device,
-                                                  const V1_0::Model& model) {
+static void mutateOperationOutputOperandIndexTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const uint32_t invalidOperand = model.operands.size();
         for (size_t output = 0; output < model.operations[operation].outputs.size(); ++output) {
@@ -381,7 +372,7 @@
     removeValueAndDecrementGreaterValues(&model->outputIndexes, index);
 }
 
-static void removeOperandTest(const sp<IDevice>& device, const V1_0::Model& model) {
+static void removeOperandTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operand = 0; operand < model.operands.size(); ++operand) {
         const std::string message = "removeOperandTest: operand " + std::to_string(operand);
         validate(device, message, model,
@@ -398,7 +389,7 @@
     hidl_vec_removeAt(&model->operations, index);
 }
 
-static void removeOperationTest(const sp<IDevice>& device, const V1_0::Model& model) {
+static void removeOperationTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const std::string message = "removeOperationTest: operation " + std::to_string(operation);
         validate(device, message, model,
@@ -408,14 +399,14 @@
 
 ///////////////////////// REMOVE OPERATION INPUT /////////////////////////
 
-static void removeOperationInputTest(const sp<IDevice>& device, const V1_0::Model& model) {
+static void removeOperationInputTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         for (size_t input = 0; input < model.operations[operation].inputs.size(); ++input) {
-            const V1_0::Operation& op = model.operations[operation];
+            const Operation& op = model.operations[operation];
             // CONCATENATION has at least 2 inputs, with the last element being
             // INT32. Skip this test if removing one of CONCATENATION's
             // inputs still produces a valid model.
-            if (op.type == V1_0::OperationType::CONCATENATION && op.inputs.size() > 2 &&
+            if (op.type == OperationType::CONCATENATION && op.inputs.size() > 2 &&
                 input != op.inputs.size() - 1) {
                 continue;
             }
@@ -433,7 +424,7 @@
 
 ///////////////////////// REMOVE OPERATION OUTPUT /////////////////////////
 
-static void removeOperationOutputTest(const sp<IDevice>& device, const V1_0::Model& model) {
+static void removeOperationOutputTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         for (size_t output = 0; output < model.operations[operation].outputs.size(); ++output) {
             const std::string message = "removeOperationOutputTest: operation " +
@@ -454,7 +445,7 @@
 
 ///////////////////////// ADD OPERATION INPUT /////////////////////////
 
-static void addOperationInputTest(const sp<IDevice>& device, const V1_0::Model& model) {
+static void addOperationInputTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const std::string message = "addOperationInputTest: operation " + std::to_string(operation);
         validate(device, message, model, [operation](Model* model) {
@@ -467,10 +458,10 @@
 
 ///////////////////////// ADD OPERATION OUTPUT /////////////////////////
 
-static void addOperationOutputTest(const sp<IDevice>& device, const V1_0::Model& model) {
+static void addOperationOutputTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const std::string message =
-            "addOperationOutputTest: operation " + std::to_string(operation);
+                "addOperationOutputTest: operation " + std::to_string(operation);
         validate(device, message, model, [operation](Model* model) {
             uint32_t index = addOperand(model, OperandLifeTime::MODEL_OUTPUT);
             hidl_vec_push_back(&model->operations[operation].outputs, index);
@@ -481,7 +472,7 @@
 
 ////////////////////////// ENTRY POINT //////////////////////////////
 
-void ValidationTest::validateModel(const V1_0::Model& model) {
+void validateModel(const sp<IDevice>& device, const Model& model) {
     mutateOperandTypeTest(device, model);
     mutateOperandRankTest(device, model);
     mutateOperandScaleTest(device, model);
@@ -498,9 +489,4 @@
     addOperationOutputTest(device, model);
 }
 
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_0
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::neuralnetworks::V1_0::vts::functional
diff --git a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
index f0c93b7..05eefd1 100644
--- a/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.0/vts/functional/ValidateRequest.cpp
@@ -16,28 +16,13 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
+#include "1.0/Callbacks.h"
+#include "GeneratedTestHarness.h"
 #include "VtsHalNeuralnetworks.h"
 
-#include "Callbacks.h"
-#include "TestHarness.h"
-#include "Utils.h"
+namespace android::hardware::neuralnetworks::V1_0::vts::functional {
 
-#include <android-base/logging.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
-
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hidl::memory::V1_0::IMemory;
-using test_helper::for_all;
-using test_helper::MixedTyped;
-using test_helper::MixedTypedExample;
+using implementation::ExecutionCallback;
 
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
@@ -51,7 +36,6 @@
     SCOPED_TRACE(message + " [execute]");
 
     sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-    ASSERT_NE(nullptr, executionCallback.get());
     Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
     ASSERT_TRUE(executeLaunchStatus.isOk());
     ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
@@ -103,104 +87,9 @@
 
 ///////////////////////////// ENTRY POINT //////////////////////////////////
 
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples) {
-    const uint32_t INPUT = 0;
-    const uint32_t OUTPUT = 1;
-
-    std::vector<Request> requests;
-
-    for (const MixedTypedExample& example : examples) {
-        const MixedTyped& inputs = example.operands.first;
-        const MixedTyped& outputs = example.operands.second;
-
-        std::vector<RequestArgument> inputs_info, outputs_info;
-        uint32_t inputSize = 0, outputSize = 0;
-
-        // This function only partially specifies the metadata (vector of RequestArguments).
-        // The contents are copied over below.
-        for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
-            if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
-            RequestArgument arg = {
-                .location = {.poolIndex = INPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
-                .dimensions = {},
-            };
-            RequestArgument arg_empty = {
-                .hasNoValue = true,
-            };
-            inputs_info[index] = s ? arg : arg_empty;
-            inputSize += s;
-        });
-        // Compute offset for inputs 1 and so on
-        {
-            size_t offset = 0;
-            for (auto& i : inputs_info) {
-                if (!i.hasNoValue) i.location.offset = offset;
-                offset += i.location.length;
-            }
-        }
-
-        // Go through all outputs, initialize RequestArgument descriptors
-        for_all(outputs, [&outputs_info, &outputSize](int index, auto, auto s) {
-            if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
-            RequestArgument arg = {
-                .location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
-                .dimensions = {},
-            };
-            outputs_info[index] = arg;
-            outputSize += s;
-        });
-        // Compute offset for outputs 1 and so on
-        {
-            size_t offset = 0;
-            for (auto& i : outputs_info) {
-                i.location.offset = offset;
-                offset += i.location.length;
-            }
-        }
-        std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
-                                          nn::allocateSharedMemory(outputSize)};
-        if (pools[INPUT].size() == 0 || pools[OUTPUT].size() == 0) {
-            return {};
-        }
-
-        // map pool
-        sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
-        if (inputMemory == nullptr) {
-            return {};
-        }
-        char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
-        if (inputPtr == nullptr) {
-            return {};
-        }
-
-        // initialize pool
-        inputMemory->update();
-        for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) {
-            char* begin = (char*)p;
-            char* end = begin + s;
-            // TODO: handle more than one input
-            std::copy(begin, end, inputPtr + inputs_info[index].location.offset);
-        });
-        inputMemory->commit();
-
-        requests.push_back({.inputs = inputs_info, .outputs = outputs_info, .pools = pools});
-    }
-
-    return requests;
+void validateRequest(const sp<IPreparedModel>& preparedModel, const Request& request) {
+    removeInputTest(preparedModel, request);
+    removeOutputTest(preparedModel, request);
 }
 
-void ValidationTest::validateRequests(const sp<IPreparedModel>& preparedModel,
-                                      const std::vector<Request>& requests) {
-    // validate each request
-    for (const Request& request : requests) {
-        removeInputTest(preparedModel, request);
-        removeOutputTest(preparedModel, request);
-    }
-}
-
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_0
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::neuralnetworks::V1_0::vts::functional
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
index aee2f85..cb22250 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.cpp
@@ -17,45 +17,45 @@
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
 #include "VtsHalNeuralnetworks.h"
+#include "1.0/Callbacks.h"
+#include "GeneratedTestHarness.h"
+#include "TestHarness.h"
 
 #include <android-base/logging.h>
+#include <hidl/ServiceManagement.h>
+#include <string>
+#include <utility>
 
-#include "Callbacks.h"
+namespace android::hardware::neuralnetworks::V1_0::vts::functional {
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
+using implementation::PreparedModelCallback;
 
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
-
-static void createPreparedModel(const sp<IDevice>& device, const V1_0::Model& model,
-                                sp<IPreparedModel>* preparedModel) {
+void createPreparedModel(const sp<IDevice>& device, const Model& model,
+                         sp<IPreparedModel>* preparedModel) {
     ASSERT_NE(nullptr, preparedModel);
+    *preparedModel = nullptr;
 
     // see if service can handle model
     bool fullySupportsModel = false;
-    Return<void> supportedOpsLaunchStatus = device->getSupportedOperations(
+    const Return<void> supportedCall = device->getSupportedOperations(
             model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
                 ASSERT_EQ(ErrorStatus::NONE, status);
                 ASSERT_NE(0ul, supported.size());
                 fullySupportsModel = std::all_of(supported.begin(), supported.end(),
                                                  [](bool valid) { return valid; });
             });
-    ASSERT_TRUE(supportedOpsLaunchStatus.isOk());
+    ASSERT_TRUE(supportedCall.isOk());
 
     // launch prepare model
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel(model, preparedModelCallback);
+    const sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    const Return<ErrorStatus> prepareLaunchStatus =
+            device->prepareModel(model, preparedModelCallback);
     ASSERT_TRUE(prepareLaunchStatus.isOk());
     ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
 
     // retrieve prepared model
     preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    const ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
     *preparedModel = preparedModelCallback->getPreparedModel();
 
     // The getSupportedOperations call returns a list of operations that are
@@ -67,99 +67,73 @@
     // can continue.
     if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
         ASSERT_EQ(nullptr, preparedModel->get());
-        LOG(INFO) << "NN VTS: Unable to test Request validation because vendor service cannot "
-                     "prepare model that it does not support.";
-        std::cout << "[          ]   Unable to test Request validation because vendor service "
-                     "cannot prepare model that it does not support."
+        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot prepare "
+                     "model that it does not support.";
+        std::cout << "[          ]   Early termination of test because vendor service cannot "
+                     "prepare model that it does not support."
                   << std::endl;
-        return;
+        GTEST_SKIP();
     }
     ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus);
     ASSERT_NE(nullptr, preparedModel->get());
 }
 
-// A class for test environment setup
-NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {}
-
-NeuralnetworksHidlEnvironment::~NeuralnetworksHidlEnvironment() {}
-
-NeuralnetworksHidlEnvironment* NeuralnetworksHidlEnvironment::getInstance() {
-    // This has to return a "new" object because it is freed inside
-    // ::testing::AddGlobalTestEnvironment when the gtest is being torn down
-    static NeuralnetworksHidlEnvironment* instance = new NeuralnetworksHidlEnvironment();
-    return instance;
-}
-
-void NeuralnetworksHidlEnvironment::registerTestServices() {
-    registerTestService<IDevice>();
-}
-
-// The main test class for NEURALNETWORK HIDL HAL.
-NeuralnetworksHidlTest::NeuralnetworksHidlTest() {}
-
-NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {}
-
 void NeuralnetworksHidlTest::SetUp() {
-    ::testing::VtsHalHidlTargetTestBase::SetUp();
-    device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
-            NeuralnetworksHidlEnvironment::getInstance());
-
-#ifdef PRESUBMIT_NOT_VTS
-    const std::string name =
-            NeuralnetworksHidlEnvironment::getInstance()->getServiceName<IDevice>();
-    const std::string sampleDriver = "sample-";
-    if (device == nullptr && name.substr(0, sampleDriver.size()) == sampleDriver) {
-        GTEST_SKIP();
-    }
-#endif  // PRESUBMIT_NOT_VTS
-
-    ASSERT_NE(nullptr, device.get());
+    testing::TestWithParam<NeuralnetworksHidlTestParam>::SetUp();
+    ASSERT_NE(kDevice, nullptr);
 }
 
-void NeuralnetworksHidlTest::TearDown() {
-    device = nullptr;
-    ::testing::VtsHalHidlTargetTestBase::TearDown();
+static NamedDevice makeNamedDevice(const std::string& name) {
+    return {name, IDevice::getService(name)};
 }
 
-void ValidationTest::validateEverything(const Model& model, const std::vector<Request>& requests) {
-    validateModel(model);
+static std::vector<NamedDevice> getNamedDevicesImpl() {
+    // Retrieves the name of all service instances that implement IDevice,
+    // including any Lazy HAL instances.
+    const std::vector<std::string> names = hardware::getAllHalInstanceNames(IDevice::descriptor);
 
-    // create IPreparedModel
+    // Get a handle to each device and pair it with its name.
+    std::vector<NamedDevice> namedDevices;
+    namedDevices.reserve(names.size());
+    std::transform(names.begin(), names.end(), std::back_inserter(namedDevices), makeNamedDevice);
+    return namedDevices;
+}
+
+const std::vector<NamedDevice>& getNamedDevices() {
+    const static std::vector<NamedDevice> devices = getNamedDevicesImpl();
+    return devices;
+}
+
+std::string printNeuralnetworksHidlTest(
+        const testing::TestParamInfo<NeuralnetworksHidlTestParam>& info) {
+    return gtestCompliantName(getName(info.param));
+}
+
+INSTANTIATE_DEVICE_TEST(NeuralnetworksHidlTest);
+
+// Forward declaration from ValidateModel.cpp
+void validateModel(const sp<IDevice>& device, const Model& model);
+// Forward declaration from ValidateRequest.cpp
+void validateRequest(const sp<IPreparedModel>& preparedModel, const Request& request);
+
+void validateEverything(const sp<IDevice>& device, const Model& model, const Request& request) {
+    validateModel(device, model);
+
+    // Create IPreparedModel.
     sp<IPreparedModel> preparedModel;
-    ASSERT_NO_FATAL_FAILURE(createPreparedModel(device, model, &preparedModel));
-    if (preparedModel == nullptr) {
-        return;
-    }
+    createPreparedModel(device, model, &preparedModel);
+    if (preparedModel == nullptr) return;
 
-    validateRequests(preparedModel, requests);
+    validateRequest(preparedModel, request);
 }
 
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_0
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
-
-namespace android::hardware::neuralnetworks::V1_0 {
-
-::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus) {
-    return os << toString(errorStatus);
+TEST_P(ValidationTest, Test) {
+    const Model model = createModel(kTestModel);
+    const Request request = createRequest(kTestModel);
+    ASSERT_FALSE(kTestModel.expectFailure);
+    validateEverything(kDevice, model, request);
 }
 
-::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus) {
-    return os << toString(deviceStatus);
-}
+INSTANTIATE_GENERATED_TEST(ValidationTest, [](const test_helper::TestModel&) { return true; });
 
-}  // namespace android::hardware::neuralnetworks::V1_0
-
-using android::hardware::neuralnetworks::V1_0::vts::functional::NeuralnetworksHidlEnvironment;
-
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(NeuralnetworksHidlEnvironment::getInstance());
-    ::testing::InitGoogleTest(&argc, argv);
-    NeuralnetworksHidlEnvironment::getInstance()->init(&argc, argv);
-
-    int status = RUN_ALL_TESTS();
-    return status;
-}
+}  // namespace android::hardware::neuralnetworks::V1_0::vts::functional
diff --git a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
index 22285be..17f4613 100644
--- a/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.0/vts/functional/VtsHalNeuralnetworks.h
@@ -14,79 +14,42 @@
  * limitations under the License.
  */
 
-#ifndef VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H
-#define VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_0_VTS_HAL_NEURALNETWORKS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_0_VTS_HAL_NEURALNETWORKS_H
+
+#include "1.0/Utils.h"
 
 #include <android/hardware/neuralnetworks/1.0/IDevice.h>
 #include <android/hardware/neuralnetworks/1.0/types.h>
-
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
-
-#include <android-base/macros.h>
 #include <gtest/gtest.h>
-#include <iostream>
+
 #include <vector>
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_0 {
-namespace vts {
-namespace functional {
+namespace android::hardware::neuralnetworks::V1_0::vts::functional {
 
-// A class for test environment setup
-class NeuralnetworksHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-    DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlEnvironment);
-    NeuralnetworksHidlEnvironment();
-    ~NeuralnetworksHidlEnvironment() override;
+using NamedDevice = Named<sp<IDevice>>;
+using NeuralnetworksHidlTestParam = NamedDevice;
 
-   public:
-    static NeuralnetworksHidlEnvironment* getInstance();
-    void registerTestServices() override;
-};
-
-// The main test class for NEURALNETWORKS HIDL HAL.
-class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-    DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlTest);
-
-   public:
-    NeuralnetworksHidlTest();
-    ~NeuralnetworksHidlTest() override;
+class NeuralnetworksHidlTest : public testing::TestWithParam<NeuralnetworksHidlTestParam> {
+  protected:
     void SetUp() override;
-    void TearDown() override;
-
-   protected:
-    sp<IDevice> device;
+    const sp<IDevice> kDevice = getData(GetParam());
 };
 
-// Tag for the validation tests
-class ValidationTest : public NeuralnetworksHidlTest {
-   protected:
-     void validateEverything(const Model& model, const std::vector<Request>& request);
+const std::vector<NamedDevice>& getNamedDevices();
 
-   private:
-     void validateModel(const Model& model);
-     void validateRequests(const sp<IPreparedModel>& preparedModel,
-                           const std::vector<Request>& requests);
-};
+std::string printNeuralnetworksHidlTest(
+        const testing::TestParamInfo<NeuralnetworksHidlTestParam>& info);
 
-// Tag for the generated tests
-class GeneratedTest : public NeuralnetworksHidlTest {};
+#define INSTANTIATE_DEVICE_TEST(TestSuite)                                                 \
+    INSTANTIATE_TEST_SUITE_P(PerInstance, TestSuite, testing::ValuesIn(getNamedDevices()), \
+                             printNeuralnetworksHidlTest)
 
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_0
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
+// Create an IPreparedModel object. If the model cannot be prepared,
+// "preparedModel" will be nullptr instead.
+void createPreparedModel(const sp<IDevice>& device, const Model& model,
+                         sp<IPreparedModel>* preparedModel);
 
-namespace android::hardware::neuralnetworks::V1_0 {
+}  // namespace android::hardware::neuralnetworks::V1_0::vts::functional
 
-// pretty-print values for error messages
-::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus);
-::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus);
-
-}  // namespace android::hardware::neuralnetworks::V1_0
-
-#endif  // VTS_HAL_NEURALNETWORKS_V1_0_TARGET_TESTS_H
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_0_VTS_HAL_NEURALNETWORKS_H
diff --git a/neuralnetworks/1.0/vts/functional/include/1.0/Callbacks.h b/neuralnetworks/1.0/vts/functional/include/1.0/Callbacks.h
new file mode 100644
index 0000000..820bb10
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/include/1.0/Callbacks.h
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_0_CALLBACKS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_0_CALLBACKS_H
+
+#include <android-base/thread_annotations.h>
+#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
+#include <hidl/Status.h>
+#include <condition_variable>
+#include <mutex>
+
+/*
+ * The Callback classes are used internally by the NeuralNetworks runtime to
+ * synchronize between different threads. An asynchronous task is launched
+ * paired with a callback object. When a client thread requires the output being
+ * generated by the asynchronous task, the client thread can wait for the result
+ * and be blocked until it has completed. Any wait may safely be called
+ * concurrently, even on the same callback object. When the asynchronous task
+ * has finished its workload, it must immediately call "notify". If the
+ * asynchronous task has failed to launch, the function that tried to launch the
+ * asynchronous task must immediately call "notify". This "notify" call
+ * awakens any client threads waiting on the callback object.
+ *
+ * These classes exist to enable synchronization across HIDL. When
+ * synchronization is only required in the same process, consider using
+ * std::future, std::mutex, std::condition_variable, or std::experimental::latch
+ * instead.
+ */
+
+namespace android::hardware::neuralnetworks::V1_0::implementation {
+
+/**
+ * The PreparedModelCallback class is used to receive the error status of
+ * preparing a model as well as the prepared model from a task executing
+ * asynchronously with respect to the runtime. If a calling thread calls wait
+ * or get* on a PreparedModelCallback object and the corresponding asynchronous
+ * task has not finished preparing the model, the calling thread will block
+ * until the asynchronous task has called notify.
+ *
+ * If the callback object is notified more than once, only the results of the
+ * first call to notify are used, and the results from subsequent calls are
+ * discarded.
+ *
+ * This callback object is passed as an argument to IDevice::prepareModel*.
+ */
+class PreparedModelCallback : public IPreparedModelCallback {
+  public:
+    /**
+     * IPreparedModelCallback::notify marks the callback object with the return
+     * status of the asynchronous model preparation along with the prepared
+     * model, and allows all prior and future wait calls on the
+     * PreparedModelCallback object to proceed.
+     *
+     * IPreparedModelCallback::notify must be called on a given
+     * PreparedModelCallback object.
+     *
+     * If the callback object is notified more than once, only the results of
+     * the first call to notify are used, and the results from subsequent calls
+     * are discarded.
+     *
+     * @param status Error status returned from asynchronously preparing the
+     *     model; will be:
+     *     - NONE if the asynchronous preparation was successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - INVALID_ARGUMENT if the input model is invalid
+     * @param preparedModel Returned model that has been prepared for execution,
+     *     nullptr if the model was unable to be prepared.
+     */
+    Return<void> notify(ErrorStatus status, const sp<IPreparedModel>& preparedModel) override;
+
+    /**
+     * PreparedModelCallback::wait blocks until notify has been called on the
+     * callback object.
+     */
+    void wait() const;
+
+    /**
+     * Retrieves the error status returned from the asynchronous task launched
+     * by IDevice::prepareModel*. If IDevice::prepareModel* has not finished
+     * asynchronously preparing the model, this call will block until the
+     * asynchronous task notifies the object.
+     *
+     * @return status Error status returned from asynchronously preparing the
+     *     model; will be:
+     *     - NONE if the asynchronous preparation was successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - INVALID_ARGUMENT if the input model is invalid
+     */
+    ErrorStatus getStatus() const;
+
+    /**
+     * Retrieves the model that has been prepared for execution from the
+     * asynchronous task launched by IDevice::prepareModel*. If
+     * IDevice::prepareModel* has not finished asynchronously preparing the
+     * model, this call will block until the asynchronous task notifies the
+     * object.
+     *
+     * @return preparedModel Returned model that has been prepared for
+     *     execution, nullptr if the model was unable to be prepared.
+     */
+    sp<IPreparedModel> getPreparedModel() const;
+
+  private:
+    mutable std::mutex mMutex;
+    mutable std::condition_variable mCondition;
+    bool mNotified GUARDED_BY(mMutex) = false;
+    ErrorStatus mErrorStatus = ErrorStatus::GENERAL_FAILURE;
+    sp<IPreparedModel> mPreparedModel;
+};
+
+/**
+ * The ExecutionCallback class is used to receive the results of the execution
+ * from a task executing asynchronously with respect to the runtime. If a
+ * calling thread calls wait or get* on a ExecutionCallback object and the
+ * corresponding asynchronous task has not finished the execution, the calling
+ * thread will block until the asynchronous task has called notify.
+ *
+ * If the callback object is notified more than once, only the results of the
+ * first call to notify are used, and the results from subsequent calls are
+ * discarded.
+ *
+ * This callback object is passed as an argument to IPreparedModel::execute*.
+ */
+class ExecutionCallback : public IExecutionCallback {
+  public:
+    /**
+     * IExecutionCallback::notify marks the callback object with the return
+     * status of the asynchronous execution that held this callback and enables
+     * all prior and future wait calls on the ExecutionCallback object to
+     * proceed.
+     *
+     * IExecutionCallback::notify must be called on a given ExecutionCallback
+     * object.
+     *
+     * If the callback object is notified more than once, only the results of
+     * the first call to notify are used, and the results from subsequent calls
+     * are discarded.
+     *
+     * @param status Error status returned from launching the asynchronous task
+     *     (if the launch fails) or from the asynchronous task itself (if the
+     *     launch succeeds). Must be:
+     *     - NONE if the asynchronous execution was successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is not large
+     *         enough to store the resultant values
+     *     - INVALID_ARGUMENT if the input request is invalid
+     */
+    Return<void> notify(ErrorStatus status) override;
+
+    /**
+     * ExecutionCallback::wait blocks until notify has been called on the
+     * callback object.
+     */
+    void wait() const;
+
+    /**
+     * Retrieves the error status returned from the asynchronous task launched
+     * by IPreparedModel::execute. If IPreparedModel::execute has not finished
+     * asynchronously executing, this call will block until the asynchronous
+     * task notifies the object.
+     *
+     * @return status Error status returned from launching the asynchronous task
+     *     (if the launch fails) or from the asynchronous task itself (if the
+     *     launch succeeds). Must be:
+     *     - NONE if the asynchronous execution was successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if the asynchronous task resulted in an unspecified
+     *         error
+     *     - OUTPUT_INSUFFICIENT_SIZE if at least one output operand buffer is
+     *         not large enough to store the corresponding output
+     *     - INVALID_ARGUMENT if one of the input arguments to prepareModel is
+     *         invalid
+     */
+    ErrorStatus getStatus() const;
+
+  private:
+    mutable std::mutex mMutex;
+    mutable std::condition_variable mCondition;
+    bool mNotified GUARDED_BY(mMutex) = false;
+    ErrorStatus mErrorStatus = ErrorStatus::GENERAL_FAILURE;
+};
+
+}  // namespace android::hardware::neuralnetworks::V1_0::implementation
+
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_0_CALLBACKS_H
diff --git a/neuralnetworks/1.0/vts/functional/include/1.0/Utils.h b/neuralnetworks/1.0/vts/functional/include/1.0/Utils.h
new file mode 100644
index 0000000..6d4534c
--- /dev/null
+++ b/neuralnetworks/1.0/vts/functional/include/1.0/Utils.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_0_UTILS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_0_UTILS_H
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <algorithm>
+#include <iosfwd>
+#include <string>
+#include <utility>
+#include <vector>
+#include "TestHarness.h"
+
+namespace android::hardware::neuralnetworks {
+
+// Create HIDL Request from the TestModel struct.
+V1_0::Request createRequest(const test_helper::TestModel& testModel);
+
+// After execution, copy out output results from the output memory pool.
+std::vector<::test_helper::TestBuffer> getOutputBuffers(const V1_0::Request& request);
+
+// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
+// so this is efficiently accomplished by moving the element to the end and
+// resizing the hidl_vec to one less.
+template <typename Type>
+inline void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
+    CHECK(vec != nullptr);
+    std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
+    vec->resize(vec->size() - 1);
+}
+
+template <typename Type>
+inline uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
+    CHECK(vec != nullptr);
+    const uint32_t index = vec->size();
+    vec->resize(index + 1);
+    (*vec)[index] = value;
+    return index;
+}
+
+template <typename Type>
+using Named = std::pair<std::string, Type>;
+
+template <typename Type>
+const std::string& getName(const Named<Type>& namedData) {
+    return namedData.first;
+}
+
+template <typename Type>
+const Type& getData(const Named<Type>& namedData) {
+    return namedData.second;
+}
+
+std::string gtestCompliantName(std::string name);
+
+}  // namespace android::hardware::neuralnetworks
+
+namespace android::hardware::neuralnetworks::V1_0 {
+
+// pretty-print values for error messages
+::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus);
+::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus);
+
+}  // namespace android::hardware::neuralnetworks::V1_0
+
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_0_UTILS_H
diff --git a/neuralnetworks/1.1/Android.bp b/neuralnetworks/1.1/Android.bp
index 1158a90..bef21c0 100644
--- a/neuralnetworks/1.1/Android.bp
+++ b/neuralnetworks/1.1/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/neuralnetworks/1.1/types.hal b/neuralnetworks/1.1/types.hal
index 73705bb..3d78fb6 100644
--- a/neuralnetworks/1.1/types.hal
+++ b/neuralnetworks/1.1/types.hal
@@ -26,7 +26,6 @@
  * The type of an operation in a model.
  */
 enum OperationType : @1.0::OperationType {
-
     /**
      * BatchToSpace for N-dimensional tensors.
      *
@@ -41,7 +40,8 @@
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
-     * Supported tensor rank: 4
+     * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+     * and Channels) data layout.
      *
      * Inputs:
      * * 0: An n-D tensor, specifying the tensor to be reshaped
@@ -51,8 +51,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 28.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     BATCH_TO_SPACE_ND = 29,
 
@@ -91,8 +91,6 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 28.
      */
     DIV = 30,
 
@@ -126,8 +124,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 28.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be same as input0.
      */
     MEAN = 31,
 
@@ -138,7 +136,8 @@
      *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT32}
-     * * {@link OperandType::TENSOR_QUANT8_ASYMM} (the pad value is undefined)
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     *   (the pad value is undefined)
      *
      * Supported tensor rank: up to 4
      *
@@ -160,11 +159,8 @@
      *      of the padding:
      *          output0.dimension[i] =
      *              padding[i, 0] + input0.dimension[i] + padding[i, 1]
-     *
-     *      NOTE: The pad value for {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM}
-     *      is undefined.
-     *
-     * Available since API level 28.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     PAD = 32,
 
@@ -182,8 +178,10 @@
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     *   (the pad value is undefined)
      *
-     * Supported tensor rank: 4
+     * Supported tensor rank: 4, with "NHWC" (i.e., Num_samples, Height, Width,
+     * and Channels) data layout.
      *
      * Inputs:
      * * 0: An n-D tensor, specifying the input.
@@ -201,8 +199,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 28.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     SPACE_TO_BATCH_ND = 33,
 
@@ -232,8 +230,8 @@
      * * 0: A tensor of the same {@link OperandType} as input0. Contains the
      *      same data as input, but has one or more dimensions of size 1
      *      removed.
-     *
-     * Available since API level 28.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     SQUEEZE = 34,
 
@@ -278,8 +276,8 @@
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0 and rank (n - k),
      *      where k is the number of bits set in shrink_axis_mask.
-     *
-     * Available since API level 28.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     STRIDED_SLICE = 35,
 
@@ -318,8 +316,6 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 28.
      */
     SUB = 36,
 
@@ -345,11 +341,10 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 28.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     TRANSPOSE = 37,
-
 };
 
 /**
diff --git a/neuralnetworks/1.1/types.t b/neuralnetworks/1.1/types.t
new file mode 100644
index 0000000..75ac2e7
--- /dev/null
+++ b/neuralnetworks/1.1/types.t
@@ -0,0 +1,158 @@
+%% template file for generating types.hal.
+%% see frameworks/ml/nn/tools/api/README.md.
+/*
+ * 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.
+ */
+
+package android.hardware.neuralnetworks@1.1;
+
+import @1.0::Operand;
+import @1.0::OperationType;
+import @1.0::PerformanceInfo;
+
+/**
+ * Operation types.
+ *
+ * The type of an operation in a model.
+ */
+enum OperationType : @1.0::OperationType {
+%insert Operation_1.1
+};
+
+/**
+ * The capabilities of a driver.
+ */
+struct Capabilities {
+    /**
+     * Driver performance when operating on float32 data.
+     */
+    PerformanceInfo float32Performance;
+
+    /**
+     * Driver performance when operating on asymmetric 8-bit quantized data.
+     */
+    PerformanceInfo quantized8Performance;
+
+    /**
+     * Driver performance when operating on float32 data but performing
+     * calculations with range and/or precision as low as that of the IEEE
+     * 754 16-bit floating-point format.
+     */
+    PerformanceInfo relaxedFloat32toFloat16Performance;
+};
+
+/**
+ * Describes one operation of the model's graph.
+ */
+struct Operation {
+    /**
+     * The operation type.
+     */
+    OperationType type;
+
+    /**
+     * Describes the table that contains the indexes of the inputs of the
+     * operation. The offset is the index in the operandIndexes table.
+     */
+    vec<uint32_t> inputs;
+
+    /**
+     * Describes the table that contains the indexes of the outputs of the
+     * operation. The offset is the index in the operandIndexes table.
+     */
+    vec<uint32_t> outputs;
+};
+
+/**
+ * A Neural Network Model.
+ *
+ * This includes not only the execution graph, but also constant data such as
+ * weights or scalars added at construction time. The only information that
+ * may not be known is the shape of the input tensors.
+ */
+struct Model {
+    /**
+     * All operands included in the model.
+     */
+    vec<Operand> operands;
+
+    /**
+     * All operations included in the model.
+     *
+     * The operations are sorted into execution order. Every operand
+     * with lifetime MODEL_OUTPUT or TEMPORARY_VARIABLE must be
+     * written before it is read.
+     */
+    vec<Operation> operations;
+
+    /**
+     * Input indexes of the model. There must be at least one.
+     *
+     * Each value corresponds to the index of the operand in "operands".
+     */
+    vec<uint32_t> inputIndexes;
+
+    /**
+     * Output indexes of the model. There must be at least one.
+     *
+     * Each value corresponds to the index of the operand in "operands".
+     */
+    vec<uint32_t> outputIndexes;
+
+    /**
+     * A byte buffer containing operand data that were copied into the model.
+     *
+     * An operand's value must be located here if and only if Operand::lifetime
+     * equals OperandLifeTime::CONSTANT_COPY.
+     */
+    vec<uint8_t> operandValues;
+
+    /**
+     * A collection of shared memory pools containing operand values.
+     *
+     * An operand's value must be located here if and only if Operand::lifetime
+     * equals OperandLifeTime::CONSTANT_REFERENCE.
+     */
+    vec<memory> pools;
+
+    /**
+     * 'true' indicates TENSOR_FLOAT32 may be calculated with range and/or
+     * precision as low as that of the IEEE 754 16-bit floating-point format.
+     * 'false' indicates TENSOR_FLOAT32 must be calculated using at least the
+     * range and precision of the IEEE 754 32-bit floating-point format.
+     */
+    bool relaxComputationFloat32toFloat16;
+};
+
+/**
+ * Execution preferences.
+ */
+enum ExecutionPreference : int32_t {
+    /**
+     * Prefer executing in a way that minimizes battery drain.
+     * This is desirable for compilations that will be executed often.
+     */
+    LOW_POWER = 0,
+    /**
+     * Prefer returning a single answer as fast as possible, even if this causes
+     * more power consumption.
+     */
+    FAST_SINGLE_ANSWER = 1,
+    /**
+     * Prefer maximizing the throughput of successive frames, for example when
+     * processing successive frames coming from the camera.
+     */
+    SUSTAINED_SPEED = 2,
+};
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index 4fbeac9..4e85355 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -14,33 +14,38 @@
 // limitations under the License.
 //
 
-// Tests for V1_0 models using the V1_1 HAL.
-cc_test {
-    name: "VtsHalNeuralnetworksV1_1CompatV1_0TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
-    srcs: [
-        "GeneratedTestsV1_0.cpp",
-    ],
-}
-
-// Tests for V1_1 models.
 cc_test {
     name: "VtsHalNeuralnetworksV1_1TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "BasicTests.cpp",
-        "GeneratedTests.cpp",
+        "TestAssertions.cpp",
+        "ValidateModel.cpp",
+        "ValidateRequest.cpp",
+        "VtsHalNeuralnetworks.cpp",
+        "GeneratedTestHarness.cpp",
     ],
-}
-
-cc_test {
-    name: "PresubmitHalNeuralnetworksV1_1TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
-    srcs: [
-        "BasicTests.cpp",
-        "GeneratedTests.cpp",
+    shared_libs: [
+        "libfmq",
+        "libnativewindow",
     ],
-    cflags: [
-        "-DPRESUBMIT_NOT_VTS",
+    static_libs: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hardware.neuralnetworks@1.1",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libgmock",
+        "libhidlmemory",
+        "libneuralnetworks_generated_test_harness",
+        "libneuralnetworks_utils",
+        "VtsHalNeuralNetworksV1_0_utils",
     ],
+    whole_static_libs: [
+        "neuralnetworks_generated_V1_0_example",
+        "neuralnetworks_generated_V1_1_example",
+    ],
+    header_libs: [
+        "libneuralnetworks_headers",
+    ],
+    test_suites: ["general-tests"],
 }
diff --git a/neuralnetworks/1.1/vts/functional/BasicTests.cpp b/neuralnetworks/1.1/vts/functional/BasicTests.cpp
index ed59a2d..44836f0 100644
--- a/neuralnetworks/1.1/vts/functional/BasicTests.cpp
+++ b/neuralnetworks/1.1/vts/functional/BasicTests.cpp
@@ -18,41 +18,34 @@
 
 #include "VtsHalNeuralnetworks.h"
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-namespace vts {
-namespace functional {
+namespace android::hardware::neuralnetworks::V1_1::vts::functional {
+
+using V1_0::DeviceStatus;
+using V1_0::ErrorStatus;
 
 // create device test
-TEST_F(NeuralnetworksHidlTest, CreateDevice) {}
+TEST_P(NeuralnetworksHidlTest, CreateDevice) {}
 
 // status test
-TEST_F(NeuralnetworksHidlTest, StatusTest) {
-    Return<DeviceStatus> status = device->getStatus();
+TEST_P(NeuralnetworksHidlTest, StatusTest) {
+    Return<DeviceStatus> status = kDevice->getStatus();
     ASSERT_TRUE(status.isOk());
     EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status));
 }
 
 // initialization
-TEST_F(NeuralnetworksHidlTest, GetCapabilitiesTest) {
+TEST_P(NeuralnetworksHidlTest, GetCapabilitiesTest) {
     Return<void> ret =
-        device->getCapabilities_1_1([](ErrorStatus status, const Capabilities& capabilities) {
-            EXPECT_EQ(ErrorStatus::NONE, status);
-            EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
-            EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
-            EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
-            EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
-            EXPECT_LT(0.0f, capabilities.relaxedFloat32toFloat16Performance.execTime);
-            EXPECT_LT(0.0f, capabilities.relaxedFloat32toFloat16Performance.powerUsage);
-        });
+            kDevice->getCapabilities_1_1([](ErrorStatus status, const Capabilities& capabilities) {
+                EXPECT_EQ(ErrorStatus::NONE, status);
+                EXPECT_LT(0.0f, capabilities.float32Performance.execTime);
+                EXPECT_LT(0.0f, capabilities.float32Performance.powerUsage);
+                EXPECT_LT(0.0f, capabilities.quantized8Performance.execTime);
+                EXPECT_LT(0.0f, capabilities.quantized8Performance.powerUsage);
+                EXPECT_LT(0.0f, capabilities.relaxedFloat32toFloat16Performance.execTime);
+                EXPECT_LT(0.0f, capabilities.relaxedFloat32toFloat16Performance.powerUsage);
+            });
     EXPECT_TRUE(ret.isOk());
 }
 
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_1
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::neuralnetworks::V1_1::vts::functional
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp
new file mode 100644
index 0000000..7a929d6
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.cpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "GeneratedTestHarness.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/IDevice.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+#include <gtest/gtest.h>
+#include <iostream>
+
+#include "1.0/Callbacks.h"
+#include "1.0/Utils.h"
+#include "MemoryUtils.h"
+#include "TestHarness.h"
+#include "VtsHalNeuralnetworks.h"
+
+namespace android::hardware::neuralnetworks::V1_1::vts::functional {
+
+using namespace test_helper;
+using hidl::memory::V1_0::IMemory;
+using V1_0::DataLocation;
+using V1_0::ErrorStatus;
+using V1_0::IPreparedModel;
+using V1_0::Operand;
+using V1_0::OperandLifeTime;
+using V1_0::OperandType;
+using V1_0::Request;
+using V1_0::implementation::ExecutionCallback;
+using V1_0::implementation::PreparedModelCallback;
+
+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];
+
+        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();
+        } 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();
+        }
+
+        operands[i] = {.type = static_cast<OperandType>(op.type),
+                       .dimensions = op.dimensions,
+                       .numberOfConsumers = op.numberOfConsumers,
+                       .scale = op.scale,
+                       .zeroPoint = op.zeroPoint,
+                       .lifetime = static_cast<OperandLifeTime>(op.lifetime),
+                       .location = loc};
+    }
+
+    // Model operations.
+    hidl_vec<Operation> operations(testModel.operations.size());
+    std::transform(testModel.operations.begin(), testModel.operations.end(), operations.begin(),
+                   [](const TestOperation& op) -> Operation {
+                       return {.type = static_cast<OperationType>(op.type),
+                               .inputs = op.inputs,
+                               .outputs = op.outputs};
+                   });
+
+    // 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);
+        }
+    }
+
+    // Shared memory.
+    hidl_vec<hidl_memory> pools;
+    if (constRefSize > 0) {
+        hidl_vec_push_back(&pools, nn::allocateSharedMemory(constRefSize));
+        CHECK_NE(pools[0].size(), 0u);
+
+        // load data
+        sp<IMemory> mappedMemory = mapMemory(pools[0]);
+        CHECK(mappedMemory.get() != nullptr);
+        uint8_t* mappedPtr =
+                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);
+            }
+        }
+    }
+
+    return {.operands = std::move(operands),
+            .operations = std::move(operations),
+            .inputIndexes = testModel.inputIndexes,
+            .outputIndexes = testModel.outputIndexes,
+            .operandValues = std::move(operandValues),
+            .pools = std::move(pools),
+            .relaxComputationFloat32toFloat16 = testModel.isRelaxed};
+}
+
+// Top level driver for models and examples generated by test_generator.py
+// Test driver for those generated from ml/nn/runtime/test/spec
+void Execute(const sp<IDevice>& device, const TestModel& testModel) {
+    const Model model = createModel(testModel);
+    const Request request = createRequest(testModel);
+
+    // Create IPreparedModel.
+    sp<IPreparedModel> preparedModel;
+    createPreparedModel(device, model, &preparedModel);
+    if (preparedModel == nullptr) return;
+
+    // Launch execution.
+    sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+    Return<ErrorStatus> executionLaunchStatus = preparedModel->execute(request, executionCallback);
+    ASSERT_TRUE(executionLaunchStatus.isOk());
+    EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
+
+    // Retrieve execution status.
+    executionCallback->wait();
+    ASSERT_EQ(ErrorStatus::NONE, executionCallback->getStatus());
+
+    // Retrieve execution results.
+    const std::vector<TestBuffer> outputs = getOutputBuffers(request);
+
+    // We want "close-enough" results.
+    checkResults(testModel, outputs);
+}
+
+void GeneratedTestBase::SetUp() {
+    testing::TestWithParam<GeneratedTestParam>::SetUp();
+    ASSERT_NE(kDevice, nullptr);
+}
+
+std::vector<NamedModel> getNamedModels(const FilterFn& filter) {
+    return TestModelManager::get().getTestModels(filter);
+}
+
+std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info) {
+    const auto& [namedDevice, namedModel] = info.param;
+    return gtestCompliantName(getName(namedDevice) + "_" + getName(namedModel));
+}
+
+// Tag for the generated tests
+class GeneratedTest : public GeneratedTestBase {};
+
+TEST_P(GeneratedTest, Test) {
+    Execute(kDevice, kTestModel);
+}
+
+INSTANTIATE_GENERATED_TEST(GeneratedTest,
+                           [](const TestModel& testModel) { return !testModel.expectFailure; });
+
+}  // namespace android::hardware::neuralnetworks::V1_1::vts::functional
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h
new file mode 100644
index 0000000..cf449ea
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/GeneratedTestHarness.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_1_GENERATED_TEST_HARNESS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_1_GENERATED_TEST_HARNESS_H
+
+#include <android/hardware/neuralnetworks/1.1/IDevice.h>
+#include "1.0/Utils.h"
+#include "TestHarness.h"
+#include "VtsHalNeuralnetworks.h"
+
+namespace android::hardware::neuralnetworks::V1_1::vts::functional {
+
+using NamedModel = Named<const test_helper::TestModel*>;
+using GeneratedTestParam = std::tuple<NamedDevice, NamedModel>;
+
+class GeneratedTestBase : public testing::TestWithParam<GeneratedTestParam> {
+  protected:
+    void SetUp() override;
+    const sp<IDevice> kDevice = getData(std::get<NamedDevice>(GetParam()));
+    const test_helper::TestModel& kTestModel = *getData(std::get<NamedModel>(GetParam()));
+};
+
+using FilterFn = std::function<bool(const test_helper::TestModel&)>;
+std::vector<NamedModel> getNamedModels(const FilterFn& filter);
+
+std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info);
+
+#define INSTANTIATE_GENERATED_TEST(TestSuite, filter)                                     \
+    INSTANTIATE_TEST_SUITE_P(TestGenerated, TestSuite,                                    \
+                             testing::Combine(testing::ValuesIn(getNamedDevices()),       \
+                                              testing::ValuesIn(getNamedModels(filter))), \
+                             printGeneratedTest)
+
+// Tag for the validation tests, instantiated in VtsHalNeuralnetworks.cpp.
+// TODO: Clean up the hierarchy for ValidationTest.
+class ValidationTest : public GeneratedTestBase {};
+
+Model createModel(const test_helper::TestModel& testModel);
+
+}  // namespace android::hardware::neuralnetworks::V1_1::vts::functional
+
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_1_GENERATED_TEST_HARNESS_H
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
deleted file mode 100644
index 4db1276..0000000
--- a/neuralnetworks/1.1/vts/functional/GeneratedTests.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "neuralnetworks_hidl_hal_test"
-
-#include "VtsHalNeuralnetworks.h"
-
-#include "Callbacks.h"
-#include "GeneratedTestHarness.h"
-#include "TestHarness.h"
-#include "Utils.h"
-
-#include <android-base/logging.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-namespace vts {
-namespace functional {
-
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
-using ::android::nn::allocateSharedMemory;
-using ::test_helper::MixedTypedExample;
-
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
-
-// in frameworks/ml/nn/runtime/tests/generated/
-#include "all_generated_V1_1_vts_tests.cpp"
-
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_1
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
diff --git a/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp b/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp
deleted file mode 100644
index e67ef8e..0000000
--- a/neuralnetworks/1.1/vts/functional/GeneratedTestsV1_0.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "neuralnetworks_hidl_hal_test"
-
-#include "VtsHalNeuralnetworks.h"
-
-#include "Callbacks.h"
-#include "GeneratedTestHarness.h"
-#include "TestHarness.h"
-#include "Utils.h"
-
-#include <android-base/logging.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-namespace vts {
-namespace functional {
-
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
-using ::android::nn::allocateSharedMemory;
-using ::test_helper::MixedTypedExample;
-
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
-
-// in frameworks/ml/nn/runtime/tests/generated/
-#include "all_generated_V1_0_vts_tests.cpp"
-
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_1
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
diff --git a/neuralnetworks/1.1/vts/functional/TestAssertions.cpp b/neuralnetworks/1.1/vts/functional/TestAssertions.cpp
new file mode 100644
index 0000000..f4a49bc
--- /dev/null
+++ b/neuralnetworks/1.1/vts/functional/TestAssertions.cpp
@@ -0,0 +1,69 @@
+/*
+ * 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/hardware/neuralnetworks/1.1/types.h>
+#include "TestHarness.h"
+
+namespace android::hardware::neuralnetworks::V1_1 {
+
+// Make sure that the HIDL enums are compatible with the values defined in
+// frameworks/ml/nn/tools/test_generator/test_harness/include/TestHarness.h.
+using namespace test_helper;
+#define CHECK_TEST_ENUM(EnumType, enumValue) \
+    static_assert(static_cast<EnumType>(Test##EnumType::enumValue) == EnumType::enumValue)
+
+CHECK_TEST_ENUM(OperationType, ADD);
+CHECK_TEST_ENUM(OperationType, AVERAGE_POOL_2D);
+CHECK_TEST_ENUM(OperationType, CONCATENATION);
+CHECK_TEST_ENUM(OperationType, CONV_2D);
+CHECK_TEST_ENUM(OperationType, DEPTHWISE_CONV_2D);
+CHECK_TEST_ENUM(OperationType, DEPTH_TO_SPACE);
+CHECK_TEST_ENUM(OperationType, DEQUANTIZE);
+CHECK_TEST_ENUM(OperationType, EMBEDDING_LOOKUP);
+CHECK_TEST_ENUM(OperationType, FLOOR);
+CHECK_TEST_ENUM(OperationType, FULLY_CONNECTED);
+CHECK_TEST_ENUM(OperationType, HASHTABLE_LOOKUP);
+CHECK_TEST_ENUM(OperationType, L2_NORMALIZATION);
+CHECK_TEST_ENUM(OperationType, L2_POOL_2D);
+CHECK_TEST_ENUM(OperationType, LOCAL_RESPONSE_NORMALIZATION);
+CHECK_TEST_ENUM(OperationType, LOGISTIC);
+CHECK_TEST_ENUM(OperationType, LSH_PROJECTION);
+CHECK_TEST_ENUM(OperationType, LSTM);
+CHECK_TEST_ENUM(OperationType, MAX_POOL_2D);
+CHECK_TEST_ENUM(OperationType, MUL);
+CHECK_TEST_ENUM(OperationType, RELU);
+CHECK_TEST_ENUM(OperationType, RELU1);
+CHECK_TEST_ENUM(OperationType, RELU6);
+CHECK_TEST_ENUM(OperationType, RESHAPE);
+CHECK_TEST_ENUM(OperationType, RESIZE_BILINEAR);
+CHECK_TEST_ENUM(OperationType, RNN);
+CHECK_TEST_ENUM(OperationType, SOFTMAX);
+CHECK_TEST_ENUM(OperationType, SPACE_TO_DEPTH);
+CHECK_TEST_ENUM(OperationType, SVDF);
+CHECK_TEST_ENUM(OperationType, TANH);
+CHECK_TEST_ENUM(OperationType, BATCH_TO_SPACE_ND);
+CHECK_TEST_ENUM(OperationType, DIV);
+CHECK_TEST_ENUM(OperationType, MEAN);
+CHECK_TEST_ENUM(OperationType, PAD);
+CHECK_TEST_ENUM(OperationType, SPACE_TO_BATCH_ND);
+CHECK_TEST_ENUM(OperationType, SQUEEZE);
+CHECK_TEST_ENUM(OperationType, STRIDED_SLICE);
+CHECK_TEST_ENUM(OperationType, SUB);
+CHECK_TEST_ENUM(OperationType, TRANSPOSE);
+
+#undef CHECK_TEST_ENUM
+
+}  // namespace android::hardware::neuralnetworks::V1_1
diff --git a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
index b35a901..0629a1e 100644
--- a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
@@ -16,47 +16,40 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
+#include "1.0/Callbacks.h"
+#include "1.0/Utils.h"
+#include "GeneratedTestHarness.h"
 #include "VtsHalNeuralnetworks.h"
 
-#include "Callbacks.h"
+namespace android::hardware::neuralnetworks::V1_1::vts::functional {
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-
+using V1_0::ErrorStatus;
 using V1_0::IPreparedModel;
 using V1_0::Operand;
 using V1_0::OperandLifeTime;
 using V1_0::OperandType;
-
-namespace vts {
-namespace functional {
-
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
+using V1_0::implementation::PreparedModelCallback;
 
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
 static void validateGetSupportedOperations(const sp<IDevice>& device, const std::string& message,
-                                           const V1_1::Model& model) {
+                                           const Model& model) {
     SCOPED_TRACE(message + " [getSupportedOperations_1_1]");
 
-    Return<void> ret =
-        device->getSupportedOperations_1_1(model, [&](ErrorStatus status, const hidl_vec<bool>&) {
-            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
-        });
+    Return<void> ret = device->getSupportedOperations_1_1(
+            model, [&](ErrorStatus status, const hidl_vec<bool>&) {
+                EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
+            });
     EXPECT_TRUE(ret.isOk());
 }
 
 static void validatePrepareModel(const sp<IDevice>& device, const std::string& message,
-                                 const V1_1::Model& model, ExecutionPreference preference) {
+                                 const Model& model, ExecutionPreference preference) {
     SCOPED_TRACE(message + " [prepareModel_1_1]");
 
     sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
     Return<ErrorStatus> prepareLaunchStatus =
-        device->prepareModel_1_1(model, preference, preparedModelCallback);
+            device->prepareModel_1_1(model, preference, preparedModelCallback);
     ASSERT_TRUE(prepareLaunchStatus.isOk());
     ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
 
@@ -77,7 +70,7 @@
 // mutation to it to invalidate the model, then pass it to interface calls that
 // use the model. Note that the model here is passed by value, and any mutation
 // to the model does not leave this function.
-static void validate(const sp<IDevice>& device, const std::string& message, V1_1::Model model,
+static void validate(const sp<IDevice>& device, const std::string& message, Model model,
                      const std::function<void(Model*)>& mutation,
                      ExecutionPreference preference = ExecutionPreference::FAST_SINGLE_ANSWER) {
     mutation(&model);
@@ -87,36 +80,16 @@
     validatePrepareModel(device, message, model, preference);
 }
 
-// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
-// so this is efficiently accomplished by moving the element to the end and
-// resizing the hidl_vec to one less.
-template <typename Type>
-static void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
-    if (vec) {
-        std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
-        vec->resize(vec->size() - 1);
-    }
-}
-
-template <typename Type>
-static uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
-    // assume vec is valid
-    const uint32_t index = vec->size();
-    vec->resize(index + 1);
-    (*vec)[index] = value;
-    return index;
-}
-
 static uint32_t addOperand(Model* model) {
     return hidl_vec_push_back(&model->operands,
                               {
-                                  .type = OperandType::INT32,
-                                  .dimensions = {},
-                                  .numberOfConsumers = 0,
-                                  .scale = 0.0f,
-                                  .zeroPoint = 0,
-                                  .lifetime = OperandLifeTime::MODEL_INPUT,
-                                  .location = {.poolIndex = 0, .offset = 0, .length = 0},
+                                      .type = OperandType::INT32,
+                                      .dimensions = {},
+                                      .numberOfConsumers = 0,
+                                      .scale = 0.0f,
+                                      .zeroPoint = 0,
+                                      .lifetime = OperandLifeTime::MODEL_INPUT,
+                                      .location = {.poolIndex = 0, .offset = 0, .length = 0},
                               });
 }
 
@@ -130,13 +103,13 @@
 ///////////////////////// VALIDATE MODEL OPERAND TYPE /////////////////////////
 
 static const int32_t invalidOperandTypes[] = {
-    static_cast<int32_t>(OperandType::FLOAT32) - 1,              // lower bound fundamental
-    static_cast<int32_t>(OperandType::TENSOR_QUANT8_ASYMM) + 1,  // upper bound fundamental
-    static_cast<int32_t>(OperandType::OEM) - 1,                  // lower bound OEM
-    static_cast<int32_t>(OperandType::TENSOR_OEM_BYTE) + 1,      // upper bound OEM
+        static_cast<int32_t>(OperandType::FLOAT32) - 1,              // lower bound fundamental
+        static_cast<int32_t>(OperandType::TENSOR_QUANT8_ASYMM) + 1,  // upper bound fundamental
+        static_cast<int32_t>(OperandType::OEM) - 1,                  // lower bound OEM
+        static_cast<int32_t>(OperandType::TENSOR_OEM_BYTE) + 1,      // upper bound OEM
 };
 
-static void mutateOperandTypeTest(const sp<IDevice>& device, const V1_1::Model& model) {
+static void mutateOperandTypeTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operand = 0; operand < model.operands.size(); ++operand) {
         for (int32_t invalidOperandType : invalidOperandTypes) {
             const std::string message = "mutateOperandTypeTest: operand " +
@@ -166,7 +139,7 @@
     }
 }
 
-static void mutateOperandRankTest(const sp<IDevice>& device, const V1_1::Model& model) {
+static void mutateOperandRankTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operand = 0; operand < model.operands.size(); ++operand) {
         const uint32_t invalidRank = getInvalidRank(model.operands[operand].type);
         const std::string message = "mutateOperandRankTest: operand " + std::to_string(operand) +
@@ -195,7 +168,7 @@
     }
 }
 
-static void mutateOperandScaleTest(const sp<IDevice>& device, const V1_1::Model& model) {
+static void mutateOperandScaleTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operand = 0; operand < model.operands.size(); ++operand) {
         const float invalidScale = getInvalidScale(model.operands[operand].type);
         const std::string message = "mutateOperandScaleTest: operand " + std::to_string(operand) +
@@ -223,10 +196,10 @@
     }
 }
 
-static void mutateOperandZeroPointTest(const sp<IDevice>& device, const V1_1::Model& model) {
+static void mutateOperandZeroPointTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operand = 0; operand < model.operands.size(); ++operand) {
         const std::vector<int32_t> invalidZeroPoints =
-            getInvalidZeroPoints(model.operands[operand].type);
+                getInvalidZeroPoints(model.operands[operand].type);
         for (int32_t invalidZeroPoint : invalidZeroPoints) {
             const std::string message = "mutateOperandZeroPointTest: operand " +
                                         std::to_string(operand) + " has zero point of " +
@@ -258,18 +231,18 @@
             break;
         case OperandType::TENSOR_FLOAT32:
             newOperand.dimensions =
-                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+                    operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.scale = 0.0f;
             newOperand.zeroPoint = 0;
             break;
         case OperandType::TENSOR_INT32:
             newOperand.dimensions =
-                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+                    operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.zeroPoint = 0;
             break;
         case OperandType::TENSOR_QUANT8_ASYMM:
             newOperand.dimensions =
-                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+                    operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.scale = operand->scale != 0.0f ? operand->scale : 1.0f;
             break;
         case OperandType::OEM:
@@ -280,7 +253,7 @@
     *operand = newOperand;
 }
 
-static bool mutateOperationOperandTypeSkip(size_t operand, const V1_1::Model& model) {
+static bool mutateOperationOperandTypeSkip(size_t operand, const Model& model) {
     // LSH_PROJECTION's second argument is allowed to have any type. This is the
     // only operation that currently has a type that can be anything independent
     // from any other type. Changing the operand type to any other type will
@@ -294,7 +267,7 @@
     return false;
 }
 
-static void mutateOperationOperandTypeTest(const sp<IDevice>& device, const V1_1::Model& model) {
+static void mutateOperationOperandTypeTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operand = 0; operand < model.operands.size(); ++operand) {
         if (mutateOperationOperandTypeSkip(operand, model)) {
             continue;
@@ -319,13 +292,13 @@
 ///////////////////////// VALIDATE MODEL OPERATION TYPE /////////////////////////
 
 static const int32_t invalidOperationTypes[] = {
-    static_cast<int32_t>(OperationType::ADD) - 1,            // lower bound fundamental
-    static_cast<int32_t>(OperationType::TRANSPOSE) + 1,      // upper bound fundamental
-    static_cast<int32_t>(OperationType::OEM_OPERATION) - 1,  // lower bound OEM
-    static_cast<int32_t>(OperationType::OEM_OPERATION) + 1,  // upper bound OEM
+        static_cast<int32_t>(OperationType::ADD) - 1,            // lower bound fundamental
+        static_cast<int32_t>(OperationType::TRANSPOSE) + 1,      // upper bound fundamental
+        static_cast<int32_t>(OperationType::OEM_OPERATION) - 1,  // lower bound OEM
+        static_cast<int32_t>(OperationType::OEM_OPERATION) + 1,  // upper bound OEM
 };
 
-static void mutateOperationTypeTest(const sp<IDevice>& device, const V1_1::Model& model) {
+static void mutateOperationTypeTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         for (int32_t invalidOperationType : invalidOperationTypes) {
             const std::string message = "mutateOperationTypeTest: operation " +
@@ -333,7 +306,7 @@
                                         std::to_string(invalidOperationType);
             validate(device, message, model, [operation, invalidOperationType](Model* model) {
                 model->operations[operation].type =
-                    static_cast<OperationType>(invalidOperationType);
+                        static_cast<OperationType>(invalidOperationType);
             });
         }
     }
@@ -341,8 +314,7 @@
 
 ///////////////////////// VALIDATE MODEL OPERATION INPUT OPERAND INDEX /////////////////////////
 
-static void mutateOperationInputOperandIndexTest(const sp<IDevice>& device,
-                                                 const V1_1::Model& model) {
+static void mutateOperationInputOperandIndexTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const uint32_t invalidOperand = model.operands.size();
         for (size_t input = 0; input < model.operations[operation].inputs.size(); ++input) {
@@ -358,8 +330,7 @@
 
 ///////////////////////// VALIDATE MODEL OPERATION OUTPUT OPERAND INDEX /////////////////////////
 
-static void mutateOperationOutputOperandIndexTest(const sp<IDevice>& device,
-                                                  const V1_1::Model& model) {
+static void mutateOperationOutputOperandIndexTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const uint32_t invalidOperand = model.operands.size();
         for (size_t output = 0; output < model.operations[operation].outputs.size(); ++output) {
@@ -397,7 +368,7 @@
     removeValueAndDecrementGreaterValues(&model->outputIndexes, index);
 }
 
-static void removeOperandTest(const sp<IDevice>& device, const V1_1::Model& model) {
+static void removeOperandTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operand = 0; operand < model.operands.size(); ++operand) {
         const std::string message = "removeOperandTest: operand " + std::to_string(operand);
         validate(device, message, model,
@@ -414,7 +385,7 @@
     hidl_vec_removeAt(&model->operations, index);
 }
 
-static void removeOperationTest(const sp<IDevice>& device, const V1_1::Model& model) {
+static void removeOperationTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const std::string message = "removeOperationTest: operation " + std::to_string(operation);
         validate(device, message, model,
@@ -424,14 +395,14 @@
 
 ///////////////////////// REMOVE OPERATION INPUT /////////////////////////
 
-static void removeOperationInputTest(const sp<IDevice>& device, const V1_1::Model& model) {
+static void removeOperationInputTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         for (size_t input = 0; input < model.operations[operation].inputs.size(); ++input) {
-            const V1_1::Operation& op = model.operations[operation];
+            const Operation& op = model.operations[operation];
             // CONCATENATION has at least 2 inputs, with the last element being
             // INT32. Skip this test if removing one of CONCATENATION's
             // inputs still produces a valid model.
-            if (op.type == V1_1::OperationType::CONCATENATION && op.inputs.size() > 2 &&
+            if (op.type == OperationType::CONCATENATION && op.inputs.size() > 2 &&
                 input != op.inputs.size() - 1) {
                 continue;
             }
@@ -449,7 +420,7 @@
 
 ///////////////////////// REMOVE OPERATION OUTPUT /////////////////////////
 
-static void removeOperationOutputTest(const sp<IDevice>& device, const V1_1::Model& model) {
+static void removeOperationOutputTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         for (size_t output = 0; output < model.operations[operation].outputs.size(); ++output) {
             const std::string message = "removeOperationOutputTest: operation " +
@@ -470,7 +441,7 @@
 
 ///////////////////////// ADD OPERATION INPUT /////////////////////////
 
-static void addOperationInputTest(const sp<IDevice>& device, const V1_1::Model& model) {
+static void addOperationInputTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const std::string message = "addOperationInputTest: operation " + std::to_string(operation);
         validate(device, message, model, [operation](Model* model) {
@@ -483,10 +454,10 @@
 
 ///////////////////////// ADD OPERATION OUTPUT /////////////////////////
 
-static void addOperationOutputTest(const sp<IDevice>& device, const V1_1::Model& model) {
+static void addOperationOutputTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const std::string message =
-            "addOperationOutputTest: operation " + std::to_string(operation);
+                "addOperationOutputTest: operation " + std::to_string(operation);
         validate(device, message, model, [operation](Model* model) {
             uint32_t index = addOperand(model, OperandLifeTime::MODEL_OUTPUT);
             hidl_vec_push_back(&model->operations[operation].outputs, index);
@@ -498,22 +469,23 @@
 ///////////////////////// VALIDATE EXECUTION PREFERENCE /////////////////////////
 
 static const int32_t invalidExecutionPreferences[] = {
-    static_cast<int32_t>(ExecutionPreference::LOW_POWER) - 1,        // lower bound
-    static_cast<int32_t>(ExecutionPreference::SUSTAINED_SPEED) + 1,  // upper bound
+        static_cast<int32_t>(ExecutionPreference::LOW_POWER) - 1,        // lower bound
+        static_cast<int32_t>(ExecutionPreference::SUSTAINED_SPEED) + 1,  // upper bound
 };
 
-static void mutateExecutionPreferenceTest(const sp<IDevice>& device, const V1_1::Model& model) {
+static void mutateExecutionPreferenceTest(const sp<IDevice>& device, const Model& model) {
     for (int32_t preference : invalidExecutionPreferences) {
         const std::string message =
-            "mutateExecutionPreferenceTest: preference " + std::to_string(preference);
-        validate(device, message, model, [](Model*) {},
-                 static_cast<ExecutionPreference>(preference));
+                "mutateExecutionPreferenceTest: preference " + std::to_string(preference);
+        validate(
+                device, message, model, [](Model*) {},
+                static_cast<ExecutionPreference>(preference));
     }
 }
 
 ////////////////////////// ENTRY POINT //////////////////////////////
 
-void ValidationTest::validateModel(const V1_1::Model& model) {
+void validateModel(const sp<IDevice>& device, const Model& model) {
     mutateOperandTypeTest(device, model);
     mutateOperandRankTest(device, model);
     mutateOperandScaleTest(device, model);
@@ -531,9 +503,4 @@
     mutateExecutionPreferenceTest(device, model);
 }
 
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_1
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::neuralnetworks::V1_1::vts::functional
diff --git a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
index f4adbab..9684eb2 100644
--- a/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.1/vts/functional/ValidateRequest.cpp
@@ -16,28 +16,17 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
+#include "1.0/Callbacks.h"
+#include "1.0/Utils.h"
+#include "GeneratedTestHarness.h"
 #include "VtsHalNeuralnetworks.h"
 
-#include "Callbacks.h"
-#include "TestHarness.h"
-#include "Utils.h"
+namespace android::hardware::neuralnetworks::V1_1::vts::functional {
 
-#include <android-base/logging.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-namespace vts {
-namespace functional {
-
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hidl::memory::V1_0::IMemory;
-using test_helper::for_all;
-using test_helper::MixedTyped;
-using test_helper::MixedTypedExample;
+using V1_0::ErrorStatus;
+using V1_0::IPreparedModel;
+using V1_0::Request;
+using V1_0::implementation::ExecutionCallback;
 
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
@@ -51,7 +40,6 @@
     SCOPED_TRACE(message + " [execute]");
 
     sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-    ASSERT_NE(nullptr, executionCallback.get());
     Return<ErrorStatus> executeLaunchStatus = preparedModel->execute(request, executionCallback);
     ASSERT_TRUE(executeLaunchStatus.isOk());
     ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(executeLaunchStatus));
@@ -61,26 +49,6 @@
     ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, executionReturnStatus);
 }
 
-// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
-// so this is efficiently accomplished by moving the element to the end and
-// resizing the hidl_vec to one less.
-template <typename Type>
-static void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
-    if (vec) {
-        std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
-        vec->resize(vec->size() - 1);
-    }
-}
-
-template <typename Type>
-static uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
-    // assume vec is valid
-    const uint32_t index = vec->size();
-    vec->resize(index + 1);
-    (*vec)[index] = value;
-    return index;
-}
-
 ///////////////////////// REMOVE INPUT ////////////////////////////////////
 
 static void removeInputTest(const sp<IPreparedModel>& preparedModel, const Request& request) {
@@ -103,104 +71,9 @@
 
 ///////////////////////////// ENTRY POINT //////////////////////////////////
 
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples) {
-    const uint32_t INPUT = 0;
-    const uint32_t OUTPUT = 1;
-
-    std::vector<Request> requests;
-
-    for (auto& example : examples) {
-        const MixedTyped& inputs = example.operands.first;
-        const MixedTyped& outputs = example.operands.second;
-
-        std::vector<RequestArgument> inputs_info, outputs_info;
-        uint32_t inputSize = 0, outputSize = 0;
-
-        // This function only partially specifies the metadata (vector of RequestArguments).
-        // The contents are copied over below.
-        for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
-            if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
-            RequestArgument arg = {
-                .location = {.poolIndex = INPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
-                .dimensions = {},
-            };
-            RequestArgument arg_empty = {
-                .hasNoValue = true,
-            };
-            inputs_info[index] = s ? arg : arg_empty;
-            inputSize += s;
-        });
-        // Compute offset for inputs 1 and so on
-        {
-            size_t offset = 0;
-            for (auto& i : inputs_info) {
-                if (!i.hasNoValue) i.location.offset = offset;
-                offset += i.location.length;
-            }
-        }
-
-        // Go through all outputs, initialize RequestArgument descriptors
-        for_all(outputs, [&outputs_info, &outputSize](int index, auto, auto s) {
-            if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
-            RequestArgument arg = {
-                .location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
-                .dimensions = {},
-            };
-            outputs_info[index] = arg;
-            outputSize += s;
-        });
-        // Compute offset for outputs 1 and so on
-        {
-            size_t offset = 0;
-            for (auto& i : outputs_info) {
-                i.location.offset = offset;
-                offset += i.location.length;
-            }
-        }
-        std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
-                                          nn::allocateSharedMemory(outputSize)};
-        if (pools[INPUT].size() == 0 || pools[OUTPUT].size() == 0) {
-            return {};
-        }
-
-        // map pool
-        sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
-        if (inputMemory == nullptr) {
-            return {};
-        }
-        char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
-        if (inputPtr == nullptr) {
-            return {};
-        }
-
-        // initialize pool
-        inputMemory->update();
-        for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) {
-            char* begin = (char*)p;
-            char* end = begin + s;
-            // TODO: handle more than one input
-            std::copy(begin, end, inputPtr + inputs_info[index].location.offset);
-        });
-        inputMemory->commit();
-
-        requests.push_back({.inputs = inputs_info, .outputs = outputs_info, .pools = pools});
-    }
-
-    return requests;
+void validateRequest(const sp<IPreparedModel>& preparedModel, const Request& request) {
+    removeInputTest(preparedModel, request);
+    removeOutputTest(preparedModel, request);
 }
 
-void ValidationTest::validateRequests(const sp<IPreparedModel>& preparedModel,
-                                      const std::vector<Request>& requests) {
-    // validate each request
-    for (const Request& request : requests) {
-        removeInputTest(preparedModel, request);
-        removeOutputTest(preparedModel, request);
-    }
-}
-
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_1
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::neuralnetworks::V1_1::vts::functional
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
index 08069f2..d56d40b 100644
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.cpp
@@ -17,46 +17,48 @@
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
 #include "VtsHalNeuralnetworks.h"
-
 #include <android-base/logging.h>
+#include <hidl/ServiceManagement.h>
+#include <string>
+#include <utility>
+#include "1.0/Callbacks.h"
+#include "1.0/Utils.h"
+#include "GeneratedTestHarness.h"
+#include "TestHarness.h"
 
-#include "Callbacks.h"
+namespace android::hardware::neuralnetworks::V1_1::vts::functional {
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
-namespace vts {
-namespace functional {
+using V1_0::ErrorStatus;
+using V1_0::IPreparedModel;
+using V1_0::Request;
+using V1_0::implementation::PreparedModelCallback;
 
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
-
-static void createPreparedModel(const sp<IDevice>& device, const V1_1::Model& model,
-                                sp<IPreparedModel>* preparedModel) {
+void createPreparedModel(const sp<IDevice>& device, const Model& model,
+                         sp<IPreparedModel>* preparedModel) {
     ASSERT_NE(nullptr, preparedModel);
+    *preparedModel = nullptr;
 
     // see if service can handle model
     bool fullySupportsModel = false;
-    Return<void> supportedOpsLaunchStatus = device->getSupportedOperations_1_1(
+    const Return<void> supportedCall = device->getSupportedOperations_1_1(
             model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
                 ASSERT_EQ(ErrorStatus::NONE, status);
                 ASSERT_NE(0ul, supported.size());
                 fullySupportsModel = std::all_of(supported.begin(), supported.end(),
                                                  [](bool valid) { return valid; });
             });
-    ASSERT_TRUE(supportedOpsLaunchStatus.isOk());
+    ASSERT_TRUE(supportedCall.isOk());
 
     // launch prepare model
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_1(
+    const sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    const Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_1(
             model, ExecutionPreference::FAST_SINGLE_ANSWER, preparedModelCallback);
     ASSERT_TRUE(prepareLaunchStatus.isOk());
     ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
 
     // retrieve prepared model
     preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    const ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
     *preparedModel = preparedModelCallback->getPreparedModel();
 
     // The getSupportedOperations_1_1 call returns a list of operations that are
@@ -68,99 +70,73 @@
     // can continue.
     if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
         ASSERT_EQ(nullptr, preparedModel->get());
-        LOG(INFO) << "NN VTS: Unable to test Request validation because vendor service cannot "
-                     "prepare model that it does not support.";
-        std::cout << "[          ]   Unable to test Request validation because vendor service "
-                     "cannot prepare model that it does not support."
+        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot prepare "
+                     "model that it does not support.";
+        std::cout << "[          ]   Early termination of test because vendor service cannot "
+                     "prepare model that it does not support."
                   << std::endl;
-        return;
+        GTEST_SKIP();
     }
     ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus);
     ASSERT_NE(nullptr, preparedModel->get());
 }
 
-// A class for test environment setup
-NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {}
-
-NeuralnetworksHidlEnvironment::~NeuralnetworksHidlEnvironment() {}
-
-NeuralnetworksHidlEnvironment* NeuralnetworksHidlEnvironment::getInstance() {
-    // This has to return a "new" object because it is freed inside
-    // ::testing::AddGlobalTestEnvironment when the gtest is being torn down
-    static NeuralnetworksHidlEnvironment* instance = new NeuralnetworksHidlEnvironment();
-    return instance;
-}
-
-void NeuralnetworksHidlEnvironment::registerTestServices() {
-    registerTestService<IDevice>();
-}
-
-// The main test class for NEURALNETWORK HIDL HAL.
-NeuralnetworksHidlTest::NeuralnetworksHidlTest() {}
-
-NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {}
-
 void NeuralnetworksHidlTest::SetUp() {
-    ::testing::VtsHalHidlTargetTestBase::SetUp();
-    device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
-            NeuralnetworksHidlEnvironment::getInstance());
-
-#ifdef PRESUBMIT_NOT_VTS
-    const std::string name =
-            NeuralnetworksHidlEnvironment::getInstance()->getServiceName<IDevice>();
-    const std::string sampleDriver = "sample-";
-    if (device == nullptr && name.substr(0, sampleDriver.size()) == sampleDriver) {
-        GTEST_SKIP();
-    }
-#endif  // PRESUBMIT_NOT_VTS
-
-    ASSERT_NE(nullptr, device.get());
+    testing::TestWithParam<NeuralnetworksHidlTestParam>::SetUp();
+    ASSERT_NE(kDevice, nullptr);
 }
 
-void NeuralnetworksHidlTest::TearDown() {
-    device = nullptr;
-    ::testing::VtsHalHidlTargetTestBase::TearDown();
+static NamedDevice makeNamedDevice(const std::string& name) {
+    return {name, IDevice::getService(name)};
 }
 
-void ValidationTest::validateEverything(const Model& model, const std::vector<Request>& requests) {
-    validateModel(model);
+static std::vector<NamedDevice> getNamedDevicesImpl() {
+    // Retrieves the name of all service instances that implement IDevice,
+    // including any Lazy HAL instances.
+    const std::vector<std::string> names = hardware::getAllHalInstanceNames(IDevice::descriptor);
 
-    // create IPreparedModel
+    // Get a handle to each device and pair it with its name.
+    std::vector<NamedDevice> namedDevices;
+    namedDevices.reserve(names.size());
+    std::transform(names.begin(), names.end(), std::back_inserter(namedDevices), makeNamedDevice);
+    return namedDevices;
+}
+
+const std::vector<NamedDevice>& getNamedDevices() {
+    const static std::vector<NamedDevice> devices = getNamedDevicesImpl();
+    return devices;
+}
+
+std::string printNeuralnetworksHidlTest(
+        const testing::TestParamInfo<NeuralnetworksHidlTestParam>& info) {
+    return gtestCompliantName(getName(info.param));
+}
+
+INSTANTIATE_DEVICE_TEST(NeuralnetworksHidlTest);
+
+// Forward declaration from ValidateModel.cpp
+void validateModel(const sp<IDevice>& device, const Model& model);
+// Forward declaration from ValidateRequest.cpp
+void validateRequest(const sp<V1_0::IPreparedModel>& preparedModel, const V1_0::Request& request);
+
+void validateEverything(const sp<IDevice>& device, const Model& model, const Request& request) {
+    validateModel(device, model);
+
+    // Create IPreparedModel.
     sp<IPreparedModel> preparedModel;
-    ASSERT_NO_FATAL_FAILURE(createPreparedModel(device, model, &preparedModel));
-    if (preparedModel == nullptr) {
-        return;
-    }
+    createPreparedModel(device, model, &preparedModel);
+    if (preparedModel == nullptr) return;
 
-    validateRequests(preparedModel, requests);
+    validateRequest(preparedModel, request);
 }
 
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_1
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
-
-namespace android::hardware::neuralnetworks::V1_0 {
-
-::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus) {
-    return os << toString(errorStatus);
+TEST_P(ValidationTest, Test) {
+    const Model model = createModel(kTestModel);
+    const Request request = createRequest(kTestModel);
+    ASSERT_FALSE(kTestModel.expectFailure);
+    validateEverything(kDevice, model, request);
 }
 
-::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus) {
-    return os << toString(deviceStatus);
-}
+INSTANTIATE_GENERATED_TEST(ValidationTest, [](const test_helper::TestModel&) { return true; });
 
-}  // namespace android::hardware::neuralnetworks::V1_0
-
-using android::hardware::neuralnetworks::V1_1::vts::functional::NeuralnetworksHidlEnvironment;
-
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(NeuralnetworksHidlEnvironment::getInstance());
-    ::testing::InitGoogleTest(&argc, argv);
-    NeuralnetworksHidlEnvironment::getInstance()->init(&argc, argv);
-
-    int status = RUN_ALL_TESTS();
-    return status;
-}
+}  // namespace android::hardware::neuralnetworks::V1_1::vts::functional
diff --git a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
index f3f587b..e879d84 100644
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
@@ -14,88 +14,41 @@
  * limitations under the License.
  */
 
-#ifndef VTS_HAL_NEURALNETWORKS_V1_1_H
-#define VTS_HAL_NEURALNETWORKS_V1_1_H
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_1_VTS_HAL_NEURALNETWORKS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_1_VTS_HAL_NEURALNETWORKS_H
 
-#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
 #include <android/hardware/neuralnetworks/1.1/IDevice.h>
 #include <android/hardware/neuralnetworks/1.1/types.h>
-
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
-
-#include <android-base/macros.h>
 #include <gtest/gtest.h>
-#include <iostream>
 #include <vector>
+#include "1.0/Utils.h"
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_1 {
+namespace android::hardware::neuralnetworks::V1_1::vts::functional {
 
-using V1_0::DeviceStatus;
-using V1_0::ErrorStatus;
-using V1_0::IPreparedModel;
-using V1_0::Operand;
-using V1_0::OperandType;
-using V1_0::Request;
+using NamedDevice = Named<sp<IDevice>>;
+using NeuralnetworksHidlTestParam = NamedDevice;
 
-namespace vts {
-namespace functional {
-
-// A class for test environment setup
-class NeuralnetworksHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-    DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlEnvironment);
-    NeuralnetworksHidlEnvironment();
-    ~NeuralnetworksHidlEnvironment() override;
-
-   public:
-    static NeuralnetworksHidlEnvironment* getInstance();
-    void registerTestServices() override;
-};
-
-// The main test class for NEURALNETWORKS HIDL HAL.
-class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-    DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlTest);
-
-   public:
-    NeuralnetworksHidlTest();
-    ~NeuralnetworksHidlTest() override;
+class NeuralnetworksHidlTest : public testing::TestWithParam<NeuralnetworksHidlTestParam> {
+  protected:
     void SetUp() override;
-    void TearDown() override;
-
-   protected:
-    sp<IDevice> device;
+    const sp<IDevice> kDevice = getData(GetParam());
 };
 
-// Tag for the validation tests
-class ValidationTest : public NeuralnetworksHidlTest {
-   protected:
-     void validateEverything(const Model& model, const std::vector<Request>& request);
+const std::vector<NamedDevice>& getNamedDevices();
 
-   private:
-     void validateModel(const Model& model);
-     void validateRequests(const sp<IPreparedModel>& preparedModel,
-                           const std::vector<Request>& requests);
-};
+std::string printNeuralnetworksHidlTest(
+        const testing::TestParamInfo<NeuralnetworksHidlTestParam>& info);
 
-// Tag for the generated tests
-class GeneratedTest : public NeuralnetworksHidlTest {};
+#define INSTANTIATE_DEVICE_TEST(TestSuite)                                                 \
+    INSTANTIATE_TEST_SUITE_P(PerInstance, TestSuite, testing::ValuesIn(getNamedDevices()), \
+                             printNeuralnetworksHidlTest)
 
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_1
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
+// Create an IPreparedModel object. If the model cannot be prepared,
+// "preparedModel" will be nullptr instead.
+void createPreparedModel(const sp<IDevice>& device, const Model& model,
+                         sp<V1_0::IPreparedModel>* preparedModel);
 
-namespace android::hardware::neuralnetworks::V1_0 {
+}  // namespace android::hardware::neuralnetworks::V1_1::vts::functional
 
-// pretty-print values for error messages
-::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus);
-::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus);
-
-}  // namespace android::hardware::neuralnetworks::V1_0
-
-#endif  // VTS_HAL_NEURALNETWORKS_V1_1_H
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_1_VTS_HAL_NEURALNETWORKS_H
diff --git a/neuralnetworks/1.2/Android.bp b/neuralnetworks/1.2/Android.bp
index 085bda1..4aa90aa 100644
--- a/neuralnetworks/1.2/Android.bp
+++ b/neuralnetworks/1.2/Android.bp
@@ -23,4 +23,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal
index d83f9e6..ff20c12 100644
--- a/neuralnetworks/1.2/IDevice.hal
+++ b/neuralnetworks/1.2/IDevice.hal
@@ -64,14 +64,14 @@
      * results, the developer could choose an ACCELERATOR type device for ML
      * workloads, and reserve GPU for graphical rendering.
      *
-     * @param status Error status returned from querying the device type. Must be:
-     *               - NONE if the query was successful
-     *               - DEVICE_UNAVAILABLE if driver is offline or busy
-     *               - GENERAL_FAILURE if the query resulted in an
-     *                 unspecified error
-     * @param type The DeviceType of the device. Please note, this is not a
-     *             bitfield of DeviceTypes. Each device must only be of a
-     *             single DeviceType.
+     * @return status Error status returned from querying the device type. Must be:
+     *                - NONE if the query was successful
+     *                - DEVICE_UNAVAILABLE if driver is offline or busy
+     *                - GENERAL_FAILURE if the query resulted in an
+     *                  unspecified error
+     * @return type The DeviceType of the device. Please note, this is not a
+     *              bitfield of DeviceTypes. Each device must only be of a
+     *              single DeviceType.
      */
     getType() generates (ErrorStatus status, DeviceType type);
 
diff --git a/neuralnetworks/1.2/IPreparedModel.hal b/neuralnetworks/1.2/IPreparedModel.hal
index 5d2d80f..1445f18 100644
--- a/neuralnetworks/1.2/IPreparedModel.hal
+++ b/neuralnetworks/1.2/IPreparedModel.hal
@@ -47,11 +47,21 @@
      * execute_1_2 function. This callback must be provided with the ErrorStatus of
      * the execution.
      *
-     * If the prepared model was prepared from a model wherein all
-     * tensor operands have fully specified dimensions, and the inputs
-     * to the function are valid, then the execution should launch
-     * and complete successfully (ErrorStatus::NONE). There must be
-     * no failure unless the device itself is in a bad state.
+     * If the launch is successful, the caller must not change the content of
+     * any data object referenced by 'request' (described by the
+     * {@link @1.0::DataLocation} of a {@link @1.0::RequestArgument}) until the
+     * asynchronous task has invoked the callback object. The asynchronous task
+     * must not change the content of any of the data objects corresponding to
+     * 'request' inputs.
+     *
+     * If the prepared model was prepared from a model wherein all tensor
+     * operands have fully specified dimensions, and the inputs to the function
+     * are valid, then:
+     * - the execution should launch successfully (ErrorStatus::NONE): There
+     *   must be no failure unless the device itself is in a bad state.
+     * - if at execution time every operation's input operands have legal
+     *   values, the execution should complete successfully (ErrorStatus::NONE):
+     *   There must be no failure unless the device itself is in a bad state.
      *
      * Any number of calls to the execute, execute_1_2, and executeSynchronously
      * functions, in any combination, may be made concurrently, even on the same
@@ -90,10 +100,17 @@
      * perform the execution, and must not return until the execution is
      * complete.
      *
+     * The caller must not change the content of any data object referenced by
+     * 'request' (described by the {@link @1.0::DataLocation} of a
+     * {@link @1.0::RequestArgument}) until executeSynchronously
+     * returns. executeSynchronously must not change the content of any of the
+     * data objects corresponding to 'request' inputs.
+     *
      * If the prepared model was prepared from a model wherein all tensor
      * operands have fully specified dimensions, and the inputs to the function
-     * are valid, then the execution should complete successfully
-     * (ErrorStatus::NONE). There must be no failure unless the device itself is
+     * are valid, and at execution time every operation's input operands have
+     * legal values, then the execution should complete successfully
+     * (ErrorStatus::NONE): There must be no failure unless the device itself is
      * in a bad state.
      *
      * Any number of calls to the execute, execute_1_2, and executeSynchronously
@@ -132,17 +149,52 @@
      * Configure a Burst object used to execute multiple inferences on a
      * prepared model in rapid succession.
      *
+     * If the prepared model was prepared from a model wherein all tensor
+     * operands have fully specified dimensions, and a valid serialized Request
+     * is sent to the Burst for execution, and at execution time every
+     * operation's input operands have legal values, then the execution should
+     * complete successfully (ErrorStatus::NONE): There must be no failure
+     * unless the device itself is in a bad state.
+     *
      * @param callback A callback object used to retrieve memory resources
-     *                 corresponding to a unique identifiers ("slots").
-     * @param requestChannel Used by the client to send a serialized Request to
-     *                       the Burst for execution. requestChannel must not be
-     *                       used to pass a second Request object until a result
-     *                       has been received from resultChannel.
-     * @param resultChannel Used by the service to return the results of an
-     *                      execution to the client: the status of the execution
-     *                      and OutputShape of all output tensors. resultChannel
-     *                      must be used to return the results if a Request was
-     *                      sent through the requestChannel.
+     *                 corresponding to unique identifiers ("slots").
+     * @param requestChannel FMQ used by the client to send a serialized Request
+     *                       to the Burst for execution. The client must not
+     *                       change the content of any data object referenced by
+     *                       the Request (described by the
+     *                       {@link @1.0::DataLocation} of an
+     *                       {@link OperandInformation}) until a result has been
+     *                       received from resultChannel. Execution must not
+     *                       change the content of any of the data objects
+     *                       corresponding to Request inputs. requestChannel
+     *                       must not be used to pass a second Request object
+     *                       until a result has been received from
+     *                       resultChannel. The client must send the request
+     *                       messages to the consumer atomically by using
+     *                       MessageQueue::writeBlocking if the queue is
+     *                       blocking, or by using MessageQueue::write if the
+     *                       queue is non-blocking. When the service receives a
+     *                       packet, it must dequeue the entire packet from the
+     *                       requestChannel. The client must not send a request
+     *                       packet that exceeds the length of the FMQ.
+     * @param resultChannel FMQ used by the service to return the results of an
+     *                      execution to the client: the status of the
+     *                      execution, OutputShape of all output tensors, and
+     *                      timing information. resultChannel must be used to
+     *                      return the results if a Request was sent through the
+     *                      requestChannel. The service must send the result
+     *                      messages to the consumer atomically by using
+     *                      MessageQueue::writeBlocking if the queue is
+     *                      blocking, or by using MessageQueue::write if the
+     *                      queue is non-blocking. When the client receives a
+     *                      packet, it must dequeue the entire packet from the
+     *                      resultChannel. If the packet's length exceeds the
+     *                      size of the FMQ, the service must not send this
+     *                      result packet; instead, the service must send a
+     *                      packet consisting of the error code
+     *                      ErrorStatus::GENERAL_FAILURE, no information for the
+     *                      outputShapes, and an indication that timing
+     *                      information is unavailable.
      * @return status Error status of configuring the execution burst, must be:
      *                - NONE if the burst is successfully configured
      *                - DEVICE_UNAVAILABLE if driver is offline or busy
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index f368ce2..837ced5 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -43,8 +43,6 @@
      *
      * Values of this operand type are either true or false. A zero value
      * represents false; any other value represents true.
-     *
-     * Available since API level 29.
      */
     BOOL = 6,
     /**
@@ -55,14 +53,10 @@
      * realValue = integerValue * scale.
      *
      * scale is a 32 bit floating point with value greater than zero.
-     *
-     * Available since API level 29.
      */
     TENSOR_QUANT16_SYMM = 7,
     /**
      * A tensor of IEEE 754 16 bit floating point values.
-     *
-     * Available since API level 29.
      */
     TENSOR_FLOAT16 = 8,
     /**
@@ -70,14 +64,10 @@
      *
      * Values of this operand type are either true or false. A zero value
      * represents false; any other value represents true.
-     *
-     * Available since API level 29.
      */
     TENSOR_BOOL8 = 9,
     /**
      * An IEEE 754 16 bit floating point scalar value.
-     *
-     * Available since API level 29.
      */
     FLOAT16 = 10,
     /**
@@ -90,14 +80,13 @@
      * - scales: an array of positive 32 bit floating point values.
      * The size of the scales array must be equal to dimensions[channelDim].
      *
+     *{@link SymmPerChannelQuantParams} must hold the parameters for an Operand of this type.
      * The channel dimension of this tensor must not be unknown (dimensions[channelDim] != 0).
      *
      * The formula is:
      * realValue[..., C, ...] =
      *     integerValue[..., C, ...] * scales[C]
      * where C is an index in the Channel dimension.
-     *
-     * Available since API level 29.
      */
     TENSOR_QUANT8_SYMM_PER_CHANNEL = 11,
     /**
@@ -110,8 +99,6 @@
      *
      * The formula is:
      * real_value = (integer_value - zeroPoint) * scale.
-     *
-     * Available since API level 29.
      */
     TENSOR_QUANT16_ASYMM = 12,
     /**
@@ -122,20 +109,19 @@
      * realValue = integerValue * scale.
      *
      * scale is a 32 bit floating point with value greater than zero.
-     *
-     * Available since API level 29.
      */
     TENSOR_QUANT8_SYMM = 13,
+
     /*
-     * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to
-     * OEM operation and data types.
+     * DEPRECATED. Since HAL version 1.2, extensions are the preferred
+     * alternative to OEM operation and data types.
      *
      * OEM specific scalar value.
      * OEM                 = 10000,
      */
     /*
-     * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to
-     * OEM operation and data types.
+     * DEPRECATED. Since HAL version 1.2, extensions are the preferred
+     * alternative to OEM operation and data types.
      *
      * A tensor of OEM specific values.
      * TENSOR_OEM_BYTE     = 10001,
@@ -166,6 +152,7 @@
  * The type of an operation in a model.
  */
 enum OperationType : int32_t {
+
     /**
      * Adds two tensors, element-wise.
      *
@@ -187,12 +174,12 @@
      *     input2.dimension = {5, 4, 3, 1}
      *     output.dimension = {5, 4, 3, 2}
      *
-     * Since API level 29, generic zero-sized input tensor is supported. Zero
+     * Since HAL version 1.2, generic zero-sized input tensor is supported. Zero
      * dimension is only compatible with 0 or 1. The size of the output
      * dimension is zero if either of corresponding input dimension is zero.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
@@ -202,14 +189,16 @@
      * * 0: A tensor.
      * * 1: A tensor of the same {@link OperandType}, and compatible dimensions
      *      as input0.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scales and zeroPoint can be different from input0 scale and zeroPoint.
      * * 2: An {@link OperandType::INT32} scalar, and has to be one of the
      *      {@link FusedActivationFunc} values. Specifies the activation to
      *      invoke on the result.
      *
      * Outputs:
      * * 0: The sum, a tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      */
     ADD = @1.1::OperationType:ADD,
 
@@ -227,7 +216,7 @@
      *         ) / sum(1)
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
@@ -235,13 +224,14 @@
      * With the default data layout NHWC, the data is stored in the order of:
      * [batch, height, width, channels]. Alternatively, the data layout could
      * be NCHW, the data storage order of: [batch, channels, height, width].
+     * NCHW is supported since HAL version 1.2.
      *
      * Both explicit padding and implicit padding are supported.
      *
      * Inputs (explicit padding):
      * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
-     *      the input. Since API level 29, zero batches is supported for this
-     *      tensor.
+     *      the input.
+     *      Since HAL version 1.2, zero batches is supported for this tensor.
      * * 1: An {@link OperandType::INT32} scalar, specifying the padding on
      *      the left, in the ‘width’ dimension.
      * * 2: An {@link OperandType::INT32} scalar, specifying the padding on
@@ -263,12 +253,12 @@
      *      invoke on the result.
      * * 10: An optional {@link OperandType::BOOL} scalar, default to false.
      *       Set to true to specify NCHW data layout for input0 and output0.
-     *       Available since API level 29.
+     *       Available since HAL version 1.2.
      *
      * Inputs (implicit padding):
      * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
-     *      the input. Since API level 29, zero batches is supported for this
-     *      tensor.
+     *      the input.
+     *      Since HAL version 1.2, zero batches is supported for this tensor.
      * * 1: An {@link OperandType::INT32} scalar, specifying the implicit
      *      padding scheme, has to be one of the
      *      following values: {0 (NONE), 1 (SAME), 2 (VALID)}.
@@ -285,13 +275,13 @@
      *      invoke on the result.
      * * 7: An optional {@link OperandType::BOOL} scalar, default to false.
      *      Set to true to specify NCHW data layout for input0 and output0.
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      *
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, out_height, out_width, depth].
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     AVERAGE_POOL_2D = @1.1::OperationType:AVERAGE_POOL_2D,
 
@@ -302,33 +292,34 @@
      * dimensions except the dimension along the concatenation axis.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
-     * * {@link OperandType::TENSOR_QUANT8_ASYMM} (full support since API
-     *   level 29, see the input section)
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     *   (full support since HAL version 1.2, see the input section)
      *
      * Supported tensor rank: up to 4
      *
      * Inputs:
      * * 0 ~ n-1: The list of n input tensors, of shape
      *            [D0, D1, ..., Daxis(i), ..., Dm].
-     *            Before API level 29, all input tensors of
+     *            Before HAL version 1.2, all input tensors of
      *            {@link OperandType::TENSOR_QUANT8_ASYMM}
      *            must have the same scale and zeroPoint as the output tensor.
-     *            Since API level 29, zero-sized tensors are supported.
+     *            Since HAL version 1.2, zero-sized tensors are supported.
      * * n: An {@link OperandType::INT32} scalar, specifying the
      *      concatenation axis.
      *
      * Outputs:
      * * 0: The output, a tensor of the same {@link OperandType} as the input
      *      tensors. The output shape is [D0, D1, ..., sum(Daxis(i)), ..., Dm].
-     *
-     * Available since API level 27.
+     *      Since HAL version 1.2, for a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint values can be different from
+     *      input tensors. Before HAL version 1.2 they have to be the same as for the input tensors.
      */
     CONCATENATION = @1.1::OperationType:CONCATENATION,
 
     /**
-     * Performs an 2-D convolution operation.
+     * Performs a 2-D convolution operation.
      *
      * The CONV_2D op sweeps a 2-D filter that can mix channels together over a
      * batch of images, applying the filter to each window of each image of the
@@ -354,7 +345,7 @@
      * * * {@link OperandType::TENSOR_INT32} for bias (with scale set to
      * * * input.scale * filter.scale).
      *
-     * Available since API level 29:
+     * Available since HAL version 1.2:
      * * 16 bit floating point:
      * * * {@link OperandType::TENSOR_FLOAT16} for input, filter, output, and bias.
      *
@@ -368,27 +359,29 @@
      * With the default data layout NHWC, the data is stored in the order of:
      * [batch, height, width, channels]. Alternatively, the data layout could
      * be NCHW, the data storage order of: [batch, channels, height, width].
+     * NCHW is supported since HAL version 1.2.
      *
      * Both explicit padding and implicit padding are supported.
      *
      * Inputs (explicit padding):
      * * 0: A 4-D tensor, of shape [batches, height, width, depth_in],
-     *      specifying the input. Since API level 29, zero batches is supported
-     *      for this tensor.
+     *      specifying the input.
+     *      Since HAL version 1.2, zero batches is supported for this tensor.
      * * 1: A 4-D tensor, of shape
      *      [depth_out, filter_height, filter_width, depth_in], specifying the
-     *      filter. For tensor of type
-     *      {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} the channel
-     *      dimension (extraParams.channelQuant.channelDim) must be set to 0.
+     *      filter.
+     *      For tensor of type {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}
+     *      the channel dimension (SymmPerChannelQuantParams::channelDim)
+     *      must be set to 0.
      * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
-     *      tensor of type {@link OperandType::TENSOR_FLOAT32} or
-     *      {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same
+     *      tensor of type {@link OperandType::TENSOR_FLOAT32}
+     *      or {@link OperandType::TENSOR_FLOAT16} the bias must be of the same
      *      type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
-     *      of 0 and bias_scale == input_scale * filter_scale. For filter tensor
-     *      of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}, the bias
-     *      should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of
-     *      0 and bias_scale of 0. The actual scale of each value 'i' is equal to
+     *      of 0 and bias_scale == input_scale * filter_scale.
+     *      For filter tensor of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL},
+     *      the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0
+     *      and bias_scale of 0. The actual scale of each value 'i' is equal to
      *      bias_scale[i] = input_scale * filter_scale[i].
      * * 3: An {@link OperandType::INT32} scalar, specifying the padding on
      *      the left, in the ‘width’ dimension.
@@ -407,36 +400,37 @@
      *      invoke on the result.
      * * 10: An optional {@link OperandType::BOOL} scalar, default to false.
      *      Set to true to specify NCHW data layout for input0 and output0.
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      * * 11: An optional {@link OperandType::INT32} scalar, specifying the dilation
      *      factor for width. Defaults to 1. If set to k > 1, there will be k-1 skipped
      *      cells between each filter element on width dimension. If this input is set,
      *      input 12 (dilation factor for height) must be specified as well.
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      * * 12: An optional {@link OperandType::INT32} scalar, specifying the dilation
      *      factor for height. Defaults to 1. If set to k > 1, there will be k-1 skipped
      *      cells between each filter element on height dimension. If this input is set,
      *      input 11 (dilation factor for width) must be specified as well.
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      *
      * Inputs (implicit padding):
      * * 0: A 4-D tensor, of shape [batches, height, width, depth_in],
-     *      specifying the input. Since API level 29, zero batches is supported
-     *      for this tensor.
+     *      specifying the input.
+     *      Since HAL version 1.2, zero batches is supported for this tensor.
      * * 1: A 4-D tensor, of shape
      *      [depth_out, filter_height, filter_width, depth_in], specifying the
-     *      filter. For tensor of type
-     *      {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} the channel
-     *      dimension (extraParams.channelQuant.channelDim) must be set to 0.
+     *      filter.
+     *      For tensor of type {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}
+     *      the channel dimension (SymmPerChannelQuantParams::channelDim)
+     *      must be set to 0.
      * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
-     *      tensor of type {@link OperandType::TENSOR_FLOAT32} or
-     *      {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same
+     *      tensor of type {@link OperandType::TENSOR_FLOAT32}
+     *      or {@link OperandType::TENSOR_FLOAT16} the bias must be of the same
      *      type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
-     *      of 0 and bias_scale == input_scale * filter_scale. For filter tensor
-     *      of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}, the bias
-     *      should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of
-     *      0 and bias_scale of 0. The actual scale of each value 'i' is equal to
+     *      of 0 and bias_scale == input_scale * filter_scale.
+     *      For filter tensor of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL},
+     *      the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0
+     *      and bias_scale of 0. The actual scale of each value 'i' is equal to
      *      bias_scale[i] = input_scale * filter_scale[i].
      * * 3: An {@link OperandType::INT32} scalar, specifying the implicit
      *      padding scheme, has to be one of the
@@ -450,26 +444,23 @@
      *      invoke on the result.
      * * 7: An optional {@link OperandType::BOOL} scalar, default to false.
      *      Set to true to specify NCHW data layout for input0 and output0.
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      * * 8: An optional {@link OperandType::INT32} scalar, specifying the dilation
      *      factor for width. Defaults to 1. If set to k > 1, there will be k-1 skipped
      *      cells between each filter element on width dimension. If this input is set,
      *      input 9 (dilation factor for height) must be specified as well.
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      * * 9: An optional {@link OperandType::INT32} scalar, specifying the dilation
      *      factor for height. Defaults to 1. If set to k > 1, there will be k-1 skipped
      *      cells between each filter element on height dimension. If this input is set,
      *      input 8 (dilation factor for width) must be specified as well.
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      *
      * Outputs:
      * * 0: The output 4-D tensor, of shape
-     *      [batches, out_height, out_width, depth_out]. Before API level 29,
-     *      for output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the
-     *      following condition must be satisfied:
-     *      output_scale > input_scale * filter_scale
-     *
-     * Available since API level 27.
+     *      [batches, out_height, out_width, depth_out].
+     *      Before HAL version 1.2, for output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
+     *      the following condition must be satisfied: output_scale > input_scale * filter_scale
      */
     CONV_2D = @1.1::OperationType:CONV_2D,
 
@@ -504,7 +495,7 @@
      * * * {@link OperandType::TENSOR_INT32} for bias (with scale set to
      * * * input.scale * filter.scale).
      *
-     * Available since API level 29:
+     * Available since HAL version 1.2:
      * * 16 bit floating point:
      * * * {@link OperandType::TENSOR_FLOAT16} for input, filter, output, and bias.
      *
@@ -518,6 +509,7 @@
      * With the default data layout NHWC, the data is stored in the order of:
      * [batch, height, width, channels]. Alternatively, the data layout could
      * be NCHW, the data storage order of: [batch, channels, height, width].
+     * NCHW is supported since HAL version 1.2.
      *
      * Both explicit padding and implicit padding are supported.
      *
@@ -525,18 +517,19 @@
      * * 0: A 4-D tensor, of shape [batches, height, width, depth_in],
      *      specifying the input.
      * * 1: A 4-D tensor, of shape [1, filter_height, filter_width, depth_out],
-     *      specifying the filter. For tensor of type
-     *      {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} the channel
-     *      dimension (extraParams.channelQuant.channelDim) must be set to 3.
+     *      specifying the filter.
+     *      For tensor of type {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}
+     *      the channel dimension (SymmPerChannelQuantParams::channelDim)
+     *      must be set to 3.
      * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
-     *      tensor of type {@link OperandType::TENSOR_FLOAT32} or
-     *      {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same
+     *      tensor of type {@link OperandType::TENSOR_FLOAT32}
+     *      or {@link OperandType::TENSOR_FLOAT16} the bias must be of the same
      *      type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
-     *      of 0 and bias_scale == input_scale * filter_scale. For filter tensor
-     *      of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}, the bias
-     *      should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of
-     *      0 and bias_scale of 0. The actual scale of each value 'i' is equal to
+     *      of 0 and bias_scale == input_scale * filter_scale.
+     *      For filter tensor of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL},
+     *      the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0
+     *      and bias_scale of 0. The actual scale of each value 'i' is equal to
      *      bias_scale[i] = input_scale * filter_scale[i].
      * * 3: An {@link OperandType::INT32} scalar, specifying the padding on
      *      the left, in the ‘width’ dimension.
@@ -557,17 +550,17 @@
      *       invoke on the result.
      * * 11: An optional {@link OperandType::BOOL} scalar, default to false.
      *       Set to true to specify NCHW data layout for input0 and output0.
-     *       Available since API level 29.
+     *       Available since HAL version 1.2.
      * * 12: An optional {@link OperandType::INT32} scalar, specifying the dilation
      *      factor for width. Defaults to 1. If set to k > 1, there will be k-1 skipped
      *      cells between each filter element on width dimension. If this input is set,
      *      input 13 (dilation factor for height) must be specified as well.
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      * * 13: An optional {@link OperandType::INT32} scalar, specifying the dilation
      *      factor for height. Defaults to 1. If set to k > 1, there will be k-1 skipped
      *      cells between each filter element on height dimension. If this input is set,
      *      input 12 (dilation factor for width) must be specified as well.
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      *
      * Inputs (implicit padding):
      * * 0: A 4-D tensor, of shape [batches, height, width, depth_in],
@@ -575,14 +568,14 @@
      * * 1: A 4-D tensor, of shape [1, filter_height, filter_width, depth_out],
      *      specifying the filter.
      * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
-     *      tensor of type {@link OperandType::TENSOR_FLOAT32} or
-     *      {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same
+     *      tensor of type {@link OperandType::TENSOR_FLOAT32}
+     *      or {@link OperandType::TENSOR_FLOAT16} the bias must be of the same
      *      type. For filter tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint
-     *      of 0 and bias_scale == input_scale * filter_scale. For filter tensor
-     *      of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}, the bias
-     *      should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of
-     *      0 and bias_scale of 0. The actual scale of each value 'i' is equal to
+     *      of 0 and bias_scale == input_scale * filter_scale.
+     *      For filter tensor of {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL},
+     *      the bias should be of {@link OperandType::TENSOR_INT32}, with zeroPoint of 0
+     *      and bias_scale of 0. The actual scale of each value 'i' is equal to
      *      bias_scale[i] = input_scale * filter_scale[i].
      * * 3: An {@link OperandType::INT32} scalar, specifying the implicit
      *      padding scheme, has to be one of the
@@ -598,27 +591,24 @@
      *      invoke on the result.
      * * 8: An optional {@link OperandType::BOOL} scalar, default to false.
      *      Set to true to specify NCHW data layout for input0 and output0.
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      * * 9: An optional {@link OperandType::INT32} scalar, specifying the dilation
      *      factor for width. Defaults to 1. If set to k > 1, there will be k-1 skipped
      *      cells between each filter element on width dimension. If this input is set,
      *      input 10 (dilation factor for height) must be specified as well.
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      * * 10: An optional {@link OperandType::INT32} scalar, specifying the dilation
      *      factor for height. Defaults to 1. If set to k > 1, there will be k-1 skipped
      *      cells between each filter element on height dimension. If this input is set,
      *      input 9 (dilation factor for width) must be specified as well.
-     *      Available since API level 29.
-
+     *      Available since HAL version 1.2.
      *
      * Outputs:
      * * 0: The output 4-D tensor, of shape
-     *      [batches, out_height, out_width, depth_out]. Before API level 29,
-     *      for output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the
-     *      following condition must be satisfied:
+     *      [batches, out_height, out_width, depth_out]. Before HAL version 1.2, for
+     *      output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
+     *      the following condition must be satisfied:
      *      output_scale > input_scale * filter_scale
-     *
-     * Available since API level 27.
      */
     DEPTHWISE_CONV_2D = @1.1::OperationType:DEPTHWISE_CONV_2D,
 
@@ -638,7 +628,7 @@
      * be divisible by block_size * block_size
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
@@ -646,6 +636,7 @@
      * With the default data layout NHWC, the data is stored in the order of:
      * [batch, height, width, channels]. Alternatively, the data layout could
      * be NCHW, the data storage order of: [batch, channels, height, width].
+     * NCHW is supported since HAL version 1.2.
      *
      * Inputs:
      * * 0: A 4-D tensor, of shape [batches, height, width, depth_in],
@@ -655,13 +646,13 @@
      *      of the input depth.
      * * 2: An optional {@link OperandType::BOOL} scalar, default to false.
      *      Set to true to specify NCHW data layout for input0 and output0.
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      *
      * Outputs:
      * * 0: The output 4-D tensor, of shape [batch, height*block_size,
      *      width*block_size, depth/(block_size*block_size)].
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     DEPTH_TO_SPACE = @1.1::OperationType:DEPTH_TO_SPACE,
 
@@ -674,22 +665,21 @@
      *
      * Supported input tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
-     * * {@link OperandType::TENSOR_QUANT8_SYMM} (since API level 29)
-     * * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} (since API level 29)
+     * * {@link OperandType::TENSOR_QUANT8_SYMM} (since HAL version 1.2)
+     * * {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} (since HAL version 1.2)
      *
      * Supported output tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}.
      *
      * Supported tensor rank: up to 4
      *
      * Inputs:
-     * * 0: A tensor. Since API level 29, this tensor may be zero-sized.
+     * * 0: A tensor.
+     *      Since HAL version 1.2, this tensor may be zero-sized.
      *
      * Outputs:
      * * 0: A tensor with the same shape as input0.
-     *
-     * Available since API level 27.
      */
     DEQUANTIZE = @1.1::OperationType:DEQUANTIZE,
 
@@ -730,8 +720,8 @@
      * * 0: A n-D tensor with the same rank and shape as the Values
      *      tensor, except for the first dimension which has the same size
      *      as Lookups' only dimension.
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input1.
      */
     EMBEDDING_LOOKUP = @1.1::OperationType:EMBEDDING_LOOKUP,
 
@@ -739,7 +729,7 @@
      * Computes element-wise floor() on the input tensor.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      *
      * Supported tensor rank: up to 4
@@ -750,8 +740,6 @@
      * Outputs:
      * * 0: The output tensor, of the same {@link OperandType} and dimensions as
      *      the input tensor.
-     *
-     * Available since API level 27.
      */
     FLOOR = @1.1::OperationType:FLOOR,
 
@@ -764,7 +752,7 @@
      *     outputs = activation(inputs * weights’ + bias)
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
@@ -777,8 +765,8 @@
      *      [batch_size, input_size], where "input_size" corresponds to the
      *      number of inputs to the layer, matching the second dimension of
      *      weights, and "batch_size" is calculated by dividing the number of
-     *      elements by "input_size". Since API level 29, zero batch_size is
-     *      supported for this tensor.
+     *      elements by "input_size".
+     *      Since HAL version 1.2, zero batch_size is supported for this tensor.
      * * 1: A 2-D tensor, specifying the weights, of shape
      *      [num_units, input_size], where "num_units" corresponds to the number
      *      of output nodes.
@@ -793,12 +781,9 @@
      *      invoke on the result.
      *
      * Outputs:
-     * * 0: The output tensor, of shape [batch_size, num_units]. Before API
-     *      level 29, For output tensor of {@link
-     *      OperandType::TENSOR_QUANT8_ASYMM}, the following condition must be
-     *      satisfied: output_scale > input_scale * filter_scale.
-     *
-     * Available since API level 27.
+     * * 0: The output tensor, of shape [batch_size, num_units]. Before HAL version 1.2, for
+     *      output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the following
+     *      condition must be satisfied: output_scale > input_scale * filter_scale.
      */
     FULLY_CONNECTED = @1.1::OperationType:FULLY_CONNECTED,
 
@@ -849,13 +834,13 @@
      *
      * Outputs:
      * * 0: Output. A tensor with shape [ k …].
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input2.
      * * 1: Hits. A boolean tensor with shape [ k ] indicates whether the lookup
      *      hits (True) or not (False).
      *      Stored as {@link OperandType::TENSOR_QUANT8_ASYMM} with offset 0
      *      and scale 1.0f.
      *      A non-zero byte represents True, a hit. A zero indicates otherwise.
-     *
-     * Available since API level 27.
      */
     HASHTABLE_LOOKUP = @1.1::OperationType:HASHTABLE_LOOKUP,
 
@@ -872,12 +857,12 @@
      * 1-D slice along dimension dim.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
-     * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since API level 29)
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since HAL version 1.2)
      *
      * Supported tensor rank: up to 4
-     * Tensors with rank less than 4 are only supported since API level 29.
+     * Tensors with rank less than 4 are only supported since HAL version 1.2.
      *
      * Inputs:
      * * 0: An n-D tensor, specifying the tensor to be normalized.
@@ -885,14 +870,12 @@
      *      specifying the dimension normalization would be performed on.
      *      Negative index is used to specify axis from the end (e.g. -1 for
      *      the last axis). Must be in the range [-n, n).
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} and same shape as input0.
      *      For {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the scale must be 1.f / 128 and the zeroPoint must be 128.
-     *
-     * Available since API level 27.
      */
     L2_NORMALIZATION = @1.1::OperationType:L2_NORMALIZATION,
 
@@ -909,20 +892,21 @@
      *              sum(1))
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      *
      * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout.
      * With the default data layout NHWC, the data is stored in the order of:
      * [batch, height, width, channels]. Alternatively, the data layout could
      * be NCHW, the data storage order of: [batch, channels, height, width].
+     * NCHW is supported since HAL version 1.2.
      *
      * Both explicit padding and implicit padding are supported.
      *
      * Inputs (explicit padding):
      * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
-     *      the input. Since API level 29, zero batches is supported for this
-     *      tensor.
+     *      the input.
+     *      Since HAL version 1.2, zero batches is supported for this tensor.
      * * 1: An {@link OperandType::INT32} scalar, specifying the padding on
      *      the left, in the ‘width’ dimension.
      * * 2: An {@link OperandType::INT32} scalar, specifying the padding on
@@ -944,12 +928,12 @@
      *      invoke on the result.
      * * 10: An optional {@link OperandType::BOOL} scalar, default to false.
      *       Set to true to specify NCHW data layout for input0 and output0.
-     *       Available since API level 29.
+     *       Available since HAL version 1.2.
      *
      * Inputs (implicit padding):
      * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
-     *      the input. Since API level 29, zero batches is supported for this
-     *      tensor.
+     *      the input.
+     *      Since HAL version 1.2, zero batches is supported for this tensor.
      * * 1: An {@link OperandType::INT32} scalar, specifying the implicit
      *      padding scheme, has to be one of the
      *      following values: {0 (NONE), 1 (SAME), 2 (VALID)}.
@@ -966,13 +950,11 @@
      *      invoke on the result.
      * * 7: An optional {@link OperandType::BOOL} scalar, default to false.
      *      Set to true to specify NCHW data layout for input0 and output0.
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      *
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, out_height, out_width, depth].
-     *
-     * Available since API level 27.
      */
     L2_POOL_2D = @1.1::OperationType:L2_POOL_2D,
 
@@ -994,11 +976,11 @@
      * 1-D slice along specified dimension.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      *
      * Supported tensor rank: up to 4
-     * Tensors with rank less than 4 are only supported since API level 29.
+     * Tensors with rank less than 4 are only supported since HAL version 1.2.
      *
      * Inputs:
      * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
@@ -1011,10 +993,10 @@
      *      For input tensor of {@link OperandType::TENSOR_FLOAT32}, the bias
      *      value must be of {@link OperandType::FLOAT32}.
      * * 3: A scalar, specifying the scale factor, alpha.
-     *      For input tensor of {@link OperandType::TENSOR_FLOAT16}, the alpha
-     *      value must be of {@link OperandType::FLOAT16}.
-     *      For input tensor of {@link OperandType::TENSOR_FLOAT32}, the alpha
-     *      value must be of {@link OperandType::FLOAT32}.
+     *      For input tensor of {@link OperandType::TENSOR_FLOAT16}, the
+     *      alpha value must be of {@link OperandType::FLOAT16}.
+     *      For input tensor of {@link OperandType::TENSOR_FLOAT32}, the
+     *      alpha value must be of {@link OperandType::FLOAT32}.
      * * 4: A scalar, specifying the exponent, beta.
      *      For input tensor of {@link OperandType::TENSOR_FLOAT16}, the beta
      *      value must be of {@link OperandType::FLOAT16}.
@@ -1024,12 +1006,10 @@
      *      specifying the dimension normalization would be performed on.
      *      Negative index is used to specify axis from the end (e.g. -1 for
      *      the last axis). Must be in the range [-n, n).
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
-     *
-     * Available since API level 27.
      */
     LOCAL_RESPONSE_NORMALIZATION = @1.1::OperationType:LOCAL_RESPONSE_NORMALIZATION,
 
@@ -1041,22 +1021,20 @@
      *     output = 1 / (1 + exp(-input))
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
      * Supported tensor rank: up to 4.
      *
      * Inputs:
-     * * 0: A tensor, specifying the input. Since API level 29, this tensor may
-     *      be zero-sized.
+     * * 0: A tensor, specifying the input.
+     *      Since HAL version 1.2, this tensor may be zero-sized.
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
      *      For {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the scale must be 1.f / 256 and the zeroPoint must be 0.
-     *
-     * Available since API level 27.
      */
     LOGISTIC = @1.1::OperationType:LOGISTIC,
 
@@ -1064,7 +1042,7 @@
      * Projects an input to a bit vector via locality senstive hashing.
      *
      * Supported input tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_INT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
@@ -1086,7 +1064,7 @@
      *      Tensor[1].Dim[0] == Tensor[2].Dim[0]
      * * 3: Type:
      *        Sparse:
-     *          Value LSHProjectionType_SPARSE(=3) (since API level 29).
+     *          Value LSHProjectionType_SPARSE(=3) (since HAL version 1.2).
      *          Computed bit vector is considered to be sparse.
      *          Each output element is an int32 made up of multiple bits
      *          computed from hash functions.
@@ -1107,14 +1085,12 @@
      * Outputs:
      * * 0: If the projection type is Sparse:
      *      Output.Dim == { Tensor[0].Dim[0] }
-     *      A tensor of int32 that represents hash signatures,
+     *      A tensor of int32 that represents hash signatures.
      *
      *      If the projection type is Dense:
      *      Output.Dim == { Tensor[0].Dim[0] * Tensor[0].Dim[1] }
      *      A flattened tensor that represents projected bit vectors.
-     *
-     * Available since API level 27.
-     * The offset value for sparse projections was added in API level 29.
+     * The offset value for sparse projections was added in HAL version 1.2.
      */
     LSH_PROJECTION = @1.1::OperationType:LSH_PROJECTION,
 
@@ -1170,7 +1146,7 @@
      *   matrix, each element of which is the product of the corresponding
      *   elements of the input matrices.
      *
-     * Since API level 29 LSTM supports layer normalization.
+     * Since HAL version 1.2 LSTM supports layer normalization.
      * In case layer normalization is used, the inputs to internal activation
      * functions (sigmoid and \f$g\f$) are normalized, rescaled and recentered
      * following an approach from section 3.1 from
@@ -1197,7 +1173,7 @@
      * * The projection bias (\f$b_{proj}\f$) may (but not required to) have a
      *   value if the recurrent projection layer exists, and should otherwise
      *   have no value.
-     * * (API level >= 29) The four layer normalization weights either all have
+     * * (HAL version 1.2 or later) The four layer normalization weights either all have
      *   values or none of them have values. Additionally, if CIFG is used,
      *   input layer normalization weights tensor is omitted and the other layer
      *   normalization weights either all have values or none of them have
@@ -1228,7 +1204,7 @@
      * Jimmy Ba et al. "Layer Normalization"
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      *
      * All input and output tensors must be of the same type.
@@ -1291,24 +1267,24 @@
      * * 21:The clipping threshold (\f$t_{cell}\f$) for the cell state, such
      *      that values are bound within [-cell_clip, cell_clip]. If set to 0.0
      *      then clipping is disabled.
-     *      Until API level 29 this scalar must be of type {@link
-     *      FLOAT32}. Since API level 29, if all the input
+     *      Until HAL version 1.2 this scalar must be of type {@link
+     *      OperandType::FLOAT32}. Since HAL version 1.2, if all the input
      *      tensors have type {@link OperandType::TENSOR_FLOAT32}, this
      *      scalar must be of the type {@link OperandType::FLOAT32},
      *      otherwise if all the input tensors have the type {@link
-     *      TENSOR_FLOAT16}, this scalar must be of type {@link
-     *      FLOAT16}.
+     *      OperandType::TENSOR_FLOAT16}, this scalar must be of type {@link
+     *      OperandType::FLOAT16}.
      * * 22:The clipping threshold (\f$t_{proj}\f$) for the output from the
      *      projection layer, such that values are bound within
      *      [-proj_clip, proj_clip]. If set to 0.0 then clipping is disabled.
-     *      Until API level 29 this scalar must be of type {@link
-     *      FLOAT32}. Since API level 29, if all the input
+     *      Until HAL version 1.2 this scalar must be of type {@link
+     *      OperandType::FLOAT32}. Since HAL version 1.2, if all the input
      *      tensors have type {@link OperandType::TENSOR_FLOAT32}, this
      *      scalar must be of the type {@link OperandType::FLOAT32},
      *      otherwise if all the input tensors have the type {@link
-     *      TENSOR_FLOAT16}, this scalar must be of type {@link
-     *      FLOAT16}.
-     * Since API level 29 there are additional inputs to this op:
+     *      OperandType::TENSOR_FLOAT16}, this scalar must be of type {@link
+     *      OperandType::FLOAT16}.
+     * Since HAL version 1.2 there are additional inputs to this op:
      * * 23:The input layer normalization weights.
      *      A 1-D tensor of shape [num_units]. Used to rescale normalized inputs
      *      to activation at input gate.
@@ -1333,8 +1309,6 @@
      * * 3: The output (\f$o_t\f$).
      *      A 2-D tensor of shape [batch_size, output_size]. This is effectively
      *      the same as the current “output state (out)” value.
-     *
-     * Available since API level 27.
      */
     LSTM = @1.1::OperationType:LSTM,
 
@@ -1352,7 +1326,7 @@
      *         )
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
@@ -1360,13 +1334,14 @@
      * With the default data layout NHWC, the data is stored in the order of:
      * [batch, height, width, channels]. Alternatively, the data layout could
      * be NCHW, the data storage order of: [batch, channels, height, width].
+     * NCHW is supported since HAL version 1.2.
      *
      * Both explicit padding and implicit padding are supported.
      *
      * Inputs (explicit padding):
      * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
-     *      the input. Since API level 29, zero batches is supported for this
-     *      tensor.
+     *      the input.
+     *      Since HAL version 1.2, zero batches is supported for this tensor.
      * * 1: An {@link OperandType::INT32} scalar, specifying the padding on
      *      the left, in the ‘width’ dimension.
      * * 2: An {@link OperandType::INT32} scalar, specifying the padding on
@@ -1388,12 +1363,12 @@
      *      invoke on the result.
      * * 10: An optional {@link OperandType::BOOL} scalar, default to false.
      *       Set to true to specify NCHW data layout for input0 and output0.
-     *       Available since API level 29.
+     *       Available since HAL version 1.2.
      *
      * Inputs (implicit padding):
      * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
-     *      the input. Since API level 29, zero batches is supported for this
-     *      tensor.
+     *      the input.
+     *      Since HAL version 1.2, zero batches is supported for this tensor.
      * * 1: An {@link OperandType::INT32} scalar, specifying the implicit
      *      padding scheme, has to be one of the
      *      following values: {0 (NONE), 1 (SAME), 2 (VALID)}.
@@ -1410,13 +1385,13 @@
      *      invoke on the result.
      * * 7: An optional {@link OperandType::BOOL} scalar, default to false.
      *      Set to true to specify NCHW data layout for input0 and output0.
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      *
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, out_height, out_width, depth].
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     MAX_POOL_2D = @1.1::OperationType:MAX_POOL_2D,
 
@@ -1435,15 +1410,15 @@
      * of the input operands. It starts with the trailing dimensions, and works
      * its way forward.
      *
-     * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
-     * * {@link OperandType::TENSOR_FLOAT32}
-     * * {@link OperandType::TENSOR_QUANT8_ASYMM}
-     *
-     * Since API level 29, generic zero-sized input tensor is supported. Zero
+     * Since HAL version 1.2, generic zero-sized input tensor is supported. Zero
      * dimension is only compatible with 0 or 1. The size of the output
      * dimension is zero if either of corresponding input dimension is zero.
      *
+     * Supported tensor {@link OperandType}:
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
+     * * {@link OperandType::TENSOR_FLOAT32}
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     *
      * Supported tensor rank: up to 4
      *
      * Inputs:
@@ -1459,8 +1434,6 @@
      *      For output tensor of {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the following condition must be satisfied:
      *      output_scale > input1_scale * input2_scale.
-     *
-     * Available since API level 27.
      */
     MUL = @1.1::OperationType:MUL,
 
@@ -1472,20 +1445,20 @@
      *     output = max(0, input)
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
      * Supported tensor rank: up to 4.
      *
      * Inputs:
-     * * 0: A tensor, specifying the input. Since API level 29, this tensor may
-     *      be zero-sized.
+     * * 0: A tensor, specifying the input.
+     *      Since HAL version 1.2, this tensor may be zero-sized.
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     RELU = @1.1::OperationType:RELU,
 
@@ -1497,20 +1470,20 @@
      *     output = min(1.f, max(-1.f, input))
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
      * Supported tensor rank: up to 4.
      *
      * Inputs:
-     * * 0: A tensor, specifying the input. Since API level 29, this tensor may
-     *      be zero-sized.
+     * * 0: A tensor, specifying the input.
+     *      Since HAL version 1.2, this tensor may be zero-sized.
      *
      * Outputs:
-     * * 0: The output tensor of same shape as input0.
-     *
-     * Available since API level 27.
+     * * 0: The output tensor of the same shape as input0.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     RELU1 = @1.1::OperationType:RELU1,
 
@@ -1522,20 +1495,20 @@
      *     output = min(6, max(0, input))
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
      * Supported tensor rank: up to 4.
      *
      * Inputs:
-     * * 0: A tensor, specifying the input. Since API level 29, this tensor may
-     *      be zero-sized.
+     * * 0: A tensor, specifying the input.
+     *      Since HAL version 1.2, this tensor may be zero-sized.
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     RELU6 = @1.1::OperationType:RELU6,
 
@@ -1546,7 +1519,7 @@
      * tensor, but with a newly specified shape.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
@@ -1565,8 +1538,8 @@
      *
      * Outputs:
      * * 0: The output tensor, of shape specified by the input shape.
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     RESHAPE = @1.1::OperationType:RESHAPE,
 
@@ -1578,30 +1551,31 @@
      * same as corner pixels of input.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
-     * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since API level 29)
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since HAL version 1.2)
      *
      * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout.
      * With the default data layout NHWC, the data is stored in the order of:
      * [batch, height, width, channels]. Alternatively, the data layout could
      * be NCHW, the data storage order of: [batch, channels, height, width].
+     * NCHW is supported since HAL version 1.2.
      *
      * Both resizing by shape and resizing by scale are supported.
      *
      * Inputs (resizing by shape):
      * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
-     *      the input. Since API level 29, zero batches is supported for this
-     *      tensor.
+     *      the input.
+     *      Since HAL version 1.2, zero batches is supported for this tensor.
      * * 1: An {@link OperandType::INT32} scalar, specifying the output
      *      width of the output tensor.
      * * 2: An {@link OperandType::INT32} scalar, specifying the output
      *      height of the output tensor.
      * * 3: An optional {@link OperandType::BOOL} scalar, default to false.
      *      Set to true to specify NCHW data layout for input0 and output0.
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      *
-     * Inputs (resizing by scale, since API level 29):
+     * Inputs (resizing by scale, since HAL version 1.2):
      * * 0: A 4-D tensor, of shape [batches, height, width, depth], specifying
      *      the input. Zero batches is supported for this tensor.
      * * 1: A scalar, specifying width_scale, the scaling factor of the width
@@ -1622,8 +1596,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, new_height, new_width, depth].
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     RESIZE_BILINEAR = @1.1::OperationType:RESIZE_BILINEAR,
 
@@ -1644,7 +1618,7 @@
      *   argument (if not “NONE”).
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      *
      * The input tensors must all be the same type.
@@ -1676,8 +1650,6 @@
      * * 1: output.
      *      A 2-D tensor of shape [batch_size, num_units]. This is effectively
      *      the same as the current state value.
-     *
-     * Available since API level 27.
      */
     RNN = @1.1::OperationType:RNN,
 
@@ -1696,34 +1668,32 @@
      * independently on each 1-D slice along specified dimension.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
      * Supported tensor rank: up to 4.
-     * Tensors with rank other than 2 or 4 are only supported since API level 29.
+     * Tensors with rank other than 2 or 4 are only supported since HAL version 1.2.
      *
      * Inputs:
-     * * 0: A 2-D or 4-D tensor, specifying the tensor to be reshaped. Since
-     *      API level 29, this tensor may be zero-sized.
+     * * 0: A 2-D or 4-D tensor, specifying the tensor to be reshaped.
+     *      Since HAL version 1.2, this tensor may be zero-sized.
      * * 1: A scalar, specifying the positive scaling factor for the exponent,
      *      beta. If input0 is of {@link OperandType::TENSOR_FLOAT32} or
      *      {@link OperandType::TENSOR_QUANT8_ASYMM}, the scalar must be of
-     *      {@link OperandType::FLOAT32}. If input0 is of {@link
-     *      OperandType::TENSOR_FLOAT16}, then the scalar must be of {@link
-     *      OperandType::FLOAT16}.
+     *      {@link OperandType::FLOAT32}.
+     *      If input0 is of {@link OperandType::TENSOR_FLOAT16}, then the
+     *      scalar must be of {@link OperandType::FLOAT16}.
      * * 2: An optional {@link OperandType::INT32} scalar, default to -1,
      *      specifying the dimension the activation would be performed on.
      *      Negative index is used to specify axis from the end (e.g. -1 for
      *      the last axis). Must be in the range [-n, n).
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
      *      For {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the scale must be 1.f / 256 and the zeroPoint must be 0.
-     *
-     * Available since API level 27.
      */
     SOFTMAX = @1.1::OperationType:SOFTMAX,
 
@@ -1742,7 +1712,7 @@
      * The input tensor's height and width must be divisible by block_size.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
@@ -1750,6 +1720,7 @@
      * With the default data layout NHWC, the data is stored in the order of:
      * [batch, height, width, channels]. Alternatively, the data layout could
      * be NCHW, the data storage order of: [batch, channels, height, width].
+     * NCHW is supported since HAL version 1.2.
      *
      * Inputs:
      * * 0: A 4-D tensor, of shape [batches, height, width, depth_in],
@@ -1759,13 +1730,13 @@
      *      input height and width.
      * * 2: An optional {@link OperandType::BOOL} scalar, default to false.
      *      Set to true to specify NCHW data layout for input0 and output0.
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      *
      * Outputs:
      * * 0: The output 4-D tensor, of shape [batches, height/block_size,
      *      width/block_size, depth_in*block_size*block_size].
-     *
-     * Available since API level 27.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     SPACE_TO_DEPTH = @1.1::OperationType:SPACE_TO_DEPTH,
 
@@ -1809,7 +1780,7 @@
      * the filters.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      *
      * All input tensors must be the same type.
@@ -1843,8 +1814,6 @@
      * * 1: output.
      *      A 2-D tensor of the same {@link OperandType} as the inputs, with shape
      *      [batch_size, num_units].
-     *
-     * Available since API level 27.
      */
     SVDF = @1.1::OperationType:SVDF,
 
@@ -1856,22 +1825,20 @@
      *     output = tanh(input)
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
-     * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since API level 29)
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since HAL version 1.2)
      *
      * Supported tensor rank: up to 4.
      *
      * Inputs:
-     * * 0: A tensor, specifying the input. Since API level 29, this tensor may
-     *      be zero-sized.
+     * * 0: A tensor, specifying the input.
+     *      Since HAL version 1.2, this tensor may be zero-sized.
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
      *      For {@link OperandType::TENSOR_QUANT8_ASYMM},
      *      the scale must be 1.f / 128 and the zeroPoint must be 128.
-     *
-     * Available since API level 27.
      */
     TANH = @1.1::OperationType:TANH,
 
@@ -1886,7 +1853,7 @@
      * This is the reverse of SpaceToBatch.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
@@ -1894,6 +1861,7 @@
      * With the default data layout NHWC, the data is stored in the order of:
      * [batch, height, width, channels]. Alternatively, the data layout could
      * be NCHW, the data storage order of: [batch, channels, height, width].
+     * NCHW is supported since HAL version 1.2.
      *
      * Inputs:
      * * 0: An n-D tensor, specifying the tensor to be reshaped
@@ -1906,8 +1874,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 28.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     BATCH_TO_SPACE_ND = @1.1::OperationType:BATCH_TO_SPACE_ND,
 
@@ -1931,12 +1899,12 @@
      *     input2.dimension = {5, 4, 3, 1}
      *     output.dimension = {5, 4, 3, 2}
      *
-     * Since API level 29, generic zero-sized input tensor is supported. Zero
+     * Since HAL version 1.2, generic zero-sized input tensor is supported. Zero
      * dimension is only compatible with 0 or 1. The size of the output
      * dimension is zero if either of corresponding input dimension is zero.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      *
      * Supported tensor rank: up to 4
@@ -1951,8 +1919,6 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 28.
      */
     DIV = @1.1::OperationType:DIV,
 
@@ -1965,7 +1931,7 @@
      * length 1.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
@@ -1987,21 +1953,21 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 28.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be same as input0.
      */
     MEAN = @1.1::OperationType:MEAN,
 
     /**
-     * Pads a tensor with zeros.
+     * Pads a tensor.
      *
      * This operation pads a tensor according to the specified paddings.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
-     * * {@link OperandType::TENSOR_QUANT8_ASYMM} (full support since API
-     *   level 29, see the output section)
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     *   (full support since HAL version 1.2, see the output section)
      *
      * Supported tensor rank: up to 4
      *
@@ -2023,12 +1989,12 @@
      *      of the padding:
      *          output0.dimension[i] =
      *              padding[i, 0] + input0.dimension[i] + padding[i, 1]
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      *
-     *      NOTE: Before API level 29, the pad value for
-     *      {@link ANEURALNETWORKS_TENSOR_QUANT8_ASYMM} is undefined.
-     *      Since API level 29, the pad value is always the logical zero.
-     *
-     * Available since API level 28.
+     *      NOTE: Before HAL version 1.2, the pad value for
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM} is undefined.
+     *      Since HAL version 1.2, the pad value is always the logical zero.
      */
     PAD = @1.1::OperationType:PAD,
 
@@ -2044,14 +2010,16 @@
      * dimensions of the input are optionally zero padded according to paddings.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
+     *   (full support since HAL version 1.2, see the output section)
      *
      * Supported tensor rank: 4, with "NHWC" or "NCHW" data layout.
      * With the default data layout NHWC, the data is stored in the order of:
      * [batch, height, width, channels]. Alternatively, the data layout could
      * be NCHW, the data storage order of: [batch, channels, height, width].
+     * NCHW is supported since HAL version 1.2.
      *
      * Inputs:
      * * 0: An n-D tensor, specifying the input.
@@ -2068,12 +2036,16 @@
      *      end of dimension i.
      * * 3: An optional {@link OperandType::BOOL} scalar, default to false.
      *      Set to true to specify NCHW data layout for input0 and output0.
-     *      Available since API level 29.
+     *      Available since HAL version 1.2.
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      *
-     * Available since API level 28.
+     *      NOTE: Before HAL version 1.2, the pad value for
+     *      {@link OperandType::TENSOR_QUANT8_ASYMM} is undefined.
+     *      Since HAL version 1.2, the pad value is always the logical zero.
      */
     SPACE_TO_BATCH_ND = @1.1::OperationType:SPACE_TO_BATCH_ND,
 
@@ -2086,7 +2058,7 @@
      * dimensions by specifying the axes (input1).
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
@@ -2104,8 +2076,8 @@
      * * 0: A tensor of the same {@link OperandType} as input0. Contains the
      *      same data as input, but has one or more dimensions of size 1
      *      removed.
-     *
-     * Available since API level 28.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     SQUEEZE = @1.1::OperationType:SQUEEZE,
 
@@ -2119,7 +2091,7 @@
      * reverse slice.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
@@ -2151,8 +2123,8 @@
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0 and rank (n - k),
      *      where k is the number of bits set in shrink_axis_mask.
-     *
-     * Available since API level 28.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     STRIDED_SLICE = @1.1::OperationType:STRIDED_SLICE,
 
@@ -2176,14 +2148,14 @@
      *     input2.dimension = {5, 4, 3, 1}
      *     output.dimension = {5, 4, 3, 2}
      *
-     * Since API level 29, generic zero-sized input tensor is supported. Zero
+     * Since HAL version 1.2, generic zero-sized input tensor is supported. Zero
      * dimension is only compatible with 0 or 1. The size of the output
      * dimension is zero if either of corresponding input dimension is zero.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
-     * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since API level 29)
+     * * {@link OperandType::TENSOR_QUANT8_ASYMM} (since HAL version 1.2)
      *
      * Supported tensor rank: up to 4
      *
@@ -2197,8 +2169,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 28.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      */
     SUB = @1.1::OperationType:SUB,
 
@@ -2212,7 +2184,7 @@
      * regular matrix transpose on 2-D input Tensors.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16} (since HAL version 1.2)
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
@@ -2220,14 +2192,14 @@
      *
      * Inputs:
      * * 0: An n-D tensor, specifying the tensor to be transposed.
-     *      Since API level 29, this tensor may be zero-sized.
+     *      Since HAL version 1.2, this tensor may be zero-sized.
      * * 1: An optional 1-D Tensor of {@link OperandType::TENSOR_INT32},
      *      the permutation of the dimensions of the input tensor.
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 28.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     TRANSPOSE = @1.1::OperationType:TRANSPOSE,
 
@@ -2245,8 +2217,6 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
-     *
-     * Available since API level 29.
      */
     ABS = 38,
 
@@ -2269,8 +2239,6 @@
      *
      * Outputs:
      * * 0: An (n - 1)-D {@link OperandType::TENSOR_INT32} tensor.
-     *
-     * Available since API level 29.
      */
     // There is no underscore in ARG_MAX to avoid name conflict with
     // the macro defined in libc/kernel/uapi/linux/limits.h.
@@ -2295,8 +2263,6 @@
      *
      * Outputs:
      * * 0: An (n - 1)-D {@link OperandType::TENSOR_INT32} tensor.
-     *
-     * Available since API level 29.
      */
     ARGMIN = 40,  // See ARGMAX for naming discussion.
 
@@ -2341,8 +2307,8 @@
      * * 0: A tensor of the same {@link OperandType} as input0, with shape
      *      [num_rois, num_classes * 4], specifying the coordinates of each
      *      output bounding box for each class, with format [x1, y1, x2, y2].
-     *
-     * Available since API level 29.
+     *      For type of {@link OperandType::TENSOR_QUANT16_ASYMM}, the
+     *      scale must be 0.125 and the zero point must be 0.
      */
     AXIS_ALIGNED_BBOX_TRANSFORM = 41,
 
@@ -2482,17 +2448,15 @@
      *       then clipping is disabled.
      *       If all the input tensors have type {@link OperandType::TENSOR_FLOAT32},
      *       this scalar must be of the type {@link OperandType::FLOAT32},
-     *       otherwise if all the input tensors have the type {@link
-     *       TENSOR_FLOAT16}, this scalar must be of type {@link
-     *       FLOAT16}.
+     *       otherwise if all the input tensors have the type {@link OperandType::TENSOR_FLOAT16},
+     *       this scalar must be of type {@link OperandType::FLOAT16}.
      * * 50: The clipping threshold for the output from the
      *       projection layer, such that values are bound within
      *       [-proj_clip, proj_clip]. If set to 0.0 then clipping is disabled.
      *       If all the input tensors have type {@link OperandType::TENSOR_FLOAT32},
      *       this scalar must be of the type {@link OperandType::FLOAT32},
-     *       otherwise if all the input tensors have the type {@link
-     *       TENSOR_FLOAT16}, this scalar must be of type {@link
-     *       FLOAT16}.
+     *       otherwise if all the input tensors have the type {@link OperandType::TENSOR_FLOAT16},
+     *       this scalar must be of type {@link OperandType::FLOAT16}.
      * * 51: merge_outputs
      *       An {@link OperandType::BOOL} scalar specifying if the outputs
      *       from forward and backward cells should be merged.
@@ -2539,8 +2503,6 @@
      *      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]
-     *
-     * Available since API level 29.
      */
     BIDIRECTIONAL_SEQUENCE_LSTM = 42,
 
@@ -2658,8 +2620,6 @@
      *      (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].
-     *
-     * Available since API level 29.
      */
     BIDIRECTIONAL_SEQUENCE_RNN = 43,
 
@@ -2737,8 +2697,6 @@
      * * 3: A 1-D {@link OperandType::TENSOR_INT32} tensor, of shape
      *      [num_output_rois], specifying the batch index of each box. Boxes
      *      with the same batch index are grouped together.
-     *
-     * Available since API level 29.
      */
     BOX_WITH_NMS_LIMIT = 44,
 
@@ -2762,8 +2720,6 @@
      *
      * Outputs:
      * * 0: A tensor with the same shape as input0.
-     *
-     * Available since API level 29.
      */
     CAST = 45,
 
@@ -2800,8 +2756,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} and same shape as input0.
-     *
-     * Available since API level 29.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     CHANNEL_SHUFFLE = 46,
 
@@ -2856,14 +2812,14 @@
      * * 11: A scalar, score_threshold. Boxes with scores lower than the
      *       threshold are filtered before sending to the NMS algorithm. The
      *       scalar must be of {@link OperandType::FLOAT16} if input0 is of
-     *       {@link OperandType::TENSOR_FLOAT16} and of {@link
-     *       OperandType::FLOAT32} if input0 is of {@link
-     *       OperandType::TENSOR_FLOAT32}.
+     *       {@link OperandType::TENSOR_FLOAT16} and of
+     *       {@link OperandType::FLOAT32} if input0 is of
+     *       {@link OperandType::TENSOR_FLOAT32}.
      * * 12: A scalar, specifying the IoU threshold for hard NMS. The scalar
-     *       must be of {@link OperandType::FLOAT16} if input0 is of {@link
-     *       OperandType::TENSOR_FLOAT16} and of {@link
-     *       OperandType::FLOAT32} if input0 is of {@link
-     *       OperandType::TENSOR_FLOAT32}.
+     *       must be of {@link OperandType::FLOAT16} if input0 is of
+     *       {@link OperandType::TENSOR_FLOAT16} and of
+     *       {@link OperandType::FLOAT32} if input0 is of
+     *       {@link OperandType::TENSOR_FLOAT32}.
      * * 13: An {@link OperandType::BOOL} scalar, set to true to include
      *       background class in the list of label map for the output, set
      *       to false to not include the background. When the background
@@ -2882,8 +2838,6 @@
      *      output detection.
      * * 3: An 1-D {@link OperandType::TENSOR_INT32} tensor, of shape [batches],
      *      specifying the number of valid output detections for each batch.
-     *
-     * Available since API level 29.
      */
     DETECTION_POSTPROCESSING = 47,
 
@@ -2908,8 +2862,6 @@
      *
      * Outputs:
      * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
-     *
-     * Available since API level 29.
      */
     EQUAL = 48,
 
@@ -2927,8 +2879,6 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
-     *
-     * Available since API level 29.
      */
     EXP = 49,
 
@@ -2956,8 +2906,8 @@
      * Outputs:
      * * 0: An (n + 1)-D tensor with the same {@link OperandType} and data as
      *      input0.
-     *
-     * Available since API level 29.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     EXPAND_DIMS = 50,
 
@@ -2994,8 +2944,8 @@
      *
      * Outputs:
      * * 0: An (n + k - 1)-D tensor with the same {@link OperandType} as input0.
-     *
-     * Available since API level 29.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     GATHER = 51,
 
@@ -3074,8 +3024,6 @@
      * * 2: A 1-D {@link OperandType::TENSOR_INT32} tensor, of shape
      *      [num_output_rois], specifying the batch index of each box. Boxes
      *      with the same batch index are grouped together.
-     *
-     * Available since API level 29.
      */
     GENERATE_PROPOSALS = 52,
 
@@ -3100,8 +3048,6 @@
      *
      * Outputs:
      * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
-     *
-     * Available since API level 29.
      */
     GREATER = 53,
     /**
@@ -3125,8 +3071,6 @@
      *
      * Outputs:
      * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
-     *
-     * Available since API level 29.
      */
     GREATER_EQUAL = 54,
 
@@ -3191,7 +3135,8 @@
      *      [depth_out, filter_height, filter_width, depth_group], specifying
      *      the filter, where depth_out must be divisible by num_groups.  For
      *      tensor of type {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}
-     *      the channel dimension must be set to 0.
+     *      the channel dimension (channelDim at
+     *      {@link SymmPerChannelQuantParams}) must be set to 0.
      * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
      *      tensor of type {@link OperandType::TENSOR_FLOAT32} or
      *      {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same
@@ -3229,7 +3174,8 @@
      *      [depth_out, filter_height, filter_width, depth_group], specifying
      *      the filter, where depth_out must be divisible by num_groups.  For
      *      tensor of type {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL}
-     *      the channel dimension must be set to 0.
+     *      the channel dimension (SymmPerChannelQuantParams::channelDim)
+     *      must be set to 0.
      * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
      *      tensor of type {@link OperandType::TENSOR_FLOAT32} or
      *      {@link OperandType::TENSOR_FLOAT16}, the bias must be of the same
@@ -3258,8 +3204,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, out_height, out_width, depth_out].
-     *
-     * Available since API level 29.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      */
     GROUPED_CONV_2D = 55,
 
@@ -3300,12 +3246,14 @@
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0, with shape
      *      [num_boxes, num_keypoints], specifying score of the keypoints.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint can be different from input0 scale and zeroPoint.
      * * 1: A tensor of the same {@link OperandType} as input1, with shape
      *      [num_boxes, num_keypoints, 2], specifying the location of
      *      the keypoints, the second dimension is organized as
      *      [keypoint_x, keypoint_y].
-     *
-     * Available since API level 29.
+     *      For type of {@link OperandType::TENSOR_QUANT16_ASYMM}, the
+     *      scale must be 0.125 and the zero point must be 0.
      */
     HEATMAP_MAX_KEYPOINT = 56,
 
@@ -3339,26 +3287,24 @@
      * * 0: An n-D tensor, specifying the tensor to be normalized.
      * * 1: A scalar, specifying gamma, the scale applied to the normalized
      *      tensor. The scalar must be of {@link OperandType::FLOAT16} if
-     *      input0 is of {@link OperandType::TENSOR_FLOAT16} and of {@link
-     *      OperandType::FLOAT32} if input0 is of {@link
-     *      OperandType::TENSOR_FLOAT32}.
+     *      input0 is of {@link OperandType::TENSOR_FLOAT16} and of
+     *      {@link OperandType::FLOAT32} if input0 is of
+     *      {@link OperandType::TENSOR_FLOAT32}.
      * * 2: A scalar, specifying beta, the offset applied to the normalized
      *      tensor. The scalar must be of {@link OperandType::FLOAT16} if
-     *      input0 is of {@link OperandType::TENSOR_FLOAT16} and of {@link
-     *      OperandType::FLOAT32} if input0 is of {@link
-     *      OperandType::TENSOR_FLOAT32}.
+     *      input0 is of {@link OperandType::TENSOR_FLOAT16} and of
+     *      {@link OperandType::FLOAT32} if input0 is of
+     *      {@link OperandType::TENSOR_FLOAT32}.
      * * 3: A scalar, specifying epsilon, the small value added to variance to
      *      avoid dividing by zero. The scalar must be of {@link OperandType::FLOAT16} if
-     *      input0 is of {@link OperandType::TENSOR_FLOAT16} and of {@link
-     *      OperandType::FLOAT32} if input0 is of {@link
-     *      OperandType::TENSOR_FLOAT32}.
+     *      input0 is of {@link OperandType::TENSOR_FLOAT16} and of
+     *      {@link OperandType::FLOAT32} if input0 is of
+     *      {@link OperandType::TENSOR_FLOAT32}.
      * * 4: An {@link OperandType::BOOL} scalar, set to true to specify
      *      NCHW data layout for input0 and output0. Set to false for NHWC.
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} and same shape as input0.
-     *
-     * Available since API level 29.
      */
     INSTANCE_NORMALIZATION = 57,
 
@@ -3383,8 +3329,6 @@
      *
      * Outputs:
      * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
-     *
-     * Available since API level 29.
      */
     LESS = 58,
 
@@ -3409,8 +3353,6 @@
      *
      * Outputs:
      * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
-     *
-     * Available since API level 29.
      */
     LESS_EQUAL = 59,
 
@@ -3428,8 +3370,6 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
-     *
-     * Available since API level 29.
      */
     LOG = 60,
 
@@ -3450,8 +3390,6 @@
      *
      * Outputs:
      * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
-     *
-     * Available since API level 29.
      */
     LOGICAL_AND = 61,
 
@@ -3468,8 +3406,6 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
-     *
-     * Available since API level 29.
      */
     LOGICAL_NOT = 62,
 
@@ -3490,8 +3426,6 @@
      *
      * Outputs:
      * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
-     *
-     * Available since API level 29.
      */
     LOGICAL_OR = 63,
 
@@ -3523,8 +3457,6 @@
      * Outputs:
      * * 0: The output tensor of the same {@link OperandType} and shape as
      *      input0.
-     *
-     * Available since API level 29.
      */
     LOG_SOFTMAX = 64,
 
@@ -3543,11 +3475,13 @@
      * * 0: A tensor.
      * * 1: A tensor of the same {@link OperandType} and compatible dimensions
      *      with input0.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scales and zeroPoint can be different from input0 scale and zeroPoint.
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 29.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      */
     MAXIMUM = 65,
 
@@ -3566,11 +3500,13 @@
      * * 0: A tensor.
      * * 1: A tensor of the same {@link OperandType} and compatible dimensions
      *      with input0.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scales and zeroPoint can be different from input0 scale and zeroPoint.
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 29.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      */
     MINIMUM = 66,
 
@@ -3589,8 +3525,6 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
-     *
-     * Available since API level 29.
      */
     NEG = 67,
 
@@ -3615,8 +3549,6 @@
      *
      * Outputs:
      * * 0: A tensor of {@link OperandType::TENSOR_BOOL8}.
-     *
-     * Available since API level 29.
      */
     NOT_EQUAL = 68,
 
@@ -3657,8 +3589,8 @@
      *      of the padding:
      *          output0.dimension[i] =
      *              padding[i, 0] + input0.dimension[i] + padding[i, 1]
-     *
-     * Available since API level 29.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     PAD_V2 = 69,
 
@@ -3689,8 +3621,6 @@
      *
      * Outputs:
      * * 0: An output tensor.
-     *
-     * Available since API level 29.
      */
     POW = 70,
 
@@ -3728,8 +3658,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 29.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint can be diffent from the input0 scale and zeroPoint.
      */
     PRELU = 71,
 
@@ -3752,8 +3682,6 @@
      * Outputs:
      * * 0: The output tensor of same shape as input0, but with
      *      {@link OperandType::TENSOR_QUANT8_ASYMM}.
-     *
-     * Available since API level 29.
      */
     QUANTIZE = 72,
 
@@ -3879,8 +3807,6 @@
      * Outputs:
      * * 0: A 2-D {@link OperandType::TENSOR_INT32} tensor with shape
      *      [batches, samples], containing the drawn samples.
-     *
-     * Available since API level 29.
      */
     RANDOM_MULTINOMIAL = 74,
 
@@ -3906,8 +3832,6 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 29.
      */
     REDUCE_ALL = 75,
 
@@ -3933,8 +3857,6 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 29.
      */
     REDUCE_ANY = 76,
 
@@ -3962,8 +3884,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 29.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     REDUCE_MAX = 77,
 
@@ -3991,8 +3913,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 29.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     REDUCE_MIN = 78,
 
@@ -4018,8 +3940,6 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 29.
      */
     REDUCE_PROD = 79,
 
@@ -4045,8 +3965,6 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
-     *
-     * Available since API level 29.
      */
     REDUCE_SUM = 80,
 
@@ -4064,7 +3982,7 @@
      * interpolation.
      *
      * Supported tensor {@link OperandType}:
-     * * {@link OperandType::TENSOR_FLOAT16} (since API level 29)
+     * * {@link OperandType::TENSOR_FLOAT16}
      * * {@link OperandType::TENSOR_FLOAT32}
      * * {@link OperandType::TENSOR_QUANT8_ASYMM}
      *
@@ -4105,8 +4023,8 @@
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0. The output
      *      shape is [num_rois, out_height, out_width, depth].
-     *
-     * Available since API level 29.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint can be different from the input0 scale and zeroPoint.
      */
     ROI_ALIGN = 81,
 
@@ -4156,8 +4074,8 @@
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0. The output
      *      shape is [num_rois, out_height, out_width, depth].
-     *
-     * Available since API level 29.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     ROI_POOLING = 82,
 
@@ -4175,8 +4093,6 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
-     *
-     * Available since API level 29.
      */
     RSQRT = 83,
 
@@ -4201,9 +4117,13 @@
      *      true) or input2 (if false).
      * * 1: An input tensor of the same shape as input0.
      * * 2: An input tensor of the same shape and type as input1.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scales and zeroPoint can be different from input1 scale and zeroPoint.
      *
      * Outputs:
      * * 0: A tensor of the same type and shape as input1 and input2.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      *
      */
     SELECT = 84,
@@ -4222,8 +4142,6 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
-     *
-     * Available since API level 29.
      */
     SIN = 85,
 
@@ -4235,7 +4153,6 @@
      * for each dimension. The size is specified as a 1-D tensor containing
      * either size of a slice along corresponding dimension or -1. In the latter
      * case, all the remaining elements in dimension are included in the slice.
-     * Slice size in each dimension cannot be zero.
      *
      * A sum of begin offset and a size of a slice must not exceed size of a
      * corresponding dimension.
@@ -4257,8 +4174,8 @@
      *
      * Outputs:
      * * 0: An n-D tensor of the same type as the input containing the slice.
-     *
-     * Available since API level 29.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      its scale and zeroPoint has to be same as the input0 scale and zeroPoint.
      */
     SLICE = 86,
 
@@ -4282,8 +4199,8 @@
      *
      * Outputs:
      * * 0 ~ (num_splits - 1): Resulting subtensors.
-     *
-     * Available since API level 29.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     SPLIT = 87,
 
@@ -4301,8 +4218,6 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
-     *
-     * Available since API level 29.
      */
     SQRT = 88,
 
@@ -4330,8 +4245,8 @@
      *
      * Outputs:
      * * 0: A tiled tensor of the same {@link OperandType} and rank as `input`.
-     *
-     * Available since API level 29.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     TILE = 89,
 
@@ -4357,10 +4272,10 @@
      * Outputs:
      * * 0: An n-D tensor of the same type as the input, containing the k
      *      largest elements along each last dimensional slice.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      * * 1: An n-D tensor of type {@link OperandType::TENSOR_INT32}
      *      containing the indices of values within the last dimension of input.
-     *
-     * Available since API level 29.
      */
     TOPK_V2 = 90,
 
@@ -4374,7 +4289,7 @@
      * The output dimensions are functions of the filter dimensions, stride, and
      * padding.
      *
-     * Supported tensor {@link OperandCode} configurations:
+     * Supported tensor {@link OperandType} configurations:
      * * 16 bit floating point:
      * * * {@link OperandType::TENSOR_FLOAT16} for input, filter, output, and bias.
      *
@@ -4406,7 +4321,7 @@
      *      [depth_out, filter_height, filter_width, depth_in], specifying the
      *      filter. For tensor of type
      *      {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} the channel
-     *      dimension (extraParams.channelQuant.channelDim) must be set to 0.
+     *      dimension (SymmPerChannelQuantParams::channelDim) must be set to 0.
      * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
      *      tensor of type {@link OperandType::TENSOR_FLOAT32} or
      *      {@link OperandType::TENSOR_FLOAT16}, the bias should be of the
@@ -4443,7 +4358,7 @@
      *      [depth_out, filter_height, filter_width, depth_in], specifying the
      *      filter. For tensor of type
      *      {@link OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL} the channel
-     *      dimension (extraParams.channelQuant.channelDim) must be set to 0.
+     *      dimension (SymmPerChannelQuantParams::channelDim) must be set to 0.
      * * 2: A 1-D tensor, of shape [depth_out], specifying the bias. For input
      *      tensor of type {@link OperandType::TENSOR_FLOAT32} or
      *      {@link OperandType::TENSOR_FLOAT16}, the bias should be of the
@@ -4473,8 +4388,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, out_height, out_width, depth_out].
-     *
-     * Available since API level 29.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint can be different from inputs' scale and zeroPoint.
      */
     TRANSPOSE_CONV_2D = 91,
 
@@ -4584,8 +4499,6 @@
      *      A 3-D tensor of shape:
      *        If time-major: [max_time, batch_size, output_size]
      *        If batch-major: [batch_size, max_time, output_size]
-     *
-     * Available since API level 29.
      */
     UNIDIRECTIONAL_SEQUENCE_LSTM = 92,
 
@@ -4641,8 +4554,6 @@
      *      it is set to 1, then the output has a shape [maxTime, batchSize,
      *      numUnits], otherwise the output has a shape [batchSize, maxTime,
      *      numUnits].
-     *
-     * Available since API level 29.
      */
     UNIDIRECTIONAL_SEQUENCE_RNN = 93,
 
@@ -4696,8 +4607,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, new_height, new_width, depth].
-     *
-     * Available since API level 29.
+     *      For a {@link OperandType::TENSOR_QUANT8_ASYMM} tensor,
+     *      the scale and zeroPoint must be the same as input0.
      */
     RESIZE_NEAREST_NEIGHBOR = 94,
 
diff --git a/neuralnetworks/1.2/types.t b/neuralnetworks/1.2/types.t
new file mode 100644
index 0000000..cab330d
--- /dev/null
+++ b/neuralnetworks/1.2/types.t
@@ -0,0 +1,745 @@
+%% template file for generating types.hal.
+%% see frameworks/ml/nn/tools/api/README.md.
+/*
+ * 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.
+ */
+
+package android.hardware.neuralnetworks@1.2;
+
+import @1.0::DataLocation;
+import @1.0::ErrorStatus;
+import @1.0::OperandLifeTime;
+import @1.0::OperandType;
+import @1.0::PerformanceInfo;
+import @1.1::OperationType;
+
+import android.hidl.safe_union@1.0::Monostate;
+
+enum Constant : uint32_t {
+    /**
+     * The byte size of the cache token.
+     */
+    BYTE_SIZE_OF_CACHE_TOKEN = 32,
+
+    /**
+     * The maximum number of files for each type of cache in compilation caching.
+     */
+    MAX_NUMBER_OF_CACHE_FILES = 32,
+};
+
+enum OperandType : @1.0::OperandType {
+%insert Operand_1.2
+
+    /*
+     * DEPRECATED. Since HAL version 1.2, extensions are the preferred
+     * alternative to OEM operation and data types.
+     *
+     * OEM specific scalar value.
+     * OEM                 = 10000,
+     */
+    /*
+     * DEPRECATED. Since HAL version 1.2, extensions are the preferred
+     * alternative to OEM operation and data types.
+     *
+     * A tensor of OEM specific values.
+     * TENSOR_OEM_BYTE     = 10001,
+     */
+    /* ADDING A NEW FUNDAMENTAL TYPE REQUIRES UPDATING THE VALUE OF
+     * OperandTypeRange::FUNDAMENTAL_MAX.
+     */
+    /* ADDING A NEW OEM TYPE REQUIRES UPDATING THE VALUE OF
+     * OperandTypeRange::OEM_MAX.
+     */
+};
+
+/**
+ * The range of operand values in the OperandType enum.
+ */
+enum OperandTypeRange : uint32_t {
+    BASE_MIN        = 0,
+    FUNDAMENTAL_MIN = 0,
+%insert Operand_1.2_MAX
+    OEM_MIN         = 10000,
+    OEM_MAX         = 10001,
+    BASE_MAX        = 0xFFFF,
+};
+
+/**
+ * Operation types.
+ *
+ * The type of an operation in a model.
+ */
+enum OperationType : int32_t {
+
+%insert Operation_1.0
+
+%insert Operation_1.1
+
+%insert Operation_1.2
+
+    /**
+     * DEPRECATED. Since NNAPI 1.2, extensions are the preferred alternative to
+     * OEM operation and data types.
+     *
+     * This operation is OEM specific. It should only be used for OEM
+     * applications.
+     */
+    OEM_OPERATION = @1.1::OperationType:OEM_OPERATION,
+    /* ADDING A NEW FUNDAMENTAL OPERATION REQUIRES UPDATING THE VALUE OF
+     * OperationTypeRange::FUNDAMENTAL_MAX.
+     */
+    /* ADDING A NEW OEM OPERATION REQUIRES UPDATING THE VALUE OF
+     * OperationTypeRange::OEM_MAX.
+     */
+};
+
+/**
+ * The range of values in the OperationType enum.
+ */
+enum OperationTypeRange : uint32_t {
+    BASE_MIN        = 0,
+    FUNDAMENTAL_MIN = 0,
+%insert Operation_1.2_MAX
+    OEM_MIN         = 10000,
+    OEM_MAX         = 10000,
+    BASE_MAX        = 0xFFFF,
+};
+
+/**
+ * Device types.
+ *
+ * The type of NNAPI device.
+ */
+enum DeviceType : int32_t {
+    // Leaving 0 unused as it means unknown type in NDK NNAPI. There is no
+    // HAL equivalent of unknown type and a 1.2 HAL implementation must belong
+    // to one of the categories below.
+    /** The device does not fall into any category below. */
+    OTHER             = 1,
+    /** The device runs NNAPI models on single or multi-core CPU. */
+    CPU               = 2,
+    /** The device can run NNAPI models and also accelerate graphics APIs such
+      * as OpenGL ES and Vulkan. */
+    GPU               = 3,
+    /** Dedicated accelerator for Machine Learning workloads. */
+    ACCELERATOR       = 4,
+};
+
+/**
+ * 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.
+ */
+struct Capabilities {
+    /**
+     * Driver performance when operating on float32 data but performing
+     * calculations with range and/or precision as low as that of the IEEE
+     * 754 16-bit floating-point format.
+     */
+    PerformanceInfo relaxedFloat32toFloat16PerformanceScalar;
+    PerformanceInfo relaxedFloat32toFloat16PerformanceTensor;
+
+    /**
+     * Driver performance when operating on a particular data type.
+     * In the case of float32 data, this is used when the calculations
+     * are not relaxed.
+     */
+    struct OperandPerformance {
+        OperandType type;
+        PerformanceInfo info;
+    };
+
+    /**
+     * Performance by operand type. Must be sorted by OperandType.
+     * If a particular OperandType is not present in operandPerformance,
+     * its performance is treated as { .execTime = FLT_MAX, .powerUsage = FLT_MAX }.
+     */
+    vec<OperandPerformance> operandPerformance;
+};
+
+/**
+ * Describes one operation of the model's graph.
+ */
+struct Operation {
+    /**
+     * The operation type.
+     *
+     * Besides the values listed in {@link OperationType}, any value above
+     * {@link OperationTypeRange::BASE_MAX} is possible and should be interpreted
+     * as an extension type according to {@link Model::extensionNameToPrefix}.
+     */
+    OperationType type;
+
+    /**
+     * Describes the table that contains the indexes of the inputs of the
+     * operation. The offset is the index in the operandIndexes table.
+     */
+    vec<uint32_t> inputs;
+
+    /**
+     * Describes the table that contains the indexes of the outputs of the
+     * operation. The offset is the index in the operandIndexes table.
+     */
+    vec<uint32_t> outputs;
+};
+
+/**
+ * Parameters for TENSOR_QUANT8_SYMM_PER_CHANNEL operand.
+ */
+struct SymmPerChannelQuantParams {
+    /** Array of scaling values for each channel. Each value must be greater than zero. */
+    vec<float> scales;
+    /** Index of the channel dimension */
+    uint32_t channelDim;
+};
+
+/**
+ * Describes one operand of the model's graph.
+ */
+struct Operand {
+    /**
+     * The data type.
+     *
+     * Besides the values listed in {@link OperandType}, any value above
+     * {@link OperandTypeRange::BASE_MAX} is possible and should be interpreted
+     * as an extension type according to {@link Model::extensionNameToPrefix}.
+     */
+    OperandType type;
+
+    /**
+     * Dimensions of the operand.
+     *
+     * For a scalar operand, dimensions.size() must be 0.
+     *
+     * A tensor operand with all dimensions specified has "fully
+     * specified" dimensions. Whenever possible (i.e., whenever the
+     * dimensions are known at model construction time), a tensor
+     * operand should have (but is not required to have) fully
+     * specified dimensions, in order to enable the best possible
+     * performance.
+     *
+     * If a tensor operand's dimensions are not fully specified, the
+     * dimensions of the operand are deduced from the operand
+     * dimensions and values of the operation for which that operand
+     * is an output.
+     *
+     * In the following situations, a tensor operand's dimensions must
+     * be fully specified:
+     *
+     *     . The operand has lifetime CONSTANT_COPY or
+     *       CONSTANT_REFERENCE.
+     *
+     *     . The operand has lifetime MODEL_INPUT. Fully
+     *       specified dimensions must either be present in the
+     *       Operand or they must be provided in the corresponding
+     *       RequestArgument.
+     *       EXCEPTION: If the input is optional and omitted
+     *       (by setting the hasNoValue field of the corresponding
+     *       RequestArgument to true) then it need not have fully
+     *       specified dimensions.
+     *
+     * A tensor operand with some number of unspecified dimensions is
+     * represented by setting each unspecified dimension to 0.
+     *
+     * A tensor operand with unspecified rank is represented by providing
+     * an empty dimensions vector.
+     */
+    vec<uint32_t> dimensions;
+
+    /**
+     * The number of times this operand appears as an operation input.
+     *
+     * (For example, if this operand appears once in one operation's
+     * input list, and three times in another operation's input list,
+     * then numberOfConsumers = 4.)
+     */
+    uint32_t numberOfConsumers;
+
+    /**
+     * Quantized scale of the operand.
+     *
+     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM or
+     * TENSOR_INT32.
+     */
+    float scale;
+
+    /**
+     * Quantized zero-point offset of the operand.
+     *
+     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
+     */
+    int32_t zeroPoint;
+
+    /**
+     * How the operand is used.
+     */
+    OperandLifeTime lifetime;
+
+    /**
+     * Where to find the data for this operand.
+     * If the lifetime is TEMPORARY_VARIABLE, MODEL_INPUT, MODEL_OUTPUT, or
+     * NO_VALUE:
+     * - All the fields must be 0.
+     * If the lifetime is CONSTANT_COPY:
+     * - location.poolIndex is 0.
+     * - location.offset is the offset in bytes into Model.operandValues.
+     * - location.length is set.
+     * If the lifetime is CONSTANT_REFERENCE:
+     * - location.poolIndex is set.
+     * - location.offset is the offset in bytes into the specified pool.
+     * - location.length is set.
+     */
+    DataLocation location;
+
+    /**
+     * 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;
+};
+
+/**
+ * A Neural Network Model.
+ *
+ * This includes not only the execution graph, but also constant data such as
+ * weights or scalars added at construction time. The only information that
+ * may not be known is the shape of the input tensors.
+ */
+struct Model {
+    /**
+     * All operands included in the model.
+     */
+    vec<Operand> operands;
+
+    /**
+     * All operations included in the model.
+     *
+     * The operations are sorted into execution order. Every operand
+     * with lifetime MODEL_OUTPUT or TEMPORARY_VARIABLE must be
+     * written before it is read.
+     */
+    vec<Operation> operations;
+
+    /**
+     * Input indexes of the model. There must be at least one.
+     *
+     * Each value corresponds to the index of the operand in "operands".
+     */
+    vec<uint32_t> inputIndexes;
+
+    /**
+     * Output indexes of the model. There must be at least one.
+     *
+     * Each value corresponds to the index of the operand in "operands".
+     */
+    vec<uint32_t> outputIndexes;
+
+    /**
+     * A byte buffer containing operand data that were copied into the model.
+     *
+     * An operand's value must be located here if and only if Operand::lifetime
+     * equals OperandLifeTime::CONSTANT_COPY.
+     */
+    vec<uint8_t> operandValues;
+
+    /**
+     * A collection of shared memory pools containing operand values.
+     *
+     * An operand's value must be located here if and only if Operand::lifetime
+     * equals OperandLifeTime::CONSTANT_REFERENCE.
+     */
+    vec<memory> pools;
+
+    /**
+     * 'true' indicates TENSOR_FLOAT32 may be calculated with range and/or
+     * precision as low as that of the IEEE 754 16-bit floating-point format.
+     * 'false' indicates TENSOR_FLOAT32 must be calculated using at least the
+     * range and precision of the IEEE 754 32-bit floating-point format.
+     */
+    bool relaxComputationFloat32toFloat16;
+
+    /**
+     * The mapping between extension names and prefixes of operand and
+     * operation type values.
+     *
+     * An operand or operation whose numeric type value is above
+     * {@link OperandTypeRange::BASE_MAX} or
+     * {@link OperationTypeRange::BASE_MAX} respectively should be interpreted
+     * as an extension operand. The low
+     * {@link Model::ExtensionTypeEncoding::LOW_BITS_TYPE} bits of the value
+     * correspond to the type ID within the extension and the high
+     * {@link Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX} bits encode
+     * the "prefix", which maps uniquely to the extension name.
+     *
+     * For example, if a model contains an operation whose value is
+     * 0xAAAABBBB and extensionNameToPrefix contains an entry with
+     * prefix=0xAAAA and name="vendor.test.test_extension", then
+     * the operation should be interpreted as the operation 0xBBBB
+     * of the extension named vendor.test.test_extension.
+     *
+     * This is a one-to-one correspondence. That is, there must be at most one
+     * prefix corresponding to each extension name and at most one extension
+     * name corresponding to each prefix.
+     */
+    vec<ExtensionNameAndPrefix> extensionNameToPrefix;
+
+    /**
+     * A correspondence between an extension name and a prefix of operand and
+     * operation type values.
+     */
+    struct ExtensionNameAndPrefix {
+        /**
+         * The extension name.
+         *
+         * See {@link Extension::name} for the format specification.
+         */
+        string name;
+
+        /**
+         * The unique extension identifier within the model.
+         *
+         * See {@link Model::extensionNameToPrefix}.
+         */
+        uint16_t prefix;
+    };
+
+    /**
+     * Numeric values of extension operand and operation types have the
+     * following structure:
+     * - 16 high bits represent the "prefix", which corresponds uniquely to the
+     *   extension name.
+     * - 16 low bits represent the type ID within the extension.
+     */
+    enum ExtensionTypeEncoding : uint8_t {
+        HIGH_BITS_PREFIX = 16,
+        LOW_BITS_TYPE = 16,
+    };
+};
+
+/**
+ * Describes the shape information of an output operand after execution.
+ */
+struct OutputShape {
+    /**
+     * Dimensions of the operand.
+     */
+    vec<uint32_t> dimensions;
+
+    /**
+     * Whether the provided buffer size is sufficient for the output.
+     */
+    bool isSufficient;
+};
+
+/**
+ * Specifies whether or not to measure timing information during execution.
+ */
+enum MeasureTiming : int32_t {
+    NO  = 0,
+    YES = 1,
+};
+
+/**
+
+ * Timing information measured during execution. Each time is a duration from
+ * the beginning of some task to the end of that task, including time when that
+ * task is not active (for example, preempted by some other task, or
+ * waiting for some resource to become available).
+ *
+ * Times are measured in microseconds.
+ * When a time is not available, it must be reported as UINT64_MAX.
+ */
+struct Timing {
+    /** Execution time on device (not driver, which runs on host processor). */
+    uint64_t timeOnDevice;
+    /** Execution time in driver (including time on device). */
+    uint64_t timeInDriver;
+};
+
+/**
+ * FmqRequestDatum is a single element of a serialized representation of an
+ * execution request (a {@link @1.0::Request} object and a {@link MeasureTiming}
+ * value) which is sent across FastMessageQueue.
+ *
+ * The serialized representation for a particular execution is referred to later
+ * in these descriptions as a 'packet'.
+ *
+ * FastMessageQueue can only pass HIDL-defined types that do not involve nested
+ * buffers, handles, or interfaces.
+ *
+ * The request is serialized as follows:
+ * 1) 'packetInformation'
+ * 2) For each input operand:
+ *    2.1) 'inputOperandInformation'
+ *    2.2) For each dimension element of the operand:
+ *         2.2.1) 'inputOperandDimensionValue'
+ * 3) For each output operand:
+ *    3.1) 'outputOperandInformation'
+ *    3.2) For each dimension element of the operand:
+ *         3.2.1) 'outputOperandDimensionValue'
+ * 4) For each pool:
+ *    4.1) 'poolIdentifier'
+ * 5) 'measureTiming'
+ */
+safe_union FmqRequestDatum {
+    /**
+     * Type to describe the high-level layout of the packet.
+     */
+    struct PacketInformation {
+        /**
+         * How many elements the packet contains, including the
+         * "packetInformation" datum.
+         */
+        uint32_t packetSize;
+
+        /**
+         * Number of input operands.
+         */
+        uint32_t numberOfInputOperands;
+
+        /**
+         * Number of output operands.
+         */
+        uint32_t numberOfOutputOperands;
+
+        /**
+         * Number of pool identifiers.
+         */
+        uint32_t numberOfPools;
+    };
+
+    /**
+     * Type representing the information for each operand.
+     */
+    struct OperandInformation {
+        /**
+         * If true, the argument does not have a value. This can be used for
+         * operations that take optional arguments. If true, the fields of
+         * 'location' are set to 0, 'numberOfDimensions' is set to 0,  and the
+         * dimensions information is omitted from the serialization.
+         */
+        bool hasNoValue;
+
+        /**
+         * The location within one of the memory pools passed in the Request.
+         */
+        DataLocation location;
+
+        /**
+         * Number of subsequent elements that belong to the dimensions vector.
+         */
+        uint32_t numberOfDimensions;
+    };
+
+    /**
+     * packetInformation is the first element of the packet and describes the
+     * remainder of the packet.
+     */
+    PacketInformation packetInformation;
+
+    /**
+     * Information for each input operand.
+     */
+    OperandInformation inputOperandInformation;
+
+    /**
+     * Element of the dimensions vector.
+     */
+    uint32_t inputOperandDimensionValue;
+
+    /**
+     * Information for each output operand.
+     */
+    OperandInformation outputOperandInformation;
+
+    /**
+     * Element of the dimensions vector.
+     */
+    uint32_t outputOperandDimensionValue;
+
+    /**
+     * Unique identifier for a pool.
+     *
+     * A {@link @1.0::Request} passes across one or more pools of shared memory
+     * for the inputs and outputs of an execution. However, these memory pools
+     * are not able to be sent across FastMessageQueue directly. Instead, the
+     * producing side of the FMQ represents each different pool with a unique
+     * identifier, and sends this identifier across the FMQ. Whenever the
+     * consuming side of the FMQ needs the memory corresponding to this unique
+     * identifier, it can pass the identifier to
+     * {@link IBurstCallback::getMemories} to retreive the memory. Although this
+     * HIDL Binder call is expensive compared to communication across FMQ, it is
+     * only needed in the cases when the consumer does not recognize the unique
+     * identifier.
+     */
+    int32_t poolIdentifier;
+
+    /**
+     * Specifies whether or not to measure duration of the execution. The
+     * duration runs from the time the driver dequeues the request from a
+     * FastMessageQueue to the time the driver enqueues results to a
+     * FastMessageQueue.
+     */
+    MeasureTiming measureTiming;
+};
+
+/**
+ * FmqResultDatum is a single element of a serialized representation of the
+ * values returned from an execution ({@link @1.0::ErrorStatus},
+ * vec<{@link OutputShape}>, and {@link Timing}) which is returned via
+ * FastMessageQueue.
+ *
+ * The serialized representation for a particular execution is referred to later
+ * in these descriptions as a 'packet'.
+ *
+ * FastMessageQueue can only pass HIDL-defined types that do not involve nested
+ * buffers, handles, or interfaces.
+ *
+ * The execution return values ({@link @1.0::ErrorStatus} and
+ * vec<{@link OutputShape}>) are serialized as follows:
+ * 1) 'packetInformation'
+ * 2) For each returned operand:
+ *    2.1) 'operandInformation'
+ *    2.2) For each dimension element of the operand:
+ *         2.2.1) 'operandDimensionValue'
+ * 3) 'executionTiming'
+ */
+safe_union FmqResultDatum {
+    /**
+     * Type to describe the high-level layout of the packet.
+     */
+    struct PacketInformation {
+        /**
+         * How many elements the packet contains, including the
+         * "packetInformation" datum.
+         */
+        uint32_t packetSize;
+
+        /**
+         * Status of the execution.
+         */
+        ErrorStatus errorStatus;
+
+        /**
+         * Number of returned operands.
+         */
+        uint32_t numberOfOperands;
+    };
+
+    /**
+     * Type representing the information for each operand.
+     */
+    struct OperandInformation {
+        /**
+         * Indicates whether the operand's output buffer is large enough to
+         * store the operand's result data.
+         */
+        bool isSufficient;
+
+        /**
+         * Number of subsequent elements that belong to the dimensions vector.
+         */
+        uint32_t numberOfDimensions;
+    };
+
+    /**
+     * packetInformation is the first element of the packet and describes the
+     * remainder of the packet. It additionally includes the status of the
+     * execution.
+     */
+    PacketInformation packetInformation;
+
+    /**
+     * Information for each returned operand.
+     */
+    OperandInformation operandInformation;
+
+    /**
+     * Element of the dimensions vector.
+     */
+    uint32_t operandDimensionValue;
+
+    /**
+     * Duration of execution. Unless measurement was requested and execution
+     * succeeds, all times must be reported as UINT64_MAX. A driver may choose
+     * to report any time as UINT64_MAX, indicating that measurement is not
+     * available.
+     */
+    Timing executionTiming;
+};
+
+/**
+ * Information about an extension.
+ */
+struct Extension {
+    /**
+     * The extension name.
+     *
+     * The name must consist of lowercase latin letters, numbers, periods, and
+     * underscore signs. The name must contain at least one period.
+     *
+     * The name must start with the reverse domain name of the vendor.
+     *
+     * Example: com.google.test_extension
+     */
+    string name;
+
+    /**
+     * Information about an extension operand type.
+     */
+    struct OperandTypeInformation {
+        /**
+         * The extension operand type.
+         */
+        uint16_t type;
+
+        /**
+         * Indicates whether the extension operand type represents a tensor or
+         * a scalar.
+         */
+        bool isTensor;
+
+        /**
+         * The byte size of the operand (if scalar) or of a single element (if
+         * tensor).
+         */
+        uint32_t byteSize;
+    };
+
+    /**
+     * Information about operand types defined by the extension.
+     */
+    vec<OperandTypeInformation> operandTypes;
+};
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
index 6c26820..3ba8879 100644
--- a/neuralnetworks/1.2/vts/functional/Android.bp
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -14,57 +14,44 @@
 // limitations under the License.
 //
 
-// Tests for V1_0 models using the V1_2 HAL.
-cc_test {
-    name: "VtsHalNeuralnetworksV1_2CompatV1_0TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
-    srcs: [
-        "GeneratedTestsV1_0.cpp",
-        "ValidateBurst.cpp",
-    ],
-    cflags: [
-        "-DNN_TEST_DYNAMIC_OUTPUT_SHAPE"
-    ],
-}
-
-// Tests for V1_1 models using the V1_2 HAL.
-cc_test {
-    name: "VtsHalNeuralnetworksV1_2CompatV1_1TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
-    srcs: [
-        "GeneratedTestsV1_1.cpp",
-        "ValidateBurst.cpp",
-    ],
-    cflags: [
-        "-DNN_TEST_DYNAMIC_OUTPUT_SHAPE"
-    ],
-}
-
-// Tests for V1_2 models.
 cc_test {
     name: "VtsHalNeuralnetworksV1_2TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "BasicTests.cpp",
+        "Callbacks.cpp",
         "CompilationCachingTests.cpp",
-        "GeneratedTests.cpp",
+        "GeneratedTestHarness.cpp",
+        "TestAssertions.cpp",
+        "ValidateModel.cpp",
+        "ValidateRequest.cpp",
         "ValidateBurst.cpp",
+        "VtsHalNeuralnetworks.cpp",
     ],
-    cflags: [
-        "-DNN_TEST_DYNAMIC_OUTPUT_SHAPE"
+    local_include_dirs: ["include"],
+    shared_libs: [
+        "libfmq",
+        "libnativewindow",
     ],
-}
-
-cc_test {
-    name: "PresubmitHalNeuralnetworksV1_2TargetTest",
-    defaults: ["VtsHalNeuralNetworksTargetTestDefaults"],
-    srcs: [
-        "BasicTests.cpp",
-        "GeneratedTests.cpp",
-        "ValidateBurst.cpp",
+    static_libs: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hardware.neuralnetworks@1.1",
+        "android.hardware.neuralnetworks@1.2",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libgmock",
+        "libhidlmemory",
+        "libneuralnetworks_generated_test_harness",
+        "libneuralnetworks_utils",
+        "VtsHalNeuralNetworksV1_0_utils",
     ],
-    cflags: [
-        "-DNN_TEST_DYNAMIC_OUTPUT_SHAPE",
-        "-DPRESUBMIT_NOT_VTS",
+    whole_static_libs: [
+        "neuralnetworks_generated_V1_0_example",
+        "neuralnetworks_generated_V1_1_example",
+        "neuralnetworks_generated_V1_2_example",
     ],
+    header_libs: [
+        "libneuralnetworks_headers",
+    ],
+    test_suites: ["general-tests"],
 }
diff --git a/neuralnetworks/1.2/vts/functional/BasicTests.cpp b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
index 5c269df..8e82c53 100644
--- a/neuralnetworks/1.2/vts/functional/BasicTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
@@ -18,30 +18,27 @@
 
 #include "VtsHalNeuralnetworks.h"
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
 
+using V1_0::DeviceStatus;
+using V1_0::ErrorStatus;
 using V1_0::PerformanceInfo;
 
 // create device test
-TEST_F(NeuralnetworksHidlTest, CreateDevice) {}
+TEST_P(NeuralnetworksHidlTest, CreateDevice) {}
 
 // status test
-TEST_F(NeuralnetworksHidlTest, StatusTest) {
-    Return<DeviceStatus> status = device->getStatus();
+TEST_P(NeuralnetworksHidlTest, StatusTest) {
+    Return<DeviceStatus> status = kDevice->getStatus();
     ASSERT_TRUE(status.isOk());
     EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status));
 }
 
 // initialization
-TEST_F(NeuralnetworksHidlTest, GetCapabilitiesTest) {
+TEST_P(NeuralnetworksHidlTest, GetCapabilitiesTest) {
     using OperandPerformance = Capabilities::OperandPerformance;
-    Return<void> ret = device->getCapabilities_1_2([](ErrorStatus status,
-                                                      const Capabilities& capabilities) {
+    Return<void> ret = kDevice->getCapabilities_1_2([](ErrorStatus status,
+                                                       const Capabilities& capabilities) {
         EXPECT_EQ(ErrorStatus::NONE, status);
 
         auto isPositive = [](const PerformanceInfo& perf) {
@@ -63,17 +60,18 @@
 }
 
 // device version test
-TEST_F(NeuralnetworksHidlTest, GetDeviceVersionStringTest) {
-    Return<void> ret = device->getVersionString([](ErrorStatus status, const hidl_string& version) {
-        EXPECT_EQ(ErrorStatus::NONE, status);
-        EXPECT_LT(0, version.size());
-    });
+TEST_P(NeuralnetworksHidlTest, GetDeviceVersionStringTest) {
+    Return<void> ret =
+            kDevice->getVersionString([](ErrorStatus status, const hidl_string& version) {
+                EXPECT_EQ(ErrorStatus::NONE, status);
+                EXPECT_LT(0, version.size());
+            });
     EXPECT_TRUE(ret.isOk());
 }
 
 // device type test
-TEST_F(NeuralnetworksHidlTest, GetDeviceTypeTest) {
-    Return<void> ret = device->getType([](ErrorStatus status, DeviceType type) {
+TEST_P(NeuralnetworksHidlTest, GetDeviceTypeTest) {
+    Return<void> ret = kDevice->getType([](ErrorStatus status, DeviceType type) {
         EXPECT_EQ(ErrorStatus::NONE, status);
         EXPECT_TRUE(type == DeviceType::OTHER || type == DeviceType::CPU ||
                     type == DeviceType::GPU || type == DeviceType::ACCELERATOR);
@@ -82,8 +80,8 @@
 }
 
 // device supported extensions test
-TEST_F(NeuralnetworksHidlTest, GetDeviceSupportedExtensionsTest) {
-    Return<void> ret = device->getSupportedExtensions(
+TEST_P(NeuralnetworksHidlTest, GetDeviceSupportedExtensionsTest) {
+    Return<void> ret = kDevice->getSupportedExtensions(
             [](ErrorStatus status, const hidl_vec<Extension>& extensions) {
                 EXPECT_EQ(ErrorStatus::NONE, status);
                 for (auto& extension : extensions) {
@@ -103,8 +101,8 @@
 }
 
 // getNumberOfCacheFilesNeeded test
-TEST_F(NeuralnetworksHidlTest, getNumberOfCacheFilesNeeded) {
-    Return<void> ret = device->getNumberOfCacheFilesNeeded(
+TEST_P(NeuralnetworksHidlTest, getNumberOfCacheFilesNeeded) {
+    Return<void> ret = kDevice->getNumberOfCacheFilesNeeded(
             [](ErrorStatus status, uint32_t numModelCache, uint32_t numDataCache) {
                 EXPECT_EQ(ErrorStatus::NONE, status);
                 EXPECT_LE(numModelCache,
@@ -113,9 +111,4 @@
             });
     EXPECT_TRUE(ret.isOk());
 }
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_2
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::neuralnetworks::V1_2::vts::functional
diff --git a/neuralnetworks/1.2/vts/functional/Callbacks.cpp b/neuralnetworks/1.2/vts/functional/Callbacks.cpp
new file mode 100644
index 0000000..3972ad6
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/Callbacks.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Callbacks"
+
+#include "1.2/Callbacks.h"
+
+#include <android-base/logging.h>
+
+#include <limits>
+
+namespace android::hardware::neuralnetworks::V1_2::implementation {
+
+using V1_0::ErrorStatus;
+
+constexpr Timing kNoTiming = {.timeOnDevice = std::numeric_limits<uint64_t>::max(),
+                              .timeInDriver = std::numeric_limits<uint64_t>::max()};
+
+// PreparedModelCallback methods begin here
+
+Return<void> PreparedModelCallback::notify(ErrorStatus errorStatus,
+                                           const sp<V1_0::IPreparedModel>& preparedModel) {
+    {
+        std::lock_guard<std::mutex> hold(mMutex);
+
+        // quick-return if object has already been notified
+        if (mNotified) {
+            return Void();
+        }
+
+        // store results and mark as notified
+        mErrorStatus = errorStatus;
+        mPreparedModel = preparedModel;
+        mNotified = true;
+    }
+
+    mCondition.notify_all();
+    return Void();
+}
+
+Return<void> PreparedModelCallback::notify_1_2(ErrorStatus errorStatus,
+                                               const sp<V1_2::IPreparedModel>& preparedModel) {
+    return notify(errorStatus, preparedModel);
+}
+
+void PreparedModelCallback::wait() const {
+    std::unique_lock<std::mutex> lock(mMutex);
+    mCondition.wait(lock, [this] { return mNotified; });
+}
+
+ErrorStatus PreparedModelCallback::getStatus() const {
+    wait();
+    return mErrorStatus;
+}
+
+sp<V1_0::IPreparedModel> PreparedModelCallback::getPreparedModel() const {
+    wait();
+    return mPreparedModel;
+}
+
+// ExecutionCallback methods begin here
+
+Return<void> ExecutionCallback::notify(ErrorStatus errorStatus) {
+    notifyInternal(errorStatus, {}, kNoTiming);
+    return Void();
+}
+
+Return<void> ExecutionCallback::notify_1_2(ErrorStatus errorStatus,
+                                           const hidl_vec<OutputShape>& outputShapes,
+                                           const Timing& timing) {
+    if (errorStatus == ErrorStatus::OUTPUT_INSUFFICIENT_SIZE) {
+        // outputShapes must not be empty if OUTPUT_INSUFFICIENT_SIZE.
+        if (outputShapes.size() == 0) {
+            LOG(ERROR) << "Notified with empty output shape vector when OUTPUT_INSUFFICIENT_SIZE";
+            notifyInternal(ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
+            return Void();
+        }
+    } else if (errorStatus != ErrorStatus::NONE) {
+        // outputShapes must be empty if errorStatus is neither NONE nor OUTPUT_INSUFFICIENT_SIZE.
+        if (outputShapes.size() != 0) {
+            LOG(ERROR) << "Notified with non-empty output shape vector when error status is "
+                          "neither NONE nor OUTPUT_INSUFFICIENT_SIZE";
+            notifyInternal(ErrorStatus::GENERAL_FAILURE, {}, kNoTiming);
+            return Void();
+        }
+    }
+    notifyInternal(errorStatus, outputShapes, timing);
+    return Void();
+}
+
+void ExecutionCallback::wait() const {
+    std::unique_lock<std::mutex> lock(mMutex);
+    mCondition.wait(lock, [this] { return mNotified; });
+}
+
+ErrorStatus ExecutionCallback::getStatus() const {
+    wait();
+    return mErrorStatus;
+}
+
+const std::vector<OutputShape>& ExecutionCallback::getOutputShapes() const {
+    wait();
+    return mOutputShapes;
+}
+
+Timing ExecutionCallback::getTiming() const {
+    wait();
+    return mTiming;
+}
+
+void ExecutionCallback::notifyInternal(ErrorStatus errorStatus,
+                                       const hidl_vec<OutputShape>& outputShapes,
+                                       const Timing& timing) {
+    {
+        std::lock_guard<std::mutex> hold(mMutex);
+
+        // quick-return if object has already been notified
+        if (mNotified) {
+            return;
+        }
+
+        mErrorStatus = errorStatus;
+        mOutputShapes = outputShapes;
+        mTiming = timing;
+        mNotified = true;
+    }
+    mCondition.notify_all();
+}
+
+}  // namespace android::hardware::neuralnetworks::V1_2::implementation
diff --git a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
index 4411b90..2130a76 100644
--- a/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
+++ b/neuralnetworks/1.2/vts/functional/CompilationCachingTests.cpp
@@ -17,7 +17,7 @@
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
 #include <android-base/logging.h>
-#include <android/hidl/memory/1.0/IMemory.h>
+#include <fcntl.h>
 #include <ftw.h>
 #include <gtest/gtest.h>
 #include <hidlmemory/mapping.h>
@@ -26,68 +26,41 @@
 #include <cstdio>
 #include <cstdlib>
 #include <random>
+#include <thread>
 
-#include "Callbacks.h"
+#include "1.2/Callbacks.h"
 #include "GeneratedTestHarness.h"
+#include "MemoryUtils.h"
 #include "TestHarness.h"
 #include "Utils.h"
 #include "VtsHalNeuralnetworks.h"
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
+// Forward declaration of the mobilenet generated test models in
+// frameworks/ml/nn/runtime/test/generated/.
+namespace generated_tests::mobilenet_224_gender_basic_fixed {
+const test_helper::TestModel& get_test_model();
+}  // namespace generated_tests::mobilenet_224_gender_basic_fixed
 
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
-using ::android::nn::allocateSharedMemory;
-using ::test_helper::MixedTypedExample;
+namespace generated_tests::mobilenet_quantized {
+const test_helper::TestModel& get_test_model();
+}  // namespace generated_tests::mobilenet_quantized
+
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
+
+using namespace test_helper;
+using implementation::PreparedModelCallback;
+using V1_0::ErrorStatus;
+using V1_1::ExecutionPreference;
 
 namespace float32_model {
 
-// In frameworks/ml/nn/runtime/test/generated/, creates a hidl model of float32 mobilenet.
-#include "examples/mobilenet_224_gender_basic_fixed.example.cpp"
-#include "vts_models/mobilenet_224_gender_basic_fixed.model.cpp"
-
-// Prevent the compiler from complaining about an otherwise unused function.
-[[maybe_unused]] auto dummy_createTestModel = createTestModel_dynamic_output_shape;
-[[maybe_unused]] auto dummy_get_examples = get_examples_dynamic_output_shape;
-
-// MixedTypedExample is defined in frameworks/ml/nn/tools/test_generator/include/TestHarness.h.
-// This function assumes the operation is always ADD.
-std::vector<MixedTypedExample> getLargeModelExamples(uint32_t len) {
-    float outputValue = 1.0f + static_cast<float>(len);
-    return {{.operands = {
-                     // Input
-                     {.operandDimensions = {{0, {1}}}, .float32Operands = {{0, {1.0f}}}},
-                     // Output
-                     {.operandDimensions = {{0, {1}}}, .float32Operands = {{0, {outputValue}}}}}}};
-}
+constexpr auto get_test_model = generated_tests::mobilenet_224_gender_basic_fixed::get_test_model;
 
 }  // namespace float32_model
 
 namespace quant8_model {
 
-// In frameworks/ml/nn/runtime/test/generated/, creates a hidl model of quant8 mobilenet.
-#include "examples/mobilenet_quantized.example.cpp"
-#include "vts_models/mobilenet_quantized.model.cpp"
-
-// Prevent the compiler from complaining about an otherwise unused function.
-[[maybe_unused]] auto dummy_createTestModel = createTestModel_dynamic_output_shape;
-[[maybe_unused]] auto dummy_get_examples = get_examples_dynamic_output_shape;
-
-// MixedTypedExample is defined in frameworks/ml/nn/tools/test_generator/include/TestHarness.h.
-// This function assumes the operation is always ADD.
-std::vector<MixedTypedExample> getLargeModelExamples(uint32_t len) {
-    uint8_t outputValue = 1 + static_cast<uint8_t>(len);
-    return {{.operands = {// Input
-                          {.operandDimensions = {{0, {1}}}, .quant8AsymmOperands = {{0, {1}}}},
-                          // Output
-                          {.operandDimensions = {{0, {1}}},
-                           .quant8AsymmOperands = {{0, {outputValue}}}}}}};
-}
+constexpr auto get_test_model = generated_tests::mobilenet_quantized::get_test_model;
 
 }  // namespace quant8_model
 
@@ -140,39 +113,34 @@
 //               [1]    [1]    [1]           [1]
 //
 // This function assumes the operation is either ADD or MUL.
-template <typename CppType, OperandType operandType>
-Model createLargeTestModelImpl(OperationType op, uint32_t len) {
-    EXPECT_TRUE(op == OperationType::ADD || op == OperationType::MUL);
+template <typename CppType, TestOperandType operandType>
+TestModel createLargeTestModelImpl(TestOperationType op, uint32_t len) {
+    EXPECT_TRUE(op == TestOperationType::ADD || op == TestOperationType::MUL);
 
     // Model operations and operands.
-    std::vector<Operation> operations(len);
-    std::vector<Operand> operands(len * 2 + 2);
-
-    // The constant buffer pool. This contains the activation scalar, followed by the
-    // per-operation constant operands.
-    std::vector<uint8_t> operandValues(sizeof(int32_t) + len * sizeof(CppType));
+    std::vector<TestOperation> operations(len);
+    std::vector<TestOperand> operands(len * 2 + 2);
 
     // The activation scalar, value = 0.
     operands[0] = {
-            .type = OperandType::INT32,
+            .type = TestOperandType::INT32,
             .dimensions = {},
             .numberOfConsumers = len,
             .scale = 0.0f,
             .zeroPoint = 0,
-            .lifetime = OperandLifeTime::CONSTANT_COPY,
-            .location = {.poolIndex = 0, .offset = 0, .length = sizeof(int32_t)},
+            .lifetime = TestOperandLifeTime::CONSTANT_COPY,
+            .data = TestBuffer::createFromVector<int32_t>({0}),
     };
-    memset(operandValues.data(), 0, sizeof(int32_t));
 
     // The buffer value of the constant second operand. The logical value is always 1.0f.
     CppType bufferValue;
     // The scale of the first and second operand.
     float scale1, scale2;
-    if (operandType == OperandType::TENSOR_FLOAT32) {
+    if (operandType == TestOperandType::TENSOR_FLOAT32) {
         bufferValue = 1.0f;
         scale1 = 0.0f;
         scale2 = 0.0f;
-    } else if (op == OperationType::ADD) {
+    } else if (op == TestOperationType::ADD) {
         bufferValue = 1;
         scale1 = 1.0f;
         scale2 = 1.0f;
@@ -196,9 +164,9 @@
                 .numberOfConsumers = 1,
                 .scale = scale1,
                 .zeroPoint = 0,
-                .lifetime = (i == 0 ? OperandLifeTime::MODEL_INPUT
-                                    : OperandLifeTime::TEMPORARY_VARIABLE),
-                .location = {},
+                .lifetime = (i == 0 ? TestOperandLifeTime::MODEL_INPUT
+                                    : TestOperandLifeTime::TEMPORARY_VARIABLE),
+                .data = (i == 0 ? TestBuffer::createFromVector<CppType>({1}) : TestBuffer()),
         };
 
         // The second operation input, value = 1.
@@ -208,13 +176,9 @@
                 .numberOfConsumers = 1,
                 .scale = scale2,
                 .zeroPoint = 0,
-                .lifetime = OperandLifeTime::CONSTANT_COPY,
-                .location = {.poolIndex = 0,
-                             .offset = static_cast<uint32_t>(i * sizeof(CppType) + sizeof(int32_t)),
-                             .length = sizeof(CppType)},
+                .lifetime = TestOperandLifeTime::CONSTANT_COPY,
+                .data = TestBuffer::createFromVector<CppType>({bufferValue}),
         };
-        memcpy(operandValues.data() + sizeof(int32_t) + i * sizeof(CppType), &bufferValue,
-               sizeof(CppType));
 
         // The operation. All operations share the same activation scalar.
         // The output operand is created as an input in the next iteration of the loop, in the case
@@ -227,6 +191,10 @@
         };
     }
 
+    // For TestOperationType::ADD, output = 1 + 1 * len = len + 1
+    // For TestOperationType::MUL, output = 1 * 1 ^ len = 1
+    CppType outputResult = static_cast<CppType>(op == TestOperationType::ADD ? len + 1u : 1u);
+
     // The model output.
     operands.back() = {
             .type = operandType,
@@ -234,34 +202,30 @@
             .numberOfConsumers = 0,
             .scale = scale1,
             .zeroPoint = 0,
-            .lifetime = OperandLifeTime::MODEL_OUTPUT,
-            .location = {},
+            .lifetime = TestOperandLifeTime::MODEL_OUTPUT,
+            .data = TestBuffer::createFromVector<CppType>({outputResult}),
     };
 
-    const std::vector<uint32_t> inputIndexes = {1};
-    const std::vector<uint32_t> outputIndexes = {len * 2 + 1};
-    const std::vector<hidl_memory> pools = {};
-
     return {
-            .operands = operands,
-            .operations = operations,
-            .inputIndexes = inputIndexes,
-            .outputIndexes = outputIndexes,
-            .operandValues = operandValues,
-            .pools = pools,
+            .operands = std::move(operands),
+            .operations = std::move(operations),
+            .inputIndexes = {1},
+            .outputIndexes = {len * 2 + 1},
+            .isRelaxed = false,
     };
 }
 
 }  // namespace
 
 // Tag for the compilation caching tests.
-class CompilationCachingTestBase : public NeuralnetworksHidlTest {
+class CompilationCachingTestBase : public testing::Test {
   protected:
-    CompilationCachingTestBase(OperandType type) : kOperandType(type) {}
+    CompilationCachingTestBase(sp<IDevice> device, OperandType type)
+        : kDevice(std::move(device)), kOperandType(type) {}
 
     void SetUp() override {
-        NeuralnetworksHidlTest::SetUp();
-        ASSERT_NE(device.get(), nullptr);
+        testing::Test::SetUp();
+        ASSERT_NE(kDevice.get(), nullptr);
 
         // Create cache directory. The cache directory and a temporary cache file is always created
         // to test the behavior of prepareModelFromCache, even when caching is not supported.
@@ -271,7 +235,7 @@
         mCacheDir = cacheDir;
         mCacheDir.push_back('/');
 
-        Return<void> ret = device->getNumberOfCacheFilesNeeded(
+        Return<void> ret = kDevice->getNumberOfCacheFilesNeeded(
                 [this](ErrorStatus status, uint32_t numModelCache, uint32_t numDataCache) {
                     EXPECT_EQ(ErrorStatus::NONE, status);
                     mNumModelCache = numModelCache;
@@ -305,54 +269,40 @@
 
     void TearDown() override {
         // If the test passes, remove the tmp directory.  Otherwise, keep it for debugging purposes.
-        if (!::testing::Test::HasFailure()) {
+        if (!testing::Test::HasFailure()) {
             // Recursively remove the cache directory specified by mCacheDir.
             auto callback = [](const char* entry, const struct stat*, int, struct FTW*) {
                 return remove(entry);
             };
             nftw(mCacheDir.c_str(), callback, 128, FTW_DEPTH | FTW_MOUNT | FTW_PHYS);
         }
-        NeuralnetworksHidlTest::TearDown();
+        testing::Test::TearDown();
     }
 
     // Model and examples creators. According to kOperandType, the following methods will return
     // either float32 model/examples or the quant8 variant.
-    Model createTestModel() {
+    TestModel createTestModel() {
         if (kOperandType == OperandType::TENSOR_FLOAT32) {
-            return float32_model::createTestModel();
+            return float32_model::get_test_model();
         } else {
-            return quant8_model::createTestModel();
+            return quant8_model::get_test_model();
         }
     }
 
-    std::vector<MixedTypedExample> get_examples() {
+    TestModel createLargeTestModel(OperationType op, uint32_t len) {
         if (kOperandType == OperandType::TENSOR_FLOAT32) {
-            return float32_model::get_examples();
+            return createLargeTestModelImpl<float, TestOperandType::TENSOR_FLOAT32>(
+                    static_cast<TestOperationType>(op), len);
         } else {
-            return quant8_model::get_examples();
-        }
-    }
-
-    Model createLargeTestModel(OperationType op, uint32_t len) {
-        if (kOperandType == OperandType::TENSOR_FLOAT32) {
-            return createLargeTestModelImpl<float, OperandType::TENSOR_FLOAT32>(op, len);
-        } else {
-            return createLargeTestModelImpl<uint8_t, OperandType::TENSOR_QUANT8_ASYMM>(op, len);
-        }
-    }
-
-    std::vector<MixedTypedExample> getLargeModelExamples(uint32_t len) {
-        if (kOperandType == OperandType::TENSOR_FLOAT32) {
-            return float32_model::getLargeModelExamples(len);
-        } else {
-            return quant8_model::getLargeModelExamples(len);
+            return createLargeTestModelImpl<uint8_t, TestOperandType::TENSOR_QUANT8_ASYMM>(
+                    static_cast<TestOperationType>(op), len);
         }
     }
 
     // See if the service can handle the model.
-    bool isModelFullySupported(const V1_2::Model& model) {
+    bool isModelFullySupported(const Model& model) {
         bool fullySupportsModel = false;
-        Return<void> supportedCall = device->getSupportedOperations_1_2(
+        Return<void> supportedCall = kDevice->getSupportedOperations_1_2(
                 model,
                 [&fullySupportsModel, &model](ErrorStatus status, const hidl_vec<bool>& supported) {
                     ASSERT_EQ(ErrorStatus::NONE, status);
@@ -364,18 +314,17 @@
         return fullySupportsModel;
     }
 
-    void saveModelToCache(const V1_2::Model& model, const hidl_vec<hidl_handle>& modelCache,
+    void saveModelToCache(const Model& model, const hidl_vec<hidl_handle>& modelCache,
                           const hidl_vec<hidl_handle>& dataCache,
                           sp<IPreparedModel>* preparedModel = nullptr) {
         if (preparedModel != nullptr) *preparedModel = nullptr;
 
         // Launch prepare model.
         sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-        ASSERT_NE(nullptr, preparedModelCallback.get());
         hidl_array<uint8_t, sizeof(mToken)> cacheToken(mToken);
         Return<ErrorStatus> prepareLaunchStatus =
-                device->prepareModel_1_2(model, ExecutionPreference::FAST_SINGLE_ANSWER, modelCache,
-                                         dataCache, cacheToken, preparedModelCallback);
+                kDevice->prepareModel_1_2(model, ExecutionPreference::FAST_SINGLE_ANSWER,
+                                          modelCache, dataCache, cacheToken, preparedModelCallback);
         ASSERT_TRUE(prepareLaunchStatus.isOk());
         ASSERT_EQ(static_cast<ErrorStatus>(prepareLaunchStatus), ErrorStatus::NONE);
 
@@ -383,9 +332,8 @@
         preparedModelCallback->wait();
         ASSERT_EQ(preparedModelCallback->getStatus(), ErrorStatus::NONE);
         if (preparedModel != nullptr) {
-            *preparedModel =
-                    V1_2::IPreparedModel::castFrom(preparedModelCallback->getPreparedModel())
-                            .withDefault(nullptr);
+            *preparedModel = IPreparedModel::castFrom(preparedModelCallback->getPreparedModel())
+                                     .withDefault(nullptr);
         }
     }
 
@@ -401,7 +349,7 @@
         return false;
     }
 
-    bool checkEarlyTermination(const V1_2::Model& model) {
+    bool checkEarlyTermination(const Model& model) {
         if (!isModelFullySupported(model)) {
             LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
                          "prepare model that it does not support.";
@@ -418,9 +366,8 @@
                                sp<IPreparedModel>* preparedModel, ErrorStatus* status) {
         // Launch prepare model from cache.
         sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-        ASSERT_NE(nullptr, preparedModelCallback.get());
         hidl_array<uint8_t, sizeof(mToken)> cacheToken(mToken);
-        Return<ErrorStatus> prepareLaunchStatus = device->prepareModelFromCache(
+        Return<ErrorStatus> prepareLaunchStatus = kDevice->prepareModelFromCache(
                 modelCache, dataCache, cacheToken, preparedModelCallback);
         ASSERT_TRUE(prepareLaunchStatus.isOk());
         if (static_cast<ErrorStatus>(prepareLaunchStatus) != ErrorStatus::NONE) {
@@ -432,7 +379,7 @@
         // Retrieve prepared model.
         preparedModelCallback->wait();
         *status = preparedModelCallback->getStatus();
-        *preparedModel = V1_2::IPreparedModel::castFrom(preparedModelCallback->getPreparedModel())
+        *preparedModel = IPreparedModel::castFrom(preparedModelCallback->getPreparedModel())
                                  .withDefault(nullptr);
     }
 
@@ -453,22 +400,28 @@
     uint32_t mNumDataCache;
     uint32_t mIsCachingSupported;
 
+    const sp<IDevice> kDevice;
     // The primary data type of the testModel.
     const OperandType kOperandType;
 };
 
+using CompilationCachingTestParam = std::tuple<NamedDevice, OperandType>;
+
 // A parameterized fixture of CompilationCachingTestBase. Every test will run twice, with the first
 // pass running with float32 models and the second pass running with quant8 models.
 class CompilationCachingTest : public CompilationCachingTestBase,
-                               public ::testing::WithParamInterface<OperandType> {
+                               public testing::WithParamInterface<CompilationCachingTestParam> {
   protected:
-    CompilationCachingTest() : CompilationCachingTestBase(GetParam()) {}
+    CompilationCachingTest()
+        : CompilationCachingTestBase(getData(std::get<NamedDevice>(GetParam())),
+                                     std::get<OperandType>(GetParam())) {}
 };
 
 TEST_P(CompilationCachingTest, CacheSavingAndRetrieval) {
     // Create test HIDL model and compile.
-    const Model testModel = createTestModel();
-    if (checkEarlyTermination(testModel)) return;
+    const TestModel& testModel = createTestModel();
+    const Model model = createModel(testModel);
+    if (checkEarlyTermination(model)) return;
     sp<IPreparedModel> preparedModel = nullptr;
 
     // Save the compilation to cache.
@@ -476,7 +429,7 @@
         hidl_vec<hidl_handle> modelCache, dataCache;
         createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
         createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
-        saveModelToCache(testModel, modelCache, dataCache);
+        saveModelToCache(model, modelCache, dataCache);
     }
 
     // Retrieve preparedModel from cache.
@@ -501,15 +454,15 @@
     }
 
     // Execute and verify results.
-    generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, get_examples(),
-                                           testModel.relaxComputationFloat32toFloat16,
-                                           /*testDynamicOutputShape=*/false);
+    EvaluatePreparedModel(preparedModel, testModel,
+                          /*testDynamicOutputShape=*/false);
 }
 
 TEST_P(CompilationCachingTest, CacheSavingAndRetrievalNonZeroOffset) {
     // Create test HIDL model and compile.
-    const Model testModel = createTestModel();
-    if (checkEarlyTermination(testModel)) return;
+    const TestModel& testModel = createTestModel();
+    const Model model = createModel(testModel);
+    if (checkEarlyTermination(model)) return;
     sp<IPreparedModel> preparedModel = nullptr;
 
     // Save the compilation to cache.
@@ -530,7 +483,7 @@
                     write(dataCache[i].getNativeHandle()->data[0], &dummyBytes, sizeof(dummyBytes)),
                     sizeof(dummyBytes));
         }
-        saveModelToCache(testModel, modelCache, dataCache);
+        saveModelToCache(model, modelCache, dataCache);
     }
 
     // Retrieve preparedModel from cache.
@@ -564,15 +517,15 @@
     }
 
     // Execute and verify results.
-    generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; }, get_examples(),
-                                           testModel.relaxComputationFloat32toFloat16,
-                                           /*testDynamicOutputShape=*/false);
+    EvaluatePreparedModel(preparedModel, testModel,
+                          /*testDynamicOutputShape=*/false);
 }
 
 TEST_P(CompilationCachingTest, SaveToCacheInvalidNumCache) {
     // Create test HIDL model and compile.
-    const Model testModel = createTestModel();
-    if (checkEarlyTermination(testModel)) return;
+    const TestModel& testModel = createTestModel();
+    const Model model = createModel(testModel);
+    if (checkEarlyTermination(model)) return;
 
     // Test with number of model cache files greater than mNumModelCache.
     {
@@ -583,13 +536,11 @@
         createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
         mModelCache.pop_back();
         sp<IPreparedModel> preparedModel = nullptr;
-        saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+        saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
-                                               get_examples(),
-                                               testModel.relaxComputationFloat32toFloat16,
-                                               /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel,
+                              /*testDynamicOutputShape=*/false);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -610,13 +561,11 @@
         createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
         mModelCache.push_back(tmp);
         sp<IPreparedModel> preparedModel = nullptr;
-        saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+        saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
-                                               get_examples(),
-                                               testModel.relaxComputationFloat32toFloat16,
-                                               /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel,
+                              /*testDynamicOutputShape=*/false);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -636,13 +585,11 @@
         createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
         mDataCache.pop_back();
         sp<IPreparedModel> preparedModel = nullptr;
-        saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+        saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
-                                               get_examples(),
-                                               testModel.relaxComputationFloat32toFloat16,
-                                               /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel,
+                              /*testDynamicOutputShape=*/false);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -663,13 +610,11 @@
         createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
         mDataCache.push_back(tmp);
         sp<IPreparedModel> preparedModel = nullptr;
-        saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+        saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
-                                               get_examples(),
-                                               testModel.relaxComputationFloat32toFloat16,
-                                               /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel,
+                              /*testDynamicOutputShape=*/false);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -683,15 +628,16 @@
 
 TEST_P(CompilationCachingTest, PrepareModelFromCacheInvalidNumCache) {
     // Create test HIDL model and compile.
-    const Model testModel = createTestModel();
-    if (checkEarlyTermination(testModel)) return;
+    const TestModel& testModel = createTestModel();
+    const Model model = createModel(testModel);
+    if (checkEarlyTermination(model)) return;
 
     // Save the compilation to cache.
     {
         hidl_vec<hidl_handle> modelCache, dataCache;
         createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
         createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
-        saveModelToCache(testModel, modelCache, dataCache);
+        saveModelToCache(model, modelCache, dataCache);
     }
 
     // Test with number of model cache files greater than mNumModelCache.
@@ -763,8 +709,9 @@
 
 TEST_P(CompilationCachingTest, SaveToCacheInvalidNumFd) {
     // Create test HIDL model and compile.
-    const Model testModel = createTestModel();
-    if (checkEarlyTermination(testModel)) return;
+    const TestModel& testModel = createTestModel();
+    const Model model = createModel(testModel);
+    if (checkEarlyTermination(model)) return;
 
     // Go through each handle in model cache, test with NumFd greater than 1.
     for (uint32_t i = 0; i < mNumModelCache; i++) {
@@ -775,13 +722,11 @@
         createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
         mModelCache[i].pop_back();
         sp<IPreparedModel> preparedModel = nullptr;
-        saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+        saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
-                                               get_examples(),
-                                               testModel.relaxComputationFloat32toFloat16,
-                                               /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel,
+                              /*testDynamicOutputShape=*/false);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -802,13 +747,11 @@
         createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
         mModelCache[i].push_back(tmp);
         sp<IPreparedModel> preparedModel = nullptr;
-        saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+        saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
-                                               get_examples(),
-                                               testModel.relaxComputationFloat32toFloat16,
-                                               /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel,
+                              /*testDynamicOutputShape=*/false);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -828,13 +771,11 @@
         createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
         mDataCache[i].pop_back();
         sp<IPreparedModel> preparedModel = nullptr;
-        saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+        saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
-                                               get_examples(),
-                                               testModel.relaxComputationFloat32toFloat16,
-                                               /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel,
+                              /*testDynamicOutputShape=*/false);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -855,13 +796,11 @@
         createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
         mDataCache[i].push_back(tmp);
         sp<IPreparedModel> preparedModel = nullptr;
-        saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+        saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
-                                               get_examples(),
-                                               testModel.relaxComputationFloat32toFloat16,
-                                               /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel,
+                              /*testDynamicOutputShape=*/false);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -875,15 +814,16 @@
 
 TEST_P(CompilationCachingTest, PrepareModelFromCacheInvalidNumFd) {
     // Create test HIDL model and compile.
-    const Model testModel = createTestModel();
-    if (checkEarlyTermination(testModel)) return;
+    const TestModel& testModel = createTestModel();
+    const Model model = createModel(testModel);
+    if (checkEarlyTermination(model)) return;
 
     // Save the compilation to cache.
     {
         hidl_vec<hidl_handle> modelCache, dataCache;
         createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
         createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
-        saveModelToCache(testModel, modelCache, dataCache);
+        saveModelToCache(model, modelCache, dataCache);
     }
 
     // Go through each handle in model cache, test with NumFd greater than 1.
@@ -955,8 +895,9 @@
 
 TEST_P(CompilationCachingTest, SaveToCacheInvalidAccessMode) {
     // Create test HIDL model and compile.
-    const Model testModel = createTestModel();
-    if (checkEarlyTermination(testModel)) return;
+    const TestModel& testModel = createTestModel();
+    const Model model = createModel(testModel);
+    if (checkEarlyTermination(model)) return;
     std::vector<AccessMode> modelCacheMode(mNumModelCache, AccessMode::READ_WRITE);
     std::vector<AccessMode> dataCacheMode(mNumDataCache, AccessMode::READ_WRITE);
 
@@ -968,13 +909,11 @@
         createCacheHandles(mDataCache, dataCacheMode, &dataCache);
         modelCacheMode[i] = AccessMode::READ_WRITE;
         sp<IPreparedModel> preparedModel = nullptr;
-        saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+        saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
-                                               get_examples(),
-                                               testModel.relaxComputationFloat32toFloat16,
-                                               /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel,
+                              /*testDynamicOutputShape=*/false);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -993,13 +932,11 @@
         createCacheHandles(mDataCache, dataCacheMode, &dataCache);
         dataCacheMode[i] = AccessMode::READ_WRITE;
         sp<IPreparedModel> preparedModel = nullptr;
-        saveModelToCache(testModel, modelCache, dataCache, &preparedModel);
+        saveModelToCache(model, modelCache, dataCache, &preparedModel);
         ASSERT_NE(preparedModel, nullptr);
         // Execute and verify results.
-        generated_tests::EvaluatePreparedModel(preparedModel, [](int) { return false; },
-                                               get_examples(),
-                                               testModel.relaxComputationFloat32toFloat16,
-                                               /*testDynamicOutputShape=*/false);
+        EvaluatePreparedModel(preparedModel, testModel,
+                              /*testDynamicOutputShape=*/false);
         // Check if prepareModelFromCache fails.
         preparedModel = nullptr;
         ErrorStatus status;
@@ -1013,8 +950,9 @@
 
 TEST_P(CompilationCachingTest, PrepareModelFromCacheInvalidAccessMode) {
     // Create test HIDL model and compile.
-    const Model testModel = createTestModel();
-    if (checkEarlyTermination(testModel)) return;
+    const TestModel& testModel = createTestModel();
+    const Model model = createModel(testModel);
+    if (checkEarlyTermination(model)) return;
     std::vector<AccessMode> modelCacheMode(mNumModelCache, AccessMode::READ_WRITE);
     std::vector<AccessMode> dataCacheMode(mNumDataCache, AccessMode::READ_WRITE);
 
@@ -1023,7 +961,7 @@
         hidl_vec<hidl_handle> modelCache, dataCache;
         createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
         createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
-        saveModelToCache(testModel, modelCache, dataCache);
+        saveModelToCache(model, modelCache, dataCache);
     }
 
     // Go through each handle in model cache, test with invalid access mode.
@@ -1091,12 +1029,14 @@
     if (!mIsCachingSupported) return;
 
     // Create test models and check if fully supported by the service.
-    const Model testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize);
-    if (checkEarlyTermination(testModelMul)) return;
-    const Model testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize);
-    if (checkEarlyTermination(testModelAdd)) return;
+    const TestModel testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize);
+    const Model modelMul = createModel(testModelMul);
+    if (checkEarlyTermination(modelMul)) return;
+    const TestModel testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize);
+    const Model modelAdd = createModel(testModelAdd);
+    if (checkEarlyTermination(modelAdd)) return;
 
-    // Save the testModelMul compilation to cache.
+    // Save the modelMul compilation to cache.
     auto modelCacheMul = mModelCache;
     for (auto& cache : modelCacheMul) {
         cache[0].append("_mul");
@@ -1105,15 +1045,15 @@
         hidl_vec<hidl_handle> modelCache, dataCache;
         createCacheHandles(modelCacheMul, AccessMode::READ_WRITE, &modelCache);
         createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
-        saveModelToCache(testModelMul, modelCache, dataCache);
+        saveModelToCache(modelMul, modelCache, dataCache);
     }
 
-    // Use a different token for testModelAdd.
+    // Use a different token for modelAdd.
     mToken[0]++;
 
     // This test is probabilistic, so we run it multiple times.
     for (uint32_t i = 0; i < kNumIterationsTOCTOU; i++) {
-        // Save the testModelAdd compilation to cache.
+        // Save the modelAdd compilation to cache.
         {
             hidl_vec<hidl_handle> modelCache, dataCache;
             createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
@@ -1121,7 +1061,7 @@
 
             // Spawn a thread to copy the cache content concurrently while saving to cache.
             std::thread thread(copyCacheFiles, std::cref(modelCacheMul), std::cref(mModelCache));
-            saveModelToCache(testModelAdd, modelCache, dataCache);
+            saveModelToCache(modelAdd, modelCache, dataCache);
             thread.join();
         }
 
@@ -1140,11 +1080,8 @@
                 ASSERT_EQ(preparedModel, nullptr);
             } else {
                 ASSERT_NE(preparedModel, nullptr);
-                generated_tests::EvaluatePreparedModel(
-                        preparedModel, [](int) { return false; },
-                        getLargeModelExamples(kLargeModelSize),
-                        testModelAdd.relaxComputationFloat32toFloat16,
-                        /*testDynamicOutputShape=*/false);
+                EvaluatePreparedModel(preparedModel, testModelAdd,
+                                      /*testDynamicOutputShape=*/false);
             }
         }
     }
@@ -1154,12 +1091,14 @@
     if (!mIsCachingSupported) return;
 
     // Create test models and check if fully supported by the service.
-    const Model testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize);
-    if (checkEarlyTermination(testModelMul)) return;
-    const Model testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize);
-    if (checkEarlyTermination(testModelAdd)) return;
+    const TestModel testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize);
+    const Model modelMul = createModel(testModelMul);
+    if (checkEarlyTermination(modelMul)) return;
+    const TestModel testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize);
+    const Model modelAdd = createModel(testModelAdd);
+    if (checkEarlyTermination(modelAdd)) return;
 
-    // Save the testModelMul compilation to cache.
+    // Save the modelMul compilation to cache.
     auto modelCacheMul = mModelCache;
     for (auto& cache : modelCacheMul) {
         cache[0].append("_mul");
@@ -1168,20 +1107,20 @@
         hidl_vec<hidl_handle> modelCache, dataCache;
         createCacheHandles(modelCacheMul, AccessMode::READ_WRITE, &modelCache);
         createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
-        saveModelToCache(testModelMul, modelCache, dataCache);
+        saveModelToCache(modelMul, modelCache, dataCache);
     }
 
-    // Use a different token for testModelAdd.
+    // Use a different token for modelAdd.
     mToken[0]++;
 
     // This test is probabilistic, so we run it multiple times.
     for (uint32_t i = 0; i < kNumIterationsTOCTOU; i++) {
-        // Save the testModelAdd compilation to cache.
+        // Save the modelAdd compilation to cache.
         {
             hidl_vec<hidl_handle> modelCache, dataCache;
             createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
             createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
-            saveModelToCache(testModelAdd, modelCache, dataCache);
+            saveModelToCache(modelAdd, modelCache, dataCache);
         }
 
         // Retrieve preparedModel from cache.
@@ -1203,11 +1142,8 @@
                 ASSERT_EQ(preparedModel, nullptr);
             } else {
                 ASSERT_NE(preparedModel, nullptr);
-                generated_tests::EvaluatePreparedModel(
-                        preparedModel, [](int) { return false; },
-                        getLargeModelExamples(kLargeModelSize),
-                        testModelAdd.relaxComputationFloat32toFloat16,
-                        /*testDynamicOutputShape=*/false);
+                EvaluatePreparedModel(preparedModel, testModelAdd,
+                                      /*testDynamicOutputShape=*/false);
             }
         }
     }
@@ -1217,12 +1153,14 @@
     if (!mIsCachingSupported) return;
 
     // Create test models and check if fully supported by the service.
-    const Model testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize);
-    if (checkEarlyTermination(testModelMul)) return;
-    const Model testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize);
-    if (checkEarlyTermination(testModelAdd)) return;
+    const TestModel testModelMul = createLargeTestModel(OperationType::MUL, kLargeModelSize);
+    const Model modelMul = createModel(testModelMul);
+    if (checkEarlyTermination(modelMul)) return;
+    const TestModel testModelAdd = createLargeTestModel(OperationType::ADD, kLargeModelSize);
+    const Model modelAdd = createModel(testModelAdd);
+    if (checkEarlyTermination(modelAdd)) return;
 
-    // Save the testModelMul compilation to cache.
+    // Save the modelMul compilation to cache.
     auto modelCacheMul = mModelCache;
     for (auto& cache : modelCacheMul) {
         cache[0].append("_mul");
@@ -1231,21 +1169,21 @@
         hidl_vec<hidl_handle> modelCache, dataCache;
         createCacheHandles(modelCacheMul, AccessMode::READ_WRITE, &modelCache);
         createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
-        saveModelToCache(testModelMul, modelCache, dataCache);
+        saveModelToCache(modelMul, modelCache, dataCache);
     }
 
-    // Use a different token for testModelAdd.
+    // Use a different token for modelAdd.
     mToken[0]++;
 
-    // Save the testModelAdd compilation to cache.
+    // Save the modelAdd compilation to cache.
     {
         hidl_vec<hidl_handle> modelCache, dataCache;
         createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
         createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
-        saveModelToCache(testModelAdd, modelCache, dataCache);
+        saveModelToCache(modelAdd, modelCache, dataCache);
     }
 
-    // Replace the model cache of testModelAdd with testModelMul.
+    // Replace the model cache of modelAdd with modelMul.
     copyCacheFiles(modelCacheMul, mModelCache);
 
     // Retrieve the preparedModel from cache, expect failure.
@@ -1261,16 +1199,30 @@
     }
 }
 
+static const auto kNamedDeviceChoices = testing::ValuesIn(getNamedDevices());
 static const auto kOperandTypeChoices =
-        ::testing::Values(OperandType::TENSOR_FLOAT32, OperandType::TENSOR_QUANT8_ASYMM);
+        testing::Values(OperandType::TENSOR_FLOAT32, OperandType::TENSOR_QUANT8_ASYMM);
 
-INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingTest, kOperandTypeChoices);
+std::string printCompilationCachingTest(
+        const testing::TestParamInfo<CompilationCachingTestParam>& info) {
+    const auto& [namedDevice, operandType] = info.param;
+    const std::string type = (operandType == OperandType::TENSOR_FLOAT32 ? "float32" : "quant8");
+    return gtestCompliantName(getName(namedDevice) + "_" + type);
+}
+
+INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingTest,
+                        testing::Combine(kNamedDeviceChoices, kOperandTypeChoices),
+                        printCompilationCachingTest);
+
+using CompilationCachingSecurityTestParam = std::tuple<NamedDevice, OperandType, uint32_t>;
 
 class CompilationCachingSecurityTest
     : public CompilationCachingTestBase,
-      public ::testing::WithParamInterface<std::tuple<OperandType, uint32_t>> {
+      public testing::WithParamInterface<CompilationCachingSecurityTestParam> {
   protected:
-    CompilationCachingSecurityTest() : CompilationCachingTestBase(std::get<0>(GetParam())) {}
+    CompilationCachingSecurityTest()
+        : CompilationCachingTestBase(getData(std::get<NamedDevice>(GetParam())),
+                                     std::get<OperandType>(GetParam())) {}
 
     void SetUp() {
         CompilationCachingTestBase::SetUp();
@@ -1321,15 +1273,16 @@
     // The modifier accepts one pointer argument "skip" as the returning value, indicating
     // whether the test should be skipped or not.
     void testCorruptedCache(ExpectedResult expected, std::function<void(bool*)> modifier) {
-        const Model testModel = createTestModel();
-        if (checkEarlyTermination(testModel)) return;
+        const TestModel& testModel = createTestModel();
+        const Model model = createModel(testModel);
+        if (checkEarlyTermination(model)) return;
 
         // Save the compilation to cache.
         {
             hidl_vec<hidl_handle> modelCache, dataCache;
             createCacheHandles(mModelCache, AccessMode::READ_WRITE, &modelCache);
             createCacheHandles(mDataCache, AccessMode::READ_WRITE, &dataCache);
-            saveModelToCache(testModel, modelCache, dataCache);
+            saveModelToCache(model, modelCache, dataCache);
         }
 
         bool skip = false;
@@ -1359,7 +1312,7 @@
         }
     }
 
-    const uint32_t kSeed = std::get<1>(GetParam());
+    const uint32_t kSeed = std::get<uint32_t>(GetParam());
     std::mt19937 generator;
 };
 
@@ -1406,12 +1359,16 @@
     });
 }
 
-INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingSecurityTest,
-                        ::testing::Combine(kOperandTypeChoices, ::testing::Range(0U, 10U)));
+std::string printCompilationCachingSecurityTest(
+        const testing::TestParamInfo<CompilationCachingSecurityTestParam>& info) {
+    const auto& [namedDevice, operandType, seed] = info.param;
+    const std::string type = (operandType == OperandType::TENSOR_FLOAT32 ? "float32" : "quant8");
+    return gtestCompliantName(getName(namedDevice) + "_" + type + "_" + std::to_string(seed));
+}
 
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_2
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
+INSTANTIATE_TEST_CASE_P(TestCompilationCaching, CompilationCachingSecurityTest,
+                        testing::Combine(kNamedDeviceChoices, kOperandTypeChoices,
+                                         testing::Range(0U, 10U)),
+                        printCompilationCachingSecurityTest);
+
+}  // namespace android::hardware::neuralnetworks::V1_2::vts::functional
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
new file mode 100644
index 0000000..2beec98
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.cpp
@@ -0,0 +1,408 @@
+/*
+ * 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 "GeneratedTestHarness.h"
+
+#include <android-base/logging.h>
+#include <android/hardware/neuralnetworks/1.0/IDevice.h>
+#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/IDevice.h>
+#include <android/hardware/neuralnetworks/1.2/IDevice.h>
+#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
+#include <android/hidl/allocator/1.0/IAllocator.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <hidlmemory/mapping.h>
+
+#include <gtest/gtest.h>
+#include <algorithm>
+#include <iostream>
+#include <numeric>
+
+#include "1.0/Utils.h"
+#include "1.2/Callbacks.h"
+#include "ExecutionBurstController.h"
+#include "MemoryUtils.h"
+#include "TestHarness.h"
+#include "Utils.h"
+#include "VtsHalNeuralnetworks.h"
+
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
+
+using namespace test_helper;
+using hidl::memory::V1_0::IMemory;
+using implementation::ExecutionCallback;
+using implementation::PreparedModelCallback;
+using V1_0::DataLocation;
+using V1_0::ErrorStatus;
+using V1_0::OperandLifeTime;
+using V1_0::Request;
+using V1_1::ExecutionPreference;
+using HidlToken = hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
+
+enum class OutputType { FULLY_SPECIFIED, UNSPECIFIED, INSUFFICIENT };
+
+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];
+
+        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();
+        } 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();
+        }
+
+        Operand::ExtraParams extraParams;
+        if (op.type == TestOperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL) {
+            extraParams.channelQuant(SymmPerChannelQuantParams{
+                    .scales = op.channelQuant.scales, .channelDim = op.channelQuant.channelDim});
+        }
+
+        operands[i] = {.type = static_cast<OperandType>(op.type),
+                       .dimensions = op.dimensions,
+                       .numberOfConsumers = op.numberOfConsumers,
+                       .scale = op.scale,
+                       .zeroPoint = op.zeroPoint,
+                       .lifetime = static_cast<OperandLifeTime>(op.lifetime),
+                       .location = loc,
+                       .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 {
+                       return {.type = static_cast<OperationType>(op.type),
+                               .inputs = op.inputs,
+                               .outputs = op.outputs};
+                   });
+
+    // 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);
+        }
+    }
+
+    // Shared memory.
+    hidl_vec<hidl_memory> pools = {};
+    if (constRefSize > 0) {
+        hidl_vec_push_back(&pools, nn::allocateSharedMemory(constRefSize));
+        CHECK_NE(pools[0].size(), 0u);
+
+        // load data
+        sp<IMemory> mappedMemory = mapMemory(pools[0]);
+        CHECK(mappedMemory.get() != nullptr);
+        uint8_t* mappedPtr =
+                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);
+            }
+        }
+    }
+
+    return {.operands = std::move(operands),
+            .operations = std::move(operations),
+            .inputIndexes = testModel.inputIndexes,
+            .outputIndexes = testModel.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();
+    return byteSize > 1u;
+}
+
+static void makeOutputInsufficientSize(uint32_t outputIndex, Request* request) {
+    auto& length = request->outputs[outputIndex].location.length;
+    ASSERT_GT(length, 1u);
+    length -= 1u;
+}
+
+static void makeOutputDimensionsUnspecified(Model* model) {
+    for (auto i : model->outputIndexes) {
+        auto& dims = model->operands[i].dimensions;
+        std::fill(dims.begin(), dims.end(), 0);
+    }
+}
+
+static Return<ErrorStatus> ExecutePreparedModel(const sp<IPreparedModel>& preparedModel,
+                                                const Request& request, MeasureTiming measure,
+                                                sp<ExecutionCallback>& callback) {
+    return preparedModel->execute_1_2(request, measure, callback);
+}
+static Return<ErrorStatus> ExecutePreparedModel(const sp<IPreparedModel>& preparedModel,
+                                                const Request& request, MeasureTiming measure,
+                                                hidl_vec<OutputShape>* outputShapes,
+                                                Timing* timing) {
+    ErrorStatus result;
+    Return<void> ret = preparedModel->executeSynchronously(
+            request, measure,
+            [&result, outputShapes, timing](ErrorStatus error, const hidl_vec<OutputShape>& shapes,
+                                            const Timing& time) {
+                result = error;
+                *outputShapes = shapes;
+                *timing = time;
+            });
+    if (!ret.isOk()) {
+        return ErrorStatus::GENERAL_FAILURE;
+    }
+    return result;
+}
+static std::shared_ptr<::android::nn::ExecutionBurstController> CreateBurst(
+        const sp<IPreparedModel>& preparedModel) {
+    return android::nn::ExecutionBurstController::create(preparedModel, /*blocking=*/true);
+}
+enum class Executor { ASYNC, SYNC, BURST };
+
+void EvaluatePreparedModel(const sp<IPreparedModel>& preparedModel, const TestModel& testModel,
+                           Executor executor, MeasureTiming measure, OutputType outputType) {
+    // If output0 does not have size larger than one byte, we can not test with insufficient buffer.
+    if (outputType == OutputType::INSUFFICIENT && !isOutputSizeGreaterThanOne(testModel, 0)) {
+        return;
+    }
+
+    Request request = createRequest(testModel);
+    if (outputType == OutputType::INSUFFICIENT) {
+        makeOutputInsufficientSize(/*outputIndex=*/0, &request);
+    }
+
+    ErrorStatus executionStatus;
+    hidl_vec<OutputShape> outputShapes;
+    Timing timing;
+    switch (executor) {
+        case Executor::ASYNC: {
+            SCOPED_TRACE("asynchronous");
+
+            // launch execution
+            sp<ExecutionCallback> executionCallback = new ExecutionCallback();
+            Return<ErrorStatus> executionLaunchStatus =
+                    ExecutePreparedModel(preparedModel, request, measure, executionCallback);
+            ASSERT_TRUE(executionLaunchStatus.isOk());
+            EXPECT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(executionLaunchStatus));
+
+            // retrieve execution status
+            executionCallback->wait();
+            executionStatus = executionCallback->getStatus();
+            outputShapes = executionCallback->getOutputShapes();
+            timing = executionCallback->getTiming();
+
+            break;
+        }
+        case Executor::SYNC: {
+            SCOPED_TRACE("synchronous");
+
+            // execute
+            Return<ErrorStatus> executionReturnStatus =
+                    ExecutePreparedModel(preparedModel, request, measure, &outputShapes, &timing);
+            ASSERT_TRUE(executionReturnStatus.isOk());
+            executionStatus = static_cast<ErrorStatus>(executionReturnStatus);
+
+            break;
+        }
+        case Executor::BURST: {
+            SCOPED_TRACE("burst");
+
+            // create burst
+            const std::shared_ptr<::android::nn::ExecutionBurstController> controller =
+                    CreateBurst(preparedModel);
+            ASSERT_NE(nullptr, controller.get());
+
+            // create memory keys
+            std::vector<intptr_t> keys(request.pools.size());
+            for (size_t i = 0; i < keys.size(); ++i) {
+                keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
+            }
+
+            // execute burst
+            std::tie(executionStatus, outputShapes, timing) =
+                    controller->compute(request, measure, keys);
+
+            break;
+        }
+    }
+
+    if (outputType != OutputType::FULLY_SPECIFIED &&
+        executionStatus == ErrorStatus::GENERAL_FAILURE) {
+        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot "
+                     "execute model that it does not support.";
+        std::cout << "[          ]   Early termination of test because vendor service cannot "
+                     "execute model that it does not support."
+                  << std::endl;
+        GTEST_SKIP();
+    }
+    if (measure == MeasureTiming::NO) {
+        EXPECT_EQ(UINT64_MAX, timing.timeOnDevice);
+        EXPECT_EQ(UINT64_MAX, timing.timeInDriver);
+    } else {
+        if (timing.timeOnDevice != UINT64_MAX && timing.timeInDriver != UINT64_MAX) {
+            EXPECT_LE(timing.timeOnDevice, timing.timeInDriver);
+        }
+    }
+
+    switch (outputType) {
+        case OutputType::FULLY_SPECIFIED:
+            // If the model output operands are fully specified, outputShapes must be either
+            // either empty, or have the same number of elements as the number of outputs.
+            ASSERT_EQ(ErrorStatus::NONE, executionStatus);
+            ASSERT_TRUE(outputShapes.size() == 0 ||
+                        outputShapes.size() == testModel.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());
+            break;
+        case OutputType::INSUFFICIENT:
+            ASSERT_EQ(ErrorStatus::OUTPUT_INSUFFICIENT_SIZE, executionStatus);
+            ASSERT_EQ(outputShapes.size(), testModel.outputIndexes.size());
+            ASSERT_FALSE(outputShapes[0].isSufficient);
+            return;
+    }
+
+    // Go through all outputs, check returned output shapes.
+    for (uint32_t i = 0; i < outputShapes.size(); i++) {
+        EXPECT_TRUE(outputShapes[i].isSufficient);
+        const auto& expect = testModel.operands[testModel.outputIndexes[i]].dimensions;
+        const std::vector<uint32_t> actual = outputShapes[i].dimensions;
+        EXPECT_EQ(expect, actual);
+    }
+
+    // Retrieve execution results.
+    const std::vector<TestBuffer> outputs = getOutputBuffers(request);
+
+    // We want "close-enough" results.
+    checkResults(testModel, outputs);
+}
+
+void EvaluatePreparedModel(const sp<IPreparedModel>& preparedModel, const TestModel& testModel,
+                           bool testDynamicOutputShape) {
+    if (testDynamicOutputShape) {
+        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::NO,
+                              OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::NO,
+                              OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::NO,
+                              OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::YES,
+                              OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::YES,
+                              OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::YES,
+                              OutputType::UNSPECIFIED);
+        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::NO,
+                              OutputType::INSUFFICIENT);
+        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::NO,
+                              OutputType::INSUFFICIENT);
+        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::NO,
+                              OutputType::INSUFFICIENT);
+        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::YES,
+                              OutputType::INSUFFICIENT);
+        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::YES,
+                              OutputType::INSUFFICIENT);
+        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::YES,
+                              OutputType::INSUFFICIENT);
+    } else {
+        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::NO,
+                              OutputType::FULLY_SPECIFIED);
+        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::NO,
+                              OutputType::FULLY_SPECIFIED);
+        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::NO,
+                              OutputType::FULLY_SPECIFIED);
+        EvaluatePreparedModel(preparedModel, testModel, Executor::ASYNC, MeasureTiming::YES,
+                              OutputType::FULLY_SPECIFIED);
+        EvaluatePreparedModel(preparedModel, testModel, Executor::SYNC, MeasureTiming::YES,
+                              OutputType::FULLY_SPECIFIED);
+        EvaluatePreparedModel(preparedModel, testModel, Executor::BURST, MeasureTiming::YES,
+                              OutputType::FULLY_SPECIFIED);
+    }
+}
+
+void Execute(const sp<IDevice>& device, const TestModel& testModel, bool testDynamicOutputShape) {
+    Model model = createModel(testModel);
+    if (testDynamicOutputShape) {
+        makeOutputDimensionsUnspecified(&model);
+    }
+
+    sp<IPreparedModel> preparedModel;
+    createPreparedModel(device, model, &preparedModel);
+    if (preparedModel == nullptr) return;
+
+    EvaluatePreparedModel(preparedModel, testModel, testDynamicOutputShape);
+}
+
+void GeneratedTestBase::SetUp() {
+    testing::TestWithParam<GeneratedTestParam>::SetUp();
+    ASSERT_NE(kDevice, nullptr);
+}
+
+std::vector<NamedModel> getNamedModels(const FilterFn& filter) {
+    return TestModelManager::get().getTestModels(filter);
+}
+
+std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info) {
+    const auto& [namedDevice, namedModel] = info.param;
+    return gtestCompliantName(getName(namedDevice) + "_" + getName(namedModel));
+}
+
+// Tag for the generated tests
+class GeneratedTest : public GeneratedTestBase {};
+
+// Tag for the dynamic output shape tests
+class DynamicOutputShapeTest : public GeneratedTest {};
+
+TEST_P(GeneratedTest, Test) {
+    Execute(kDevice, kTestModel, /*testDynamicOutputShape=*/false);
+}
+
+TEST_P(DynamicOutputShapeTest, Test) {
+    Execute(kDevice, kTestModel, /*testDynamicOutputShape=*/true);
+}
+
+INSTANTIATE_GENERATED_TEST(GeneratedTest,
+                           [](const TestModel& testModel) { return !testModel.expectFailure; });
+
+INSTANTIATE_GENERATED_TEST(DynamicOutputShapeTest,
+                           [](const TestModel& testModel) { return !testModel.expectFailure; });
+
+}  // namespace android::hardware::neuralnetworks::V1_2::vts::functional
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h
new file mode 100644
index 0000000..dfc980c
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTestHarness.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_2_GENERATED_TEST_HARNESS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_2_GENERATED_TEST_HARNESS_H
+
+#include <android/hardware/neuralnetworks/1.2/IDevice.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+#include <functional>
+#include <vector>
+#include "1.0/Utils.h"
+#include "TestHarness.h"
+#include "VtsHalNeuralnetworks.h"
+
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
+
+using NamedModel = Named<const test_helper::TestModel*>;
+using GeneratedTestParam = std::tuple<NamedDevice, NamedModel>;
+
+class GeneratedTestBase : public testing::TestWithParam<GeneratedTestParam> {
+  protected:
+    void SetUp() override;
+    const sp<IDevice> kDevice = getData(std::get<NamedDevice>(GetParam()));
+    const test_helper::TestModel& kTestModel = *getData(std::get<NamedModel>(GetParam()));
+};
+
+using FilterFn = std::function<bool(const test_helper::TestModel&)>;
+std::vector<NamedModel> getNamedModels(const FilterFn& filter);
+
+std::string printGeneratedTest(const testing::TestParamInfo<GeneratedTestParam>& info);
+
+#define INSTANTIATE_GENERATED_TEST(TestSuite, filter)                                     \
+    INSTANTIATE_TEST_SUITE_P(TestGenerated, TestSuite,                                    \
+                             testing::Combine(testing::ValuesIn(getNamedDevices()),       \
+                                              testing::ValuesIn(getNamedModels(filter))), \
+                             printGeneratedTest)
+
+// Tag for the validation tests, instantiated in VtsHalNeuralnetworks.cpp.
+// TODO: Clean up the hierarchy for ValidationTest.
+class ValidationTest : public GeneratedTestBase {};
+
+Model createModel(const test_helper::TestModel& testModel);
+
+void PrepareModel(const sp<IDevice>& device, const Model& model, sp<IPreparedModel>* preparedModel);
+
+void EvaluatePreparedModel(const sp<IPreparedModel>& preparedModel,
+                           const test_helper::TestModel& testModel, bool testDynamicOutputShape);
+
+}  // namespace android::hardware::neuralnetworks::V1_2::vts::functional
+
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_2_GENERATED_TEST_HARNESS_H
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
deleted file mode 100644
index 2c3287a..0000000
--- a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "neuralnetworks_hidl_hal_test"
-
-#include "VtsHalNeuralnetworks.h"
-
-#include "Callbacks.h"
-#include "GeneratedTestHarness.h"
-#include "TestHarness.h"
-#include "Utils.h"
-
-#include <android-base/logging.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
-
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
-using ::android::nn::allocateSharedMemory;
-using ::test_helper::MixedTypedExample;
-
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
-
-// in frameworks/ml/nn/runtime/tests/generated/
-#include "all_generated_V1_2_vts_tests.cpp"
-
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_2
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp
deleted file mode 100644
index 990cab9..0000000
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_0.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "neuralnetworks_hidl_hal_test"
-
-#include "VtsHalNeuralnetworks.h"
-
-#include "Callbacks.h"
-#include "GeneratedTestHarness.h"
-#include "TestHarness.h"
-#include "Utils.h"
-
-#include <android-base/logging.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
-
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
-using ::android::nn::allocateSharedMemory;
-using ::test_helper::MixedTypedExample;
-
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
-
-// in frameworks/ml/nn/runtime/tests/generated/
-#include "all_generated_V1_0_vts_tests.cpp"
-
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_2
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp
deleted file mode 100644
index fa6d54d..0000000
--- a/neuralnetworks/1.2/vts/functional/GeneratedTestsV1_1.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "neuralnetworks_hidl_hal_test"
-
-#include "VtsHalNeuralnetworks.h"
-
-#include "Callbacks.h"
-#include "GeneratedTestHarness.h"
-#include "TestHarness.h"
-#include "Utils.h"
-
-#include <android-base/logging.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
-
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
-
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
-using ::android::nn::allocateSharedMemory;
-using ::test_helper::MixedTypedExample;
-
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
-
-// in frameworks/ml/nn/runtime/tests/generated/
-#include "all_generated_V1_1_vts_tests.cpp"
-
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_2
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
diff --git a/neuralnetworks/1.2/vts/functional/TestAssertions.cpp b/neuralnetworks/1.2/vts/functional/TestAssertions.cpp
new file mode 100644
index 0000000..a0aa3c3
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/TestAssertions.cpp
@@ -0,0 +1,141 @@
+/*
+ * 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/hardware/neuralnetworks/1.2/types.h>
+#include "TestHarness.h"
+
+namespace android::hardware::neuralnetworks::V1_2 {
+
+// Make sure that the HIDL enums are compatible with the values defined in
+// frameworks/ml/nn/tools/test_generator/test_harness/include/TestHarness.h.
+using namespace test_helper;
+#define CHECK_TEST_ENUM(EnumType, enumValue) \
+    static_assert(static_cast<EnumType>(Test##EnumType::enumValue) == EnumType::enumValue)
+
+CHECK_TEST_ENUM(OperandType, FLOAT32);
+CHECK_TEST_ENUM(OperandType, INT32);
+CHECK_TEST_ENUM(OperandType, UINT32);
+CHECK_TEST_ENUM(OperandType, TENSOR_FLOAT32);
+CHECK_TEST_ENUM(OperandType, TENSOR_INT32);
+CHECK_TEST_ENUM(OperandType, TENSOR_QUANT8_ASYMM);
+CHECK_TEST_ENUM(OperandType, BOOL);
+CHECK_TEST_ENUM(OperandType, TENSOR_QUANT16_SYMM);
+CHECK_TEST_ENUM(OperandType, TENSOR_FLOAT16);
+CHECK_TEST_ENUM(OperandType, TENSOR_BOOL8);
+CHECK_TEST_ENUM(OperandType, FLOAT16);
+CHECK_TEST_ENUM(OperandType, TENSOR_QUANT8_SYMM_PER_CHANNEL);
+CHECK_TEST_ENUM(OperandType, TENSOR_QUANT16_ASYMM);
+CHECK_TEST_ENUM(OperandType, TENSOR_QUANT8_SYMM);
+
+CHECK_TEST_ENUM(OperationType, ADD);
+CHECK_TEST_ENUM(OperationType, AVERAGE_POOL_2D);
+CHECK_TEST_ENUM(OperationType, CONCATENATION);
+CHECK_TEST_ENUM(OperationType, CONV_2D);
+CHECK_TEST_ENUM(OperationType, DEPTHWISE_CONV_2D);
+CHECK_TEST_ENUM(OperationType, DEPTH_TO_SPACE);
+CHECK_TEST_ENUM(OperationType, DEQUANTIZE);
+CHECK_TEST_ENUM(OperationType, EMBEDDING_LOOKUP);
+CHECK_TEST_ENUM(OperationType, FLOOR);
+CHECK_TEST_ENUM(OperationType, FULLY_CONNECTED);
+CHECK_TEST_ENUM(OperationType, HASHTABLE_LOOKUP);
+CHECK_TEST_ENUM(OperationType, L2_NORMALIZATION);
+CHECK_TEST_ENUM(OperationType, L2_POOL_2D);
+CHECK_TEST_ENUM(OperationType, LOCAL_RESPONSE_NORMALIZATION);
+CHECK_TEST_ENUM(OperationType, LOGISTIC);
+CHECK_TEST_ENUM(OperationType, LSH_PROJECTION);
+CHECK_TEST_ENUM(OperationType, LSTM);
+CHECK_TEST_ENUM(OperationType, MAX_POOL_2D);
+CHECK_TEST_ENUM(OperationType, MUL);
+CHECK_TEST_ENUM(OperationType, RELU);
+CHECK_TEST_ENUM(OperationType, RELU1);
+CHECK_TEST_ENUM(OperationType, RELU6);
+CHECK_TEST_ENUM(OperationType, RESHAPE);
+CHECK_TEST_ENUM(OperationType, RESIZE_BILINEAR);
+CHECK_TEST_ENUM(OperationType, RNN);
+CHECK_TEST_ENUM(OperationType, SOFTMAX);
+CHECK_TEST_ENUM(OperationType, SPACE_TO_DEPTH);
+CHECK_TEST_ENUM(OperationType, SVDF);
+CHECK_TEST_ENUM(OperationType, TANH);
+CHECK_TEST_ENUM(OperationType, BATCH_TO_SPACE_ND);
+CHECK_TEST_ENUM(OperationType, DIV);
+CHECK_TEST_ENUM(OperationType, MEAN);
+CHECK_TEST_ENUM(OperationType, PAD);
+CHECK_TEST_ENUM(OperationType, SPACE_TO_BATCH_ND);
+CHECK_TEST_ENUM(OperationType, SQUEEZE);
+CHECK_TEST_ENUM(OperationType, STRIDED_SLICE);
+CHECK_TEST_ENUM(OperationType, SUB);
+CHECK_TEST_ENUM(OperationType, TRANSPOSE);
+CHECK_TEST_ENUM(OperationType, ABS);
+CHECK_TEST_ENUM(OperationType, ARGMAX);
+CHECK_TEST_ENUM(OperationType, ARGMIN);
+CHECK_TEST_ENUM(OperationType, AXIS_ALIGNED_BBOX_TRANSFORM);
+CHECK_TEST_ENUM(OperationType, BIDIRECTIONAL_SEQUENCE_LSTM);
+CHECK_TEST_ENUM(OperationType, BIDIRECTIONAL_SEQUENCE_RNN);
+CHECK_TEST_ENUM(OperationType, BOX_WITH_NMS_LIMIT);
+CHECK_TEST_ENUM(OperationType, CAST);
+CHECK_TEST_ENUM(OperationType, CHANNEL_SHUFFLE);
+CHECK_TEST_ENUM(OperationType, DETECTION_POSTPROCESSING);
+CHECK_TEST_ENUM(OperationType, EQUAL);
+CHECK_TEST_ENUM(OperationType, EXP);
+CHECK_TEST_ENUM(OperationType, EXPAND_DIMS);
+CHECK_TEST_ENUM(OperationType, GATHER);
+CHECK_TEST_ENUM(OperationType, GENERATE_PROPOSALS);
+CHECK_TEST_ENUM(OperationType, GREATER);
+CHECK_TEST_ENUM(OperationType, GREATER_EQUAL);
+CHECK_TEST_ENUM(OperationType, GROUPED_CONV_2D);
+CHECK_TEST_ENUM(OperationType, HEATMAP_MAX_KEYPOINT);
+CHECK_TEST_ENUM(OperationType, INSTANCE_NORMALIZATION);
+CHECK_TEST_ENUM(OperationType, LESS);
+CHECK_TEST_ENUM(OperationType, LESS_EQUAL);
+CHECK_TEST_ENUM(OperationType, LOG);
+CHECK_TEST_ENUM(OperationType, LOGICAL_AND);
+CHECK_TEST_ENUM(OperationType, LOGICAL_NOT);
+CHECK_TEST_ENUM(OperationType, LOGICAL_OR);
+CHECK_TEST_ENUM(OperationType, LOG_SOFTMAX);
+CHECK_TEST_ENUM(OperationType, MAXIMUM);
+CHECK_TEST_ENUM(OperationType, MINIMUM);
+CHECK_TEST_ENUM(OperationType, NEG);
+CHECK_TEST_ENUM(OperationType, NOT_EQUAL);
+CHECK_TEST_ENUM(OperationType, PAD_V2);
+CHECK_TEST_ENUM(OperationType, POW);
+CHECK_TEST_ENUM(OperationType, PRELU);
+CHECK_TEST_ENUM(OperationType, QUANTIZE);
+CHECK_TEST_ENUM(OperationType, QUANTIZED_16BIT_LSTM);
+CHECK_TEST_ENUM(OperationType, RANDOM_MULTINOMIAL);
+CHECK_TEST_ENUM(OperationType, REDUCE_ALL);
+CHECK_TEST_ENUM(OperationType, REDUCE_ANY);
+CHECK_TEST_ENUM(OperationType, REDUCE_MAX);
+CHECK_TEST_ENUM(OperationType, REDUCE_MIN);
+CHECK_TEST_ENUM(OperationType, REDUCE_PROD);
+CHECK_TEST_ENUM(OperationType, REDUCE_SUM);
+CHECK_TEST_ENUM(OperationType, ROI_ALIGN);
+CHECK_TEST_ENUM(OperationType, ROI_POOLING);
+CHECK_TEST_ENUM(OperationType, RSQRT);
+CHECK_TEST_ENUM(OperationType, SELECT);
+CHECK_TEST_ENUM(OperationType, SIN);
+CHECK_TEST_ENUM(OperationType, SLICE);
+CHECK_TEST_ENUM(OperationType, SPLIT);
+CHECK_TEST_ENUM(OperationType, SQRT);
+CHECK_TEST_ENUM(OperationType, TILE);
+CHECK_TEST_ENUM(OperationType, TOPK_V2);
+CHECK_TEST_ENUM(OperationType, TRANSPOSE_CONV_2D);
+CHECK_TEST_ENUM(OperationType, UNIDIRECTIONAL_SEQUENCE_LSTM);
+CHECK_TEST_ENUM(OperationType, UNIDIRECTIONAL_SEQUENCE_RNN);
+CHECK_TEST_ENUM(OperationType, RESIZE_NEAREST_NEIGHBOR);
+
+#undef CHECK_TEST_ENUM
+
+}  // namespace android::hardware::neuralnetworks::V1_2
diff --git a/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp b/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp
index 8c6391e..1d4493d 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateBurst.cpp
@@ -18,26 +18,24 @@
 
 #include "VtsHalNeuralnetworks.h"
 
-#include "Callbacks.h"
+#include "1.2/Callbacks.h"
 #include "ExecutionBurstController.h"
 #include "ExecutionBurstServer.h"
+#include "GeneratedTestHarness.h"
 #include "TestHarness.h"
 #include "Utils.h"
 
 #include <android-base/logging.h>
 #include <cstring>
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
 
-using ::android::nn::ExecutionBurstController;
-using ::android::nn::RequestChannelSender;
-using ::android::nn::ResultChannelReceiver;
-using ExecutionBurstCallback = ::android::nn::ExecutionBurstController::ExecutionBurstCallback;
+using nn::ExecutionBurstController;
+using nn::RequestChannelSender;
+using nn::ResultChannelReceiver;
+using V1_0::ErrorStatus;
+using V1_0::Request;
+using ExecutionBurstCallback = ExecutionBurstController::ExecutionBurstCallback;
 
 // This constant value represents the length of an FMQ that is large enough to
 // return a result from a burst execution for all of the generated test cases.
@@ -239,7 +237,7 @@
 ///////////////////////// BURST VALIATION TESTS ////////////////////////////////////
 
 static void validateBurstSerialization(const sp<IPreparedModel>& preparedModel,
-                                       const std::vector<Request>& requests) {
+                                       const Request& request) {
     // create burst
     std::unique_ptr<RequestChannelSender> sender;
     std::unique_ptr<ResultChannelReceiver> receiver;
@@ -250,35 +248,32 @@
     ASSERT_NE(nullptr, receiver.get());
     ASSERT_NE(nullptr, context.get());
 
-    // validate each request
-    for (const Request& request : requests) {
-        // load memory into callback slots
-        std::vector<intptr_t> keys;
-        keys.reserve(request.pools.size());
-        std::transform(request.pools.begin(), request.pools.end(), std::back_inserter(keys),
-                       [](const auto& pool) { return reinterpret_cast<intptr_t>(&pool); });
-        const std::vector<int32_t> slots = callback->getSlots(request.pools, keys);
+    // load memory into callback slots
+    std::vector<intptr_t> keys;
+    keys.reserve(request.pools.size());
+    std::transform(request.pools.begin(), request.pools.end(), std::back_inserter(keys),
+                   [](const auto& pool) { return reinterpret_cast<intptr_t>(&pool); });
+    const std::vector<int32_t> slots = callback->getSlots(request.pools, keys);
 
-        // ensure slot std::numeric_limits<int32_t>::max() doesn't exist (for
-        // subsequent slot validation testing)
-        ASSERT_TRUE(std::all_of(slots.begin(), slots.end(), [](int32_t slot) {
-            return slot != std::numeric_limits<int32_t>::max();
-        }));
+    // ensure slot std::numeric_limits<int32_t>::max() doesn't exist (for
+    // subsequent slot validation testing)
+    ASSERT_TRUE(std::all_of(slots.begin(), slots.end(), [](int32_t slot) {
+        return slot != std::numeric_limits<int32_t>::max();
+    }));
 
-        // serialize the request
-        const auto serialized = ::android::nn::serialize(request, MeasureTiming::YES, slots);
+    // serialize the request
+    const auto serialized = android::nn::serialize(request, MeasureTiming::YES, slots);
 
-        // validations
-        removeDatumTest(sender.get(), receiver.get(), serialized);
-        addDatumTest(sender.get(), receiver.get(), serialized);
-        mutateDatumTest(sender.get(), receiver.get(), serialized);
-    }
+    // validations
+    removeDatumTest(sender.get(), receiver.get(), serialized);
+    addDatumTest(sender.get(), receiver.get(), serialized);
+    mutateDatumTest(sender.get(), receiver.get(), serialized);
 }
 
 // This test validates that when the Result message size exceeds length of the
 // result FMQ, the service instance gracefully fails and returns an error.
 static void validateBurstFmqLength(const sp<IPreparedModel>& preparedModel,
-                                   const std::vector<Request>& requests) {
+                                   const Request& request) {
     // create regular burst
     std::shared_ptr<ExecutionBurstController> controllerRegular;
     ASSERT_NO_FATAL_FAILURE(createBurstWithResultChannelLength(
@@ -291,35 +286,32 @@
             preparedModel, kExecutionBurstChannelSmallLength, &controllerSmall));
     ASSERT_NE(nullptr, controllerSmall.get());
 
-    // validate each request
-    for (const Request& request : requests) {
-        // load memory into callback slots
-        std::vector<intptr_t> keys(request.pools.size());
-        for (size_t i = 0; i < keys.size(); ++i) {
-            keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
-        }
-
-        // collect serialized result by running regular burst
-        const auto [statusRegular, outputShapesRegular, timingRegular] =
-                controllerRegular->compute(request, MeasureTiming::NO, keys);
-
-        // skip test if regular burst output isn't useful for testing a failure
-        // caused by having too small of a length for the result FMQ
-        const std::vector<FmqResultDatum> serialized =
-                ::android::nn::serialize(statusRegular, outputShapesRegular, timingRegular);
-        if (statusRegular != ErrorStatus::NONE ||
-            serialized.size() <= kExecutionBurstChannelSmallLength) {
-            continue;
-        }
-
-        // by this point, execution should fail because the result channel isn't
-        // large enough to return the serialized result
-        const auto [statusSmall, outputShapesSmall, timingSmall] =
-                controllerSmall->compute(request, MeasureTiming::NO, keys);
-        EXPECT_NE(ErrorStatus::NONE, statusSmall);
-        EXPECT_EQ(0u, outputShapesSmall.size());
-        EXPECT_TRUE(badTiming(timingSmall));
+    // load memory into callback slots
+    std::vector<intptr_t> keys(request.pools.size());
+    for (size_t i = 0; i < keys.size(); ++i) {
+        keys[i] = reinterpret_cast<intptr_t>(&request.pools[i]);
     }
+
+    // collect serialized result by running regular burst
+    const auto [statusRegular, outputShapesRegular, timingRegular] =
+            controllerRegular->compute(request, MeasureTiming::NO, keys);
+
+    // skip test if regular burst output isn't useful for testing a failure
+    // caused by having too small of a length for the result FMQ
+    const std::vector<FmqResultDatum> serialized =
+            android::nn::serialize(statusRegular, outputShapesRegular, timingRegular);
+    if (statusRegular != ErrorStatus::NONE ||
+        serialized.size() <= kExecutionBurstChannelSmallLength) {
+        return;
+    }
+
+    // by this point, execution should fail because the result channel isn't
+    // large enough to return the serialized result
+    const auto [statusSmall, outputShapesSmall, timingSmall] =
+            controllerSmall->compute(request, MeasureTiming::NO, keys);
+    EXPECT_NE(ErrorStatus::NONE, statusSmall);
+    EXPECT_EQ(0u, outputShapesSmall.size());
+    EXPECT_TRUE(badTiming(timingSmall));
 }
 
 static bool isSanitized(const FmqResultDatum& datum) {
@@ -367,7 +359,7 @@
 }
 
 static void validateBurstSanitized(const sp<IPreparedModel>& preparedModel,
-                                   const std::vector<Request>& requests) {
+                                   const Request& request) {
     // create burst
     std::unique_ptr<RequestChannelSender> sender;
     std::unique_ptr<ResultChannelReceiver> receiver;
@@ -378,40 +370,31 @@
     ASSERT_NE(nullptr, receiver.get());
     ASSERT_NE(nullptr, context.get());
 
-    // validate each request
-    for (const Request& request : requests) {
-        // load memory into callback slots
-        std::vector<intptr_t> keys;
-        keys.reserve(request.pools.size());
-        std::transform(request.pools.begin(), request.pools.end(), std::back_inserter(keys),
-                       [](const auto& pool) { return reinterpret_cast<intptr_t>(&pool); });
-        const std::vector<int32_t> slots = callback->getSlots(request.pools, keys);
+    // load memory into callback slots
+    std::vector<intptr_t> keys;
+    keys.reserve(request.pools.size());
+    std::transform(request.pools.begin(), request.pools.end(), std::back_inserter(keys),
+                   [](const auto& pool) { return reinterpret_cast<intptr_t>(&pool); });
+    const std::vector<int32_t> slots = callback->getSlots(request.pools, keys);
 
-        // send valid request
-        ASSERT_TRUE(sender->send(request, MeasureTiming::YES, slots));
+    // send valid request
+    ASSERT_TRUE(sender->send(request, MeasureTiming::YES, slots));
 
-        // receive valid result
-        auto serialized = receiver->getPacketBlocking();
-        ASSERT_TRUE(serialized.has_value());
+    // receive valid result
+    auto serialized = receiver->getPacketBlocking();
+    ASSERT_TRUE(serialized.has_value());
 
-        // sanitize result
-        ASSERT_TRUE(std::all_of(serialized->begin(), serialized->end(), isSanitized))
-                << "The result serialized data is not properly sanitized";
-    }
+    // sanitize result
+    ASSERT_TRUE(std::all_of(serialized->begin(), serialized->end(), isSanitized))
+            << "The result serialized data is not properly sanitized";
 }
 
 ///////////////////////////// ENTRY POINT //////////////////////////////////
 
-void ValidationTest::validateBurst(const sp<IPreparedModel>& preparedModel,
-                                   const std::vector<Request>& requests) {
-    ASSERT_NO_FATAL_FAILURE(validateBurstSerialization(preparedModel, requests));
-    ASSERT_NO_FATAL_FAILURE(validateBurstFmqLength(preparedModel, requests));
-    ASSERT_NO_FATAL_FAILURE(validateBurstSanitized(preparedModel, requests));
+void validateBurst(const sp<IPreparedModel>& preparedModel, const Request& request) {
+    ASSERT_NO_FATAL_FAILURE(validateBurstSerialization(preparedModel, request));
+    ASSERT_NO_FATAL_FAILURE(validateBurstFmqLength(preparedModel, request));
+    ASSERT_NO_FATAL_FAILURE(validateBurstSanitized(preparedModel, request));
 }
 
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_2
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::neuralnetworks::V1_2::vts::functional
diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
index a0b6d9a..a14b86b 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -16,23 +16,17 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
+#include "1.0/Utils.h"
+#include "1.2/Callbacks.h"
+#include "GeneratedTestHarness.h"
 #include "VtsHalNeuralnetworks.h"
 
-#include "Callbacks.h"
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-
+using implementation::PreparedModelCallback;
+using V1_0::ErrorStatus;
 using V1_0::OperandLifeTime;
 using V1_1::ExecutionPreference;
-
-namespace vts {
-namespace functional {
-
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
 using HidlToken = hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
 
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
@@ -41,10 +35,10 @@
                                            const Model& model) {
     SCOPED_TRACE(message + " [getSupportedOperations_1_2]");
 
-    Return<void> ret =
-        device->getSupportedOperations_1_2(model, [&](ErrorStatus status, const hidl_vec<bool>&) {
-            EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
-        });
+    Return<void> ret = device->getSupportedOperations_1_2(
+            model, [&](ErrorStatus status, const hidl_vec<bool>&) {
+                EXPECT_EQ(ErrorStatus::INVALID_ARGUMENT, status);
+            });
     EXPECT_TRUE(ret.isOk());
 }
 
@@ -53,7 +47,6 @@
     SCOPED_TRACE(message + " [prepareModel_1_2]");
 
     sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
     Return<ErrorStatus> prepareLaunchStatus =
             device->prepareModel_1_2(model, preference, hidl_vec<hidl_handle>(),
                                      hidl_vec<hidl_handle>(), HidlToken(), preparedModelCallback);
@@ -87,36 +80,16 @@
     validatePrepareModel(device, message, model, preference);
 }
 
-// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
-// so this is efficiently accomplished by moving the element to the end and
-// resizing the hidl_vec to one less.
-template <typename Type>
-static void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
-    if (vec) {
-        std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
-        vec->resize(vec->size() - 1);
-    }
-}
-
-template <typename Type>
-static uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
-    // assume vec is valid
-    const uint32_t index = vec->size();
-    vec->resize(index + 1);
-    (*vec)[index] = value;
-    return index;
-}
-
 static uint32_t addOperand(Model* model) {
     return hidl_vec_push_back(&model->operands,
                               {
-                                  .type = OperandType::INT32,
-                                  .dimensions = {},
-                                  .numberOfConsumers = 0,
-                                  .scale = 0.0f,
-                                  .zeroPoint = 0,
-                                  .lifetime = OperandLifeTime::MODEL_INPUT,
-                                  .location = {.poolIndex = 0, .offset = 0, .length = 0},
+                                      .type = OperandType::INT32,
+                                      .dimensions = {},
+                                      .numberOfConsumers = 0,
+                                      .scale = 0.0f,
+                                      .zeroPoint = 0,
+                                      .lifetime = OperandLifeTime::MODEL_INPUT,
+                                      .location = {.poolIndex = 0, .offset = 0, .length = 0},
                               });
 }
 
@@ -256,7 +229,7 @@
 static void mutateOperandZeroPointTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operand = 0; operand < model.operands.size(); ++operand) {
         const std::vector<int32_t> invalidZeroPoints =
-            getInvalidZeroPoints(model.operands[operand].type);
+                getInvalidZeroPoints(model.operands[operand].type);
         for (int32_t invalidZeroPoint : invalidZeroPoints) {
             const std::string message = "mutateOperandZeroPointTest: operand " +
                                         std::to_string(operand) + " has zero point of " +
@@ -292,13 +265,13 @@
         case OperandType::TENSOR_FLOAT16:
         case OperandType::TENSOR_FLOAT32:
             newOperand.dimensions =
-                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+                    operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.scale = 0.0f;
             newOperand.zeroPoint = 0;
             break;
         case OperandType::TENSOR_INT32:
             newOperand.dimensions =
-                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+                    operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.zeroPoint = 0;
             break;
         case OperandType::TENSOR_QUANT8_ASYMM:
@@ -306,19 +279,20 @@
         case OperandType::TENSOR_QUANT16_ASYMM:
         case OperandType::TENSOR_QUANT16_SYMM:
             newOperand.dimensions =
-                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+                    operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.scale = operand->scale != 0.0f ? operand->scale : 1.0f;
             break;
         case OperandType::TENSOR_QUANT8_SYMM_PER_CHANNEL: {
             newOperand.dimensions =
-                operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
+                    operand->dimensions.size() > 0 ? operand->dimensions : hidl_vec<uint32_t>({1});
             newOperand.scale = 0.0f;
             newOperand.zeroPoint = 0;
 
             SymmPerChannelQuantParams channelQuant;
             channelQuant.channelDim = 0;
             channelQuant.scales = hidl_vec<float>(
-                operand->dimensions.size() > 0 ? static_cast<size_t>(operand->dimensions[0]) : 0);
+                    operand->dimensions.size() > 0 ? static_cast<size_t>(operand->dimensions[0])
+                                                   : 0);
             for (size_t i = 0; i < channelQuant.scales.size(); ++i) {
                 channelQuant.scales[i] = 1.0f;
             }
@@ -435,7 +409,7 @@
                                         std::to_string(invalidOperationType);
             validate(device, message, model, [operation, invalidOperationType](Model* model) {
                 model->operations[operation].type =
-                    static_cast<OperationType>(invalidOperationType);
+                        static_cast<OperationType>(invalidOperationType);
             });
         }
     }
@@ -508,15 +482,15 @@
                 }
             }
         }
-        // BIDIRECTIONAL_SEQUENCE_LSTM and BIDIRECTIONAL_SEQUENCE_RNN can have either one or two
-        // outputs depending on their mergeOutputs parameter.
+        // 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 ||
             operation.type == OperationType::BIDIRECTIONAL_SEQUENCE_RNN) {
-            for (const size_t outOprand : operation.outputs) {
-                if (operand == outOprand) {
-                    return true;
-                }
+          for (const size_t outOprand : operation.outputs) {
+            if (operand == outOprand) {
+              return true;
             }
+          }
         }
     }
     return false;
@@ -690,7 +664,7 @@
 static void addOperationOutputTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
         const std::string message =
-            "addOperationOutputTest: operation " + std::to_string(operation);
+                "addOperationOutputTest: operation " + std::to_string(operation);
         validate(device, message, model, [operation](Model* model) {
             uint32_t index = addOperand(model, OperandLifeTime::MODEL_OUTPUT);
             hidl_vec_push_back(&model->operations[operation].outputs, index);
@@ -702,22 +676,23 @@
 ///////////////////////// VALIDATE EXECUTION PREFERENCE /////////////////////////
 
 static const int32_t invalidExecutionPreferences[] = {
-    static_cast<int32_t>(ExecutionPreference::LOW_POWER) - 1,        // lower bound
-    static_cast<int32_t>(ExecutionPreference::SUSTAINED_SPEED) + 1,  // upper bound
+        static_cast<int32_t>(ExecutionPreference::LOW_POWER) - 1,        // lower bound
+        static_cast<int32_t>(ExecutionPreference::SUSTAINED_SPEED) + 1,  // upper bound
 };
 
 static void mutateExecutionPreferenceTest(const sp<IDevice>& device, const Model& model) {
     for (int32_t preference : invalidExecutionPreferences) {
         const std::string message =
-            "mutateExecutionPreferenceTest: preference " + std::to_string(preference);
-        validate(device, message, model, [](Model*) {},
-                 static_cast<ExecutionPreference>(preference));
+                "mutateExecutionPreferenceTest: preference " + std::to_string(preference);
+        validate(
+                device, message, model, [](Model*) {},
+                static_cast<ExecutionPreference>(preference));
     }
 }
 
 ////////////////////////// ENTRY POINT //////////////////////////////
 
-void ValidationTest::validateModel(const Model& model) {
+void validateModel(const sp<IDevice>& device, const Model& model) {
     mutateOperandTypeTest(device, model);
     mutateOperandRankTest(device, model);
     mutateOperandScaleTest(device, model);
@@ -735,9 +710,4 @@
     mutateExecutionPreferenceTest(device, model);
 }
 
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_2
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::neuralnetworks::V1_2::vts::functional
diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
index 9703c2d..f25ee62 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
@@ -16,29 +16,19 @@
 
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
-#include "VtsHalNeuralnetworks.h"
-
-#include "Callbacks.h"
+#include "1.0/Utils.h"
+#include "1.2/Callbacks.h"
 #include "ExecutionBurstController.h"
+#include "GeneratedTestHarness.h"
 #include "TestHarness.h"
 #include "Utils.h"
+#include "VtsHalNeuralnetworks.h"
 
-#include <android-base/logging.h>
-#include <android/hidl/memory/1.0/IMemory.h>
-#include <hidlmemory/mapping.h>
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
-
-using ::android::hardware::neuralnetworks::V1_2::implementation::ExecutionCallback;
-using ::android::hidl::memory::V1_0::IMemory;
-using test_helper::for_all;
-using test_helper::MixedTyped;
-using test_helper::MixedTypedExample;
+using implementation::ExecutionCallback;
+using V1_0::ErrorStatus;
+using V1_0::Request;
 
 ///////////////////////// UTILITY FUNCTIONS /////////////////////////
 
@@ -69,7 +59,6 @@
         SCOPED_TRACE(message + " [execute_1_2]");
 
         sp<ExecutionCallback> executionCallback = new ExecutionCallback();
-        ASSERT_NE(nullptr, executionCallback.get());
         Return<ErrorStatus> executeLaunchStatus =
                 preparedModel->execute_1_2(request, measure, executionCallback);
         ASSERT_TRUE(executeLaunchStatus.isOk());
@@ -105,7 +94,7 @@
 
         // create burst
         std::shared_ptr<::android::nn::ExecutionBurstController> burst =
-                ::android::nn::ExecutionBurstController::create(preparedModel, /*blocking=*/true);
+                android::nn::ExecutionBurstController::create(preparedModel, /*blocking=*/true);
         ASSERT_NE(nullptr, burst.get());
 
         // create memory keys
@@ -137,26 +126,6 @@
     }
 }
 
-// Delete element from hidl_vec. hidl_vec doesn't support a "remove" operation,
-// so this is efficiently accomplished by moving the element to the end and
-// resizing the hidl_vec to one less.
-template <typename Type>
-static void hidl_vec_removeAt(hidl_vec<Type>* vec, uint32_t index) {
-    if (vec) {
-        std::rotate(vec->begin() + index, vec->begin() + index + 1, vec->end());
-        vec->resize(vec->size() - 1);
-    }
-}
-
-template <typename Type>
-static uint32_t hidl_vec_push_back(hidl_vec<Type>* vec, const Type& value) {
-    // assume vec is valid
-    const uint32_t index = vec->size();
-    vec->resize(index + 1);
-    (*vec)[index] = value;
-    return index;
-}
-
 ///////////////////////// REMOVE INPUT ////////////////////////////////////
 
 static void removeInputTest(const sp<IPreparedModel>& preparedModel, const Request& request) {
@@ -179,104 +148,21 @@
 
 ///////////////////////////// ENTRY POINT //////////////////////////////////
 
-std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples) {
-    const uint32_t INPUT = 0;
-    const uint32_t OUTPUT = 1;
-
-    std::vector<Request> requests;
-
-    for (auto& example : examples) {
-        const MixedTyped& inputs = example.operands.first;
-        const MixedTyped& outputs = example.operands.second;
-
-        std::vector<RequestArgument> inputs_info, outputs_info;
-        uint32_t inputSize = 0, outputSize = 0;
-
-        // This function only partially specifies the metadata (vector of RequestArguments).
-        // The contents are copied over below.
-        for_all(inputs, [&inputs_info, &inputSize](int index, auto, auto s) {
-            if (inputs_info.size() <= static_cast<size_t>(index)) inputs_info.resize(index + 1);
-            RequestArgument arg = {
-                .location = {.poolIndex = INPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
-                .dimensions = {},
-            };
-            RequestArgument arg_empty = {
-                .hasNoValue = true,
-            };
-            inputs_info[index] = s ? arg : arg_empty;
-            inputSize += s;
-        });
-        // Compute offset for inputs 1 and so on
-        {
-            size_t offset = 0;
-            for (auto& i : inputs_info) {
-                if (!i.hasNoValue) i.location.offset = offset;
-                offset += i.location.length;
-            }
-        }
-
-        // Go through all outputs, initialize RequestArgument descriptors
-        for_all(outputs, [&outputs_info, &outputSize](int index, auto, auto s) {
-            if (outputs_info.size() <= static_cast<size_t>(index)) outputs_info.resize(index + 1);
-            RequestArgument arg = {
-                .location = {.poolIndex = OUTPUT, .offset = 0, .length = static_cast<uint32_t>(s)},
-                .dimensions = {},
-            };
-            outputs_info[index] = arg;
-            outputSize += s;
-        });
-        // Compute offset for outputs 1 and so on
-        {
-            size_t offset = 0;
-            for (auto& i : outputs_info) {
-                i.location.offset = offset;
-                offset += i.location.length;
-            }
-        }
-        std::vector<hidl_memory> pools = {nn::allocateSharedMemory(inputSize),
-                                          nn::allocateSharedMemory(outputSize)};
-        if (pools[INPUT].size() == 0 || pools[OUTPUT].size() == 0) {
-            return {};
-        }
-
-        // map pool
-        sp<IMemory> inputMemory = mapMemory(pools[INPUT]);
-        if (inputMemory == nullptr) {
-            return {};
-        }
-        char* inputPtr = reinterpret_cast<char*>(static_cast<void*>(inputMemory->getPointer()));
-        if (inputPtr == nullptr) {
-            return {};
-        }
-
-        // initialize pool
-        inputMemory->update();
-        for_all(inputs, [&inputs_info, inputPtr](int index, auto p, auto s) {
-            char* begin = (char*)p;
-            char* end = begin + s;
-            // TODO: handle more than one input
-            std::copy(begin, end, inputPtr + inputs_info[index].location.offset);
-        });
-        inputMemory->commit();
-
-        requests.push_back({.inputs = inputs_info, .outputs = outputs_info, .pools = pools});
-    }
-
-    return requests;
+void validateRequest(const sp<IPreparedModel>& preparedModel, const Request& request) {
+    removeInputTest(preparedModel, request);
+    removeOutputTest(preparedModel, request);
 }
 
-void ValidationTest::validateRequests(const sp<IPreparedModel>& preparedModel,
-                                      const std::vector<Request>& requests) {
-    // validate each request
-    for (const Request& request : requests) {
-        removeInputTest(preparedModel, request);
-        removeOutputTest(preparedModel, request);
-    }
+void validateRequestFailure(const sp<IPreparedModel>& preparedModel, const Request& request) {
+    SCOPED_TRACE("Expecting request to fail [executeSynchronously]");
+    Return<void> executeStatus = preparedModel->executeSynchronously(
+            request, MeasureTiming::NO,
+            [](ErrorStatus error, const hidl_vec<OutputShape>& outputShapes, const Timing& timing) {
+                ASSERT_NE(ErrorStatus::NONE, error);
+                EXPECT_EQ(outputShapes.size(), 0);
+                EXPECT_TRUE(badTiming(timing));
+            });
+    ASSERT_TRUE(executeStatus.isOk());
 }
 
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_2
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::neuralnetworks::V1_2::vts::functional
diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp
index 4ddefe8..4fbd0e2 100644
--- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp
+++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp
@@ -17,42 +17,43 @@
 #define LOG_TAG "neuralnetworks_hidl_hal_test"
 
 #include "VtsHalNeuralnetworks.h"
-
 #include <android-base/logging.h>
+#include <hidl/ServiceManagement.h>
+#include <string>
+#include <utility>
+#include "1.0/Callbacks.h"
+#include "1.0/Utils.h"
+#include "GeneratedTestHarness.h"
+#include "TestHarness.h"
 
-#include "Callbacks.h"
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
-namespace vts {
-namespace functional {
-
-using ::android::hardware::neuralnetworks::V1_2::implementation::PreparedModelCallback;
+using implementation::PreparedModelCallback;
 using HidlToken = hidl_array<uint8_t, static_cast<uint32_t>(Constant::BYTE_SIZE_OF_CACHE_TOKEN)>;
+using V1_0::ErrorStatus;
+using V1_0::Request;
 using V1_1::ExecutionPreference;
 
 // internal helper function
-static void createPreparedModel(const sp<IDevice>& device, const Model& model,
-                                sp<IPreparedModel>* preparedModel) {
+void createPreparedModel(const sp<IDevice>& device, const Model& model,
+                         sp<IPreparedModel>* preparedModel) {
     ASSERT_NE(nullptr, preparedModel);
+    *preparedModel = nullptr;
 
     // see if service can handle model
     bool fullySupportsModel = false;
-    Return<void> supportedOpsLaunchStatus = device->getSupportedOperations_1_2(
+    const Return<void> supportedCall = device->getSupportedOperations_1_2(
             model, [&fullySupportsModel](ErrorStatus status, const hidl_vec<bool>& supported) {
                 ASSERT_EQ(ErrorStatus::NONE, status);
                 ASSERT_NE(0ul, supported.size());
                 fullySupportsModel = std::all_of(supported.begin(), supported.end(),
                                                  [](bool valid) { return valid; });
             });
-    ASSERT_TRUE(supportedOpsLaunchStatus.isOk());
+    ASSERT_TRUE(supportedCall.isOk());
 
     // launch prepare model
-    sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
-    ASSERT_NE(nullptr, preparedModelCallback.get());
-    Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_2(
+    const sp<PreparedModelCallback> preparedModelCallback = new PreparedModelCallback();
+    const Return<ErrorStatus> prepareLaunchStatus = device->prepareModel_1_2(
             model, ExecutionPreference::FAST_SINGLE_ANSWER, hidl_vec<hidl_handle>(),
             hidl_vec<hidl_handle>(), HidlToken(), preparedModelCallback);
     ASSERT_TRUE(prepareLaunchStatus.isOk());
@@ -60,7 +61,7 @@
 
     // retrieve prepared model
     preparedModelCallback->wait();
-    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    const ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
     *preparedModel = getPreparedModel_1_2(preparedModelCallback);
 
     // The getSupportedOperations_1_2 call returns a list of operations that are
@@ -72,106 +73,99 @@
     // can continue.
     if (!fullySupportsModel && prepareReturnStatus != ErrorStatus::NONE) {
         ASSERT_EQ(nullptr, preparedModel->get());
-        LOG(INFO) << "NN VTS: Unable to test Request validation because vendor service cannot "
-                     "prepare model that it does not support.";
-        std::cout << "[          ]   Unable to test Request validation because vendor service "
-                     "cannot prepare model that it does not support."
+        LOG(INFO) << "NN VTS: Early termination of test because vendor service cannot prepare "
+                     "model that it does not support.";
+        std::cout << "[          ]   Early termination of test because vendor service cannot "
+                     "prepare model that it does not support."
                   << std::endl;
-        return;
+        GTEST_SKIP();
     }
     ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus);
     ASSERT_NE(nullptr, preparedModel->get());
 }
 
-// A class for test environment setup
-NeuralnetworksHidlEnvironment::NeuralnetworksHidlEnvironment() {}
-
-NeuralnetworksHidlEnvironment::~NeuralnetworksHidlEnvironment() {}
-
-NeuralnetworksHidlEnvironment* NeuralnetworksHidlEnvironment::getInstance() {
-    // This has to return a "new" object because it is freed inside
-    // ::testing::AddGlobalTestEnvironment when the gtest is being torn down
-    static NeuralnetworksHidlEnvironment* instance = new NeuralnetworksHidlEnvironment();
-    return instance;
-}
-
-void NeuralnetworksHidlEnvironment::registerTestServices() {
-    registerTestService<IDevice>();
-}
-
-// The main test class for NEURALNETWORK HIDL HAL.
-NeuralnetworksHidlTest::NeuralnetworksHidlTest() {}
-
-NeuralnetworksHidlTest::~NeuralnetworksHidlTest() {}
-
 void NeuralnetworksHidlTest::SetUp() {
-    ::testing::VtsHalHidlTargetTestBase::SetUp();
-    device = ::testing::VtsHalHidlTargetTestBase::getService<IDevice>(
-            NeuralnetworksHidlEnvironment::getInstance());
-
-#ifdef PRESUBMIT_NOT_VTS
-    const std::string name =
-            NeuralnetworksHidlEnvironment::getInstance()->getServiceName<IDevice>();
-    const std::string sampleDriver = "sample-";
-    if (device == nullptr && name.substr(0, sampleDriver.size()) == sampleDriver) {
-        GTEST_SKIP();
-    }
-#endif  // PRESUBMIT_NOT_VTS
-
-    ASSERT_NE(nullptr, device.get());
+    testing::TestWithParam<NeuralnetworksHidlTestParam>::SetUp();
+    ASSERT_NE(kDevice, nullptr);
 }
 
-void NeuralnetworksHidlTest::TearDown() {
-    device = nullptr;
-    ::testing::VtsHalHidlTargetTestBase::TearDown();
+static NamedDevice makeNamedDevice(const std::string& name) {
+    return {name, IDevice::getService(name)};
 }
 
-void ValidationTest::validateEverything(const Model& model, const std::vector<Request>& requests) {
-    validateModel(model);
+static std::vector<NamedDevice> getNamedDevicesImpl() {
+    // Retrieves the name of all service instances that implement IDevice,
+    // including any Lazy HAL instances.
+    const std::vector<std::string> names = hardware::getAllHalInstanceNames(IDevice::descriptor);
 
-    // create IPreparedModel
+    // Get a handle to each device and pair it with its name.
+    std::vector<NamedDevice> namedDevices;
+    namedDevices.reserve(names.size());
+    std::transform(names.begin(), names.end(), std::back_inserter(namedDevices), makeNamedDevice);
+    return namedDevices;
+}
+
+const std::vector<NamedDevice>& getNamedDevices() {
+    const static std::vector<NamedDevice> devices = getNamedDevicesImpl();
+    return devices;
+}
+
+std::string printNeuralnetworksHidlTest(
+        const testing::TestParamInfo<NeuralnetworksHidlTestParam>& info) {
+    return gtestCompliantName(getName(info.param));
+}
+
+INSTANTIATE_DEVICE_TEST(NeuralnetworksHidlTest);
+
+// Forward declaration from ValidateModel.cpp
+void validateModel(const sp<IDevice>& device, const Model& model);
+// Forward declaration from ValidateRequest.cpp
+void validateRequest(const sp<IPreparedModel>& preparedModel, const V1_0::Request& request);
+// Forward declaration from ValidateRequest.cpp
+void validateRequestFailure(const sp<IPreparedModel>& preparedModel, const V1_0::Request& request);
+// Forward declaration from ValidateBurst.cpp
+void validateBurst(const sp<IPreparedModel>& preparedModel, const V1_0::Request& request);
+
+void validateEverything(const sp<IDevice>& device, const Model& model, const Request& request) {
+    validateModel(device, model);
+
+    // Create IPreparedModel.
     sp<IPreparedModel> preparedModel;
-    ASSERT_NO_FATAL_FAILURE(createPreparedModel(device, model, &preparedModel));
-    if (preparedModel == nullptr) {
-        return;
+    createPreparedModel(device, model, &preparedModel);
+    if (preparedModel == nullptr) return;
+
+    validateRequest(preparedModel, request);
+    validateBurst(preparedModel, request);
+}
+
+void validateFailure(const sp<IDevice>& device, const Model& model, const Request& request) {
+    // TODO: Should this always succeed?
+    //       What if the invalid input is part of the model (i.e., a parameter).
+    validateModel(device, model);
+
+    // Create IPreparedModel.
+    sp<IPreparedModel> preparedModel;
+    createPreparedModel(device, model, &preparedModel);
+    if (preparedModel == nullptr) return;
+
+    validateRequestFailure(preparedModel, request);
+}
+
+TEST_P(ValidationTest, Test) {
+    const Model model = createModel(kTestModel);
+    const Request request = createRequest(kTestModel);
+    if (kTestModel.expectFailure) {
+        validateFailure(kDevice, model, request);
+    } else {
+        validateEverything(kDevice, model, request);
     }
-
-    validateRequests(preparedModel, requests);
-    validateBurst(preparedModel, requests);
 }
 
-sp<IPreparedModel> getPreparedModel_1_2(
-    const sp<V1_2::implementation::PreparedModelCallback>& callback) {
+INSTANTIATE_GENERATED_TEST(ValidationTest, [](const test_helper::TestModel&) { return true; });
+
+sp<IPreparedModel> getPreparedModel_1_2(const sp<implementation::PreparedModelCallback>& callback) {
     sp<V1_0::IPreparedModel> preparedModelV1_0 = callback->getPreparedModel();
-    return V1_2::IPreparedModel::castFrom(preparedModelV1_0).withDefault(nullptr);
+    return IPreparedModel::castFrom(preparedModelV1_0).withDefault(nullptr);
 }
 
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_2
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
-
-namespace android::hardware::neuralnetworks::V1_0 {
-
-::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus) {
-    return os << toString(errorStatus);
-}
-
-::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus) {
-    return os << toString(deviceStatus);
-}
-
-}  // namespace android::hardware::neuralnetworks::V1_0
-
-using android::hardware::neuralnetworks::V1_2::vts::functional::NeuralnetworksHidlEnvironment;
-
-int main(int argc, char** argv) {
-    ::testing::AddGlobalTestEnvironment(NeuralnetworksHidlEnvironment::getInstance());
-    ::testing::InitGoogleTest(&argc, argv);
-    NeuralnetworksHidlEnvironment::getInstance()->init(&argc, argv);
-
-    int status = RUN_ALL_TESTS();
-    return status;
-}
+}  // namespace android::hardware::neuralnetworks::V1_2::vts::functional
diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
index 8d1acbe..d01336e 100644
--- a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
@@ -14,97 +14,44 @@
  * limitations under the License.
  */
 
-#ifndef VTS_HAL_NEURALNETWORKS_V1_2_H
-#define VTS_HAL_NEURALNETWORKS_V1_2_H
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_2_VTS_HAL_NEURALNETWORKS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_2_VTS_HAL_NEURALNETWORKS_H
 
-#include "Callbacks.h"
-
-#include <android/hardware/neuralnetworks/1.0/types.h>
-#include <android/hardware/neuralnetworks/1.1/types.h>
 #include <android/hardware/neuralnetworks/1.2/IDevice.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModel.h>
 #include <android/hardware/neuralnetworks/1.2/types.h>
-
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
-
-#include <android-base/macros.h>
 #include <gtest/gtest.h>
-#include <iostream>
-#include <vector>
+#include "1.0/Utils.h"
+#include "1.2/Callbacks.h"
 
-namespace android {
-namespace hardware {
-namespace neuralnetworks {
-namespace V1_2 {
+namespace android::hardware::neuralnetworks::V1_2::vts::functional {
 
-using V1_0::DeviceStatus;
-using V1_0::ErrorStatus;
-using V1_0::Request;
+using NamedDevice = Named<sp<IDevice>>;
+using NeuralnetworksHidlTestParam = NamedDevice;
 
-namespace vts {
-namespace functional {
-
-// A class for test environment setup
-class NeuralnetworksHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-    DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlEnvironment);
-    NeuralnetworksHidlEnvironment();
-    ~NeuralnetworksHidlEnvironment() override;
-
-   public:
-    static NeuralnetworksHidlEnvironment* getInstance();
-    void registerTestServices() override;
-};
-
-// The main test class for NEURALNETWORKS HIDL HAL.
-class NeuralnetworksHidlTest : public ::testing::VtsHalHidlTargetTestBase {
-    DISALLOW_COPY_AND_ASSIGN(NeuralnetworksHidlTest);
-
-   public:
-    NeuralnetworksHidlTest();
-    ~NeuralnetworksHidlTest() override;
+class NeuralnetworksHidlTest : public testing::TestWithParam<NeuralnetworksHidlTestParam> {
+  protected:
     void SetUp() override;
-    void TearDown() override;
-
-   protected:
-    sp<IDevice> device;
+    const sp<IDevice> kDevice = getData(GetParam());
 };
 
-// Tag for the validation tests
-class ValidationTest : public NeuralnetworksHidlTest {
-   protected:
-     void validateEverything(const Model& model, const std::vector<Request>& requests);
+const std::vector<NamedDevice>& getNamedDevices();
 
-   private:
-     void validateModel(const Model& model);
-     void validateRequests(const sp<IPreparedModel>& preparedModel,
-                           const std::vector<Request>& requests);
-     void validateBurst(const sp<IPreparedModel>& preparedModel,
-                        const std::vector<Request>& requests);
-};
+std::string printNeuralnetworksHidlTest(
+        const testing::TestParamInfo<NeuralnetworksHidlTestParam>& info);
 
-// Tag for the generated tests
-class GeneratedTest : public NeuralnetworksHidlTest {};
+#define INSTANTIATE_DEVICE_TEST(TestSuite)                                                 \
+    INSTANTIATE_TEST_SUITE_P(PerInstance, TestSuite, testing::ValuesIn(getNamedDevices()), \
+                             printNeuralnetworksHidlTest)
 
-// Tag for the dynamic output shape tests
-class DynamicOutputShapeTest : public NeuralnetworksHidlTest {};
+// Create an IPreparedModel object. If the model cannot be prepared,
+// "preparedModel" will be nullptr instead.
+void createPreparedModel(const sp<IDevice>& device, const Model& model,
+                         sp<IPreparedModel>* preparedModel);
 
 // Utility function to get PreparedModel from callback and downcast to V1_2.
-sp<IPreparedModel> getPreparedModel_1_2(
-    const sp<V1_2::implementation::PreparedModelCallback>& callback);
+sp<IPreparedModel> getPreparedModel_1_2(const sp<implementation::PreparedModelCallback>& callback);
 
-}  // namespace functional
-}  // namespace vts
-}  // namespace V1_2
-}  // namespace neuralnetworks
-}  // namespace hardware
-}  // namespace android
+}  // namespace android::hardware::neuralnetworks::V1_2::vts::functional
 
-namespace android::hardware::neuralnetworks::V1_0 {
-
-// pretty-print values for error messages
-::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus);
-::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus);
-
-}  // namespace android::hardware::neuralnetworks::V1_0
-
-#endif  // VTS_HAL_NEURALNETWORKS_V1_2_H
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_2_VTS_HAL_NEURALNETWORKS_H
diff --git a/neuralnetworks/1.2/vts/functional/include/1.2/Callbacks.h b/neuralnetworks/1.2/vts/functional/include/1.2/Callbacks.h
new file mode 100644
index 0000000..bf4792c
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/include/1.2/Callbacks.h
@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_NEURALNETWORKS_V1_2_CALLBACKS_H
+#define ANDROID_HARDWARE_NEURALNETWORKS_V1_2_CALLBACKS_H
+
+#include <android-base/thread_annotations.h>
+#include <android/hardware/neuralnetworks/1.0/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.0/IPreparedModelCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IExecutionCallback.h>
+#include <android/hardware/neuralnetworks/1.2/IPreparedModelCallback.h>
+#include <hidl/Status.h>
+#include <condition_variable>
+#include <mutex>
+
+/*
+ * The Callback classes are used internally by the NeuralNetworks runtime to
+ * synchronize between different threads. An asynchronous task is launched
+ * paired with a callback object. When a client thread requires the output being
+ * generated by the asynchronous task, the client thread can wait for the result
+ * and be blocked until it has completed. Any wait may safely be called
+ * concurrently, even on the same callback object. When the asynchronous task
+ * has finished its workload, it must immediately call "notify*". If the
+ * asynchronous task has failed to launch, the function that tried to launch the
+ * asynchronous task must immediately call "notify*". This "notify*" call
+ * awakens any client threads waiting on the callback object.
+ *
+ * These classes exist to enable synchronization across HIDL. When
+ * synchronization is only required in the same process, consider using
+ * std::future, std::mutex, std::condition_variable, or std::experimental::latch
+ * instead.
+ */
+
+namespace android::hardware::neuralnetworks::V1_2::implementation {
+
+/**
+ * The PreparedModelCallback class is used to receive the error status of
+ * preparing a model as well as the prepared model from a task executing
+ * asynchronously with respect to the runtime. If a calling thread calls wait
+ * or get* on a PreparedModelCallback object and the corresponding asynchronous
+ * task has not finished preparing the model, the calling thread will block
+ * until the asynchronous task has either called notify or notify_1_2.
+ *
+ * If the callback object is notified more than once, only the results of the
+ * first call to notify* are used, and the results from subsequent calls are
+ * discarded.
+ *
+ * This callback object is passed as an argument to IDevice::prepareModel*.
+ */
+class PreparedModelCallback : public IPreparedModelCallback {
+  public:
+    /**
+     * IPreparedModelCallback::notify marks the callback object with the return
+     * status of the asynchronous model preparation along with the prepared
+     * model, and allows all prior and future wait calls on the
+     * PreparedModelCallback object to proceed.
+     *
+     * Either IPreparedModelCallback::notify or
+     * IPreparedModelCallback::notify_1_2 must be called on a given
+     * PreparedModelCallback object.
+     *
+     * If the callback object is notified more than once, only the results of
+     * the first call to notify* are used, and the results from subsequent calls
+     * are discarded.
+     *
+     * @param status Error status returned from asynchronously preparing the
+     *     model; will be:
+     *     - NONE if the asynchronous preparation was successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - INVALID_ARGUMENT if the input model is invalid
+     * @param preparedModel Returned model that has been prepared for execution,
+     *     nullptr if the model was unable to be prepared.
+     */
+    Return<void> notify(V1_0::ErrorStatus status,
+                        const sp<V1_0::IPreparedModel>& preparedModel) override;
+
+    /**
+     * IPreparedModelCallback::notify_1_2 marks the callback object with the
+     * return status of the asynchronous model preparation along with the
+     * prepared model, and allows all prior and future wait calls on the
+     * PreparedModelCallback object to proceed.
+     *
+     * Either IPreparedModelCallback::notify or
+     * IPreparedModelCallback::notify_1_2 must be called on a given
+     * PreparedModelCallback object.
+     *
+     * If the callback object is notified more than once, only the results of
+     * the first call to notify* are used, and the results from subsequent calls
+     * are discarded.
+     *
+     * @param status Error status returned from asynchronously preparing the
+     *     model; will be:
+     *     - NONE if the asynchronous preparation was successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - INVALID_ARGUMENT if the input model is invalid
+     * @param preparedModel Returned model that has been prepared for execution,
+     *     nullptr if the model was unable to be prepared.
+     */
+    Return<void> notify_1_2(V1_0::ErrorStatus status,
+                            const sp<V1_2::IPreparedModel>& preparedModel) override;
+
+    /**
+     * PreparedModelCallback::wait blocks until notify* has been called on the
+     * callback object.
+     */
+    void wait() const;
+
+    /**
+     * Retrieves the error status returned from the asynchronous task launched
+     * by IDevice::prepareModel*. If IDevice::prepareModel* has not finished
+     * asynchronously preparing the model, this call will block until the
+     * asynchronous task notifies the object.
+     *
+     * @return status Error status returned from asynchronously preparing the
+     *     model; will be:
+     *     - NONE if the asynchronous preparation was successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - INVALID_ARGUMENT if the input model is invalid
+     */
+    V1_0::ErrorStatus getStatus() const;
+
+    /**
+     * Retrieves the model that has been prepared for execution from the
+     * asynchronous task launched by IDevice::prepareModel*. If
+     * IDevice::prepareModel* has not finished asynchronously preparing the
+     * model, this call will block until the asynchronous task notifies the
+     * object.
+     *
+     * @return preparedModel Returned model that has been prepared for
+     *     execution, nullptr if the model was unable to be prepared.
+     */
+    sp<V1_0::IPreparedModel> getPreparedModel() const;
+
+  private:
+    mutable std::mutex mMutex;
+    mutable std::condition_variable mCondition;
+    bool mNotified GUARDED_BY(mMutex) = false;
+    V1_0::ErrorStatus mErrorStatus = V1_0::ErrorStatus::GENERAL_FAILURE;
+    sp<V1_0::IPreparedModel> mPreparedModel;
+};
+
+/**
+ * The ExecutionCallback class is used to receive the results of the execution
+ * from a task executing asynchronously with respect to the runtime. If a
+ * calling thread calls wait or get* on a ExecutionCallback object and the
+ * corresponding asynchronous task has not finished the execution, the calling
+ * thread will block until the asynchronous task has either called notify or
+ * notify_1_2.
+ *
+ * If the callback object is notified more than once, only the results of the
+ * first call to notify* are used, and the results from subsequent calls are
+ * discarded.
+ *
+ * This callback object is passed as an argument to IPreparedModel::execute*.
+ */
+class ExecutionCallback : public IExecutionCallback {
+  public:
+    /**
+     * IExecutionCallback::notify marks the callback object with the return
+     * status of the asynchronous execution that held this callback and enables
+     * all prior and future wait calls on the ExecutionCallback object to
+     * proceed.
+     *
+     * Either IExecutionCallback::notify or IExecutionCallback::notify_1_2 must
+     * be called on a given ExecutionCallback object.
+     *
+     * If the callback object is notified more than once, only the results of
+     * the first call to notify* are used, and the results from subsequent calls
+     * are discarded.
+     *
+     * @param status Error status returned from launching the asynchronous task
+     *     (if the launch fails) or from the asynchronous task itself (if the
+     *     launch succeeds). Must be:
+     *     - NONE if the asynchronous execution was successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - OUTPUT_INSUFFICIENT_SIZE if provided output buffer is not large
+     *         enough to store the resultant values
+     *     - INVALID_ARGUMENT if the input request is invalid
+     */
+    Return<void> notify(V1_0::ErrorStatus status) override;
+
+    /**
+     * IExecutionCallback::notify_1_2 marks the callback object with the results
+     * (error status, dynamic output shapes, and timing information) of the
+     * asynchronous execution that held this callback and enables all prior and
+     * future wait calls on the ExecutionCallback object to proceed.
+     *
+     * Either IExecutionCallback::notify or IExecutionCallback::notify_1_2 must
+     * be called on a given ExecutionCallback object.
+     *
+     * If the callback object is notified more than once, only the results of
+     * the first call to notify* are used, and the results from subsequent calls
+     * are discarded.
+     *
+     * @param status Error status returned from launching the asynchronous task
+     *     (if the launch fails) or from the asynchronous task itself (if the
+     *     launch succeeds). Must be:
+     *     - NONE if the asynchronous execution was successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if the asynchronous task resulted in an unspecified
+     *         error
+     *     - OUTPUT_INSUFFICIENT_SIZE if at least one output operand buffer is
+     *         not large enough to store the corresponding output
+     *     - INVALID_ARGUMENT if one of the input arguments to prepareModel is
+     *         invalid
+     * @param outputShapes A list of shape information of model output operands.
+     *     The index into "outputShapes" corresponds to the index of the output
+     *     operand in the Request outputs vector. outputShapes must be empty
+     *     unless the status is either NONE or OUTPUT_INSUFFICIENT_SIZE.
+     * @param Timing Duration of execution. Unless MeasureTiming::YES was passed
+     *     when launching the execution and status is NONE, all times must be
+     *     reported as UINT64_MAX. A driver may choose to report any time as
+     *     UINT64_MAX, indicating that particular measurement is not available.
+     */
+    Return<void> notify_1_2(V1_0::ErrorStatus status, const hidl_vec<OutputShape>& outputShapes,
+                            const Timing& timing) override;
+
+    // An overload of the latest notify interface to hide the version from ExecutionBuilder.
+    Return<void> notify(V1_0::ErrorStatus status, const hidl_vec<OutputShape>& outputShapes,
+                        const Timing& timing) {
+        return notify_1_2(status, outputShapes, timing);
+    }
+
+    /**
+     * ExecutionCallback::wait blocks until notify* has been called on the
+     * callback object.
+     */
+    void wait() const;
+
+    /**
+     * Retrieves the error status returned from the asynchronous task launched
+     * by either IPreparedModel::execute or IPreparedModel::execute_1_2. If
+     * IPreparedModel::execute or IPreparedModel::execute_1_2 has not finished
+     * asynchronously executing, this call will block until the asynchronous
+     * task notifies the object.
+     *
+     * @return status Error status returned from launching the asynchronous task
+     *     (if the launch fails) or from the asynchronous task itself (if the
+     *     launch succeeds). Must be:
+     *     - NONE if the asynchronous execution was successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if the asynchronous task resulted in an unspecified
+     *         error
+     *     - OUTPUT_INSUFFICIENT_SIZE if at least one output operand buffer is
+     *         not large enough to store the corresponding output
+     *     - INVALID_ARGUMENT if one of the input arguments to prepareModel is
+     *         invalid
+     */
+    V1_0::ErrorStatus getStatus() const;
+
+    /**
+     * Retrieves the output shapes returned from the asynchronous task launched
+     * by IPreparedModel::execute_1_2. If IPreparedModel::execute_1_2 has not
+     * finished asynchronously executing, this call will block until the
+     * asynchronous task notifies the object.
+     *
+     * If the asynchronous task was launched by IPreparedModel::execute, an
+     * empty vector will be returned.
+     *
+     * @return outputShapes A list of shape information of model output
+     *     operands. The index into "outputShapes" corresponds to the index of
+     *     the output operand in the Request outputs vector. outputShapes must
+     *     be empty unless the status is either NONE or
+     *     OUTPUT_INSUFFICIENT_SIZE. outputShaps may be empty if the status is
+     *     NONE and all model output operands are fully-specified at execution
+     *     time. outputShapes must have the same number of elements as the
+     *     number of model output operands if the status is
+     *     OUTPUT_INSUFFICIENT_SIZE, or if the status is NONE and the model has
+     *     at least one output operand that is not fully-specified.
+     */
+    const std::vector<OutputShape>& getOutputShapes() const;
+
+    /**
+     * Retrieves the duration of execution of the asynchronous task launched by
+     * IPreparedModel::execute_1_2. If IPreparedModel::execute_1_2 has not
+     * finished asynchronously executing, this call will block until the
+     * asynchronous task notifies the object.
+     *
+     * If the asynchronous task was launched by IPreparedModel::execute, every
+     * time must be UINT64_MAX.
+     *
+     * @return timing Duration of the execution. Every time must be UINT64_MAX
+     *     unless the status is NONE.
+     */
+    Timing getTiming() const;
+
+  private:
+    /*
+     * ExecutionCallback::notifyInternal stores the results of the execution
+     * (status, output shapes, and timing information) in the ExecutionCallback
+     * object before any call to wait or get* return. It then enables all prior
+     * and future wait calls on the ExecutionCallback object to proceed.
+     */
+    void notifyInternal(V1_0::ErrorStatus errorStatus, const hidl_vec<OutputShape>& outputShapes,
+                        const Timing& timing);
+
+    // members
+    mutable std::mutex mMutex;
+    mutable std::condition_variable mCondition;
+    bool mNotified GUARDED_BY(mMutex) = false;
+    V1_0::ErrorStatus mErrorStatus = V1_0::ErrorStatus::GENERAL_FAILURE;
+    std::vector<OutputShape> mOutputShapes = {};
+    Timing mTiming = {};
+};
+
+}  // namespace android::hardware::neuralnetworks::V1_2::implementation
+
+#endif  // ANDROID_HARDWARE_NEURALNETWORKS_V1_2_CALLBACKS_H
diff --git a/neuralnetworks/TEST_MAPPING b/neuralnetworks/TEST_MAPPING
index 50b6c19..421922a 100644
--- a/neuralnetworks/TEST_MAPPING
+++ b/neuralnetworks/TEST_MAPPING
@@ -1,26 +1,35 @@
 {
   "presubmit": [
     {
-      "name": "PresubmitHalNeuralnetworksV1_0TargetTest",
+      "name": "VtsHalNeuralnetworksV1_0TargetTest",
       "options": [
         {
-          "native-test-flag": "--hal_service_instance=android.hardware.neuralnetworks@1.0::IDevice/sample-all"
+          // Just use sample-all driver for presubmit tests for faster results.
+          // The other sample drivers (fast-float, quant, etc.) are subsets of
+          // sample-all.
+          "native-test-flag": "--gtest_filter=*sample_all*"
         }
       ]
     },
     {
-      "name": "PresubmitHalNeuralnetworksV1_1TargetTest",
+      "name": "VtsHalNeuralnetworksV1_1TargetTest",
       "options": [
         {
-          "native-test-flag": "--hal_service_instance=android.hardware.neuralnetworks@1.1::IDevice/sample-all"
+          // Just use sample-all driver for presubmit tests for faster results.
+          // The other sample drivers (fast-float, quant, etc.) are subsets of
+          // sample-all.
+          "native-test-flag": "--gtest_filter=*sample_all*"
         }
       ]
     },
     {
-      "name": "PresubmitHalNeuralnetworksV1_2TargetTest",
+      "name": "VtsHalNeuralnetworksV1_2TargetTest",
       "options": [
         {
-          "native-test-flag": "--hal_service_instance=android.hardware.neuralnetworks@1.2::IDevice/sample-all"
+          // Just use sample-all driver for presubmit tests for faster results.
+          // The other sample drivers (fast-float, quant, etc.) are subsets of
+          // sample-all.
+          "native-test-flag": "--gtest_filter=*sample_all*"
         }
       ]
     }
diff --git a/nfc/1.0/Android.bp b/nfc/1.0/Android.bp
index e0625d0..bd64907 100644
--- a/nfc/1.0/Android.bp
+++ b/nfc/1.0/Android.bp
@@ -17,4 +17,3 @@
     gen_java: true,
     gen_java_constants: true,
 }
-
diff --git a/nfc/1.0/default/Android.bp b/nfc/1.0/default/Android.bp
index 3b53d16..9827edd 100644
--- a/nfc/1.0/default/Android.bp
+++ b/nfc/1.0/default/Android.bp
@@ -12,7 +12,6 @@
         "libcutils",
         "libutils",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.nfc@1.0",
     ],
 }
@@ -33,7 +32,6 @@
         "libutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.nfc@1.0",
     ],
 
diff --git a/nfc/1.0/default/android.hardware.nfc@1.0-service.rc b/nfc/1.0/default/android.hardware.nfc@1.0-service.rc
index 3a5c776..27e35d2 100644
--- a/nfc/1.0/default/android.hardware.nfc@1.0-service.rc
+++ b/nfc/1.0/default/android.hardware.nfc@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.nfc_hal_service /vendor/bin/hw/android.hardware.nfc@1.0-service
+    interface android.hardware.nfc@1.0::INfc default
     class hal
     user nfc
     group nfc
diff --git a/nfc/1.1/Android.bp b/nfc/1.1/Android.bp
index bbf49b2..1f8789f 100644
--- a/nfc/1.1/Android.bp
+++ b/nfc/1.1/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/nfc/1.2/Android.bp b/nfc/1.2/Android.bp
index cfb8b85..aa68d2f 100644
--- a/nfc/1.2/Android.bp
+++ b/nfc/1.2/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/nfc/1.2/vts/OWNERS b/nfc/1.2/vts/OWNERS
new file mode 100644
index 0000000..21d4df1
--- /dev/null
+++ b/nfc/1.2/vts/OWNERS
@@ -0,0 +1,3 @@
+zachoverflow@google.com
+jackcwyu@google.com
+georgekgchang@google.com
diff --git a/oemlock/1.0/Android.bp b/oemlock/1.0/Android.bp
index 894188b..e784be0 100644
--- a/oemlock/1.0/Android.bp
+++ b/oemlock/1.0/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/power/1.0/Android.bp b/power/1.0/Android.bp
index dbc0a36..6ba1d78 100644
--- a/power/1.0/Android.bp
+++ b/power/1.0/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/power/1.0/default/Android.bp b/power/1.0/default/Android.bp
index 4f43b95..1d152ee 100644
--- a/power/1.0/default/Android.bp
+++ b/power/1.0/default/Android.bp
@@ -28,7 +28,6 @@
         "liblog",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "android.hardware.power@1.0",
     ],
@@ -54,7 +53,6 @@
         "libutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.power@1.0",
     ],
 
diff --git a/power/1.0/default/android.hardware.power@1.0-service.rc b/power/1.0/default/android.hardware.power@1.0-service.rc
index 657c733..f3fd303 100644
--- a/power/1.0/default/android.hardware.power@1.0-service.rc
+++ b/power/1.0/default/android.hardware.power@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.power-hal-1-0 /vendor/bin/hw/android.hardware.power@1.0-service
+    interface android.hardware.power@1.0::IPower default
     class hal
     user system
     group system
diff --git a/power/1.1/Android.bp b/power/1.1/Android.bp
index de55396..6b133cc 100644
--- a/power/1.1/Android.bp
+++ b/power/1.1/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/power/1.2/Android.bp b/power/1.2/Android.bp
index 284e736..296965b 100644
--- a/power/1.2/Android.bp
+++ b/power/1.2/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/power/1.3/Android.bp b/power/1.3/Android.bp
index 320f1e6..00ca750 100644
--- a/power/1.3/Android.bp
+++ b/power/1.3/Android.bp
@@ -18,4 +18,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/power/stats/1.0/Android.bp b/power/stats/1.0/Android.bp
index 9cf24cf..c592006 100644
--- a/power/stats/1.0/Android.bp
+++ b/power/stats/1.0/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/power/stats/1.0/default/Android.bp b/power/stats/1.0/default/Android.bp
index 7a09639..0321da1 100644
--- a/power/stats/1.0/default/Android.bp
+++ b/power/stats/1.0/default/Android.bp
@@ -25,7 +25,6 @@
         "libcutils",
         "libfmq",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
         "android.hardware.power.stats@1.0",
diff --git a/power/stats/1.0/default/PowerStats.cpp b/power/stats/1.0/default/PowerStats.cpp
index 78766f2..68275ce 100644
--- a/power/stats/1.0/default/PowerStats.cpp
+++ b/power/stats/1.0/default/PowerStats.cpp
@@ -87,7 +87,7 @@
     std::string railFileName;
     std::string spsFileName;
     uint32_t index = 0;
-    uint32_t samplingRate;
+    unsigned long samplingRate;
     for (const auto& path : mPm.devicePaths) {
         railFileName = path + "/enabled_rails";
         spsFileName = path + "/sampling_rate";
@@ -109,10 +109,11 @@
         while (std::getline(railNames, line)) {
             std::vector<std::string> words = android::base::Split(line, ":");
             if (words.size() == 2) {
-                mPm.railsInfo.emplace(words[0], RailData{.devicePath = path,
-                                                         .index = index,
-                                                         .subsysName = words[1],
-                                                         .samplingRate = samplingRate});
+                mPm.railsInfo.emplace(
+                        words[0], RailData{.devicePath = path,
+                                           .index = index,
+                                           .subsysName = words[1],
+                                           .samplingRate = static_cast<uint32_t>(samplingRate)});
                 index++;
             } else {
                 ALOGW("Unexpected format in file: %s", railFileName.c_str());
diff --git a/power/stats/1.0/vts/functional/Android.bp b/power/stats/1.0/vts/functional/Android.bp
index 4f0b325..f564cbe 100644
--- a/power/stats/1.0/vts/functional/Android.bp
+++ b/power/stats/1.0/vts/functional/Android.bp
@@ -31,8 +31,6 @@
         "liblog",
         "libhidlbase",
         "libfmq",
-        "libhidltransport",
-        "libhwbinder",
         "libutils",
     ],
 }
diff --git a/prebuilt_hashes/28.txt b/prebuilt_hashes/28.txt
index cc15322..8a45ca5 100644
--- a/prebuilt_hashes/28.txt
+++ b/prebuilt_hashes/28.txt
@@ -348,6 +348,8 @@
 5e278fcaa3287d397d8eebe1c22aaa28150f5caae1cf9381cd6dc32cb37899c5 android.hardware.nfc@1.1::types
 163e115e833fc1d77cdd4a8cf0c833bb8b8d74fe35c880fe693101d17774926f android.hardware.power@1.2::IPower
 7899b9305587b2d5cd74a3cc87e9090f58bf4ae74256ce3ee36e7ec011822840 android.hardware.power@1.2::types
+5a464e6db53fad223986d655028a18185b73db8e2bfa9663f9042c9623eb0aa0 android.hardware.power@1.3::IPower
+a54a28d39b892d27a3cb06829181c038edcdd9e8eef359543b01e4313ae59aa0 android.hardware.power@1.3::types
 ab132c990a62f0aca35871c092c22fb9c85d478e22124ef6a4d0a2302da76a9f android.hardware.radio@1.2::IRadio
 cda752aeabaabc20486a82ac57a3dd107785c006094a349bc5e224e8aa22a17c android.hardware.radio@1.2::IRadioIndication
 da8c6ae991c6a4b284cc6e445332e064e28ee8a09482ed5afff9d159ec6694b7 android.hardware.radio@1.2::IRadioResponse
diff --git a/radio/1.0/Android.bp b/radio/1.0/Android.bp
index f023471..6765b4d 100644
--- a/radio/1.0/Android.bp
+++ b/radio/1.0/Android.bp
@@ -19,4 +19,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/radio/1.1/Android.bp b/radio/1.1/Android.bp
index 4375d8c..28388b0 100644
--- a/radio/1.1/Android.bp
+++ b/radio/1.1/Android.bp
@@ -19,4 +19,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/radio/1.2/Android.bp b/radio/1.2/Android.bp
index b7364a8..28e6b26 100644
--- a/radio/1.2/Android.bp
+++ b/radio/1.2/Android.bp
@@ -20,4 +20,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/radio/1.2/default/Android.bp b/radio/1.2/default/Android.bp
index f8ff4c7..74fcf11 100644
--- a/radio/1.2/default/Android.bp
+++ b/radio/1.2/default/Android.bp
@@ -9,7 +9,6 @@
     ],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
         "android.hardware.radio@1.2",
@@ -29,7 +28,6 @@
     ],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
         "android.hardware.radio@1.2",
diff --git a/radio/1.2/default/android.hardware.radio@1.2-radio-service.rc b/radio/1.2/default/android.hardware.radio@1.2-radio-service.rc
index e126cd8..eab37ec 100644
--- a/radio/1.2/default/android.hardware.radio@1.2-radio-service.rc
+++ b/radio/1.2/default/android.hardware.radio@1.2-radio-service.rc
@@ -1,4 +1,13 @@
 service vendor.radio-1-2 /vendor/bin/hw/android.hardware.radio@1.2-radio-service
+    interface android.hardware.radio@1.0::IRadio slot1
+    interface android.hardware.radio@1.0::IRadio slot2
+    interface android.hardware.radio@1.0::IRadio slot3
+    interface android.hardware.radio@1.1::IRadio slot1
+    interface android.hardware.radio@1.1::IRadio slot2
+    interface android.hardware.radio@1.1::IRadio slot3
+    interface android.hardware.radio@1.2::IRadio slot1
+    interface android.hardware.radio@1.2::IRadio slot2
+    interface android.hardware.radio@1.2::IRadio slot3
     class hal
     user system
     group system
diff --git a/radio/1.2/default/android.hardware.radio@1.2-sap-service.rc b/radio/1.2/default/android.hardware.radio@1.2-sap-service.rc
index 845e6e5..9f163f6 100644
--- a/radio/1.2/default/android.hardware.radio@1.2-sap-service.rc
+++ b/radio/1.2/default/android.hardware.radio@1.2-sap-service.rc
@@ -1,4 +1,7 @@
 service vendor.sap-1-2 /vendor/bin/hw/android.hardware.radio@1.2-sap-service
+    interface android.hardware.radio@1.0::ISap slot1
+    interface android.hardware.radio@1.1::ISap slot1
+    interface android.hardware.radio@1.2::ISap slot1
     class hal
     user system
     group system
diff --git a/radio/1.2/types.hal b/radio/1.2/types.hal
index dffebd3..f10d753 100644
--- a/radio/1.2/types.hal
+++ b/radio/1.2/types.hal
@@ -161,7 +161,8 @@
     ScanType type;
 
     /**
-     * Time interval in seconds between periodic scans, only valid when type = PERIODIC
+     * Time interval in seconds between the completion of one scan and the start of a subsequent scan.
+     * This field is only valid when 'type' is 'PERIODIC'.
      * Range: ScanIntervalRange:MIN to ScanIntervalRange:MAX
      */
     int32_t interval;
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
index 5184ef9..a98f22a 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
@@ -46,7 +46,10 @@
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
             .type = ScanType::ONE_SHOT,
             .interval = 60,
-            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850}};
+            .specifiers = {::GERAN_SPECIFIER_P900, ::GERAN_SPECIFIER_850},
+            .maxSearchTime = 60,
+            .incrementalResults = false,
+            .incrementalResultsPeriodicity = 1};
 
     Return<void> res = radio_v1_2->startNetworkScan_1_2(serial, request);
     ASSERT_OK(res);
diff --git a/radio/1.3/Android.bp b/radio/1.3/Android.bp
index de2a3e5..b6af874 100644
--- a/radio/1.3/Android.bp
+++ b/radio/1.3/Android.bp
@@ -20,4 +20,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/radio/1.4/Android.bp b/radio/1.4/Android.bp
index 9f5f2f9..ff2e0d6 100644
--- a/radio/1.4/Android.bp
+++ b/radio/1.4/Android.bp
@@ -22,4 +22,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
index f81af9b..a4953d7 100644
--- a/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.4/vts/functional/radio_hidl_hal_api.cpp
@@ -183,7 +183,12 @@
                                       .channels = {1, 2}};
 
     ::android::hardware::radio::V1_2::NetworkScanRequest request = {
-            .type = ScanType::ONE_SHOT, .interval = 60, .specifiers = {specifier}};
+            .type = ScanType::ONE_SHOT,
+            .interval = 60,
+            .specifiers = {specifier},
+            .maxSearchTime = 60,
+            .incrementalResults = false,
+            .incrementalResultsPeriodicity = 1};
 
     Return<void> res = radio_v1_4->startNetworkScan_1_4(serial, request);
     ASSERT_OK(res);
@@ -398,7 +403,7 @@
             .interval = 60,
             .specifiers = {specifier},
             .maxSearchTime = 600,
-            .incrementalResults = false,
+            .incrementalResults = true,
             .incrementalResultsPeriodicity = 0};
 
     Return<void> res = radio_v1_4->startNetworkScan_1_4(serial, request);
@@ -434,7 +439,7 @@
             .interval = 60,
             .specifiers = {specifier},
             .maxSearchTime = 600,
-            .incrementalResults = false,
+            .incrementalResults = true,
             .incrementalResultsPeriodicity = 11};
 
     Return<void> res = radio_v1_4->startNetworkScan_1_4(serial, request);
diff --git a/radio/config/1.0/Android.bp b/radio/config/1.0/Android.bp
index 7fb0ea1..387f953 100644
--- a/radio/config/1.0/Android.bp
+++ b/radio/config/1.0/Android.bp
@@ -18,4 +18,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/radio/config/1.0/default/Android.bp b/radio/config/1.0/default/Android.bp
index f52335e..a0f4214 100644
--- a/radio/config/1.0/default/Android.bp
+++ b/radio/config/1.0/default/Android.bp
@@ -11,7 +11,6 @@
     ],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
         "android.hardware.radio.config@1.0",
diff --git a/radio/config/1.0/default/android.hardware.radio.config@1.0-service.rc b/radio/config/1.0/default/android.hardware.radio.config@1.0-service.rc
index fad16b1..94d5edb 100644
--- a/radio/config/1.0/default/android.hardware.radio.config@1.0-service.rc
+++ b/radio/config/1.0/default/android.hardware.radio.config@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.radio-config-hal-1-0 /vendor/bin/hw/android.hardware.radio.config@1.0-service
+    interface android.hardware.radio.config@1.0::IRadioConfig default
     class hal
     user system
     group system
diff --git a/radio/config/1.1/Android.bp b/radio/config/1.1/Android.bp
index 5c9ad7c..1e9071a 100644
--- a/radio/config/1.1/Android.bp
+++ b/radio/config/1.1/Android.bp
@@ -19,4 +19,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/radio/config/1.2/Android.bp b/radio/config/1.2/Android.bp
index e69be40..812f166 100644
--- a/radio/config/1.2/Android.bp
+++ b/radio/config/1.2/Android.bp
@@ -19,4 +19,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/radio/deprecated/1.0/Android.bp b/radio/deprecated/1.0/Android.bp
index c9f86f0..cb13b86 100644
--- a/radio/deprecated/1.0/Android.bp
+++ b/radio/deprecated/1.0/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/renderscript/1.0/Android.bp b/renderscript/1.0/Android.bp
index 1d7efad..feae9f7 100644
--- a/renderscript/1.0/Android.bp
+++ b/renderscript/1.0/Android.bp
@@ -18,4 +18,3 @@
     gen_java: false,
     gen_java_constants: true,
 }
-
diff --git a/renderscript/1.0/default/Android.bp b/renderscript/1.0/default/Android.bp
index d5d6d8d..4fa85c6 100644
--- a/renderscript/1.0/default/Android.bp
+++ b/renderscript/1.0/default/Android.bp
@@ -14,7 +14,6 @@
         "libdl",
         "libbase",
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "android.hardware.renderscript@1.0",
     ],
diff --git a/secure_element/1.0/Android.bp b/secure_element/1.0/Android.bp
index c6fa6a9..32b752b 100644
--- a/secure_element/1.0/Android.bp
+++ b/secure_element/1.0/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/secure_element/1.1/Android.bp b/secure_element/1.1/Android.bp
index e16bc3d..3ea2de9 100644
--- a/secure_element/1.1/Android.bp
+++ b/secure_element/1.1/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/sensors/1.0/Android.bp b/sensors/1.0/Android.bp
index 3a41f9c..509f72f 100644
--- a/sensors/1.0/Android.bp
+++ b/sensors/1.0/Android.bp
@@ -16,4 +16,3 @@
     gen_java: false,
     gen_java_constants: true,
 }
-
diff --git a/sensors/1.0/default/Android.bp b/sensors/1.0/default/Android.bp
index 2485b05..d5c1b23 100644
--- a/sensors/1.0/default/Android.bp
+++ b/sensors/1.0/default/Android.bp
@@ -11,7 +11,6 @@
         "libbase",
         "libutils",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.sensors@1.0",
     ],
     static_libs: [
@@ -34,7 +33,6 @@
         "libbase",
         "libutils",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.sensors@1.0",
     ],
     local_include_dirs: ["include/sensors"],
@@ -57,7 +55,6 @@
         "libbase",
         "libutils",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.sensors@1.0",
     ],
 }
diff --git a/sensors/1.0/default/android.hardware.sensors@1.0-service.rc b/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
index b54842d..4faa562 100644
--- a/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
+++ b/sensors/1.0/default/android.hardware.sensors@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.sensors-hal-1-0 /vendor/bin/hw/android.hardware.sensors@1.0-service
+    interface android.hardware.sensors@1.0::ISensors default
     class hal
     user system
     group system wakelock
diff --git a/sensors/2.0/Android.bp b/sensors/2.0/Android.bp
index eead1d3..c8517c8 100644
--- a/sensors/2.0/Android.bp
+++ b/sensors/2.0/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/sensors/2.0/default/Android.bp b/sensors/2.0/default/Android.bp
index 05a34bb..62c9487 100644
--- a/sensors/2.0/default/Android.bp
+++ b/sensors/2.0/default/Android.bp
@@ -30,7 +30,6 @@
         "libcutils",
         "libfmq",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libpower",
         "libutils",
diff --git a/soundtrigger/2.0/Android.bp b/soundtrigger/2.0/Android.bp
index b805be8..5613abd 100644
--- a/soundtrigger/2.0/Android.bp
+++ b/soundtrigger/2.0/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/soundtrigger/2.0/ISoundTriggerHwCallback.hal b/soundtrigger/2.0/ISoundTriggerHwCallback.hal
index 90132d9..84b11c8 100644
--- a/soundtrigger/2.0/ISoundTriggerHwCallback.hal
+++ b/soundtrigger/2.0/ISoundTriggerHwCallback.hal
@@ -46,7 +46,6 @@
         int32_t           captureSession;
         /**
          * Delay in ms between end of model detection and start of audio
-        /**
          * available for capture. A negative value is possible
          * (e.g. if key phrase is also available for capture */
         int32_t           captureDelayMs;
diff --git a/soundtrigger/2.0/default/Android.bp b/soundtrigger/2.0/default/Android.bp
index cc20f91..1f9ae45 100644
--- a/soundtrigger/2.0/default/Android.bp
+++ b/soundtrigger/2.0/default/Android.bp
@@ -28,7 +28,6 @@
 
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
         "libhardware",
diff --git a/soundtrigger/2.1/Android.bp b/soundtrigger/2.1/Android.bp
index ed1ec3d..68e425b 100644
--- a/soundtrigger/2.1/Android.bp
+++ b/soundtrigger/2.1/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/soundtrigger/2.1/default/Android.mk b/soundtrigger/2.1/default/Android.mk
index 5851d63..b8d0407 100644
--- a/soundtrigger/2.1/default/Android.mk
+++ b/soundtrigger/2.1/default/Android.mk
@@ -29,7 +29,6 @@
         libhardware \
         libhidlbase \
         libhidlmemory \
-        libhidltransport \
         liblog \
         libutils \
         android.hardware.soundtrigger@2.1 \
diff --git a/soundtrigger/2.2/Android.bp b/soundtrigger/2.2/Android.bp
index 0a7c2d8..43898c7 100644
--- a/soundtrigger/2.2/Android.bp
+++ b/soundtrigger/2.2/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/soundtrigger/2.2/default/Android.bp b/soundtrigger/2.2/default/Android.bp
index 78bb69f..db37c5b 100644
--- a/soundtrigger/2.2/default/Android.bp
+++ b/soundtrigger/2.2/default/Android.bp
@@ -22,7 +22,6 @@
     ],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libhidlmemory",
         "libutils",
diff --git a/tests/bar/1.0/Android.bp b/tests/bar/1.0/Android.bp
index a1b6b88..0aeccd6 100644
--- a/tests/bar/1.0/Android.bp
+++ b/tests/bar/1.0/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/tests/bar/1.0/default/Android.bp b/tests/bar/1.0/default/Android.bp
index 8aa6135..8e3d072 100644
--- a/tests/bar/1.0/default/Android.bp
+++ b/tests/bar/1.0/default/Android.bp
@@ -13,8 +13,6 @@
         "libbase",
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libutils",
     ],
diff --git a/tests/baz/1.0/Android.bp b/tests/baz/1.0/Android.bp
index 618f4f8..ed18876 100644
--- a/tests/baz/1.0/Android.bp
+++ b/tests/baz/1.0/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/tests/baz/1.0/IBaz.hal b/tests/baz/1.0/IBaz.hal
index 91ed1f2..7855446 100644
--- a/tests/baz/1.0/IBaz.hal
+++ b/tests/baz/1.0/IBaz.hal
@@ -29,6 +29,11 @@
         VALL = V0 | V1 | V2 | V3,
     };
 
+    struct BitFieldTester {
+      bitfield<BitField> scalar;
+      vec<bitfield<BitField>> vector;
+     };
+
     enum SomeOtherEnum : uint8_t {
         bar = 66
     };
@@ -108,6 +113,7 @@
 
     haveSomeStrings(string[3] array) generates (string[2] result);
     haveAStringVec(vec<string> vector) generates (vec<string> result);
+    repeatBitfieldVec(vec<bitfield<BitField>> vector) generates (vec<bitfield<BitField>> result);
 
     returnABunchOfStrings() generates (string a, string b, string c);
 
diff --git a/tests/baz/1.0/default/Android.bp b/tests/baz/1.0/default/Android.bp
index 492e0b4..4096d47 100644
--- a/tests/baz/1.0/default/Android.bp
+++ b/tests/baz/1.0/default/Android.bp
@@ -9,8 +9,6 @@
         "libbase",
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libutils",
     ],
diff --git a/tests/baz/1.0/default/Baz.cpp b/tests/baz/1.0/default/Baz.cpp
index e118122..2ce096c 100644
--- a/tests/baz/1.0/default/Baz.cpp
+++ b/tests/baz/1.0/default/Baz.cpp
@@ -364,6 +364,12 @@
     return Void();
 }
 
+Return<void> Baz::repeatBitfieldVec(const hidl_vec<uint8_t>& vector,
+                                    repeatBitfieldVec_cb _hidl_cb) {
+    _hidl_cb(vector);
+    return Void();
+}
+
 Return<void> Baz::returnABunchOfStrings(returnABunchOfStrings_cb _hidl_cb) {
     hidl_string eins; eins = "Eins";
     hidl_string zwei; zwei = "Zwei";
diff --git a/tests/baz/1.0/default/Baz.h b/tests/baz/1.0/default/Baz.h
index c264f47..1e24d52 100644
--- a/tests/baz/1.0/default/Baz.h
+++ b/tests/baz/1.0/default/Baz.h
@@ -86,6 +86,8 @@
                                  haveSomeStrings_cb _hidl_cb) override;
     Return<void> haveAStringVec(const hidl_vec<hidl_string>& vector,
                                 haveAStringVec_cb _hidl_cb) override;
+    Return<void> repeatBitfieldVec(const hidl_vec<uint8_t>& vector,
+                                   repeatBitfieldVec_cb _hidl_cb) override;
     Return<void> returnABunchOfStrings(returnABunchOfStrings_cb _hidl_cb) override;
     Return<uint8_t> returnABitField() override;
     Return<uint32_t> size(uint32_t size) override;
diff --git a/tests/expression/1.0/Android.bp b/tests/expression/1.0/Android.bp
index 61ca6ac..4bc3848 100644
--- a/tests/expression/1.0/Android.bp
+++ b/tests/expression/1.0/Android.bp
@@ -12,4 +12,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/tests/expression/1.0/IExpression.hal b/tests/expression/1.0/IExpression.hal
index 36aed60..039897a 100644
--- a/tests/expression/1.0/IExpression.hal
+++ b/tests/expression/1.0/IExpression.hal
@@ -215,7 +215,6 @@
     MY_INT32_MIN_PLUS_1, // 0x80000001
   };
 
-  @callflow(key=Constants:CONST_FOO + 1)
   foo1(int32_t[Constants:CONST_FOO + 1] array);
   foo2(int32_t[5 + 8] array);
   foo3(int32_t[Constants:MAX_ARRAY_SIZE] array);
diff --git a/tests/expression/1.0/IExpressionExt.hal b/tests/expression/1.0/IExpressionExt.hal
index 8b56ec6..e721978 100644
--- a/tests/expression/1.0/IExpressionExt.hal
+++ b/tests/expression/1.0/IExpressionExt.hal
@@ -36,7 +36,6 @@
         SixteenColors my16Colors;
     };
 
-    @callflow(key=@1.0::IExpression.Constants:MAX_ARRAY_SIZE)
     foo3(int32_t[IExpression.Constants:MAX_ARRAY_SIZE] array);
     foo2(SixteenColors array);
     foo1(int32_t[Constants:CONST_FOO + 5] array);
diff --git a/tests/extension/light/2.0/Android.bp b/tests/extension/light/2.0/Android.bp
index 916af71..e19a913 100644
--- a/tests/extension/light/2.0/Android.bp
+++ b/tests/extension/light/2.0/Android.bp
@@ -13,4 +13,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/tests/extension/light/2.0/default/Android.bp b/tests/extension/light/2.0/default/Android.bp
index dcac97c..d8d8dd5 100644
--- a/tests/extension/light/2.0/default/Android.bp
+++ b/tests/extension/light/2.0/default/Android.bp
@@ -27,7 +27,6 @@
 
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "android.hardware.light@2.0",
         "android.hardware.tests.extension.light@2.0",
diff --git a/tests/foo/1.0/Android.bp b/tests/foo/1.0/Android.bp
index 1c3b3c5..2f97fca 100644
--- a/tests/foo/1.0/Android.bp
+++ b/tests/foo/1.0/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/tests/foo/1.0/default/Android.bp b/tests/foo/1.0/default/Android.bp
index d9dfc69..48d6894 100644
--- a/tests/foo/1.0/default/Android.bp
+++ b/tests/foo/1.0/default/Android.bp
@@ -13,8 +13,6 @@
         "libcutils",
         "libfootest",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libutils",
     ],
diff --git a/tests/foo/1.0/default/lib/Android.bp b/tests/foo/1.0/default/lib/Android.bp
index 2cc96c5..ba2081e 100644
--- a/tests/foo/1.0/default/lib/Android.bp
+++ b/tests/foo/1.0/default/lib/Android.bp
@@ -8,8 +8,6 @@
     shared_libs: [
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
     ],
     static_libs: ["android.hardware.tests.foo@1.0"],
diff --git a/tests/hash/1.0/Android.bp b/tests/hash/1.0/Android.bp
index 20334cd..1095576 100644
--- a/tests/hash/1.0/Android.bp
+++ b/tests/hash/1.0/Android.bp
@@ -11,4 +11,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/tests/hash/1.0/default/Android.bp b/tests/hash/1.0/default/Android.bp
index 6e6d6a8..410b759 100644
--- a/tests/hash/1.0/default/Android.bp
+++ b/tests/hash/1.0/default/Android.bp
@@ -8,8 +8,6 @@
     shared_libs: [
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libutils",
     ],
diff --git a/tests/inheritance/1.0/Android.bp b/tests/inheritance/1.0/Android.bp
index 1d36d07..0042b57 100644
--- a/tests/inheritance/1.0/Android.bp
+++ b/tests/inheritance/1.0/Android.bp
@@ -14,4 +14,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/tests/inheritance/1.0/default/Android.bp b/tests/inheritance/1.0/default/Android.bp
index 891355b..4a0c876 100644
--- a/tests/inheritance/1.0/default/Android.bp
+++ b/tests/inheritance/1.0/default/Android.bp
@@ -14,8 +14,6 @@
         "libbase",
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libutils",
     ],
diff --git a/tests/libhwbinder/1.0/Android.bp b/tests/libhwbinder/1.0/Android.bp
index d561002..13af77c 100644
--- a/tests/libhwbinder/1.0/Android.bp
+++ b/tests/libhwbinder/1.0/Android.bp
@@ -12,4 +12,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/tests/libhwbinder/1.0/default/Android.bp b/tests/libhwbinder/1.0/default/Android.bp
index aad1e31..81022b8 100644
--- a/tests/libhwbinder/1.0/default/Android.bp
+++ b/tests/libhwbinder/1.0/default/Android.bp
@@ -9,8 +9,6 @@
     shared_libs: [
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libutils",
     ],
diff --git a/tests/libhwbinder/aidl/Android.bp b/tests/libhwbinder/aidl/Android.bp
index 6d49704..c9e09f7 100644
--- a/tests/libhwbinder/aidl/Android.bp
+++ b/tests/libhwbinder/aidl/Android.bp
@@ -1,4 +1,4 @@
-cc_library_shared {
+cc_library {
     name: "android.hardware.tests.libbinder",
     defaults: ["hidl_defaults"],
 
diff --git a/tests/memory/1.0/Android.bp b/tests/memory/1.0/Android.bp
index cbee247..29f6be7 100644
--- a/tests/memory/1.0/Android.bp
+++ b/tests/memory/1.0/Android.bp
@@ -13,4 +13,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/tests/memory/1.0/default/Android.bp b/tests/memory/1.0/default/Android.bp
index 3f13634..0293953 100644
--- a/tests/memory/1.0/default/Android.bp
+++ b/tests/memory/1.0/default/Android.bp
@@ -22,9 +22,7 @@
     shared_libs: [
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
         "libhidlmemory",
-        "libhwbinder",
         "liblog",
         "libutils",
         "android.hidl.memory@1.0",
diff --git a/tests/msgq/1.0/Android.bp b/tests/msgq/1.0/Android.bp
index 2d8d565..eea1ce6 100644
--- a/tests/msgq/1.0/Android.bp
+++ b/tests/msgq/1.0/Android.bp
@@ -12,4 +12,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/tests/msgq/1.0/default/Android.bp b/tests/msgq/1.0/default/Android.bp
index 6c8be6c..e6408aa 100644
--- a/tests/msgq/1.0/default/Android.bp
+++ b/tests/msgq/1.0/default/Android.bp
@@ -26,8 +26,6 @@
         "libcutils",
         "libfmq",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libutils",
     ],
@@ -49,7 +47,6 @@
         "libbase",
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
         "android.hardware.tests.msgq@1.0"
@@ -68,8 +65,6 @@
         "libcutils",
         "libfmq",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libutils",
     ],
diff --git a/tests/multithread/1.0/Android.bp b/tests/multithread/1.0/Android.bp
index 0d21b1b..ed3a687 100644
--- a/tests/multithread/1.0/Android.bp
+++ b/tests/multithread/1.0/Android.bp
@@ -11,4 +11,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/tests/multithread/1.0/default/Android.bp b/tests/multithread/1.0/default/Android.bp
index a94ee3e..ff89938 100644
--- a/tests/multithread/1.0/default/Android.bp
+++ b/tests/multithread/1.0/default/Android.bp
@@ -9,8 +9,6 @@
         "libbase",
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libutils",
     ],
diff --git a/tests/pointer/1.0/.hidl_for_test b/tests/pointer/1.0/.hidl_for_test
deleted file mode 100644
index e69de29..0000000
--- a/tests/pointer/1.0/.hidl_for_test
+++ /dev/null
diff --git a/tests/pointer/1.0/Android.bp b/tests/pointer/1.0/Android.bp
deleted file mode 100644
index 3dc8e8a..0000000
--- a/tests/pointer/1.0/Android.bp
+++ /dev/null
@@ -1,15 +0,0 @@
-// This file is autogenerated by hidl-gen -Landroidbp.
-
-hidl_interface {
-    name: "android.hardware.tests.pointer@1.0",
-    root: "android.hardware",
-    srcs: [
-        "IGraph.hal",
-        "IPointer.hal",
-    ],
-    interfaces: [
-        "android.hidl.base@1.0",
-    ],
-    gen_java: false,
-}
-
diff --git a/tests/pointer/1.0/IGraph.hal b/tests/pointer/1.0/IGraph.hal
deleted file mode 100644
index 0853745..0000000
--- a/tests/pointer/1.0/IGraph.hal
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.tests.pointer@1.0;
-
-interface IGraph {
-
-  struct Node {
-    int32_t data;
-  };
-  struct Edge {
-    ref<Node> left;
-    ref<Node> right;
-  };
-  struct Graph {
-    vec<Node> nodes;
-    vec<Edge> edges;
-  };
-
-  struct Theta {
-    int32_t data;
-  };
-  struct Alpha {
-    ref<Theta> s_ptr;
-  };
-  struct Beta {
-    ref<Theta> s_ptr;
-  };
-  struct Gamma {
-    ref<Alpha> a_ptr;
-    ref<Beta> b_ptr;
-  };
-
-  passANode(Node n);
-  passAGraph(Graph g);
-  passTwoGraphs(ref<Graph> g1, ref<Graph> g2);
-  giveAGraph() generates (Graph g);
-  passAGamma(Gamma c);
-  passASimpleRef(ref<Alpha> a);
-  passASimpleRefS(ref<Theta> s);
-  giveASimpleRef() generates (ref<Alpha> a);
-
-  getErrors() generates (int32_t errors);
-};
diff --git a/tests/pointer/1.0/IPointer.hal b/tests/pointer/1.0/IPointer.hal
deleted file mode 100644
index 4560a4a..0000000
--- a/tests/pointer/1.0/IPointer.hal
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.hardware.tests.pointer@1.0;
-
-interface IPointer {
-  struct S { int32_t data; };
-  struct A { S s; };
-  // type declarations
-  struct Sam { int32_t data; };
-  struct Ada { ref<Sam> s_ptr; };
-  struct Bob { ref<Ada> a_ptr; ref<Sam> s_ptr; };
-  struct Cin { Ada a; ref<Bob> b_ptr; };
-  struct Dom { Cin c; };
-
-  typedef ref<int32_t> Int32Ptr;
-  typedef ref<Sam>     SamPtr;
-
-  struct Ptr {
-    ref<Ada>[5] ptr_array;
-    ref<Ada[5]> array_ptr;
-    Int32Ptr int_ptr;
-    ref<int32_t[5]> int_array_ptr;
-    ref<int32_t>[5] int_ptr_array;
-    ref<string> str_ref;
-    vec<ref<Ada>> a_ptr_vec;
-    ref<vec<Ada>> a_vec_ptr;
-  };
-
-  // test cases
-  foo1(Sam s, SamPtr s_ptr);
-  foo2(Sam s, Ada a);
-  foo3(Sam s, Ada a, Bob b);
-  foo4(ref<Sam> s_ptr);
-  foo5(Ada a, Bob b);
-  foo6(ref<Ada> a_ptr);
-  foo7(ref<Ada> a_ptr, ref<Bob> b_ptr);
-  foo8(Dom d);
-  foo9(ref<string> str_ref);
-  foo10(vec<ref<Sam>> s_ptr_vec);
-  foo11(ref<vec<Sam>> s_vec_ptr);
-  foo12(ref<Sam[5]> s_array_ref);
-  foo13(ref<Sam>[5] s_ref_array);
-  foo14(ref<ref<ref<Sam>>> s_3ptr);
-  foo15(ref<ref<ref<int32_t>>> i_3ptr);
-  foo16(Ptr p);
-  foo17(ref<Ptr> p);
-  foo18(ref<string> str_ref, ref<string> str_ref2, string str);
-  foo19(ref<vec<Ada>> a_vec_ref, vec<Ada> a_vec, ref<vec<Ada>> a_vec_ref2);
-  foo20(vec<ref<Sam>> s_ptr_vec);
-  foo21(ref<Ada[1][2][3]> a_array_ptr);
-  foo22(ref<Ada>[1][2][3] a_ptr_array);
-
-  bar1() generates (Sam s, ref<Sam> s_ptr);
-  bar2() generates (Sam s, Ada a);
-  bar3() generates (Sam s, Ada a, Bob b);
-  bar4() generates (ref<Sam> s_ptr);
-  bar5() generates (Ada a, Bob b);
-  bar6() generates (ref<Ada> a_ptr);
-  bar7() generates (ref<Ada> a_ptr, ref<Bob> b_ptr);
-  bar8() generates (Dom d);
-  bar9() generates (ref<string> str_ref);
-  bar10() generates (vec<ref<Sam>> s_ptr_vec);
-  bar11() generates (ref<vec<Sam>> s_vec_ptr);
-  bar12() generates (ref<Sam[5]> s_array_ref);
-  bar13() generates (ref<Sam>[5] s_ref_array);
-  bar14() generates (ref<ref<ref<Sam>>> s_3ptr);
-  bar15() generates (ref<ref<ref<int32_t>>> i_3ptr);
-  bar16() generates (Ptr p);
-  bar17() generates (ref<Ptr> p);
-  bar18() generates (ref<string> str_ref, ref<string> str_ref2, string str);
-  bar19() generates (ref<vec<Ada>> a_vec_ref, vec<Ada> a_vec, ref<vec<Ada>> a_vec_ref2);
-  bar20() generates (vec<ref<Sam>> s_ptr_vec);
-  bar21() generates (ref<Ada[1][2][3]> a_array_ptr);
-  bar22() generates (ref<Ada>[1][2][3] a_ptr_array);
-
-  getErrors() generates(int32_t errors);
-};
diff --git a/tests/pointer/1.0/default/Android.bp b/tests/pointer/1.0/default/Android.bp
deleted file mode 100644
index 4825ac7..0000000
--- a/tests/pointer/1.0/default/Android.bp
+++ /dev/null
@@ -1,27 +0,0 @@
-
-
-cc_library {
-    name: "android.hardware.tests.pointer@1.0-impl",
-    defaults: ["hidl_defaults"],
-    relative_install_path: "hw",
-    srcs: [
-        "Graph.cpp",
-        "Pointer.cpp",
-    ],
-
-    shared_libs: [
-        "libbase",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
-        "libpointertest",
-        "liblog",
-        "libutils",
-    ],
-
-    // These are static libs only for testing purposes and portability. Shared
-    // libs should be used on device.
-    static_libs: ["android.hardware.tests.pointer@1.0"],
-
-}
diff --git a/tests/pointer/1.0/default/Graph.cpp b/tests/pointer/1.0/default/Graph.cpp
deleted file mode 100644
index 5c8098b..0000000
--- a/tests/pointer/1.0/default/Graph.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-#define LOG_TAG "hidl_test"
-
-#include "Graph.h"
-
-#include <log/log.h>
-
-#include <hidl-test/PointerHelper.h>
-
-#define PUSH_ERROR_IF(__cond__) if(__cond__) { errors.push_back(std::to_string(__LINE__) + ": " + #__cond__); }
-
-namespace android {
-namespace hardware {
-namespace tests {
-namespace pointer {
-namespace V1_0 {
-namespace implementation {
-
-// Methods from ::android::hardware::tests::pointer::V1_0::IGraph follow.
-Return<void> Graph::passAGraph(const IGraph::Graph& g) {
-    ALOGI("SERVER(Graph) passAGraph start.");
-    PUSH_ERROR_IF(!isSimpleGraph(g));
-    // logSimpleGraph("SERVER(Graph) passAGraph:", g);
-    return Void();
-}
-
-Return<void> Graph::giveAGraph(giveAGraph_cb _cb) {
-    IGraph::Graph g;
-    simpleGraph(g);
-    _cb(g);
-    return Void();
-}
-
-Return<void> Graph::passANode(const IGraph::Node& n) {
-    PUSH_ERROR_IF(n.data != 10);
-    return Void();
-}
-
-Return<void> Graph::passTwoGraphs(IGraph::Graph const* g1, IGraph::Graph const* g2) {
-    PUSH_ERROR_IF(g1 != g2);
-    PUSH_ERROR_IF(!isSimpleGraph(*g1));
-    logSimpleGraph("SERVER(Graph): passTwoGraphs", *g2);
-    return Void();
-}
-
-Return<void> Graph::passAGamma(const IGraph::Gamma& c) {
-    if(c.a_ptr == nullptr && c.b_ptr == nullptr)
-      return Void();
-    ALOGI("SERVER(Graph) passAGamma received c.a = %p, c.b = %p, c.a->s = %p, c.b->s = %p",
-        c.a_ptr, c.b_ptr, c.a_ptr->s_ptr, c.b_ptr->s_ptr);
-    ALOGI("SERVER(Graph) passAGamma received data %d, %d",
-        (int)c.a_ptr->s_ptr->data, (int)c.b_ptr->s_ptr->data);
-    PUSH_ERROR_IF(c.a_ptr->s_ptr != c.b_ptr->s_ptr);
-    return Void();
-}
-Return<void> Graph::passASimpleRef(const IGraph::Alpha * a_ptr) {
-    ALOGI("SERVER(Graph) passASimpleRef received %d", a_ptr->s_ptr->data);
-    PUSH_ERROR_IF(a_ptr->s_ptr->data != 500);
-    return Void();
-}
-Return<void> Graph::passASimpleRefS(const IGraph::Theta * s_ptr) {
-    ALOGI("SERVER(Graph) passASimpleRefS received %d @ %p", s_ptr->data, s_ptr);
-    PUSH_ERROR_IF(s_ptr->data == 10);
-    return Void();
-}
-Return<void> Graph::giveASimpleRef(giveASimpleRef_cb _cb) {
-    IGraph::Theta s; s.data = 500;
-    IGraph::Alpha a; a.s_ptr = &s;
-    _cb(&a);
-    return Void();
-}
-
-Return<int32_t> Graph::getErrors() {
-    if(!errors.empty()) {
-        for(const auto& e : errors)
-            ALOGW("SERVER(Graph) error: %s", e.c_str());
-    }
-    return errors.size();
-}
-
-IGraph* HIDL_FETCH_IGraph(const char* /* name */) {
-    return new Graph();
-}
-
-} // namespace implementation
-}  // namespace V1_0
-}  // namespace pointer
-}  // namespace tests
-}  // namespace hardware
-}  // namespace android
diff --git a/tests/pointer/1.0/default/Graph.h b/tests/pointer/1.0/default/Graph.h
deleted file mode 100644
index 03bd163..0000000
--- a/tests/pointer/1.0/default/Graph.h
+++ /dev/null
@@ -1,47 +0,0 @@
-#ifndef ANDROID_HARDWARE_TESTS_POINTER_V1_0_GRAPH_H
-#define ANDROID_HARDWARE_TESTS_POINTER_V1_0_GRAPH_H
-
-#include <android/hardware/tests/pointer/1.0/IGraph.h>
-#include <hidl/Status.h>
-
-#include <hidl/MQDescriptor.h>
-namespace android {
-namespace hardware {
-namespace tests {
-namespace pointer {
-namespace V1_0 {
-namespace implementation {
-
-using ::android::hardware::tests::pointer::V1_0::IGraph;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::hidl_string;
-using ::android::sp;
-
-struct Graph : public IGraph {
-    // Methods from ::android::hardware::tests::pointer::V1_0::IGraph follow.
-    Return<void> passANode(const IGraph::Node& n)  override;
-    Return<void> passAGraph(const IGraph::Graph& g)  override;
-    Return<void> passTwoGraphs(::android::hardware::tests::pointer::V1_0::IGraph::Graph const* g1, ::android::hardware::tests::pointer::V1_0::IGraph::Graph const* g2)  override;
-    Return<void> giveAGraph(giveAGraph_cb _hidl_cb)  override;
-    Return<void> passAGamma(const IGraph::Gamma& c)  override;
-    Return<void> passASimpleRef(::android::hardware::tests::pointer::V1_0::IGraph::Alpha const* a)  override;
-    Return<void> passASimpleRefS(::android::hardware::tests::pointer::V1_0::IGraph::Theta const* s)  override;
-    Return<void> giveASimpleRef(giveASimpleRef_cb _hidl_cb)  override;
-    Return<int32_t> getErrors()  override;
-private:
-    std::vector<std::string> errors;
-
-};
-
-extern "C" IGraph* HIDL_FETCH_IGraph(const char* name);
-
-}  // namespace implementation
-}  // namespace V1_0
-}  // namespace pointer
-}  // namespace tests
-}  // namespace hardware
-}  // namespace android
-
-#endif  // ANDROID_HARDWARE_TESTS_POINTER_V1_0_GRAPH_H
diff --git a/tests/pointer/1.0/default/Pointer.cpp b/tests/pointer/1.0/default/Pointer.cpp
deleted file mode 100644
index 52712d4..0000000
--- a/tests/pointer/1.0/default/Pointer.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-#define LOG_TAG "hidl_test"
-
-#include "Pointer.h"
-
-#include <log/log.h>
-
-namespace android {
-namespace hardware {
-namespace tests {
-namespace pointer {
-namespace V1_0 {
-namespace implementation {
-
-Return<int32_t> Pointer::getErrors() {
-    if(!errors.empty()) {
-        for(const auto& e : errors)
-            ALOGW("SERVER(Pointer) error: %s", e.c_str());
-    }
-    return errors.size();
-}
-
-IPointer* HIDL_FETCH_IPointer(const char* /* name */) {
-    return new Pointer();
-}
-
-} // namespace implementation
-}  // namespace V1_0
-}  // namespace pointer
-}  // namespace tests
-}  // namespace hardware
-}  // namespace android
diff --git a/tests/pointer/1.0/default/Pointer.h b/tests/pointer/1.0/default/Pointer.h
deleted file mode 100644
index d6e3e48..0000000
--- a/tests/pointer/1.0/default/Pointer.h
+++ /dev/null
@@ -1,338 +0,0 @@
-#ifndef ANDROID_HARDWARE_TESTS_POINTER_V1_0_POINTER_H
-#define ANDROID_HARDWARE_TESTS_POINTER_V1_0_POINTER_H
-
-#include <android/hardware/tests/pointer/1.0/IPointer.h>
-#include <hidl/Status.h>
-
-#include <hidl/MQDescriptor.h>
-
-// TODO move to Pointer.cpp so that I won't have weird macros in headers
-#define PUSH_ERROR_IF(__cond__) if(__cond__) { errors.push_back(std::to_string(__LINE__) + ": " + #__cond__); }
-
-namespace android {
-namespace hardware {
-namespace tests {
-namespace pointer {
-namespace V1_0 {
-namespace implementation {
-
-using ::android::hardware::tests::pointer::V1_0::IPointer;
-using ::android::hardware::Return;
-using ::android::hardware::Void;
-using ::android::hardware::hidl_vec;
-using ::android::hardware::hidl_string;
-using ::android::sp;
-
-struct Pointer : public IPointer {
-private:
-    std::vector<std::string> errors;
-public:
-    Return<int32_t> getErrors() override;
-    Return<void> foo1(const IPointer::Sam& s, IPointer::Sam const* s_ptr) override {
-        PUSH_ERROR_IF(!(&s == s_ptr));
-        return Void();
-    }
-    Return<void> foo2(const IPointer::Sam& s, const IPointer::Ada& a) override {
-        PUSH_ERROR_IF(!(&s == a.s_ptr));
-        return Void();
-    }
-    Return<void> foo3(const IPointer::Sam& s, const IPointer::Ada& a, const IPointer::Bob& b) override {
-        PUSH_ERROR_IF(!(&a == b.a_ptr && a.s_ptr == b.s_ptr && a.s_ptr == &s));
-        return Void();
-    }
-    Return<void> foo4(IPointer::Sam const* s_ptr) override {
-        PUSH_ERROR_IF(!(s_ptr->data == 500));
-        return Void();
-    }
-    Return<void> foo5(const IPointer::Ada& a, const IPointer::Bob& b) override {
-        PUSH_ERROR_IF(!(a.s_ptr == b.s_ptr && b.a_ptr == &a));
-        return Void();
-    }
-    Return<void> foo6(IPointer::Ada const* a_ptr) override {
-        PUSH_ERROR_IF(!(a_ptr->s_ptr->data == 500));
-        return Void();
-    }
-    Return<void> foo7(IPointer::Ada const* a_ptr, IPointer::Bob const* b_ptr) override {
-        PUSH_ERROR_IF(!(a_ptr->s_ptr == b_ptr->s_ptr && a_ptr == b_ptr->a_ptr && a_ptr->s_ptr->data == 500));
-        return Void();
-    }
-    Return<void> foo8(const IPointer::Dom& d) override {
-        const IPointer::Cin& c = d.c;
-        PUSH_ERROR_IF(&c.a != c.b_ptr->a_ptr);
-        PUSH_ERROR_IF(c.a.s_ptr != c.b_ptr->s_ptr);
-        PUSH_ERROR_IF(c.a.s_ptr->data != 500);
-        return Void();
-    }
-    Return<void> foo9(::android::hardware::hidl_string const* str_ref) override {
-        PUSH_ERROR_IF(!(strcmp(str_ref->c_str(), "meowmeowmeow") == 0));
-        return Void();
-    }
-    Return<void> foo10(const ::android::hardware::hidl_vec<IPointer::Sam const*>& s_ptr_vec) override {
-        PUSH_ERROR_IF(s_ptr_vec[0]->data != 500);
-        if(s_ptr_vec.size() != 5) {
-            errors.push_back("foo10: s_ptr_vec.size() != 5");
-            return Void();
-        }
-        for(size_t i = 0; i < s_ptr_vec.size(); i++)
-            PUSH_ERROR_IF(s_ptr_vec[0] != s_ptr_vec[i]);
-        return Void();
-    }
-    Return<void> foo11(::android::hardware::hidl_vec<IPointer::Sam> const* s_vec_ptr) override {
-        if(s_vec_ptr->size() != 5) {
-            errors.push_back("foo11: s_vec_ptr->size() != 5");
-            return Void();
-        }
-        for(size_t i = 0; i < 5; i++)
-            PUSH_ERROR_IF((*s_vec_ptr)[i].data != 500);
-        return Void();
-    }
-    Return<void> foo12(hidl_array<IPointer::Sam, 5> const* s_array_ref) override {
-        for(size_t i = 0; i < 5; ++i)
-            PUSH_ERROR_IF((*s_array_ref)[i].data != 500);
-        return Void();
-    }
-    Return<void> foo13(const hidl_array<IPointer::Sam const*, 5>& s_ref_array) override {
-        PUSH_ERROR_IF(s_ref_array[0]->data != 500)
-        for(size_t i = 0; i < 5; i++)
-            PUSH_ERROR_IF(s_ref_array[i] != s_ref_array[0])
-        return Void();
-    }
-    Return<void> foo14(IPointer::Sam const* const* const* s_3ptr) override {
-        PUSH_ERROR_IF(!((***s_3ptr).data == 500))
-        return Void();
-    }
-    Return<void> foo15(int32_t const* const* const* i_3ptr) override {
-        PUSH_ERROR_IF(!((***i_3ptr) == 500))
-        return Void();
-    }
-
-    Return<void> foo16(const IPointer::Ptr& p) override {
-        PUSH_ERROR_IF((*p.array_ptr)[0].s_ptr->data != 500);
-        for(size_t i = 0; i < 5; i++) PUSH_ERROR_IF((*p.array_ptr)[i].s_ptr != (*p.array_ptr)[0].s_ptr);
-        PUSH_ERROR_IF(*(p.int_ptr) != 500);
-        for(size_t i = 0; i < 5; i++) PUSH_ERROR_IF((*p.int_array_ptr)[i] != 500);
-        for(size_t i = 0; i < 5; i++) PUSH_ERROR_IF(p.int_ptr_array[i] != p.int_ptr);
-        PUSH_ERROR_IF(p.a_ptr_vec.size() != 5);
-        PUSH_ERROR_IF(p.a_ptr_vec[0]->s_ptr->data != 500);
-        for(size_t i = 0; i < 5; i++) PUSH_ERROR_IF(p.a_ptr_vec[i]->s_ptr != p.a_ptr_vec[0]->s_ptr);
-        PUSH_ERROR_IF(strcmp(p.str_ref->c_str(), "meowmeowmeow") != 0);
-        PUSH_ERROR_IF(p.a_vec_ptr->size() != 5);
-        PUSH_ERROR_IF((*p.a_vec_ptr)[0].s_ptr->data != 500);
-        for(size_t i = 0; i < 5; i++) PUSH_ERROR_IF((*p.a_vec_ptr)[i].s_ptr != (*p.a_vec_ptr)[0].s_ptr);
-        return Void();
-    };
-    Return<void> foo17(IPointer::Ptr const* p) override {
-        return foo16(*p);
-    };
-    Return<void> foo18(hidl_string const* str_ref, hidl_string const* str_ref2, const hidl_string& str) override {
-        PUSH_ERROR_IF(&str != str_ref);
-        PUSH_ERROR_IF(str_ref != str_ref2);
-        PUSH_ERROR_IF(strcmp(str.c_str(), "meowmeowmeow") != 0)
-        return Void();
-    };
-    Return<void> foo19(
-                hidl_vec<IPointer::Ada> const* a_vec_ref,
-                const hidl_vec<IPointer::Ada>& a_vec,
-                hidl_vec<IPointer::Ada> const* a_vec_ref2) {
-        PUSH_ERROR_IF(&a_vec != a_vec_ref);
-        PUSH_ERROR_IF(a_vec_ref2 != a_vec_ref);
-        PUSH_ERROR_IF(a_vec.size() != 5);
-        PUSH_ERROR_IF(a_vec[0].s_ptr->data != 500);
-        for(size_t i = 0; i < 5; i++)
-            PUSH_ERROR_IF(a_vec[i].s_ptr != a_vec[0].s_ptr);
-        return Void();
-    };
-
-    Return<void> foo20(const hidl_vec<IPointer::Sam const*>&) override {
-        return Void();
-    }
-    Return<void> foo21(hidl_array<IPointer::Ada, 1, 2, 3> const* a_array_ptr) override {
-        const hidl_array<IPointer::Ada, 1, 2, 3>& a_array = *a_array_ptr;
-        PUSH_ERROR_IF(a_array[0][0][0].s_ptr->data != 500);
-        for(size_t i = 0; i < 1; i++)
-            for(size_t j = 0; j < 2; j++)
-                for(size_t k = 0; k < 3; k++)
-                    PUSH_ERROR_IF(a_array[i][j][k].s_ptr != a_array[0][0][0].s_ptr);
-        return Void();
-    }
-    Return<void> foo22(const hidl_array<IPointer::Ada const*, 1, 2, 3>& a_ptr_array) override {
-        PUSH_ERROR_IF(a_ptr_array[0][0][0]->s_ptr->data != 500);
-        for(size_t i = 0; i < 1; i++)
-            for(size_t j = 0; j < 2; j++)
-                for(size_t k = 0; k < 3; k++)
-                    PUSH_ERROR_IF(a_ptr_array[i][j][k] != a_ptr_array[0][0][0]);
-        return Void();
-    }
-
-    IPointer::Sam *s;
-    IPointer::Ada *a;
-    IPointer::Bob *b;
-    IPointer::Cin *c;
-    IPointer::Dom *d;
-
-    IPointer::Ptr p;
-    hidl_array<IPointer::Ada, 5> a_array;
-    int32_t someInt;
-    hidl_array<int32_t, 5> someIntArray;
-    hidl_string str;
-    hidl_vec<IPointer::Ada> a_vec;
-    Pointer() {
-        d = new IPointer::Dom();
-        s = new IPointer::Sam();
-        b = new IPointer::Bob();
-        c = &d->c;
-        a = &c->a;
-        b->s_ptr = a->s_ptr = s;
-        b->a_ptr = a;
-        c->b_ptr = b;
-        s->data = 500;
-
-        someInt = 500;
-        for(size_t i = 0; i < 5; i++) someIntArray[i] = 500;
-
-        for(size_t i = 0; i < 5; i++) a_array[i] = *a;
-
-        for(size_t i = 0; i < 5; i++) p.ptr_array[i] = a;
-        p.array_ptr = &a_array;
-        p.int_ptr = &someInt;
-        p.int_array_ptr = &someIntArray;
-        for(size_t i = 0; i < 5; i++) p.int_ptr_array[i] = &someInt;
-        p.a_ptr_vec.resize(5);
-        for(size_t i = 0; i < 5; i++) p.a_ptr_vec[i] = a;
-        str = "meowmeowmeow";
-        p.str_ref = &str;
-        a_vec.resize(5);
-        for(size_t i = 0; i < 5; i++) a_vec[i].s_ptr = s;
-        p.a_vec_ptr = &a_vec;
-    }
-    ~Pointer() {
-        delete d; delete s; delete b;
-    }
-    Return<void> bar1(bar1_cb _cb) override {
-        _cb(*s, s);
-        return Void();
-    }
-    Return<void> bar2(bar2_cb _cb) override {
-        _cb(*s, *a);
-        return Void();
-    }
-    Return<void> bar3(bar3_cb _cb) override {
-        _cb(*s, *a, *b);
-        return Void();
-    }
-    Return<void> bar4(bar4_cb _cb) override {
-        _cb(s);
-        return Void();
-    }
-    Return<void> bar5(bar5_cb _cb) override {
-        _cb(*a, *b);
-        return Void();
-    }
-    Return<void> bar6(bar6_cb _cb) override {
-        _cb(a);
-        return Void();
-    }
-    Return<void> bar7(bar7_cb _cb) override {
-        _cb(a, b);
-        return Void();
-    }
-    Return<void> bar8(bar8_cb _cb) override {
-        _cb(*d);
-        return Void();
-    }
-    Return<void> bar9(bar9_cb _cb) override {
-        _cb(&str);
-        return Void();
-    }
-    Return<void> bar10(bar10_cb _cb) override {
-        hidl_vec<const IPointer::Sam *> v; v.resize(5);
-        for(size_t i = 0; i < 5; i++) v[i] = s;
-        _cb(v);
-        return Void();
-    }
-    Return<void> bar11(bar11_cb _cb) override {
-        hidl_vec<IPointer::Sam> v; v.resize(5);
-        for(size_t i = 0; i < 5; i++) v[i].data = 500;
-            _cb(&v);
-        return Void();
-    }
-    Return<void> bar12(bar12_cb _cb) override {
-        hidl_array<IPointer::Sam, 5> array;
-        for(size_t i = 0; i < 5; i++) array[i] = *s;
-        _cb(&array);
-        return Void();
-    }
-    Return<void> bar13(bar13_cb _cb) override {
-        hidl_array<const IPointer::Sam *, 5> array;
-        for(size_t i = 0; i < 5; i++) array[i] = s;
-        _cb(array);
-        return Void();
-    }
-    Return<void> bar14(bar14_cb _cb) override {
-        IPointer::Sam const* p1 = s;
-        IPointer::Sam const* const* p2 = &p1;
-        _cb(&p2);
-        return Void();
-    }
-    Return<void> bar15(bar15_cb _cb) override {
-        int32_t const* p1 = &someInt;
-        int32_t const* const* p2 = &p1;
-        _cb(&p2);
-        return Void();
-    }
-    Return<void> bar16(bar16_cb _cb) override {
-        _cb(p);
-        return Void();
-    }
-    Return<void> bar17(bar17_cb _cb) override {
-        _cb(&p);
-        return Void();
-    }
-    Return<void> bar18(bar18_cb _cb) override {
-        _cb(&str, &str, str);
-        return Void();
-    }
-    Return<void> bar19(bar19_cb _cb) override {
-        _cb(&a_vec, a_vec, &a_vec);
-        return Void();
-    }
-    Return<void> bar20(bar20_cb _cb) override {
-        // 1026 == PARCEL_REF_CAP + 2.
-        // 1026 means 1 writeBuffer and 1025 writeReferences. 1025 > PARCEL_REF_CAP.
-        hidl_vec<const IPointer::Sam *> v; v.resize(1026);
-        for(size_t i = 0; i < 1026; i++) v[i] = s;
-        _cb(v);
-        return Void();
-    }
-    Return<void> bar21(bar21_cb _cb) override {
-        hidl_array<IPointer::Ada, 1, 2, 3> a_array;
-        for(size_t i = 0; i < 1; i++)
-            for(size_t j = 0; j < 2; j++)
-                for(size_t k = 0; k < 3; k++)
-                    a_array[i][j][k] = *a;
-        _cb(&a_array);
-        return Void();
-    }
-    Return<void> bar22(bar22_cb _cb) override {
-        hidl_array<const IPointer::Ada *, 1, 2, 3> a_ptr_array;
-        for(size_t i = 0; i < 1; i++)
-            for(size_t j = 0; j < 2; j++)
-                for(size_t k = 0; k < 3; k++)
-                    a_ptr_array[i][j][k] = a;
-        _cb(a_ptr_array);
-        return Void();
-    }
-};
-
-extern "C" IPointer* HIDL_FETCH_IPointer(const char* name);
-
-}  // namespace implementation
-}  // namespace V1_0
-}  // namespace pointer
-}  // namespace tests
-}  // namespace hardware
-}  // namespace android
-
-#undef PUSH_ERROR_IF
-
-#endif  // ANDROID_HARDWARE_TESTS_POINTER_V1_0_POINTER_H
diff --git a/tests/pointer/1.0/default/lib/Android.bp b/tests/pointer/1.0/default/lib/Android.bp
deleted file mode 100644
index 180906b..0000000
--- a/tests/pointer/1.0/default/lib/Android.bp
+++ /dev/null
@@ -1,19 +0,0 @@
-cc_library {
-    name: "libpointertest",
-    defaults: ["hidl_defaults"],
-    srcs: [
-        "PointerHelper.cpp"
-    ],
-
-    shared_libs: [
-        "libbase",
-        "libhidlbase",
-        "libhidltransport",
-        "liblog",
-    ],
-    static_libs: ["android.hardware.tests.pointer@1.0"],
-
-    local_include_dirs: ["include/hidl-test"],
-    export_include_dirs: ["include"],
-
-}
diff --git a/tests/pointer/1.0/default/lib/PointerHelper.cpp b/tests/pointer/1.0/default/lib/PointerHelper.cpp
deleted file mode 100644
index 0a64cc3..0000000
--- a/tests/pointer/1.0/default/lib/PointerHelper.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-#define LOG_TAG "hidl_test"
-
-#include <log/log.h>
-
-#include "PointerHelper.h"
-
-namespace android {
-
-void simpleGraph(IGraph::Graph& g) {
-    g.nodes.resize(2);
-    g.edges.resize(1);
-    g.nodes[0].data = 10;
-    g.nodes[1].data = 20;
-    g.edges[0].left = &g.nodes[0];
-    g.edges[0].right = &g.nodes[1];
-}
-
-bool isSimpleGraph(const IGraph::Graph &g) {
-    if(g.nodes.size() != 2) return false;
-    if(g.edges.size() != 1) return false;
-    if(g.nodes[0].data != 10) return false;
-    if(g.nodes[1].data != 20) return false;
-    if(g.edges[0].left != &g.nodes[0]) return false;
-    if(g.edges[0].right != &g.nodes[1]) return false;
-    return true;
-}
-
-void logSimpleGraph(const char *prefix, const IGraph::Graph& g) {
-    ALOGI("%s Graph %p, %d nodes, %d edges", prefix, &g, (int)g.nodes.size(), (int)g.edges.size());
-    std::ostringstream os;
-    for(size_t i = 0; i < g.nodes.size(); i++)
-      os << &g.nodes[i] << " = " << g.nodes[i].data << ", ";
-    ALOGI("%s Nodes: [%s]", prefix, os.str().c_str());
-    os.str("");
-    os.clear();
-    for(size_t i = 0; i < g.edges.size(); i++)
-      os << g.edges[i].left << " -> " << g.edges[i].right << ", ";
-    ALOGI("%s Edges: [%s]", prefix, os.str().c_str());
-}
-} // namespace android
diff --git a/tests/pointer/1.0/default/lib/include/hidl-test/PointerHelper.h b/tests/pointer/1.0/default/lib/include/hidl-test/PointerHelper.h
deleted file mode 100644
index cd2edcb..0000000
--- a/tests/pointer/1.0/default/lib/include/hidl-test/PointerHelper.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef ANDROID_HIDL_TEST_POINTER_HELPER_H
-#define ANDROID_HIDL_TEST_POINTER_HELPER_H
-
-#include <android/hardware/tests/pointer/1.0/IGraph.h>
-
-using ::android::hardware::tests::pointer::V1_0::IGraph;
-
-namespace android {
-
-void simpleGraph(IGraph::Graph& g);
-bool isSimpleGraph(const IGraph::Graph &g);
-void logSimpleGraph(const char *prefix, const IGraph::Graph& g);
-
-} // namespace android
-#endif // ANDROID_HIDL_TEST_POINTER_HELPER_H
diff --git a/tests/safeunion/1.0/Android.bp b/tests/safeunion/1.0/Android.bp
index 87edd53..2937832 100644
--- a/tests/safeunion/1.0/Android.bp
+++ b/tests/safeunion/1.0/Android.bp
@@ -13,4 +13,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/tests/safeunion/1.0/default/Android.bp b/tests/safeunion/1.0/default/Android.bp
index fc2443e..759a49c 100644
--- a/tests/safeunion/1.0/default/Android.bp
+++ b/tests/safeunion/1.0/default/Android.bp
@@ -9,8 +9,6 @@
         "libbase",
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libutils",
     ],
diff --git a/tests/safeunion/cpp/1.0/Android.bp b/tests/safeunion/cpp/1.0/Android.bp
index 1111719..221643a 100644
--- a/tests/safeunion/cpp/1.0/Android.bp
+++ b/tests/safeunion/cpp/1.0/Android.bp
@@ -11,4 +11,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/tests/safeunion/cpp/1.0/default/Android.bp b/tests/safeunion/cpp/1.0/default/Android.bp
index 210a639..618f295 100644
--- a/tests/safeunion/cpp/1.0/default/Android.bp
+++ b/tests/safeunion/cpp/1.0/default/Android.bp
@@ -8,8 +8,6 @@
         "libbase",
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libutils",
     ],
diff --git a/tests/trie/1.0/Android.bp b/tests/trie/1.0/Android.bp
index 0795f66..5a33aea 100644
--- a/tests/trie/1.0/Android.bp
+++ b/tests/trie/1.0/Android.bp
@@ -12,4 +12,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/tests/trie/1.0/default/Android.bp b/tests/trie/1.0/default/Android.bp
index 948a8cb..4ca705c 100644
--- a/tests/trie/1.0/default/Android.bp
+++ b/tests/trie/1.0/default/Android.bp
@@ -9,8 +9,6 @@
         "libbase",
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
-        "libhwbinder",
         "liblog",
         "libutils",
     ],
diff --git a/tests/trie/1.0/types.hal b/tests/trie/1.0/types.hal
index c626909..889d3b2 100644
--- a/tests/trie/1.0/types.hal
+++ b/tests/trie/1.0/types.hal
@@ -29,16 +29,16 @@
 // Some forward reference tests.
 
 struct A {
-    ref<B> b;
+    vec<B> b;
 };
 
 struct B {
-    ref<A> a;
+    vec<A> a;
 };
 
-typedef ref<S> refS;
+typedef vec<S> vecS;
 struct S {
-    refS f;
+    vecS f;
 };
 
 enum E2 : E1 {
diff --git a/tetheroffload/config/1.0/Android.bp b/tetheroffload/config/1.0/Android.bp
index f20d77c..321224a 100644
--- a/tetheroffload/config/1.0/Android.bp
+++ b/tetheroffload/config/1.0/Android.bp
@@ -14,4 +14,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/tetheroffload/control/1.0/Android.bp b/tetheroffload/control/1.0/Android.bp
index dc2487b..f894448 100644
--- a/tetheroffload/control/1.0/Android.bp
+++ b/tetheroffload/control/1.0/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/thermal/1.0/Android.bp b/thermal/1.0/Android.bp
index 8428977..de168d8 100644
--- a/thermal/1.0/Android.bp
+++ b/thermal/1.0/Android.bp
@@ -16,4 +16,3 @@
     gen_java: true,
     gen_java_constants: true,
 }
-
diff --git a/thermal/1.0/default/Android.bp b/thermal/1.0/default/Android.bp
index 9d81474..194a9f8 100644
--- a/thermal/1.0/default/Android.bp
+++ b/thermal/1.0/default/Android.bp
@@ -27,7 +27,6 @@
         "libcutils",
         "libutils",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.thermal@1.0",
     ],
 }
@@ -48,7 +47,6 @@
         "libutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.thermal@1.0",
     ],
 }
diff --git a/thermal/1.0/default/android.hardware.thermal@1.0-service.rc b/thermal/1.0/default/android.hardware.thermal@1.0-service.rc
index cf9bdee..ba3ce82 100644
--- a/thermal/1.0/default/android.hardware.thermal@1.0-service.rc
+++ b/thermal/1.0/default/android.hardware.thermal@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.thermal-hal-1-0 /vendor/bin/hw/android.hardware.thermal@1.0-service
+    interface android.hardware.thermal@1.0::IThermal default
     class hal
     user system
     group system
diff --git a/thermal/1.1/Android.bp b/thermal/1.1/Android.bp
index 8c0f1f9..f38ed3b 100644
--- a/thermal/1.1/Android.bp
+++ b/thermal/1.1/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/thermal/2.0/Android.bp b/thermal/2.0/Android.bp
index af23ee3..1b76f37 100644
--- a/thermal/2.0/Android.bp
+++ b/thermal/2.0/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/thermal/2.0/default/Android.bp b/thermal/2.0/default/Android.bp
index dab0d33..7b72694 100644
--- a/thermal/2.0/default/Android.bp
+++ b/thermal/2.0/default/Android.bp
@@ -27,7 +27,6 @@
     shared_libs: [
         "libbase",
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "android.hardware.thermal@2.0",
         "android.hardware.thermal@1.0",
diff --git a/thermal/2.0/default/android.hardware.thermal@2.0-service.rc b/thermal/2.0/default/android.hardware.thermal@2.0-service.rc
index 046c771..4ff8bd6 100644
--- a/thermal/2.0/default/android.hardware.thermal@2.0-service.rc
+++ b/thermal/2.0/default/android.hardware.thermal@2.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.thermal-hal-2-0-mock /vendor/bin/hw/android.hardware.thermal@2.0-service.mock
+    interface android.hardware.thermal@1.0::IThermal default
     interface android.hardware.thermal@2.0::IThermal default
     class hal
     user system
diff --git a/tv/cec/1.0/Android.bp b/tv/cec/1.0/Android.bp
index 7626dc0..d41a7e7 100644
--- a/tv/cec/1.0/Android.bp
+++ b/tv/cec/1.0/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/tv/cec/1.0/default/Android.bp b/tv/cec/1.0/default/Android.bp
index 069f327..239a527 100644
--- a/tv/cec/1.0/default/Android.bp
+++ b/tv/cec/1.0/default/Android.bp
@@ -7,7 +7,6 @@
 
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libbase",
         "libutils",
@@ -34,8 +33,29 @@
         "libhardware_legacy",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.tv.cec@1.0",
     ],
 
 }
+
+cc_binary {
+    name: "android.hardware.tv.cec@1.0-service.mock",
+    vintf_fragments: ["android.hardware.tv.cec@1.0-service.mock.xml"],
+    relative_install_path: "hw",
+    vendor: true,
+    init_rc: ["android.hardware.tv.cec@1.0-service.mock.rc"],
+    srcs: [
+        "serviceMock.cpp",
+        "HdmiCecMock.cpp",
+    ],
+
+    shared_libs: [
+        "liblog",
+        "libcutils",
+        "libbase",
+        "libutils",
+        "libhardware",
+        "libhidlbase",
+        "android.hardware.tv.cec@1.0",
+    ],
+}
diff --git a/tv/cec/1.0/default/HdmiCecMock.cpp b/tv/cec/1.0/default/HdmiCecMock.cpp
new file mode 100644
index 0000000..219be86
--- /dev/null
+++ b/tv/cec/1.0/default/HdmiCecMock.cpp
@@ -0,0 +1,318 @@
+/*
+ * 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 "android.hardware.tv.cec@1.0-mock"
+#include <android-base/logging.h>
+#include <utils/Log.h>
+
+#include <hardware/hardware.h>
+#include <hardware/hdmi_cec.h>
+#include "HdmiCecMock.h"
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace cec {
+namespace V1_0 {
+namespace implementation {
+
+/*
+ * (*set_option)() passes flags controlling the way HDMI-CEC service works down
+ * to HAL implementation. Those flags will be used in case the feature needs
+ * update in HAL itself, firmware or microcontroller.
+ */
+void HdmiCecMock::cec_set_option(int flag, int value) {
+    // maintain options and set them accordingly
+    switch (flag) {
+        case HDMI_OPTION_WAKEUP:
+            mOptionWakeUp = value;
+            break;
+        case HDMI_OPTION_ENABLE_CEC:
+            mOptionEnableCec = value;
+            break;
+        case HDMI_OPTION_SYSTEM_CEC_CONTROL:
+            mOptionSystemCecControl = value;
+            break;
+        case HDMI_OPTION_SET_LANG:
+            mOptionLanguage = value;
+    }
+}
+
+// Methods from ::android::hardware::tv::cec::V1_0::IHdmiCec follow.
+Return<Result> HdmiCecMock::addLogicalAddress(CecLogicalAddress addr) {
+    // have a list to maintain logical addresses
+    int size = mLogicalAddresses.size();
+    mLogicalAddresses.resize(size + 1);
+    mLogicalAddresses[size + 1] = addr;
+    return Result::SUCCESS;
+}
+
+Return<void> HdmiCecMock::clearLogicalAddress() {
+    // remove logical address from the list
+    mLogicalAddresses = {};
+    return Void();
+}
+
+Return<void> HdmiCecMock::getPhysicalAddress(getPhysicalAddress_cb _hidl_cb) {
+    // maintain a physical address and return it
+    // default 0xFFFF, update on hotplug event
+    _hidl_cb(Result::SUCCESS, mPhysicalAddress);
+    return Void();
+}
+
+Return<SendMessageResult> HdmiCecMock::sendMessage(const CecMessage& message) {
+    if (message.body.size() == 0) {
+        return SendMessageResult::NACK;
+    }
+    sendMessageToFifo(message);
+    return SendMessageResult::SUCCESS;
+}
+
+Return<void> HdmiCecMock::setCallback(const sp<IHdmiCecCallback>& callback) {
+    if (mCallback != nullptr) {
+        mCallback = nullptr;
+    }
+
+    if (callback != nullptr) {
+        mCallback = callback;
+        mCallback->linkToDeath(this, 0 /*cookie*/);
+
+        mInputFile = open(CEC_MSG_IN_FIFO, O_RDWR);
+        mOutputFile = open(CEC_MSG_OUT_FIFO, O_RDWR);
+        pthread_create(&mThreadId, NULL, __threadLoop, this);
+        pthread_setname_np(mThreadId, "hdmi_cec_loop");
+    }
+    return Void();
+}
+
+Return<int32_t> HdmiCecMock::getCecVersion() {
+    // maintain a cec version and return it
+    return mCecVersion;
+}
+
+Return<uint32_t> HdmiCecMock::getVendorId() {
+    return mCecVendorId;
+}
+
+Return<void> HdmiCecMock::getPortInfo(getPortInfo_cb _hidl_cb) {
+    // TODO ready port info from device specific config
+    _hidl_cb(mPortInfo);
+    return Void();
+}
+
+Return<void> HdmiCecMock::setOption(OptionKey key, bool value) {
+    cec_set_option(static_cast<int>(key), value ? 1 : 0);
+    return Void();
+}
+
+Return<void> HdmiCecMock::setLanguage(const hidl_string& language) {
+    if (language.size() != 3) {
+        LOG(ERROR) << "Wrong language code: expected 3 letters, but it was " << language.size()
+                   << ".";
+        return Void();
+    }
+    // TODO validate if language is a valid language code
+    const char* languageStr = language.c_str();
+    int convertedLanguage = ((languageStr[0] & 0xFF) << 16) | ((languageStr[1] & 0xFF) << 8) |
+                            (languageStr[2] & 0xFF);
+    cec_set_option(HDMI_OPTION_SET_LANG, convertedLanguage);
+    return Void();
+}
+
+Return<void> HdmiCecMock::enableAudioReturnChannel(int32_t portId __unused, bool enable __unused) {
+    // Maintain ARC status
+    return Void();
+}
+
+Return<bool> HdmiCecMock::isConnected(int32_t portId) {
+    // maintain port connection status and update on hotplug event
+    if (portId < mTotalPorts && portId >= 0) {
+        return mPortConnectionStatus[portId];
+    }
+    return false;
+}
+
+void* HdmiCecMock::__threadLoop(void* user) {
+    HdmiCecMock* const self = static_cast<HdmiCecMock*>(user);
+    self->threadLoop();
+    return 0;
+}
+
+int HdmiCecMock::readMessageFromFifo(unsigned char* buf, int msgCount) {
+    if (msgCount <= 0 || !buf) {
+        return 0;
+    }
+
+    int ret = -1;
+    /* maybe blocked at driver */
+    ret = read(mInputFile, buf, msgCount);
+    if (ret < 0) {
+        ALOGE("[halimp] read :%s failed, ret:%d\n", CEC_MSG_IN_FIFO, ret);
+        return -1;
+    }
+
+    return ret;
+}
+
+int HdmiCecMock::sendMessageToFifo(const CecMessage& message) {
+    unsigned char msgBuf[CEC_MESSAGE_BODY_MAX_LENGTH];
+    int ret = -1;
+
+    memset(msgBuf, 0, sizeof(msgBuf));
+    msgBuf[0] = ((static_cast<uint8_t>(message.initiator) & 0xf) << 4) |
+                (static_cast<uint8_t>(message.destination) & 0xf);
+
+    size_t length = std::min(static_cast<size_t>(message.body.size()),
+                             static_cast<size_t>(MaxLength::MESSAGE_BODY));
+    for (size_t i = 0; i < length; ++i) {
+        msgBuf[i + 1] = static_cast<unsigned char>(message.body[i]);
+    }
+
+    // open the output pipe for writing outgoing cec message
+    mOutputFile = open(CEC_MSG_OUT_FIFO, O_WRONLY);
+    if (mOutputFile < 0) {
+        ALOGD("[halimp] file open failed for writing");
+        return -1;
+    }
+
+    // write message into the output pipe
+    ret = write(mOutputFile, msgBuf, length + 1);
+    close(mOutputFile);
+    if (ret < 0) {
+        ALOGE("[halimp] write :%s failed, ret:%d\n", CEC_MSG_OUT_FIFO, ret);
+        return -1;
+    }
+    return ret;
+}
+
+void HdmiCecMock::printCecMsgBuf(const char* msg_buf, int len) {
+    char buf[64] = {};
+    int i, size = 0;
+    memset(buf, 0, sizeof(buf));
+    for (i = 0; i < len; i++) {
+        size += sprintf(buf + size, " %02x", msg_buf[i]);
+    }
+    ALOGD("[halimp] %s, msg:%s", __FUNCTION__, buf);
+}
+
+void HdmiCecMock::handleHotplugMessage(unsigned char* msgBuf) {
+    HotplugEvent hotplugEvent{.connected = ((msgBuf[3]) & 0xf) > 0,
+                              .portId = static_cast<uint32_t>(msgBuf[0] & 0xf)};
+
+    if (hotplugEvent.portId >= mPortInfo.size()) {
+        ALOGD("[halimp] ignore hot plug message, id %x does not exist", hotplugEvent.portId);
+        return;
+    }
+
+    ALOGD("[halimp] hot plug port id %x, is connected %x", (msgBuf[0] & 0xf), (msgBuf[3] & 0xf));
+    if (mPortInfo[hotplugEvent.portId].type == HdmiPortType::OUTPUT) {
+        mPhysicalAddress =
+                ((hotplugEvent.connected == 0) ? 0xffff : ((msgBuf[1] << 8) | (msgBuf[2])));
+        mPortInfo[hotplugEvent.portId].physicalAddress = mPhysicalAddress;
+        ALOGD("[halimp] hot plug physical address %x", mPhysicalAddress);
+    }
+
+    // todo update connection status
+
+    if (mCallback != nullptr) {
+        mCallback->onHotplugEvent(hotplugEvent);
+    }
+}
+
+void HdmiCecMock::handleCecMessage(unsigned char* msgBuf, int megSize) {
+    CecMessage message;
+    size_t length = std::min(static_cast<size_t>(megSize - 1),
+                             static_cast<size_t>(MaxLength::MESSAGE_BODY));
+    message.body.resize(length);
+
+    for (size_t i = 0; i < length; ++i) {
+        message.body[i] = static_cast<uint8_t>(msgBuf[i + 1]);
+        ALOGD("[halimp] msg body %x", message.body[i]);
+    }
+
+    message.initiator = static_cast<CecLogicalAddress>((msgBuf[0] >> 4) & 0xf);
+    ALOGD("[halimp] msg init %x", message.initiator);
+    message.destination = static_cast<CecLogicalAddress>((msgBuf[0] >> 0) & 0xf);
+    ALOGD("[halimp] msg dest %x", message.destination);
+
+    // messageValidateAndHandle(&event);
+
+    if (mCallback != nullptr) {
+        mCallback->onCecMessage(message);
+    }
+}
+
+void HdmiCecMock::threadLoop() {
+    ALOGD("[halimp] threadLoop start.");
+    unsigned char msgBuf[CEC_MESSAGE_BODY_MAX_LENGTH];
+    int r = -1;
+
+    // open the input pipe
+    while (mInputFile < 0) {
+        usleep(1000 * 1000);
+        mInputFile = open(CEC_MSG_IN_FIFO, O_RDONLY);
+    }
+    ALOGD("[halimp] file open ok, fd = %d.", mInputFile);
+
+    while (mCecThreadRun) {
+        if (!mOptionSystemCecControl) {
+            usleep(1000 * 1000);
+            continue;
+        }
+
+        memset(msgBuf, 0, sizeof(msgBuf));
+        // try to get a message from dev.
+        // echo -n -e '\x04\x83' >> /dev/cec
+        r = readMessageFromFifo(msgBuf, CEC_MESSAGE_BODY_MAX_LENGTH);
+        if (r <= 1) {
+            // ignore received ping messages
+            continue;
+        }
+
+        printCecMsgBuf((const char*)msgBuf, r);
+
+        if (((msgBuf[0] >> 4) & 0xf) == 0xf) {
+            // the message is a hotplug event
+            handleHotplugMessage(msgBuf);
+            continue;
+        }
+
+        handleCecMessage(msgBuf, r);
+    }
+
+    ALOGD("[halimp] thread end.");
+    // mCecDevice.mExited = true;
+}
+
+HdmiCecMock::HdmiCecMock() {
+    ALOGE("[halimp] Opening a virtual HAL for testing and virtual machine.");
+    mCallback = nullptr;
+    mPortInfo.resize(mTotalPorts);
+    mPortConnectionStatus.resize(mTotalPorts);
+    mPortInfo[0] = {.type = HdmiPortType::OUTPUT,
+                    .portId = static_cast<uint32_t>(0),
+                    .cecSupported = true,
+                    .arcSupported = false,
+                    .physicalAddress = mPhysicalAddress};
+    mPortConnectionStatus[0] = false;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace cec
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/cec/1.0/default/HdmiCecMock.h b/tv/cec/1.0/default/HdmiCecMock.h
new file mode 100644
index 0000000..0a708fa
--- /dev/null
+++ b/tv/cec/1.0/default/HdmiCecMock.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_CEC_V1_0_HDMICEC_H
+#define ANDROID_HARDWARE_TV_CEC_V1_0_HDMICEC_H
+
+#include <android/hardware/tv/cec/1.0/IHdmiCec.h>
+#include <hardware/hardware.h>
+#include <hardware/hdmi_cec.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <algorithm>
+#include <vector>
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace cec {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::tv::cec::V1_0::CecLogicalAddress;
+using ::android::hardware::tv::cec::V1_0::CecMessage;
+using ::android::hardware::tv::cec::V1_0::HdmiPortInfo;
+using ::android::hardware::tv::cec::V1_0::IHdmiCec;
+using ::android::hardware::tv::cec::V1_0::IHdmiCecCallback;
+using ::android::hardware::tv::cec::V1_0::MaxLength;
+using ::android::hardware::tv::cec::V1_0::OptionKey;
+using ::android::hardware::tv::cec::V1_0::Result;
+using ::android::hardware::tv::cec::V1_0::SendMessageResult;
+
+#define CEC_MSG_IN_FIFO "/dev/cec_in_pipe"
+#define CEC_MSG_OUT_FIFO "/dev/cec_out_pipe"
+
+struct HdmiCecMock : public IHdmiCec, public hidl_death_recipient {
+    HdmiCecMock();
+    // Methods from ::android::hardware::tv::cec::V1_0::IHdmiCec follow.
+    Return<Result> addLogicalAddress(CecLogicalAddress addr) override;
+    Return<void> clearLogicalAddress() override;
+    Return<void> getPhysicalAddress(getPhysicalAddress_cb _hidl_cb) override;
+    Return<SendMessageResult> sendMessage(const CecMessage& message) override;
+    Return<void> setCallback(const sp<IHdmiCecCallback>& callback) override;
+    Return<int32_t> getCecVersion() override;
+    Return<uint32_t> getVendorId() override;
+    Return<void> getPortInfo(getPortInfo_cb _hidl_cb) override;
+    Return<void> setOption(OptionKey key, bool value) override;
+    Return<void> setLanguage(const hidl_string& language) override;
+    Return<void> enableAudioReturnChannel(int32_t portId, bool enable) override;
+    Return<bool> isConnected(int32_t portId) override;
+
+    virtual void serviceDied(uint64_t /*cookie*/,
+                             const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
+        setCallback(nullptr);
+    }
+
+    void cec_set_option(int flag, int value);
+    void printCecMsgBuf(const char* msg_buf, int len);
+
+  private:
+    static void* __threadLoop(void* data);
+    void threadLoop();
+    int readMessageFromFifo(unsigned char* buf, int msgCount);
+    int sendMessageToFifo(const CecMessage& message);
+    void handleHotplugMessage(unsigned char* msgBuf);
+    void handleCecMessage(unsigned char* msgBuf, int length);
+
+  private:
+    sp<IHdmiCecCallback> mCallback;
+
+    // Variables for the virtual cec hal impl
+    uint16_t mPhysicalAddress = 0xFFFF;
+    vector<CecLogicalAddress> mLogicalAddresses;
+    int32_t mCecVersion = 0;
+    uint32_t mCecVendorId = 0;
+
+    // Port configuration
+    int mTotalPorts = 1;
+    hidl_vec<HdmiPortInfo> mPortInfo;
+    hidl_vec<bool> mPortConnectionStatus;
+
+    // CEC Option value
+    int mOptionWakeUp = 0;
+    int mOptionEnableCec = 0;
+    int mOptionSystemCecControl = 0;
+    int mOptionLanguage = 0;
+
+    // Testing variables
+    // Input file descriptor
+    int mInputFile;
+    // Output file descriptor
+    int mOutputFile;
+    bool mCecThreadRun = true;
+    pthread_t mThreadId = 0;
+};
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace cec
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TV_CEC_V1_0_HDMICEC_H
diff --git a/tv/cec/1.0/default/android.hardware.tv.cec@1.0-service.mock.rc b/tv/cec/1.0/default/android.hardware.tv.cec@1.0-service.mock.rc
new file mode 100644
index 0000000..170b485
--- /dev/null
+++ b/tv/cec/1.0/default/android.hardware.tv.cec@1.0-service.mock.rc
@@ -0,0 +1,5 @@
+service vendor.cec-hal-1-0-mock /vendor/bin/hw/android.hardware.tv.cec@1.0-service.mock
+    interface android.hardware.tv.cec@1.0::IHdmiCec default
+    class hal
+    user system
+    group system
diff --git a/tv/cec/1.0/default/android.hardware.tv.cec@1.0-service.mock.xml b/tv/cec/1.0/default/android.hardware.tv.cec@1.0-service.mock.xml
new file mode 100644
index 0000000..5afa59d
--- /dev/null
+++ b/tv/cec/1.0/default/android.hardware.tv.cec@1.0-service.mock.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.tv.cec</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IHdmiCec</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/tv/cec/1.0/default/android.hardware.tv.cec@1.0-service.rc b/tv/cec/1.0/default/android.hardware.tv.cec@1.0-service.rc
index 8595099..6d25229 100644
--- a/tv/cec/1.0/default/android.hardware.tv.cec@1.0-service.rc
+++ b/tv/cec/1.0/default/android.hardware.tv.cec@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.cec-hal-1-0 /vendor/bin/hw/android.hardware.tv.cec@1.0-service
+    interface android.hardware.tv.cec@1.0::IHdmiCec default
     class hal
     user system
     group system
diff --git a/tv/cec/1.0/default/serviceMock.cpp b/tv/cec/1.0/default/serviceMock.cpp
new file mode 100644
index 0000000..c0af22f
--- /dev/null
+++ b/tv/cec/1.0/default/serviceMock.cpp
@@ -0,0 +1,40 @@
+/*
+ * 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 "android.hardware.tv.cec@1.0-service-shim"
+
+#include <android/hardware/tv/cec/1.0/IHdmiCec.h>
+#include <hidl/LegacySupport.h>
+#include "HdmiCecMock.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::tv::cec::V1_0::IHdmiCec;
+using android::hardware::tv::cec::V1_0::implementation::HdmiCecMock;
+
+int main() {
+    configureRpcThreadpool(8, true /* callerWillJoin */);
+
+    // Setup hwbinder service
+    android::sp<IHdmiCec> service = new HdmiCecMock();
+    android::status_t status;
+    status = service->registerAsService();
+    LOG_ALWAYS_FATAL_IF(status != android::OK, "Error while registering mock cec service: %d",
+                        status);
+
+    joinRpcThreadpool();
+    return 0;
+}
diff --git a/tv/cec/2.0/Android.bp b/tv/cec/2.0/Android.bp
index 5a67fa5..61450ac 100644
--- a/tv/cec/2.0/Android.bp
+++ b/tv/cec/2.0/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/tv/cec/2.0/default/Android.bp b/tv/cec/2.0/default/Android.bp
index 6e624e3..d3d5342 100644
--- a/tv/cec/2.0/default/Android.bp
+++ b/tv/cec/2.0/default/Android.bp
@@ -7,7 +7,6 @@
 
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libbase",
         "libutils",
@@ -35,7 +34,6 @@
         "libhardware_legacy",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.tv.cec@2.0",
     ],
 
diff --git a/tv/input/1.0/Android.bp b/tv/input/1.0/Android.bp
index a6c1959..7288558 100644
--- a/tv/input/1.0/Android.bp
+++ b/tv/input/1.0/Android.bp
@@ -18,4 +18,3 @@
     gen_java: false,
     gen_java_constants: true,
 }
-
diff --git a/tv/input/1.0/default/Android.bp b/tv/input/1.0/default/Android.bp
index 7c140a5..5f6b7e7 100644
--- a/tv/input/1.0/default/Android.bp
+++ b/tv/input/1.0/default/Android.bp
@@ -10,7 +10,6 @@
         "liblog",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "libutils",
         "android.hardware.audio.common@2.0",
         "android.hardware.tv.input@1.0",
@@ -35,7 +34,6 @@
         "libhardware_legacy",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.audio.common@2.0",
         "android.hardware.tv.input@1.0",
     ],
diff --git a/tv/input/1.0/default/android.hardware.tv.input@1.0-service.rc b/tv/input/1.0/default/android.hardware.tv.input@1.0-service.rc
index 972c654..6cb9a43 100644
--- a/tv/input/1.0/default/android.hardware.tv.input@1.0-service.rc
+++ b/tv/input/1.0/default/android.hardware.tv.input@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.tv-input-1-0 /vendor/bin/hw/android.hardware.tv.input@1.0-service
+    interface android.hardware.tv.input@1.0::ITvInput default
     class hal
     user system
     group system
diff --git a/tv/tuner/1.0/Android.bp b/tv/tuner/1.0/Android.bp
new file mode 100644
index 0000000..09265f7
--- /dev/null
+++ b/tv/tuner/1.0/Android.bp
@@ -0,0 +1,24 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.tv.tuner@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IDemux.hal",
+        "IDemuxCallback.hal",
+        "IDescrambler.hal",
+        "IFrontend.hal",
+        "IFrontendCallback.hal",
+        "ILnb.hal",
+        "ITuner.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    gen_java: false,
+    gen_java_constants: true,
+}
diff --git a/tv/tuner/1.0/IDemux.hal b/tv/tuner/1.0/IDemux.hal
new file mode 100644
index 0000000..7ead34b
--- /dev/null
+++ b/tv/tuner/1.0/IDemux.hal
@@ -0,0 +1,415 @@
+/*
+ * 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.tv.tuner@1.0;
+
+import IDemuxCallback;
+
+/**
+ * Demultiplexer(Demux) takes a single multiplexed input and splits it into
+ * one or more output.
+ *
+ */
+interface IDemux {
+
+    /**
+     * Set a frontend resource as data input of the demux
+     *
+     * It is used by the client to specify a hardware frontend as data source of
+     * this demux instance. A demux instance can have only one data source.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    setFrontendDataSource(FrontendId frontendId) generates (Result result);
+
+    /**
+     * Add a filter to the demux
+     *
+     * It is used by the client to add a filter to the demux.
+     *
+     * @param type the type of the filter to be added.
+     * @param bufferSize the buffer size of the filter to be added. It's used to
+     * create a FMQ(Fast Message Queue) to hold data output from the filter.
+     * @param cb the callback for the filter to be used to send notifications
+     * back to the client.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     * @return filterId the ID of the newly added filter.
+     */
+    addFilter(DemuxFilterType type, uint32_t bufferSize, IDemuxCallback cb)
+        generates (Result result, DemuxFilterId filterId);
+
+    /**
+     * Get the descriptor of the filter's FMQ
+     *
+     * It is used by the client to get the descriptor of the filter's Fast
+     * Message Queue. The data in FMQ is filtered out from MPEG transport
+     * stream. The data is origanized to data blocks which may have
+     * different length. The length's information of one or multiple data blocks
+     * is sent to client throught DemuxFilterEvent.
+     *
+     * @param filterId the ID of the filter.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_ARGUMENT if failed for wrong filter ID.
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     * @return queue the descriptor of the filter's FMQ
+     */
+    getFilterQueueDesc(DemuxFilterId filterId)
+        generates (Result result, fmq_sync<uint8_t> queue);
+
+    /**
+     * Configure the filter.
+     *
+     * It is used by the client to configure the filter so that it can filter out
+     * intended data.
+     *
+     * @param filterId the ID of the filter.
+     * @param settings the settings of the filter.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_ARGUMENT if failed for wrong filter ID.
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    configureFilter(DemuxFilterId filterId, DemuxFilterSettings settings)
+        generates(Result result);
+
+    /**
+     * Start the filter.
+     *
+     * It is used by the client to ask the filter to start filterring data.
+     *
+     * @param filterId the ID of the filter.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_ARGUMENT if failed for wrong filter ID.
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    startFilter(DemuxFilterId filterId) generates (Result result);
+
+    /**
+     * Stop the filter.
+     *
+     * It is used by the client to ask the filter to stop filterring data.
+     * It won't discard the data already filtered out by the filter. The filter
+     * will be stopped and removed automatically if the demux is closed.
+     *
+     * @param filterId the ID of the filter.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_ARGUMENT if failed for wrong filter ID.
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    stopFilter(DemuxFilterId filterId) generates (Result result);
+
+    /**
+     * Flush the filter.
+     *
+     * It is used by the client to ask the filter to flush the data which is
+     * already produced but not consumed yet.
+     *
+     * @param filterId the ID of the filter.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_ARGUMENT if failed for wrong filter ID.
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    flushFilter(DemuxFilterId filterId) generates (Result result);
+
+    /**
+     * Remove a filter from the demux
+     *
+     * It is used by the client to remove a filter from the demux.
+     *
+     * @param filterId the ID of the removed filter.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_ARGUMENT if failed for wrong filter ID.
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    removeFilter(DemuxFilterId filterId) generates (Result result);
+
+    /**
+     * Get hardware sync ID for audio and video.
+     *
+     * It is used by the client to get the hardware sync ID for audio and video.
+     *
+     * @param filterId the ID of the filter.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_ARGUMENT if failed for a wrong filter ID.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     * @return avSyncHwId the id of hardware A/V sync.
+     */
+    getAvSyncHwId(DemuxFilterId filterId)
+        generates (Result result, AvSyncHwId avSyncHwId);
+
+    /**
+     * Get current time stamp to use for A/V sync
+     *
+     * It is used by the client to get current time stamp for A/V sync. HW is
+     * supported to increment and maintain current time stamp.
+     *
+     * @param avSyncHwId the hardware id of A/V sync.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_ARGUMENT if failed for a wrong hardware ID of A/V sync.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     * @return time the current time stamp of hardware A/V sync. The time stamp
+     * based on 90KHz has the same format as PTS (Presentation Time Stamp).
+     */
+    getAvSyncTime(AvSyncHwId avSyncHwId)
+        generates (Result result, uint64_t time);
+
+    /**
+     * Close the Demux instance
+     *
+     * It is used by the client to release the demux instance. HAL clear
+     * underneath resource. client mustn't access the instance any more.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    close() generates (Result result);
+
+    /**
+     * Add output to the demux
+     *
+     * It is used by the client to record output data from selected filters.
+     *
+     * @param bufferSize the buffer size of the output to be added. It's used to
+     * create a FMQ(Fast Message Queue) to hold data from selected filters.
+     * @param cb the callback for the demux to be used to send notifications
+     * back to the client.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         OUT_OF_MEMORY if failed for not enough memory.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    addOutput(uint32_t bufferSize, IDemuxCallback cb) generates (Result result);
+
+    /**
+     * Get the descriptor of the output's FMQ
+     *
+     * It is used by the client to get the descriptor of the output's Fast
+     * Message Queue. The data in FMQ is muxed packets output from selected
+     * filters. The packet's format is specifed by DemuxDataFormat in
+     * DemuxOutputSettings.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNKNOWN_ERROR if failed for other reasons.
+     * @return queue the descriptor of the output's FMQ
+     */
+    getOutputQueueDesc() generates (Result result, fmq_sync<uint8_t> queue);
+
+    /**
+     * Configure the demux's output.
+     *
+     * It is used by the client to configure the demux's output for recording.
+     *
+     * @param settings the settings of the demux's output.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    configureOutput(DemuxOutputSettings settings) generates (Result result);
+
+    /**
+     * Attach one filter to the demux's output.
+     *
+     * It is used by the client to mux one filter's output to demux's output.
+     *
+     * @param filterId the ID of the attached filter.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    attachOutputFilter(DemuxFilterId filterId) generates (Result result);
+
+    /**
+     * Detach one filter from the demux's output.
+     *
+     * It is used by the client to remove one filter's output from demux's
+     * output.
+     *
+     * @param filterId the ID of the detached filter.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    detachOutputFilter(DemuxFilterId filterId) generates (Result result);
+
+    /**
+     * Start to take data to the demux's output.
+     *
+     * It is used by the client to ask the output to start to take data from
+     * attached filters.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    startOutput() generates (Result result);
+
+    /**
+     * Stop to take data to the demux's output.
+     *
+     * It is used by the client to ask the output to stop to take data from
+     * attached filters.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    stopOutput() generates (Result result);
+
+    /**
+     * Flush unconsumed data in the demux's output.
+     *
+     * It is used by the client to ask the demux to flush the data which is
+     * already produced but not consumed yet in the demux's output.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    flushOutput() generates (Result result);
+
+    /**
+     * Remove the demux's output.
+     *
+     * It is used by the client to remove the demux's output.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    removeOutput() generates (Result result);
+
+    /**
+     * Add input to the demux
+     *
+     * It is used by the client to add the demux's input for playback content.
+     *
+     * @param bufferSize the buffer size of the demux's input to be added.
+     * It's used to create a FMQ(Fast Message Queue) to hold input data.
+     * @param cb the callback for the demux to be used to send notifications
+     * back to the client.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         OUT_OF_MEMORY if failed for not enough memory.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    addInput(uint32_t bufferSize, IDemuxCallback cb) generates (Result result);
+
+    /**
+     * Get the descriptor of the input's FMQ
+     *
+     * It is used by the client to get the descriptor of the input's Fast
+     * Message Queue. The data in FMQ is fed by client. Data format is specifed
+     * by DemuxDataFormat in DemuxInputSettings.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNKNOWN_ERROR if failed for other reasons.
+     * @return queue the descriptor of the output's FMQ
+     */
+    getInputQueueDesc() generates (Result result, fmq_sync<uint8_t> queue);
+
+    /**
+     * Configure the demux's input.
+     *
+     * It is used by the client to configure the demux's input for playback.
+     *
+     * @param settings the settings of the demux's input.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    configureInput(DemuxInputSettings settings) generates (Result result);
+
+    /**
+     * Start to consume the data from the demux's input.
+     *
+     * It is used by the client to ask the demux to start to consume data from
+     * the demux's input.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    startInput() generates (Result result);
+
+    /**
+     * Stop to consume the data from the demux's input.
+     *
+     * It is used by the client to ask the demux to stop to consume data from
+     * the demux's input.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    stopInput() generates (Result result);
+
+    /**
+     * Flush unconsumed data in the demux's input.
+     *
+     * It is used by the client to ask the demux to flush the data which is
+     * already produced but not consumed yet in the demux's input.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    flushInput() generates (Result result);
+
+    /**
+     * Remove the demux's input.
+     *
+     * It is used by the client to remove the demux's input.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    removeInput() generates (Result result);
+};
diff --git a/tv/tuner/1.0/IDemuxCallback.hal b/tv/tuner/1.0/IDemuxCallback.hal
new file mode 100644
index 0000000..7bce9ef
--- /dev/null
+++ b/tv/tuner/1.0/IDemuxCallback.hal
@@ -0,0 +1,49 @@
+/*
+ * 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.tv.tuner@1.0;
+
+interface IDemuxCallback {
+    /**
+     * Notify the client that a new filter event happened.
+     *
+     * @param filterEvent a demux filter event.
+     */
+    oneway onFilterEvent(DemuxFilterEvent filterEvent);
+
+    /**
+     * Notify the client a new status of a demux filter.
+     *
+     * @param filterId the demux filter ID.
+     * @param status a new status of the demux filter.
+     */
+    oneway onFilterStatus(DemuxFilterId filterId, DemuxFilterStatus status);
+
+    /**
+     * Notify the client a new status of the demux's output.
+     *
+     * @param status a new status of the demux's output.
+     */
+    oneway onOutputStatus(DemuxOutputStatus status);
+
+    /**
+     * Notify the client a new status of the demux's input.
+     *
+     * @param status a new status of the demux's input.
+     */
+    oneway onInputStatus(DemuxInputStatus status);
+};
+
diff --git a/tv/tuner/1.0/IDescrambler.hal b/tv/tuner/1.0/IDescrambler.hal
new file mode 100644
index 0000000..61ff1df
--- /dev/null
+++ b/tv/tuner/1.0/IDescrambler.hal
@@ -0,0 +1,95 @@
+/*
+ * 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.tv.tuner@1.0;
+/**
+ * Descrambler is used to descramble input data.
+ *
+ */
+interface IDescrambler {
+    /**
+     * Set a demux as source of the descrambler
+     *
+     * It is used by the client to specify a demux as source of this
+     * descrambler. A descrambler instance can have only one source, and
+     * this method can be only called once.
+     *
+     * @param demuxId the id of the demux to be used as descrambler's source.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    setDemuxSource(DemuxId demuxId) generates (Result result);
+
+    /**
+     * Set a key token to link descrambler to a key slot
+     *
+     * It is used by the client to link a hardware key slot to a descrambler.
+     * A descrambler instance can have only one key slot to link, but a key
+     * slot can hold a few keys for different purposes.
+     *
+     * @param keyToken the token to be used to link the key slot.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    setKeyToken(TunerKeyToken keyToken) generates (Result result);
+
+    /**
+     * Add packets' PID to the descrambler for descrambling
+     *
+     * It is used by the client to specify Package ID (PID) of packets which the
+     * descrambler start to descramble. Multiple PIDs can be added into one
+     * descrambler instance because descambling can happen simultaneously on
+     * packets from different PIDs.
+     *
+     * @param pid the PID of packets to start to be descrambled.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    addPid(DemuxTpid pid) generates (Result result);
+
+    /**
+     * Remove packets' PID from the descrambler
+     *
+     * It is used by the client to specify Package ID (PID) of packets which the
+     * descrambler stop to descramble.
+     *
+     * @param pid the PID of packets to stop to be descrambled.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if failed for wrong state.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    removePid(DemuxTpid pid) generates (Result result);
+
+    /**
+     * Release the descrambler instance
+     *
+     * It is used by the client to release the descrambler instance. HAL clear
+     * underneath resource. client mustn't access the instance any more.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    close() generates (Result result);
+};
+
diff --git a/tv/tuner/1.0/IFrontend.hal b/tv/tuner/1.0/IFrontend.hal
new file mode 100644
index 0000000..962e4ba
--- /dev/null
+++ b/tv/tuner/1.0/IFrontend.hal
@@ -0,0 +1,159 @@
+/*
+ * 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.tv.tuner@1.0;
+
+import IFrontendCallback;
+import ILnb;
+
+/**
+ * A Tuner Frontend is used to tune to a frequency and lock signal. It provide
+ * live data feed to Tuner Demux interface.
+ */
+interface IFrontend {
+    /**
+     * Set the callback
+     *
+     * It is used by the client to receive events from the Frontend.
+     * Only one callback for one Frontend instance is supported. The callback
+     * will be replaced if it's set again.
+     *
+     * @param callback Callback object to pass Frontend events to the system.
+     *        The previously registered callback must be replaced with this one.
+     *        It can be null.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if callback can't be set at current stage,
+     *         UNKNOWN_ERROR if callback setting failed for other reasons.
+     */
+    setCallback(IFrontendCallback callback) generates (Result result);
+
+    /**
+     * Tuning Frontend
+     *
+     * It is used by the client to lock a frequency by providing signal
+     * delivery information. If previous tuning isn't completed, this call must
+     * stop previous tuning, and start a new tuning. Tune is a async call.
+     * LOCKED or NO_SIGNAL eventi is sent back to caller through callback.
+     *
+     * @param settings Signal delivery information which frontend can use to
+     * search and lock the signal.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if tuning can't be applied at current stage,
+     *         UNKNOWN_ERROR if tuning failed for other reasons.
+     */
+    tune(FrontendSettings settings) generates (Result result);
+
+    /**
+     * Stop the tuning
+     *
+     * It is used by the client to stop a previous tuning.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successfully stop tuning.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    stopTune() generates (Result result);
+
+    /**
+     * Release the Frontend instance
+     *
+     * It is used by the client to release the frontend instance. HAL clear
+     * underneath resource. client mustn't access the instance any more.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    close() generates (Result result);
+
+    /**
+     * Scan the frontend to use the settings given.
+     *
+     * This uses the frontend to start a scan from signal delivery information.
+     * If previous scan isn't completed, this call MUST stop previous scan,
+     * and start a new scan.
+     * Scan is an async call, with FrontendScanMessage sent via callback.
+     *
+     * @param settings Signal delivery information which the frontend uses to
+     * scan the signal.
+     * @param type the type which the frontend uses to scan the signal.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if tuning can't be applied at current stage,
+     *         UNKNOWN_ERROR if tuning failed for other reasons.
+     */
+    scan(FrontendSettings settings, FrontendScanType type) generates (Result result);
+
+    /**
+     * Stops a previous scanning.
+     *
+     * If the method completes successfully, the frontend stop previous
+     * scanning.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successfully stop tuning.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    stopScan() generates (Result result);
+
+    /**
+     * Gets the statuses of the frontend.
+     *
+     * This retrieve the statuses of the frontend for given status types.
+     *
+     * @param statusTypes an array of status type which the caller request.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if tuning can't be applied at current stage,
+     *         UNKNOWN_ERROR if tuning failed for other reasons.
+     * @return statuses an array of statuses which response the caller's
+     *         request.
+     */
+    getStatus(vec<FrontendStatusType> statusTypes) generates (Result result, vec<FrontendStatus> statuses);
+
+    /**
+     * Sets Low-Noise Block downconverter (LNB) for satellite frontend.
+     *
+     * This assigns a hardware LNB resource to the satellite frontend. It can be
+     * called multiple times to update LNB assignment. The LNB resource must be
+     * released when the frontend is closed.
+     *
+     * @param lnbId the Id of assigned LNB resource.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if the frontend can't be set with a LNB, such as
+     *         cable frontend.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    setLnb(LnbId lnbId) generates (Result result);
+
+    /**
+     * Enble or Disable Low Noise Amplifier (LNA).
+     *
+     * @param bEnable true if activate LNA module; false if deactivate LNA
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if the frontend doesn't support LNA.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    setLna(bool bEnable) generates (Result result);
+};
diff --git a/tv/tuner/1.0/IFrontendCallback.hal b/tv/tuner/1.0/IFrontendCallback.hal
new file mode 100644
index 0000000..8896a09
--- /dev/null
+++ b/tv/tuner/1.0/IFrontendCallback.hal
@@ -0,0 +1,45 @@
+/*
+ * 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.tv.tuner@1.0;
+
+interface IFrontendCallback {
+    /**
+     * Notify the client that a new event happened on the frontend.
+     *
+     * @param frontendEventType the event type.
+     */
+    oneway onEvent(FrontendEventType frontendEventType);
+
+    /**
+     * The callback function that must be called by HAL implementation to notify
+     * the client of new DiSEqC message.
+     *
+     * @param diseqcMessage a byte array of data for DiSEqC (Digital Satellite
+     * Equipment Control) message which is specified by EUTELSAT Bus Functional
+     * Specification Version 4.2.
+     */
+    oneway onDiseqcMessage(vec<uint8_t> diseqcMessage);
+
+    /**
+     * The callback function that must be called by HAL implementation to notify
+     * the client of scan messages.
+     *
+     * @param type the type of scan message.
+     * @param message the scan message sent by HAL to the client.
+     */
+    oneway onScanMessage(FrontendScanMessageType type, FrontendScanMessage message);
+};
diff --git a/tv/tuner/1.0/ILnb.hal b/tv/tuner/1.0/ILnb.hal
new file mode 100644
index 0000000..6b7119e
--- /dev/null
+++ b/tv/tuner/1.0/ILnb.hal
@@ -0,0 +1,86 @@
+/*
+ * 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.tv.tuner@1.0;
+
+/**
+ * A Tuner LNB (low-noise block downconverter) is used by satellite frontend
+ * to receive the microwave signal from the satellite, amplify it, and
+ * downconvert the frequency to a lower frequency.
+ */
+interface ILnb {
+    /**
+     * Set the lnb's power voltage.
+     *
+     * @param voltage the power's voltage the Lnb to use.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_ARGUMENT if the selected voltage isn't allowed,
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    setVoltage(FrontendLnbVoltage voltage) generates (Result result);
+
+    /**
+     * Set the lnb's tone mode.
+     *
+     * @param tone the tone mode the Lnb to use.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_ARGUMENT if the selected tone mode isn't allowed,
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    setTone(FrontendLnbTone tone) generates (Result result);
+
+    /**
+     * Select the lnb's position.
+     *
+     * @param position the position the Lnb to use.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_ARGUMENT if the selected position isn't allowed,
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    setSatellitePosition(FrontendLnbPosition position) generates (Result result);
+
+    /**
+     *  Sends DiSEqC (Digital Satellite Equipment Control) message.
+     *
+     * Client sends DiSeqc message to DiSEqc to LNB. The response message from
+     * the device comes back to the client through frontend's callback
+     * onDiseqcMessage.
+     *
+     * @param diseqcMessage a byte array of data for DiSEqC message which is
+     *        specified by EUTELSAT Bus Functional Specification Version 4.2.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         INVALID_STATE if the frontend can't send DiSEqc Message, such as
+     *         cable frontend.
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    sendDiseqcMessage(vec<uint8_t> diseqcMessage) generates (Result result);
+
+    /**
+     * Releases the LNB instance
+     *
+     * Associated resources are released.  close may be called more than once.
+     * Calls to any other method after this will return an error
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNKNOWN_ERROR if failed for other reasons.
+     */
+    close() generates (Result result);
+};
diff --git a/tv/tuner/1.0/ITuner.hal b/tv/tuner/1.0/ITuner.hal
new file mode 100644
index 0000000..0d63442
--- /dev/null
+++ b/tv/tuner/1.0/ITuner.hal
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.tuner@1.0;
+
+import IDemux;
+import IDescrambler;
+import IFrontend;
+import ILnb;
+
+/**
+ * Top level interface to manage Frontend, Demux and Decrambler hardware
+ * resouces which are needed for Android TV.
+ */
+interface ITuner {
+    /**
+     * Get Frontend IDs
+     *
+     * It is used by the client to get all available frontends' IDs.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNKNOWN_ERROR if tuning failed for other reasons.
+     * @return frontendIds an array of FrontendId for the available frontends.
+     */
+    getFrontendIds() generates (Result result, vec<FrontendId> frontendIds);
+
+    /**
+     * Create a new instance of Frontend given a frontendId.
+     *
+     * It is used by the client to create a frontend instance.
+     *
+     * @param frontendId the id of the frontend to be opened.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNAVAILABLE if no resource.
+     *         UNKNOWN_ERROR if creation failed for other reasons.
+     * @return frontend the newly created frontend interface.
+     */
+    openFrontendById(FrontendId frontendId)
+        generates (Result result, IFrontend frontend);
+
+    /**
+     * Create a new instance of Demux.
+     *
+     * It is used by the client to create a Demux instance.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNKNOWN_ERROR if creation failed for other reasons.
+     * @return demuxId newly created demux id.
+     * @return demux the newly created demux interface.
+     */
+    openDemux()
+         generates (Result result, DemuxId demuxId, IDemux demux);
+
+    /**
+     * Retrieve the Demux's Capabilities.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNKNOWN_ERROR if the inquiry failed for other reasons.
+     * @return caps the Demux's Capabilities.
+     */
+    getDemuxCaps() generates (Result result, DemuxCapabilities caps);
+
+    /**
+     * Create a new instance of Descrambler.
+     *
+     * It is used by the client to create a Descrambler instance.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNKNOWN_ERROR if creation failed for other reasons.
+     * @return descrambler the newly created descrambler interface.
+     */
+    openDescrambler()
+         generates (Result result, IDescrambler descrambler);
+
+    /**
+     * Retrieve the frontend's information.
+     *
+     * @param frontendId the id of the frontend to be inquiried.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNKNOWN_ERROR if the inquiry failed for other reasons.
+     * @return info the frontend's information.
+     */
+    getFrontendInfo(FrontendId frontendId)
+        generates (Result result, FrontendInfo info);
+
+    /**
+     * Get low-noise block downconverter (LNB) IDs.
+     *
+     * It is used by the client to get all available LNBs' IDs.
+     *
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNKNOWN_ERROR if tuning failed for other reasons.
+     * @return frontendIds an array of LnbId for the available LNBs.
+     */
+    getLnbIds() generates (Result result, vec<LnbId> lnbIds);
+
+    /**
+     * Create a new instance of Lnb given a lnbId.
+     *
+     * It is used by the client to create a Lnb instance for satellite Frontend.
+     *
+     * @param lnbId the id of the LNB to be opened.
+     * @return result Result status of the operation.
+     *         SUCCESS if successful,
+     *         UNAVAILABLE if no resource.
+     *         UNKNOWN_ERROR if creation failed for other reasons.
+     * @return lnb the newly created Lnb interface.
+     */
+    openLnbById(LnbId lnbId)
+        generates (Result result, ILnb lnb);
+};
+
diff --git a/tv/tuner/1.0/default/Android.bp b/tv/tuner/1.0/default/Android.bp
new file mode 100644
index 0000000..0ae8bcd
--- /dev/null
+++ b/tv/tuner/1.0/default/Android.bp
@@ -0,0 +1,47 @@
+cc_defaults {
+    name: "tuner_service_defaults",
+    defaults: ["hidl_defaults"],
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: [
+        "Frontend.cpp",
+        "Descrambler.cpp",
+        "Demux.cpp",
+        "Tuner.cpp",
+        "Lnb.cpp",
+        "service.cpp",
+    ],
+
+    compile_multilib: "first",
+
+    shared_libs: [
+        "android.hardware.tv.tuner@1.0",
+        "android.hidl.memory@1.0",
+        "libcutils",
+        "libfmq",
+        "libhidlbase",
+        "libhidlmemory",
+        "liblog",
+        "libstagefright_foundation",
+        "libutils",
+    ],
+    header_libs: [
+        "media_plugin_headers",
+    ],
+}
+
+cc_binary {
+    name: "android.hardware.tv.tuner@1.0-service",
+    vintf_fragments: ["android.hardware.tv.tuner@1.0-service.xml"],
+    defaults: ["tuner_service_defaults"],
+    init_rc: ["android.hardware.tv.tuner@1.0-service.rc"],
+}
+
+cc_binary {
+    name: "android.hardware.tv.tuner@1.0-service-lazy",
+    vintf_fragments: ["android.hardware.tv.tuner@1.0-service-lazy.xml"],
+    overrides: ["android.hardware.tv.tuner@1.0-service"],
+    defaults: ["tuner_service_defaults"],
+    init_rc: ["android.hardware.tv.tuner@1.0-service-lazy.rc"],
+    cflags: ["-DLAZY_SERVICE"],
+}
diff --git a/tv/tuner/1.0/default/Demux.cpp b/tv/tuner/1.0/default/Demux.cpp
new file mode 100644
index 0000000..04382b0
--- /dev/null
+++ b/tv/tuner/1.0/default/Demux.cpp
@@ -0,0 +1,849 @@
+/*
+ * 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 "android.hardware.tv.tuner@1.0-Demux"
+
+#include "Demux.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+#define WAIT_TIMEOUT 3000000000
+
+const std::vector<uint8_t> fakeDataInputBuffer{
+        0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb,
+        0x01, 0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03,
+        0xc5, 0x8b, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06,
+        0x05, 0xff, 0xff, 0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8,
+        0x20, 0xd9, 0x23, 0xee, 0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72,
+        0x65, 0x20, 0x31, 0x34, 0x32, 0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d,
+        0x50, 0x45, 0x47, 0x2d, 0x34, 0x20, 0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63,
+        0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30,
+        0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+        0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f,
+        0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x2d, 0x20,
+        0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x63, 0x61, 0x62, 0x61, 0x63, 0x3d,
+        0x30, 0x20, 0x72, 0x65, 0x66, 0x3d, 0x32, 0x20, 0x64, 0x65, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+        0x3d, 0x31, 0x3a, 0x30, 0x3a, 0x30, 0x20, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x65, 0x3d,
+        0x30, 0x78, 0x31, 0x3a, 0x30, 0x78, 0x31, 0x31, 0x31, 0x20, 0x6d, 0x65, 0x3d, 0x68, 0x65,
+        0x78, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x65, 0x3d, 0x37, 0x20, 0x70, 0x73, 0x79, 0x3d, 0x31,
+        0x20, 0x70, 0x73, 0x79, 0x5f, 0x72, 0x64, 0x3d, 0x31, 0x2e, 0x30, 0x30, 0x3a, 0x30, 0x2e,
+        0x30, 0x30, 0x20, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x3d, 0x31, 0x20,
+        0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x3d, 0x31, 0x36, 0x20, 0x63, 0x68, 0x72,
+        0x6f, 0x6d, 0x61, 0x5f, 0x6d, 0x65, 0x3d, 0x31, 0x20, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x69,
+        0x73, 0x3d, 0x31, 0x20, 0x38, 0x78, 0x38, 0x64, 0x63, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x71,
+        0x6d, 0x3d, 0x30, 0x20, 0x64, 0x65, 0x61, 0x64, 0x7a, 0x6f, 0x6e, 0x65, 0x3d, 0x32, 0x31,
+        0x2c, 0x31, 0x31, 0x20, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x73, 0x6b, 0x69, 0x70, 0x3d,
+        0x31, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x5f, 0x71, 0x70, 0x5f, 0x6f, 0x66, 0x66,
+        0x73, 0x65, 0x74, 0x3d, 0x2d, 0x32, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d,
+        0x36, 0x30, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x61, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x68,
+        0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x35, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x64, 0x5f,
+        0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x30, 0x20, 0x6e, 0x72, 0x3d, 0x30, 0x20,
+        0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x3d, 0x31, 0x20, 0x69, 0x6e, 0x74, 0x65,
+        0x72, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x3d, 0x30, 0x20, 0x62, 0x6c, 0x75, 0x72, 0x61, 0x79,
+        0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
+        0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x3d, 0x30, 0x20,
+        0x62, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3d, 0x30, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68,
+        0x74, 0x70, 0x3d, 0x30, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x3d, 0x32, 0x35, 0x30,
+        0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x3d, 0x32, 0x35, 0x20,
+        0x73, 0x63, 0x65, 0x6e, 0x65,
+};
+
+Demux::Demux(uint32_t demuxId, sp<Tuner> tuner) {
+    mDemuxId = demuxId;
+    mTunerService = tuner;
+}
+
+Demux::~Demux() {}
+
+Return<Result> Demux::setFrontendDataSource(uint32_t frontendId) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (mTunerService == nullptr) {
+        return Result::NOT_INITIALIZED;
+    }
+
+    mFrontend = mTunerService->getFrontendById(frontendId);
+
+    if (mFrontend == nullptr) {
+        return Result::INVALID_STATE;
+    }
+
+    mFrontendSourceFile = mFrontend->getSourceFile();
+
+    mTunerService->setFrontendAsDemuxSource(frontendId, mDemuxId);
+    return startBroadcastInputLoop();
+}
+
+Return<void> Demux::addFilter(DemuxFilterType type, uint32_t bufferSize,
+                              const sp<IDemuxCallback>& cb, addFilter_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    uint32_t filterId;
+
+    if (!mUnusedFilterIds.empty()) {
+        filterId = *mUnusedFilterIds.begin();
+
+        mUnusedFilterIds.erase(filterId);
+    } else {
+        filterId = ++mLastUsedFilterId;
+
+        mDemuxCallbacks.resize(filterId + 1);
+        mFilterMQs.resize(filterId + 1);
+        mFilterEvents.resize(filterId + 1);
+        mFilterEventFlags.resize(filterId + 1);
+        mFilterThreadRunning.resize(filterId + 1);
+        mFilterThreads.resize(filterId + 1);
+        mFilterPids.resize(filterId + 1);
+        mFilterOutputs.resize(filterId + 1);
+    }
+
+    mUsedFilterIds.insert(filterId);
+
+    if ((type != DemuxFilterType::PCR || type != DemuxFilterType::TS) && cb == nullptr) {
+        ALOGW("callback can't be null");
+        _hidl_cb(Result::INVALID_ARGUMENT, filterId);
+        return Void();
+    }
+
+    // Add callback
+    mDemuxCallbacks[filterId] = cb;
+
+    // Mapping from the filter ID to the filter event
+    DemuxFilterEvent event{
+            .filterId = filterId,
+            .filterType = type,
+    };
+    mFilterEvents[filterId] = event;
+
+    if (!createFilterMQ(bufferSize, filterId)) {
+        _hidl_cb(Result::UNKNOWN_ERROR, -1);
+        return Void();
+    }
+
+    _hidl_cb(Result::SUCCESS, filterId);
+    return Void();
+}
+
+Return<void> Demux::getFilterQueueDesc(uint32_t filterId, getFilterQueueDesc_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (mUsedFilterIds.find(filterId) == mUsedFilterIds.end()) {
+        ALOGW("No filter with id: %d exists to get desc", filterId);
+        _hidl_cb(Result::INVALID_ARGUMENT, FilterMQ::Descriptor());
+        return Void();
+    }
+
+    _hidl_cb(Result::SUCCESS, *mFilterMQs[filterId]->getDesc());
+    return Void();
+}
+
+Return<Result> Demux::configureFilter(uint32_t filterId, const DemuxFilterSettings& settings) {
+    ALOGV("%s", __FUNCTION__);
+
+    switch (mFilterEvents[filterId].filterType) {
+        case DemuxFilterType::SECTION:
+            mFilterPids[filterId] = settings.section().tpid;
+            break;
+        case DemuxFilterType::PES:
+            mFilterPids[filterId] = settings.pesData().tpid;
+            break;
+        case DemuxFilterType::TS:
+            mFilterPids[filterId] = settings.ts().tpid;
+            break;
+        case DemuxFilterType::AUDIO:
+            mFilterPids[filterId] = settings.audio().tpid;
+            break;
+        case DemuxFilterType::VIDEO:
+            mFilterPids[filterId] = settings.video().tpid;
+            break;
+        case DemuxFilterType::RECORD:
+            mFilterPids[filterId] = settings.record().tpid;
+            break;
+        case DemuxFilterType::PCR:
+            mFilterPids[filterId] = settings.pcr().tpid;
+            break;
+        default:
+            return Result::UNKNOWN_ERROR;
+    }
+    return Result::SUCCESS;
+}
+
+Return<Result> Demux::startFilter(uint32_t filterId) {
+    ALOGV("%s", __FUNCTION__);
+    Result result;
+
+    if (mUsedFilterIds.find(filterId) == mUsedFilterIds.end()) {
+        ALOGW("No filter with id: %d exists to start filter", filterId);
+        return Result::INVALID_ARGUMENT;
+    }
+
+    result = startFilterLoop(filterId);
+
+    return result;
+}
+
+Return<Result> Demux::stopFilter(uint32_t filterId) {
+    ALOGV("%s", __FUNCTION__);
+
+    mFilterThreadRunning[filterId] = false;
+
+    std::lock_guard<std::mutex> lock(mFilterThreadLock);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Demux::flushFilter(uint32_t /* filterId */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Demux::removeFilter(uint32_t filterId) {
+    ALOGV("%s", __FUNCTION__);
+
+    // resetFilterRecords(filterId);
+    mUsedFilterIds.erase(filterId);
+    mUnusedFilterIds.insert(filterId);
+
+    return Result::SUCCESS;
+}
+
+Return<void> Demux::getAvSyncHwId(uint32_t /* filterId */, getAvSyncHwId_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    AvSyncHwId avSyncHwId = 0;
+
+    _hidl_cb(Result::SUCCESS, avSyncHwId);
+    return Void();
+}
+
+Return<void> Demux::getAvSyncTime(AvSyncHwId /* avSyncHwId */, getAvSyncTime_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    uint64_t avSyncTime = 0;
+
+    _hidl_cb(Result::SUCCESS, avSyncTime);
+    return Void();
+}
+
+Return<Result> Demux::close() {
+    ALOGV("%s", __FUNCTION__);
+
+    set<uint32_t>::iterator it;
+    mInputThread = 0;
+    mOutputThread = 0;
+    mFilterThreads.clear();
+    mUnusedFilterIds.clear();
+    mUsedFilterIds.clear();
+    mDemuxCallbacks.clear();
+    mFilterMQs.clear();
+    mFilterEvents.clear();
+    mFilterEventFlags.clear();
+    mFilterOutputs.clear();
+    mFilterPids.clear();
+    mLastUsedFilterId = -1;
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Demux::addOutput(uint32_t bufferSize, const sp<IDemuxCallback>& cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    // Create a synchronized FMQ that supports blocking read/write
+    std::unique_ptr<FilterMQ> tmpFilterMQ =
+            std::unique_ptr<FilterMQ>(new (std::nothrow) FilterMQ(bufferSize, true));
+    if (!tmpFilterMQ->isValid()) {
+        ALOGW("Failed to create output FMQ");
+        return Result::UNKNOWN_ERROR;
+    }
+
+    mOutputMQ = std::move(tmpFilterMQ);
+
+    if (EventFlag::createEventFlag(mOutputMQ->getEventFlagWord(), &mOutputEventFlag) != OK) {
+        return Result::UNKNOWN_ERROR;
+    }
+
+    mOutputCallback = cb;
+
+    return Result::SUCCESS;
+}
+
+Return<void> Demux::getOutputQueueDesc(getOutputQueueDesc_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (!mOutputMQ) {
+        _hidl_cb(Result::NOT_INITIALIZED, FilterMQ::Descriptor());
+        return Void();
+    }
+
+    _hidl_cb(Result::SUCCESS, *mOutputMQ->getDesc());
+    return Void();
+}
+
+Return<Result> Demux::configureOutput(const DemuxOutputSettings& settings) {
+    ALOGV("%s", __FUNCTION__);
+
+    mOutputConfigured = true;
+    mOutputSettings = settings;
+    return Result::SUCCESS;
+}
+
+Return<Result> Demux::attachOutputFilter(uint32_t /*filterId*/) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Demux::detachOutputFilter(uint32_t /* filterId */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Demux::startOutput() {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Demux::stopOutput() {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Demux::flushOutput() {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Demux::removeOutput() {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Demux::addInput(uint32_t bufferSize, const sp<IDemuxCallback>& cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    // Create a synchronized FMQ that supports blocking read/write
+    std::unique_ptr<FilterMQ> tmpInputMQ =
+            std::unique_ptr<FilterMQ>(new (std::nothrow) FilterMQ(bufferSize, true));
+    if (!tmpInputMQ->isValid()) {
+        ALOGW("Failed to create input FMQ");
+        return Result::UNKNOWN_ERROR;
+    }
+
+    mInputMQ = std::move(tmpInputMQ);
+
+    if (EventFlag::createEventFlag(mInputMQ->getEventFlagWord(), &mInputEventFlag) != OK) {
+        return Result::UNKNOWN_ERROR;
+    }
+
+    mInputCallback = cb;
+
+    return Result::SUCCESS;
+}
+
+Return<void> Demux::getInputQueueDesc(getInputQueueDesc_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (!mInputMQ) {
+        _hidl_cb(Result::NOT_INITIALIZED, FilterMQ::Descriptor());
+        return Void();
+    }
+
+    _hidl_cb(Result::SUCCESS, *mInputMQ->getDesc());
+    return Void();
+}
+
+Return<Result> Demux::configureInput(const DemuxInputSettings& settings) {
+    ALOGV("%s", __FUNCTION__);
+
+    mInputConfigured = true;
+    mInputSettings = settings;
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Demux::startInput() {
+    ALOGV("%s", __FUNCTION__);
+
+    if (!mInputCallback) {
+        return Result::NOT_INITIALIZED;
+    }
+
+    if (!mInputConfigured) {
+        return Result::INVALID_STATE;
+    }
+
+    pthread_create(&mInputThread, NULL, __threadLoopInput, this);
+    pthread_setname_np(mInputThread, "demux_input_waiting_loop");
+
+    // TODO start another thread to send filter status callback to the framework
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Demux::stopInput() {
+    ALOGV("%s", __FUNCTION__);
+
+    mInputThreadRunning = false;
+
+    std::lock_guard<std::mutex> lock(mInputThreadLock);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Demux::flushInput() {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Demux::removeInput() {
+    ALOGV("%s", __FUNCTION__);
+
+    mInputMQ = nullptr;
+
+    return Result::SUCCESS;
+}
+
+Result Demux::startFilterLoop(uint32_t filterId) {
+    struct ThreadArgs* threadArgs = (struct ThreadArgs*)malloc(sizeof(struct ThreadArgs));
+    threadArgs->user = this;
+    threadArgs->filterId = filterId;
+
+    pthread_t mFilterThread;
+    pthread_create(&mFilterThread, NULL, __threadLoopFilter, (void*)threadArgs);
+    mFilterThreads[filterId] = mFilterThread;
+    pthread_setname_np(mFilterThread, "demux_filter_waiting_loop");
+
+    return Result::SUCCESS;
+}
+
+Result Demux::startSectionFilterHandler(uint32_t filterId) {
+    if (mFilterOutputs[filterId].empty()) {
+        return Result::SUCCESS;
+    }
+    if (!writeSectionsAndCreateEvent(filterId, mFilterOutputs[filterId])) {
+        ALOGD("[Demux] filter %d fails to write into FMQ. Ending thread", filterId);
+        return Result::UNKNOWN_ERROR;
+    }
+
+    mFilterOutputs[filterId].clear();
+
+    return Result::SUCCESS;
+}
+
+Result Demux::startPesFilterHandler(uint32_t filterId) {
+    std::lock_guard<std::mutex> lock(mFilterEventLock);
+    DemuxFilterPesEvent pesEvent;
+    if (mFilterOutputs[filterId].empty()) {
+        return Result::SUCCESS;
+    }
+
+    for (int i = 0; i < mFilterOutputs[filterId].size(); i += 188) {
+        uint8_t pusi = mFilterOutputs[filterId][i + 1] & 0x40;
+        uint8_t adaptFieldControl = (mFilterOutputs[filterId][i + 3] & 0x30) >> 4;
+        ALOGD("[Demux] pusi %d, adaptFieldControl %d", pusi, adaptFieldControl);
+        if (pusi && (adaptFieldControl == 0x01)) {
+            vector<uint8_t>::const_iterator first = mFilterOutputs[filterId].begin() + i + 4;
+            vector<uint8_t>::const_iterator last = mFilterOutputs[filterId].begin() + i + 187;
+            vector<uint8_t> filterOutData(first, last);
+            if (!writeDataToFilterMQ(filterOutData, filterId)) {
+                mFilterOutputs[filterId].clear();
+                return Result::INVALID_STATE;
+            }
+            pesEvent = {
+                    // temp dump meta data
+                    .streamId = filterOutData[3],
+                    .dataLength = static_cast<uint16_t>(filterOutData.size()),
+            };
+            int size = mFilterEvents[filterId].events.size();
+            mFilterEvents[filterId].events.resize(size + 1);
+            mFilterEvents[filterId].events[size].pes(pesEvent);
+        }
+    }
+
+    mFilterOutputs[filterId].clear();
+
+    return Result::SUCCESS;
+}
+
+Result Demux::startTsFilterHandler() {
+    // TODO handle starting TS filter
+    return Result::SUCCESS;
+}
+
+Result Demux::startMediaFilterHandler(uint32_t filterId) {
+    DemuxFilterMediaEvent mediaEvent;
+    mediaEvent = {
+            // temp dump meta data
+            .pts = 0,
+            .dataLength = 530,
+            .secureMemory = nullptr,
+    };
+    mFilterEvents[filterId].events.resize(1);
+    mFilterEvents[filterId].events[0].media() = mediaEvent;
+
+    mFilterOutputs[filterId].clear();
+    // TODO handle write FQM for media stream
+    return Result::SUCCESS;
+}
+
+Result Demux::startRecordFilterHandler(uint32_t filterId) {
+    DemuxFilterRecordEvent recordEvent;
+    recordEvent = {
+            // temp dump meta data
+            .tpid = 0,
+            .packetNum = 0,
+    };
+    recordEvent.indexMask.tsIndexMask() = 0x01;
+    mFilterEvents[filterId].events.resize(1);
+    mFilterEvents[filterId].events[0].ts() = recordEvent;
+
+    mFilterOutputs[filterId].clear();
+    return Result::SUCCESS;
+}
+
+Result Demux::startPcrFilterHandler() {
+    // TODO handle starting PCR filter
+    return Result::SUCCESS;
+}
+
+bool Demux::createFilterMQ(uint32_t bufferSize, uint32_t filterId) {
+    ALOGV("%s", __FUNCTION__);
+
+    // Create a synchronized FMQ that supports blocking read/write
+    std::unique_ptr<FilterMQ> tmpFilterMQ =
+            std::unique_ptr<FilterMQ>(new (std::nothrow) FilterMQ(bufferSize, true));
+    if (!tmpFilterMQ->isValid()) {
+        ALOGW("Failed to create FMQ of filter with id: %d", filterId);
+        return false;
+    }
+
+    mFilterMQs[filterId] = std::move(tmpFilterMQ);
+
+    EventFlag* filterEventFlag;
+    if (EventFlag::createEventFlag(mFilterMQs[filterId]->getEventFlagWord(), &filterEventFlag) !=
+        OK) {
+        return false;
+    }
+    mFilterEventFlags[filterId] = filterEventFlag;
+
+    return true;
+}
+
+bool Demux::writeSectionsAndCreateEvent(uint32_t filterId, vector<uint8_t> data) {
+    // TODO check how many sections has been read
+    std::lock_guard<std::mutex> lock(mFilterEventLock);
+    if (!writeDataToFilterMQ(data, filterId)) {
+        return false;
+    }
+    int size = mFilterEvents[filterId].events.size();
+    mFilterEvents[filterId].events.resize(size + 1);
+    DemuxFilterSectionEvent secEvent;
+    secEvent = {
+            // temp dump meta data
+            .tableId = 0,
+            .version = 1,
+            .sectionNum = 1,
+            .dataLength = static_cast<uint16_t>(data.size()),
+    };
+    mFilterEvents[filterId].events[size].section(secEvent);
+    return true;
+}
+
+bool Demux::writeDataToFilterMQ(const std::vector<uint8_t>& data, uint32_t filterId) {
+    std::lock_guard<std::mutex> lock(mWriteLock);
+    if (mFilterMQs[filterId]->write(data.data(), data.size())) {
+        return true;
+    }
+    return false;
+}
+
+bool Demux::readInputFMQ() {
+    // Read input data from the input FMQ
+    int size = mInputMQ->availableToRead();
+    int inputPacketSize = mInputSettings.packetSize;
+    vector<uint8_t> dataOutputBuffer;
+    dataOutputBuffer.resize(inputPacketSize);
+
+    // Dispatch the packet to the PID matching filter output buffer
+    for (int i = 0; i < size / inputPacketSize; i++) {
+        if (!mInputMQ->read(dataOutputBuffer.data(), inputPacketSize)) {
+            return false;
+        }
+        startTsFilter(dataOutputBuffer);
+    }
+
+    return true;
+}
+
+void Demux::startTsFilter(vector<uint8_t> data) {
+    set<uint32_t>::iterator it;
+    for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
+        uint16_t pid = ((data[1] & 0x1f) << 8) | ((data[2] & 0xff));
+        ALOGW("start ts filter pid: %d", pid);
+        if (pid == mFilterPids[*it]) {
+            mFilterOutputs[*it].insert(mFilterOutputs[*it].end(), data.begin(), data.end());
+        }
+    }
+}
+
+bool Demux::startFilterDispatcher() {
+    Result result;
+    set<uint32_t>::iterator it;
+
+    // Handle the output data per filter type
+    for (it = mUsedFilterIds.begin(); it != mUsedFilterIds.end(); it++) {
+        switch (mFilterEvents[*it].filterType) {
+            case DemuxFilterType::SECTION:
+                result = startSectionFilterHandler(*it);
+                break;
+            case DemuxFilterType::PES:
+                result = startPesFilterHandler(*it);
+                break;
+            case DemuxFilterType::TS:
+                result = startTsFilterHandler();
+                break;
+            case DemuxFilterType::AUDIO:
+            case DemuxFilterType::VIDEO:
+                result = startMediaFilterHandler(*it);
+                break;
+            case DemuxFilterType::RECORD:
+                result = startRecordFilterHandler(*it);
+                break;
+            case DemuxFilterType::PCR:
+                result = startPcrFilterHandler();
+                break;
+            default:
+                return false;
+        }
+    }
+
+    return result == Result::SUCCESS;
+}
+
+void* Demux::__threadLoopFilter(void* threadArg) {
+    Demux* const self = static_cast<Demux*>(((struct ThreadArgs*)threadArg)->user);
+    self->filterThreadLoop(((struct ThreadArgs*)threadArg)->filterId);
+    return 0;
+}
+
+void* Demux::__threadLoopInput(void* user) {
+    Demux* const self = static_cast<Demux*>(user);
+    self->inputThreadLoop();
+    return 0;
+}
+
+void Demux::filterThreadLoop(uint32_t filterId) {
+    ALOGD("[Demux] filter %d threadLoop start.", filterId);
+    std::lock_guard<std::mutex> lock(mFilterThreadLock);
+    mFilterThreadRunning[filterId] = true;
+
+    // For the first time of filter output, implementation needs to send the filter
+    // Event Callback without waiting for the DATA_CONSUMED to init the process.
+    while (mFilterThreadRunning[filterId]) {
+        if (mFilterEvents[filterId].events.size() == 0) {
+            ALOGD("[Demux] wait for filter data output.");
+            usleep(1000 * 1000);
+            continue;
+        }
+        // After successfully write, send a callback and wait for the read to be done
+        mDemuxCallbacks[filterId]->onFilterEvent(mFilterEvents[filterId]);
+        mFilterEvents[filterId].events.resize(0);
+        break;
+    }
+
+    while (mFilterThreadRunning[filterId]) {
+        uint32_t efState = 0;
+        // We do not wait for the last round of writen data to be read to finish the thread
+        // because the VTS can verify the reading itself.
+        for (int i = 0; i < SECTION_WRITE_COUNT; i++) {
+            while (mFilterThreadRunning[filterId]) {
+                status_t status = mFilterEventFlags[filterId]->wait(
+                        static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED), &efState,
+                        WAIT_TIMEOUT, true /* retry on spurious wake */);
+                if (status != OK) {
+                    ALOGD("[Demux] wait for data consumed");
+                    continue;
+                }
+                break;
+            }
+
+            if (mDemuxCallbacks[filterId] == nullptr) {
+                ALOGD("[Demux] filter %d does not hava callback. Ending thread", filterId);
+                break;
+            }
+
+            while (mFilterThreadRunning[filterId]) {
+                std::lock_guard<std::mutex> lock(mFilterEventLock);
+                if (mFilterEvents[filterId].events.size() == 0) {
+                    continue;
+                }
+                // After successfully write, send a callback and wait for the read to be done
+                mDemuxCallbacks[filterId]->onFilterEvent(mFilterEvents[filterId]);
+                mFilterEvents[filterId].events.resize(0);
+                break;
+            }
+            // We do not wait for the last read to be done
+            // VTS can verify the read result itself.
+            if (i == SECTION_WRITE_COUNT - 1) {
+                ALOGD("[Demux] filter %d writing done. Ending thread", filterId);
+                break;
+            }
+        }
+        mFilterThreadRunning[filterId] = false;
+    }
+
+    ALOGD("[Demux] filter thread ended.");
+}
+
+void Demux::inputThreadLoop() {
+    ALOGD("[Demux] input threadLoop start.");
+    std::lock_guard<std::mutex> lock(mInputThreadLock);
+    mInputThreadRunning = true;
+
+    while (mInputThreadRunning) {
+        uint32_t efState = 0;
+        status_t status =
+                mInputEventFlag->wait(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY),
+                                      &efState, WAIT_TIMEOUT, true /* retry on spurious wake */);
+        if (status != OK) {
+            ALOGD("[Demux] wait for data ready on the input FMQ");
+            continue;
+        }
+        // Our current implementation filter the data and write it into the filter FMQ immedaitely
+        // after the DATA_READY from the VTS/framework
+        if (!readInputFMQ() || !startFilterDispatcher()) {
+            ALOGD("[Demux] input data failed to be filtered. Ending thread");
+            break;
+        }
+
+        maySendInputStatusCallback();
+    }
+
+    mInputThreadRunning = false;
+    ALOGD("[Demux] input thread ended.");
+}
+
+void Demux::maySendInputStatusCallback() {
+    std::lock_guard<std::mutex> lock(mInputStatusLock);
+    int availableToRead = mInputMQ->availableToRead();
+    int availableToWrite = mInputMQ->availableToWrite();
+
+    DemuxInputStatus newStatus =
+            checkStatusChange(availableToWrite, availableToRead, mInputSettings.highThreshold,
+                              mInputSettings.lowThreshold);
+    if (mIntputStatus != newStatus) {
+        mInputCallback->onInputStatus(newStatus);
+        mIntputStatus = newStatus;
+    }
+}
+
+DemuxInputStatus Demux::checkStatusChange(uint32_t availableToWrite, uint32_t availableToRead,
+                                          uint32_t highThreshold, uint32_t lowThreshold) {
+    if (availableToWrite == 0) {
+        return DemuxInputStatus::SPACE_FULL;
+    } else if (availableToRead > highThreshold) {
+        return DemuxInputStatus::SPACE_ALMOST_FULL;
+    } else if (availableToRead < lowThreshold) {
+        return DemuxInputStatus::SPACE_ALMOST_EMPTY;
+    } else if (availableToRead == 0) {
+        return DemuxInputStatus::SPACE_EMPTY;
+    }
+    return mIntputStatus;
+}
+
+Result Demux::startBroadcastInputLoop() {
+    pthread_create(&mBroadcastInputThread, NULL, __threadLoopBroadcast, this);
+    pthread_setname_np(mBroadcastInputThread, "broadcast_input_thread");
+
+    return Result::SUCCESS;
+}
+
+void* Demux::__threadLoopBroadcast(void* user) {
+    Demux* const self = static_cast<Demux*>(user);
+    self->broadcastInputThreadLoop();
+    return 0;
+}
+
+void Demux::broadcastInputThreadLoop() {
+    std::lock_guard<std::mutex> lock(mBroadcastInputThreadLock);
+    mBroadcastInputThreadRunning = true;
+    mKeepFetchingDataFromFrontend = true;
+
+    // open the stream and get its length
+    std::ifstream inputData(mFrontendSourceFile, std::ifstream::binary);
+    // TODO take the packet size from the frontend setting
+    int packetSize = 188;
+    int writePacketAmount = 6;
+    char* buffer = new char[packetSize];
+    ALOGW("[Demux] broadcast input thread loop start %s", mFrontendSourceFile.c_str());
+    if (!inputData.is_open()) {
+        mBroadcastInputThreadRunning = false;
+        ALOGW("[Demux] Error %s", strerror(errno));
+    }
+
+    while (mBroadcastInputThreadRunning) {
+        // move the stream pointer for packet size * 6 every read until the end
+        while (mKeepFetchingDataFromFrontend) {
+            for (int i = 0; i < writePacketAmount; i++) {
+                inputData.read(buffer, packetSize);
+                if (!inputData) {
+                    mBroadcastInputThreadRunning = false;
+                    break;
+                }
+                // filter and dispatch filter output
+                vector<uint8_t> byteBuffer;
+                byteBuffer.resize(sizeof(buffer));
+                for (int index = 0; index < byteBuffer.size(); index++) {
+                    byteBuffer[index] = static_cast<uint8_t>(buffer[index]);
+                }
+                startTsFilter(byteBuffer);
+                inputData.seekg(packetSize, inputData.cur);
+            }
+            startFilterDispatcher();
+            sleep(1);
+        }
+    }
+
+    ALOGW("[Demux] Broadcast Input thread end.");
+    delete[] buffer;
+    inputData.close();
+}
+
+void Demux::stopBroadcastInput() {
+    mKeepFetchingDataFromFrontend = false;
+    mBroadcastInputThreadRunning = false;
+    std::lock_guard<std::mutex> lock(mBroadcastInputThreadLock);
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/tuner/1.0/default/Demux.h b/tv/tuner/1.0/default/Demux.h
new file mode 100644
index 0000000..e4a4e2b
--- /dev/null
+++ b/tv/tuner/1.0/default/Demux.h
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_TUNER_V1_0_DEMUX_H_
+#define ANDROID_HARDWARE_TV_TUNER_V1_0_DEMUX_H_
+
+#include <android/hardware/tv/tuner/1.0/IDemux.h>
+#include <fmq/MessageQueue.h>
+#include <set>
+#include "Frontend.h"
+#include "Tuner.h"
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::EventFlag;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::MQDescriptorSync;
+using ::android::hardware::tv::tuner::V1_0::IDemux;
+using ::android::hardware::tv::tuner::V1_0::IDemuxCallback;
+using ::android::hardware::tv::tuner::V1_0::Result;
+
+using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+
+class Tuner;
+class Frontend;
+
+class Demux : public IDemux {
+  public:
+    Demux(uint32_t demuxId, sp<Tuner> tuner);
+
+    ~Demux();
+
+    virtual Return<Result> setFrontendDataSource(uint32_t frontendId) override;
+
+    virtual Return<Result> close() override;
+
+    virtual Return<void> addFilter(DemuxFilterType type, uint32_t bufferSize,
+                                   const sp<IDemuxCallback>& cb, addFilter_cb _hidl_cb) override;
+
+    virtual Return<void> getFilterQueueDesc(uint32_t filterId,
+                                            getFilterQueueDesc_cb _hidl_cb) override;
+
+    virtual Return<Result> configureFilter(uint32_t filterId,
+                                           const DemuxFilterSettings& settings) override;
+
+    virtual Return<Result> startFilter(uint32_t filterId) override;
+
+    virtual Return<Result> stopFilter(uint32_t filterId) override;
+
+    virtual Return<Result> flushFilter(uint32_t filterId) override;
+
+    virtual Return<Result> removeFilter(uint32_t filterId) override;
+
+    virtual Return<void> getAvSyncHwId(uint32_t filterId, getAvSyncHwId_cb _hidl_cb) override;
+
+    virtual Return<void> getAvSyncTime(AvSyncHwId avSyncHwId, getAvSyncTime_cb _hidl_cb) override;
+
+    virtual Return<Result> addInput(uint32_t bufferSize, const sp<IDemuxCallback>& cb) override;
+
+    virtual Return<void> getInputQueueDesc(getInputQueueDesc_cb _hidl_cb) override;
+
+    virtual Return<Result> configureInput(const DemuxInputSettings& settings) override;
+
+    virtual Return<Result> startInput() override;
+
+    virtual Return<Result> stopInput() override;
+
+    virtual Return<Result> flushInput() override;
+
+    virtual Return<Result> removeInput() override;
+
+    virtual Return<Result> addOutput(uint32_t bufferSize, const sp<IDemuxCallback>& cb) override;
+
+    virtual Return<void> getOutputQueueDesc(getOutputQueueDesc_cb _hidl_cb) override;
+
+    virtual Return<Result> configureOutput(const DemuxOutputSettings& settings) override;
+
+    virtual Return<Result> attachOutputFilter(uint32_t filterId) override;
+
+    virtual Return<Result> detachOutputFilter(uint32_t filterId) override;
+
+    virtual Return<Result> startOutput() override;
+
+    virtual Return<Result> stopOutput() override;
+
+    virtual Return<Result> flushOutput() override;
+
+    virtual Return<Result> removeOutput() override;
+
+    // Functions interacts with Tuner Service
+    void stopBroadcastInput();
+
+  private:
+    // Tuner service
+    sp<Tuner> mTunerService;
+
+    // Frontend source
+    sp<Frontend> mFrontend;
+    string mFrontendSourceFile;
+
+    // A struct that passes the arguments to a newly created filter thread
+    struct ThreadArgs {
+        Demux* user;
+        uint32_t filterId;
+    };
+
+    /**
+     * Filter handlers to handle the data filtering.
+     * They are also responsible to write the filtered output into the filter FMQ
+     * and update the filterEvent bound with the same filterId.
+     */
+    Result startSectionFilterHandler(uint32_t filterId);
+    Result startPesFilterHandler(uint32_t filterId);
+    Result startTsFilterHandler();
+    Result startMediaFilterHandler(uint32_t filterId);
+    Result startRecordFilterHandler(uint32_t filterId);
+    Result startPcrFilterHandler();
+    Result startFilterLoop(uint32_t filterId);
+    Result startBroadcastInputLoop();
+
+    /**
+     * To create a FilterMQ with the the next available Filter ID.
+     * Creating Event Flag at the same time.
+     * Add the successfully created/saved FilterMQ into the local list.
+     *
+     * Return false is any of the above processes fails.
+     */
+    bool createFilterMQ(uint32_t bufferSize, uint32_t filterId);
+    bool createMQ(FilterMQ* queue, EventFlag* eventFlag, uint32_t bufferSize);
+    void deleteEventFlag();
+    bool writeDataToFilterMQ(const std::vector<uint8_t>& data, uint32_t filterId);
+    bool readDataFromMQ();
+    bool writeSectionsAndCreateEvent(uint32_t filterId, vector<uint8_t> data);
+    void maySendInputStatusCallback();
+    DemuxInputStatus checkStatusChange(uint32_t availableToWrite, uint32_t availableToRead,
+                                       uint32_t highThreshold, uint32_t lowThreshold);
+    /**
+     * A dispatcher to read and dispatch input data to all the started filters.
+     * Each filter handler handles the data filtering/output writing/filterEvent updating.
+     */
+    bool readInputFMQ();
+    void startTsFilter(vector<uint8_t> data);
+    bool startFilterDispatcher();
+    static void* __threadLoopFilter(void* data);
+    static void* __threadLoopInput(void* user);
+    static void* __threadLoopBroadcast(void* user);
+    void filterThreadLoop(uint32_t filterId);
+    void inputThreadLoop();
+    void broadcastInputThreadLoop();
+
+    uint32_t mDemuxId;
+    /**
+     * Record the last used filter id. Initial value is -1.
+     * Filter Id starts with 0.
+     */
+    uint32_t mLastUsedFilterId = -1;
+    /**
+     * Record all the used filter Ids.
+     * Any removed filter id should be removed from this set.
+     */
+    set<uint32_t> mUsedFilterIds;
+    /**
+     * Record all the unused filter Ids within mLastUsedFilterId.
+     * Removed filter Id should be added into this set.
+     * When this set is not empty, ids here should be allocated first
+     * and added into usedFilterIds.
+     */
+    set<uint32_t> mUnusedFilterIds;
+    /**
+     * A list of created FilterMQ ptrs.
+     * The array number is the filter ID.
+     */
+    vector<uint16_t> mFilterPids;
+    vector<vector<uint8_t>> mFilterOutputs;
+    vector<unique_ptr<FilterMQ>> mFilterMQs;
+    vector<EventFlag*> mFilterEventFlags;
+    vector<DemuxFilterEvent> mFilterEvents;
+    unique_ptr<FilterMQ> mInputMQ;
+    unique_ptr<FilterMQ> mOutputMQ;
+    EventFlag* mInputEventFlag;
+    EventFlag* mOutputEventFlag;
+    /**
+     * Demux callbacks used on filter events or IO buffer status
+     */
+    vector<sp<IDemuxCallback>> mDemuxCallbacks;
+    sp<IDemuxCallback> mInputCallback;
+    sp<IDemuxCallback> mOutputCallback;
+    bool mInputConfigured = false;
+    bool mOutputConfigured = false;
+    DemuxInputSettings mInputSettings;
+    DemuxOutputSettings mOutputSettings;
+
+    // Thread handlers
+    pthread_t mInputThread;
+    pthread_t mOutputThread;
+    pthread_t mBroadcastInputThread;
+    vector<pthread_t> mFilterThreads;
+
+    // FMQ status local records
+    DemuxInputStatus mIntputStatus;
+    /**
+     * If a specific filter's writing loop is still running
+     */
+    vector<bool> mFilterThreadRunning;
+    bool mInputThreadRunning;
+    bool mBroadcastInputThreadRunning;
+    bool mKeepFetchingDataFromFrontend;
+    /**
+     * Lock to protect writes to the FMQs
+     */
+    std::mutex mWriteLock;
+    /**
+     * Lock to protect writes to the filter event
+     */
+    // TODO make each filter separate event lock
+    std::mutex mFilterEventLock;
+    /**
+     * Lock to protect writes to the input status
+     */
+    std::mutex mInputStatusLock;
+    std::mutex mBroadcastInputThreadLock;
+    std::mutex mFilterThreadLock;
+    std::mutex mInputThreadLock;
+    /**
+     * How many times a filter should write
+     * TODO make this dynamic/random/can take as a parameter
+     */
+    const uint16_t SECTION_WRITE_COUNT = 10;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TV_TUNER_V1_0_DEMUX_H_
diff --git a/tv/tuner/1.0/default/Descrambler.cpp b/tv/tuner/1.0/default/Descrambler.cpp
new file mode 100644
index 0000000..085f2c8
--- /dev/null
+++ b/tv/tuner/1.0/default/Descrambler.cpp
@@ -0,0 +1,77 @@
+/*
+ * 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 "android.hardware.tv.tuner@1.0-Descrambler"
+
+#include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
+#include <utils/Log.h>
+
+#include "Descrambler.h"
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+Descrambler::Descrambler() {}
+
+Descrambler::~Descrambler() {}
+
+Return<Result> Descrambler::setDemuxSource(uint32_t demuxId) {
+    ALOGV("%s", __FUNCTION__);
+    if (mDemuxSet) {
+        ALOGW("[   WARN   ] Descrambler has already been set with a demux id %d", mSourceDemuxId);
+        return Result::INVALID_STATE;
+    }
+    mDemuxSet = true;
+    mSourceDemuxId = demuxId;
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Descrambler::setKeyToken(const hidl_vec<uint8_t>& /* keyToken */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Descrambler::addPid(uint16_t /* pid */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Descrambler::removePid(uint16_t /* pid */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Descrambler::close() {
+    ALOGV("%s", __FUNCTION__);
+    mDemuxSet = false;
+
+    return Result::SUCCESS;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/tuner/1.0/default/Descrambler.h b/tv/tuner/1.0/default/Descrambler.h
new file mode 100644
index 0000000..436adcf
--- /dev/null
+++ b/tv/tuner/1.0/default/Descrambler.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_TUNER_V1_0_DESCRAMBLER_H_
+#define ANDROID_HARDWARE_TV_TUNER_V1_0_DESCRAMBLER_H_
+
+#include <android/hardware/tv/tuner/1.0/IDescrambler.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::tv::tuner::V1_0::IDescrambler;
+using ::android::hardware::tv::tuner::V1_0::Result;
+
+class Descrambler : public IDescrambler {
+  public:
+    Descrambler();
+
+    virtual Return<Result> setDemuxSource(uint32_t demuxId) override;
+
+    virtual Return<Result> setKeyToken(const hidl_vec<uint8_t>& keyToken) override;
+
+    virtual Return<Result> addPid(uint16_t pid) override;
+
+    virtual Return<Result> removePid(uint16_t pid) override;
+
+    virtual Return<Result> close() override;
+
+  private:
+    virtual ~Descrambler();
+    uint32_t mSourceDemuxId;
+    bool mDemuxSet = false;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TV_TUNER_V1_DESCRAMBLER_H_
diff --git a/tv/tuner/1.0/default/Frontend.cpp b/tv/tuner/1.0/default/Frontend.cpp
new file mode 100644
index 0000000..1e07edd
--- /dev/null
+++ b/tv/tuner/1.0/default/Frontend.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.tv.tuner@1.0-Frontend"
+
+#include "Frontend.h"
+#include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+Frontend::Frontend(FrontendType type, FrontendId id, sp<Tuner> tuner) {
+    mType = type;
+    mId = id;
+    mTunerService = tuner;
+    // Init callback to nullptr
+    mCallback = nullptr;
+}
+
+Frontend::~Frontend() {}
+
+Return<Result> Frontend::close() {
+    ALOGV("%s", __FUNCTION__);
+    // Reset callback
+    mCallback = nullptr;
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Frontend::setCallback(const sp<IFrontendCallback>& callback) {
+    ALOGV("%s", __FUNCTION__);
+    if (callback == nullptr) {
+        ALOGW("[   WARN   ] Set Frontend callback with nullptr");
+        return Result::INVALID_ARGUMENT;
+    }
+
+    mCallback = callback;
+    return Result::SUCCESS;
+}
+
+Return<Result> Frontend::tune(const FrontendSettings& /* settings */) {
+    ALOGV("%s", __FUNCTION__);
+    if (mCallback == nullptr) {
+        ALOGW("[   WARN   ] Frontend callback is not set when tune");
+        return Result::INVALID_STATE;
+    }
+
+    // TODO dynamically allocate file to the source file
+    mSourceStreamFile = FRONTEND_STREAM_FILE;
+
+    mCallback->onEvent(FrontendEventType::LOCKED);
+    return Result::SUCCESS;
+}
+
+Return<Result> Frontend::stopTune() {
+    ALOGV("%s", __FUNCTION__);
+
+    mTunerService->frontendStopTune(mId);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Frontend::scan(const FrontendSettings& /* settings */, FrontendScanType /* type */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Frontend::stopScan() {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<void> Frontend::getStatus(const hidl_vec<FrontendStatusType>& /* statusTypes */,
+                                 getStatus_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    vector<FrontendStatus> statuses;
+    _hidl_cb(Result::SUCCESS, statuses);
+
+    return Void();
+}
+
+Return<Result> Frontend::setLna(bool /* bEnable */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Frontend::setLnb(uint32_t /* lnb */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+FrontendType Frontend::getFrontendType() {
+    return mType;
+}
+
+FrontendId Frontend::getFrontendId() {
+    return mId;
+}
+
+string Frontend::getSourceFile() {
+    return mSourceStreamFile;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/tuner/1.0/default/Frontend.h b/tv/tuner/1.0/default/Frontend.h
new file mode 100644
index 0000000..07fa7b9
--- /dev/null
+++ b/tv/tuner/1.0/default/Frontend.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_TUNER_V1_0_FRONTEND_H_
+#define ANDROID_HARDWARE_TV_TUNER_V1_0_FRONTEND_H_
+
+#include <android/hardware/tv/tuner/1.0/IFrontend.h>
+#include <fstream>
+#include <iostream>
+#include "Tuner.h"
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::tv::tuner::V1_0::FrontendId;
+using ::android::hardware::tv::tuner::V1_0::FrontendType;
+using ::android::hardware::tv::tuner::V1_0::IFrontend;
+using ::android::hardware::tv::tuner::V1_0::IFrontendCallback;
+using ::android::hardware::tv::tuner::V1_0::Result;
+
+class Tuner;
+
+class Frontend : public IFrontend {
+  public:
+    Frontend(FrontendType type, FrontendId id, sp<Tuner> tuner);
+
+    virtual Return<Result> close() override;
+
+    virtual Return<Result> setCallback(const sp<IFrontendCallback>& callback) override;
+
+    virtual Return<Result> tune(const FrontendSettings& settings) override;
+
+    virtual Return<Result> stopTune() override;
+
+    virtual Return<Result> scan(const FrontendSettings& settings, FrontendScanType type) override;
+
+    virtual Return<Result> stopScan() override;
+
+    virtual Return<void> getStatus(const hidl_vec<FrontendStatusType>& statusTypes,
+                                   getStatus_cb _hidl_cb) override;
+
+    virtual Return<Result> setLna(bool bEnable) override;
+
+    virtual Return<Result> setLnb(uint32_t lnb) override;
+
+    FrontendType getFrontendType();
+
+    FrontendId getFrontendId();
+
+    string getSourceFile();
+
+  private:
+    virtual ~Frontend();
+    sp<IFrontendCallback> mCallback;
+    sp<Tuner> mTunerService;
+    FrontendType mType = FrontendType::UNDEFINED;
+    FrontendId mId = 0;
+
+    const string FRONTEND_STREAM_FILE = "/vendor/etc/test1.ts";
+    string mSourceStreamFile;
+    std::ifstream mFrontendData;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TV_TUNER_V1_0_FRONTEND_H_
diff --git a/tv/tuner/1.0/default/Lnb.cpp b/tv/tuner/1.0/default/Lnb.cpp
new file mode 100644
index 0000000..1446f7f
--- /dev/null
+++ b/tv/tuner/1.0/default/Lnb.cpp
@@ -0,0 +1,68 @@
+/*
+ * 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 "android.hardware.tv.tuner@1.0-Lnb"
+
+#include "Lnb.h"
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+Lnb::Lnb() {}
+
+Lnb::~Lnb() {}
+
+Return<Result> Lnb::setVoltage(FrontendLnbVoltage /* voltage */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Lnb::setTone(FrontendLnbTone /* tone */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Lnb::setSatellitePosition(FrontendLnbPosition /* position */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Lnb::sendDiseqcMessage(const hidl_vec<uint8_t>& /* diseqcMessage */) {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+Return<Result> Lnb::close() {
+    ALOGV("%s", __FUNCTION__);
+
+    return Result::SUCCESS;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
\ No newline at end of file
diff --git a/tv/tuner/1.0/default/Lnb.h b/tv/tuner/1.0/default/Lnb.h
new file mode 100644
index 0000000..4c251f7
--- /dev/null
+++ b/tv/tuner/1.0/default/Lnb.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_TUNER_V1_0_LNB_H_
+#define ANDROID_HARDWARE_TV_TUNER_V1_0_LNB_H_
+
+#include <android/hardware/tv/tuner/1.0/ILnb.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::tv::tuner::V1_0::FrontendLnbPosition;
+using ::android::hardware::tv::tuner::V1_0::FrontendLnbTone;
+using ::android::hardware::tv::tuner::V1_0::FrontendLnbVoltage;
+using ::android::hardware::tv::tuner::V1_0::Result;
+
+class Lnb : public ILnb {
+  public:
+    Lnb();
+
+    virtual Return<Result> setVoltage(FrontendLnbVoltage voltage) override;
+
+    virtual Return<Result> setTone(FrontendLnbTone tone) override;
+
+    virtual Return<Result> setSatellitePosition(FrontendLnbPosition position) override;
+
+    virtual Return<Result> sendDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) override;
+
+    virtual Return<Result> close() override;
+
+  private:
+    virtual ~Lnb();
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TV_TUNER_V1_0_LNB_H_
\ No newline at end of file
diff --git a/tv/tuner/1.0/default/OWNERS b/tv/tuner/1.0/default/OWNERS
new file mode 100644
index 0000000..1b3d095
--- /dev/null
+++ b/tv/tuner/1.0/default/OWNERS
@@ -0,0 +1,4 @@
+nchalko@google.com
+amyjojo@google.com
+shubang@google.com
+quxiangfang@google.com
diff --git a/tv/tuner/1.0/default/Tuner.cpp b/tv/tuner/1.0/default/Tuner.cpp
new file mode 100644
index 0000000..f86b28d
--- /dev/null
+++ b/tv/tuner/1.0/default/Tuner.cpp
@@ -0,0 +1,160 @@
+/*
+ * 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 "android.hardware.tv.tuner@1.0-Tuner"
+
+#include "Tuner.h"
+#include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
+#include <utils/Log.h>
+#include "Demux.h"
+#include "Descrambler.h"
+#include "Frontend.h"
+#include "Lnb.h"
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::tv::tuner::V1_0::DemuxId;
+
+Tuner::Tuner() {
+    // Static Frontends array to maintain local frontends information
+    // Array index matches their FrontendId in the default impl
+    mFrontendSize = 8;
+    mFrontends.resize(mFrontendSize);
+    mFrontends[0] = new Frontend(FrontendType::DVBT, 0, this);
+    mFrontends[1] = new Frontend(FrontendType::ATSC, 1, this);
+    mFrontends[2] = new Frontend(FrontendType::DVBC, 2, this);
+    mFrontends[3] = new Frontend(FrontendType::DVBS, 3, this);
+    mFrontends[4] = new Frontend(FrontendType::DVBT, 4, this);
+    mFrontends[5] = new Frontend(FrontendType::ISDBT, 5, this);
+    mFrontends[6] = new Frontend(FrontendType::ANALOG, 6, this);
+    mFrontends[7] = new Frontend(FrontendType::ATSC, 7, this);
+}
+
+Tuner::~Tuner() {}
+
+Return<void> Tuner::getFrontendIds(getFrontendIds_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    vector<FrontendId> frontendIds;
+    frontendIds.resize(mFrontendSize);
+    for (int i = 0; i < mFrontendSize; i++) {
+        frontendIds[i] = mFrontends[i]->getFrontendId();
+    }
+
+    _hidl_cb(Result::SUCCESS, frontendIds);
+    return Void();
+}
+
+Return<void> Tuner::openFrontendById(uint32_t frontendId, openFrontendById_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    if (frontendId >= mFrontendSize || frontendId < 0) {
+        ALOGW("[   WARN   ] Frontend with id %d isn't available", frontendId);
+        _hidl_cb(Result::UNAVAILABLE, nullptr);
+        return Void();
+    }
+
+    _hidl_cb(Result::SUCCESS, mFrontends[frontendId]);
+    return Void();
+}
+
+Return<void> Tuner::openDemux(openDemux_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    DemuxId demuxId = mLastUsedId + 1;
+    mLastUsedId += 1;
+    sp<Demux> demux = new Demux(demuxId, this);
+    mDemuxes[demuxId] = demux;
+
+    _hidl_cb(Result::SUCCESS, demuxId, demux);
+    return Void();
+}
+
+Return<void> Tuner::getDemuxCaps(getDemuxCaps_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    DemuxCapabilities caps;
+
+    _hidl_cb(Result::SUCCESS, caps);
+    return Void();
+}
+
+Return<void> Tuner::openDescrambler(openDescrambler_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    sp<IDescrambler> descrambler = new Descrambler();
+
+    _hidl_cb(Result::SUCCESS, descrambler);
+    return Void();
+}
+
+Return<void> Tuner::getFrontendInfo(FrontendId /* frontendId */, getFrontendInfo_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    FrontendInfo info;
+
+    _hidl_cb(Result::SUCCESS, info);
+    return Void();
+}
+
+Return<void> Tuner::getLnbIds(getLnbIds_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    vector<LnbId> lnbIds;
+
+    _hidl_cb(Result::SUCCESS, lnbIds);
+    return Void();
+}
+
+Return<void> Tuner::openLnbById(LnbId /* lnbId */, openLnbById_cb _hidl_cb) {
+    ALOGV("%s", __FUNCTION__);
+
+    sp<ILnb> lnb = new Lnb();
+
+    _hidl_cb(Result::SUCCESS, lnb);
+    return Void();
+}
+
+sp<Frontend> Tuner::getFrontendById(uint32_t frontendId) {
+    ALOGV("%s", __FUNCTION__);
+
+    return mFrontends[frontendId];
+}
+
+void Tuner::setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId) {
+    mFrontendToDemux[frontendId] = demuxId;
+}
+
+void Tuner::frontendStopTune(uint32_t frontendId) {
+    map<uint32_t, uint32_t>::iterator it = mFrontendToDemux.find(frontendId);
+    uint32_t demuxId;
+    if (it != mFrontendToDemux.end()) {
+        demuxId = it->second;
+        mDemuxes[demuxId]->stopBroadcastInput();
+    }
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
diff --git a/tv/tuner/1.0/default/Tuner.h b/tv/tuner/1.0/default/Tuner.h
new file mode 100644
index 0000000..96da257
--- /dev/null
+++ b/tv/tuner/1.0/default/Tuner.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_TV_TUNER_V1_0_TUNER_H_
+#define ANDROID_HARDWARE_TV_TUNER_V1_0_TUNER_H_
+
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <map>
+#include "Demux.h"
+#include "Frontend.h"
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace tuner {
+namespace V1_0 {
+namespace implementation {
+
+class Frontend;
+class Demux;
+
+class Tuner : public ITuner {
+  public:
+    Tuner();
+    virtual Return<void> getFrontendIds(getFrontendIds_cb _hidl_cb) override;
+
+    virtual Return<void> openFrontendById(uint32_t frontendId,
+                                          openFrontendById_cb _hidl_cb) override;
+
+    virtual Return<void> openDemux(openDemux_cb _hidl_cb) override;
+
+    virtual Return<void> getDemuxCaps(getDemuxCaps_cb _hidl_cb) override;
+
+    virtual Return<void> openDescrambler(openDescrambler_cb _hidl_cb) override;
+
+    virtual Return<void> getFrontendInfo(FrontendId frontendId,
+                                         getFrontendInfo_cb _hidl_cb) override;
+
+    virtual Return<void> getLnbIds(getLnbIds_cb _hidl_cb) override;
+
+    virtual Return<void> openLnbById(LnbId lnbId, openLnbById_cb _hidl_cb) override;
+
+    sp<Frontend> getFrontendById(uint32_t frontendId);
+
+    void setFrontendAsDemuxSource(uint32_t frontendId, uint32_t demuxId);
+
+    void frontendStopTune(uint32_t frontendId);
+
+  private:
+    virtual ~Tuner();
+    // Static mFrontends array to maintain local frontends information
+    vector<sp<Frontend>> mFrontends;
+    std::map<uint32_t, uint32_t> mFrontendToDemux;
+    std::map<uint32_t, sp<Demux>> mDemuxes;
+    // To maintain how many Frontends we have
+    int mFrontendSize;
+    // The last used demux id. Initial value is -1.
+    // First used id will be 0.
+    int mLastUsedId = -1;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace tuner
+}  // namespace tv
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TV_TUNER_V1_0_TUNER_H_
diff --git a/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service-lazy.rc b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service-lazy.rc
new file mode 100644
index 0000000..ad72fae
--- /dev/null
+++ b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service-lazy.rc
@@ -0,0 +1,9 @@
+service vendor.tuner-hal-1-0 /vendor/bin/hw/android.hardware.tv.tuner@1.0-service-lazy
+    interface android.hardware.tv.tuner@1.0::ITuner default
+    oneshot
+    disabled
+    class hal
+    user media
+    group mediadrm drmrpc
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks
\ No newline at end of file
diff --git a/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service-lazy.xml b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service-lazy.xml
new file mode 100644
index 0000000..4bcfe10
--- /dev/null
+++ b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service-lazy.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.tv.tuner</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>ITuner</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
\ No newline at end of file
diff --git a/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.rc b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.rc
new file mode 100644
index 0000000..6d59ed7
--- /dev/null
+++ b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.rc
@@ -0,0 +1,6 @@
+service vendor.tuner-hal-1-0 /vendor/bin/hw/android.hardware.tv.tuner@1.0-service
+    class hal
+    user media
+    group mediadrm drmrpc
+    ioprio rt 4
+    writepid /dev/cpuset/foreground/tasks
\ No newline at end of file
diff --git a/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.xml b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.xml
new file mode 100644
index 0000000..4bcfe10
--- /dev/null
+++ b/tv/tuner/1.0/default/android.hardware.tv.tuner@1.0-service.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.tv.tuner</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>ITuner</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
\ No newline at end of file
diff --git a/tv/tuner/1.0/default/service.cpp b/tv/tuner/1.0/default/service.cpp
new file mode 100644
index 0000000..581d269
--- /dev/null
+++ b/tv/tuner/1.0/default/service.cpp
@@ -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.
+ */
+
+//#define LOG_NDEBUG 0
+#ifdef LAZY_SERVICE
+#define LOG_TAG "android.hardware.tv.tuner@1.0-service-lazy"
+#else
+#define LOG_TAG "android.hardware.tv.tuner@1.0-service"
+#endif
+
+#include <binder/ProcessState.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/LegacySupport.h>
+
+#include "Tuner.h"
+
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::LazyServiceRegistrar;
+using android::hardware::tv::tuner::V1_0::ITuner;
+using android::hardware::tv::tuner::V1_0::implementation::Tuner;
+
+#ifdef LAZY_SERVICE
+const bool kLazyService = true;
+#else
+const bool kLazyService = false;
+#endif
+
+int main() {
+    configureRpcThreadpool(8, true /* callerWillJoin */);
+
+    // Setup hwbinder service
+    android::sp<ITuner> service = new Tuner();
+    android::status_t status;
+    if (kLazyService) {
+        auto serviceRegistrar = std::make_shared<LazyServiceRegistrar>();
+        status = serviceRegistrar->registerService(service);
+    } else {
+        status = service->registerAsService();
+    }
+    LOG_ALWAYS_FATAL_IF(status != android::OK, "Error while registering tuner service: %d", status);
+
+    joinRpcThreadpool();
+    return 0;
+}
diff --git a/tv/tuner/1.0/types.hal b/tv/tuner/1.0/types.hal
new file mode 100644
index 0000000..897818b
--- /dev/null
+++ b/tv/tuner/1.0/types.hal
@@ -0,0 +1,1707 @@
+/*
+ * 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.tv.tuner@1.0;
+
+import android.hidl.safe_union@1.0;
+
+@export
+enum Result : int32_t {
+    SUCCESS,
+    UNAVAILABLE,
+    NOT_INITIALIZED,
+    INVALID_STATE,
+    INVALID_ARGUMENT,
+    OUT_OF_MEMORY,
+    UNKNOWN_ERROR,
+};
+
+/**
+ * Frontend ID.
+ */
+typedef uint32_t FrontendId;
+
+/**
+ *  Frontend Types.
+ */
+@export
+enum FrontendType : uint32_t {
+    UNDEFINED = 0,
+    ANALOG,
+    /* Advanced Television Systems Committee (ATSC) Standard A/72. */
+    ATSC,
+    /* Advanced Television Systems Committee (ATSC 3.0) Standard A/300. */
+    ATSC3,
+    /**
+     * Digital Video Broadcasting - Cable
+     * DVB Cable Frontend Standard ETSI EN 300 468 V1.15.1.
+     */
+    DVBC,
+    /**
+     * Digital Video Broadcasting - Satellite
+     * DVB Satellite Frontend Standard ETSI EN 300 468 V1.15.1 and
+     * ETSI EN 302 307-2 V1.1.1.
+     */
+    DVBS,
+    /**
+     * Digital Video Broadcasting - Terrestrial
+     * DVB Terresttrial Frontend Standard ETSI EN 300 468 V1.15.1 and
+     * ETSI EN 302 755 V1.4.1.
+     */
+    DVBT,
+    /* Integrated Services Digital Broadcasting-Satellite (ISDB-S)
+     * ARIB STD-B20 is technical document of ISDB-S.
+     */
+    ISDBS,
+    /* Integrated Services Digital Broadcasting-Satellite (ISDB-S)
+     * ARIB STD-B44 is technical document of ISDB-S3.
+     */
+    ISDBS3,
+    /* Integrated Services Digital Broadcasting-Terrestrial (ISDB-T or SBTVD)
+     * ABNT NBR 15603 is technical document of ISDB-T.
+     */
+    ISDBT,
+};
+
+/**
+ *  Inner Forward Error Correction type as specified in ETSI EN 300 468 V1.15.1
+ *  and ETSI EN 302 307-2 V1.1.1.
+ */
+@export
+enum FrontendInnerFec : uint64_t {
+    /* Not defined */
+    FEC_UNDEFINED = 0,
+    /* hardware is able to detect and set FEC automatically */
+    AUTO = 1 << 0,
+    /* 1/2 conv. code rate */
+    FEC_1_2 = 1 << 1,
+    /* 1/3 conv. code rate */
+    FEC_1_3 = 1 << 2,
+    /* 1/4 conv. code rate */
+    FEC_1_4 = 1 << 3,
+    /* 1/5 conv. code rate */
+    FEC_1_5 = 1 << 4,
+    /* 2/3 conv. code rate */
+    FEC_2_3 = 1 << 5,
+    /* 2/5 conv. code rate */
+    FEC_2_5 = 1 << 6,
+    /* 2/9 conv. code rate */
+    FEC_2_9 = 1 << 7,
+    /* 3/4 conv. code rate */
+    FEC_3_4 = 1 << 8,
+    /* 3/5 conv. code rate */
+    FEC_3_5 = 1 << 9,
+    /* 4/5 conv. code rate */
+    FEC_4_5 = 1 << 10,
+    /* 4/15 conv. code rate */
+    FEC_4_15 = 1 << 11,
+    /* 5/6 conv. code rate */
+    FEC_5_6 = 1 << 12,
+    /* 5/9 conv. code rate */
+    FEC_5_9 = 1 << 13,
+    /* 6/7 conv. code rate */
+    FEC_6_7 = 1 << 14,
+    /* 7/8 conv. code rate */
+    FEC_7_8 = 1 << 15,
+    /* 7/9 conv. code rate */
+    FEC_7_9 = 1 << 16,
+    /* 7/15 conv. code rate */
+    FEC_7_15 = 1 << 17,
+    /* 8/9 conv. code rate */
+    FEC_8_9 = 1 << 18,
+    /* 8/15 conv. code rate */
+    FEC_8_15 = 1 << 19,
+    /* 9/10 conv. code rate */
+    FEC_9_10 = 1 << 20,
+    /* 9/20 conv. code rate */
+    FEC_9_20 = 1 << 21,
+    /* 11/15 conv. code rate */
+    FEC_11_15 = 1 << 22,
+    /* 11/20 conv. code rate */
+    FEC_11_20 = 1 << 23,
+    /* 11/45 conv. code rate */
+    FEC_11_45 = 1 << 24,
+    /* 13/18 conv. code rate */
+    FEC_13_18 = 1 << 25,
+    /* 13/45 conv. code rate */
+    FEC_13_45 = 1 << 26,
+    /* 14/45 conv. code rate */
+    FEC_14_45 = 1 << 27,
+    /* 23/36 conv. code rate */
+    FEC_23_36 = 1 << 28,
+    /* 25/36 conv. code rate */
+    FEC_25_36 = 1 << 29,
+    /* 26/45 conv. code rate */
+    FEC_26_45 = 1 << 30,
+    /* 28/45 conv. code rate */
+    FEC_28_45 = 1 << 31,
+    /* 29/45 conv. code rate */
+    FEC_29_45 = 1 << 32,
+    /* 31/45 conv. code rate */
+    FEC_31_45 = 1 << 33,
+    /* 32/45 conv. code rate */
+    FEC_32_45 = 1 << 34,
+    /* 77/90 conv. code rate */
+    FEC_77_90 = 1 << 35,
+};
+
+/**
+ *  Modulation Type for ATSC.
+ */
+@export
+enum FrontendAtscModulation : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set modulation automatically */
+    AUTO      = 1 << 0,
+    MOD_8VSB  = 1 << 2,
+    MOD_16VSB = 1 << 3,
+};
+
+/**
+ *  Signal Setting for ATSC Frontend.
+ */
+struct FrontendAtscSettings {
+    /** Signal frequencey in Herhz */
+    uint32_t frequency;
+    FrontendAtscModulation modulation;
+};
+
+/**
+ *  Capabilities for ATSC Frontend.
+ */
+struct FrontendAtscCapabilities {
+    /** Modulation capability */
+    bitfield<FrontendAtscModulation> modulationCap;
+};
+
+/**
+ *  Modulation Type for ATSC3.
+ */
+@export
+enum FrontendAtsc3Modulation : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set modulation automatically */
+    AUTO        = 1 << 0,
+    MOD_QPSK    = 1 << 1,
+    MOD_16QAM   = 1 << 2,
+    MOD_64QAM   = 1 << 3,
+    MOD_256QAM  = 1 << 4,
+    MOD_1024QAM = 1 << 5,
+    MOD_4096QAM = 1 << 6,
+};
+
+/**
+ *  Bandwidth for ATSC3.
+ */
+@export
+enum FrontendAtsc3Bandwidth : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set bandwidth automatically */
+    AUTO = 1 << 0,
+    BANDWIDTH_6MHZ = 1 << 1,
+    BANDWIDTH_7MHZ = 1 << 2,
+    BANDWIDTH_8MHZ = 1 << 3,
+};
+
+/**
+ *  Time Interleave Mode for ATSC3.
+ */
+@export
+enum FrontendAtsc3TimeInterleaveMode : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set TimeInterleaveMode automatically */
+    AUTO = 1 << 0,
+    CTI  = 1 << 1,
+    HTI  = 1 << 2,
+};
+
+/**
+ *  Code Rate for ATSC3.
+ */
+@export
+enum FrontendAtsc3CodeRate : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set Coderate automatically */
+    AUTO     = 1 << 0,
+    CODERATE_2_15      = 1 << 1,
+    CODERATE_3_15      = 1 << 2,
+    CODERATE_4_15      = 1 << 3,
+    CODERATE_5_15      = 1 << 4,
+    CODERATE_6_15      = 1 << 5,
+    CODERATE_7_15      = 1 << 6,
+    CODERATE_8_15      = 1 << 7,
+    CODERATE_9_15      = 1 << 8,
+    CODERATE_10_15     = 1 << 9,
+    CODERATE_11_15     = 1 << 10,
+    CODERATE_12_15     = 1 << 11,
+    CODERATE_13_15     = 1 << 12,
+};
+
+/**
+ *  Forward Error Correction (FEC) for ATSC3.
+ */
+@export
+enum FrontendAtsc3Fec : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set FEC automatically */
+    AUTO     = 1 << 0,
+    BCH_LDPC_16K = 1 << 1,
+    BCH_LDPC_64K = 1 << 2,
+    CRC_LDPC_16K = 1 << 3,
+    CRC_LDPC_64K = 1 << 4,
+    LDPC_16K     = 1 << 5,
+    LDPC_64K     = 1 << 6,
+};
+
+/**
+ *  Demodulator Output Format for an ATSC3 Frontend.
+ */
+@export
+enum FrontendAtsc3DemodOutputFormat : uint8_t {
+    /** Dummy. Scan uses this. */
+    UNDEFINED = 0,
+    /** ALP format. Typically used in US region. */
+    ATSC3_LINKLAYER_PACKET = 1 << 0,
+    /** BaseBand packet format. Typically used in Korea region. */
+    BASEBAND_PACKET        = 1 << 1,
+};
+
+/**
+ *  PLP basis Signal Settings for an ATSC3 Frontend.
+ */
+struct FrontendAtsc3PlpSettings {
+    uint8_t plpId;
+    FrontendAtsc3Modulation modulation;
+    FrontendAtsc3TimeInterleaveMode interleaveMode;
+    FrontendAtsc3CodeRate codeRate;
+    FrontendAtsc3Fec fec;
+};
+
+/**
+ *  Signal Settings for an ATSC3 Frontend.
+ */
+struct FrontendAtsc3Settings {
+    /** Signal frequency in Hertz */
+    uint32_t frequency;
+    /** Bandwidth of tuning band. */
+    FrontendAtsc3Bandwidth bandwidth;
+    FrontendAtsc3DemodOutputFormat demodOutputFormat;
+    vec<FrontendAtsc3PlpSettings> plpSettings;
+};
+
+/**
+ *  Capabilities for ATSC3 Frontend.
+ */
+struct FrontendAtsc3Capabilities {
+    /** Bandwidth capability */
+    bitfield<FrontendAtsc3Bandwidth> bandwidthCap;
+    /** Modulation capability */
+    bitfield<FrontendAtsc3Modulation> modulationCap;
+    /** TimeInterleaveMode capability */
+    bitfield<FrontendAtsc3TimeInterleaveMode> timeInterleaveModeCap;
+    /** CodeRate capability */
+    bitfield<FrontendAtsc3CodeRate> codeRateCap;
+    /** FEC capability */
+    bitfield<FrontendAtsc3Fec> fecCap;
+    /** Demodulator Output Format capability */
+    bitfield<FrontendAtsc3DemodOutputFormat> demodOutputFormatCap;
+};
+
+/**
+ *  Modulation Type for DVBS.
+ */
+@export
+enum FrontendDvbsModulation : int32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set Modulation automatically */
+    AUTO = 1 << 0,
+    MOD_QPSK = 1 << 1,
+    MOD_8PSK = 1 << 2,
+    MOD_16QAM = 1 << 3,
+    MOD_16PSK = 1 << 4,
+    MOD_32PSK = 1 << 5,
+    MOD_ACM = 1 << 6,
+    MOD_8APSK = 1 << 7,
+    MOD_16APSK = 1 << 8,
+    MOD_32APSK = 1 << 9,
+    MOD_64APSK = 1 << 10,
+    MOD_128APSK = 1 << 11,
+    MOD_256APSK = 1 << 12,
+    /** Reserved for Proprietary modulation */
+    MOD_RESERVED = 1 << 13,
+};
+
+/**
+ *  Roll Off value for DVBS.
+ */
+@export
+enum FrontendDvbsRolloff : uint32_t {
+    UNDEFINED,
+    ROLLOFF_0_35,
+    ROLLOFF_0_25,
+    ROLLOFF_0_20,
+    ROLLOFF_0_15,
+    ROLLOFF_0_10,
+    ROLLOFF_0_5,
+};
+
+/**
+ *  Pilot mode for DVBS.
+ */
+@export
+enum FrontendDvbsPilot : uint32_t {
+    UNDEFINED,
+    ON,
+    OFF,
+    AUTO,
+};
+
+/**
+ *  Code Rate for DVBS.
+ */
+struct FrontendDvbsCodeRate {
+    FrontendInnerFec fec;
+    bool isLinear;
+    /* true if enable short frame */
+    bool isShortFrames;
+    /* bits number in 1000 symbol. 0 if use the default. */
+    uint32_t bitsPer1000Symbol;
+};
+
+/**
+ *  Sub standards in DVBS.
+ */
+@export
+enum FrontendDvbsStandard : uint8_t {
+    AUTO = 1 << 0,
+    S = 1 << 1,
+    S2 = 1 << 2,
+    S2X = 1 << 3,
+};
+
+/**
+ *  Signal Settings for an DVBS Frontend.
+ */
+struct FrontendDvbsSettings {
+    /** Signal frequency in Hertz */
+    uint32_t frequency;
+    FrontendDvbsModulation modulation;
+    FrontendDvbsCodeRate coderate;
+    /** Symbols per second */
+    uint32_t symbolRate;
+    FrontendDvbsRolloff rolloff;
+    FrontendDvbsPilot pilot;
+    uint32_t inputStreamId;
+    FrontendDvbsStandard standard;
+};
+
+/**
+ *  Capabilities for DVBS Frontend.
+ */
+struct FrontendDvbsCapabilities {
+    bitfield<FrontendDvbsModulation> modulationCap;
+    bitfield<FrontendInnerFec> innerfecCap;
+    bitfield<FrontendDvbsStandard>  standard;
+};
+
+/**
+ *  Modulation Type for DVBC.
+ */
+@export
+enum FrontendDvbcModulation : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set Modulation automatically */
+    AUTO = 1 << 0,
+    MOD_16QAM = 1 << 1,
+    MOD_32QAM = 1 << 2,
+    MOD_64QAM = 1 << 3,
+    MOD_128QAM = 1 << 4,
+    MOD_256QAM = 1 << 5,
+};
+
+/**
+ *  Outer Forward Error Correction (FEC) Type for DVBC.
+ */
+@export
+enum FrontendDvbcOuterFec : uint32_t {
+    UNDEFINED = 0,
+    OUTER_FEC_NONE,
+    OUTER_FEC_RS,
+};
+
+/**
+ *   Annex Type for DVBC.
+ */
+@export
+enum FrontendDvbcAnnex : uint8_t {
+    UNDEFINED = 0,
+    A = 1 << 0,
+    B = 1 << 1,
+    C = 1 << 2,
+};
+
+/**
+ *   Spectral Inversion Type for DVBC.
+ */
+@export
+enum FrontendDvbcSpectralInversion : uint32_t {
+    UNDEFINED,
+    NORMAL,
+    INVERTED,
+};
+
+/**
+ *  Signal Settings for an DVBC Frontend.
+ */
+struct FrontendDvbcSettings {
+    /** Signal frequency in Hertz */
+    uint32_t frequency;
+    FrontendDvbcModulation modulation;
+    FrontendInnerFec fec;
+    /** Symbols per second */
+    uint32_t symbolRate;
+    FrontendDvbcOuterFec outerFec;
+    FrontendDvbcAnnex annex;
+    FrontendDvbcSpectralInversion spectralInversion;
+};
+
+/**
+ *  Capabilities for DVBC Frontend.
+ */
+struct FrontendDvbcCapabilities {
+    bitfield<FrontendDvbcModulation> modulationCap;
+    bitfield<FrontendInnerFec> fecCap;
+    bitfield<FrontendDvbcAnnex> annexCap;
+};
+
+/**
+ *  Bandwidth Type for DVBT.
+ */
+@export
+enum FrontendDvbtBandwidth : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set Bandwidth automatically */
+    AUTO = 1 << 0,
+    BANDWIDTH_8MHZ = 1 << 1,
+    BANDWIDTH_7MHZ = 1 << 2,
+    BANDWIDTH_6MHZ = 1 << 3,
+    BANDWIDTH_5MHZ = 1 << 4,
+    BANDWIDTH_1_7MHZ = 1 << 5,
+    BANDWIDTH_10MHZ = 1 << 6,
+};
+
+/**
+ *  Constellation Type for DVBT.
+ */
+@export
+enum FrontendDvbtConstellation : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set Constellation automatically */
+    AUTO = 1 << 0,
+    CONSTELLATION_QPSK = 1 << 1,
+    CONSTELLATION_16QAM = 1 << 2,
+    CONSTELLATION_64QAM = 1 << 3,
+    CONSTELLATION_256QAM = 1 << 4,
+};
+
+/**
+ *  Hierarchy Type for DVBT.
+ */
+@export
+enum FrontendDvbtHierarchy : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set Hierarchy automatically */
+    AUTO = 1 << 0,
+    HIERARCHY_NON_NATIVE = 1 << 1,
+    HIERARCHY_1_NATIVE = 1 << 2,
+    HIERARCHY_2_NATIVE = 1 << 3,
+    HIERARCHY_4_NATIVE = 1 << 4,
+    HIERARCHY_NON_INDEPTH = 1 << 5,
+    HIERARCHY_1_INDEPTH = 1 << 6,
+    HIERARCHY_2_INDEPTH = 1 << 7,
+    HIERARCHY_4_INDEPTH = 1 << 8,
+};
+
+/**
+ *  Hierarchy Type for DVBT.
+ */
+@export
+enum FrontendDvbtCoderate : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set Hierarchy automatically */
+    AUTO = 1 << 0,
+    CODERATE_1_2 = 1 << 1,
+    CODERATE_2_3 = 1 << 2,
+    CODERATE_3_4 = 1 << 3,
+    CODERATE_5_6 = 1 << 4,
+    CODERATE_7_8 = 1 << 5,
+    CODERATE_3_5 = 1 << 6,
+    CODERATE_4_5 = 1 << 7,
+    CODERATE_6_7 = 1 << 8,
+    CODERATE_8_9 = 1 << 9,
+};
+
+/**
+ *  Guard Interval Type for DVBT.
+ */
+@export
+enum FrontendDvbtGuardInterval : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set Guard Interval automatically */
+    AUTO = 1 << 0,
+    INTERVAL_1_32 = 1 << 1,
+    INTERVAL_1_16 = 1 << 2,
+    INTERVAL_1_8 = 1 << 3,
+    INTERVAL_1_4 = 1 << 4,
+    INTERVAL_1_128 = 1 << 5,
+    INTERVAL_19_128 = 1 << 6,
+    INTERVAL_19_256 = 1 << 7,
+};
+
+/**
+ *  Transmission Mode for DVBT.
+ */
+@export
+enum FrontendDvbtTransmissionMode : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set Transmission Mode automatically */
+    AUTO = 1 << 0,
+    MODE_2K = 1 << 1,
+    MODE_8K = 1 << 2,
+    MODE_4K = 1 << 3,
+    MODE_1K = 1 << 4,
+    MODE_16K = 1 << 5,
+    MODE_32K = 1 << 6,
+};
+
+/**
+ *   Physical Layer Pipe (PLP) Mode for DVBT.
+ */
+enum FrontendDvbtPlpMode : uint32_t {
+    UNDEFINED,
+    AUTO,
+    MANUAL,
+};
+
+/**
+ *  Sub standards in DVBT.
+ */
+@export
+enum FrontendDvbtStandard : uint8_t {
+    AUTO = 1 << 0,
+    T = 1 << 1,
+    T2 = 1 << 2,
+};
+
+/**
+ *  Signal Setting for DVBT Frontend.
+ */
+struct FrontendDvbtSettings {
+    /** Signal frequencey in Herhz */
+    uint32_t frequency;
+    FrontendDvbtTransmissionMode transmissionMode;
+    FrontendDvbtBandwidth bandwidth;
+    FrontendDvbtConstellation constellation;
+    FrontendDvbtHierarchy hierarchy;
+    /** Code Rate for High Priority level */
+    FrontendDvbtCoderate hpCoderate;
+    /** Code Rate for Low Priority level */
+    FrontendDvbtCoderate lpCoderate;
+    FrontendDvbtGuardInterval guardInterval;
+    bool isHighPriority;
+    FrontendDvbtStandard standard;
+    bool isMiso;
+    FrontendDvbtPlpMode plpMode;
+    /** Physical Layer Pipe (PLP) Id */
+    uint8_t plpId;
+    /** Group Id for Physical Layer Pipe (PLP) */
+    uint8_t plpGroupId;
+};
+
+/**
+ *  Capabilities for DVBT Frontend.
+ */
+struct FrontendDvbtCapabilities {
+    bitfield<FrontendDvbtTransmissionMode> transmissionModeCap;
+    bitfield<FrontendDvbtBandwidth> bandwidthCap;
+    bitfield<FrontendDvbtConstellation> constellationCap;
+    bitfield<FrontendDvbtCoderate> coderateCap;
+    bitfield<FrontendDvbtHierarchy> hierarchyCap;
+    bitfield<FrontendDvbtGuardInterval> guardIntervalCap;
+    bool isT2Supported;
+    bool isMisoSupported;
+};
+
+/**
+ *  Roll Off Type for ISDBS.
+ */
+@export
+enum FrontendIsdbsRolloff : uint32_t {
+    UNDEFINED,
+    ROLLOFF_0_35,
+};
+
+/**
+ *  Modulaltion Type for ISDBS.
+ */
+@export
+enum FrontendIsdbsModulation : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set Modulation automatically */
+    AUTO      = 1 << 0,
+    MOD_BPSK      = 1 << 1,
+    MOD_QPSK      = 1 << 2,
+    MOD_TC8PSK    = 1 << 3,
+};
+
+/**
+ *  Code Rate Type for ISDBS.
+ */
+@export
+enum FrontendIsdbsCoderate : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set Code Rate automatically */
+    AUTO      = 1 << 0,
+    CODERATE_1_2       = 1 << 1,
+    CODERATE_2_3       = 1 << 2,
+    CODERATE_3_4       = 1 << 3,
+    CODERATE_5_6       = 1 << 4,
+    CODERATE_7_8       = 1 << 5,
+};
+
+/**
+ *  Stream Id Type for ISDBS.
+ */
+@export
+enum FrontendIsdbsStreamIdType : uint32_t {
+    STREAM_ID,
+    RELATIVE_STREAM_NUMBER,
+};
+
+/**
+ *  Signal Setting for ISDBS Frontend.
+ */
+struct FrontendIsdbsSettings {
+    /** Signal frequency in Hertz */
+    uint32_t frequency;
+    uint16_t streamId;
+    FrontendIsdbsStreamIdType streamIdType;
+    FrontendIsdbsModulation modulation;
+    FrontendIsdbsCoderate coderate;
+    /** Symbols per second */
+    uint32_t symbolRate;
+    FrontendIsdbsRolloff rolloff;
+};
+
+/**
+ *  Capabilities for ISDBS Frontend.
+ */
+struct FrontendIsdbsCapabilities {
+    bitfield<FrontendIsdbsModulation> modulationCap;
+    bitfield<FrontendIsdbsCoderate> coderateCap;
+};
+
+/**
+ *  Roll of Type for ISDBS3.
+ */
+@export
+enum FrontendIsdbs3Rolloff : uint32_t {
+    UNDEFINED,
+    ROLLOFF_0_03,
+};
+
+/**
+ *  Modulaltion Type for ISDBS3.
+ */
+@export
+enum FrontendIsdbs3Modulation : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set Modulation automatically */
+    AUTO      = 1 << 5,
+    MOD_BPSK      = 1 << 1,
+    MOD_QPSK      = 1 << 2,
+    MOD_8PSK      = 1 << 3,
+    MOD_16APSK    = 1 << 4,
+    MOD_32APSK    = 1 << 5,
+};
+
+/**
+ *  Code Rate Type for ISDBS3.
+ */
+@export
+enum FrontendIsdbs3Coderate : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set Code Rate automatically */
+    AUTO      = 1 << 0,
+    CODERATE_1_3       = 1 << 1,
+    CODERATE_2_5       = 1 << 2,
+    CODERATE_1_2       = 1 << 3,
+    CODERATE_3_5       = 1 << 4,
+    CODERATE_2_3       = 1 << 5,
+    CODERATE_3_4       = 1 << 6,
+    CODERATE_7_9       = 1 << 7,
+    CODERATE_4_5       = 1 << 8,
+    CODERATE_5_6       = 1 << 9,
+    CODERATE_7_8       = 1 << 10,
+    CODERATE_9_10      = 1 << 11,
+};
+
+/**
+ *  Signal Setting for ISDBS3 Frontend.
+ */
+struct FrontendIsdbs3Settings {
+    /** Signal frequency in Hertz */
+    uint32_t frequency;
+    uint16_t streamId;
+    FrontendIsdbsStreamIdType streamIdType;
+    FrontendIsdbs3Modulation modulation;
+    FrontendIsdbs3Coderate coderate;
+    /** Symbols per second */
+    uint32_t symbolRate;
+    FrontendIsdbs3Rolloff rolloff;
+};
+
+/**
+ *  Capabilities for ISDBS3 Frontend.
+ */
+struct FrontendIsdbs3Capabilities {
+    bitfield<FrontendIsdbs3Modulation> modulationCap;
+    bitfield<FrontendIsdbs3Coderate> coderateCap;
+};
+
+/**
+ *   Mode for ISDBT.
+ */
+@export
+enum FrontendIsdbtMode : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set Mode automatically */
+    AUTO = 1 << 0,
+    MODE_1 = 1 << 1,
+    MODE_2 = 1 << 2,
+    MODE_3 = 1 << 3,
+};
+
+/**
+ *   Bandwidth for ISDBT.
+ */
+@export
+enum FrontendIsdbtBandwidth : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set Bandwidth automatically */
+    AUTO = 1 << 0,
+    BANDWIDTH_8MHZ = 1 << 1,
+    BANDWIDTH_7MHZ = 1 << 2,
+    BANDWIDTH_6MHZ = 1 << 3,
+};
+
+/**
+ *   Modulation for ISDBT.
+ */
+@export
+enum FrontendIsdbtModulation : uint32_t {
+    UNDEFINED = 0,
+    /** hardware is able to detect and set Modulation automatically */
+    AUTO = 1 << 0,
+    MOD_DQPSK = 1 << 1,
+    MOD_QPSK = 1 << 2,
+    MOD_16QAM = 1 << 3,
+    MOD_64QAM = 1 << 4,
+};
+
+/** Code Rate for ISDBT. */
+typedef FrontendDvbtCoderate FrontendIsdbtCoderate;
+
+/** Guard Interval for ISDBT. */
+typedef FrontendDvbtGuardInterval FrontendIsdbtGuardInterval;
+
+/**
+ *  Signal Setting for ISDBT Frontend.
+ */
+struct FrontendIsdbtSettings {
+    /** Signal frequency in Hertz */
+    uint32_t frequency;
+    FrontendIsdbtModulation modulation;
+    FrontendIsdbtBandwidth bandwidth;
+    FrontendIsdbtMode mode;
+    FrontendIsdbtCoderate coderate;
+    FrontendIsdbtGuardInterval guardInterval;
+    uint32_t serviceAreaId;
+};
+
+/**
+ *  Capabilities for ISDBT Frontend.
+ */
+struct FrontendIsdbtCapabilities {
+    bitfield<FrontendIsdbtMode> modeCap;
+    bitfield<FrontendIsdbtBandwidth> bandwidthCap;
+    bitfield<FrontendIsdbtModulation> constellationCap;
+    bitfield<FrontendIsdbtCoderate> coderateCap;
+    bitfield<FrontendIsdbtGuardInterval> guardIntervalCap;
+};
+
+/**
+ *   Signal Type for Analog Frontend.
+ */
+@export
+enum FrontendAnalogType : uint32_t {
+    UNDEFINED = 0,
+    PAL = 1 << 0,
+    SECAM = 1 << 1,
+    NTSC = 1 << 2,
+};
+
+/**
+ *   Standard Interchange Format (SIF) for Analog Frontend.
+ */
+@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,
+};
+
+/**
+ *  Signal Setting for Analog Frontend.
+ */
+struct FrontendAnalogSettings {
+    /** Signal frequency in Hertz */
+    uint32_t frequency;
+    FrontendAnalogType type;
+    FrontendAnalogSifStandard sifStandard;
+};
+
+/**
+ *  Capabilities for Analog Frontend.
+ */
+struct FrontendAnalogCapabilities {
+    bitfield<FrontendAnalogType> typeCap;
+    bitfield<FrontendAnalogSifStandard> sifStandardCap;
+};
+
+/**
+ *  Signal Setting for Frontend.
+ */
+safe_union FrontendSettings {
+    FrontendAnalogSettings analog;
+    FrontendAtscSettings atsc;
+    FrontendAtsc3Settings atsc3;
+    FrontendDvbsSettings dvbs;
+    FrontendDvbcSettings dvbc;
+    FrontendDvbtSettings dvbt;
+    FrontendIsdbsSettings isdbs;
+    FrontendIsdbs3Settings isdbs3;
+    FrontendIsdbtSettings isdbt;
+};
+
+/**
+ *  Scan type for Frontend.
+ */
+enum FrontendScanType : uint32_t {
+    SCAN_UNDEFINED = 0,
+    SCAN_AUTO = 1 << 0,
+    SCAN_BLIND = 1 << 1,
+};
+
+/**
+ *  Scan Message Type for Frontend.
+ */
+enum FrontendScanMessageType : uint32_t {
+    /** Scan locked the signal. */
+    LOCKED,
+    /** Scan stopped. */
+    END,
+    /** Scan progress report. */
+    PROGRESS_PERCENT,
+    /** Locked frequency report. */
+    FREQUENCY,
+    /** Locked symbol rate. */
+    SYMBOL_RATE,
+    /** Locked Plp Ids for DVBT2 frontend. */
+    PLP_IDS,
+    /** Locked group Ids for DVBT2 frontend. */
+    GROUP_IDS,
+    /** Stream Ids. */
+    INPUT_STREAM_IDS,
+    /** Locked signal stardard.  */
+    STANDARD,
+    /** PLP status in a tuned frequency band for ATSC3 frontend. */
+    ATSC3_PLP_INFO,
+};
+
+/**
+ *  ATSC3.0 PLP information for scan
+ */
+struct FrontendScanAtsc3PlpInfo {
+    uint8_t plpId;
+    bool bLlsFlag;
+};
+
+/**
+ *  Scan Message for Frontend.
+ */
+safe_union FrontendScanMessage {
+    bool islocked;
+    bool isEnd;
+    /** scan progress percent (0..100) */
+    uint8_t progressPercent;
+    /** Signal frequency in Hertz */
+    uint32_t frequency;
+    /** Symbols per second */
+    uint32_t symbolRate;
+    vec<uint8_t> plpIds;
+    vec<uint8_t> groupIds;
+    vec<uint16_t> inputStreamIds;
+    safe_union standard {
+        FrontendDvbsStandard sStd;
+        FrontendDvbtStandard tStd;
+    } std;
+    /** A list of PLP status in a tuned frequency band for ATSC3 frontend. */
+    vec<FrontendScanAtsc3PlpInfo> atsc3PlpInfos;
+};
+
+/**
+ * Frontend Event Type.
+ */
+@export
+enum FrontendEventType : uint32_t {
+    /**
+     * If frontend locked the signal which is specified by tune method, HAL sends
+     * Locked event.
+     */
+    LOCKED,
+    /**
+     * If frontend can't locked the signal which is specified by tune method,
+     * HAL sends NO_SIGNAL event.
+     */
+    NO_SIGNAL,
+    /**
+     * If frontend detect that the locked signal get lost, HAL sends LOST_LOCK
+     * event.
+     */
+    LOST_LOCK,
+    /**
+     * If frontend detect that incoming Diseqc message is overflow.
+     */
+    DISEQC_RX_OVERFLOW,
+    /**
+     * If frontend detect that outgoing Diseqc message isn't delivered on time.
+     */
+    DISEQC_RX_TIMEOUT,
+    /**
+     * If frontend detect that the incoming Diseqc message has parity error.
+     */
+    DISEQC_RX_PARITY_ERROR,
+    /**
+     * If frontend detect that the LNB is overload.
+     */
+    LNB_OVERLOAD,
+};
+
+/**
+ * Frontend Status Type.
+ */
+@export
+enum FrontendStatusType : uint32_t {
+    /** Lock status for Demod. */
+    DEMOD_LOCK,
+    /** Signal to Noise Ratio. */
+    SNR,
+    /** Bit Error Ratio. */
+    BER,
+    /** Packages Error Ratio. */
+    PER,
+    /** Bit Error Ratio before FEC. */
+    PRE_BER,
+    /*
+     * Signal Quality (0..100). Good data over total data in percent can be
+     * used as a way to present Signal Quality.
+     */
+    SIGNAL_QUALITY,
+    /** Signal Strength. */
+    SIGNAL_STRENGTH,
+    /** Symbol Rate. */
+    SYMBOL_RATE,
+    /** Forward Error Correction Type. */
+    FEC,
+    /** Modulation Type. */
+    MODULATION,
+    /** Spectral Inversion Type. */
+    SPECTRAL,
+    /** LNB Voltage. */
+    LNB_VOLTAGE,
+    /** Physical Layer Pipe ID. */
+    PLP_ID,
+    /** Status for Emergency Warning Broadcasting System. */
+    EWBS,
+    /** Automatic Gain Control. */
+    AGC,
+    /** Low Noise Amplifier. */
+    LNA,
+    /** Lock status for stream. */
+    STREAM_LOCK,
+    /** Error status by layer. */
+    LAYER_ERROR,
+    /** CN value by VBER. */
+    VBER_CN,
+    /** CN value by LBER. */
+    LBER_CN,
+    /** CN value by XER. */
+    XER_CN,
+    /** Moduration Error Ratio. */
+    MER,
+    /** Difference between tuning frequency and actual locked frequency. */
+    FREQ_OFFSET,
+    /* Hierarchy for DVBT. */
+    HIERARCHY,
+    /** Lock status for RF. */
+    RF_LOCK,
+    /** PLP information in a frequency band for ATSC3.0 frontend. */
+    ATSC3_PLP_INFO,
+};
+
+/**
+ * Status for each tuning PLPs
+ */
+struct FrontendStatusAtsc3PlpInfo {
+    /** PLP Id value. */
+    uint8_t plpId;
+    /** Demod Lock/Unlock status of this particular PLP. */
+    bool isLocked;
+    /** Uncorrectable Error Counts (UEC) of this particular PLP since last tune operation. */
+    uint32_t uec;
+};
+
+
+/**
+ * Modulation Type for Frontend's status.
+ */
+safe_union FrontendModulationStatus {
+    FrontendDvbcModulation dvbc;
+    FrontendDvbsModulation dvbs;
+    FrontendIsdbsModulation isdbs;
+    FrontendIsdbs3Modulation isdbs3;
+    FrontendIsdbtModulation isdbt;
+};
+
+/**
+ *  The status for Frontend.
+ */
+safe_union FrontendStatus {
+    /** Lock status for Demod in True/False. */
+    bool isDemodLocked;
+    /** SNR value measured by 0.001 dB. */
+    int32_t snr;
+    /** The number of error bit per 1 billion bits. */
+    uint32_t ber;
+    /** The number of error package per 1 billion packages. */
+    uint32_t per;
+    /** The number of error bit per 1 billion bits before FEC. */
+    uint32_t preBer;
+    /** Signal Quality in percent. */
+    uint32_t signalQuality;
+    /** Signal Strength measured by 0.001 dBm. */
+    int32_t signalStrength;
+    /** Symbols per second */
+    uint32_t symbolRate;
+    FrontendInnerFec innerFec;
+    FrontendModulationStatus modulation;
+    FrontendDvbcSpectralInversion inversion;
+    FrontendLnbVoltage lnbVoltage;
+    uint8_t plpId;
+    bool isEWBS;
+    /** AGC value is normalized from 0 to 255. */
+    uint8_t agc;
+    bool isLnaOn;
+    bool isStreamLock;
+    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;
+    /** Frequency difference in Hertz. */
+    int32_t freqOffset;
+    FrontendDvbtHierarchy hierarchy;
+    bool isRfLocked;
+    /** A list of PLP status for tuned PLPs for ATSC3 frontend. */
+    vec<FrontendStatusAtsc3PlpInfo> plpInfo;
+};
+
+/**
+ *  Information for the Frontend.
+ */
+struct FrontendInfo {
+    FrontendType type;
+    /** Frequency in Hertz */
+    uint32_t minFrequency;
+    /** Frequency in Hertz */
+    uint32_t maxFrequency;
+    /** Minimum symbols per second */
+    uint32_t minSymbolRate;
+    /** Maximum symbols per second */
+    uint32_t maxSymbolRate;
+    /** Range in Hertz */
+    uint32_t acquireRange;
+    /*
+     * Frontends are assigned with the same exclusiveGroupId if they can't
+     * function at same time. For instance, they share same hardware module.
+     */
+    uint32_t exclusiveGroupId;
+    /** A list of supported status types which client can inquiry */
+    vec<FrontendStatusType> statusCaps;
+    safe_union FrontendCapabilities {
+        FrontendAnalogCapabilities analogCaps;
+        FrontendAtscCapabilities atscCaps;
+        FrontendAtsc3Capabilities atsc3Caps;
+        FrontendDvbsCapabilities dvbsCaps;
+        FrontendDvbcCapabilities dvbcCaps;
+        FrontendDvbtCapabilities dvbtCaps;
+        FrontendIsdbsCapabilities isdbsCaps;
+        FrontendIsdbs3Capabilities isdbs3Caps;
+        FrontendIsdbtCapabilities isdbtCaps;
+    } frontendCaps;
+};
+
+/*
+ * Low-Noise Block downconverter (LNB) ID is used to associate with a hardware
+ * LNB module.
+ */
+typedef uint32_t LnbId;
+
+/**
+ *  Power Voltage Type for LNB.
+ */
+@export
+enum FrontendLnbVoltage : uint32_t {
+    NONE,
+    VOLTAGE_5V,
+    VOLTAGE_11V,
+    VOLTAGE_12V,
+    VOLTAGE_13V,
+    VOLTAGE_14V,
+    VOLTAGE_15V,
+    VOLTAGE_18V,
+    VOLTAGE_19V,
+};
+
+/**
+ *  Tone Type for LNB.
+ */
+@export
+enum FrontendLnbTone : int32_t {
+    NONE,
+    CONTINUOUS,
+};
+
+/**
+ *  The Position of LNB.
+ */
+@export
+enum FrontendLnbPosition : int32_t {
+    UNDEFINED,
+    POSITION_A,
+    POSITION_B,
+};
+
+/* Demux ID is used to associate with a hardware demux resource. */
+typedef uint32_t DemuxId;
+
+/* Filter ID is used to associate with a hardware filter resource. */
+typedef uint32_t DemuxFilterId;
+
+/**
+ * Filter Type according to ISO/IEC 13818-1
+ */
+@export
+enum DemuxFilterType : uint32_t {
+    /**
+     * A filter to filter section data out from input stream.
+     */
+    SECTION,
+    /**
+     * A filter to filter PES data out from input stream.
+     */
+    PES,
+    /**
+     * A filter to filter TS payload out from input stream.
+     */
+    TS,
+    /**
+     * A filter to filter Audio Metadata out from input stream.
+     */
+    AUDIO,
+    /**
+     * A filter to filter Video Metadata out from input stream.
+     */
+    VIDEO,
+    /**
+     * A filter to set PCR (Program Clock Reference) channel from input stream.
+     */
+    PCR,
+    /**
+     * A filter to filter data directly to output buffer for record.
+     */
+    RECORD,
+};
+
+/* Packet ID is used to specify packets in transport stream. */
+typedef uint16_t DemuxTpid;
+
+@export
+enum Constant : uint16_t {
+    /**
+     * An invalid packet ID in transport stream according to ISO/IEC 13818-1.
+     */
+    INVALID_TPID = 0xFFFF,
+    /**
+     * An invalid Stream ID.
+     */
+    INVALID_STREAM_ID = 0xFFFF,
+};
+
+/**
+ * A status of data in the filter's buffer.
+ */
+@export
+enum DemuxFilterStatus : uint8_t {
+    /**
+     * The data in the filter buffer is ready to be read.
+     */
+    DATA_READY = 1 << 0,
+    /**
+     * The available data amount in the filter buffer is at low level which is
+     * set to 25 percent by default.
+     */
+    LOW_WATER  = 1 << 1,
+    /**
+     * The available data amount in the filter buffer is at high level which is
+     * set to 75 percent by default.
+     */
+    HIGH_WATER = 1 << 2,
+    /**
+     * The data in the filter buffer is full and newly filtered data is being
+     * discarded.
+     */
+    OVERFLOW   = 1 << 3,
+};
+
+/**
+ *  Bits Setting for Section Filter.
+ */
+struct DemuxFilterSectionBits {
+    /* The bytes are configured for Section Filter */
+    vec<uint8_t> filter;
+    /* Active bits in the configured bytes to be used for filtering */
+    vec<uint8_t> mask;
+    /*
+     * Do positive match at the bit position of the configured bytes when the
+     * bit at same position of the mode is 0.
+     * Do negative match at the bit position of the configured bytes when the
+     * bit at same position of the mode is 1.
+     */
+    vec<uint8_t> mode;
+};
+
+/**
+ *  Filter Settings for Section data according to ISO/IEC 13818-1.
+ */
+struct DemuxFilterSectionSettings {
+    DemuxTpid tpid;
+    DemuxFilterSectionBits bits;
+    /* Table ID for Section Filter */
+    uint16_t tableId;
+    /* Version number for Section Filter */
+    uint16_t version;
+    /* true if the filter checks CRC and discards data with wrong CRC */
+    bool isCheckCrc;
+    /* true if the filter repeats the data with the same version */
+    bool isRepeat;
+    /* true if the filter output raw data */
+    bool isRaw;
+};
+
+/* Stream ID is used to specify one elementary stream */
+typedef uint16_t DemuxStreamId;
+
+/**
+ *  Filter Settings for a PES Data.
+ */
+struct DemuxFilterPesDataSettings {
+    DemuxTpid tpid;
+    DemuxStreamId streamId;
+    /* true if the filter output raw data */
+    bool isRaw;
+};
+
+/**
+ *  Filter Settings for a TS Data.
+ */
+struct DemuxFilterTsSettings {
+    DemuxTpid tpid;
+};
+
+/**
+ *  Filter Settings for a Audio.
+ */
+struct DemuxFilterAudioSettings {
+    DemuxTpid tpid;
+    /**
+     * true if the filter output goes to decoder directly in pass through mode.
+     */
+    bool isPassthrough;
+};
+
+/**
+ *  Filter Settings for a Video.
+ */
+struct DemuxFilterVideoSettings {
+    DemuxTpid tpid;
+    /**
+     * true if the filter output goes to decoder directly in pass through mode.
+     */
+    bool isPassthrough;
+};
+
+/**
+ *  Filter Settings for a PCR (Program Clock Reference).
+ */
+struct DemuxFilterPcrSettings {
+    DemuxTpid tpid;
+};
+
+/**
+ * Indexes can be tagged through TS (Transport Stream) header.
+ */
+@export
+enum DemuxTsIndex : uint32_t {
+    FIRST_PACKET                 = 1 << 0,
+    PAYLOAD_UNIT_START_INDICATOR = 1 << 1,
+    CHANGE_TO_NOT_SCRAMBLED      = 1 << 2,
+    CHANGE_TO_EVEN_SCRAMBLED     = 1 << 3,
+    CHANGE_TO_ODD_SCRAMBLED      = 1 << 4,
+    DISCONTINUITY_INDICATOR      = 1 << 5,
+    RANDOM_ACCESS_INDICATOR      = 1 << 6,
+    PRIORITY_INDICATOR           = 1 << 7,
+    PCR_FLAG                     = 1 << 8,
+    OPCR_FLAG                    = 1 << 9,
+    SPLICING_POINT_FLAG          = 1 << 10,
+    PRIVATE_DATA                 = 1 << 11,
+    ADAPTATION_EXTENSION_FLAG    = 1 << 12,
+};
+
+/**
+ * A mask of TS indexes
+ *
+ * It's a combination of TS indexes.
+ */
+typedef bitfield<DemuxTsIndex> DemuxTsIndexMask;
+
+/**
+ * Indexes can be tagged by Start Code in PES (Packetized Elementary Stream)
+ * according to ISO/IEC 13818-1.
+ */
+@export
+enum DemuxScIndex : uint32_t {
+    /* Start Code is for a new I Frame */
+    I_FRAME   = 1 << 0,
+    /* Start Code is for a new P Frame */
+    P_FRAME   = 1 << 1,
+    /* Start Code is for a new B Frame */
+    B_FRAME   = 1 << 2,
+    /* Start Code is for a new Sequence */
+    SEQUENCE  = 1 << 3,
+};
+
+/**
+ * A mask of Start Code Indexes
+ *
+ * It's a combination of Start Code Indexes.
+ */
+typedef bitfield<DemuxScIndex> DemuxScIndexMask;
+
+/* Index type to be used in the filter for record */
+@export
+enum DemuxRecordIndexType : uint32_t {
+    /* Don't use index */
+    NONE,
+    /* Use TS index */
+    TS,
+    /* Use Start Code index */
+    SC,
+};
+
+/**
+ *  Filter Settings for Record data.
+ */
+struct DemuxFilterRecordSettings {
+    DemuxTpid tpid;
+    DemuxRecordIndexType indexType;
+    safe_union IndexMask {
+        DemuxTsIndexMask tsIndexMask;
+        DemuxScIndexMask scIndexMask;
+    } indexMask;
+};
+
+/**
+ *  Filter Settings.
+ */
+safe_union DemuxFilterSettings {
+    DemuxFilterSectionSettings section;
+    DemuxFilterPesDataSettings pesData;
+    DemuxFilterTsSettings ts;
+    DemuxFilterAudioSettings audio;
+    DemuxFilterVideoSettings video;
+    DemuxFilterPcrSettings pcr;
+    DemuxFilterRecordSettings record;
+};
+
+/**
+ * The bits of EventFlag in FMQ (Fast message queue) are used by client to
+ * notify HAL the status change.
+ */
+@export
+enum DemuxQueueNotifyBits : uint32_t {
+    /* client writes data and notify HAL the data is ready. */
+    DATA_READY = 1 << 0,
+    /* client reads data and notify HAL the data is consumed. */
+    DATA_CONSUMED = 1 << 1
+};
+
+/**
+ *  Filter Event for Section Filter.
+ */
+struct DemuxFilterSectionEvent {
+    /* Table ID of filtered data */
+    uint16_t tableId;
+    /* Version number of filtered data */
+    uint16_t version;
+    /* Section number of filtered data */
+    uint16_t sectionNum;
+    /* Data size in bytes of filtered data */
+    uint16_t dataLength;
+};
+
+/**
+ *  Filter Event for Audio or Video Filter.
+ */
+struct DemuxFilterMediaEvent {
+    /* Presentation Time Stamp for audio or video frame. It based on 90KHz has
+     * the same format as PTS (Presentation Time Stamp).
+     */
+    uint64_t pts;
+    /* Data size in bytes of audio or video frame */
+    uint16_t dataLength;
+    /* A handle associated to the memory where audio or video data stays. */
+    handle secureMemory;
+};
+
+/**
+ *  Filter Event for PES data.
+ */
+struct DemuxFilterPesEvent {
+    DemuxStreamId streamId;
+    /* Data size in bytes of PES data */
+    uint16_t dataLength;
+};
+
+/**
+ *  Filter Event for Record data.
+ */
+struct DemuxFilterRecordEvent {
+    DemuxTpid tpid;
+    /* Indexes of record output */
+    safe_union IndexMask {
+        DemuxTsIndexMask tsIndexMask;
+        DemuxScIndexMask scIndexMask;
+    } indexMask;
+    /* Packet number from beginning of the filter's output */
+    uint64_t packetNum;
+};
+
+/**
+ * Filter Event.
+ */
+struct DemuxFilterEvent {
+    DemuxFilterId filterId;
+    DemuxFilterType filterType;
+    safe_union Event {
+        DemuxFilterSectionEvent section;
+        DemuxFilterMediaEvent media;
+        DemuxFilterPesEvent pes;
+        DemuxFilterRecordEvent ts;
+    };
+    /* An array of events */
+    vec<Event> events;
+};
+
+/**
+ *  A hardware resource ID to be used for audio and video hardware sync.
+ */
+typedef uint32_t AvSyncHwId;
+
+/**
+ *  A token to be used to link descrambler and key slot. It's opaque to
+ *  framework and apps.
+ */
+typedef vec<uint8_t> TunerKeyToken;
+
+/**
+ * A data format in demux's output or input according to ISO/IEC 13818-1.
+ */
+@export
+enum DemuxDataFormat : uint32_t {
+    /* Data is Transport Stream. */
+    TS,
+    /* Data is Packetized Elementary Stream. */
+    PES,
+    /* Data is Elementary Stream. */
+    ES,
+    /* Data is TLV (type-length-value) Stream for JP SHV */
+    SHV_TLV,
+};
+
+/**
+ * A status of the demux's output.
+ */
+typedef DemuxFilterStatus DemuxOutputStatus;
+
+/**
+ *  The Settings for the demux's output.
+ */
+struct DemuxOutputSettings {
+    /**
+     * Register for interested status events so that the HAL can send these
+     * status events back to client.
+     */
+    bitfield<DemuxOutputStatus> statusMask;
+    /**
+     * Unconsumed data size in bytes in the output. The HAL uses it to trigger
+     * DemuxOutputStatus::LOW_WATER.
+     */
+    uint32_t lowThreshold;
+    /**
+     * Unconsumed data size in bytes in the output. The HAL uses it to trigger
+     * DemuxOutputStatus::High_WATER.
+     */
+    uint32_t highThreshold;
+    /**
+     * The data format in the output.
+     */
+    DemuxDataFormat dataFormat;
+    /**
+     * The packet size in bytes in the output.
+     */
+    uint8_t packetSize;
+};
+
+/**
+ * A status of the demux's input.
+ */
+@export
+enum DemuxInputStatus : uint32_t {
+    /**
+     * The space of the demux's input is empty.
+     */
+    SPACE_EMPTY        = 1 << 0,
+    /**
+     * The spece of the demux's input is almost empty.
+     */
+    SPACE_ALMOST_EMPTY = 1 << 1,
+    /**
+     * The space of the demux's input is almost full.
+     */
+    SPACE_ALMOST_FULL  = 1 << 2,
+    /**
+     * The space of the demux's input is full.
+     */
+    SPACE_FULL         = 1 << 3,
+};
+
+/**
+ *  The Settings for the demux's input.
+ */
+@export
+struct DemuxInputSettings {
+    /**
+     * Register for interested status events so that the HAL can send these
+     * status events back to client.
+     */
+    bitfield<DemuxInputStatus> statusMask;
+    /**
+     * Unused space size in bytes in the input. The HAL uses it to trigger
+     * DemuxInputStatus::SPACE_ALMOST_EMPTY.
+     */
+    uint32_t lowThreshold;
+    /**
+     * Unused space size in bytes in the input. The HAL uses it to trigger
+     * DemuxInputStatus::SPACE_ALMOST_FULL.
+     */
+    uint32_t highThreshold;
+    /**
+     * The data format in the input.
+     */
+    DemuxDataFormat dataFormat;
+    /**
+     * The packet size in bytes in the input.
+     */
+    uint8_t packetSize;
+};
+
+/**
+ *  Capabilities for Demux.
+ */
+@export
+struct DemuxCapabilities {
+    /* The number of Demux to be supported. */
+    uint32_t numDemux;
+    /* The number of Input to be supported. */
+    uint32_t numInput;
+    /* The number of Output to be supported. */
+    uint32_t numOutput;
+    /* The number of TS Filter to be supported. */
+    uint32_t numTsFilter;
+    /* The number of Section Filter to be supported. */
+    uint32_t numSectionFilter;
+    /* The number of Audio Filter to be supported. */
+    uint32_t numAudioFilter;
+    /* The number of Video Filter to be supported. */
+    uint32_t numVideoFilter;
+    /* The number of PES Filter to be supported. */
+    uint32_t numPesFilter;
+    /* The number of PCR Filter to be supported. */
+    uint32_t numPcrFilter;
+    /* The maximum number of bytes is supported in the mask of Section Filter. */
+    uint32_t numBytesInSectionFilter;
+};
diff --git a/tv/tuner/1.0/vts/OWNERS b/tv/tuner/1.0/vts/OWNERS
new file mode 100644
index 0000000..1b3d095
--- /dev/null
+++ b/tv/tuner/1.0/vts/OWNERS
@@ -0,0 +1,4 @@
+nchalko@google.com
+amyjojo@google.com
+shubang@google.com
+quxiangfang@google.com
diff --git a/tv/tuner/1.0/vts/functional/Android.bp b/tv/tuner/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..7d6b990
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/Android.bp
@@ -0,0 +1,34 @@
+//
+// 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: "VtsHalTvTunerV1_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalTvTunerV1_0TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.tv.tuner@1.0",
+        "android.hidl.allocator@1.0",
+        "android.hidl.memory@1.0",
+        "libhidlallocatorutils",
+        "libhidlmemory",
+        "libcutils",
+        "libfmq",
+    ],
+    shared_libs: [
+        "libbinder",
+    ],
+    test_suites: ["general-tests"],
+}
diff --git a/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
new file mode 100644
index 0000000..7936185
--- /dev/null
+++ b/tv/tuner/1.0/vts/functional/VtsHalTvTunerV1_0TargetTest.cpp
@@ -0,0 +1,1063 @@
+/*
+ * 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 "Tuner_hidl_hal_test"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/tv/tuner/1.0/IDemux.h>
+#include <android/hardware/tv/tuner/1.0/IDemuxCallback.h>
+#include <android/hardware/tv/tuner/1.0/IDescrambler.h>
+#include <android/hardware/tv/tuner/1.0/IFrontend.h>
+#include <android/hardware/tv/tuner/1.0/IFrontendCallback.h>
+#include <android/hardware/tv/tuner/1.0/ITuner.h>
+#include <android/hardware/tv/tuner/1.0/types.h>
+#include <binder/MemoryDealer.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+#include <hidl/Status.h>
+#include <hidlmemory/FrameworkUtils.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+#include <fstream>
+#include <iostream>
+#include <map>
+
+#define WAIT_TIMEOUT 3000000000
+#define WAIT_TIMEOUT_data_ready 3000000000 * 4
+
+using android::Condition;
+using android::IMemory;
+using android::IMemoryHeap;
+using android::MemoryDealer;
+using android::Mutex;
+using android::sp;
+using android::hardware::EventFlag;
+using android::hardware::fromHeap;
+using android::hardware::hidl_string;
+using android::hardware::hidl_vec;
+using android::hardware::HidlMemory;
+using android::hardware::kSynchronizedReadWrite;
+using android::hardware::MessageQueue;
+using android::hardware::MQDescriptorSync;
+using android::hardware::Return;
+using android::hardware::Void;
+using android::hardware::tv::tuner::V1_0::DemuxDataFormat;
+using android::hardware::tv::tuner::V1_0::DemuxFilterEvent;
+using android::hardware::tv::tuner::V1_0::DemuxFilterPesDataSettings;
+using android::hardware::tv::tuner::V1_0::DemuxFilterPesEvent;
+using android::hardware::tv::tuner::V1_0::DemuxFilterSectionEvent;
+using android::hardware::tv::tuner::V1_0::DemuxFilterSectionSettings;
+using android::hardware::tv::tuner::V1_0::DemuxFilterSettings;
+using android::hardware::tv::tuner::V1_0::DemuxFilterStatus;
+using android::hardware::tv::tuner::V1_0::DemuxFilterType;
+using android::hardware::tv::tuner::V1_0::DemuxInputSettings;
+using android::hardware::tv::tuner::V1_0::DemuxInputStatus;
+using android::hardware::tv::tuner::V1_0::DemuxOutputStatus;
+using android::hardware::tv::tuner::V1_0::DemuxQueueNotifyBits;
+using android::hardware::tv::tuner::V1_0::FrontendAtscModulation;
+using android::hardware::tv::tuner::V1_0::FrontendAtscSettings;
+using android::hardware::tv::tuner::V1_0::FrontendDvbtSettings;
+using android::hardware::tv::tuner::V1_0::FrontendEventType;
+using android::hardware::tv::tuner::V1_0::FrontendId;
+using android::hardware::tv::tuner::V1_0::FrontendInnerFec;
+using android::hardware::tv::tuner::V1_0::FrontendScanMessage;
+using android::hardware::tv::tuner::V1_0::FrontendScanMessageType;
+using android::hardware::tv::tuner::V1_0::FrontendSettings;
+using android::hardware::tv::tuner::V1_0::IDemux;
+using android::hardware::tv::tuner::V1_0::IDemuxCallback;
+using android::hardware::tv::tuner::V1_0::IDescrambler;
+using android::hardware::tv::tuner::V1_0::IFrontend;
+using android::hardware::tv::tuner::V1_0::IFrontendCallback;
+using android::hardware::tv::tuner::V1_0::ITuner;
+using android::hardware::tv::tuner::V1_0::Result;
+
+namespace {
+
+using FilterMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+using MQDesc = MQDescriptorSync<uint8_t>;
+
+const std::vector<uint8_t> goldenDataOutputBuffer{
+        0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb,
+        0x01, 0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03,
+        0xc5, 0x8b, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06,
+        0x05, 0xff, 0xff, 0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8,
+        0x20, 0xd9, 0x23, 0xee, 0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72,
+        0x65, 0x20, 0x31, 0x34, 0x32, 0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d,
+        0x50, 0x45, 0x47, 0x2d, 0x34, 0x20, 0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63,
+        0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30,
+        0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+        0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f,
+        0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x2d, 0x20,
+        0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x63, 0x61, 0x62, 0x61, 0x63, 0x3d,
+        0x30, 0x20, 0x72, 0x65, 0x66, 0x3d, 0x32, 0x20, 0x64, 0x65, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+        0x3d, 0x31, 0x3a, 0x30, 0x3a, 0x30, 0x20, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x65, 0x3d,
+        0x30, 0x78, 0x31, 0x3a, 0x30, 0x78, 0x31, 0x31, 0x31, 0x20, 0x6d, 0x65, 0x3d, 0x68, 0x65,
+        0x78, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x65, 0x3d, 0x37, 0x20, 0x70, 0x73, 0x79, 0x3d, 0x31,
+        0x20, 0x70, 0x73, 0x79, 0x5f, 0x72, 0x64, 0x3d, 0x31, 0x2e, 0x30, 0x30, 0x3a, 0x30, 0x2e,
+        0x30, 0x30, 0x20, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x3d, 0x31, 0x20,
+        0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x3d, 0x31, 0x36, 0x20, 0x63, 0x68, 0x72,
+        0x6f, 0x6d, 0x61, 0x5f, 0x6d, 0x65, 0x3d, 0x31, 0x20, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x69,
+        0x73, 0x3d, 0x31, 0x20, 0x38, 0x78, 0x38, 0x64, 0x63, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x71,
+        0x6d, 0x3d, 0x30, 0x20, 0x64, 0x65, 0x61, 0x64, 0x7a, 0x6f, 0x6e, 0x65, 0x3d, 0x32, 0x31,
+        0x2c, 0x31, 0x31, 0x20, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x73, 0x6b, 0x69, 0x70, 0x3d,
+        0x31, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x5f, 0x71, 0x70, 0x5f, 0x6f, 0x66, 0x66,
+        0x73, 0x65, 0x74, 0x3d, 0x2d, 0x32, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d,
+        0x36, 0x30, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x61, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x68,
+        0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x35, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x64, 0x5f,
+        0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x30, 0x20, 0x6e, 0x72, 0x3d, 0x30, 0x20,
+        0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x3d, 0x31, 0x20, 0x69, 0x6e, 0x74, 0x65,
+        0x72, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x3d, 0x30, 0x20, 0x62, 0x6c, 0x75, 0x72, 0x61, 0x79,
+        0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
+        0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x3d, 0x30, 0x20,
+        0x62, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3d, 0x30, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68,
+        0x74, 0x70, 0x3d, 0x30, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x3d, 0x32, 0x35, 0x30,
+        0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x3d, 0x32, 0x35, 0x20,
+        0x73, 0x63, 0x65, 0x6e, 0x65,
+};
+
+const uint16_t FMQ_SIZE_4K = 0x1000;
+const uint32_t FMQ_SIZE_1M = 0x100000;
+
+struct FilterConf {
+    DemuxFilterType type;
+    DemuxFilterSettings setting;
+};
+
+struct InputConf {
+    string inputDataFile;
+    DemuxInputSettings setting;
+};
+
+class FrontendCallback : public IFrontendCallback {
+  public:
+    virtual Return<void> onEvent(FrontendEventType frontendEventType) override {
+        android::Mutex::Autolock autoLock(mMsgLock);
+        mEventReceived = true;
+        mEventType = frontendEventType;
+        mMsgCondition.signal();
+        return Void();
+    }
+
+    virtual Return<void> onDiseqcMessage(const hidl_vec<uint8_t>& diseqcMessage) override {
+        android::Mutex::Autolock autoLock(mMsgLock);
+        mDiseqcMessageReceived = true;
+        mEventMessage = diseqcMessage;
+        mMsgCondition.signal();
+        return Void();
+    }
+
+    virtual Return<void> onScanMessage(FrontendScanMessageType /* type */,
+                                       const FrontendScanMessage& /* message */) override {
+        android::Mutex::Autolock autoLock(mMsgLock);
+        mScanMessageReceived = true;
+        mMsgCondition.signal();
+        return Void();
+    };
+
+    void testOnEvent(sp<IFrontend>& frontend, FrontendSettings settings);
+    void testOnDiseqcMessage(sp<IFrontend>& frontend, FrontendSettings settings);
+
+  private:
+    bool mEventReceived = false;
+    bool mDiseqcMessageReceived = false;
+    bool mScanMessageReceived = false;
+    FrontendEventType mEventType;
+    hidl_vec<uint8_t> mEventMessage;
+    android::Mutex mMsgLock;
+    android::Condition mMsgCondition;
+};
+
+void FrontendCallback::testOnEvent(sp<IFrontend>& frontend, FrontendSettings settings) {
+    Result result = frontend->tune(settings);
+
+    EXPECT_TRUE(result == Result::SUCCESS);
+
+    android::Mutex::Autolock autoLock(mMsgLock);
+    while (!mEventReceived) {
+        if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+            EXPECT_TRUE(false) << "event not received within timeout";
+            return;
+        }
+    }
+}
+
+void FrontendCallback::testOnDiseqcMessage(sp<IFrontend>& frontend, FrontendSettings settings) {
+    Result result = frontend->tune(settings);
+
+    EXPECT_TRUE(result == Result::SUCCESS);
+
+    android::Mutex::Autolock autoLock(mMsgLock);
+    while (!mDiseqcMessageReceived) {
+        if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+            EXPECT_TRUE(false) << "diseqc message not received within timeout";
+            return;
+        }
+    }
+}
+
+class DemuxCallback : public IDemuxCallback {
+  public:
+    virtual Return<void> onFilterEvent(const DemuxFilterEvent& filterEvent) override {
+        android::Mutex::Autolock autoLock(mMsgLock);
+        // Temprarily we treat the first coming back filter data on the matching pid a success
+        // once all of the MQ are cleared, means we got all the expected output
+        mFilterIdToEvent[filterEvent.filterId] = filterEvent;
+        readFilterEventData(filterEvent.filterId);
+        mPidFilterOutputCount++;
+        // mFilterIdToMQ.erase(filterEvent.filterId);
+
+        // startFilterEventThread(filterEvent);
+        mMsgCondition.signal();
+        return Void();
+    }
+
+    virtual Return<void> onFilterStatus(uint32_t /*filterId*/,
+                                        const DemuxFilterStatus /*status*/) override {
+        return Void();
+    }
+
+    virtual Return<void> onOutputStatus(DemuxOutputStatus /*status*/) override { return Void(); }
+
+    virtual Return<void> onInputStatus(DemuxInputStatus status) override {
+        // android::Mutex::Autolock autoLock(mMsgLock);
+        ALOGW("[vts] input status %d", status);
+        switch (status) {
+            case DemuxInputStatus::SPACE_EMPTY:
+            case DemuxInputStatus::SPACE_ALMOST_EMPTY:
+                ALOGW("[vts] keep inputing %d", status);
+                mKeepWritingInputFMQ = true;
+                break;
+            case DemuxInputStatus::SPACE_ALMOST_FULL:
+            case DemuxInputStatus::SPACE_FULL:
+                ALOGW("[vts] stop inputing %d", status);
+                mKeepWritingInputFMQ = false;
+                break;
+        }
+        return Void();
+    }
+
+    void testOnFilterEvent(uint32_t filterId);
+    void testFilterDataOutput();
+    void stopInputThread();
+
+    void startPlaybackInputThread(InputConf inputConf, MQDesc& inputMQDescriptor);
+    void startFilterEventThread(DemuxFilterEvent event);
+    static void* __threadLoopInput(void* threadArgs);
+    static void* __threadLoopFilter(void* threadArgs);
+    void inputThreadLoop(InputConf* inputConf, bool* keepWritingInputFMQ);
+    void filterThreadLoop(DemuxFilterEvent& event);
+
+    void updateFilterMQ(uint32_t filterId, MQDesc& filterMQDescriptor);
+    void updateGoldenOutputMap(uint32_t filterId, string goldenOutputFile);
+    bool readFilterEventData(uint32_t filterId);
+
+  private:
+    struct InputThreadArgs {
+        DemuxCallback* user;
+        InputConf* inputConf;
+        bool* keepWritingInputFMQ;
+    };
+    struct FilterThreadArgs {
+        DemuxCallback* user;
+        DemuxFilterEvent event;
+    };
+    uint16_t mDataLength = 0;
+    std::vector<uint8_t> mDataOutputBuffer;
+
+    bool mFilterEventReceived;
+    std::map<uint32_t, string> mFilterIdToGoldenOutput;
+
+    std::map<uint32_t, std::unique_ptr<FilterMQ>> mFilterIdToMQ;
+    std::unique_ptr<FilterMQ> mInputMQ;
+    std::map<uint32_t, EventFlag*> mFilterIdToMQEventFlag;
+    std::map<uint32_t, DemuxFilterEvent> mFilterIdToEvent;
+    EventFlag* mInputMQEventFlag;
+
+    android::Mutex mMsgLock;
+    android::Mutex mFilterOutputLock;
+    android::Mutex mInputThreadLock;
+    android::Condition mMsgCondition;
+    android::Condition mFilterOutputCondition;
+
+    bool mKeepWritingInputFMQ = true;
+    bool mInputThreadRunning;
+    pthread_t mInputThread;
+    pthread_t mFilterThread;
+
+    int mPidFilterOutputCount = 0;
+};
+
+void DemuxCallback::startPlaybackInputThread(InputConf inputConf, MQDesc& inputMQDescriptor) {
+    mInputMQ = std::make_unique<FilterMQ>(inputMQDescriptor, true /* resetPointers */);
+    EXPECT_TRUE(mInputMQ);
+    struct InputThreadArgs* threadArgs =
+            (struct InputThreadArgs*)malloc(sizeof(struct InputThreadArgs));
+    threadArgs->user = this;
+    threadArgs->inputConf = &inputConf;
+    threadArgs->keepWritingInputFMQ = &mKeepWritingInputFMQ;
+
+    pthread_create(&mInputThread, NULL, __threadLoopInput, (void*)threadArgs);
+    pthread_setname_np(mInputThread, "test_playback_input_loop");
+}
+
+void DemuxCallback::startFilterEventThread(DemuxFilterEvent event) {
+    struct FilterThreadArgs* threadArgs =
+            (struct FilterThreadArgs*)malloc(sizeof(struct FilterThreadArgs));
+    threadArgs->user = this;
+    threadArgs->event = event;
+
+    pthread_create(&mFilterThread, NULL, __threadLoopFilter, (void*)threadArgs);
+    pthread_setname_np(mFilterThread, "test_playback_input_loop");
+}
+
+void DemuxCallback::testFilterDataOutput() {
+    android::Mutex::Autolock autoLock(mMsgLock);
+    while (mPidFilterOutputCount < 1) {
+        if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+            EXPECT_TRUE(false) << "filter output matching pid does not output within timeout";
+            return;
+        }
+    }
+    mPidFilterOutputCount = 0;
+    ALOGW("[vts] pass and stop");
+}
+
+void DemuxCallback::stopInputThread() {
+    mInputThreadRunning = false;
+    mKeepWritingInputFMQ = false;
+
+    android::Mutex::Autolock autoLock(mInputThreadLock);
+}
+
+void DemuxCallback::updateFilterMQ(uint32_t filterId, MQDesc& filterMQDescriptor) {
+    mFilterIdToMQ[filterId] =
+            std::make_unique<FilterMQ>(filterMQDescriptor, true /* resetPointers */);
+    EXPECT_TRUE(mFilterIdToMQ[filterId]);
+    EXPECT_TRUE(EventFlag::createEventFlag(mFilterIdToMQ[filterId]->getEventFlagWord(),
+                                           &mFilterIdToMQEventFlag[filterId]) == android::OK);
+}
+
+void DemuxCallback::updateGoldenOutputMap(uint32_t filterId, string goldenOutputFile) {
+    mFilterIdToGoldenOutput[filterId] = goldenOutputFile;
+}
+
+void* DemuxCallback::__threadLoopInput(void* threadArgs) {
+    DemuxCallback* const self =
+            static_cast<DemuxCallback*>(((struct InputThreadArgs*)threadArgs)->user);
+    self->inputThreadLoop(((struct InputThreadArgs*)threadArgs)->inputConf,
+                          ((struct InputThreadArgs*)threadArgs)->keepWritingInputFMQ);
+    return 0;
+}
+
+void DemuxCallback::inputThreadLoop(InputConf* inputConf, bool* keepWritingInputFMQ) {
+    android::Mutex::Autolock autoLock(mInputThreadLock);
+    mInputThreadRunning = true;
+
+    // Create the EventFlag that is used to signal the HAL impl that data have been
+    // written into the Input FMQ
+    EventFlag* inputMQEventFlag;
+    EXPECT_TRUE(EventFlag::createEventFlag(mInputMQ->getEventFlagWord(), &inputMQEventFlag) ==
+                android::OK);
+
+    // open the stream and get its length
+    std::ifstream inputData(inputConf->inputDataFile, std::ifstream::binary);
+    int writeSize = inputConf->setting.packetSize * 6;
+    char* buffer = new char[writeSize];
+    ALOGW("[vts] input thread loop start %s", inputConf->inputDataFile.c_str());
+    if (!inputData.is_open()) {
+        mInputThreadRunning = false;
+        ALOGW("[vts] Error %s", strerror(errno));
+    }
+
+    while (mInputThreadRunning) {
+        // move the stream pointer for packet size * 6 every read until the end
+        while (*keepWritingInputFMQ) {
+            inputData.read(buffer, writeSize);
+            if (!inputData) {
+                int leftSize = inputData.gcount();
+                if (leftSize == 0) {
+                    mInputThreadRunning = false;
+                    break;
+                }
+                inputData.clear();
+                inputData.read(buffer, leftSize);
+                // Write the left over of the input data and quit the thread
+                if (leftSize > 0) {
+                    EXPECT_TRUE(mInputMQ->write((unsigned char*)&buffer[0], leftSize));
+                    inputMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
+                }
+                mInputThreadRunning = false;
+                break;
+            }
+            // Write input FMQ and notify the Tuner Implementation
+            EXPECT_TRUE(mInputMQ->write((unsigned char*)&buffer[0], writeSize));
+            inputMQEventFlag->wake(static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_READY));
+            inputData.seekg(writeSize, inputData.cur);
+            sleep(1);
+        }
+    }
+
+    ALOGW("[vts] Input thread end.");
+
+    delete[] buffer;
+    inputData.close();
+}
+
+void* DemuxCallback::__threadLoopFilter(void* threadArgs) {
+    DemuxCallback* const self =
+            static_cast<DemuxCallback*>(((struct FilterThreadArgs*)threadArgs)->user);
+    self->filterThreadLoop(((struct FilterThreadArgs*)threadArgs)->event);
+    return 0;
+}
+
+void DemuxCallback::filterThreadLoop(DemuxFilterEvent& /* event */) {
+    android::Mutex::Autolock autoLock(mFilterOutputLock);
+    // Read from mFilterIdToMQ[event.filterId] per event and filter type
+
+    // Assemble to filterOutput[filterId]
+
+    // check if filterOutput[filterId] matches goldenOutput[filterId]
+
+    // If match, remove filterId entry from MQ map
+
+    // end thread
+}
+
+bool DemuxCallback::readFilterEventData(uint32_t filterId) {
+    bool result = false;
+    DemuxFilterEvent filterEvent = mFilterIdToEvent[filterId];
+    ALOGW("[vts] reading from filter FMQ %d", filterId);
+    // todo separate filter handlers
+    for (int i = 0; i < filterEvent.events.size(); i++) {
+        DemuxFilterPesEvent event = filterEvent.events[i].pes();
+        mDataLength = event.dataLength;
+        // EXPECT_TRUE(mDataLength == goldenDataOutputBuffer.size()) << "buffer size does not
+        // match";
+
+        mDataOutputBuffer.resize(mDataLength);
+        result = mFilterIdToMQ[filterId]->read(mDataOutputBuffer.data(), mDataLength);
+        EXPECT_TRUE(result) << "can't read from Filter MQ";
+
+        /*for (int i = 0; i < mDataLength; i++) {
+            EXPECT_TRUE(goldenDataOutputBuffer[i] == mDataOutputBuffer[i]) << "data does not match";
+        }*/
+    }
+    mFilterIdToMQEventFlag[filterId]->wake(
+            static_cast<uint32_t>(DemuxQueueNotifyBits::DATA_CONSUMED));
+    return result;
+}
+
+// Test environment for Tuner HIDL HAL.
+class TunerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+  public:
+    // get the test environment singleton
+    static TunerHidlEnvironment* Instance() {
+        static TunerHidlEnvironment* instance = new TunerHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<ITuner>(); }
+};
+
+class TunerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+  public:
+    virtual void SetUp() override {
+        mService = ::testing::VtsHalHidlTargetTestBase::getService<ITuner>(
+                TunerHidlEnvironment::Instance()->getServiceName<ITuner>());
+        ASSERT_NE(mService, nullptr);
+    }
+
+    sp<ITuner> mService;
+
+  protected:
+    static void description(const std::string& description) {
+        RecordProperty("description", description);
+    }
+
+    sp<IFrontend> mFrontend;
+    sp<FrontendCallback> mFrontendCallback;
+    sp<IDescrambler> mDescrambler;
+    sp<IDemux> mDemux;
+    sp<DemuxCallback> mDemuxCallback;
+    MQDesc mFilterMQDescriptor;
+    MQDesc mInputMQDescriptor;
+    vector<uint32_t> mUsedFilterIds;
+
+    uint32_t mDemuxId;
+    uint32_t mFilterId;
+
+    pthread_t mInputThread;
+    bool mInputThreadRunning;
+
+    ::testing::AssertionResult createFrontend(int32_t frontendId);
+    ::testing::AssertionResult tuneFrontend(int32_t frontendId);
+    ::testing::AssertionResult stopTuneFrontend(int32_t frontendId);
+    ::testing::AssertionResult closeFrontend(int32_t frontendId);
+    ::testing::AssertionResult createDemux();
+    ::testing::AssertionResult createDemuxWithFrontend(int32_t frontendId,
+                                                       FrontendSettings settings);
+    ::testing::AssertionResult getInputMQDescriptor();
+    ::testing::AssertionResult addInputToDemux(DemuxInputSettings setting);
+    ::testing::AssertionResult addFilterToDemux(DemuxFilterType type, DemuxFilterSettings setting);
+    ::testing::AssertionResult getFilterMQDescriptor(const uint32_t filterId);
+    ::testing::AssertionResult closeDemux();
+    ::testing::AssertionResult createDescrambler();
+    ::testing::AssertionResult closeDescrambler();
+
+    ::testing::AssertionResult playbackDataFlowTest(vector<FilterConf> filterConf,
+                                                    InputConf inputConf,
+                                                    vector<string> goldenOutputFiles);
+    ::testing::AssertionResult broadcastDataFlowTest(vector<FilterConf> filterConf,
+                                                     vector<string> goldenOutputFiles);
+};
+
+::testing::AssertionResult TunerHidlTest::createFrontend(int32_t frontendId) {
+    Result status;
+
+    mService->openFrontendById(frontendId, [&](Result result, const sp<IFrontend>& frontend) {
+        mFrontend = frontend;
+        status = result;
+    });
+    if (status != Result::SUCCESS) {
+        return ::testing::AssertionFailure();
+    }
+
+    mFrontendCallback = new FrontendCallback();
+    auto callbackStatus = mFrontend->setCallback(mFrontendCallback);
+
+    return ::testing::AssertionResult(callbackStatus.isOk());
+}
+
+::testing::AssertionResult TunerHidlTest::tuneFrontend(int32_t frontendId) {
+    if (createFrontend(frontendId) == ::testing::AssertionFailure()) {
+        return ::testing::AssertionFailure();
+    }
+
+    // Frontend Settings for testing
+    FrontendSettings frontendSettings;
+    FrontendAtscSettings frontendAtscSettings{
+            .frequency = 0,
+            .modulation = FrontendAtscModulation::UNDEFINED,
+    };
+    frontendSettings.atsc(frontendAtscSettings);
+    mFrontendCallback->testOnEvent(mFrontend, frontendSettings);
+
+    FrontendDvbtSettings frontendDvbtSettings{
+            .frequency = 0,
+    };
+    frontendSettings.dvbt(frontendDvbtSettings);
+    mFrontendCallback->testOnEvent(mFrontend, frontendSettings);
+
+    return ::testing::AssertionResult(true);
+}
+
+::testing::AssertionResult TunerHidlTest::stopTuneFrontend(int32_t frontendId) {
+    Result status;
+    if (!mFrontend && createFrontend(frontendId) == ::testing::AssertionFailure()) {
+        return ::testing::AssertionFailure();
+    }
+
+    status = mFrontend->stopTune();
+    return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::closeFrontend(int32_t frontendId) {
+    Result status;
+    if (!mFrontend && createFrontend(frontendId) == ::testing::AssertionFailure()) {
+        return ::testing::AssertionFailure();
+    }
+
+    status = mFrontend->close();
+    mFrontend = nullptr;
+    return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::createDemux() {
+    Result status;
+
+    mService->openDemux([&](Result result, uint32_t demuxId, const sp<IDemux>& demux) {
+        mDemux = demux;
+        mDemuxId = demuxId;
+        status = result;
+    });
+    return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::createDemuxWithFrontend(int32_t frontendId,
+                                                                  FrontendSettings settings) {
+    Result status;
+
+    if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
+        return ::testing::AssertionFailure();
+    }
+
+    if (!mFrontend && createFrontend(frontendId) == ::testing::AssertionFailure()) {
+        return ::testing::AssertionFailure();
+    }
+
+    mFrontendCallback->testOnEvent(mFrontend, settings);
+
+    status = mDemux->setFrontendDataSource(frontendId);
+
+    return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::closeDemux() {
+    Result status;
+    if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
+        return ::testing::AssertionFailure();
+    }
+
+    status = mDemux->close();
+    mDemux = nullptr;
+    return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::createDescrambler() {
+    Result status;
+
+    mService->openDescrambler([&](Result result, const sp<IDescrambler>& descrambler) {
+        mDescrambler = descrambler;
+        status = result;
+    });
+    if (status != Result::SUCCESS) {
+        return ::testing::AssertionFailure();
+    }
+
+    if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
+        return ::testing::AssertionFailure();
+    }
+
+    status = mDescrambler->setDemuxSource(mDemuxId);
+    if (status != Result::SUCCESS) {
+        return ::testing::AssertionFailure();
+    }
+
+    // Test if demux source can be set more than once.
+    status = mDescrambler->setDemuxSource(mDemuxId);
+    return ::testing::AssertionResult(status == Result::INVALID_STATE);
+}
+
+::testing::AssertionResult TunerHidlTest::closeDescrambler() {
+    Result status;
+    if (!mDescrambler && createDescrambler() == ::testing::AssertionFailure()) {
+        return ::testing::AssertionFailure();
+    }
+
+    status = mDescrambler->close();
+    mDescrambler = nullptr;
+    return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::addInputToDemux(DemuxInputSettings setting) {
+    Result status;
+
+    if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
+        return ::testing::AssertionFailure();
+    }
+
+    // Create demux callback
+    if (!mDemuxCallback) {
+        mDemuxCallback = new DemuxCallback();
+    }
+
+    // Add playback input to the local demux
+    status = mDemux->addInput(FMQ_SIZE_1M, mDemuxCallback);
+
+    if (status != Result::SUCCESS) {
+        return ::testing::AssertionFailure();
+    }
+
+    status = mDemux->configureInput(setting);
+
+    return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::getInputMQDescriptor() {
+    Result status;
+
+    if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
+        return ::testing::AssertionFailure();
+    }
+
+    mDemux->getInputQueueDesc([&](Result result, const MQDesc& inputMQDesc) {
+        mInputMQDescriptor = inputMQDesc;
+        status = result;
+    });
+
+    return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::addFilterToDemux(DemuxFilterType type,
+                                                           DemuxFilterSettings setting) {
+    Result status;
+
+    if (!mDemux && createDemux() == ::testing::AssertionFailure()) {
+        return ::testing::AssertionFailure();
+    }
+
+    // Create demux callback
+    if (!mDemuxCallback) {
+        mDemuxCallback = new DemuxCallback();
+    }
+
+    // Add filter to the local demux
+    mDemux->addFilter(type, FMQ_SIZE_4K, mDemuxCallback, [&](Result result, uint32_t filterId) {
+        // TODO use a map to save all the filter id and FMQ
+        mFilterId = filterId;
+        status = result;
+    });
+
+    if (status != Result::SUCCESS) {
+        return ::testing::AssertionFailure();
+    }
+
+    // Configure the filter
+    status = mDemux->configureFilter(mFilterId, setting);
+
+    return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::getFilterMQDescriptor(const uint32_t filterId) {
+    Result status;
+
+    if (!mDemux) {
+        return ::testing::AssertionFailure();
+    }
+
+    mDemux->getFilterQueueDesc(filterId, [&](Result result, const MQDesc& filterMQDesc) {
+        mFilterMQDescriptor = filterMQDesc;
+        status = result;
+    });
+
+    return ::testing::AssertionResult(status == Result::SUCCESS);
+}
+
+::testing::AssertionResult TunerHidlTest::playbackDataFlowTest(
+        vector<FilterConf> filterConf, InputConf inputConf, vector<string> /*goldenOutputFiles*/) {
+    Result status;
+    int filterIdsSize;
+    // Filter Configuration Module
+    for (int i = 0; i < filterConf.size(); i++) {
+        if (addFilterToDemux(filterConf[i].type, filterConf[i].setting) ==
+                    ::testing::AssertionFailure() ||
+            // TODO use a map to save the FMQs/EvenFlags and pass to callback
+            getFilterMQDescriptor(mFilterId) == ::testing::AssertionFailure()) {
+            return ::testing::AssertionFailure();
+        }
+        filterIdsSize = mUsedFilterIds.size();
+        mUsedFilterIds.resize(filterIdsSize + 1);
+        mUsedFilterIds[filterIdsSize] = mFilterId;
+        mDemuxCallback->updateFilterMQ(mFilterId, mFilterMQDescriptor);
+        // mDemuxCallback->updateGoldenOutputMap(mFilterId, goldenOutputFiles[i]);
+        status = mDemux->startFilter(mFilterId);
+        if (status != Result::SUCCESS) {
+            return ::testing::AssertionFailure();
+        }
+    }
+
+    // Playback Input Module
+    DemuxInputSettings inputSetting = inputConf.setting;
+    if (addInputToDemux(inputSetting) == ::testing::AssertionFailure() ||
+        getInputMQDescriptor() == ::testing::AssertionFailure()) {
+        return ::testing::AssertionFailure();
+    }
+    mDemuxCallback->startPlaybackInputThread(inputConf, mInputMQDescriptor);
+    status = mDemux->startInput();
+    if (status != Result::SUCCESS) {
+        return ::testing::AssertionFailure();
+    }
+
+    // Data Verify Module
+    mDemuxCallback->testFilterDataOutput();
+    mDemuxCallback->stopInputThread();
+
+    // Clean Up Module
+    for (int i = 0; i <= filterIdsSize; i++) {
+        if (mDemux->stopFilter(mUsedFilterIds[i]) != Result::SUCCESS) {
+            return ::testing::AssertionFailure();
+        }
+    }
+    if (mDemux->stopInput() != Result::SUCCESS) {
+        return ::testing::AssertionFailure();
+    }
+    return closeDemux();
+}
+
+::testing::AssertionResult TunerHidlTest::broadcastDataFlowTest(
+        vector<FilterConf> filterConf, vector<string> /*goldenOutputFiles*/) {
+    Result status;
+    hidl_vec<FrontendId> feIds;
+
+    mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
+        status = result;
+        feIds = frontendIds;
+    });
+
+    if (feIds.size() == 0) {
+        ALOGW("[   WARN   ] Frontend isn't available");
+        return ::testing::AssertionFailure();
+    }
+
+    FrontendDvbtSettings dvbt{
+            .frequency = 1000,
+    };
+    FrontendSettings settings;
+    settings.dvbt(dvbt);
+
+    if (createDemuxWithFrontend(feIds[0], settings) != ::testing::AssertionSuccess()) {
+        return ::testing::AssertionFailure();
+    }
+
+    int filterIdsSize;
+    // Filter Configuration Module
+    for (int i = 0; i < filterConf.size(); i++) {
+        if (addFilterToDemux(filterConf[i].type, filterConf[i].setting) ==
+                    ::testing::AssertionFailure() ||
+            // TODO use a map to save the FMQs/EvenFlags and pass to callback
+            getFilterMQDescriptor(mFilterId) == ::testing::AssertionFailure()) {
+            return ::testing::AssertionFailure();
+        }
+        filterIdsSize = mUsedFilterIds.size();
+        mUsedFilterIds.resize(filterIdsSize + 1);
+        mUsedFilterIds[filterIdsSize] = mFilterId;
+        mDemuxCallback->updateFilterMQ(mFilterId, mFilterMQDescriptor);
+        status = mDemux->startFilter(mFilterId);
+        if (status != Result::SUCCESS) {
+            return ::testing::AssertionFailure();
+        }
+    }
+
+    // Data Verify Module
+    mDemuxCallback->testFilterDataOutput();
+
+    // Clean Up Module
+    for (int i = 0; i <= filterIdsSize; i++) {
+        if (mDemux->stopFilter(mUsedFilterIds[i]) != Result::SUCCESS) {
+            return ::testing::AssertionFailure();
+        }
+    }
+    if (mFrontend->stopTune() != Result::SUCCESS) {
+        return ::testing::AssertionFailure();
+    }
+    return closeDemux();
+}
+
+/*
+ * API STATUS TESTS
+ */
+TEST_F(TunerHidlTest, CreateFrontend) {
+    Result status;
+    hidl_vec<FrontendId> feIds;
+
+    description("Create Frontends");
+    mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
+        status = result;
+        feIds = frontendIds;
+    });
+
+    if (feIds.size() == 0) {
+        ALOGW("[   WARN   ] Frontend isn't available");
+        return;
+    }
+
+    for (size_t i = 0; i < feIds.size(); i++) {
+        ASSERT_TRUE(createFrontend(feIds[i]));
+    }
+}
+
+TEST_F(TunerHidlTest, TuneFrontend) {
+    Result status;
+    hidl_vec<FrontendId> feIds;
+
+    description("Tune Frontends and check callback onEvent");
+    mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
+        status = result;
+        feIds = frontendIds;
+    });
+
+    if (feIds.size() == 0) {
+        ALOGW("[   WARN   ] Frontend isn't available");
+        return;
+    }
+
+    for (size_t i = 0; i < feIds.size(); i++) {
+        ASSERT_TRUE(tuneFrontend(feIds[i]));
+    }
+}
+
+TEST_F(TunerHidlTest, StopTuneFrontend) {
+    Result status;
+    hidl_vec<FrontendId> feIds;
+
+    description("stopTune Frontends");
+    mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
+        status = result;
+        feIds = frontendIds;
+    });
+
+    if (feIds.size() == 0) {
+        ALOGW("[   WARN   ] Frontend isn't available");
+        return;
+    }
+
+    for (size_t i = 0; i < feIds.size(); i++) {
+        ASSERT_TRUE(stopTuneFrontend(feIds[i]));
+    }
+}
+
+TEST_F(TunerHidlTest, CloseFrontend) {
+    Result status;
+    hidl_vec<FrontendId> feIds;
+
+    description("Close Frontends");
+    mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
+        status = result;
+        feIds = frontendIds;
+    });
+
+    if (feIds.size() == 0) {
+        ALOGW("[   WARN   ] Frontend isn't available");
+        return;
+    }
+
+    for (size_t i = 0; i < feIds.size(); i++) {
+        ASSERT_TRUE(closeFrontend(feIds[i]));
+    }
+}
+
+/*TEST_F(TunerHidlTest, CreateDemuxWithFrontend) {
+    Result status;
+    hidl_vec<FrontendId> feIds;
+
+    description("Create Demux with Frontend");
+    mService->getFrontendIds([&](Result result, const hidl_vec<FrontendId>& frontendIds) {
+        status = result;
+        feIds = frontendIds;
+    });
+
+    if (feIds.size() == 0) {
+        ALOGW("[   WARN   ] Frontend isn't available");
+        return;
+    }
+
+    FrontendDvbtSettings dvbt{
+        .frequency = 1000,
+    };
+    FrontendSettings settings;
+    settings.dvbt(dvbt);
+
+    for (size_t i = 0; i < feIds.size(); i++) {
+        ASSERT_TRUE(createDemuxWithFrontend(feIds[i], settings));
+        mFrontend->stopTune();
+    }
+}*/
+
+TEST_F(TunerHidlTest, CreateDemux) {
+    description("Create Demux");
+    ASSERT_TRUE(createDemux());
+}
+
+TEST_F(TunerHidlTest, CloseDemux) {
+    description("Close Demux");
+    ASSERT_TRUE(closeDemux());
+}
+
+TEST_F(TunerHidlTest, CreateDescrambler) {
+    description("Create Descrambler");
+    ASSERT_TRUE(createDescrambler());
+}
+
+TEST_F(TunerHidlTest, CloseDescrambler) {
+    description("Close Descrambler");
+    ASSERT_TRUE(closeDescrambler());
+}
+
+/*
+ * DATA FLOW TESTS
+ */
+TEST_F(TunerHidlTest, PlaybackDataFlowWithPesFilterTest) {
+    description("Feed ts data from playback and configure pes filter to get output");
+
+    // todo modulize the filter conf parser
+    vector<FilterConf> filterConf;
+    filterConf.resize(1);
+
+    DemuxFilterSettings filterSetting;
+    DemuxFilterPesDataSettings pesFilterSetting{
+            .tpid = 18,
+    };
+    filterSetting.pesData(pesFilterSetting);
+    FilterConf pesFilterConf{
+            .type = DemuxFilterType::PES,
+            .setting = filterSetting,
+    };
+    filterConf[0] = pesFilterConf;
+
+    DemuxInputSettings inputSetting{
+            .statusMask = 0xf,
+            .lowThreshold = 0x1000,
+            .highThreshold = 0x07fff,
+            .dataFormat = DemuxDataFormat::TS,
+            .packetSize = 188,
+    };
+
+    InputConf inputConf{
+            .inputDataFile = "/vendor/etc/test1.ts",
+            .setting = inputSetting,
+    };
+
+    vector<string> goldenOutputFiles;
+
+    ASSERT_TRUE(playbackDataFlowTest(filterConf, inputConf, goldenOutputFiles));
+}
+
+TEST_F(TunerHidlTest, BroadcastDataFlowWithPesFilterTest) {
+    description("Feed ts data from frontend and test with PES filter");
+
+    // todo modulize the filter conf parser
+    vector<FilterConf> filterConf;
+    filterConf.resize(1);
+
+    DemuxFilterSettings filterSetting;
+    DemuxFilterPesDataSettings pesFilterSetting{
+            .tpid = 18,
+    };
+    filterSetting.pesData(pesFilterSetting);
+    FilterConf pesFilterConf{
+            .type = DemuxFilterType::PES,
+            .setting = filterSetting,
+    };
+    filterConf[0] = pesFilterConf;
+
+    vector<string> goldenOutputFiles;
+
+    ASSERT_TRUE(broadcastDataFlowTest(filterConf, goldenOutputFiles));
+}
+
+}  // namespace
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(TunerHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    TunerHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
diff --git a/usb/1.0/Android.bp b/usb/1.0/Android.bp
index a00b671..c0e883f 100644
--- a/usb/1.0/Android.bp
+++ b/usb/1.0/Android.bp
@@ -17,4 +17,3 @@
     gen_java: true,
     gen_java_constants: true,
 }
-
diff --git a/usb/1.0/default/Android.bp b/usb/1.0/default/Android.bp
index 64de821..96d24c1 100644
--- a/usb/1.0/default/Android.bp
+++ b/usb/1.0/default/Android.bp
@@ -26,7 +26,6 @@
     shared_libs: [
         "libcutils",
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
         "libhardware",
diff --git a/usb/1.0/default/android.hardware.usb@1.0-service.rc b/usb/1.0/default/android.hardware.usb@1.0-service.rc
index b7a0c63..3c44d21 100644
--- a/usb/1.0/default/android.hardware.usb@1.0-service.rc
+++ b/usb/1.0/default/android.hardware.usb@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.usb-hal-1-0 /vendor/bin/hw/android.hardware.usb@1.0-service
+    interface android.hardware.usb@1.0::IUsb default
     class hal
     user system
     group system
diff --git a/usb/1.1/Android.bp b/usb/1.1/Android.bp
index fb2cc4e..6f2abae 100644
--- a/usb/1.1/Android.bp
+++ b/usb/1.1/Android.bp
@@ -18,4 +18,3 @@
     gen_java: true,
     gen_java_constants: true,
 }
-
diff --git a/usb/1.2/Android.bp b/usb/1.2/Android.bp
index 5206754..b3ba81f 100644
--- a/usb/1.2/Android.bp
+++ b/usb/1.2/Android.bp
@@ -19,4 +19,3 @@
     gen_java: true,
     gen_java_constants: true,
 }
-
diff --git a/usb/gadget/1.0/Android.bp b/usb/gadget/1.0/Android.bp
index 7ee432b..4921abf 100644
--- a/usb/gadget/1.0/Android.bp
+++ b/usb/gadget/1.0/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/vibrator/1.0/Android.bp b/vibrator/1.0/Android.bp
index acc97d4..792e130 100644
--- a/vibrator/1.0/Android.bp
+++ b/vibrator/1.0/Android.bp
@@ -16,4 +16,3 @@
     gen_java: true,
     gen_java_constants: true,
 }
-
diff --git a/vibrator/1.0/default/Android.bp b/vibrator/1.0/default/Android.bp
index 0c7d155..b0d0986 100644
--- a/vibrator/1.0/default/Android.bp
+++ b/vibrator/1.0/default/Android.bp
@@ -21,7 +21,6 @@
     srcs: ["Vibrator.cpp"],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
         "libhardware",
@@ -39,7 +38,6 @@
 
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
         "libhardware",
diff --git a/vibrator/1.0/default/android.hardware.vibrator@1.0-service.rc b/vibrator/1.0/default/android.hardware.vibrator@1.0-service.rc
index 1123eab..1bd5c10 100644
--- a/vibrator/1.0/default/android.hardware.vibrator@1.0-service.rc
+++ b/vibrator/1.0/default/android.hardware.vibrator@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.vibrator-1-0 /vendor/bin/hw/android.hardware.vibrator@1.0-service
+    interface android.hardware.vibrator@1.0::IVibrator default
     class hal
     user system
     group system
diff --git a/vibrator/1.1/Android.bp b/vibrator/1.1/Android.bp
index 2055e5a..0d04a87 100644
--- a/vibrator/1.1/Android.bp
+++ b/vibrator/1.1/Android.bp
@@ -17,4 +17,3 @@
     gen_java: true,
     gen_java_constants: true,
 }
-
diff --git a/vibrator/1.2/Android.bp b/vibrator/1.2/Android.bp
index 481adee..290a0cf 100644
--- a/vibrator/1.2/Android.bp
+++ b/vibrator/1.2/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/vibrator/1.3/Android.bp b/vibrator/1.3/Android.bp
index a2ff784..357ea9a 100644
--- a/vibrator/1.3/Android.bp
+++ b/vibrator/1.3/Android.bp
@@ -7,8 +7,8 @@
         enabled: true,
     },
     srcs: [
-        "IVibrator.hal",
         "types.hal",
+        "IVibrator.hal",
     ],
     interfaces: [
         "android.hardware.vibrator@1.0",
@@ -18,4 +18,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/vibrator/1.3/example/Android.bp b/vibrator/1.3/example/Android.bp
index 36f2ff8..07f1c26 100644
--- a/vibrator/1.3/example/Android.bp
+++ b/vibrator/1.3/example/Android.bp
@@ -23,7 +23,6 @@
     cflags: ["-Wall", "-Werror"],
     shared_libs: [
         "libhidlbase",
-        "libhidltransport",
         "liblog",
         "libutils",
         "android.hardware.vibrator@1.0",
diff --git a/vr/1.0/Android.bp b/vr/1.0/Android.bp
index ca47a6e..f91f874 100644
--- a/vr/1.0/Android.bp
+++ b/vr/1.0/Android.bp
@@ -14,4 +14,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/vr/1.0/default/Android.bp b/vr/1.0/default/Android.bp
index ddc1bfb..cfb2808 100644
--- a/vr/1.0/default/Android.bp
+++ b/vr/1.0/default/Android.bp
@@ -12,7 +12,6 @@
         "libcutils",
         "libutils",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.vr@1.0",
     ],
 }
@@ -30,7 +29,6 @@
         "libutils",
         "libhardware",
         "libhidlbase",
-        "libhidltransport",
         "android.hardware.vr@1.0",
     ],
 }
diff --git a/vr/1.0/default/android.hardware.vr@1.0-service.rc b/vr/1.0/default/android.hardware.vr@1.0-service.rc
index fc4934c..5486674 100644
--- a/vr/1.0/default/android.hardware.vr@1.0-service.rc
+++ b/vr/1.0/default/android.hardware.vr@1.0-service.rc
@@ -1,4 +1,5 @@
 service vendor.vr-1-0 /vendor/bin/hw/android.hardware.vr@1.0-service
+    interface android.hardware.vr@1.0::IVr default
     class hal
     user system
     group system
diff --git a/weaver/1.0/Android.bp b/weaver/1.0/Android.bp
index 7f93b10..7d5b8fe 100644
--- a/weaver/1.0/Android.bp
+++ b/weaver/1.0/Android.bp
@@ -15,4 +15,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/wifi/1.0/Android.bp b/wifi/1.0/Android.bp
index c5ee1bb..958ff3f 100644
--- a/wifi/1.0/Android.bp
+++ b/wifi/1.0/Android.bp
@@ -28,4 +28,3 @@
     gen_java: true,
     gen_java_constants: true,
 }
-
diff --git a/wifi/1.0/IWifiP2pIface.hal b/wifi/1.0/IWifiP2pIface.hal
index b908591..025f7ab 100644
--- a/wifi/1.0/IWifiP2pIface.hal
+++ b/wifi/1.0/IWifiP2pIface.hal
@@ -19,6 +19,6 @@
 import IWifiIface;
 
 /**
- * Interface used to represent a single NAN iface.
+ * Interface used to represent a single P2P iface.
  */
 interface IWifiP2pIface extends IWifiIface {};
diff --git a/wifi/1.1/Android.bp b/wifi/1.1/Android.bp
index a4499c8..a34ac44 100644
--- a/wifi/1.1/Android.bp
+++ b/wifi/1.1/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/wifi/1.2/Android.bp b/wifi/1.2/Android.bp
index 1863eaf..c28d09b 100644
--- a/wifi/1.2/Android.bp
+++ b/wifi/1.2/Android.bp
@@ -22,4 +22,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/wifi/1.3/Android.bp b/wifi/1.3/Android.bp
index 401c7a6..3719c2b 100644
--- a/wifi/1.3/Android.bp
+++ b/wifi/1.3/Android.bp
@@ -20,4 +20,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/wifi/1.3/default/Android.mk b/wifi/1.3/default/Android.mk
index 0a3809c..29f1c42 100644
--- a/wifi/1.3/default/Android.mk
+++ b/wifi/1.3/default/Android.mk
@@ -59,7 +59,6 @@
     libbase \
     libcutils \
     libhidlbase \
-    libhidltransport \
     liblog \
     libnl \
     libutils \
@@ -86,7 +85,6 @@
     libbase \
     libcutils \
     libhidlbase \
-    libhidltransport \
     liblog \
     libnl \
     libutils \
@@ -117,7 +115,6 @@
     libbase \
     libcutils \
     libhidlbase \
-    libhidltransport \
     liblog \
     libnl \
     libutils \
@@ -160,7 +157,6 @@
     libbase \
     libcutils \
     libhidlbase \
-    libhidltransport \
     liblog \
     libnl \
     libutils \
diff --git a/wifi/1.3/default/android.hardware.wifi@1.0-service.rc b/wifi/1.3/default/android.hardware.wifi@1.0-service.rc
index cf849d0..2317bac 100644
--- a/wifi/1.3/default/android.hardware.wifi@1.0-service.rc
+++ b/wifi/1.3/default/android.hardware.wifi@1.0-service.rc
@@ -1,4 +1,7 @@
 service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service
+    interface android.hardware.wifi@1.0::IWifi default
+    interface android.hardware.wifi@1.1::IWifi default
+    interface android.hardware.wifi@1.2::IWifi default
     class hal
     capabilities NET_ADMIN NET_RAW SYS_MODULE
     user wifi
diff --git a/wifi/1.3/default/service.cpp b/wifi/1.3/default/service.cpp
index fcbc37c..0b41d28 100644
--- a/wifi/1.3/default/service.cpp
+++ b/wifi/1.3/default/service.cpp
@@ -58,7 +58,7 @@
             std::make_shared<WifiIfaceUtil>(iface_tool),
             std::make_shared<WifiFeatureFlags>());
     if (kLazyService) {
-        LazyServiceRegistrar registrar;
+        auto registrar = LazyServiceRegistrar::getInstance();
         CHECK_EQ(registrar.registerService(service), android::NO_ERROR)
             << "Failed to register wifi HAL";
     } else {
diff --git a/wifi/hostapd/1.0/Android.bp b/wifi/hostapd/1.0/Android.bp
index 9ee976e..cce1182 100644
--- a/wifi/hostapd/1.0/Android.bp
+++ b/wifi/hostapd/1.0/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/wifi/hostapd/1.0/vts/functional/Android.bp b/wifi/hostapd/1.0/vts/functional/Android.bp
index 93867d2..5645019 100644
--- a/wifi/hostapd/1.0/vts/functional/Android.bp
+++ b/wifi/hostapd/1.0/vts/functional/Android.bp
@@ -26,7 +26,6 @@
         "android.hardware.wifi.hostapd@1.0",
         "android.hardware.wifi.hostapd@1.1",
         "android.hardware.wifi@1.0",
-        "libcrypto",
         "libgmock",
         "libwifi-system",
         "libwifi-system-iface",
@@ -46,7 +45,6 @@
         "android.hardware.wifi.hostapd@1.0",
         "android.hardware.wifi.hostapd@1.1",
         "android.hardware.wifi@1.0",
-        "libcrypto",
         "libgmock",
         "libwifi-system",
         "libwifi-system-iface",
diff --git a/wifi/hostapd/1.1/Android.bp b/wifi/hostapd/1.1/Android.bp
index d4170b6..64fbc93 100644
--- a/wifi/hostapd/1.1/Android.bp
+++ b/wifi/hostapd/1.1/Android.bp
@@ -17,4 +17,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/wifi/hostapd/1.1/vts/functional/Android.bp b/wifi/hostapd/1.1/vts/functional/Android.bp
index bbf5246..02ec2e6 100644
--- a/wifi/hostapd/1.1/vts/functional/Android.bp
+++ b/wifi/hostapd/1.1/vts/functional/Android.bp
@@ -27,7 +27,6 @@
         "android.hardware.wifi.hostapd@1.0",
         "android.hardware.wifi.hostapd@1.1",
         "android.hardware.wifi@1.0",
-        "libcrypto",
         "libgmock",
         "libwifi-system",
         "libwifi-system-iface",
@@ -48,7 +47,6 @@
         "android.hardware.wifi.hostapd@1.0",
         "android.hardware.wifi.hostapd@1.1",
         "android.hardware.wifi@1.0",
-        "libcrypto",
         "libgmock",
         "libwifi-system",
         "libwifi-system-iface",
diff --git a/wifi/offload/1.0/Android.bp b/wifi/offload/1.0/Android.bp
index 1a9ae73..110bb70 100644
--- a/wifi/offload/1.0/Android.bp
+++ b/wifi/offload/1.0/Android.bp
@@ -16,4 +16,3 @@
     ],
     gen_java: false,
 }
-
diff --git a/wifi/supplicant/1.0/Android.bp b/wifi/supplicant/1.0/Android.bp
index c99706d..d91512f 100644
--- a/wifi/supplicant/1.0/Android.bp
+++ b/wifi/supplicant/1.0/Android.bp
@@ -26,4 +26,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/wifi/supplicant/1.0/vts/functional/Android.bp b/wifi/supplicant/1.0/vts/functional/Android.bp
index bdccac1..ba79738 100644
--- a/wifi/supplicant/1.0/vts/functional/Android.bp
+++ b/wifi/supplicant/1.0/vts/functional/Android.bp
@@ -26,7 +26,6 @@
         "android.hardware.wifi.supplicant@1.0",
         "android.hardware.wifi.supplicant@1.1",
         "android.hardware.wifi@1.0",
-        "libcrypto",
         "libgmock",
         "libwifi-system",
         "libwifi-system-iface",
@@ -48,7 +47,6 @@
         "android.hardware.wifi.supplicant@1.0",
         "android.hardware.wifi.supplicant@1.1",
         "android.hardware.wifi@1.0",
-        "libcrypto",
         "libgmock",
         "libwifi-system",
         "libwifi-system-iface",
@@ -69,7 +67,6 @@
         "android.hardware.wifi.supplicant@1.0",
         "android.hardware.wifi.supplicant@1.1",
         "android.hardware.wifi@1.0",
-        "libcrypto",
         "libgmock",
         "libwifi-system",
         "libwifi-system-iface",
diff --git a/wifi/supplicant/1.1/Android.bp b/wifi/supplicant/1.1/Android.bp
index 832d1ad..6d940d1 100644
--- a/wifi/supplicant/1.1/Android.bp
+++ b/wifi/supplicant/1.1/Android.bp
@@ -18,4 +18,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/wifi/supplicant/1.1/vts/functional/Android.bp b/wifi/supplicant/1.1/vts/functional/Android.bp
index 353ae4b..8457532 100644
--- a/wifi/supplicant/1.1/vts/functional/Android.bp
+++ b/wifi/supplicant/1.1/vts/functional/Android.bp
@@ -27,7 +27,6 @@
         "android.hardware.wifi.supplicant@1.0",
         "android.hardware.wifi.supplicant@1.1",
         "android.hardware.wifi@1.0",
-        "libcrypto",
         "libgmock",
         "libwifi-system",
         "libwifi-system-iface",
@@ -51,7 +50,6 @@
         "android.hardware.wifi.supplicant@1.1",
         "android.hardware.wifi@1.0",
         "android.hardware.wifi@1.1",
-        "libcrypto",
         "libgmock",
         "libwifi-system",
         "libwifi-system-iface",
diff --git a/wifi/supplicant/1.2/Android.bp b/wifi/supplicant/1.2/Android.bp
index c685022..185d2b8 100644
--- a/wifi/supplicant/1.2/Android.bp
+++ b/wifi/supplicant/1.2/Android.bp
@@ -21,4 +21,3 @@
     ],
     gen_java: true,
 }
-
diff --git a/wifi/supplicant/1.2/vts/functional/Android.bp b/wifi/supplicant/1.2/vts/functional/Android.bp
index 1b970e1..b7949d1 100644
--- a/wifi/supplicant/1.2/vts/functional/Android.bp
+++ b/wifi/supplicant/1.2/vts/functional/Android.bp
@@ -29,7 +29,6 @@
         "android.hardware.wifi.supplicant@1.1",
         "android.hardware.wifi.supplicant@1.2",
         "android.hardware.wifi@1.0",
-        "libcrypto",
         "libgmock",
         "libwifi-system",
         "libwifi-system-iface",
@@ -54,7 +53,6 @@
         "android.hardware.wifi.supplicant@1.2",
         "android.hardware.wifi@1.0",
         "android.hardware.wifi@1.1",
-        "libcrypto",
         "libgmock",
         "libwifi-system",
         "libwifi-system-iface",
@@ -79,7 +77,6 @@
         "android.hardware.wifi.supplicant@1.2",
         "android.hardware.wifi@1.0",
         "android.hardware.wifi@1.1",
-        "libcrypto",
         "libgmock",
         "libwifi-system",
         "libwifi-system-iface",