Test getActiveMicrophones API when mic is found on the device.
am: 497edcc026

Change-Id: I55a1ab98ef141b9834ec22491b31e09f581fca1a
diff --git a/Android.bp b/Android.bp
index 5cb85b4..05ca928 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,6 +1,5 @@
 hidl_package_root {
     name: "android.hardware",
-    path: "hardware/interfaces",
 }
 
 cc_defaults {
@@ -19,6 +18,7 @@
     // Lists all dependencies that can *not* be expected on the device.
     static_libs: [
         "VtsHalHidlTargetTestBase",
+        "libhidl-gen-utils",
     ],
     group_static_libs: true,
 
diff --git a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
index 4dc01e7..f84e1e2 100644
--- a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
@@ -61,7 +61,7 @@
 using ::android::sp;
 using ::android::hardware::EventFlag;
 using ::android::hardware::hidl_bitfield;
-using ::android::hardware::hidl_enum_iterator;
+using ::android::hardware::hidl_enum_range;
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
@@ -1174,7 +1174,7 @@
 TEST_P(InputStreamTest, updateSinkMetadata) {
     doc::test("The HAL should not crash on metadata change");
 
-    hidl_enum_iterator<AudioSource> range;
+    hidl_enum_range<AudioSource> range;
     // Test all possible track configuration
     for (AudioSource source : range) {
         for (float volume : {0.0, 0.5, 1.0}) {
@@ -1418,8 +1418,8 @@
 TEST_P(OutputStreamTest, updateSourceMetadata) {
     doc::test("The HAL should not crash on metadata change");
 
-    hidl_enum_iterator<AudioUsage> usageRange;
-    hidl_enum_iterator<AudioContentType> contentRange;
+    hidl_enum_range<AudioUsage> usageRange;
+    hidl_enum_range<AudioContentType> contentRange;
     // Test all possible track configuration
     for (auto usage : usageRange) {
         for (auto content : contentRange) {
diff --git a/audio/core/all-versions/default/include/core/all-versions/default/Stream.h b/audio/core/all-versions/default/include/core/all-versions/default/Stream.h
index 6f79429..7cf12dd 100644
--- a/audio/core/all-versions/default/include/core/all-versions/default/Stream.h
+++ b/audio/core/all-versions/default/include/core/all-versions/default/Stream.h
@@ -163,8 +163,23 @@
         if (retval == Result::OK) {
             hidlHandle = native_handle_create(1, 0);
             hidlHandle->data[0] = halInfo.shared_memory_fd;
-            info.sharedMemory =
+
+            // Negative buffer size frame is a legacy hack to indicate that the buffer
+            // is shareable to applications before the relevant flag was introduced
+            bool applicationShareable =
+                halInfo.flags & AUDIO_MMAP_APPLICATION_SHAREABLE || halInfo.buffer_size_frames < 0;
+            halInfo.buffer_size_frames = abs(halInfo.buffer_size_frames);
+            info.sharedMemory =  // hidl_memory size must always be positive
                 hidl_memory("audio_buffer", hidlHandle, frameSize * halInfo.buffer_size_frames);
+#ifdef AUDIO_HAL_VERSION_2_0
+            if (applicationShareable) {
+                halInfo.buffer_size_frames *= -1;
+            }
+#else
+            info.flags =
+                halInfo.flags | (applicationShareable ? MmapBufferFlag::APPLICATION_SHAREABLE
+                                                      : MmapBufferFlag::NONE);
+#endif
             info.bufferSizeFrames = halInfo.buffer_size_frames;
             info.burstSizeFrames = halInfo.burst_size_frames;
         }
diff --git a/automotive/audiocontrol/1.0/vts/functional/VtsHalAudioControlV1_0TargetTest.cpp b/automotive/audiocontrol/1.0/vts/functional/VtsHalAudioControlV1_0TargetTest.cpp
index 68ed778..fc0deb9 100644
--- a/automotive/audiocontrol/1.0/vts/functional/VtsHalAudioControlV1_0TargetTest.cpp
+++ b/automotive/audiocontrol/1.0/vts/functional/VtsHalAudioControlV1_0TargetTest.cpp
@@ -34,7 +34,7 @@
 using namespace ::android::hardware::automotive::audiocontrol::V1_0;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using ::android::hardware::hidl_enum_iterator;
+using ::android::hardware::hidl_enum_range;
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
@@ -132,7 +132,7 @@
     int bus = -1;
 
     // For each defined context, query the driver for the BUS on which it should be delivered
-    for (const auto& ctxt : hidl_enum_iterator<ContextNumber>()) {
+    for (const auto& ctxt : hidl_enum_range<ContextNumber>()) {
          bus = pAudioControl->getBusForContext(ctxt);
 
          if (ctxt == ContextNumber::INVALID) {
@@ -147,8 +147,8 @@
     }
 
     // Try asking about an invalid context one beyond the last defined to see that it gets back a -1
-    int contextRange = std::distance(hidl_enum_iterator<ContextNumber>().begin(),
-                                     hidl_enum_iterator<ContextNumber>().end());
+    int contextRange = std::distance(hidl_enum_range<ContextNumber>().begin(),
+                                     hidl_enum_range<ContextNumber>().end());
     bus = pAudioControl->getBusForContext((ContextNumber)contextRange);
     EXPECT_EQ(bus, -1);
 
diff --git a/automotive/evs/1.0/Android.bp b/automotive/evs/1.0/Android.bp
index 4bc4068..f620eb5 100644
--- a/automotive/evs/1.0/Android.bp
+++ b/automotive/evs/1.0/Android.bp
@@ -23,6 +23,6 @@
         "DisplayState",
         "EvsResult",
     ],
-    gen_java: false,
+    gen_java: true,
 }
 
diff --git a/automotive/evs/1.0/vts/functional/Android.bp b/automotive/evs/1.0/vts/functional/Android.bp
index 6ac2458..5d696fc 100644
--- a/automotive/evs/1.0/vts/functional/Android.bp
+++ b/automotive/evs/1.0/vts/functional/Android.bp
@@ -23,20 +23,13 @@
         "FormatConvert.cpp"
     ],
 
-    defaults: [
-        "hidl_defaults",
-    ],
+    defaults: ["VtsHalTargetTestDefaults"],
 
     shared_libs: [
-        "android.hardware.automotive.evs@1.0",
-        "liblog",
-        "libutils",
         "libui",
-        "libhidlbase",
-        "libhidltransport",
     ],
 
-    static_libs: ["VtsHalHidlTargetTestBase"],
+    static_libs: ["android.hardware.automotive.evs@1.0"],
 
     cflags: [
         "-O0",
diff --git a/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp b/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp
index 9911038..d577ce4 100644
--- a/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp
+++ b/biometrics/fingerprint/2.1/vts/functional/VtsHalBiometricsFingerprintV2_1TargetTest.cpp
@@ -24,6 +24,7 @@
 #include <android/hardware/biometrics/fingerprint/2.1/IBiometricsFingerprintClientCallback.h>
 #include <hidl/HidlSupport.h>
 #include <hidl/HidlTransportSupport.h>
+#include <utils/Condition.h>
 
 #include <cinttypes>
 #include <future>
diff --git a/boot/1.0/default/Android.bp b/boot/1.0/default/Android.bp
index 6cfbf32..67dee08 100644
--- a/boot/1.0/default/Android.bp
+++ b/boot/1.0/default/Android.bp
@@ -2,7 +2,8 @@
     name: "android.hardware.boot@1.0-impl",
     defaults: ["hidl_defaults"],
     relative_install_path: "hw",
-    vendor: true,
+    vendor_available: true,
+    recovery_available: true,
     srcs: ["BootControl.cpp"],
 
     shared_libs: [
diff --git a/camera/common/1.0/default/VendorTagDescriptor.cpp b/camera/common/1.0/default/VendorTagDescriptor.cpp
index 1f53857..052bf5b 100644
--- a/camera/common/1.0/default/VendorTagDescriptor.cpp
+++ b/camera/common/1.0/default/VendorTagDescriptor.cpp
@@ -258,7 +258,7 @@
 
     for (size_t i = 0; i < static_cast<size_t>(tagCount); ++i) {
         uint32_t tag = tagArray[i];
-        String8 sectionString = tagToSectionMap.valueFor(tag);
+        const String8& sectionString = tagToSectionMap.valueFor(tag);
 
         // Set up tag to section index map
         ssize_t index = sections.indexOf(sectionString);
diff --git a/camera/device/1.0/Android.bp b/camera/device/1.0/Android.bp
index dbf2a10..b08f873 100644
--- a/camera/device/1.0/Android.bp
+++ b/camera/device/1.0/Android.bp
@@ -29,6 +29,6 @@
         "NotifyCallbackMsg",
         "VideoFrameMessage",
     ],
-    gen_java: false,
+    gen_java: true,
 }
 
diff --git a/camera/device/3.4/default/ExternalCameraDevice.cpp b/camera/device/3.4/default/ExternalCameraDevice.cpp
index ee7ffaa..e7361dd 100644
--- a/camera/device/3.4/default/ExternalCameraDevice.cpp
+++ b/camera/device/3.4/default/ExternalCameraDevice.cpp
@@ -90,7 +90,7 @@
 }
 
 Return<Status> ExternalCameraDevice::setTorchMode(TorchMode) {
-    return Status::METHOD_NOT_SUPPORTED;
+    return Status::OPERATION_NOT_SUPPORTED;
 }
 
 Return<void> ExternalCameraDevice::open(
@@ -290,8 +290,14 @@
     UPDATE(ANDROID_HOT_PIXEL_AVAILABLE_HOT_PIXEL_MODES, &hotPixelMode, 1);
 
     // android.jpeg
-    // TODO: b/72261675 See if we can provide thumbnail size for all jpeg aspect ratios
-    const int32_t jpegAvailableThumbnailSizes[] = {0, 0, 240, 180};
+    const int32_t jpegAvailableThumbnailSizes[] = {0, 0,
+                                                  176, 144,
+                                                  240, 144,
+                                                  256, 144,
+                                                  240, 160,
+                                                  256, 154,
+                                                  240, 240,
+                                                  320, 240};
     UPDATE(ANDROID_JPEG_AVAILABLE_THUMBNAIL_SIZES, jpegAvailableThumbnailSizes,
            ARRAY_SIZE(jpegAvailableThumbnailSizes));
 
@@ -787,7 +793,8 @@
 std::vector<SupportedV4L2Format>
 ExternalCameraDevice::getCandidateSupportedFormatsLocked(
         int fd, CroppingType cropType,
-        const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits) {
+        const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits,
+        const Size& minStreamSize) {
     std::vector<SupportedV4L2Format> outFmts;
     struct v4l2_fmtdesc fmtdesc {
         .index = 0,
@@ -822,6 +829,11 @@
                         if (frameSize.discrete.height > frameSize.discrete.width) {
                             continue;
                         }
+                        // Discard all formats which is smaller than minStreamSize
+                        if (frameSize.discrete.width < minStreamSize.width
+                            || frameSize.discrete.height < minStreamSize.height) {
+                            continue;
+                        }
                         SupportedV4L2Format format {
                             .width = frameSize.discrete.width,
                             .height = frameSize.discrete.height,
@@ -864,9 +876,9 @@
 void ExternalCameraDevice::initSupportedFormatsLocked(int fd) {
 
     std::vector<SupportedV4L2Format> horizontalFmts =
-            getCandidateSupportedFormatsLocked(fd, HORIZONTAL, mCfg.fpsLimits);
+            getCandidateSupportedFormatsLocked(fd, HORIZONTAL, mCfg.fpsLimits, mCfg.minStreamSize);
     std::vector<SupportedV4L2Format> verticalFmts =
-            getCandidateSupportedFormatsLocked(fd, VERTICAL, mCfg.fpsLimits);
+            getCandidateSupportedFormatsLocked(fd, VERTICAL, mCfg.fpsLimits, mCfg.minStreamSize);
 
     size_t horiSize = horizontalFmts.size();
     size_t vertSize = verticalFmts.size();
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
index 1af3f39..28ca0f3 100644
--- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
@@ -2727,7 +2727,7 @@
     const uint8_t controlMode = ANDROID_CONTROL_MODE_AUTO;
     UPDATE(md, ANDROID_CONTROL_MODE, &controlMode, 1);
 
-    auto requestTemplates = hidl_enum_iterator<RequestTemplate>();
+    auto requestTemplates = hidl_enum_range<RequestTemplate>();
     for (RequestTemplate type : requestTemplates) {
         ::android::hardware::camera::common::V1_0::helper::CameraMetadata mdCopy = md;
         uint8_t intent = ANDROID_CONTROL_CAPTURE_INTENT_PREVIEW;
diff --git a/camera/device/3.4/default/ExternalCameraUtils.cpp b/camera/device/3.4/default/ExternalCameraUtils.cpp
index 2e2f73b..680c95a 100644
--- a/camera/device/3.4/default/ExternalCameraUtils.cpp
+++ b/camera/device/3.4/default/ExternalCameraUtils.cpp
@@ -267,6 +267,15 @@
         ret.fpsLimits = limits;
     }
 
+    XMLElement *minStreamSize = deviceCfg->FirstChildElement("MinimumStreamSize");
+    if (minStreamSize == nullptr) {
+       ALOGI("%s: no minimum stream size specified", __FUNCTION__);
+    } else {
+        ret.minStreamSize = {
+                minStreamSize->UnsignedAttribute("width", /*Default*/0),
+                minStreamSize->UnsignedAttribute("height", /*Default*/0)};
+    }
+
     ALOGI("%s: external camera cfg loaded: maxJpgBufSize %d,"
             " num video buffers %d, num still buffers %d",
             __FUNCTION__, ret.maxJpegBufSize,
@@ -275,6 +284,8 @@
         ALOGI("%s: fpsLimitList: %dx%d@%f", __FUNCTION__,
                 limit.size.width, limit.size.height, limit.fpsUpperBound);
     }
+    ALOGI("%s: minStreamSize: %dx%d" , __FUNCTION__,
+         ret.minStreamSize.width, ret.minStreamSize.height);
     return ret;
 }
 
@@ -285,6 +296,7 @@
     fpsLimits.push_back({/*Size*/{ 640,  480}, /*FPS upper bound*/30.0});
     fpsLimits.push_back({/*Size*/{1280,  720}, /*FPS upper bound*/7.5});
     fpsLimits.push_back({/*Size*/{1920, 1080}, /*FPS upper bound*/5.0});
+    minStreamSize = {0, 0};
 }
 
 
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
index a52f0e4..ff0cfb3 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraDevice_3_4.h
@@ -96,7 +96,8 @@
     // Get candidate supported formats list of input cropping type.
     static std::vector<SupportedV4L2Format> getCandidateSupportedFormatsLocked(
             int fd, CroppingType cropType,
-            const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits);
+            const std::vector<ExternalCameraConfig::FpsLimitation>& fpsLimits,
+            const Size& minStreamSize);
     // Trim supported format list by the cropping type. Also sort output formats by width/height
     static void trimSupportedFormats(CroppingType cropType,
             /*inout*/std::vector<SupportedV4L2Format>* pFmts);
diff --git a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
index 37e7cfb..5754ccb 100644
--- a/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
+++ b/camera/device/3.4/default/include/ext_device_v3_4_impl/ExternalCameraUtils.h
@@ -77,6 +77,9 @@
     };
     std::vector<FpsLimitation> fpsLimits;
 
+    // Minimum output stream size
+    Size minStreamSize;
+
 private:
     ExternalCameraConfig();
 };
diff --git a/camera/provider/2.4/default/ExternalCameraProvider.cpp b/camera/provider/2.4/default/ExternalCameraProvider.cpp
index a4046d0..1cec0e5 100644
--- a/camera/provider/2.4/default/ExternalCameraProvider.cpp
+++ b/camera/provider/2.4/default/ExternalCameraProvider.cpp
@@ -105,8 +105,9 @@
 
 Return<void> ExternalCameraProvider::isSetTorchModeSupported(
         isSetTorchModeSupported_cb _hidl_cb) {
-    // No torch mode support for USB camera
-    _hidl_cb (Status::OK, false);
+    // setTorchMode API is supported, though right now no external camera device
+    // has a flash unit.
+    _hidl_cb (Status::OK, true);
     return Void();
 }
 
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index 3702cf0..22d0412 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -70,6 +70,18 @@
 
 include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
 
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/clear_vars.mk
+LOCAL_MODULE := framework_compatibility_matrix.current.xml
+LOCAL_MODULE_STEM := compatibility_matrix.current.xml
+LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
+LOCAL_KERNEL_CONFIG_DATA_PATHS := \
+    4.4.0:$(my_kernel_config_data)/android-4.4 \
+    4.9.0:$(my_kernel_config_data)/android-4.9 \
+    4.14.0:$(my_kernel_config_data)/android-4.14 \
+
+include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
+
 my_kernel_config_data :=
 
 # Framework Compatibility Matrix (common to all FCM versions)
@@ -113,43 +125,42 @@
     PLATFORM_SEPOLICY_VERSION \
     PLATFORM_SEPOLICY_COMPAT_VERSIONS
 
-LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE := PRODUCT_ENFORCE_VINTF_MANIFEST=true
-LOCAL_ASSEMBLE_VINTF_ERROR_MESSAGE := \
-    "Error: DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX cannot contain required HALs."
-
 include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
 
-# Framework Compatibility Matrix
-
-include $(CLEAR_VARS)
-include $(LOCAL_PATH)/clear_vars.mk
-LOCAL_MODULE := framework_compatibility_matrix.xml
-LOCAL_MODULE_STEM := compatibility_matrix.xml
-LOCAL_MODULE_PATH := $(TARGET_OUT)
-LOCAL_REQUIRED_MODULES := \
+my_system_matrix_deps := \
     framework_compatibility_matrix.legacy.xml \
     framework_compatibility_matrix.1.xml \
     framework_compatibility_matrix.2.xml \
     framework_compatibility_matrix.3.xml \
+    framework_compatibility_matrix.current.xml \
     framework_compatibility_matrix.device.xml
+
+# Phony target that installs all framework compatibility matrix files
+include $(CLEAR_VARS)
+LOCAL_MODULE := framework_compatibility_matrix.xml
+LOCAL_REQUIRED_MODULES := $(my_system_matrix_deps)
+include $(BUILD_PHONY_PACKAGE)
+
+# Final Framework Compatibility Matrix for OTA
+include $(CLEAR_VARS)
+include $(LOCAL_PATH)/clear_vars.mk
+LOCAL_MODULE := verified_assembled_system_matrix.xml
+LOCAL_MODULE_PATH := $(PRODUCT_OUT)
+LOCAL_REQUIRED_MODULES := $(my_system_matrix_deps)
 LOCAL_GENERATED_SOURCES := $(call module-installed-files,$(LOCAL_REQUIRED_MODULES))
+LOCAL_ADD_VBMETA_VERSION_OVERRIDE := true
 
 ifdef BUILT_VENDOR_MANIFEST
 LOCAL_GEN_FILE_DEPENDENCIES += $(BUILT_VENDOR_MANIFEST)
 LOCAL_ASSEMBLE_VINTF_FLAGS += -c "$(BUILT_VENDOR_MANIFEST)"
 endif
 
-LOCAL_ASSEMBLE_VINTF_ENV_VARS := PRODUCT_ENFORCE_VINTF_MANIFEST
-
-# TODO(b/65028233): Enforce no "unused HALs" for devices that does not define
-# DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE as well
-ifeq (true,$(strip $(PRODUCT_ENFORCE_VINTF_MANIFEST)))
-ifdef DEVICE_FRAMEWORK_COMPATIBILITY_MATRIX_FILE
-LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE := VINTF_ENFORCE_NO_UNUSED_HALS=true
-endif
+ifneq ($(PRODUCT_OTA_ENFORCE_VINTF_KERNEL_REQUIREMENTS),true)
+LOCAL_ASSEMBLE_VINTF_FLAGS += --no-kernel-requirements
 endif
 
 include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
-BUILT_SYSTEM_COMPATIBILITY_MATRIX := $(LOCAL_BUILT_MODULE)
+BUILT_SYSTEM_MATRIX := $(LOCAL_BUILT_MODULE)
 
+my_system_matrix_deps :=
 BUILD_FRAMEWORK_COMPATIBILITY_MATRIX :=
diff --git a/compatibility_matrices/clear_vars.mk b/compatibility_matrices/clear_vars.mk
index 8fde301..0e53885 100644
--- a/compatibility_matrices/clear_vars.mk
+++ b/compatibility_matrices/clear_vars.mk
@@ -16,6 +16,7 @@
 
 # Clear input variables to BUILD_FRAMEWORK_COMPATIBILITY_MATRIX
 LOCAL_ADD_VBMETA_VERSION :=
+LOCAL_ADD_VBMETA_VERSION_OVERRIDE :=
 LOCAL_ASSEMBLE_VINTF_ENV_VARS :=
 LOCAL_ASSEMBLE_VINTF_ENV_VARS_OVERRIDE :=
 LOCAL_ASSEMBLE_VINTF_ERROR_MESSAGE :=
diff --git a/compatibility_matrices/compatibility_matrix.1.xml b/compatibility_matrices/compatibility_matrix.1.xml
index 6ba87c0..d82829d 100644
--- a/compatibility_matrices/compatibility_matrix.1.xml
+++ b/compatibility_matrices/compatibility_matrix.1.xml
@@ -158,6 +158,10 @@
     <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="false">
         <name>android.hardware.keymaster</name>
diff --git a/compatibility_matrices/compatibility_matrix.2.xml b/compatibility_matrices/compatibility_matrix.2.xml
index ea8dde8..98e6cfa 100644
--- a/compatibility_matrices/compatibility_matrix.2.xml
+++ b/compatibility_matrices/compatibility_matrix.2.xml
@@ -166,6 +166,10 @@
     <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="false">
         <name>android.hardware.keymaster</name>
diff --git a/compatibility_matrices/compatibility_matrix.3.xml b/compatibility_matrices/compatibility_matrix.3.xml
index 9c6b12a..e13d293 100644
--- a/compatibility_matrices/compatibility_matrix.3.xml
+++ b/compatibility_matrices/compatibility_matrix.3.xml
@@ -218,6 +218,10 @@
     <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="false">
         <name>android.hardware.keymaster</name>
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
new file mode 100644
index 0000000..78d1bf6
--- /dev/null
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -0,0 +1,466 @@
+<compatibility-matrix version="1.0" type="framework" level="4">
+    <hal format="hidl" optional="false">
+        <name>android.hardware.audio</name>
+        <version>4.0</version>
+        <interface>
+            <name>IDevicesFactory</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.audio.effect</name>
+        <version>4.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.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.a2dp</name>
+        <version>1.0</version>
+        <interface>
+            <name>IBluetoothAudioOffload</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.boot</name>
+        <version>1.0</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.camera.provider</name>
+        <version>2.4</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.0</version>
+        <interface>
+            <name>IMediaCasService</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <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</version>
+        <interface>
+            <name>ICryptoFactory</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+        <interface>
+            <name>IDrmFactory</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.drm</name>
+        <version>1.1</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>
+        <version>1.0-1</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>
+        <interface>
+            <name>IAllocator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.composer</name>
+        <version>2.1</version>
+        <interface>
+            <name>IComposer</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
+        <name>android.hardware.graphics.mapper</name>
+        <version>2.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.filesystem</name>
+        <version>1.0</version>
+        <interface>
+            <name>IFileSystem</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.ir</name>
+        <version>1.0</version>
+    </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="false">
+        <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</version>
+        <interface>
+            <name>IDevice</name>
+            <regex-instance>.*</regex-instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.nfc</name>
+        <version>1.1</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.radio</name>
+        <version>1.0-2</version>
+        <interface>
+            <name>IRadio</name>
+            <instance>slot1</instance>
+            <instance>slot2</instance>
+            <instance>slot3</instance>
+        </interface>
+        <interface>
+            <name>ISap</name>
+            <instance>slot1</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.radio.config</name>
+        <version>1.0</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>
+        <interface>
+            <name>ISensors</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.soundtrigger</name>
+        <version>2.0-1</version>
+        <interface>
+            <name>ISoundTriggerHw</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.tetheroffload.config</name>
+        <version>1.0</version>
+        <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-1</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-1</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-2</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-2</version>
+        <interface>
+            <name>IWifi</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.hostapd</name>
+        <version>1.0</version>
+        <interface>
+            <name>IHostapd</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.offload</name>
+        <version>1.0</version>
+        <interface>
+            <name>IOffload</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
+        <name>android.hardware.wifi.supplicant</name>
+        <version>1.0-1</version>
+        <interface>
+            <name>ISupplicant</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</compatibility-matrix>
diff --git a/compatibility_matrices/compatibility_matrix.legacy.xml b/compatibility_matrices/compatibility_matrix.legacy.xml
index 6792598..224811f 100644
--- a/compatibility_matrices/compatibility_matrix.legacy.xml
+++ b/compatibility_matrices/compatibility_matrix.legacy.xml
@@ -158,6 +158,10 @@
     <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="false">
         <name>android.hardware.keymaster</name>
diff --git a/compatibility_matrices/compatibility_matrix.mk b/compatibility_matrices/compatibility_matrix.mk
index 1b6fd3b..bafc84b 100644
--- a/compatibility_matrices/compatibility_matrix.mk
+++ b/compatibility_matrices/compatibility_matrix.mk
@@ -32,7 +32,7 @@
 #       assemble_vintf invocation. Format is "VINTF_ENFORCE_NO_UNUSED_HALS=true".
 # LOCAL_ASSEMBLE_VINTF_FLAGS: Add additional command line arguments to assemble_vintf invocation.
 # LOCAL_KERNEL_CONFIG_DATA_PATHS: Paths to search for kernel config requirements. Format for each is
-#       <kernel version x.y.z>:<path that contains android-base*.cfg>.
+#       <kernel version x.y.z>:<path that contains android-base*.config>.
 # LOCAL_GEN_FILE_DEPENDENCIES: A list of additional dependencies for the generated file.
 
 ifndef LOCAL_MODULE
@@ -77,13 +77,20 @@
 $(GEN): PRIVATE_ENV_VARS += FRAMEWORK_VBMETA_VERSION
 endif # LOCAL_ADD_VBMETA_VERSION
 
+ifeq (true,$(strip $(LOCAL_ADD_VBMETA_VERSION_OVERRIDE)))
+ifneq ($(BOARD_OTA_FRAMEWORK_VBMETA_VERSION_OVERRIDE),)
+$(GEN): FRAMEWORK_VBMETA_VERSION_OVERRIDE := $(BOARD_OTA_FRAMEWORK_VBMETA_VERSION_OVERRIDE)
+$(GEN): PRIVATE_ENV_VARS += FRAMEWORK_VBMETA_VERSION_OVERRIDE
+endif
+endif
+
 ifneq (,$(strip $(LOCAL_KERNEL_CONFIG_DATA_PATHS)))
 $(GEN): PRIVATE_KERNEL_CONFIG_DATA_PATHS := $(LOCAL_KERNEL_CONFIG_DATA_PATHS)
-$(GEN): $(foreach pair,$(PRIVATE_KERNEL_CONFIG_DATA_PATHS),\
-    $(wildcard $(call word-colon,2,$(pair))/android-base*.cfg))
+$(GEN): $(foreach pair,$(LOCAL_KERNEL_CONFIG_DATA_PATHS),\
+    $(wildcard $(call word-colon,2,$(pair))/android-base*.config))
 $(GEN): PRIVATE_FLAGS += $(foreach pair,$(PRIVATE_KERNEL_CONFIG_DATA_PATHS),\
 	--kernel=$(call word-colon,1,$(pair)):$(call normalize-path-list,\
-		$(wildcard $(call word-colon,2,$(pair))/android-base*.cfg)))
+		$(wildcard $(call word-colon,2,$(pair))/android-base*.config)))
 endif
 
 my_matrix_src_files := \
diff --git a/configstore/1.0/ISurfaceFlingerConfigs.hal b/configstore/1.0/ISurfaceFlingerConfigs.hal
index 5f975bd..1de7570 100644
--- a/configstore/1.0/ISurfaceFlingerConfigs.hal
+++ b/configstore/1.0/ISurfaceFlingerConfigs.hal
@@ -61,11 +61,16 @@
     hasWideColorDisplay() generates (OptionalBool value);
 
     /**
-     * hwHdrDisplay indicates that the device has
-     * or can support an HDR (High Dynamic Range) display.
-     * Typically an HDR display is also wide-color.
+     * hwHDRDisplay indicates that the device has an High Dynamic Range display.
+     * A display is considered High Dynamic Range if it
+     *
+     *     1. is a wide color gamut display, typically DCI-P3 or lager
+     *     2. has high luminance capability, typically 540 nits or higher at 10% OPR
+     *
      * Indicate support for this feature by setting
      * TARGET_HAS_HDR_DISPLAY to true in BoardConfig.mk
+     * TARGET_HAS_WIDE_COLOR_DISPLAY must be set to true when
+     * TARGET_HAS_HDR_DISPLAY is true.
      */
     hasHDRDisplay() generates (OptionalBool value);
 
diff --git a/configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy b/configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy
index d523a1a..937fddd 100644
--- a/configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy
+++ b/configstore/1.1/default/seccomp_policy/configstore@1.1-arm64.policy
@@ -44,6 +44,7 @@
 madvise: 1
 getdents64: 1
 clock_gettime: 1
+getpid: 1
 
 # used during process crash by crash_dump to dump process info
 rt_sigprocmask: 1
diff --git a/configstore/1.1/default/surfaceflinger.mk b/configstore/1.1/default/surfaceflinger.mk
index 51f06e1..35922eb 100644
--- a/configstore/1.1/default/surfaceflinger.mk
+++ b/configstore/1.1/default/surfaceflinger.mk
@@ -9,14 +9,6 @@
     LOCAL_CFLAGS += -DSF_VSYNC_EVENT_PHASE_OFFSET_NS=$(SF_VSYNC_EVENT_PHASE_OFFSET_NS)
 endif
 
-ifeq ($(TARGET_BOARD_PLATFORM),omap4)
-    LOCAL_CFLAGS += -DUSE_CONTEXT_PRIORITY=1
-endif
-
-ifeq ($(TARGET_BOARD_PLATFORM),s5pc110)
-    LOCAL_CFLAGS += -DUSE_CONTEXT_PRIORITY=1
-endif
-
 ifeq ($(TARGET_USE_CONTEXT_PRIORITY),true)
     LOCAL_CFLAGS += -DUSE_CONTEXT_PRIORITY=1
 endif
diff --git a/configstore/README.md b/configstore/README.md
new file mode 100644
index 0000000..3e8a24e
--- /dev/null
+++ b/configstore/README.md
@@ -0,0 +1 @@
+Configstore is specifically the configuration for surface flinger. Other configurations go in other packages.
diff --git a/configstore/utils/Android.bp b/configstore/utils/Android.bp
index cb4e6eb..178f245 100644
--- a/configstore/utils/Android.bp
+++ b/configstore/utils/Android.bp
@@ -20,6 +20,7 @@
     vndk: {
         enabled: true,
     },
+    double_loadable: true,
     defaults: ["hidl_defaults"],
 
     srcs: [ "ConfigStoreUtils.cpp" ],
diff --git a/current.txt b/current.txt
index 4f574e9..327833f 100644
--- a/current.txt
+++ b/current.txt
@@ -384,6 +384,14 @@
 cd4330c3196bda1d642a32abfe23a7d64ebfbda721940643af6867af3b3f0aa9 android.hardware.wifi.supplicant@1.1::ISupplicantStaIfaceCallback
 10ff2fae516346b86121368ce5790d5accdfcb73983246b813f3d488b66db45a android.hardware.wifi.supplicant@1.1::ISupplicantStaNetwork
 
-# ABI preserving changes to HALs after Android P
-1d19720d4fd38b1095f0f555a4bd92b3b12c9b1d0f560b0e9a474cd6dcc20db6 android.hardware.radio@1.2::IRadio
+# ABI preserving changes to HALs during Android Q
+da33234403ff5d60f3473711917b9948e6484a4260b5247acdafb111193a9de2 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
+b7ecf29927055ec422ec44bf776223f07d79ad9f92ccf9becf167e62c2607e7a android.hardware.keymaster@4.0::IKeymasterDevice
+574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel
+1fb32361286b938d48a55c2539c846732afce0b99fe08590f556643125bc13d3 android.hardware.neuralnetworks@1.0::types
+e22e8135d061d0e9c4c1a70c25c19fdba10f4d3cda9795ef25b6392fc520317c android.hardware.neuralnetworks@1.1::types
 1d4a5776614c08b5d794a5ec5ab04697260cbd4b3441d5935cd53ee71d19da02 android.hardware.radio@1.0::IRadioResponse
+271187e261b30c01a33011aea257c07a2d2f05b72943ebee89e973e997849973 android.hardware.radio@1.0::types
+1d19720d4fd38b1095f0f555a4bd92b3b12c9b1d0f560b0e9a474cd6dcc20db6 android.hardware.radio@1.2::IRadio
+1722ad002317b1fae1400de709e90f442d94ef22864e05f7a12af48c32e8edc8 android.hardware.usb@1.1::types
+29c8da7a13c40d488f569c812441d5754ee45bdcdb8ce6564f524b708d10a057 android.hardware.vibrator@1.1::types
diff --git a/drm/1.0/default/DrmFactory.cpp b/drm/1.0/default/DrmFactory.cpp
index 7e5d998..05951d7 100644
--- a/drm/1.0/default/DrmFactory.cpp
+++ b/drm/1.0/default/DrmFactory.cpp
@@ -1,6 +1,6 @@
 /*
  * 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
diff --git a/drm/1.0/default/LegacyPluginPath.cpp b/drm/1.0/default/LegacyPluginPath.cpp
index 369059d..d0a8f90 100644
--- a/drm/1.0/default/LegacyPluginPath.cpp
+++ b/drm/1.0/default/LegacyPluginPath.cpp
@@ -16,6 +16,8 @@
 
 #include "LegacyPluginPath.h"
 
+#include <unistd.h>
+
 #include <cutils/properties.h>
 
 namespace android {
@@ -24,12 +26,16 @@
 namespace V1_0 {
 namespace implementation {
 
+// 64-bit DRM depends on OEM libraries that aren't
+// provided for all devices. If the drm hal service
+// is running as 64-bit use the 64-bit libs, otherwise
+// use the 32-bit libs.
 const char* getDrmPluginPath() {
-    if (property_get_bool("drm.64bit.enabled", false)) {
-        return "/vendor/lib64/mediadrm";
-    } else {
-        return "/vendor/lib/mediadrm";
-    }
+#if defined(__LP64__)
+    return "/vendor/lib64/mediadrm";
+#else
+    return "/vendor/lib/mediadrm";
+#endif
 }
 
 }  // namespace implementation
diff --git a/drm/1.0/default/include/PluginLoader.h b/drm/1.0/default/include/PluginLoader.h
index f387b3c..0c45fb3 100644
--- a/drm/1.0/default/include/PluginLoader.h
+++ b/drm/1.0/default/include/PluginLoader.h
@@ -85,7 +85,10 @@
                 libraries.push(library);
                 T* result = createFactoryFunc();
                 return  result;
-           }
+            } else {
+                ALOGE("Failed to lookup symbol %s in library %s: %s",
+                        entry, path, library->lastError());
+            }
         }
         return NULL;
     }
diff --git a/dumpstate/1.0/Android.bp b/dumpstate/1.0/Android.bp
index bc704f1..29be116 100644
--- a/dumpstate/1.0/Android.bp
+++ b/dumpstate/1.0/Android.bp
@@ -12,6 +12,6 @@
     interfaces: [
         "android.hidl.base@1.0",
     ],
-    gen_java: false,
+    gen_java: true,
 }
 
diff --git a/dumpstate/1.0/default/DumpstateDevice.cpp b/dumpstate/1.0/default/DumpstateDevice.cpp
index 818a531..25d92b0 100644
--- a/dumpstate/1.0/default/DumpstateDevice.cpp
+++ b/dumpstate/1.0/default/DumpstateDevice.cpp
@@ -18,6 +18,7 @@
 
 #include "DumpstateDevice.h"
 
+#include <hidl/HidlBinderSupport.h>
 #include <log/log.h>
 
 #include "DumpstateUtil.h"
@@ -34,8 +35,12 @@
 // Methods from ::android::hardware::dumpstate::V1_0::IDumpstateDevice follow.
 Return<void> DumpstateDevice::dumpstateBoard(const hidl_handle& handle) {
     // NOTE: this is just an example on how to use the DumpstateUtil.h functions to implement
-    // this interface - since HIDL_FETCH_IDumpstateDevice() is not defined, this function will never
-    // be called by dumpstate.
+    // 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");
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 dfc7d78..062a291 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
@@ -3,3 +3,5 @@
     user system
     group system
     interface android.hardware.dumpstate@1.0::IDumpstateDevice default
+    oneshot
+    disabled
diff --git a/fastboot/1.0/Android.bp b/fastboot/1.0/Android.bp
new file mode 100644
index 0000000..3267499
--- /dev/null
+++ b/fastboot/1.0/Android.bp
@@ -0,0 +1,22 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.fastboot@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IFastboot.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "Status",
+        "Result",
+    ],
+    gen_java: false,
+}
+
diff --git a/fastboot/1.0/IFastboot.hal b/fastboot/1.0/IFastboot.hal
new file mode 100644
index 0000000..5e42c17
--- /dev/null
+++ b/fastboot/1.0/IFastboot.hal
@@ -0,0 +1,42 @@
+/*
+ * 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.fastboot@1.0;
+
+/**
+ * IFastboot interface implements vendor specific fastboot commands.
+ */
+interface IFastboot {
+    /**
+     * Returns the file system type of the partition. This is only required for
+     * physical partitions that need to be wiped and reformatted.
+     *
+     * @return type Can be ext4, f2fs or raw.
+     * @return result SUCCESS if the operation is successful,
+     *     FAILURE_UNKNOWN if the partition is invalid or does not require
+     *     reformatting.
+     */
+    getPartitionType(string partitionName) generates (FileSystemType type, Result result);
+
+    /**
+     * Executes a fastboot OEM command.
+     *
+     * @param oemCmdArgs The oem command that is passed to the fastboot HAL.
+     * @response result Returns the status SUCCESS if the operation is successful,
+     *     INVALID_ARGUMENT for bad arguments,
+     *     FAILURE_UNKNOWN for an invalid/unsupported command.
+     */
+    doOemCommand(string oemCmd) generates (Result result);
+};
diff --git a/fastboot/1.0/types.hal b/fastboot/1.0/types.hal
new file mode 100644
index 0000000..3fbe639
--- /dev/null
+++ b/fastboot/1.0/types.hal
@@ -0,0 +1,61 @@
+/**
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.fastboot@1.0;
+
+enum Status : uint32_t {
+    /**
+     * Operation completed without errors.
+     */
+    SUCCESS,
+    /**
+     * Unsupported operation.
+     */
+    NOT_SUPPORTED,
+    /**
+     * Bad argument.
+     */
+    INVALID_ARGUMENT,
+    /**
+     * Operation failed due to unknown reason.
+     */
+    FAILURE_UNKNOWN
+};
+
+enum FileSystemType : uint8_t {
+    /**
+     * Fourth extended file system.
+     */
+    EXT4,
+    /**
+     * Flash Friendly File System.
+     */
+    F2FS,
+    /**
+     * Raw file system.
+     */
+    RAW
+};
+
+struct Result {
+    Status status;
+    /**
+     * Message pertaining to the status. It must be a failure message for
+     * Status FAILURE_UNKNOWN/NOT_SUPPORTED or an informative message for
+     * Status SUCCESS.
+     */
+    string message;
+};
diff --git a/graphics/bufferqueue/1.0/Android.bp b/graphics/bufferqueue/1.0/Android.bp
index 0333a42..e23ca59 100644
--- a/graphics/bufferqueue/1.0/Android.bp
+++ b/graphics/bufferqueue/1.0/Android.bp
@@ -15,6 +15,6 @@
         "android.hardware.media@1.0",
         "android.hidl.base@1.0",
     ],
-    gen_java: false,
+    gen_java: true,
 }
 
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 a2a12c1..5a5b51e 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
@@ -3,9 +3,5 @@
     user system
     group graphics drmrpc
     capabilities SYS_NICE
+    onrestart restart surfaceflinger
     writepid /dev/cpuset/system-background/tasks
-
-# Restart HWC when SurfaceFlinger stops. This turns off the display and prpares
-# a new HWC instance for when SurfaceFlinger gets started again
-on property:init.svc.surfaceflinger=stopped
-    restart vendor.hwcomposer-2-1
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h
index 86525b8..095189f 100644
--- a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerClient.h
@@ -102,6 +102,7 @@
         }
 
         void onRefresh(Display display) {
+            mResources->setDisplayMustValidateState(display, true);
             auto ret = mCallback->onRefresh(display);
             ALOGE_IF(!ret.isOk(), "failed to send onRefresh: %s", ret.description().c_str());
         }
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h
index 36aa64e..d87110a 100644
--- a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerCommandEngine.h
@@ -258,6 +258,7 @@
 
         auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes,
                                          &displayRequestMask, &requestedLayers, &requestMasks);
+        mResources->setDisplayMustValidateState(mCurrentDisplay, false);
         if (err == Error::NONE) {
             mWriter.setChangedCompositionTypes(changedLayers, compositionTypes);
             mWriter.setDisplayRequests(displayRequestMask, requestedLayers, requestMasks);
@@ -278,7 +279,9 @@
             int presentFence = -1;
             std::vector<Layer> layers;
             std::vector<int> fences;
-            auto err = mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences);
+            auto err = mResources->mustValidateDisplay(mCurrentDisplay)
+                           ? Error::NOT_VALIDATED
+                           : mHal->presentDisplay(mCurrentDisplay, &presentFence, &layers, &fences);
             if (err == Error::NONE) {
                 mWriter.setPresentOrValidateResult(1);
                 mWriter.setPresentFence(presentFence);
@@ -296,6 +299,7 @@
 
         auto err = mHal->validateDisplay(mCurrentDisplay, &changedLayers, &compositionTypes,
                                          &displayRequestMask, &requestedLayers, &requestMasks);
+        mResources->setDisplayMustValidateState(mCurrentDisplay, false);
         if (err == Error::NONE) {
             mWriter.setPresentOrValidateResult(0);
             mWriter.setChangedCompositionTypes(changedLayers, compositionTypes);
diff --git a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
index 7bb3692..2cbf044 100644
--- a/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
+++ b/graphics/composer/2.1/utils/hal/include/composer-hal/2.1/ComposerResources.h
@@ -216,7 +216,8 @@
         : mType(type),
           mClientTargetCache(importer),
           mOutputBufferCache(importer, ComposerHandleCache::HandleType::BUFFER,
-                             outputBufferCacheSize) {}
+                             outputBufferCacheSize),
+          mMustValidate(true) {}
 
     bool initClientTargetCache(uint32_t cacheSize) {
         return mClientTargetCache.initCache(ComposerHandleCache::HandleType::BUFFER, cacheSize);
@@ -263,10 +264,15 @@
         return layers;
     }
 
+    void setMustValidateState(bool mustValidate) { mMustValidate = mustValidate; }
+
+    bool mustValidate() const { return mMustValidate; }
+
    protected:
     const DisplayType mType;
     ComposerHandleCache mClientTargetCache;
     ComposerHandleCache mOutputBufferCache;
+    bool mMustValidate;
 
     std::unordered_map<Layer, std::unique_ptr<ComposerLayerResource>> mLayerResources;
 };
@@ -389,6 +395,23 @@
                                                        outStreamHandle, outReplacedStream);
     }
 
+    void setDisplayMustValidateState(Display display, bool mustValidate) {
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+        auto* displayResource = findDisplayResourceLocked(display);
+        if (displayResource) {
+            displayResource->setMustValidateState(mustValidate);
+        }
+    }
+
+    bool mustValidateDisplay(Display display) {
+        std::lock_guard<std::mutex> lock(mDisplayResourcesMutex);
+        auto* displayResource = findDisplayResourceLocked(display);
+        if (displayResource) {
+            return displayResource->mustValidate();
+        }
+        return false;
+    }
+
    protected:
     virtual std::unique_ptr<ComposerDisplayResource> createDisplayResource(
         ComposerDisplayResource::DisplayType type, uint32_t outputBufferCacheSize) {
diff --git a/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp b/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
index 6551a99..366d641 100644
--- a/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
+++ b/graphics/composer/2.1/utils/hwc2on1adapter/HWC2On1Adapter.cpp
@@ -2096,8 +2096,7 @@
     } else if (mCompositionType == HWC2::Composition::Sideband) {
         output << "  Handle: " << mSidebandStream << '\n';
     } else {
-        output << "  Buffer: " << mBuffer.getBuffer() << "/" <<
-                mBuffer.getFence() << '\n';
+        output << "  Buffer: " << mBuffer.getBuffer() << '\n';
         output << fill << "  Display frame [LTRB]: " <<
                 rectString(mDisplayFrame) << '\n';
         output << fill << "  Source crop: " <<
diff --git a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h
index 964e75b..436e461 100644
--- a/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h
+++ b/graphics/composer/2.1/utils/passthrough/include/composer-passthrough/2.1/HwcHal.h
@@ -111,7 +111,6 @@
     }
 
     void registerEventCallback(hal::ComposerHal::EventCallback* callback) override {
-        mMustValidateDisplay = true;
         mEventCallback = callback;
 
         mDispatch.registerCallback(mDevice, HWC2_CALLBACK_HOTPLUG, this,
@@ -331,7 +330,6 @@
         uint32_t typesCount = 0;
         uint32_t reqsCount = 0;
         int32_t err = mDispatch.validateDisplay(mDevice, display, &typesCount, &reqsCount);
-        mMustValidateDisplay = false;
 
         if (err != HWC2_ERROR_NONE && err != HWC2_ERROR_HAS_CHANGES) {
             return static_cast<Error>(err);
@@ -384,10 +382,6 @@
 
     Error presentDisplay(Display display, int32_t* outPresentFence, std::vector<Layer>* outLayers,
                          std::vector<int32_t>* outReleaseFences) override {
-        if (mMustValidateDisplay) {
-            return Error::NOT_VALIDATED;
-        }
-
         *outPresentFence = -1;
         int32_t err = mDispatch.presentDisplay(mDevice, display, outPresentFence);
         if (err != HWC2_ERROR_NONE) {
@@ -593,7 +587,6 @@
 
     static void refreshHook(hwc2_callback_data_t callbackData, hwc2_display_t display) {
         auto hal = static_cast<HwcHalImpl*>(callbackData);
-        hal->mMustValidateDisplay = true;
         hal->mEventCallback->onRefresh(display);
     }
 
@@ -654,8 +647,6 @@
     } mDispatch = {};
 
     hal::ComposerHal::EventCallback* mEventCallback = nullptr;
-
-    std::atomic<bool> mMustValidateDisplay{true};
 };
 
 }  // namespace detail
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 747c66c..72f3f1b 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -293,7 +293,7 @@
  */
 TEST_F(GraphicsComposerHidlTest, SetColorMode) {
     std::unordered_set<ColorMode> validModes;
-    for (auto mode : hidl_enum_iterator<ColorMode>()) {
+    for (auto mode : hidl_enum_range<ColorMode>()) {
         validModes.insert(mode);
     }
 
diff --git a/graphics/mapper/2.0/utils/vts/Android.bp b/graphics/mapper/2.0/utils/vts/Android.bp
index 1aa3185..e43011f 100644
--- a/graphics/mapper/2.0/utils/vts/Android.bp
+++ b/graphics/mapper/2.0/utils/vts/Android.bp
@@ -16,17 +16,13 @@
 
 cc_library_static {
     name: "android.hardware.graphics.mapper@2.0-vts",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: ["MapperVts.cpp"],
     cflags: [
         "-O0",
         "-g",
     ],
-    shared_libs: [
-        "libutils",
-    ],
     static_libs: [
-        "VtsHalHidlTargetTestBase",
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
     ],
diff --git a/health/1.0/default/Android.bp b/health/1.0/default/Android.bp
index cb2e87d..8fbb8c3 100644
--- a/health/1.0/default/Android.bp
+++ b/health/1.0/default/Android.bp
@@ -1,6 +1,7 @@
 cc_library_static {
     name: "android.hardware.health@1.0-convert",
     vendor_available: true,
+    recovery_available: true,
     srcs: ["convert.cpp"],
     include_dirs: [
         "system/core/base/include",
diff --git a/health/1.0/default/libhealthd/Android.bp b/health/1.0/default/libhealthd/Android.bp
index ce02e28..a90d50d 100644
--- a/health/1.0/default/libhealthd/Android.bp
+++ b/health/1.0/default/libhealthd/Android.bp
@@ -4,6 +4,7 @@
     srcs: ["healthd_board_default.cpp"],
     name: "libhealthd.default",
     vendor_available: true,
+    recovery_available: true,
     cflags: ["-Werror"],
     include_dirs: ["system/core/base/include"],
     header_libs: ["libhealthd_headers"],
diff --git a/health/2.0/README b/health/2.0/README
deleted file mode 100644
index 11e6a7a..0000000
--- a/health/2.0/README
+++ /dev/null
@@ -1,118 +0,0 @@
-Upgrading from health@1.0 HAL
-
-0. Remove android.hardware.health@1.0* from PRODUCT_PACKAGES
-   in device/<manufacturer>/<device>/device.mk
-
-1. If the device does not have a vendor-specific libhealthd AND does not
-   implement storage-related APIs, just do the following:
-
-    1.1 (recommended) To remove healthd from the build,
-        PRODUCT_PACKAGES += android.hardware.health@2.0-service.override
-        DEVICE_FRAMEWORK_MANIFEST_FILE += \
-            system/libhidl/vintfdata/manifest_healthd_exclude.xml
-    1.2 To keep healthd in the build,
-        PRODUCT_PACKAGES += android.hardware.health@2.0-service
-
-   Otherwise, continue to Step 2.
-
-2. Create directory
-   device/<manufacturer>/<device>/health
-
-3. Create device/<manufacturer>/<device>/health/Android.bp
-   (or equivalent device/<manufacturer>/<device>/health/Android.mk)
-
-cc_binary {
-    name: "android.hardware.health@2.0-service.<device>",
-    init_rc: ["android.hardware.health@2.0-service.<device>.rc"],
-    proprietary: true,
-    relative_install_path: "hw",
-    srcs: [
-        "HealthService.cpp",
-    ],
-
-    cflags: [
-        "-Wall",
-        "-Werror",
-    ],
-
-    static_libs: [
-        "android.hardware.health@2.0-impl",
-        "android.hardware.health@1.0-convert",
-        "libhealthservice",
-        "libbatterymonitor",
-    ],
-
-    shared_libs: [
-        "libbase",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
-        "libutils",
-        "android.hardware.health@2.0",
-    ],
-
-    header_libs: ["libhealthd_headers"],
-
-    // Uncomment the following to remove healthd from the build.
-    // overrides: [
-    //     "healthd",
-    // ],
-}
-
-    3.1 (recommended) To remove healthd from the build, keep "overrides"
-          section, and include the following in device.mk:
-            DEVICE_FRAMEWORK_MANIFEST_FILE += \
-                system/libhidl/vintfdata/manifest_healthd_exclude.xml
-    3.2 To keep healthd in the build, remove "overrides" section.
-
-4. Create device/<manufacturer>/<device>/health/android.hardware.health@2.0-service.<device>.rc
-
-service vendor.health-hal-2-0 /vendor/bin/hw/android.hardware.health@2.0-service.<device>
-    class hal
-    user system
-    group system
-    file /dev/kmsg w
-
-5. Create device/<manufacturer>/<device>/health/HealthService.cpp:
-
-#include <health2/service.h>
-int main() { return health_service_main(); }
-
-6. libhealthd dependency:
-
-6.1 If the device has a vendor-specific libhealthd.<soc>, add it to static_libs.
-
-6.2 If the device does not have a vendor-specific libhealthd, add the following
-    lines to HealthService.cpp:
-
-#include <healthd/healthd.h>
-void healthd_board_init(struct healthd_config*) {}
-
-int healthd_board_battery_update(struct android::BatteryProperties*) {
-    // return 0 to log periodic polled battery status to kernel log
-    return 0;
-}
-
-7. Storage related APIs:
-
-7.1 If the device does not implement IHealth.getDiskStats and
-    IHealth.getStorageInfo, add libstoragehealthdefault to static_libs.
-
-7.2 If the device implements one of these two APIs, add and implement the
-    following functions in HealthService.cpp:
-
-void get_storage_info(std::vector<struct StorageInfo>& info) {
-    // ...
-}
-void get_disk_stats(std::vector<struct DiskStats>& stats) {
-    // ...
-}
-
-8. Update necessary SELinux permissions. For example,
-
-# device/<manufacturer>/<device>/sepolicy/vendor/file_contexts
-/vendor/bin/hw/android\.hardware\.health@2\.0-service.<device> u:object_r:hal_health_default_exec:s0
-
-# device/<manufacturer>/<device>/sepolicy/vendor/hal_health_default.te
-# Add device specific permissions to hal_health_default domain, especially
-# if Step 6.1 or Step 7.2 is done.
diff --git a/health/2.0/README b/health/2.0/README
new file mode 120000
index 0000000..42061c0
--- /dev/null
+++ b/health/2.0/README
@@ -0,0 +1 @@
+README.md
\ No newline at end of file
diff --git a/health/2.0/README.md b/health/2.0/README.md
new file mode 100644
index 0000000..5efc51a
--- /dev/null
+++ b/health/2.0/README.md
@@ -0,0 +1,176 @@
+# Upgrading from Health 1.0 HAL
+
+1. Remove `android.hardware.health@1.0*` from `PRODUCT_PACKAGES`
+   in `device/<manufacturer>/<device>/device.mk`
+
+1. If the device does not have a vendor-specific `libhealthd` AND does not
+   implement storage-related APIs, just do the following:
+
+   ```mk
+   PRODUCT_PACKAGES += android.hardware.health@2.0-service
+   ```
+
+   Otherwise, continue to the next step.
+
+1. Create directory
+   `device/<manufacturer>/<device>/health`
+
+1. Create `device/<manufacturer>/<device>/health/Android.bp`
+   (or equivalent `device/<manufacturer>/<device>/health/Android.mk`)
+
+    ```bp
+    cc_binary {
+        name: "android.hardware.health@2.0-service.<device>",
+        init_rc: ["android.hardware.health@2.0-service.<device>.rc"],
+        proprietary: true,
+        relative_install_path: "hw",
+        srcs: [
+            "HealthService.cpp",
+        ],
+
+        cflags: [
+            "-Wall",
+            "-Werror",
+        ],
+
+        static_libs: [
+            "android.hardware.health@2.0-impl",
+            "android.hardware.health@1.0-convert",
+            "libhealthservice",
+            "libbatterymonitor",
+        ],
+
+        shared_libs: [
+            "libbase",
+            "libcutils",
+            "libhidlbase",
+            "libhidltransport",
+            "libutils",
+            "android.hardware.health@2.0",
+        ],
+
+        header_libs: ["libhealthd_headers"],
+
+        overrides: [
+            "healthd",
+        ],
+    }
+    ```
+
+    1. (recommended) To remove `healthd` from the build, keep "overrides" section.
+    1. To keep `healthd` in the build, remove "overrides" section.
+
+1. Create `device/<manufacturer>/<device>/health/android.hardware.health@2.0-service.<device>.rc`
+
+    ```rc
+    service vendor.health-hal-2-0 /vendor/bin/hw/android.hardware.health@2.0-service.<device>
+        class hal
+        user system
+        group system
+        file /dev/kmsg w
+    ```
+
+1. Create `device/<manufacturer>/<device>/health/HealthService.cpp`:
+
+    ```c++
+    #include <health2/service.h>
+    int main() { return health_service_main(); }
+    ```
+
+1. `libhealthd` dependency:
+
+    1. If the device has a vendor-specific `libhealthd.<soc>`, add it to static_libs.
+
+    1. If the device does not have a vendor-specific `libhealthd`, add the following
+        lines to `HealthService.cpp`:
+
+        ```c++
+        #include <healthd/healthd.h>
+        void healthd_board_init(struct healthd_config*) {}
+
+        int healthd_board_battery_update(struct android::BatteryProperties*) {
+            // return 0 to log periodic polled battery status to kernel log
+            return 0;
+        }
+        ```
+
+1. Storage related APIs:
+
+    1. If the device does not implement `IHealth.getDiskStats` and
+        `IHealth.getStorageInfo`, add `libstoragehealthdefault` to `static_libs`.
+
+    1. If the device implements one of these two APIs, add and implement the
+        following functions in `HealthService.cpp`:
+
+        ```c++
+        void get_storage_info(std::vector<struct StorageInfo>& info) {
+            // ...
+        }
+        void get_disk_stats(std::vector<struct DiskStats>& stats) {
+            // ...
+        }
+        ```
+
+1. Update necessary SELinux permissions. For example,
+
+    ```
+    # device/<manufacturer>/<device>/sepolicy/vendor/file_contexts
+    /vendor/bin/hw/android\.hardware\.health@2\.0-service.<device> u:object_r:hal_health_default_exec:s0
+
+    # device/<manufacturer>/<device>/sepolicy/vendor/hal_health_default.te
+    # Add device specific permissions to hal_health_default domain, especially
+    # if a device-specific libhealthd is used and/or device-specific storage related
+    # APIs are implemented.
+    ```
+
+1. Implementing health HAL in recovery. The health HAL is used for battery
+status checks during OTA for non-A/B devices. If the health HAL is not
+implemented in recovery, `is_battery_ok()` will always return `true`.
+
+    1. If the device does not have a vendor-specific `libhealthd`, nothing needs to
+    be done. A "backup" implementation is provided in
+    `android.hardware.health@2.0-impl-default`, which is always installed to recovery
+    image by default.
+
+    1. If the device does have a vendor-specific `libhealthd`, implement the following
+    module and include it in `PRODUCT_PACKAGES` (replace `<device>` with appropriate
+    strings):
+
+    ```bp
+    // Android.bp
+    cc_library_shared {
+        name: "android.hardware.health@2.0-impl-<device>",
+        recovery_available: true,
+        relative_install_path: "hw",
+        static_libs: [
+            "android.hardware.health@2.0-impl",
+            "libhealthd.<device>"
+            // Include the following or implement device-specific storage APIs
+            "libhealthstoragedefault",
+        ],
+        srcs: [
+            "HealthImpl.cpp",
+        ],
+        overrides: [
+            "android.hardware.health@2.0-impl-default",
+        ],
+    }
+    ```
+
+    ```c++
+    // HealthImpl.cpp
+    #include <health2/Health.h>
+    #include <healthd/healthd.h>
+    using android::hardware::health::V2_0::IHealth;
+    using android::hardware::health::V2_0::implementation::Health;
+    extern "C" IHealth* HIDL_FETCH_IHealth(const char* name) {
+        const static std::string providedInstance{"default"};
+        if (providedInstance != name) return nullptr;
+        return Health::initInstance(&gHealthdConfig).get();
+    }
+    ```
+
+    ```mk
+    # device.mk
+    PRODUCT_PACKAGES += android.hardware.health@2.0-impl-<device>
+    ```
diff --git a/health/2.0/default/Android.bp b/health/2.0/default/Android.bp
index 8eb02e0..a85a704 100644
--- a/health/2.0/default/Android.bp
+++ b/health/2.0/default/Android.bp
@@ -1,15 +1,12 @@
-cc_library_static {
-    name: "android.hardware.health@2.0-impl",
-    vendor_available: true,
-    srcs: [
-        "Health.cpp",
-        "healthd_common.cpp",
+cc_defaults {
+    name: "android.hardware.health@2.0-impl_defaults",
+
+    recovery_available: true,
+    cflags: [
+        "-Wall",
+        "-Werror",
     ],
 
-    cflags: ["-DHEALTHD_USE_HEALTH_2_0"],
-
-    export_include_dirs: ["include"],
-
     shared_libs: [
         "libbase",
         "libhidlbase",
@@ -26,3 +23,39 @@
         "android.hardware.health@1.0-convert",
     ],
 }
+
+// Helper library for implementing health HAL. It is recommended that a health
+// service or passthrough HAL link to this library.
+cc_library_static {
+    name: "android.hardware.health@2.0-impl",
+    defaults: ["android.hardware.health@2.0-impl_defaults"],
+
+    vendor_available: true,
+    srcs: [
+        "Health.cpp",
+        "healthd_common.cpp",
+    ],
+
+    export_include_dirs: ["include"],
+}
+
+// Default passthrough implementation for recovery. Vendors can implement
+// android.hardware.health@2.0-impl-recovery-<device> to customize the behavior
+// of the HAL in recovery.
+// The implementation does NOT start the uevent loop for polling.
+cc_library_shared {
+    name: "android.hardware.health@2.0-impl-default",
+    defaults: ["android.hardware.health@2.0-impl_defaults"],
+
+    recovery_available: true,
+    relative_install_path: "hw",
+
+    static_libs: [
+        "android.hardware.health@2.0-impl",
+        "libhealthstoragedefault",
+    ],
+
+    srcs: [
+        "HealthImplDefault.cpp",
+    ],
+}
diff --git a/health/2.0/default/HealthImplDefault.cpp b/health/2.0/default/HealthImplDefault.cpp
new file mode 100644
index 0000000..15346bf
--- /dev/null
+++ b/health/2.0/default/HealthImplDefault.cpp
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#include <health2/Health.h>
+#include <healthd/healthd.h>
+
+using android::hardware::health::V2_0::IHealth;
+using android::hardware::health::V2_0::implementation::Health;
+
+static struct healthd_config gHealthdConfig = {
+    .batteryStatusPath = android::String8(android::String8::kEmptyString),
+    .batteryHealthPath = android::String8(android::String8::kEmptyString),
+    .batteryPresentPath = android::String8(android::String8::kEmptyString),
+    .batteryCapacityPath = android::String8(android::String8::kEmptyString),
+    .batteryVoltagePath = android::String8(android::String8::kEmptyString),
+    .batteryTemperaturePath = android::String8(android::String8::kEmptyString),
+    .batteryTechnologyPath = android::String8(android::String8::kEmptyString),
+    .batteryCurrentNowPath = android::String8(android::String8::kEmptyString),
+    .batteryCurrentAvgPath = android::String8(android::String8::kEmptyString),
+    .batteryChargeCounterPath = android::String8(android::String8::kEmptyString),
+    .batteryFullChargePath = android::String8(android::String8::kEmptyString),
+    .batteryCycleCountPath = android::String8(android::String8::kEmptyString),
+    .energyCounter = nullptr,
+    .boot_min_cap = 0,
+    .screen_on = nullptr};
+
+void healthd_board_init(struct healthd_config*) {
+    // use defaults
+}
+
+int healthd_board_battery_update(struct android::BatteryProperties*) {
+    // return 0 to log periodic polled battery status to kernel log
+    return 0;
+}
+
+extern "C" IHealth* HIDL_FETCH_IHealth(const char* name) {
+    const static std::string providedInstance{"backup"};
+
+    if (providedInstance == name) {
+        // use defaults
+        // Health class stores static instance
+        return Health::initInstance(&gHealthdConfig).get();
+    }
+    return nullptr;
+}
diff --git a/health/2.0/utils/README b/health/2.0/utils/README.md
similarity index 68%
rename from health/2.0/utils/README
rename to health/2.0/utils/README.md
index 1d5c27f..c59b3f3 100644
--- a/health/2.0/utils/README
+++ b/health/2.0/utils/README.md
@@ -1,28 +1,30 @@
-* libhealthhalutils
+# libhealthhalutils
 
 A convenience library for (hwbinder) clients of health HAL to choose between
 the "default" instance (served by vendor service) or "backup" instance (served
 by healthd). C++ clients of health HAL should use this library instead of
-calling IHealth::getService() directly.
+calling `IHealth::getService()` directly.
 
-Its Java equivalent can be found in BatteryService.HealthServiceWrapper.
+Its Java equivalent can be found in `BatteryService.HealthServiceWrapper`.
 
-* libhealthservice
+# libhealthservice
 
 Common code for all (hwbinder) services of the health HAL, including healthd and
-vendor health service android.hardware.health@2.0-service(.<vendor>). main() in
-those binaries calls health_service_main() directly.
+vendor health service `android.hardware.health@2.0-service(.<vendor>)`. `main()` in
+those binaries calls `health_service_main()` directly.
 
-* libhealthstoragedefault
+# libhealthstoragedefault
 
 Default implementation for storage related APIs for (hwbinder) services of the
 health HAL. If an implementation of the health HAL do not wish to provide any
 storage info, include this library. Otherwise, it should implement the following
 two functions:
 
+```c++
 void get_storage_info(std::vector<struct StorageInfo>& info) {
     // ...
 }
 void get_disk_stats(std::vector<struct DiskStats>& stats) {
     // ...
 }
+```
diff --git a/health/2.0/utils/libhealthhalutils/Android.bp b/health/2.0/utils/libhealthhalutils/Android.bp
index 5686520..449ef16 100644
--- a/health/2.0/utils/libhealthhalutils/Android.bp
+++ b/health/2.0/utils/libhealthhalutils/Android.bp
@@ -21,6 +21,7 @@
     srcs: ["HealthHalUtils.cpp"],
     cflags: ["-Wall", "-Werror"],
     vendor_available: true,
+    recovery_available: true,
     export_include_dirs: ["include"],
     shared_libs: [
         "android.hardware.health@2.0",
diff --git a/health/2.0/utils/libhealthservice/HealthServiceCommon.cpp b/health/2.0/utils/libhealthservice/HealthServiceCommon.cpp
index acb4501..039570a 100644
--- a/health/2.0/utils/libhealthservice/HealthServiceCommon.cpp
+++ b/health/2.0/utils/libhealthservice/HealthServiceCommon.cpp
@@ -23,6 +23,7 @@
 #include <health2/service.h>
 #include <healthd/healthd.h>
 #include <hidl/HidlTransportSupport.h>
+#include <hwbinder/IPCThreadState.h>
 
 using android::hardware::IPCThreadState;
 using android::hardware::configureRpcThreadpool;
diff --git a/health/2.0/utils/libhealthstoragedefault/Android.bp b/health/2.0/utils/libhealthstoragedefault/Android.bp
index cef04fe..5bc8b9f 100644
--- a/health/2.0/utils/libhealthstoragedefault/Android.bp
+++ b/health/2.0/utils/libhealthstoragedefault/Android.bp
@@ -21,6 +21,7 @@
     srcs: ["StorageHealthDefault.cpp"],
     name: "libhealthstoragedefault",
     vendor_available: true,
+    recovery_available: true,
     cflags: ["-Werror"],
     shared_libs: [
         "android.hardware.health@2.0",
diff --git a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
index c5431e4..bba4661 100644
--- a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
+++ b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
@@ -192,7 +192,7 @@
 
 template <typename T>
 bool verifyEnum(T value) {
-    for (auto it : hidl_enum_iterator<T>()) {
+    for (auto it : hidl_enum_range<T>()) {
         if (it == value) {
             return true;
         }
diff --git a/health/storage/1.0/Android.bp b/health/storage/1.0/Android.bp
new file mode 100644
index 0000000..35ee34f
--- /dev/null
+++ b/health/storage/1.0/Android.bp
@@ -0,0 +1,22 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.health.storage@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IGarbageCollectCallback.hal",
+        "IStorage.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "Result",
+    ],
+    gen_java: true,
+}
+
diff --git a/health/storage/1.0/IGarbageCollectCallback.hal b/health/storage/1.0/IGarbageCollectCallback.hal
new file mode 100644
index 0000000..2c24ead
--- /dev/null
+++ b/health/storage/1.0/IGarbageCollectCallback.hal
@@ -0,0 +1,30 @@
+/*
+ * 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.health.storage@1.0;
+
+/**
+ * Callback interface to IStorage.garbageCollect.
+ */
+interface IGarbageCollectCallback {
+    /**
+     * When garbage collection has finished, the implementation must
+     * invoke this function to indicate the result of the garbage collection.
+     *
+     * @return result Execution result. See documentation for Result for
+     *     details.
+     */
+    oneway onFinish(Result result);
+};
diff --git a/health/storage/1.0/IStorage.hal b/health/storage/1.0/IStorage.hal
new file mode 100644
index 0000000..980cf45
--- /dev/null
+++ b/health/storage/1.0/IStorage.hal
@@ -0,0 +1,49 @@
+/*
+ * 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.health.storage@1.0;
+
+import IGarbageCollectCallback;
+
+/**
+ * IStorage is an interface that provides operations on underlying storage
+ * devices, including flash memory.
+ */
+interface IStorage {
+    /**
+     * Start garbage collection on the driver of storage devices.
+     *
+     * Garbage collection must be started at regular intervals when it is a good
+     * time for a longer-running cleanup tasks, roughly daily.
+     *
+     * When garbage collection finishes or encounters an error before the
+     * specified timeout, the implementation must call IGarbageCollect.finish
+     * immediately with appropriate result.
+     *
+     * If garbage collection does not finish within the specified timeout,
+     * the implementation must stop garbage collection, and must not call
+     * IGarbageCollect.finish.
+     *
+     * @param timeoutSeconds timeout in seconds. The implementation must
+     *     return after the timeout is reached.
+     *
+     * @param callback callback interface. Callback must be null if the client
+     *     does not need to receive any callbacks.
+     *
+     */
+    oneway garbageCollect(uint64_t timeoutSeconds,
+                          IGarbageCollectCallback callback);
+};
diff --git a/health/storage/1.0/default/Android.bp b/health/storage/1.0/default/Android.bp
new file mode 100644
index 0000000..4723443
--- /dev/null
+++ b/health/storage/1.0/default/Android.bp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+cc_binary {
+    name: "android.hardware.health.storage@1.0-service",
+    vendor: true,
+    defaults: ["hidl_defaults"],
+    relative_install_path: "hw",
+    init_rc: ["android.hardware.health.storage@1.0-service.rc"],
+    srcs: [
+        "Storage.cpp",
+        "service.cpp",
+    ],
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+        "android.hardware.health.storage@1.0",
+    ],
+
+    static_libs: [
+        "libfstab",
+    ],
+
+    vintf_fragments: [
+        "manifest_android.hardware.health.storage@1.0.xml",
+    ],
+}
diff --git a/health/storage/1.0/default/Storage.cpp b/health/storage/1.0/default/Storage.cpp
new file mode 100644
index 0000000..2e53c50
--- /dev/null
+++ b/health/storage/1.0/default/Storage.cpp
@@ -0,0 +1,151 @@
+/*
+ * 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.
+ */
+
+#include "Storage.h"
+
+#include <sstream>
+
+#include <android-base/chrono_utils.h>
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <fstab/fstab.h>
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace storage {
+namespace V1_0 {
+namespace implementation {
+
+using base::ReadFileToString;
+using base::Timer;
+using base::Trim;
+using base::WriteStringToFd;
+using base::WriteStringToFile;
+
+std::string getGarbageCollectPath() {
+    std::unique_ptr<fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_default(),
+                                                               fs_mgr_free_fstab);
+    struct fstab_rec* rec = NULL;
+
+    for (int i = 0; i < fstab->num_entries; i++) {
+        if (fs_mgr_has_sysfs_path(&fstab->recs[i])) {
+            rec = &fstab->recs[i];
+            break;
+        }
+    }
+    if (!rec) {
+        return "";
+    }
+
+    std::string path;
+    path.append(rec->sysfs_path);
+    path = path + "/manual_gc";
+
+    return path;
+}
+
+Return<void> Storage::garbageCollect(uint64_t timeoutSeconds,
+                                     const sp<IGarbageCollectCallback>& cb) {
+    Result result = Result::SUCCESS;
+    std::string path = getGarbageCollectPath();
+
+    if (path.empty()) {
+        LOG(WARNING) << "Cannot find Dev GC path";
+        result = Result::UNKNOWN_ERROR;
+    } else {
+        Timer timer;
+        LOG(INFO) << "Start Dev GC on " << path;
+        while (1) {
+            std::string require;
+            if (!ReadFileToString(path, &require)) {
+                PLOG(WARNING) << "Reading manual_gc failed in " << path;
+                result = Result::IO_ERROR;
+                break;
+            }
+            require = Trim(require);
+            if (require == "" || require == "off" || require == "disabled") {
+                LOG(DEBUG) << "No more to do Dev GC";
+                break;
+            }
+            LOG(DEBUG) << "Trigger Dev GC on " << path;
+            if (!WriteStringToFile("1", path)) {
+                PLOG(WARNING) << "Start Dev GC failed on " << path;
+                result = Result::IO_ERROR;
+                break;
+            }
+            if (timer.duration() >= std::chrono::seconds(timeoutSeconds)) {
+                LOG(WARNING) << "Dev GC timeout";
+                // Timeout is not treated as an error. Try next time.
+                break;
+            }
+            sleep(2);
+        }
+        LOG(INFO) << "Stop Dev GC on " << path;
+        if (!WriteStringToFile("0", path)) {
+            PLOG(WARNING) << "Stop Dev GC failed on " << path;
+            result = Result::IO_ERROR;
+        }
+    }
+
+    if (cb != nullptr) {
+        auto ret = cb->onFinish(result);
+        if (!ret.isOk()) {
+            LOG(WARNING) << "Cannot return result to callback: " << ret.description();
+        }
+    }
+    return Void();
+}
+
+Return<void> Storage::debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) {
+    if (handle == nullptr || handle->numFds < 1) {
+        return Void();
+    }
+
+    int fd = handle->data[0];
+    std::stringstream output;
+
+    std::string path = getGarbageCollectPath();
+    if (path.empty()) {
+        output << "Cannot find Dev GC path";
+    } else {
+        std::string require;
+
+        if (ReadFileToString(path, &require)) {
+            output << path << ":" << require << std::endl;
+        }
+
+        if (WriteStringToFile("0", path)) {
+            output << "stop success" << std::endl;
+        }
+    }
+
+    if (!WriteStringToFd(output.str(), fd)) {
+        PLOG(WARNING) << "debug: cannot write to fd";
+    }
+
+    fsync(fd);
+
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace storage
+}  // namespace health
+}  // namespace hardware
+}  // namespace android
diff --git a/health/storage/1.0/default/Storage.h b/health/storage/1.0/default/Storage.h
new file mode 100644
index 0000000..8c57ddb
--- /dev/null
+++ b/health/storage/1.0/default/Storage.h
@@ -0,0 +1,49 @@
+/*
+ * 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_HEALTH_FILESYSTEM_V1_0_FILESYSTEM_H
+#define ANDROID_HARDWARE_HEALTH_FILESYSTEM_V1_0_FILESYSTEM_H
+
+#include <android/hardware/health/storage/1.0/IStorage.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace storage {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+
+struct Storage : public IStorage {
+    Return<void> garbageCollect(uint64_t timeoutSeconds,
+                                const sp<IGarbageCollectCallback>& cb) override;
+    Return<void> debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) override;
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace storage
+}  // namespace health
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_HEALTH_FILESYSTEM_V1_0_FILESYSTEM_H
diff --git a/health/storage/1.0/default/android.hardware.health.storage@1.0-service.rc b/health/storage/1.0/default/android.hardware.health.storage@1.0-service.rc
new file mode 100644
index 0000000..c6a1425
--- /dev/null
+++ b/health/storage/1.0/default/android.hardware.health.storage@1.0-service.rc
@@ -0,0 +1,5 @@
+service vendor.health-storage-hal-1-0 /vendor/bin/hw/android.hardware.health.storage@1.0-service
+    interface android.hardware.health.storage@1.0::IStorage default
+    class hal
+    user system
+    group system
diff --git a/health/storage/1.0/default/manifest_android.hardware.health.storage@1.0.xml b/health/storage/1.0/default/manifest_android.hardware.health.storage@1.0.xml
new file mode 100644
index 0000000..ffe854e
--- /dev/null
+++ b/health/storage/1.0/default/manifest_android.hardware.health.storage@1.0.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal>
+        <name>android.hardware.health.storage</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IStorage</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/health/storage/1.0/default/service.cpp b/health/storage/1.0/default/service.cpp
new file mode 100644
index 0000000..a945033
--- /dev/null
+++ b/health/storage/1.0/default/service.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <hidl/HidlTransportSupport.h>
+#include "Storage.h"
+
+using android::OK;
+using android::sp;
+using android::status_t;
+using android::UNKNOWN_ERROR;
+using android::hardware::configureRpcThreadpool;
+using android::hardware::joinRpcThreadpool;
+using android::hardware::health::storage::V1_0::IStorage;
+using android::hardware::health::storage::V1_0::implementation::Storage;
+
+int main() {
+    configureRpcThreadpool(1, true);
+
+    sp<IStorage> service = new Storage();
+    status_t result = service->registerAsService();
+
+    if (result != OK) {
+        return result;
+    }
+
+    joinRpcThreadpool();
+    return UNKNOWN_ERROR;
+}
diff --git a/health/storage/1.0/types.hal b/health/storage/1.0/types.hal
new file mode 100644
index 0000000..2da0871
--- /dev/null
+++ b/health/storage/1.0/types.hal
@@ -0,0 +1,35 @@
+/*
+ * 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.health.storage@1.0;
+
+/**
+ * Status values for HAL methods.
+ */
+enum Result : uint32_t {
+    /**
+     * Execution of the method is successful.
+     */
+    SUCCESS = 0,
+    /**
+     * An IO error is encountered when the HAL communicates with the device.
+     */
+    IO_ERROR,
+    /**
+     * An unknown error is encountered.
+     */
+    UNKNOWN_ERROR,
+};
diff --git a/health/storage/1.0/vts/functional/Android.bp b/health/storage/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..63591cf
--- /dev/null
+++ b/health/storage/1.0/vts/functional/Android.bp
@@ -0,0 +1,26 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalHealthStorageV1_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalHealthStorageV1_0TargetTest.cpp"],
+    static_libs: ["android.hardware.health.storage@1.0"],
+    shared_libs: [
+        "libhidltransport"
+    ],
+}
+
diff --git a/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp
new file mode 100644
index 0000000..5ad561c
--- /dev/null
+++ b/health/storage/1.0/vts/functional/VtsHalHealthStorageV1_0TargetTest.cpp
@@ -0,0 +1,193 @@
+/*
+ * 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.
+ */
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+#include <android-base/logging.h>
+#include <android/hardware/health/storage/1.0/IStorage.h>
+#include <hidl/HidlTransportSupport.h>
+#include <unistd.h>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace health {
+namespace storage {
+namespace V1_0 {
+
+using ::std::literals::chrono_literals::operator""ms;
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk()) << ret.description()
+
+// Dev GC timeout. This is the timeout used by vold.
+const uint64_t kDevGcTimeoutSec = 120;
+const std::chrono::seconds kDevGcTimeout{kDevGcTimeoutSec};
+// Time accounted for RPC calls.
+const std::chrono::milliseconds kRpcTime{100};
+
+template <typename R>
+std::string toString(std::chrono::duration<R, std::milli> time) {
+    return std::to_string(time.count()) + "ms";
+}
+
+/** An atomic boolean flag that indicates whether a task has finished. */
+class Flag {
+   public:
+    void onFinish() {
+        std::unique_lock<std::mutex> lock(mMutex);
+        onFinishLocked(&lock);
+    }
+    template <typename R, typename P>
+    bool wait(std::chrono::duration<R, P> duration) {
+        std::unique_lock<std::mutex> lock(mMutex);
+        return waitLocked(&lock, duration);
+    }
+
+   protected:
+    /** Will unlock. */
+    void onFinishLocked(std::unique_lock<std::mutex>* lock) {
+        mFinished = true;
+        lock->unlock();
+        mCv.notify_all();
+    }
+    template <typename R, typename P>
+    bool waitLocked(std::unique_lock<std::mutex>* lock, std::chrono::duration<R, P> duration) {
+        mCv.wait_for(*lock, duration, [this] { return mFinished; });
+        return mFinished;
+    }
+
+    bool mFinished{false};
+    std::mutex mMutex;
+    std::condition_variable mCv;
+};
+
+class GcCallback : public IGarbageCollectCallback, public Flag {
+   public:
+    Return<void> onFinish(Result result) override {
+        std::unique_lock<std::mutex> lock(mMutex);
+        mResult = result;
+        Flag::onFinishLocked(&lock);
+        return Void();
+    }
+
+    /**
+     * Wait for a specific "timeout". If GC has finished, test that the result
+     * is equal to the "expected" value.
+     */
+    template <typename R, typename P>
+    void waitForResult(std::chrono::duration<R, P> timeout, Result expected) {
+        std::unique_lock<std::mutex> lock(mMutex);
+        if (waitLocked(&lock, timeout)) {
+            EXPECT_EQ(expected, mResult);
+        } else {
+            LOG(INFO) << "timeout after " << toString(timeout);
+        }
+    }
+
+   private:
+    Result mResult{Result::UNKNOWN_ERROR};
+};
+
+/** Test environment for Health Storage HIDL HAL. */
+class HealthStorageHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    /** get the test environment singleton */
+    static HealthStorageHidlEnvironment* Instance() {
+        static HealthStorageHidlEnvironment* instance = new HealthStorageHidlEnvironment();
+        return instance;
+    }
+    virtual void registerTestServices() override { registerTestService<IStorage>(); }
+
+   private:
+    HealthStorageHidlEnvironment() {}
+};
+
+class HealthStorageHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        fs = ::testing::VtsHalHidlTargetTestBase::getService<IStorage>(
+            HealthStorageHidlEnvironment::Instance()->getServiceName<IStorage>());
+
+        ASSERT_NE(fs, nullptr);
+        LOG(INFO) << "Service is remote " << fs->isRemote();
+    }
+
+    virtual void TearDown() override {
+        EXPECT_TRUE(ping(kRpcTime))
+            << "Service is not responsive; expect subsequent tests to fail.";
+    }
+
+    /**
+     * Ping the service and expect it to return after "timeout". Return true
+     * iff the service is responsive within "timeout".
+     */
+    template <typename R, typename P>
+    bool ping(std::chrono::duration<R, P> timeout) {
+        // Ensure the service is responsive after the test.
+        sp<IStorage> service = fs;
+        auto pingFlag = std::make_shared<Flag>();
+        std::thread([service, pingFlag] {
+            service->ping();
+            pingFlag->onFinish();
+        })
+            .detach();
+        return pingFlag->wait(timeout);
+    }
+
+    sp<IStorage> fs;
+};
+
+/**
+ * Ensure garbage collection works on null callback.
+ */
+TEST_F(HealthStorageHidlTest, GcNullCallback) {
+    auto ret = fs->garbageCollect(kDevGcTimeoutSec, nullptr);
+
+    ASSERT_OK(ret);
+
+    // Hold test process because HAL can be single-threaded and doing GC.
+    ASSERT_TRUE(ping(kDevGcTimeout + kRpcTime))
+        << "Service must be available after " << toString(kDevGcTimeout + kRpcTime);
+}
+
+/**
+ * Ensure garbage collection works on non-null callback.
+ */
+TEST_F(HealthStorageHidlTest, GcNonNullCallback) {
+    sp<GcCallback> cb = new GcCallback();
+    auto ret = fs->garbageCollect(kDevGcTimeoutSec, cb);
+    ASSERT_OK(ret);
+    cb->waitForResult(kDevGcTimeout + kRpcTime, Result::SUCCESS);
+}
+
+}  // namespace V1_0
+}  // namespace storage
+}  // namespace health
+}  // namespace hardware
+}  // namespace android
+
+int main(int argc, char** argv) {
+    using ::android::hardware::configureRpcThreadpool;
+    using ::android::hardware::health::storage::V1_0::HealthStorageHidlEnvironment;
+
+    configureRpcThreadpool(1, false /* callerWillJoin*/);
+    ::testing::AddGlobalTestEnvironment(HealthStorageHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    HealthStorageHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}
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 086ba2f..ea8d490 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,4 @@
 service vendor.keymaster-3-0 /vendor/bin/hw/android.hardware.keymaster@3.0-service
     class early_hal
-    user system
-    group system drmrpc
+    user nobody
+    group drmrpc
diff --git a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
index 7cdf253..ccb5622 100644
--- a/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/3.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -295,7 +295,7 @@
 }
 
 bool verify_chain(const hidl_vec<hidl_vec<uint8_t>>& chain) {
-    for (size_t i = 0; i < chain.size() - 1; ++i) {
+    for (size_t i = 0; i < chain.size(); ++i) {
         X509_Ptr key_cert(parse_cert_blob(chain[i]));
         X509_Ptr signing_cert;
         if (i < chain.size() - 1) {
@@ -1083,7 +1083,7 @@
         AuthorizationSet auths(keyCharacteristics.teeEnforced);
         auths.push_back(AuthorizationSet(keyCharacteristics.softwareEnforced));
 
-        if (!SupportsSymmetric() && asymmetric) {
+        if (IsSecure() && !SupportsSymmetric() && asymmetric) {
             EXPECT_TRUE(auths.Contains(TAG_ORIGIN, KeyOrigin::UNKNOWN));
         } else {
             EXPECT_TRUE(auths.Contains(TAG_ORIGIN, KeyOrigin::GENERATED));
diff --git a/keymaster/4.0/IKeymasterDevice.hal b/keymaster/4.0/IKeymasterDevice.hal
index 85a25c6..c867ab0 100644
--- a/keymaster/4.0/IKeymasterDevice.hal
+++ b/keymaster/4.0/IKeymasterDevice.hal
@@ -168,7 +168,7 @@
  * startup, preferably by the bootloader.  This bitstring must be cryptographically bound to every
  * key managed by the IKeymasterDevice.  As above, the recommended mechanism for this cryptographic
  * binding is to include the Root of Trust data in the input to the key derivation function used to
- * derive a key that is used to encryp the private/secret key material.
+ * derive a key that is used to encrypt the private/secret key material.
  *
  * The root of trust consists of a bitstring that must be derived from the public key used by
  * Verified Boot to verify the signature on the boot image and from the the lock state of the
@@ -386,7 +386,7 @@
      * Generates a new cryptographic key, specifying associated parameters, which must be
      * cryptographically bound to the key.  IKeymasterDevice implementations must disallow any use
      * of a key in any way inconsistent with the authorizations specified at generation time.  With
-     * respect to parameters that the secure environment cannot enforce, the secure envionment's
+     * respect to parameters that the secure environment cannot enforce, the secure environment's
      * obligation is limited to ensuring that the unenforceable parameters associated with the key
      * cannot be modified, so that every call to getKeyCharacteristics returns the original
      * values.  In addition, the characteristics returned by generateKey places parameters correctly
@@ -433,7 +433,7 @@
      *   supported for RSA keys.
      *
      * o Tag::DIGEST specifies digest algorithms that may be used with the new key.  TEE
-     *   IKeymasterDevice implementatiosn must support all Digest values (see types.hal) for RSA
+     *   IKeymasterDevice implementations must support all Digest values (see types.hal) for RSA
      *   keys.  StrongBox IKeymasterDevice implementations must support SHA_2_256.
      *
      * o Tag::PADDING specifies the padding modes that may be used with the new
@@ -495,13 +495,13 @@
      *
      * @param keyFormat The format of the key material to import.  See KeyFormat in types.hal.
      *
-     * @pram keyData The key material to import, in the format specifed in keyFormat.
+     * @pram keyData The key material to import, in the format specified in keyFormat.
      *
      * @return keyBlob Opaque descriptor of the imported key.  The recommended implementation
      *         strategy is to include an encrypted copy of the key material, wrapped in a key
      *         unavailable outside secure hardware.
      *
-     * @return keyCharacteristics Decription of the generated key.  See the getKeyCharacteristics
+     * @return keyCharacteristics Description of the generated key.  See the getKeyCharacteristics
      *         method below.
      */
     importKey(vec<KeyParameter> keyParams, KeyFormat keyFormat, vec<uint8_t> keyData)
@@ -615,7 +615,7 @@
      *        value, it must be computationally infeasible for the secure hardware to obtain the key
      *        material.
      *
-     * @return keyCharacteristics Decription of the generated key.  See KeyCharacteristics in
+     * @return keyCharacteristics Description of the generated key.  See KeyCharacteristics in
      *         types.hal.
      */
     getKeyCharacteristics(vec<uint8_t> keyBlob, vec<uint8_t> clientId, vec<uint8_t> appData)
@@ -815,7 +815,7 @@
      * any one of them is higher than the corresponding current device value upgradeKey() must
      * return ErrorCode::INVALID_ARGUMENT.  There is one exception: it is always permissible to
      * "downgrade" from any OS_VERSION number to OS_VERSION 0.  For example, if the key has
-     * OS_VERSION 080001, it is permisible to upgrade the key if the current system version is
+     * OS_VERSION 080001, it is permissible to upgrade the key if the current system version is
      * 080100, because the new version is larger, or if the current system version is 0, because
      * upgrades to 0 are always allowed.  If the system version were 080000, however, keymaster must
      * return ErrorCode::INVALID_ARGUMENT because that value is smaller than 080001.  Values other
@@ -1040,7 +1040,7 @@
      * authorizations contain Tag::CALLER_NONCE, then the caller may provide an IV/nonce with
      * Tag::NONCE in inParams.  If a nonce is provided when Tag::CALLER_NONCE is not authorized,
      * begin() must return ErrorCode::CALLER_NONCE_PROHIBITED.  If a nonce is not provided when
-     * Tag::CALLER_NONCE is authorized, IKeymasterDevice msut generate a random IV/nonce.
+     * Tag::CALLER_NONCE is authorized, IKeymasterDevice must generate a random IV/nonce.
      *
      * -- HMAC keys --
      *
@@ -1082,7 +1082,7 @@
 
     /**
      * Provides data to, and possibly receives output from, an ongoing cryptographic operation begun
-     * with begin().  The operation is specified by the operationHandle paramater.
+     * with begin().  The operation is specified by the operationHandle parameter.
      *
      * If operationHandle is invalid, update() must return ErrorCode::INVALID_OPERATION_HANDLE.
      *
diff --git a/keymaster/4.0/support/authorization_set.cpp b/keymaster/4.0/support/authorization_set.cpp
index bf77420..afbcdac 100644
--- a/keymaster/4.0/support/authorization_set.cpp
+++ b/keymaster/4.0/support/authorization_set.cpp
@@ -523,8 +523,7 @@
     return *this;
 }
 
-AuthorizationSetBuilder& AuthorizationSetBuilder::Digest(
-    std::initializer_list<V4_0::Digest> digests) {
+AuthorizationSetBuilder& AuthorizationSetBuilder::Digest(std::vector<V4_0::Digest> digests) {
     for (auto digest : digests) {
         push_back(TAG_DIGEST, digest);
     }
diff --git a/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
index 6c7fd35..1869682 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
@@ -278,7 +278,7 @@
     AuthorizationSetBuilder& GcmModeMacLen(uint32_t macLength);
 
     AuthorizationSetBuilder& BlockMode(std::initializer_list<BlockMode> blockModes);
-    AuthorizationSetBuilder& Digest(std::initializer_list<Digest> digests);
+    AuthorizationSetBuilder& Digest(std::vector<Digest> digests);
     AuthorizationSetBuilder& Padding(std::initializer_list<PaddingMode> paddings);
 
     template <typename... T>
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
index c89abd9..995ae4f 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
@@ -651,6 +651,8 @@
             return {3072, 4096};
         case Algorithm::EC:
             return {224, 384, 521};
+        case Algorithm::AES:
+            return {192};
         default:
             return {};
     }
@@ -670,8 +672,7 @@
     return {EcCurve::P_224, EcCurve::P_384, EcCurve::P_521};
 }
 
-std::initializer_list<Digest> KeymasterHidlTest::ValidDigests(bool withNone, bool withMD5) {
-    std::vector<Digest> result;
+std::vector<Digest> KeymasterHidlTest::ValidDigests(bool withNone, bool withMD5) {
     switch (SecLevel()) {
         case SecurityLevel::TRUSTED_ENVIRONMENT:
             if (withNone) {
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.h b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
index 94beb21..4cd6a5b 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.h
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
@@ -214,7 +214,7 @@
     std::vector<EcCurve> ValidCurves();
     std::vector<EcCurve> InvalidCurves();
 
-    std::initializer_list<Digest> ValidDigests(bool withNone, bool withMD5);
+    std::vector<Digest> ValidDigests(bool withNone, bool withMD5);
     std::vector<Digest> InvalidDigests();
 
     HidlBuf key_blob_;
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 3919a69..784ae30 100644
--- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
+++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp
@@ -751,6 +751,7 @@
  * presented.
  */
 TEST_F(SigningOperationsTest, NoUserConfirmation) {
+    if (SecLevel() == SecurityLevel::STRONGBOX) return;
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .RsaSigningKey(1024, 65537)
                                              .Digest(Digest::NONE)
@@ -773,7 +774,7 @@
  */
 TEST_F(SigningOperationsTest, RsaPkcs1Sha256Success) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .RsaSigningKey(1024, 65537)
+                                             .RsaSigningKey(2048, 65537)
                                              .Digest(Digest::SHA_2_256)
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
                                              .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
@@ -790,7 +791,7 @@
  */
 TEST_F(SigningOperationsTest, RsaPkcs1NoDigestSuccess) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .RsaSigningKey(1024, 65537)
+                                             .RsaSigningKey(2048, 65537)
                                              .Digest(Digest::NONE)
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
                                              .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
@@ -808,11 +809,11 @@
  */
 TEST_F(SigningOperationsTest, RsaPkcs1NoDigestTooLong) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .RsaSigningKey(1024, 65537)
+                                             .RsaSigningKey(2048, 65537)
                                              .Digest(Digest::NONE)
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
                                              .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
-    string message(129, 'a');
+    string message(257, 'a');
 
     EXPECT_EQ(ErrorCode::OK,
               Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
@@ -855,12 +856,12 @@
  */
 TEST_F(SigningOperationsTest, RsaNoPaddingTooLong) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .RsaSigningKey(1024, 65537)
+                                             .RsaSigningKey(2048, 65537)
                                              .Digest(Digest::NONE)
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
                                              .Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)));
     // One byte too long
-    string message(1024 / 8 + 1, 'a');
+    string message(2048 / 8 + 1, 'a');
     ASSERT_EQ(ErrorCode::OK,
               Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
                                           .Digest(Digest::NONE)
@@ -889,7 +890,7 @@
  */
 TEST_F(SigningOperationsTest, RsaAbort) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .RsaSigningKey(1024, 65537)
+                                             .RsaSigningKey(2048, 65537)
                                              .Digest(Digest::NONE)
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
                                              .Padding(PaddingMode::NONE)));
@@ -914,7 +915,7 @@
  */
 TEST_F(SigningOperationsTest, RsaUnsupportedPadding) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .RsaSigningKey(1024, 65537)
+                                             .RsaSigningKey(2048, 65537)
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
                                              .Digest(Digest::SHA_2_256 /* supported digest */)
                                              .Padding(PaddingMode::PKCS7)));
@@ -931,7 +932,7 @@
  */
 TEST_F(SigningOperationsTest, RsaNoDigest) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .RsaSigningKey(1024, 65537)
+                                             .RsaSigningKey(2048, 65537)
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
                                              .Digest(Digest::NONE)
                                              .Padding(PaddingMode::RSA_PSS)));
@@ -952,7 +953,7 @@
 TEST_F(SigningOperationsTest, RsaNoPadding) {
     // Padding must be specified
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .RsaKey(1024, 65537)
+                                             .RsaKey(2048, 65537)
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
                                              .SigningKey()
                                              .Digest(Digest::NONE)));
@@ -968,12 +969,12 @@
 TEST_F(SigningOperationsTest, RsaTooShortMessage) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .RsaSigningKey(1024, 65537)
+                                             .RsaSigningKey(2048, 65537)
                                              .Digest(Digest::NONE)
                                              .Padding(PaddingMode::NONE)));
 
     // Barely shorter
-    string message(1024 / 8 - 1, 'a');
+    string message(2048 / 8 - 1, 'a');
     SignMessage(message, AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE));
 
     // Much shorter
@@ -989,7 +990,7 @@
 TEST_F(SigningOperationsTest, RsaSignWithEncryptionKey) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .RsaEncryptionKey(1024, 65537)
+                                             .RsaEncryptionKey(2048, 65537)
                                              .Digest(Digest::NONE)
                                              .Padding(PaddingMode::NONE)));
     ASSERT_EQ(ErrorCode::INCOMPATIBLE_PURPOSE,
@@ -1006,12 +1007,12 @@
 TEST_F(SigningOperationsTest, RsaSignTooLargeMessage) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .RsaSigningKey(1024, 65537)
+                                             .RsaSigningKey(2048, 65537)
                                              .Digest(Digest::NONE)
                                              .Padding(PaddingMode::NONE)));
 
     // Largest possible message will always be larger than the public modulus.
-    string message(1024 / 8, static_cast<char>(0xff));
+    string message(2048 / 8, static_cast<char>(0xff));
     ASSERT_EQ(ErrorCode::OK, Begin(KeyPurpose::SIGN, AuthorizationSetBuilder()
                                                          .Authorization(TAG_NO_AUTH_REQUIRED)
                                                          .Digest(Digest::NONE)
@@ -1328,7 +1329,7 @@
 TEST_F(VerificationOperationsTest, RsaSuccess) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .RsaSigningKey(1024, 65537)
+                                             .RsaSigningKey(2048, 65537)
                                              .Digest(Digest::NONE)
                                              .Padding(PaddingMode::NONE)));
     string message = "12345678901234567890123456789012";
@@ -1567,7 +1568,7 @@
  */
 TEST_F(ExportKeyTest, RsaUnsupportedKeyFormat) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .RsaSigningKey(1024, 65537)
+                                             .RsaSigningKey(2048, 65537)
                                              .Digest(Digest::NONE)
                                              .Padding(PaddingMode::NONE)));
     HidlBuf export_data;
@@ -1583,7 +1584,7 @@
 TEST_F(ExportKeyTest, RsaCorruptedKeyBlob) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .RsaSigningKey(1024, 65537)
+                                             .RsaSigningKey(2048, 65537)
                                              .Digest(Digest::NONE)
                                              .Padding(PaddingMode::NONE)));
     for (size_t i = 0; i < key_blob_.size(); ++i) {
@@ -1975,16 +1976,16 @@
 TEST_F(EncryptionOperationsTest, RsaNoPaddingSuccess) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .RsaEncryptionKey(1024, 65537)
+                                             .RsaEncryptionKey(2048, 65537)
                                              .Padding(PaddingMode::NONE)));
 
-    string message = string(1024 / 8, 'a');
+    string message = string(2048 / 8, 'a');
     auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE);
     string ciphertext1 = EncryptMessage(message, params);
-    EXPECT_EQ(1024U / 8, ciphertext1.size());
+    EXPECT_EQ(2048U / 8, ciphertext1.size());
 
     string ciphertext2 = EncryptMessage(message, params);
-    EXPECT_EQ(1024U / 8, ciphertext2.size());
+    EXPECT_EQ(2048U / 8, ciphertext2.size());
 
     // Unpadded RSA is deterministic
     EXPECT_EQ(ciphertext1, ciphertext2);
@@ -1998,16 +1999,16 @@
 TEST_F(EncryptionOperationsTest, RsaNoPaddingShortMessage) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .RsaEncryptionKey(1024, 65537)
+                                             .RsaEncryptionKey(2048, 65537)
                                              .Padding(PaddingMode::NONE)));
 
     string message = "1";
     auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE);
 
     string ciphertext = EncryptMessage(message, params);
-    EXPECT_EQ(1024U / 8, ciphertext.size());
+    EXPECT_EQ(2048U / 8, ciphertext.size());
 
-    string expected_plaintext = string(1024 / 8 - 1, 0) + message;
+    string expected_plaintext = string(2048U / 8 - 1, 0) + message;
     string plaintext = DecryptMessage(ciphertext, params);
 
     EXPECT_EQ(expected_plaintext, plaintext);
@@ -2015,8 +2016,8 @@
     // Degenerate case, encrypting a numeric 1 yields 0x00..01 as the ciphertext.
     message = static_cast<char>(1);
     ciphertext = EncryptMessage(message, params);
-    EXPECT_EQ(1024U / 8, ciphertext.size());
-    EXPECT_EQ(ciphertext, string(1024 / 8 - 1, 0) + message);
+    EXPECT_EQ(2048U / 8, ciphertext.size());
+    EXPECT_EQ(ciphertext, string(2048U / 8 - 1, 0) + message);
 }
 
 /*
@@ -2027,10 +2028,10 @@
 TEST_F(EncryptionOperationsTest, RsaNoPaddingTooLong) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .RsaEncryptionKey(1024, 65537)
+                                             .RsaEncryptionKey(2048, 65537)
                                              .Padding(PaddingMode::NONE)));
 
-    string message(1024 / 8 + 1, 'a');
+    string message(2048 / 8 + 1, 'a');
 
     auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE);
     EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
@@ -2047,7 +2048,7 @@
 TEST_F(EncryptionOperationsTest, RsaNoPaddingTooLarge) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .RsaEncryptionKey(1024, 65537)
+                                             .RsaEncryptionKey(2048, 65537)
                                              .Padding(PaddingMode::NONE)));
 
     HidlBuf exported;
@@ -2058,7 +2059,7 @@
     RSA_Ptr rsa(EVP_PKEY_get1_RSA(pkey.get()));
 
     size_t modulus_len = BN_num_bytes(rsa->n);
-    ASSERT_EQ(1024U / 8, modulus_len);
+    ASSERT_EQ(2048U / 8, modulus_len);
     std::unique_ptr<uint8_t[]> modulus_buf(new uint8_t[modulus_len]);
     BN_bn2bin(rsa->n, modulus_buf.get());
 
@@ -2074,7 +2075,7 @@
     // One smaller than the modulus is okay.
     BN_sub(rsa->n, rsa->n, BN_value_one());
     modulus_len = BN_num_bytes(rsa->n);
-    ASSERT_EQ(1024U / 8, modulus_len);
+    ASSERT_EQ(2048U / 8, modulus_len);
     BN_bn2bin(rsa->n, modulus_buf.get());
     message = string(reinterpret_cast<const char*>(modulus_buf.get()), modulus_len);
     EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
@@ -2140,7 +2141,7 @@
 TEST_F(EncryptionOperationsTest, RsaOaepInvalidDigest) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .RsaEncryptionKey(1024, 65537)
+                                             .RsaEncryptionKey(2048, 65537)
                                              .Padding(PaddingMode::RSA_OAEP)
                                              .Digest(Digest::NONE)));
     string message = "Hello World!";
@@ -2186,12 +2187,12 @@
 TEST_F(EncryptionOperationsTest, RsaOaepTooLarge) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .RsaEncryptionKey(1024, 65537)
+                                             .RsaEncryptionKey(2048, 65537)
                                              .Padding(PaddingMode::RSA_OAEP)
                                              .Digest(Digest::SHA_2_256)));
     constexpr size_t digest_size = 256 /* SHA_2_256 */ / 8;
     constexpr size_t oaep_overhead = 2 * digest_size + 2;
-    string message(1024 / 8 - oaep_overhead + 1, 'a');
+    string message(2048 / 8 - oaep_overhead + 1, 'a');
     EXPECT_EQ(ErrorCode::OK,
               Begin(KeyPurpose::ENCRYPT,
                     AuthorizationSetBuilder().Padding(PaddingMode::RSA_OAEP).Digest(Digest::SHA_2_256)));
@@ -2208,16 +2209,16 @@
 TEST_F(EncryptionOperationsTest, RsaPkcs1Success) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .RsaEncryptionKey(1024, 65537)
+                                             .RsaEncryptionKey(2048, 65537)
                                              .Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT)));
 
     string message = "Hello World!";
     auto params = AuthorizationSetBuilder().Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT);
     string ciphertext1 = EncryptMessage(message, params);
-    EXPECT_EQ(1024U / 8, ciphertext1.size());
+    EXPECT_EQ(2048U / 8, ciphertext1.size());
 
     string ciphertext2 = EncryptMessage(message, params);
-    EXPECT_EQ(1024U / 8, ciphertext2.size());
+    EXPECT_EQ(2048U / 8, ciphertext2.size());
 
     // PKCS1 v1.5 randomizes padding so every result should be different.
     EXPECT_NE(ciphertext1, ciphertext2);
@@ -2247,9 +2248,9 @@
 TEST_F(EncryptionOperationsTest, RsaPkcs1TooLarge) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .RsaEncryptionKey(1024, 65537)
+                                             .RsaEncryptionKey(2048, 65537)
                                              .Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT)));
-    string message(1024 / 8 - 10, 'a');
+    string message(2048 / 8 - 10, 'a');
 
     auto params = AuthorizationSetBuilder().Padding(PaddingMode::RSA_PKCS1_1_5_ENCRYPT);
     EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, params));
@@ -2632,9 +2633,13 @@
  * Verifies AES CTR implementation against SP800-38A test vectors.
  */
 TEST_F(EncryptionOperationsTest, AesCtrSp80038aTestVector) {
+    std::vector<uint32_t> InvalidSizes = InvalidKeySizes(Algorithm::AES);
     for (size_t i = 0; i < 3; i++) {
         const AesCtrSp80038aTestVector& test(kAesCtrSp80038aTestVectors[i]);
         const string key = hex2str(test.key);
+        if (std::find(InvalidSizes.begin(), InvalidSizes.end(), (key.size() * 8)) !=
+            InvalidSizes.end())
+            continue;
         const string nonce = hex2str(test.nonce);
         const string plaintext = hex2str(test.plaintext);
         const string ciphertext = hex2str(test.ciphertext);
@@ -3827,7 +3832,7 @@
 TEST_F(AttestationTest, RsaAttestation) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .RsaSigningKey(1024, 65537)
+                                             .RsaSigningKey(2048, 65537)
                                              .Digest(Digest::NONE)
                                              .Padding(PaddingMode::NONE)
                                              .Authorization(TAG_INCLUDE_UNIQUE_ID)));
@@ -3854,7 +3859,7 @@
 TEST_F(AttestationTest, RsaAttestationRequiresAppId) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
                                              .Authorization(TAG_NO_AUTH_REQUIRED)
-                                             .RsaSigningKey(1024, 65537)
+                                             .RsaSigningKey(2048, 65537)
                                              .Digest(Digest::NONE)
                                              .Padding(PaddingMode::NONE)
                                              .Authorization(TAG_INCLUDE_UNIQUE_ID)));
@@ -3965,7 +3970,7 @@
  */
 TEST_F(KeyDeletionTest, DeleteKey) {
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .RsaSigningKey(1024, 65537)
+                                             .RsaSigningKey(2048, 65537)
                                              .Digest(Digest::NONE)
                                              .Padding(PaddingMode::NONE)
                                              .Authorization(TAG_NO_AUTH_REQUIRED)));
@@ -4009,7 +4014,7 @@
 TEST_F(KeyDeletionTest, DeleteInvalidKey) {
     // Generate key just to check if rollback protection is implemented
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .RsaSigningKey(1024, 65537)
+                                             .RsaSigningKey(2048, 65537)
                                              .Digest(Digest::NONE)
                                              .Padding(PaddingMode::NONE)
                                              .Authorization(TAG_NO_AUTH_REQUIRED)));
@@ -4048,7 +4053,7 @@
 TEST_F(KeyDeletionTest, DeleteAllKeys) {
     if (!arm_deleteAllKeys) return;
     ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
-                                             .RsaSigningKey(1024, 65537)
+                                             .RsaSigningKey(2048, 65537)
                                              .Digest(Digest::NONE)
                                              .Padding(PaddingMode::NONE)
                                              .Authorization(TAG_NO_AUTH_REQUIRED)));
diff --git a/light/utils/main.cpp b/light/utils/main.cpp
index 724e0ee..d07e799 100644
--- a/light/utils/main.cpp
+++ b/light/utils/main.cpp
@@ -55,6 +55,5 @@
         }
     });
 
-    // b/77934844: Avoid running static destructors.
-    _exit(1);
+    return 0;
 }
diff --git a/media/1.0/Android.bp b/media/1.0/Android.bp
index c5d49b6..45fedb9 100644
--- a/media/1.0/Android.bp
+++ b/media/1.0/Android.bp
@@ -17,6 +17,6 @@
         "AnwBufferAttributes",
         "Rect",
     ],
-    gen_java: false,
+    gen_java: true,
 }
 
diff --git a/neuralnetworks/1.0/IPreparedModel.hal b/neuralnetworks/1.0/IPreparedModel.hal
index ee406fb..ecaa7f8 100644
--- a/neuralnetworks/1.0/IPreparedModel.hal
+++ b/neuralnetworks/1.0/IPreparedModel.hal
@@ -42,6 +42,12 @@
      * 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.
+     *
      * 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 1ae1726..0880b2f 100644
--- a/neuralnetworks/1.0/types.hal
+++ b/neuralnetworks/1.0/types.hal
@@ -68,6 +68,7 @@
  * The type of an operation in a model.
  */
 enum OperationType : int32_t {
+
     /**
      * Adds two tensors, element-wise.
      *
@@ -105,6 +106,8 @@
      *
      * Outputs:
      * * 0: The sum, a tensor of the same {@link OperandType} as input0.
+     *
+     * Available since API level 27.
      */
     ADD = 0,
 
@@ -116,8 +119,10 @@
      *
      * The values in the output tensor are computed as:
      *
-     *     output[batch, row, col, channel] =
-     *         sum_{i, j}(input[batch, row + i, col + j, channel]) / sum(1)
+     *     output[b, i, j, channel] =
+     *         sum_{di, dj}(
+     *             input[b, strides[1] * i + di, strides[2] * j + dj, channel]
+     *         ) / sum(1)
      *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT32}
@@ -171,7 +176,9 @@
      *
      * Outputs:
      * * 0: The output 4-D tensor, of shape
-            [batches, out_height, out_width, depth].
+     *      [batches, out_height, out_width, depth].
+     *
+     * Available since API level 27.
      */
     AVERAGE_POOL_2D = 1,
 
@@ -198,6 +205,8 @@
      * 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.
      */
     CONCATENATION = 2,
 
@@ -213,12 +222,11 @@
      *
      * The values in the output tensor are computed as:
      *
-     *     output[batch, row, col, channel] =
-     *         sum_{i, j} (
-     *             input[batch, row + i, col + j, k] *
-     *             filter[channel, row + i, col + j, k] +
-     *             bias[channel]
-     *         )
+     *     output[b, i, j, channel] =
+     *         sum_{di, dj, k} (
+     *             input[b, strides[1] * i + di, strides[2] * j + dj, k] *
+     *             filter[channel, di, dj, k]
+     *         ) + bias[channel]
      *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT32}
@@ -274,7 +282,7 @@
      * * 4: An {@link OperandType::INT32} scalar, specifying the stride when
      *      walking through input in the ‘width’ dimension.
      * * 5: An {@link OperandType::INT32} scalar, specifying the stride when
-    *       walking through input in the ‘height’ dimension.
+     *      walking through input in the ‘height’ dimension.
      * * 6: An {@link OperandType::INT32} scalar, and has to be one of the
      *      {@link FusedActivationFunc} values. Specifies the activation to
      *      invoke on the result.
@@ -284,6 +292,8 @@
      *      [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.
      */
     CONV_2D = 3,
 
@@ -307,7 +317,7 @@
      *         sum_{di, dj} (
      *             input[b, strides[1] * i + di, strides[2] * j + dj, k] *
      *             filter[1, di, dj, k * channel_multiplier + q]
-     *         )
+     *         ) + bias[k * channel_multiplier + q]
      *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT32}
@@ -375,6 +385,8 @@
      *      [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.
      */
     DEPTHWISE_CONV_2D = 4,
 
@@ -409,6 +421,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.
      */
     DEPTH_TO_SPACE = 5,
 
@@ -430,6 +444,8 @@
      * Outputs:
      * * 0: The output tensor of same shape as input0, but with
      *      {@link OperandType::TENSOR_FLOAT32}.
+     *
+     * Available since API level 27.
      */
     DEQUANTIZE = 6,
 
@@ -463,6 +479,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.
      */
     EMBEDDING_LOOKUP = 7,
 
@@ -480,6 +498,8 @@
      * Outputs:
      * * 0: The output tensor, of the same {@link OperandType} and dimensions as
      *      the input tensor.
+     *
+     * Available since API level 27.
      */
     FLOOR = 8,
 
@@ -523,6 +543,8 @@
      *      tensor of {@link OperandType::TENSOR_QUANT8_ASYMM}, the following
      *      condition must be satisfied:
      *      output_scale > input_scale * filter_scale.
+     *
+     * Available since API level 27.
      */
     FULLY_CONNECTED = 9,
 
@@ -571,6 +593,8 @@
      *      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,
 
@@ -596,8 +620,10 @@
      * * 0: A 4-D tensor, of shape [batches, height, width, depth].
      *
      * Outputs:
-     * * 0: The output 4-D tensor, of shape
-     *      [batches, out_height, out_width, depth].
+     * * 0: The output 4-D tensor, of the same shape as input
+     *      [batches, height, width, depth].
+     *
+     * Available since API level 27.
      */
     L2_NORMALIZATION = 11,
 
@@ -609,8 +635,8 @@
      *
      * The values in the output tensor are computed as:
      *
-     *     output[batch, row, col, channel] =
-     *         sqrt(sum_{i, j} pow(input[batch, row + i, col + j, channel], 2) /
+     *     output[b, i, j, c] =
+     *         sqrt(sum_{di, dj} pow(input[b, strides[1] * i + di, strides[2] * j + dj, c], 2) /
      *              sum(1))
      *
      * Supported tensor {@link OperandType}:
@@ -664,6 +690,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, out_height, out_width, depth].
+     *
+     * Available since API level 27.
      */
     L2_POOL_2D = 12,
 
@@ -700,6 +728,8 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
+     *
+     * Available since API level 27.
      */
     LOCAL_RESPONSE_NORMALIZATION = 13,
 
@@ -723,6 +753,8 @@
      * * 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,
 
@@ -758,6 +790,8 @@
      *      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.
      */
     LSH_PROJECTION = 15,
 
@@ -952,6 +986,8 @@
      *      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.
      */
     LSTM = 16,
 
@@ -963,8 +999,10 @@
      *
      * The values in the output tensor are computed as:
      *
-     *     output[batch, row, col, channel] =
-     *         max_{i, j} (input[batch, row + i, col + j, channel])
+     *     output[b, i, j, channel] =
+     *         max_{di, dj} (
+     *             input[b, strides[1] * i + di, strides[2] * j + dj, channel]
+     *         )
      *
      * Supported tensor {@link OperandType}:
      * * {@link OperandType::TENSOR_FLOAT32}
@@ -1018,6 +1056,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, out_height, out_width, depth].
+     *
+     * Available since API level 27.
      */
     MAX_POOL_2D = 17,
 
@@ -1055,6 +1095,8 @@
      *      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,
 
@@ -1076,6 +1118,8 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
+     *
+     * Available since API level 27.
      */
     RELU = 19,
 
@@ -1097,6 +1141,8 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
+     *
+     * Available since API level 27.
      */
     RELU1 = 20,
 
@@ -1118,6 +1164,8 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
+     *
+     * Available since API level 27.
      */
     RELU6 = 21,
 
@@ -1141,6 +1189,8 @@
      *
      * Outputs:
      * * 0: The output tensor, of shape specified by the input shape.
+     *
+     * Available since API level 27.
      */
     RESHAPE = 22,
 
@@ -1167,6 +1217,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape
      *      [batches, new_height, new_width, depth].
+     *
+     * Available since API level 27.
      */
     RESIZE_BILINEAR = 23,
 
@@ -1222,6 +1274,8 @@
      *      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.
      */
     RNN = 24,
 
@@ -1251,6 +1305,8 @@
      * * 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,
 
@@ -1282,8 +1338,10 @@
      *      input height and width.
      *
      * Outputs:
-     * * 0: The output 4-D tensor, of shape [batch, height/block_size,
-     *      width/block_size, depth*block_size*block_size].
+     * * 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.
      */
     SPACE_TO_DEPTH = 26,
 
@@ -1361,7 +1419,9 @@
      *      [batch_size, (memory_size - 1) * num_units * rank].
      * * 1: output.
      *      A 2-D tensor of {@link OperandType::TENSOR_FLOAT32}, of shape
-         *      [batch_size, num_units].
+     *      [batch_size, num_units].
+     *
+     * Available since API level 27.
      */
     SVDF = 27,
 
@@ -1382,6 +1442,8 @@
      *
      * Outputs:
      * * 0: The output tensor of same shape as input0.
+     *
+     * Available since API level 27.
      */
     TANH = 28,
 
@@ -1410,28 +1472,36 @@
 enum OperandLifeTime : int32_t {
     /**
      * The operand is internal to the model. It's created by an operation and
-     * consumed by other operations.
+     * consumed by other operations. It must be an output operand of
+     * exactly one operation.
      */
     TEMPORARY_VARIABLE,
 
     /**
-     * The operand is an input of the model. An operand can't be both
-     * input and output of a model.
+     * 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.
+     * 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.
+     * 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.
+     * The operand is a constant that was specified via a Memory
+     * object. It must not be an output operand of any operation.
      */
     CONSTANT_REFERENCE,
 
@@ -1641,19 +1711,21 @@
     /**
      * All operations included in the model.
      *
-     * The operations are sorted into execution order.
+     * 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.
+     * 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.
+     * Output indexes of the model. There must be at least one.
      *
      * Each value corresponds to the index of the operand in "operands".
      */
@@ -1668,8 +1740,7 @@
     vec<uint8_t> operandValues;
 
     /**
-     * A collection of shared memory pools containing operand data that were
-     * registered by the model.
+     * 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.
@@ -1721,6 +1792,9 @@
  * 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 {
     /**
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index e28113b..18f35c1 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -25,6 +25,7 @@
     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",
         "libhidlmemory",
@@ -49,8 +50,9 @@
     ],
     defaults: ["VtsHalTargetTestDefaults"],
     static_libs: [
-        "android.hardware.neuralnetworks@1.1",
         "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",
         "libhidlmemory",
diff --git a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
index 64495cf..b8046c7 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -275,6 +275,58 @@
     EvaluatePreparedModel(preparedModel, is_ignored, examples, fpAtol, fpRtol);
 }
 
+// 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<MixedTypedExampleType>& examples) {
+    V1_2::Model model = create_model();
+
+    // 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());
+
+    // 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, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+    ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
+
+    // retrieve prepared model
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+
+    // 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: Adjust the error limit based on testing.
+    // If in relaxed mode, set the absolute tolerance to be 5ULP of FP16.
+    float fpAtol = !model.relaxComputationFloat32toFloat16 ? 1e-5f : 5.0f * 0.0009765625f;
+    // Set the relative tolerance to be 5ULP of the corresponding FP precision.
+    float fpRtol = !model.relaxComputationFloat32toFloat16 ? 5.0f * 1.1920928955078125e-7f
+                                                           : 5.0f * 0.0009765625f;
+    EvaluatePreparedModel(preparedModel, is_ignored, examples, fpAtol, fpRtol);
+}
+
 }  // namespace generated_tests
 
 }  // namespace neuralnetworks
diff --git a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
index 4f0697e..b813c39 100644
--- a/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.0/vts/functional/ValidateModel.cpp
@@ -283,7 +283,7 @@
         if (mutateOperationOperandTypeSkip(operand, model)) {
             continue;
         }
-        for (OperandType invalidOperandType : hidl_enum_iterator<OperandType>{}) {
+        for (OperandType invalidOperandType : hidl_enum_range<OperandType>{}) {
             // Do not test OEM types
             if (invalidOperandType == model.operands[operand].type ||
                 invalidOperandType == OperandType::OEM ||
diff --git a/neuralnetworks/1.1/types.hal b/neuralnetworks/1.1/types.hal
index e4c656d..c9de76b 100644
--- a/neuralnetworks/1.1/types.hal
+++ b/neuralnetworks/1.1/types.hal
@@ -26,6 +26,7 @@
  * The type of an operation in a model.
  */
 enum OperationType : @1.0::OperationType {
+
     /**
      * BatchToSpace for N-dimensional tensors.
      *
@@ -50,6 +51,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *
+     * Available since API level 28.
      */
     BATCH_TO_SPACE_ND = 29,
 
@@ -88,6 +91,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *
+     * Available since API level 28.
      */
     DIV = 30,
 
@@ -118,6 +123,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *
+     * Available since API level 28.
      */
     MEAN = 31,
 
@@ -137,13 +144,21 @@
      * * 1: A 2-D Tensor of {@link OperandType::TENSOR_INT32}, the paddings
      *      for each spatial dimension of the input tensor. The shape of the
      *      tensor must be {rank(input0), 2}.
-     *      padding[i, 0] specifies the number of element to be padded in the
+     *      padding[i, 0] specifies the number of elements to be padded in the
      *      front of dimension i.
-     *      padding[i, 1] specifies the number of element to be padded after the
+     *      padding[i, 1] specifies the number of elements to be padded after the
      *      end of dimension i.
      *
      * Outputs:
-     * * 0: A tensor of the same {@link OperandType} as input0.
+     * * 0: A tensor of the same {@link OperandType} as input0. The
+     *      output tensor has the same rank as input0, and each
+     *      dimension of the output tensor has the same size as the
+     *      corresponding dimension of the input tensor plus the size
+     *      of the padding:
+     *          output0.dimension[i] =
+     *              padding[i, 0] + input0.dimension[i] + padding[i, 1]
+     *
+     * Available since API level 28.
      */
     PAD = 32,
 
@@ -179,6 +194,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *
+     * Available since API level 28.
      */
     SPACE_TO_BATCH_ND = 33,
 
@@ -208,6 +225,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.
      */
     SQUEEZE = 34,
 
@@ -228,28 +247,32 @@
      *
      * Inputs:
      * * 0: An n-D tensor, specifying the tensor to be sliced.
-     * * 1: A 1-D Tensor of {@link OperandType::TENSOR_INT32}, the starts of
-     *      the dimensions of the input tensor to be sliced. The length must be
-     *      of rank(input0).
-     * * 2: A 1-D Tensor of {@link OperandType::TENSOR_INT32}, the ends of
-     *      the dimensions of the input tensor to be sliced. The length must be
-     *      of rank(input0).
-     * * 3: A 1-D Tensor of {@link OperandType::TENSOR_INT32}, the strides of
-     *      the dimensions of the input tensor to be sliced. The length must be
-     *      of rank(input0).
-     * * 4: An {@link OperandType::INT32} scalar, begin_mask. If the ith bit
+     * * 1: begin, a 1-D tensor of {@link OperandType::TENSOR_INT32}. The
+     *      starts of the dimensions of the input tensor to be sliced. The
+     *      length must be of rank(input0).
+     * * 2: end, a 1-D tensor of {@link OperandType::TENSOR_INT32}. The
+     *      ends of the dimensions of the input tensor to be sliced. The length
+     *      must be of rank(input0).
+     * * 3: strides, a 1-D tensor of {@link OperandType::TENSOR_INT32}. The
+     *      strides of the dimensions of the input tensor to be sliced. The
+     *      length must be of rank(input0). The entries must be non-zero.
+     * * 4: begin_mask, an {@link OperandType::INT32} scalar. If the ith bit
      *      of begin_mask is set, begin[i] is ignored and the fullest possible
      *      range in that dimension is used instead.
-     * * 5: An {@link OperandType::INT32} scalar, end_mask. If the ith bit of
+     * * 5: end_mask, an {@link OperandType::INT32} scalar. If the ith bit of
      *      end_mask is set, end[i] is ignored and the fullest possible range in
      *      that dimension is used instead.
-     * * 6: An {@link OperandType::INT32} scalar, shrink_axis_mask. An int32
-     *      mask. If the ith bit of shrink_axis_mask is set, it implies that the
-     *      ith specification shrinks the dimensionality by 1. A slice of size 1
-     *      starting from begin[i] in the dimension must be preserved.
+     * * 6: shrink_axis_mask, an {@link OperandType::INT32} scalar. If the
+     *      ith bit of shrink_axis_mask is set, the ith dimension specification
+     *      shrinks the dimensionality by 1, taking on the value at index
+     *      begin[i]. In this case, the ith specification must define a
+     *      slice of size 1, e.g. begin[i] = x, end[i] = x + 1.
      *
      * Outputs:
-     * * 0: A tensor of the same {@link OperandType} as input0.
+     * * 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.
      */
     STRIDED_SLICE = 35,
 
@@ -288,6 +311,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *
+     * Available since API level 28.
      */
     SUB = 36,
 
@@ -313,8 +338,11 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *
+     * Available since API level 28.
      */
     TRANSPOSE = 37,
+
 };
 
 /**
@@ -377,19 +405,21 @@
     /**
      * All operations included in the model.
      *
-     * The operations are sorted into execution order.
+     * 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.
+     * 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.
+     * Output indexes of the model. There must be at least one.
      *
      * Each value corresponds to the index of the operand in "operands".
      */
@@ -404,8 +434,7 @@
     vec<uint8_t> operandValues;
 
     /**
-     * A collection of shared memory pools containing operand data that were
-     * registered by the model.
+     * 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.
diff --git a/neuralnetworks/1.1/vts/functional/Android.bp b/neuralnetworks/1.1/vts/functional/Android.bp
index f755c20..52a804a 100644
--- a/neuralnetworks/1.1/vts/functional/Android.bp
+++ b/neuralnetworks/1.1/vts/functional/Android.bp
@@ -28,6 +28,7 @@
     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",
         "libhidlmemory",
diff --git a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
index 3aa55f8..d6c6533 100644
--- a/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.1/vts/functional/ValidateModel.cpp
@@ -299,7 +299,7 @@
         if (mutateOperationOperandTypeSkip(operand, model)) {
             continue;
         }
-        for (OperandType invalidOperandType : hidl_enum_iterator<OperandType>{}) {
+        for (OperandType invalidOperandType : hidl_enum_range<OperandType>{}) {
             // Do not test OEM types
             if (invalidOperandType == model.operands[operand].type ||
                 invalidOperandType == OperandType::OEM ||
diff --git a/neuralnetworks/1.2/Android.bp b/neuralnetworks/1.2/Android.bp
new file mode 100644
index 0000000..e183a26
--- /dev/null
+++ b/neuralnetworks/1.2/Android.bp
@@ -0,0 +1,24 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.neuralnetworks@1.2",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IDevice.hal",
+    ],
+    interfaces: [
+        "android.hardware.neuralnetworks@1.0",
+        "android.hardware.neuralnetworks@1.1",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "Model",
+        "Operation",
+        "OperationType",
+    ],
+    gen_java: false,
+}
diff --git a/neuralnetworks/1.2/IDevice.hal b/neuralnetworks/1.2/IDevice.hal
new file mode 100644
index 0000000..9cc23a2
--- /dev/null
+++ b/neuralnetworks/1.2/IDevice.hal
@@ -0,0 +1,106 @@
+/*
+ * 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::ErrorStatus;
+import @1.0::IPreparedModelCallback;
+import @1.1::ExecutionPreference;
+import @1.1::IDevice;
+
+/**
+ * This interface represents a device driver.
+ */
+interface IDevice extends @1.1::IDevice {
+    /**
+     * Gets the supported operations in a model.
+     *
+     * getSupportedOperations indicates which operations of a model are fully
+     * supported by the vendor driver. If an operation may not be supported for
+     * any reason, getSupportedOperations must return false for that operation.
+     *
+     * @param model A model whose operations--and their corresponding operands--
+     *     are to be verified by the driver.
+     * @return status Error status of the call, must be:
+     *     - NONE if successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - INVALID_ARGUMENT if provided model is invalid
+     * @return supportedOperations A list of supported operations, where true
+     *     indicates the operation is supported and false indicates the
+     *     operation is not supported. The index of "supported" corresponds with
+     *     the index of the operation it is describing.
+     */
+    getSupportedOperations_1_2(Model model)
+            generates (ErrorStatus status, vec<bool> supportedOperations);
+
+    /**
+     * Creates a prepared model for execution.
+     *
+     * prepareModel is used to make any necessary transformations or alternative
+     * representations to a model for execution, possibly including
+     * transformations on the constant data, optimization on the model's graph,
+     * or compilation into the device's native binary format. The model itself
+     * is not changed.
+     *
+     * The model is prepared asynchronously with respect to the caller. The
+     * prepareModel function must verify the inputs to the prepareModel function
+     * are correct. If there is an error, prepareModel must immediately invoke
+     * the callback with the appropriate ErrorStatus value and nullptr for the
+     * IPreparedModel, then return with the same ErrorStatus. If the inputs to
+     * the prepareModel function are valid and there is no error, prepareModel
+     * must launch an asynchronous task to prepare the model in the background,
+     * and immediately return from prepareModel with ErrorStatus::NONE. If the
+     * asynchronous task fails to launch, prepareModel must immediately invoke
+     * the callback with ErrorStatus::GENERAL_FAILURE and nullptr for the
+     * IPreparedModel, then return with ErrorStatus::GENERAL_FAILURE.
+     *
+     * When the asynchronous task has finished preparing the model, it must
+     * immediately invoke the callback function provided as an input to
+     * prepareModel. If the model was prepared successfully, the callback object
+     * must be invoked with an error status of ErrorStatus::NONE and the
+     * produced IPreparedModel object. If an error occurred preparing the model,
+     * the callback object must be invoked with the appropriate ErrorStatus
+     * value and nullptr for the IPreparedModel.
+     *
+     * The only information that may be unknown to the model at this stage is
+     * the shape of the tensors, which may only be known at execution time. As
+     * such, some driver services may return partially prepared models, where
+     * the prepared model may only be finished when it is paired with a set of
+     * inputs to the model. Note that the same prepared model object may be
+     * used with different shapes of inputs on different (possibly concurrent)
+     * executions.
+     *
+     * Multiple threads may call prepareModel on the same model concurrently.
+     *
+     * @param model The model to be prepared for execution.
+     * @param preference Indicates the intended execution behavior of a prepared
+     *     model.
+     * @param callback A callback object used to return the error status of
+     *     preparing the model for execution and the prepared model if
+     *     successful, nullptr otherwise. The callback object's notify function
+     *     must be called exactly once, even if the model could not be prepared.
+     * @return status Error status of launching a task which prepares the model
+     *     in the background; must be:
+     *     - NONE if preparation task is successfully launched
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if there is an unspecified error
+     *     - INVALID_ARGUMENT if one of the input arguments is invalid
+     */
+    prepareModel_1_2(Model model, ExecutionPreference preference,
+                     IPreparedModelCallback callback)
+          generates (ErrorStatus status);
+};
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
new file mode 100644
index 0000000..61970f0
--- /dev/null
+++ b/neuralnetworks/1.2/types.hal
@@ -0,0 +1,113 @@
+/*
+ * 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::Operand;
+import @1.0::PerformanceInfo;
+import @1.1::OperationType;
+
+/**
+ * Operation types.
+ *
+ * The type of an operation in a model.
+ */
+enum OperationType : @1.1::OperationType {
+
+};
+
+/**
+ * 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;
+};
diff --git a/neuralnetworks/1.2/vts/OWNERS b/neuralnetworks/1.2/vts/OWNERS
new file mode 100644
index 0000000..8f25436
--- /dev/null
+++ b/neuralnetworks/1.2/vts/OWNERS
@@ -0,0 +1,14 @@
+# Neuralnetworks team
+butlermichael@google.com
+dgross@google.com
+jeanluc@google.com
+levp@google.com
+miaowang@google.com
+mikie@google.com
+mks@google.com
+pszczepaniak@google.com
+slavash@google.com
+
+# VTS team
+yim@google.com
+yuexima@google.com
diff --git a/neuralnetworks/1.2/vts/functional/Android.bp b/neuralnetworks/1.2/vts/functional/Android.bp
new file mode 100644
index 0000000..2dc19cc
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/Android.bp
@@ -0,0 +1,52 @@
+//
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+cc_test {
+    name: "VtsHalNeuralnetworksV1_2TargetTest",
+    srcs: [
+        "BasicTests.cpp",
+        "GeneratedTests.cpp",
+        "ValidateModel.cpp",
+        "ValidateRequest.cpp",
+        "ValidationTests.cpp",
+        "VtsHalNeuralnetworks.cpp",
+    ],
+    defaults: ["VtsHalTargetTestDefaults"],
+    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",
+        "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,
+            },
+        },
+    },
+}
diff --git a/neuralnetworks/1.2/vts/functional/BasicTests.cpp b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
new file mode 100644
index 0000000..d2dea1d
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
@@ -0,0 +1,45 @@
+/*
+ * 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"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_2 {
+namespace vts {
+namespace functional {
+
+using V1_1::Capabilities;
+
+// create device test
+TEST_F(NeuralnetworksHidlTest, CreateDevice) {}
+
+// status test
+TEST_F(NeuralnetworksHidlTest, StatusTest) {
+    Return<DeviceStatus> status = device->getStatus();
+    ASSERT_TRUE(status.isOk());
+    EXPECT_EQ(DeviceStatus::AVAILABLE, static_cast<DeviceStatus>(status));
+}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_2
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp b/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
new file mode 100644
index 0000000..662c531
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/GeneratedTests.cpp
@@ -0,0 +1,60 @@
+/*
+ * 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 "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 generated_tests {
+using ::test_helper::MixedTypedExampleType;
+extern void Execute(const sp<V1_2::IDevice>&, std::function<V1_2::Model(void)>,
+                    std::function<bool(int)>, const std::vector<MixedTypedExampleType>&);
+}  // namespace generated_tests
+
+namespace V1_2 {
+namespace vts {
+namespace functional {
+
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::nn::allocateSharedMemory;
+
+// Mixed-typed examples
+typedef generated_tests::MixedTypedExampleType MixedTypedExample;
+
+// in frameworks/ml/nn/runtime/tests/generated/
+#include "all_generated_V1_0_vts_tests.cpp"
+#include "all_generated_V1_1_vts_tests.cpp"
+#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/Models.h b/neuralnetworks/1.2/vts/functional/Models.h
new file mode 100644
index 0000000..f3769bc
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/Models.h
@@ -0,0 +1,378 @@
+/*
+ * 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 VTS_HAL_NEURALNETWORKS_V1_2_VTS_FUNCTIONAL_MODELS_H
+#define VTS_HAL_NEURALNETWORKS_V1_2_VTS_FUNCTIONAL_MODELS_H
+
+#define LOG_TAG "neuralnetworks_hidl_hal_test"
+
+#include "TestHarness.h"
+
+#include <android/hardware/neuralnetworks/1.0/types.h>
+#include <android/hardware/neuralnetworks/1.1/types.h>
+#include <android/hardware/neuralnetworks/1.2/types.h>
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_2 {
+namespace vts {
+namespace functional {
+
+using MixedTypedExample = test_helper::MixedTypedExampleType;
+
+#define FOR_EACH_TEST_MODEL(FN)                                  \
+    FN(add)                                                      \
+    FN(add_broadcast_quant8)                                     \
+    FN(add_quant8)                                               \
+    FN(add_relaxed)                                              \
+    FN(avg_pool_float_1)                                         \
+    FN(avg_pool_float_1_relaxed)                                 \
+    FN(avg_pool_float_2)                                         \
+    FN(avg_pool_float_2_relaxed)                                 \
+    FN(avg_pool_float_3)                                         \
+    FN(avg_pool_float_3_relaxed)                                 \
+    FN(avg_pool_float_4)                                         \
+    FN(avg_pool_float_4_relaxed)                                 \
+    FN(avg_pool_float_5)                                         \
+    FN(avg_pool_float_5_relaxed)                                 \
+    FN(avg_pool_quant8_1)                                        \
+    FN(avg_pool_quant8_2)                                        \
+    FN(avg_pool_quant8_3)                                        \
+    FN(avg_pool_quant8_4)                                        \
+    FN(avg_pool_quant8_5)                                        \
+    FN(batch_to_space)                                           \
+    FN(batch_to_space_float_1)                                   \
+    FN(batch_to_space_float_1_relaxed)                           \
+    FN(batch_to_space_quant8_1)                                  \
+    FN(batch_to_space_relaxed)                                   \
+    FN(concat_float_1)                                           \
+    FN(concat_float_1_relaxed)                                   \
+    FN(concat_float_2)                                           \
+    FN(concat_float_2_relaxed)                                   \
+    FN(concat_float_3)                                           \
+    FN(concat_float_3_relaxed)                                   \
+    FN(concat_quant8_1)                                          \
+    FN(concat_quant8_2)                                          \
+    FN(concat_quant8_3)                                          \
+    FN(conv_1_h3_w2_SAME)                                        \
+    FN(conv_1_h3_w2_SAME_relaxed)                                \
+    FN(conv_1_h3_w2_VALID)                                       \
+    FN(conv_1_h3_w2_VALID_relaxed)                               \
+    FN(conv_3_h3_w2_SAME)                                        \
+    FN(conv_3_h3_w2_SAME_relaxed)                                \
+    FN(conv_3_h3_w2_VALID)                                       \
+    FN(conv_3_h3_w2_VALID_relaxed)                               \
+    FN(conv_float)                                               \
+    FN(conv_float_2)                                             \
+    FN(conv_float_2_relaxed)                                     \
+    FN(conv_float_channels)                                      \
+    FN(conv_float_channels_relaxed)                              \
+    FN(conv_float_channels_weights_as_inputs)                    \
+    FN(conv_float_channels_weights_as_inputs_relaxed)            \
+    FN(conv_float_large)                                         \
+    FN(conv_float_large_relaxed)                                 \
+    FN(conv_float_large_weights_as_inputs)                       \
+    FN(conv_float_large_weights_as_inputs_relaxed)               \
+    FN(conv_float_relaxed)                                       \
+    FN(conv_float_weights_as_inputs)                             \
+    FN(conv_float_weights_as_inputs_relaxed)                     \
+    FN(conv_quant8)                                              \
+    FN(conv_quant8_2)                                            \
+    FN(conv_quant8_channels)                                     \
+    FN(conv_quant8_channels_weights_as_inputs)                   \
+    FN(conv_quant8_large)                                        \
+    FN(conv_quant8_large_weights_as_inputs)                      \
+    FN(conv_quant8_overflow)                                     \
+    FN(conv_quant8_overflow_weights_as_inputs)                   \
+    FN(conv_quant8_weights_as_inputs)                            \
+    FN(depth_to_space_float_1)                                   \
+    FN(depth_to_space_float_1_relaxed)                           \
+    FN(depth_to_space_float_2)                                   \
+    FN(depth_to_space_float_2_relaxed)                           \
+    FN(depth_to_space_float_3)                                   \
+    FN(depth_to_space_float_3_relaxed)                           \
+    FN(depth_to_space_quant8_1)                                  \
+    FN(depth_to_space_quant8_2)                                  \
+    FN(depthwise_conv)                                           \
+    FN(depthwise_conv2d_float)                                   \
+    FN(depthwise_conv2d_float_2)                                 \
+    FN(depthwise_conv2d_float_2_relaxed)                         \
+    FN(depthwise_conv2d_float_large)                             \
+    FN(depthwise_conv2d_float_large_2)                           \
+    FN(depthwise_conv2d_float_large_2_relaxed)                   \
+    FN(depthwise_conv2d_float_large_2_weights_as_inputs)         \
+    FN(depthwise_conv2d_float_large_2_weights_as_inputs_relaxed) \
+    FN(depthwise_conv2d_float_large_relaxed)                     \
+    FN(depthwise_conv2d_float_large_weights_as_inputs)           \
+    FN(depthwise_conv2d_float_large_weights_as_inputs_relaxed)   \
+    FN(depthwise_conv2d_float_relaxed)                           \
+    FN(depthwise_conv2d_float_weights_as_inputs)                 \
+    FN(depthwise_conv2d_float_weights_as_inputs_relaxed)         \
+    FN(depthwise_conv2d_quant8)                                  \
+    FN(depthwise_conv2d_quant8_2)                                \
+    FN(depthwise_conv2d_quant8_large)                            \
+    FN(depthwise_conv2d_quant8_large_weights_as_inputs)          \
+    FN(depthwise_conv2d_quant8_weights_as_inputs)                \
+    FN(depthwise_conv_relaxed)                                   \
+    FN(dequantize)                                               \
+    FN(dequantize_relaxed)                                       \
+    FN(div)                                                      \
+    FN(div_broadcast_float)                                      \
+    FN(div_broadcast_float_relaxed)                              \
+    FN(div_relaxed)                                              \
+    FN(embedding_lookup)                                         \
+    FN(embedding_lookup_relaxed)                                 \
+    FN(floor)                                                    \
+    FN(floor_relaxed)                                            \
+    FN(fully_connected_float)                                    \
+    FN(fully_connected_float_2)                                  \
+    FN(fully_connected_float_2_relaxed)                          \
+    FN(fully_connected_float_4d_simple)                          \
+    FN(fully_connected_float_4d_simple_relaxed)                  \
+    FN(fully_connected_float_large)                              \
+    FN(fully_connected_float_large_relaxed)                      \
+    FN(fully_connected_float_large_weights_as_inputs)            \
+    FN(fully_connected_float_large_weights_as_inputs_relaxed)    \
+    FN(fully_connected_float_relaxed)                            \
+    FN(fully_connected_float_weights_as_inputs)                  \
+    FN(fully_connected_float_weights_as_inputs_relaxed)          \
+    FN(fully_connected_quant8)                                   \
+    FN(fully_connected_quant8_2)                                 \
+    FN(fully_connected_quant8_large)                             \
+    FN(fully_connected_quant8_large_weights_as_inputs)           \
+    FN(fully_connected_quant8_weights_as_inputs)                 \
+    FN(hashtable_lookup_float)                                   \
+    FN(hashtable_lookup_float_relaxed)                           \
+    FN(hashtable_lookup_quant8)                                  \
+    FN(l2_normalization)                                         \
+    FN(l2_normalization_2)                                       \
+    FN(l2_normalization_2_relaxed)                               \
+    FN(l2_normalization_large)                                   \
+    FN(l2_normalization_large_relaxed)                           \
+    FN(l2_normalization_relaxed)                                 \
+    FN(l2_pool_float)                                            \
+    FN(l2_pool_float_2)                                          \
+    FN(l2_pool_float_2_relaxed)                                  \
+    FN(l2_pool_float_large)                                      \
+    FN(l2_pool_float_large_relaxed)                              \
+    FN(l2_pool_float_relaxed)                                    \
+    FN(local_response_norm_float_1)                              \
+    FN(local_response_norm_float_1_relaxed)                      \
+    FN(local_response_norm_float_2)                              \
+    FN(local_response_norm_float_2_relaxed)                      \
+    FN(local_response_norm_float_3)                              \
+    FN(local_response_norm_float_3_relaxed)                      \
+    FN(local_response_norm_float_4)                              \
+    FN(local_response_norm_float_4_relaxed)                      \
+    FN(logistic_float_1)                                         \
+    FN(logistic_float_1_relaxed)                                 \
+    FN(logistic_float_2)                                         \
+    FN(logistic_float_2_relaxed)                                 \
+    FN(logistic_quant8_1)                                        \
+    FN(logistic_quant8_2)                                        \
+    FN(lsh_projection)                                           \
+    FN(lsh_projection_2)                                         \
+    FN(lsh_projection_2_relaxed)                                 \
+    FN(lsh_projection_relaxed)                                   \
+    FN(lsh_projection_weights_as_inputs)                         \
+    FN(lsh_projection_weights_as_inputs_relaxed)                 \
+    FN(lstm)                                                     \
+    FN(lstm2)                                                    \
+    FN(lstm2_relaxed)                                            \
+    FN(lstm2_state)                                              \
+    FN(lstm2_state2)                                             \
+    FN(lstm2_state2_relaxed)                                     \
+    FN(lstm2_state_relaxed)                                      \
+    FN(lstm3)                                                    \
+    FN(lstm3_relaxed)                                            \
+    FN(lstm3_state)                                              \
+    FN(lstm3_state2)                                             \
+    FN(lstm3_state2_relaxed)                                     \
+    FN(lstm3_state3)                                             \
+    FN(lstm3_state3_relaxed)                                     \
+    FN(lstm3_state_relaxed)                                      \
+    FN(lstm_relaxed)                                             \
+    FN(lstm_state)                                               \
+    FN(lstm_state2)                                              \
+    FN(lstm_state2_relaxed)                                      \
+    FN(lstm_state_relaxed)                                       \
+    FN(max_pool_float_1)                                         \
+    FN(max_pool_float_1_relaxed)                                 \
+    FN(max_pool_float_2)                                         \
+    FN(max_pool_float_2_relaxed)                                 \
+    FN(max_pool_float_3)                                         \
+    FN(max_pool_float_3_relaxed)                                 \
+    FN(max_pool_float_4)                                         \
+    FN(max_pool_float_4_relaxed)                                 \
+    FN(max_pool_quant8_1)                                        \
+    FN(max_pool_quant8_2)                                        \
+    FN(max_pool_quant8_3)                                        \
+    FN(max_pool_quant8_4)                                        \
+    FN(mean)                                                     \
+    FN(mean_float_1)                                             \
+    FN(mean_float_1_relaxed)                                     \
+    FN(mean_float_2)                                             \
+    FN(mean_float_2_relaxed)                                     \
+    FN(mean_quant8_1)                                            \
+    FN(mean_quant8_2)                                            \
+    FN(mean_relaxed)                                             \
+    FN(mobilenet_224_gender_basic_fixed)                         \
+    FN(mobilenet_224_gender_basic_fixed_relaxed)                 \
+    FN(mobilenet_quantized)                                      \
+    FN(mul)                                                      \
+    FN(mul_broadcast_quant8)                                     \
+    FN(mul_quant8)                                               \
+    FN(mul_relaxed)                                              \
+    FN(mul_relu)                                                 \
+    FN(mul_relu_relaxed)                                         \
+    FN(pad)                                                      \
+    FN(pad_float_1)                                              \
+    FN(pad_float_1_relaxed)                                      \
+    FN(pad_relaxed)                                              \
+    FN(relu1_float_1)                                            \
+    FN(relu1_float_1_relaxed)                                    \
+    FN(relu1_float_2)                                            \
+    FN(relu1_float_2_relaxed)                                    \
+    FN(relu1_quant8_1)                                           \
+    FN(relu1_quant8_2)                                           \
+    FN(relu6_float_1)                                            \
+    FN(relu6_float_1_relaxed)                                    \
+    FN(relu6_float_2)                                            \
+    FN(relu6_float_2_relaxed)                                    \
+    FN(relu6_quant8_1)                                           \
+    FN(relu6_quant8_2)                                           \
+    FN(relu_float_1)                                             \
+    FN(relu_float_1_relaxed)                                     \
+    FN(relu_float_2)                                             \
+    FN(relu_float_2_relaxed)                                     \
+    FN(relu_quant8_1)                                            \
+    FN(relu_quant8_2)                                            \
+    FN(reshape)                                                  \
+    FN(reshape_quant8)                                           \
+    FN(reshape_quant8_weights_as_inputs)                         \
+    FN(reshape_relaxed)                                          \
+    FN(reshape_weights_as_inputs)                                \
+    FN(reshape_weights_as_inputs_relaxed)                        \
+    FN(resize_bilinear)                                          \
+    FN(resize_bilinear_2)                                        \
+    FN(resize_bilinear_2_relaxed)                                \
+    FN(resize_bilinear_relaxed)                                  \
+    FN(rnn)                                                      \
+    FN(rnn_relaxed)                                              \
+    FN(rnn_state)                                                \
+    FN(rnn_state_relaxed)                                        \
+    FN(softmax_float_1)                                          \
+    FN(softmax_float_1_relaxed)                                  \
+    FN(softmax_float_2)                                          \
+    FN(softmax_float_2_relaxed)                                  \
+    FN(softmax_quant8_1)                                         \
+    FN(softmax_quant8_2)                                         \
+    FN(space_to_batch)                                           \
+    FN(space_to_batch_float_1)                                   \
+    FN(space_to_batch_float_1_relaxed)                           \
+    FN(space_to_batch_float_2)                                   \
+    FN(space_to_batch_float_2_relaxed)                           \
+    FN(space_to_batch_float_3)                                   \
+    FN(space_to_batch_float_3_relaxed)                           \
+    FN(space_to_batch_quant8_1)                                  \
+    FN(space_to_batch_quant8_2)                                  \
+    FN(space_to_batch_quant8_3)                                  \
+    FN(space_to_batch_relaxed)                                   \
+    FN(space_to_depth_float_1)                                   \
+    FN(space_to_depth_float_1_relaxed)                           \
+    FN(space_to_depth_float_2)                                   \
+    FN(space_to_depth_float_2_relaxed)                           \
+    FN(space_to_depth_float_3)                                   \
+    FN(space_to_depth_float_3_relaxed)                           \
+    FN(space_to_depth_quant8_1)                                  \
+    FN(space_to_depth_quant8_2)                                  \
+    FN(squeeze)                                                  \
+    FN(squeeze_float_1)                                          \
+    FN(squeeze_float_1_relaxed)                                  \
+    FN(squeeze_quant8_1)                                         \
+    FN(squeeze_relaxed)                                          \
+    FN(strided_slice)                                            \
+    FN(strided_slice_float_1)                                    \
+    FN(strided_slice_float_10)                                   \
+    FN(strided_slice_float_10_relaxed)                           \
+    FN(strided_slice_float_11)                                   \
+    FN(strided_slice_float_11_relaxed)                           \
+    FN(strided_slice_float_1_relaxed)                            \
+    FN(strided_slice_float_2)                                    \
+    FN(strided_slice_float_2_relaxed)                            \
+    FN(strided_slice_float_3)                                    \
+    FN(strided_slice_float_3_relaxed)                            \
+    FN(strided_slice_float_4)                                    \
+    FN(strided_slice_float_4_relaxed)                            \
+    FN(strided_slice_float_5)                                    \
+    FN(strided_slice_float_5_relaxed)                            \
+    FN(strided_slice_float_6)                                    \
+    FN(strided_slice_float_6_relaxed)                            \
+    FN(strided_slice_float_7)                                    \
+    FN(strided_slice_float_7_relaxed)                            \
+    FN(strided_slice_float_8)                                    \
+    FN(strided_slice_float_8_relaxed)                            \
+    FN(strided_slice_float_9)                                    \
+    FN(strided_slice_float_9_relaxed)                            \
+    FN(strided_slice_qaunt8_10)                                  \
+    FN(strided_slice_qaunt8_11)                                  \
+    FN(strided_slice_quant8_1)                                   \
+    FN(strided_slice_quant8_2)                                   \
+    FN(strided_slice_quant8_3)                                   \
+    FN(strided_slice_quant8_4)                                   \
+    FN(strided_slice_quant8_5)                                   \
+    FN(strided_slice_quant8_6)                                   \
+    FN(strided_slice_quant8_7)                                   \
+    FN(strided_slice_quant8_8)                                   \
+    FN(strided_slice_quant8_9)                                   \
+    FN(strided_slice_relaxed)                                    \
+    FN(sub)                                                      \
+    FN(sub_broadcast_float)                                      \
+    FN(sub_broadcast_float_relaxed)                              \
+    FN(sub_relaxed)                                              \
+    FN(svdf)                                                     \
+    FN(svdf2)                                                    \
+    FN(svdf2_relaxed)                                            \
+    FN(svdf_relaxed)                                             \
+    FN(svdf_state)                                               \
+    FN(svdf_state_relaxed)                                       \
+    FN(tanh)                                                     \
+    FN(tanh_relaxed)                                             \
+    FN(transpose)                                                \
+    FN(transpose_float_1)                                        \
+    FN(transpose_float_1_relaxed)                                \
+    FN(transpose_quant8_1)                                       \
+    FN(transpose_relaxed)
+
+#define FORWARD_DECLARE_GENERATED_OBJECTS(function) \
+    namespace function {                            \
+    extern std::vector<MixedTypedExample> examples; \
+    Model createTestModel();                        \
+    }
+
+FOR_EACH_TEST_MODEL(FORWARD_DECLARE_GENERATED_OBJECTS)
+
+#undef FORWARD_DECLARE_GENERATED_OBJECTS
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_2
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
+
+#endif  // VTS_HAL_NEURALNETWORKS_V1_2_VTS_FUNCTIONAL_MODELS_H
diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
new file mode 100644
index 0000000..7ec6ff1
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -0,0 +1,538 @@
+/*
+ * 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"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_2 {
+
+using V1_0::IPreparedModel;
+using V1_0::Operand;
+using V1_0::OperandLifeTime;
+using V1_0::OperandType;
+using V1_1::ExecutionPreference;
+
+namespace vts {
+namespace functional {
+
+using ::android::hardware::neuralnetworks::V1_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+
+///////////////////////// UTILITY FUNCTIONS /////////////////////////
+
+static void validateGetSupportedOperations(const sp<IDevice>& device, const std::string& message,
+                                           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);
+        });
+    EXPECT_TRUE(ret.isOk());
+}
+
+static void validatePrepareModel(const sp<IDevice>& device, const std::string& message,
+                                 const Model& model, ExecutionPreference preference) {
+    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, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, static_cast<ErrorStatus>(prepareLaunchStatus));
+
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    ASSERT_EQ(ErrorStatus::INVALID_ARGUMENT, prepareReturnStatus);
+    sp<IPreparedModel> preparedModel = preparedModelCallback->getPreparedModel();
+    ASSERT_EQ(nullptr, preparedModel.get());
+}
+
+static bool validExecutionPreference(ExecutionPreference preference) {
+    return preference == ExecutionPreference::LOW_POWER ||
+           preference == ExecutionPreference::FAST_SINGLE_ANSWER ||
+           preference == ExecutionPreference::SUSTAINED_SPEED;
+}
+
+// Primary validation function. This function will take a valid model, apply a
+// 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, Model model,
+                     const std::function<void(Model*)>& mutation,
+                     ExecutionPreference preference = ExecutionPreference::FAST_SINGLE_ANSWER) {
+    mutation(&model);
+    if (validExecutionPreference(preference)) {
+        validateGetSupportedOperations(device, message, model);
+    }
+    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},
+                              });
+}
+
+static uint32_t addOperand(Model* model, OperandLifeTime lifetime) {
+    uint32_t index = addOperand(model);
+    model->operands[index].numberOfConsumers = 1;
+    model->operands[index].lifetime = lifetime;
+    return index;
+}
+
+///////////////////////// 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 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 " +
+                                        std::to_string(operand) + " set to value " +
+                                        std::to_string(invalidOperandType);
+            validate(device, message, model, [operand, invalidOperandType](Model* model) {
+                model->operands[operand].type = static_cast<OperandType>(invalidOperandType);
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE OPERAND RANK /////////////////////////
+
+static uint32_t getInvalidRank(OperandType type) {
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+            return 1;
+        case OperandType::TENSOR_FLOAT32:
+        case OperandType::TENSOR_INT32:
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            return 0;
+        default:
+            return 0;
+    }
+}
+
+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) +
+                                    " has rank of " + std::to_string(invalidRank);
+        validate(device, message, model, [operand, invalidRank](Model* model) {
+            model->operands[operand].dimensions = std::vector<uint32_t>(invalidRank, 0);
+        });
+    }
+}
+
+///////////////////////// VALIDATE OPERAND SCALE /////////////////////////
+
+static float getInvalidScale(OperandType type) {
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+        case OperandType::TENSOR_FLOAT32:
+            return 1.0f;
+        case OperandType::TENSOR_INT32:
+            return -1.0f;
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            return 0.0f;
+        default:
+            return 0.0f;
+    }
+}
+
+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) +
+                                    " has scale of " + std::to_string(invalidScale);
+        validate(device, message, model, [operand, invalidScale](Model* model) {
+            model->operands[operand].scale = invalidScale;
+        });
+    }
+}
+
+///////////////////////// VALIDATE OPERAND ZERO POINT /////////////////////////
+
+static std::vector<int32_t> getInvalidZeroPoints(OperandType type) {
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+        case OperandType::TENSOR_FLOAT32:
+        case OperandType::TENSOR_INT32:
+            return {1};
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            return {-1, 256};
+        default:
+            return {};
+    }
+}
+
+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);
+        for (int32_t invalidZeroPoint : invalidZeroPoints) {
+            const std::string message = "mutateOperandZeroPointTest: operand " +
+                                        std::to_string(operand) + " has zero point of " +
+                                        std::to_string(invalidZeroPoint);
+            validate(device, message, model, [operand, invalidZeroPoint](Model* model) {
+                model->operands[operand].zeroPoint = invalidZeroPoint;
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE EXTRA ??? /////////////////////////
+
+// TODO: Operand::lifetime
+// TODO: Operand::location
+
+///////////////////////// VALIDATE OPERATION OPERAND TYPE /////////////////////////
+
+static void mutateOperand(Operand* operand, OperandType type) {
+    Operand newOperand = *operand;
+    newOperand.type = type;
+    switch (type) {
+        case OperandType::FLOAT32:
+        case OperandType::INT32:
+        case OperandType::UINT32:
+            newOperand.dimensions = hidl_vec<uint32_t>();
+            newOperand.scale = 0.0f;
+            newOperand.zeroPoint = 0;
+            break;
+        case OperandType::TENSOR_FLOAT32:
+            newOperand.dimensions =
+                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});
+            newOperand.zeroPoint = 0;
+            break;
+        case OperandType::TENSOR_QUANT8_ASYMM:
+            newOperand.dimensions =
+                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:
+        case OperandType::TENSOR_OEM_BYTE:
+        default:
+            break;
+    }
+    *operand = newOperand;
+}
+
+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
+    // result in a valid model for LSH_PROJECTION. If this is the case, skip the
+    // test.
+    for (const Operation& operation : model.operations) {
+        if (operation.type == OperationType::LSH_PROJECTION && operand == operation.inputs[1]) {
+            return true;
+        }
+    }
+    return false;
+}
+
+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;
+        }
+        for (OperandType invalidOperandType : hidl_enum_range<OperandType>{}) {
+            // Do not test OEM types
+            if (invalidOperandType == model.operands[operand].type ||
+                invalidOperandType == OperandType::OEM ||
+                invalidOperandType == OperandType::TENSOR_OEM_BYTE) {
+                continue;
+            }
+            const std::string message = "mutateOperationOperandTypeTest: operand " +
+                                        std::to_string(operand) + " set to type " +
+                                        toString(invalidOperandType);
+            validate(device, message, model, [operand, invalidOperandType](Model* model) {
+                mutateOperand(&model->operands[operand], invalidOperandType);
+            });
+        }
+    }
+}
+
+///////////////////////// 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 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 " +
+                                        std::to_string(operation) + " set to value " +
+                                        std::to_string(invalidOperationType);
+            validate(device, message, model, [operation, invalidOperationType](Model* model) {
+                model->operations[operation].type =
+                    static_cast<OperationType>(invalidOperationType);
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE MODEL OPERATION INPUT OPERAND INDEX /////////////////////////
+
+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) {
+            const std::string message = "mutateOperationInputOperandIndexTest: operation " +
+                                        std::to_string(operation) + " input " +
+                                        std::to_string(input);
+            validate(device, message, model, [operation, input, invalidOperand](Model* model) {
+                model->operations[operation].inputs[input] = invalidOperand;
+            });
+        }
+    }
+}
+
+///////////////////////// VALIDATE MODEL OPERATION OUTPUT OPERAND INDEX /////////////////////////
+
+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) {
+            const std::string message = "mutateOperationOutputOperandIndexTest: operation " +
+                                        std::to_string(operation) + " output " +
+                                        std::to_string(output);
+            validate(device, message, model, [operation, output, invalidOperand](Model* model) {
+                model->operations[operation].outputs[output] = invalidOperand;
+            });
+        }
+    }
+}
+
+///////////////////////// REMOVE OPERAND FROM EVERYTHING /////////////////////////
+
+static void removeValueAndDecrementGreaterValues(hidl_vec<uint32_t>* vec, uint32_t value) {
+    if (vec) {
+        // remove elements matching "value"
+        auto last = std::remove(vec->begin(), vec->end(), value);
+        vec->resize(std::distance(vec->begin(), last));
+
+        // decrement elements exceeding "value"
+        std::transform(vec->begin(), vec->end(), vec->begin(),
+                       [value](uint32_t v) { return v > value ? v-- : v; });
+    }
+}
+
+static void removeOperand(Model* model, uint32_t index) {
+    hidl_vec_removeAt(&model->operands, index);
+    for (Operation& operation : model->operations) {
+        removeValueAndDecrementGreaterValues(&operation.inputs, index);
+        removeValueAndDecrementGreaterValues(&operation.outputs, index);
+    }
+    removeValueAndDecrementGreaterValues(&model->inputIndexes, index);
+    removeValueAndDecrementGreaterValues(&model->outputIndexes, index);
+}
+
+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,
+                 [operand](Model* model) { removeOperand(model, operand); });
+    }
+}
+
+///////////////////////// REMOVE OPERATION /////////////////////////
+
+static void removeOperation(Model* model, uint32_t index) {
+    for (uint32_t operand : model->operations[index].inputs) {
+        model->operands[operand].numberOfConsumers--;
+    }
+    hidl_vec_removeAt(&model->operations, index);
+}
+
+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,
+                 [operation](Model* model) { removeOperation(model, operation); });
+    }
+}
+
+///////////////////////// REMOVE OPERATION INPUT /////////////////////////
+
+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 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 == OperationType::CONCATENATION && op.inputs.size() > 2 &&
+                input != op.inputs.size() - 1) {
+                continue;
+            }
+            const std::string message = "removeOperationInputTest: operation " +
+                                        std::to_string(operation) + ", input " +
+                                        std::to_string(input);
+            validate(device, message, model, [operation, input](Model* model) {
+                uint32_t operand = model->operations[operation].inputs[input];
+                model->operands[operand].numberOfConsumers--;
+                hidl_vec_removeAt(&model->operations[operation].inputs, input);
+            });
+        }
+    }
+}
+
+///////////////////////// REMOVE OPERATION OUTPUT /////////////////////////
+
+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 " +
+                                        std::to_string(operation) + ", output " +
+                                        std::to_string(output);
+            validate(device, message, model, [operation, output](Model* model) {
+                hidl_vec_removeAt(&model->operations[operation].outputs, output);
+            });
+        }
+    }
+}
+
+///////////////////////// MODEL VALIDATION /////////////////////////
+
+// TODO: remove model input
+// TODO: remove model output
+// TODO: add unused operation
+
+///////////////////////// ADD OPERATION INPUT /////////////////////////
+
+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) {
+            uint32_t index = addOperand(model, OperandLifeTime::MODEL_INPUT);
+            hidl_vec_push_back(&model->operations[operation].inputs, index);
+            hidl_vec_push_back(&model->inputIndexes, index);
+        });
+    }
+}
+
+///////////////////////// ADD OPERATION OUTPUT /////////////////////////
+
+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);
+        validate(device, message, model, [operation](Model* model) {
+            uint32_t index = addOperand(model, OperandLifeTime::MODEL_OUTPUT);
+            hidl_vec_push_back(&model->operations[operation].outputs, index);
+            hidl_vec_push_back(&model->outputIndexes, index);
+        });
+    }
+}
+
+///////////////////////// 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 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));
+    }
+}
+
+////////////////////////// ENTRY POINT //////////////////////////////
+
+void ValidationTest::validateModel(const Model& model) {
+    mutateOperandTypeTest(device, model);
+    mutateOperandRankTest(device, model);
+    mutateOperandScaleTest(device, model);
+    mutateOperandZeroPointTest(device, model);
+    mutateOperationOperandTypeTest(device, model);
+    mutateOperationTypeTest(device, model);
+    mutateOperationInputOperandIndexTest(device, model);
+    mutateOperationOutputOperandIndexTest(device, model);
+    removeOperandTest(device, model);
+    removeOperationTest(device, model);
+    removeOperationInputTest(device, model);
+    removeOperationOutputTest(device, model);
+    addOperationInputTest(device, model);
+    addOperationOutputTest(device, model);
+    mutateExecutionPreferenceTest(device, model);
+}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_2
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
new file mode 100644
index 0000000..f4476fa
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/ValidateRequest.cpp
@@ -0,0 +1,261 @@
+/*
+ * 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 "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_0::implementation::ExecutionCallback;
+using ::android::hardware::neuralnetworks::V1_0::implementation::PreparedModelCallback;
+using ::android::hidl::memory::V1_0::IMemory;
+using test_helper::for_all;
+using test_helper::MixedTyped;
+using test_helper::MixedTypedExampleType;
+
+///////////////////////// UTILITY FUNCTIONS /////////////////////////
+
+static void createPreparedModel(const sp<IDevice>& device, const Model& model,
+                                sp<IPreparedModel>* preparedModel) {
+    ASSERT_NE(nullptr, preparedModel);
+
+    // see if service can handle model
+    bool fullySupportsModel = false;
+    Return<void> supportedOpsLaunchStatus = 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());
+
+    // 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, preparedModelCallback);
+    ASSERT_TRUE(prepareLaunchStatus.isOk());
+    ASSERT_EQ(ErrorStatus::NONE, static_cast<ErrorStatus>(prepareLaunchStatus));
+
+    // retrieve prepared model
+    preparedModelCallback->wait();
+    ErrorStatus prepareReturnStatus = preparedModelCallback->getStatus();
+    *preparedModel = preparedModelCallback->getPreparedModel();
+
+    // The getSupportedOperations_1_2 call returns a list of operations that are
+    // guaranteed not to fail if prepareModel_1_2 is called, and
+    // 'fullySupportsModel' is true i.f.f. the entire model is guaranteed.
+    // If a driver has any doubt that it can prepare an operation, it must
+    // return false. So here, if a driver isn't sure if it can support an
+    // operation, but reports that it successfully prepared the model, the test
+    // 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."
+                  << std::endl;
+        return;
+    }
+    ASSERT_EQ(ErrorStatus::NONE, prepareReturnStatus);
+    ASSERT_NE(nullptr, preparedModel->get());
+}
+
+// Primary validation function. This function will take a valid request, apply a
+// mutation to it to invalidate the request, then pass it to interface calls
+// that use the request. Note that the request here is passed by value, and any
+// mutation to the request does not leave this function.
+static void validate(const sp<IPreparedModel>& preparedModel, const std::string& message,
+                     Request request, const std::function<void(Request*)>& mutation) {
+    mutation(&request);
+    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));
+
+    executionCallback->wait();
+    ErrorStatus executionReturnStatus = executionCallback->getStatus();
+    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) {
+    for (size_t input = 0; input < request.inputs.size(); ++input) {
+        const std::string message = "removeInput: removed input " + std::to_string(input);
+        validate(preparedModel, message, request,
+                 [input](Request* request) { hidl_vec_removeAt(&request->inputs, input); });
+    }
+}
+
+///////////////////////// REMOVE OUTPUT ////////////////////////////////////
+
+static void removeOutputTest(const sp<IPreparedModel>& preparedModel, const Request& request) {
+    for (size_t output = 0; output < request.outputs.size(); ++output) {
+        const std::string message = "removeOutput: removed Output " + std::to_string(output);
+        validate(preparedModel, message, request,
+                 [output](Request* request) { hidl_vec_removeAt(&request->outputs, output); });
+    }
+}
+
+///////////////////////////// ENTRY POINT //////////////////////////////////
+
+std::vector<Request> createRequests(const std::vector<MixedTypedExampleType>& examples) {
+    const uint32_t INPUT = 0;
+    const uint32_t OUTPUT = 1;
+
+    std::vector<Request> requests;
+
+    for (auto& example : examples) {
+        const MixedTyped& inputs = example.first;
+        const MixedTyped& outputs = example.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 ValidationTest::validateRequests(const Model& model, const std::vector<Request>& requests) {
+    // create IPreparedModel
+    sp<IPreparedModel> preparedModel;
+    ASSERT_NO_FATAL_FAILURE(createPreparedModel(device, model, &preparedModel));
+    if (preparedModel == nullptr) {
+        return;
+    }
+
+    // validate each request
+    for (const Request& request : requests) {
+        removeInputTest(preparedModel, request);
+        removeOutputTest(preparedModel, request);
+    }
+}
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_2
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.2/vts/functional/ValidationTests.cpp b/neuralnetworks/1.2/vts/functional/ValidationTests.cpp
new file mode 100644
index 0000000..3bdc5cd
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/ValidationTests.cpp
@@ -0,0 +1,50 @@
+/*
+ * 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 "Models.h"
+#include "VtsHalNeuralnetworks.h"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_2 {
+namespace vts {
+namespace functional {
+
+// forward declarations
+std::vector<Request> createRequests(const std::vector<MixedTypedExample>& examples);
+
+// generate validation tests
+#define VTS_CURRENT_TEST_CASE(TestName)                                           \
+    TEST_F(ValidationTest, TestName) {                                            \
+        const Model model = TestName::createTestModel();                          \
+        const std::vector<Request> requests = createRequests(TestName::examples); \
+        validateModel(model);                                                     \
+        validateRequests(model, requests);                                        \
+    }
+
+FOR_EACH_TEST_MODEL(VTS_CURRENT_TEST_CASE)
+
+#undef VTS_CURRENT_TEST_CASE
+
+}  // namespace functional
+}  // namespace vts
+}  // namespace V1_2
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp
new file mode 100644
index 0000000..90a910c
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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"
+
+namespace android {
+namespace hardware {
+namespace neuralnetworks {
+namespace V1_2 {
+namespace vts {
+namespace functional {
+
+// 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());
+    ASSERT_NE(nullptr, device.get());
+}
+
+void NeuralnetworksHidlTest::TearDown() {
+    device = nullptr;
+    ::testing::VtsHalHidlTargetTestBase::TearDown();
+}
+
+}  // namespace functional
+}  // namespace vts
+
+::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 V1_2
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
+
+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;
+}
diff --git a/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
new file mode 100644
index 0000000..a87d788
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/VtsHalNeuralnetworks.h
@@ -0,0 +1,92 @@
+/*
+ * 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 VTS_HAL_NEURALNETWORKS_V1_2_H
+#define VTS_HAL_NEURALNETWORKS_V1_2_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/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_2 {
+
+using V1_0::DeviceStatus;
+using V1_0::ErrorStatus;
+using V1_0::Request;
+
+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;
+    void SetUp() override;
+    void TearDown() override;
+
+   protected:
+    sp<IDevice> device;
+};
+
+// Tag for the validation tests
+class ValidationTest : public NeuralnetworksHidlTest {
+   protected:
+    void validateModel(const Model& model);
+    void validateRequests(const Model& model, const std::vector<Request>& request);
+};
+
+// Tag for the generated tests
+class GeneratedTest : public NeuralnetworksHidlTest {};
+
+}  // namespace functional
+}  // namespace vts
+
+// pretty-print values for error messages
+::std::ostream& operator<<(::std::ostream& os, ErrorStatus errorStatus);
+::std::ostream& operator<<(::std::ostream& os, DeviceStatus deviceStatus);
+
+}  // namespace V1_2
+}  // namespace neuralnetworks
+}  // namespace hardware
+}  // namespace android
+
+#endif  // VTS_HAL_NEURALNETWORKS_V1_2_H
diff --git a/power/1.3/Android.bp b/power/1.3/Android.bp
index 65b7597..1869b56 100644
--- a/power/1.3/Android.bp
+++ b/power/1.3/Android.bp
@@ -3,6 +3,9 @@
 hidl_interface {
     name: "android.hardware.power@1.3",
     root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
     srcs: [
         "types.hal",
         "IPower.hal",
diff --git a/radio/1.0/types.hal b/radio/1.0/types.hal
index ab1834b..17718e0 100644
--- a/radio/1.0/types.hal
+++ b/radio/1.0/types.hal
@@ -1500,9 +1500,10 @@
 };
 
 struct CellIdentityGsm {
-    string mcc;                           // 3-digit Mobile Country Code, 0..999, INT_MAX if unknown
-    string mnc;                           // 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if
+    string mcc;                           // 3-digit Mobile Country Code, 0..999, empty string if
                                           // unknown
+    string mnc;                           // 2 or 3-digit Mobile Network Code, 0..999, empty string
+                                          // if unknown
     int32_t lac;                          // 16-bit Location Area Code, 0..65535, INT_MAX if unknown
     int32_t cid;                          // 16-bit GSM Cell Identity described in
                                           // TS 27.007, 0..65535, INT_MAX if unknown
@@ -1512,8 +1513,9 @@
 };
 
 struct CellIdentityWcdma {
-    string mcc;                           // 3-digit Mobile Country Code, 0..999, INT_MAX if unknown
-    string mnc;                           // 2 or 3-digit Mobile Network Code, 0..999, INT_MAX
+    string mcc;                           // 3-digit Mobile Country Code, 0..999, empty string if
+                                          // unknown
+    string mnc;                           // 2 or 3-digit Mobile Network Code, 0..999, empty string
                                           // if unknown
     int32_t lac;                          // 16-bit Location Area Code, 0..65535, INT_MAX if unknown
     int32_t cid;                          // 28-bit UMTS Cell Identity described in
@@ -1541,9 +1543,10 @@
 };
 
 struct CellIdentityLte {
-    string mcc;                           // 3-digit Mobile Country Code, 0..999, INT_MAX if unknown
-    string mnc;                           // 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if
+    string mcc;                           // 3-digit Mobile Country Code, 0..999, empty string if
                                           // unknown
+    string mnc;                           // 2 or 3-digit Mobile Network Code, 0..999, empty string
+                                          // if unknown
     int32_t ci;                           // 28-bit Cell Identity described in TS TS 27.007, INT_MAX
                                           // if unknown
     int32_t pci;                          // physical cell id 0..503; this value must be valid
@@ -1553,9 +1556,10 @@
 };
 
 struct CellIdentityTdscdma {
-    string mcc;                           // 3-digit Mobile Country Code, 0..999, INT_MAX if unknown
-    string mnc;                           // 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if
+    string mcc;                           // 3-digit Mobile Country Code, 0..999, empty string if
                                           // unknown
+    string mnc;                           // 2 or 3-digit Mobile Network Code, 0..999, empty string
+                                          // if unknown
     int32_t lac;                          // 16-bit Location Area Code, 0..65535, INT_MAX if
                                           // unknown
     int32_t cid;                          // 28-bit UMTS Cell Identity described in
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_data.cpp b/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
index 4f10f11..eaef3ed 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
+++ b/radio/1.0/vts/functional/radio_hidl_hal_data.cpp
@@ -32,6 +32,67 @@
 
     if (cardStatus.cardState == CardState::ABSENT) {
         EXPECT_EQ(RadioError::NONE, radioRsp->rspInfo.error);
+    } else if (cardStatus.cardState == CardState::PRESENT) {
+        ASSERT_TRUE(CheckAnyOfErrors(
+            radioRsp->rspInfo.error,
+            {RadioError::NONE, RadioError::NOT_PROVISIONED, RadioError::CANCELLED}));
+
+        // Check the mcc [0, 999] and mnc [0, 999].
+        string hidl_mcc;
+        string hidl_mnc;
+        bool checkMccMnc = true;
+        int totalIdentitySizeExpected = 1;
+        CellIdentity cellIdentities = radioRsp->dataRegResp.cellIdentity;
+        CellInfoType cellInfoType = cellIdentities.cellInfoType;
+
+        if (cellInfoType == CellInfoType::NONE) {
+            // All the fields are 0
+            totalIdentitySizeExpected = 0;
+            checkMccMnc = false;
+        } else if (cellInfoType == CellInfoType::GSM) {
+            EXPECT_EQ(1, cellIdentities.cellIdentityGsm.size());
+            CellIdentityGsm cig = cellIdentities.cellIdentityGsm[0];
+            hidl_mcc = cig.mcc;
+            hidl_mnc = cig.mnc;
+        } else if (cellInfoType == CellInfoType::LTE) {
+            EXPECT_EQ(1, cellIdentities.cellIdentityLte.size());
+            CellIdentityLte cil = cellIdentities.cellIdentityLte[0];
+            hidl_mcc = cil.mcc;
+            hidl_mnc = cil.mnc;
+        } else if (cellInfoType == CellInfoType::WCDMA) {
+            EXPECT_EQ(1, cellIdentities.cellIdentityWcdma.size());
+            CellIdentityWcdma ciw = cellIdentities.cellIdentityWcdma[0];
+            hidl_mcc = ciw.mcc;
+            hidl_mnc = ciw.mnc;
+        } else if (cellInfoType == CellInfoType::TD_SCDMA) {
+            EXPECT_EQ(1, cellIdentities.cellIdentityTdscdma.size());
+            CellIdentityTdscdma cit = cellIdentities.cellIdentityTdscdma[0];
+            hidl_mcc = cit.mcc;
+            hidl_mnc = cit.mnc;
+        } else {
+            // CellIndentityCdma has no mcc and mnc.
+            EXPECT_EQ(CellInfoType::CDMA, cellInfoType);
+            EXPECT_EQ(1, cellIdentities.cellIdentityCdma.size());
+            checkMccMnc = false;
+        }
+
+        // Check only one CellIdentity is size 1, and others must be 0.
+        EXPECT_EQ(totalIdentitySizeExpected, cellIdentities.cellIdentityGsm.size() +
+                                                 cellIdentities.cellIdentityCdma.size() +
+                                                 cellIdentities.cellIdentityLte.size() +
+                                                 cellIdentities.cellIdentityWcdma.size() +
+                                                 cellIdentities.cellIdentityTdscdma.size());
+
+        if (checkMccMnc) {
+            // 32 bit system gets result: "\xff\xff\xff..." from RIL, which is not testable. Only
+            // test for 64 bit here. TODO: remove this limit after b/113181277 being fixed.
+            if (hidl_mcc.size() < 4 && hidl_mnc.size() < 4) {
+                int mcc = stoi(hidl_mcc);
+                int mnc = stoi(hidl_mnc);
+                EXPECT_TRUE(mcc >= 0 && mcc <= 999);
+                EXPECT_TRUE(mnc >= 0 && mnc <= 999);
+            }
+        }
     }
 }
 
diff --git a/radio/1.0/vts/functional/radio_hidl_hal_utils_v1_0.h b/radio/1.0/vts/functional/radio_hidl_hal_utils_v1_0.h
index f5ce072..23bc434 100644
--- a/radio/1.0/vts/functional/radio_hidl_hal_utils_v1_0.h
+++ b/radio/1.0/vts/functional/radio_hidl_hal_utils_v1_0.h
@@ -60,6 +60,9 @@
     uint32_t writeSmsToSimIndex;
     uint32_t writeSmsToRuimIndex;
 
+    // Data
+    DataRegStateResult dataRegResp;
+
     RadioResponse(RadioHidlTest& parent);
 
     virtual ~RadioResponse() = default;
diff --git a/radio/1.0/vts/functional/radio_response.cpp b/radio/1.0/vts/functional/radio_response.cpp
index 93d5557..f3938a9 100644
--- a/radio/1.0/vts/functional/radio_response.cpp
+++ b/radio/1.0/vts/functional/radio_response.cpp
@@ -157,8 +157,9 @@
 }
 
 Return<void> RadioResponse::getDataRegistrationStateResponse(
-    const RadioResponseInfo& info, const DataRegStateResult& /*dataRegResponse*/) {
+    const RadioResponseInfo& info, const DataRegStateResult& dataRegResponse) {
     rspInfo = info;
+    dataRegResp = dataRegResponse;
     parent.notify(info.serial);
     return Void();
 }
diff --git a/radio/1.0/vts/functional/vts_test_util.cpp b/radio/1.0/vts/functional/vts_test_util.cpp
index 7d15f35..ec96e5f 100644
--- a/radio/1.0/vts/functional/vts_test_util.cpp
+++ b/radio/1.0/vts/functional/vts_test_util.cpp
@@ -53,4 +53,4 @@
         }
     }
     return testing::AssertionFailure() << "SapError:" + toString(err) + " is returned";
-}
+}
\ No newline at end of file
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 3510163..730d969 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.2/vts/functional/radio_hidl_hal_api.cpp
@@ -753,6 +753,56 @@
     ASSERT_TRUE(CheckAnyOfErrors(
         radioRsp_v1_2->rspInfo.error,
         {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::NOT_PROVISIONED}));
+
+    // Check the mcc [0, 999] and mnc [0, 999].
+    string hidl_mcc;
+    string hidl_mnc;
+    int totalIdentitySizeExpected = 1;
+    ::android::hardware::radio::V1_2::CellIdentity cellIdentities =
+        radioRsp_v1_2->dataRegResp.cellIdentity;
+    CellInfoType cellInfoType = cellIdentities.cellInfoType;
+
+    if (cellInfoType == CellInfoType::NONE) {
+        // All the fields are 0
+        totalIdentitySizeExpected = 0;
+    } else if (cellInfoType == CellInfoType::GSM) {
+        EXPECT_EQ(1, cellIdentities.cellIdentityGsm.size());
+        ::android::hardware::radio::V1_2::CellIdentityGsm cig = cellIdentities.cellIdentityGsm[0];
+        hidl_mcc = cig.base.mcc;
+        hidl_mnc = cig.base.mnc;
+    } else if (cellInfoType == CellInfoType::LTE) {
+        EXPECT_EQ(1, cellIdentities.cellIdentityLte.size());
+        ::android::hardware::radio::V1_2::CellIdentityLte cil = cellIdentities.cellIdentityLte[0];
+        hidl_mcc = cil.base.mcc;
+        hidl_mnc = cil.base.mnc;
+    } else if (cellInfoType == CellInfoType::WCDMA) {
+        EXPECT_EQ(1, cellIdentities.cellIdentityWcdma.size());
+        ::android::hardware::radio::V1_2::CellIdentityWcdma ciw =
+            cellIdentities.cellIdentityWcdma[0];
+        hidl_mcc = ciw.base.mcc;
+        hidl_mnc = ciw.base.mnc;
+    } else if (cellInfoType == CellInfoType::TD_SCDMA) {
+        EXPECT_EQ(1, cellIdentities.cellIdentityTdscdma.size());
+        ::android::hardware::radio::V1_2::CellIdentityTdscdma cit =
+            cellIdentities.cellIdentityTdscdma[0];
+        hidl_mcc = cit.base.mcc;
+        hidl_mnc = cit.base.mnc;
+    } else {
+        // CellIndentityCdma has no mcc and mnc.
+        EXPECT_EQ(CellInfoType::CDMA, cellInfoType);
+        EXPECT_EQ(1, cellIdentities.cellIdentityCdma.size());
+    }
+
+    // Check only one CellIdentity is size 1, and others must be 0.
+    EXPECT_EQ(totalIdentitySizeExpected,
+              cellIdentities.cellIdentityGsm.size() + cellIdentities.cellIdentityCdma.size() +
+                  cellIdentities.cellIdentityLte.size() + cellIdentities.cellIdentityWcdma.size() +
+                  cellIdentities.cellIdentityTdscdma.size());
+
+    int mcc = stoi(hidl_mcc);
+    int mnc = stoi(hidl_mnc);
+    EXPECT_TRUE(mcc >= 0 && mcc <= 999);
+    EXPECT_TRUE(mnc >= 0 && mnc <= 999);
 }
 
 /*
diff --git a/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h b/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h
index 4712202..2e65bfb 100644
--- a/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h
+++ b/radio/1.2/vts/functional/radio_hidl_hal_utils_v1_2.h
@@ -56,6 +56,9 @@
 
     RadioResponseInfo rspInfo;
 
+    // Data
+    ::android::hardware::radio::V1_2::DataRegStateResult dataRegResp;
+
     RadioResponse_v1_2(RadioHidlTest_v1_2& parent_v1_2);
     virtual ~RadioResponse_v1_2() = default;
 
diff --git a/radio/1.2/vts/functional/radio_response.cpp b/radio/1.2/vts/functional/radio_response.cpp
index c5c7b14..e91a557 100644
--- a/radio/1.2/vts/functional/radio_response.cpp
+++ b/radio/1.2/vts/functional/radio_response.cpp
@@ -756,8 +756,9 @@
 
 Return<void> RadioResponse_v1_2::getDataRegistrationStateResponse_1_2(
     const RadioResponseInfo& info,
-    const ::android::hardware::radio::V1_2::DataRegStateResult& /*dataRegResponse*/) {
+    const ::android::hardware::radio::V1_2::DataRegStateResult& dataRegResponse) {
     rspInfo = info;
+    dataRegResp = dataRegResponse;
     parent_v1_2.notify(info.serial);
     return Void();
 }
diff --git a/radio/1.3/Android.bp b/radio/1.3/Android.bp
new file mode 100644
index 0000000..5ac38cd
--- /dev/null
+++ b/radio/1.3/Android.bp
@@ -0,0 +1,30 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.radio@1.3",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IRadio.hal",
+        "IRadioIndication.hal",
+        "IRadioResponse.hal",
+    ],
+    interfaces: [
+        "android.hardware.radio@1.0",
+        "android.hardware.radio@1.1",
+        "android.hardware.radio@1.2",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "AccessNetwork",
+        "DataRegStateResult",
+        "EmergencyNumber",
+        "EmergencyServiceCategory",
+        "LteVopsInfo",
+    ],
+    gen_java: true,
+}
+
diff --git a/radio/1.3/IRadio.hal b/radio/1.3/IRadio.hal
new file mode 100644
index 0000000..480a61f
--- /dev/null
+++ b/radio/1.3/IRadio.hal
@@ -0,0 +1,128 @@
+/*
+ * 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.radio@1.3;
+
+import @1.0::DataProfileInfo;
+import @1.0::Dial;
+import @1.2::DataRequestReason;
+import @1.2::IRadio;
+import @1.3::AccessNetwork;
+import @1.3::EmergencyServiceCategory;
+
+/**
+ * This interface is used by telephony and telecom to talk to cellular radio.
+ * All the functions have minimum one parameter:
+ * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
+ * duration of a method call. If clients provide colliding serials (including passing the same
+ * serial to different methods), multiple responses (one for each method call) must still be served.
+ * setResponseFunctions must work with @1.1::IRadioResponse and @1.1::IRadioIndication.
+ */
+interface IRadio extends @1.2::IRadio {
+    /**
+     * Setup a packet data connection. If DataCallResponse.status returns DataCallFailCause:NONE,
+     * the data connection must be added to data calls and a unsolDataCallListChanged() must be
+     * sent. The call remains until removed by subsequent unsolDataCallIstChanged(). It may be
+     * lost due to many factors, including deactivateDataCall() being issued, the radio powered
+     * off, reception lost or even transient factors like congestion. This data call list is
+     * returned by getDataCallList() and dataCallListChanged().
+     *
+     * The Radio is expected to:
+     *   - Create one data call context.
+     *   - Create and configure a dedicated interface for the context.
+     *   - The interface must be point to point.
+     *   - The interface is configured with one or more addresses and is capable of sending and
+     *     receiving packets. The prefix length of the addresses must be /32 for IPv4 and /128
+     *     for IPv6.
+     *   - Must not modify routing configuration related to this interface; routing management is
+     *     exclusively within the purview of the Android OS.
+     *   - Support simultaneous data call contexts up to DataRegStateResult.maxDataCalls specified
+     *     in the response of getDataRegistrationState.
+     *
+     * @param serial Serial number of request.
+     * @param accessNetwork The access network to setup the data call. If the data connection cannot
+     *     be established on the specified access network, the setup request must be failed.
+     * @param dataProfileInfo Data profile info.
+     * @param modemCognitive Indicates that the requested profile has previously been provided via
+     *     setDataProfile().
+     * @param roamingAllowed Indicates whether or not data roaming is allowed by the user.
+     * @param isRoaming Indicates whether or not the framework has requested this setupDataCall for
+     *     a roaming network. The 'protocol' parameter in the old RIL API must be filled
+     *     accordingly based on the roaming condition. Note this is for backward compatibility with
+     *     the old radio modem. The modem must not use this param for any other reason.
+     * @param reason The request reason. Must be DataRequestReason.NORMAL or
+     *     DataRequestReason.HANDOVER.
+     * @param addresses If the reason is DataRequestReason.HANDOVER, this indicates the list of link
+     *     addresses of the existing data connection. The format is IP address with optional "/"
+     *     prefix length (The format is defined in RFC-4291 section 2.3). For example, "192.0.1.3",
+     *     "192.0.1.11/16", or "2001:db8::1/64". Typically one IPv4 or one IPv6 or one of each. If
+     *     the prefix length is absent, then the addresses are assumed to be point to point with
+     *     IPv4 with prefix length 32 or IPv6 with prefix length 128. This parameter must be ignored
+     *     unless reason is DataRequestReason.HANDOVER.
+     * @param dnses If the reason is DataRequestReason.HANDOVER, this indicates the list of DNS
+     *     addresses of the existing data connection. The format is defined in RFC-4291 section
+     *     2.2. For example, "192.0.1.3" or "2001:db8::1". This parameter must be ignored unless
+     *     reason is DataRequestReason.HANDOVER.
+     *
+     * Response function is IRadioResponse.setupDataCallResponse()
+     *
+     * Note this API is same as 1.2 version except using the 1.3 AccessNetwork as the input param.
+     */
+    oneway setupDataCall_1_3(int32_t serial, AccessNetwork accessNetwork,
+            DataProfileInfo dataProfileInfo, bool modemCognitive, bool roamingAllowed,
+            bool isRoaming, DataRequestReason reason, vec<string> addresses, vec<string> dnses);
+
+    /**
+     * Request the current emergency number list.
+     *
+     * Each emergency number (@1.3::EmergencyNumber) in the emergency number list contains a
+     * dialing number, one or more service category(s), and mobile country code.
+     *
+     * Radio must collect all sources of the emergency number to build the response.
+     * For example, network operator signals, sim card information, modem configuration, OEM
+     * configuration (for example, OEM system properties), always-available emergency numbers and
+     * sim-absence emergency numbers, etc.
+     *
+     * 112, 911 are always available. Besides, 000, 08, 110, 999, 118 and 119 should be available
+     * when sim is not present.
+     *
+     * Please refer the document of @1.3::EmergencyNumber to construct each emergency number to be
+     * returned.
+     *
+     * Reference: 3GPP TS 22.101 version 9.1.0 Release 9
+     *
+     * @param serial Serial number of request.
+     *
+     * Response function is IRadioResponse.getCurrentEmergencyNumberListResponse()
+     */
+    oneway getCurrentEmergencyNumberList(int32_t serial);
+
+    /**
+     * Initiate emergency voice call, with one or more emergency service category(s).
+     *
+     * Note this API is the same as IRadio.dial except using the
+     * @1.3::EmergencyServiceCategory as the input param.
+     *
+     * @param serial Serial number of request.
+     * @param dialInfo the same @1.0::Dial information used by @1.0::IRadio.dial.
+     * @param categories bitfield<@1.3::EmergencyServiceCategory> the Emergency Service Category(s)
+     *     of the call.
+     *
+     * Response function is IRadioResponse.emergencyDialResponse()
+     */
+    oneway emergencyDial(int32_t serial, Dial dialInfo,
+            bitfield<EmergencyServiceCategory> categories);
+};
diff --git a/radio/1.3/IRadioIndication.hal b/radio/1.3/IRadioIndication.hal
new file mode 100644
index 0000000..c80e762
--- /dev/null
+++ b/radio/1.3/IRadioIndication.hal
@@ -0,0 +1,53 @@
+/*
+ * 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.radio@1.3;
+
+import @1.0::RadioIndicationType;
+import @1.2::IRadioIndication;
+
+/**
+ * Interface declaring unsolicited radio indications.
+ */
+interface IRadioIndication extends @1.2::IRadioIndication {
+    /**
+     * Indicate and update all of the current Emergency Number information known to the radio,
+     * when any of the Emergency Number sources (For example, network operator signals, sim card
+     * information, modem configuration, OEM configuration or system properties, etc.) change the
+     * list of emergency numbers.
+     *
+     * 112, 911 are always available. Besides, 000, 08, 110, 999, 118 and 119 should be available
+     * when sim is not present.
+     *
+     * This should be the same information as returned by getCurrentEmergencyNumberList() in
+     * 1.3::IRadio.
+     *
+     * The indicated list of emergency numbers should not have duplicate @1.3::EmergencyNumber.
+     * Please refer the document of @1.3::EmergencyNumber to construct each emergency number to be
+     * returned.
+     *
+     * Reference: 3GPP TS 22.101 version 9.1.0 Release 9
+     *
+     * @param type Type of radio indication
+     * @param emergencyNumberList List of current Emergency Number information
+     *     (@1.3::EmergencyNumber) known to radio. Radio must collect all sources of the emergency
+     *     numbers to build the indication. For example, network operator signals, sim card
+     *     information, modem configuration, OEM configuration (for example, OEM specific system
+     *     properties), always-available emergency numbers and sim-absence emergency numbers, etc.
+     */
+    oneway currentEmergencyNumberList(RadioIndicationType type,
+            vec<EmergencyNumber> emergencyNumberList);
+};
diff --git a/radio/1.3/IRadioResponse.hal b/radio/1.3/IRadioResponse.hal
new file mode 100644
index 0000000..3604953
--- /dev/null
+++ b/radio/1.3/IRadioResponse.hal
@@ -0,0 +1,88 @@
+/*
+ * 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.radio@1.3;
+
+import @1.0::RadioResponseInfo;
+import @1.2::IRadioResponse;
+
+/**
+ * Interface declaring response functions to solicited radio requests.
+ */
+interface IRadioResponse extends @1.2::IRadioResponse {
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param emergencyNumberList List of current Emergency Number information known to radio.
+     *
+     * Radio must collect all sources of the emergency number to build the response. For example,
+     * network operator signals, sim card information, modem configuration, OEM configuration (for
+     * example, OEM system properties), always-available emergency numbers and sim-absence
+     * emergency numbers, etc.
+     *
+     * The returned list of emergency numbers must not have duplicate @1.3::EmergencyNumber. Please
+     * refer the document of @1.3::EmergencyNumber to construct each emergency number to be
+     * returned.
+     *
+     * Reference: 3GPP TS 22.101 version 9.1.0 Release 9
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:NO_MEMORY
+     *   RadioError:MODEM_ERR
+     */
+    oneway getCurrentEmergencyNumberListResponse(RadioResponseInfo info,
+            vec<EmergencyNumber> emergencyNumberList);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE (radio resetting)
+     *   RadioError:DIAL_MODIFIED_TO_USSD
+     *   RadioError:DIAL_MODIFIED_TO_SS
+     *   RadioError:DIAL_MODIFIED_TO_DIAL
+     *   RadioError:INVALID_ARGUMENTS
+     *   RadioError:NO_MEMORY
+     *   RadioError:NO_RESOURCES
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:FDN_CHECK_FAILURE
+     *   RadioError:MODEM_ERR
+     *   RadioError:NO_SUBSCRIPTION
+     *   RadioError:NO_NETWORK_FOUND
+     *   RadioError:INVALID_CALL_ID
+     *   RadioError:DEVICE_IN_USE
+     *   RadioError:ABORTED
+     *   RadioError:INVALID_MODEM_STATE
+     *   RadioError:CANCELLED
+     */
+    oneway emergencyDialResponse(RadioResponseInfo info);
+
+    /**
+     * @param info Response info struct containing response type, serial no. and error
+     * @param dataRegResponse Current Data registration response as defined by DataRegStateResult in
+     *        types.hal
+     *
+     * Valid errors returned:
+     *   RadioError:NONE
+     *   RadioError:RADIO_NOT_AVAILABLE
+     *   RadioError:INTERNAL_ERR
+     *   RadioError:NOT_PROVISIONED
+     */
+    oneway getDataRegistrationStateResponse_1_3(RadioResponseInfo info,
+            DataRegStateResult dataRegResponse);
+};
diff --git a/radio/1.3/types.hal b/radio/1.3/types.hal
new file mode 100644
index 0000000..d472ca7
--- /dev/null
+++ b/radio/1.3/types.hal
@@ -0,0 +1,122 @@
+/*
+ * 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.radio@1.3;
+
+import @1.0::RegState;
+import @1.2::AccessNetwork;
+import @1.2::CellIdentity;
+import @1.2::DataRegStateResult;
+
+enum AccessNetwork : @1.2::AccessNetwork {
+    /**
+     * Unknown access network
+     */
+    UNKNOWN = 0,
+};
+
+/**
+ * Emergency number contains information of number, one or more service category(s), and mobile
+ * country code (mcc).
+ *
+ * If the source of the emergency number is associated with country, field ‘mcc’ must be
+ * provided; otherwise the field ‘mcc’ must be an empty string.
+ *
+ * A unique EmergencyNumber has a unique combination of ‘number’ and ‘mcc’ fields.
+ * Multiple @1.3::EmergencyServiceCategory should be merged into the bitfield for the same
+ * EmergencyNumber.
+ *
+ * Reference: 3GPP TS 22.101 version 9.1.0 Release 9
+ */
+struct EmergencyNumber{
+    /**
+     * The emergency number. The character in the number string should only be the dial pad
+     * character('0'-'9', '*', or '#'). For example: 911.
+     */
+    string number;
+    /**
+     * 3-digit Mobile Country Code, 0..999. Empty string if not applicable.
+     */
+    string mcc;
+    /**
+     * The bitfield of @1.3::EmergencyServiceCategory(s). See @1.3::EmergencyServiceCategory for
+     * the value of each bit.
+     */
+    bitfield<EmergencyServiceCategory> categories;
+};
+
+/**
+ * Defining Emergency Service Category as follows:
+ * - General emergency call, all categories;
+ * - Police;
+ * - Ambulance;
+ * - Fire Brigade;
+ * - Marine Guard;
+ * - Mountain Rescue;
+ * - Manually Initiated eCall (MIeC);
+ * - Automatically Initiated eCall (AIeC);
+ *
+ * Type GENERIC (General emergency call, all categories) is considered to use if the reported type
+ * is not any of the other specific types.
+ *
+ * Reference: 3GPP TS 22.101 version 9.1.0 Release 9
+ */
+enum EmergencyServiceCategory : int32_t {
+    GENERIC = 0, // General emergency call, all categories
+    POLICE = 1 << 0,
+    AMBULANCE = 1 << 1,
+    FIRE_BRIGADE = 1 << 2,
+    MARINE_GUARD = 1 << 3,
+    MOUNTAIN_RESCUE = 1 << 4,
+    MIEC = 1 << 5, // Manually Initiated eCall (MIeC)
+    AIEC = 1 << 6, // Automatically Initiated eCall (AIeC)
+};
+
+/**
+ * Type to define the LTE specific network capabilities for voice over PS including
+ * emergency and normal voice calls.
+ */
+struct LteVopsInfo {
+    /**
+     * This indicates if camped network support VoLTE services. This information is received
+     * from LTE network during LTE NAS registration procedure through LTE ATTACH ACCEPT/TAU
+     * ACCEPT. Refer 3GPP 24.301 EPS network feature support -> IMS VoPS
+     */
+    bool isVopsSupported;
+    /**
+     * This indicates if camped network support VoLTE emergency bearers. This information
+     * is received from LTE network through two sources:
+     * a. During LTE NAS registration procedure through LTE ATTACH ACCEPT/TAU ACCEPT. Refer
+     *    3GPP 24.301 EPS network feature support -> EMC BS
+     * b. In case device is not registered on network. Refer 3GPP 25.331 LTE RRC
+     *    SIB1 : ims-EmergencySupport-r9
+     * If device is registered on LTE, then this field indicates (a).
+     * In case of limited service on LTE this field indicates (b).
+     */
+    bool isEmcBearerSupported;
+};
+
+struct DataRegStateResult {
+    @1.2::DataRegStateResult base;
+    /**
+     * Network capabilities for voice over PS services. This info is valid only
+     * on LTE network and must be present when device is camped on LTE. vopsInfo
+     * will be empty when device is camped only on 2G/3G .
+     */
+    safe_union VopsInfo {
+        LteVopsInfo lteVopsInfo; // LTE network capability
+    } vopsInfo;
+};
diff --git a/tests/baz/1.0/IBaz.hal b/tests/baz/1.0/IBaz.hal
index 9a9e754..8118d8b 100644
--- a/tests/baz/1.0/IBaz.hal
+++ b/tests/baz/1.0/IBaz.hal
@@ -68,8 +68,16 @@
         bitfield<BitField> bf;
     };
 
+    struct MyHandle {
+        handle h;
+        int32_t guard;
+    };
+
     struct StructWithInterface {
         int32_t number;
+        int8_t[7] array;
+        string oneString;
+        vec<string> vectorOfStrings;
         IBase dummy;
     };
     oneway doThis(float param);
diff --git a/tests/msgq/1.0/ITestMsgQ.hal b/tests/msgq/1.0/ITestMsgQ.hal
index 350e26d..112270a 100644
--- a/tests/msgq/1.0/ITestMsgQ.hal
+++ b/tests/msgq/1.0/ITestMsgQ.hal
@@ -24,14 +24,14 @@
 
     /**
      * This method requests the service to set up a synchronous read/write
-     * wait-free FMQ with the client as reader.
+     * wait-free FMQ using the input descriptor with the client as reader.
+     *
+     * @param mqDesc This structure describes the FMQ that was set up by the
+     * client. Server uses this descriptor to set up a FMQ object at its end.
      *
      * @return ret True if the setup is successful.
-     * @return mqDesc This structure describes the FMQ that was
-     * set up by the service. Client can use it to set up the FMQ at its end.
      */
-    configureFmqSyncReadWrite()
-        generates(bool ret, fmq_sync<uint16_t> mqDesc);
+    configureFmqSyncReadWrite(fmq_sync<uint16_t> mqDesc) generates(bool ret);
 
     /**
      * This method requests the service to return an MQDescriptor to
diff --git a/tests/msgq/1.0/default/TestMsgQ.cpp b/tests/msgq/1.0/default/TestMsgQ.cpp
index 6fd4fc6..ba665c9 100644
--- a/tests/msgq/1.0/default/TestMsgQ.cpp
+++ b/tests/msgq/1.0/default/TestMsgQ.cpp
@@ -24,24 +24,21 @@
 namespace implementation {
 
 // Methods from ::android::hardware::tests::msgq::V1_0::ITestMsgQ follow.
-Return<void> TestMsgQ::configureFmqSyncReadWrite(configureFmqSyncReadWrite_cb _hidl_cb) {
-    static constexpr size_t kNumElementsInQueue = 1024;
-    mFmqSynchronized.reset(new (std::nothrow) MessageQueueSync(
-            kNumElementsInQueue, true /* configureEventFlagWord */));
+Return<bool> TestMsgQ::configureFmqSyncReadWrite(
+    const android::hardware::MQDescriptorSync<uint16_t>& mqDesc) {
+    mFmqSynchronized.reset(new (std::nothrow) MessageQueueSync(mqDesc));
     if ((mFmqSynchronized == nullptr) || (mFmqSynchronized->isValid() == false)) {
-        _hidl_cb(false /* ret */, MessageQueueSync::Descriptor());
-    } else {
-        /*
-         * Initialize the EventFlag word with bit FMQ_NOT_FULL.
-         */
-        auto evFlagWordPtr = mFmqSynchronized->getEventFlagWord();
-        if (evFlagWordPtr != nullptr) {
-            std::atomic_init(evFlagWordPtr,
-                             static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL));
-        }
-        _hidl_cb(true /* ret */, *mFmqSynchronized->getDesc());
+        return false;
     }
-    return Void();
+    /*
+     * Initialize the EventFlag word with bit FMQ_NOT_FULL.
+     */
+    auto evFlagWordPtr = mFmqSynchronized->getEventFlagWord();
+    if (evFlagWordPtr != nullptr) {
+        std::atomic_init(evFlagWordPtr,
+                         static_cast<uint32_t>(ITestMsgQ::EventFlagBits::FMQ_NOT_FULL));
+    }
+    return true;
 }
 
 Return<void> TestMsgQ::getFmqUnsyncWrite(bool configureFmq, getFmqUnsyncWrite_cb _hidl_cb) {
diff --git a/tests/msgq/1.0/default/TestMsgQ.h b/tests/msgq/1.0/default/TestMsgQ.h
index 86e4ac4..f9fcddd 100644
--- a/tests/msgq/1.0/default/TestMsgQ.h
+++ b/tests/msgq/1.0/default/TestMsgQ.h
@@ -55,7 +55,7 @@
     TestMsgQ() : mFmqSynchronized(nullptr), mFmqUnsynchronized(nullptr) {}
 
     // Methods from ::android::hardware::tests::msgq::V1_0::ITestMsgQ follow.
-    Return<void> configureFmqSyncReadWrite(configureFmqSyncReadWrite_cb _hidl_cb) override;
+    Return<bool> configureFmqSyncReadWrite(const MQDescriptorSync<uint16_t>& mqDesc) override;
     Return<void> getFmqUnsyncWrite(bool configureFmq, getFmqUnsyncWrite_cb _hidl_cb) override;
     Return<bool> requestWriteFmqSync(int32_t count) override;
     Return<bool> requestReadFmqSync(int32_t count) override;
diff --git a/tests/safeunion/1.0/.hidl_for_test b/tests/safeunion/1.0/.hidl_for_test
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tests/safeunion/1.0/.hidl_for_test
diff --git a/tests/safeunion/1.0/Android.bp b/tests/safeunion/1.0/Android.bp
new file mode 100644
index 0000000..ede8401
--- /dev/null
+++ b/tests/safeunion/1.0/Android.bp
@@ -0,0 +1,15 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.tests.safeunion@1.0",
+    root: "android.hardware",
+    srcs: [
+        "IOtherInterface.hal",
+        "ISafeUnion.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    gen_java: true,
+}
+
diff --git a/tests/safeunion/1.0/IOtherInterface.hal b/tests/safeunion/1.0/IOtherInterface.hal
new file mode 100644
index 0000000..cdaf847
--- /dev/null
+++ b/tests/safeunion/1.0/IOtherInterface.hal
@@ -0,0 +1,21 @@
+/*
+ * 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.tests.safeunion@1.0;
+
+interface IOtherInterface {
+    concatTwoStrings(string a, string b) generates (string result);
+};
diff --git a/tests/safeunion/1.0/ISafeUnion.hal b/tests/safeunion/1.0/ISafeUnion.hal
new file mode 100644
index 0000000..f48248b
--- /dev/null
+++ b/tests/safeunion/1.0/ISafeUnion.hal
@@ -0,0 +1,113 @@
+/*
+ * 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.tests.safeunion@1.0;
+
+import IOtherInterface;
+
+interface ISafeUnion {
+
+    enum BitField : uint8_t {
+        V0 = 1 << 0,
+        V1 = 1 << 1,
+        V2 = 1 << 2,
+        V3 = 1 << 3,
+    };
+
+    struct J {
+        vec<uint32_t> j1;
+        uint8_t[65] j2;
+        string j3;
+    };
+
+    safe_union EmptySafeUnion {
+    };
+
+    safe_union SmallSafeUnion {
+        uint8_t a;
+    };
+
+    safe_union LargeSafeUnion {
+        int8_t a;
+        uint16_t b;
+        int32_t c;
+        uint64_t d;
+
+        int8_t[13] e;
+        int64_t[5] f;
+
+        string g;
+        vec<bool> h;
+        vec<uint64_t> i;
+
+        J j;
+        struct K {
+            uint8_t k1;
+            uint64_t k2;
+        } k;
+
+        SmallSafeUnion l;
+
+        BitField m;
+        bitfield<BitField> n;
+    };
+
+    safe_union InterfaceTypeSafeUnion {
+        uint32_t a;
+        int8_t[7] b;
+        IOtherInterface c;
+        string d;
+        vec<string> e;
+        handle f;
+        vec<handle> g;
+    };
+
+    safe_union HandleTypeSafeUnion {
+        handle a;
+        handle[5] b;
+        vec<handle> c;
+    };
+
+    newLargeSafeUnion() generates (LargeSafeUnion myUnion);
+    setA(LargeSafeUnion myUnion, int8_t a) generates (LargeSafeUnion myUnion);
+    setB(LargeSafeUnion myUnion, uint16_t b) generates (LargeSafeUnion myUnion);
+    setC(LargeSafeUnion myUnion, int32_t c) generates (LargeSafeUnion myUnion);
+    setD(LargeSafeUnion myUnion, uint64_t d) generates (LargeSafeUnion myUnion);
+    setE(LargeSafeUnion myUnion, int8_t[13] e) generates (LargeSafeUnion myUnion);
+    setF(LargeSafeUnion myUnion, int64_t[5] f) generates (LargeSafeUnion myUnion);
+    setG(LargeSafeUnion myUnion, string g) generates (LargeSafeUnion myUnion);
+    setH(LargeSafeUnion myUnion, vec<bool> h) generates (LargeSafeUnion myUnion);
+    setI(LargeSafeUnion myUnion, vec<uint64_t> i) generates (LargeSafeUnion myUnion);
+    setJ(LargeSafeUnion myUnion, J j) generates (LargeSafeUnion myUnion);
+    setK(LargeSafeUnion myUnion, LargeSafeUnion.K k) generates (LargeSafeUnion myUnion);
+    setL(LargeSafeUnion myUnion, SmallSafeUnion l) generates (LargeSafeUnion myUnion);
+    setM(LargeSafeUnion myUnion, BitField m) generates (LargeSafeUnion myUnion);
+    setN(LargeSafeUnion myUnion, bitfield<BitField> m) generates (LargeSafeUnion myUnion);
+
+    newInterfaceTypeSafeUnion() generates (InterfaceTypeSafeUnion myUnion);
+    setInterfaceA(InterfaceTypeSafeUnion myUnion, uint32_t a) generates (InterfaceTypeSafeUnion myUnion);
+    setInterfaceB(InterfaceTypeSafeUnion myUnion, int8_t[7] b) generates (InterfaceTypeSafeUnion myUnion);
+    setInterfaceC(InterfaceTypeSafeUnion myUnion, IOtherInterface c) generates (InterfaceTypeSafeUnion myUnion);
+    setInterfaceD(InterfaceTypeSafeUnion myUnion, string d) generates (InterfaceTypeSafeUnion myUnion);
+    setInterfaceE(InterfaceTypeSafeUnion myUnion, vec<string> e) generates (InterfaceTypeSafeUnion myUnion);
+    setInterfaceF(InterfaceTypeSafeUnion myUnion, handle f) generates (InterfaceTypeSafeUnion myUnion);
+    setInterfaceG(InterfaceTypeSafeUnion myUnion, vec<handle> g) generates (InterfaceTypeSafeUnion myUnion);
+
+    newHandleTypeSafeUnion() generates (HandleTypeSafeUnion myUnion);
+    setHandleA(HandleTypeSafeUnion myUnion, handle a) generates (HandleTypeSafeUnion myUnion);
+    setHandleB(HandleTypeSafeUnion myUnion, handle[5] b) generates (HandleTypeSafeUnion myUnion);
+    setHandleC(HandleTypeSafeUnion myUnion, vec<handle> c) generates (HandleTypeSafeUnion myUnion);
+};
diff --git a/tests/safeunion/1.0/default/Android.bp b/tests/safeunion/1.0/default/Android.bp
new file mode 100644
index 0000000..fc2443e
--- /dev/null
+++ b/tests/safeunion/1.0/default/Android.bp
@@ -0,0 +1,21 @@
+cc_library {
+    name: "android.hardware.tests.safeunion@1.0-impl",
+    defaults: ["hidl_defaults"],
+    relative_install_path: "hw",
+    srcs: [
+        "SafeUnion.cpp",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+    ],
+
+    // These are static libs only for testing purposes and portability. Shared
+    // libs should be used on device.
+    static_libs: ["android.hardware.tests.safeunion@1.0"],
+}
diff --git a/tests/safeunion/1.0/default/SafeUnion.cpp b/tests/safeunion/1.0/default/SafeUnion.cpp
new file mode 100644
index 0000000..4fb0974
--- /dev/null
+++ b/tests/safeunion/1.0/default/SafeUnion.cpp
@@ -0,0 +1,310 @@
+/*
+ * 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.
+ */
+
+#include "SafeUnion.h"
+#include <android-base/logging.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace safeunion {
+namespace V1_0 {
+namespace implementation {
+
+// Methods from ::android::hardware::tests::safeunion::V1_0::ISafeUnion follow.
+Return<void> SafeUnion::newLargeSafeUnion(newLargeSafeUnion_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) newLargeSafeUnion()";
+
+    LargeSafeUnion ret;
+    _hidl_cb(ret);
+    return Void();
+}
+
+Return<void> SafeUnion::setA(const LargeSafeUnion& myUnion, int8_t a, setA_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setA(myUnion, " << a << ")";
+
+    LargeSafeUnion myNewUnion = myUnion;
+    myNewUnion.a(a);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setB(const LargeSafeUnion& myUnion, uint16_t b, setB_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setB(myUnion, " << b << ")";
+
+    LargeSafeUnion myNewUnion = myUnion;
+    myNewUnion.b(b);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setC(const LargeSafeUnion& myUnion, int32_t c, setC_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setC(myUnion, " << c << ")";
+
+    LargeSafeUnion myNewUnion = myUnion;
+    myNewUnion.c(c);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setD(const LargeSafeUnion& myUnion, uint64_t d, setD_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setD(myUnion, " << d << ")";
+
+    LargeSafeUnion myNewUnion = myUnion;
+    myNewUnion.d(d);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setE(const LargeSafeUnion& myUnion, const hidl_array<int8_t, 13>& e, setE_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setE(myUnion, " << toString(e) << ")";
+
+    LargeSafeUnion myNewUnion = myUnion;
+    myNewUnion.e(e);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setF(const LargeSafeUnion& myUnion, const hidl_array<int64_t, 5>& f, setF_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setF(myUnion, " << toString(f) << ")";
+
+    LargeSafeUnion myNewUnion = myUnion;
+    myNewUnion.f(f);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setG(const LargeSafeUnion& myUnion, const hidl_string& g, setG_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setG(myUnion, " << toString(g) << ")";
+
+    LargeSafeUnion myNewUnion = myUnion;
+    myNewUnion.g(g);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setH(const LargeSafeUnion& myUnion, const hidl_vec<bool>& h, setH_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setH(myUnion, " << toString(h) << ")";
+
+    LargeSafeUnion myNewUnion = myUnion;
+    myNewUnion.h(h);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setI(const LargeSafeUnion& myUnion, const hidl_vec<uint64_t>& i, setI_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setI(myUnion, " << toString(i) << ")";
+
+    LargeSafeUnion myNewUnion = myUnion;
+    myNewUnion.i(i);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setJ(const LargeSafeUnion& myUnion, const J& j, setJ_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setJ(myUnion, " << toString(j) << ")";
+
+    LargeSafeUnion myNewUnion = myUnion;
+    myNewUnion.j(j);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setK(const LargeSafeUnion& myUnion, const LargeSafeUnion::K& k, setK_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setK(myUnion, " << toString(k) << ")";
+
+    LargeSafeUnion myNewUnion = myUnion;
+    myNewUnion.k(k);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setL(const LargeSafeUnion& myUnion, const SmallSafeUnion& l, setL_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setL(myUnion, " << toString(l) << ")";
+
+    LargeSafeUnion myNewUnion = myUnion;
+    myNewUnion.l(l);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setM(const LargeSafeUnion& myUnion, BitField m, setL_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setM(myUnion, " << toString(m) << ")";
+
+    LargeSafeUnion myNewUnion = myUnion;
+    myNewUnion.m(m);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setN(const LargeSafeUnion& myUnion, hidl_bitfield<BitField> n,
+                             setL_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setN(myUnion, " << n << ")";
+
+    LargeSafeUnion myNewUnion = myUnion;
+    myNewUnion.n(n);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::newInterfaceTypeSafeUnion(newInterfaceTypeSafeUnion_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) newInterfaceTypeSafeUnion()";
+
+    InterfaceTypeSafeUnion ret;
+    _hidl_cb(ret);
+    return Void();
+}
+
+Return<void> SafeUnion::setInterfaceA(const InterfaceTypeSafeUnion& myUnion, uint32_t a, setInterfaceA_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setInterfaceA(myUnion, " << a << ")";
+
+    InterfaceTypeSafeUnion myNewUnion = myUnion;
+    myNewUnion.a(a);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setInterfaceB(const InterfaceTypeSafeUnion& myUnion, const hidl_array<int8_t, 7>& b, setInterfaceB_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setInterfaceB(myUnion, " << toString(b) << ")";
+
+    InterfaceTypeSafeUnion myNewUnion = myUnion;
+    myNewUnion.b(b);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setInterfaceC(const InterfaceTypeSafeUnion& myUnion, const sp<::android::hardware::tests::safeunion::V1_0::IOtherInterface>& c, setInterfaceC_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setInterfaceC(myUnion, " << toString(c) << ")";
+
+    InterfaceTypeSafeUnion myNewUnion = myUnion;
+    myNewUnion.c(c);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setInterfaceD(const InterfaceTypeSafeUnion& myUnion, const hidl_string& d,
+                                      setInterfaceD_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setInterfaceD(myUnion, " << toString(d) << ")";
+
+    InterfaceTypeSafeUnion myNewUnion = myUnion;
+    myNewUnion.d(d);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setInterfaceE(const InterfaceTypeSafeUnion& myUnion,
+                                      const hidl_vec<hidl_string>& e, setInterfaceE_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setInterfaceE(myUnion, " << toString(e) << ")";
+
+    InterfaceTypeSafeUnion myNewUnion = myUnion;
+    myNewUnion.e(e);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setInterfaceF(const InterfaceTypeSafeUnion& myUnion, const hidl_handle& f,
+                                      setInterfaceF_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setInterfaceF(myUnion, " << toString(f) << ")";
+
+    InterfaceTypeSafeUnion myNewUnion = myUnion;
+    myNewUnion.f(f);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setInterfaceG(const InterfaceTypeSafeUnion& myUnion,
+                                      const hidl_vec<hidl_handle>& g, setInterfaceG_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setInterfaceG(myUnion, " << toString(g) << ")";
+
+    InterfaceTypeSafeUnion myNewUnion = myUnion;
+    myNewUnion.g(g);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::newHandleTypeSafeUnion(newHandleTypeSafeUnion_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) newHandleTypeSafeUnion()";
+
+    HandleTypeSafeUnion ret;
+    _hidl_cb(ret);
+    return Void();
+}
+
+Return<void> SafeUnion::setHandleA(
+    const ::android::hardware::tests::safeunion::V1_0::ISafeUnion::HandleTypeSafeUnion& myUnion,
+    const hidl_handle& a, setHandleA_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setHandleA(myUnion, " << toString(a) << ")";
+
+    HandleTypeSafeUnion myNewUnion = myUnion;
+    myNewUnion.a(a);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setHandleB(const HandleTypeSafeUnion& myUnion,
+                                   const hidl_array<hidl_handle, 5>& b, setHandleB_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setHandleB(myUnion, " << toString(b) << ")";
+
+    HandleTypeSafeUnion myNewUnion = myUnion;
+    myNewUnion.b(b);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+Return<void> SafeUnion::setHandleC(const HandleTypeSafeUnion& myUnion,
+                                   const hidl_vec<hidl_handle>& c, setHandleC_cb _hidl_cb) {
+    LOG(INFO) << "SERVER(SafeUnion) setHandleC(myUnion, " << toString(c) << ")";
+
+    HandleTypeSafeUnion myNewUnion = myUnion;
+    myNewUnion.c(c);
+
+    _hidl_cb(myNewUnion);
+    return Void();
+}
+
+ISafeUnion* HIDL_FETCH_ISafeUnion(const char* /* name */) {
+    return new SafeUnion();
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace safeunion
+}  // namespace tests
+}  // namespace hardware
+}  // namespace android
diff --git a/tests/safeunion/1.0/default/SafeUnion.h b/tests/safeunion/1.0/default/SafeUnion.h
new file mode 100644
index 0000000..ee3a954
--- /dev/null
+++ b/tests/safeunion/1.0/default/SafeUnion.h
@@ -0,0 +1,83 @@
+/*
+ * 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_TESTS_SAFEUNION_V1_0_SAFEUNION_H
+#define ANDROID_HARDWARE_TESTS_SAFEUNION_V1_0_SAFEUNION_H
+
+#include <android/hardware/tests/safeunion/1.0/ISafeUnion.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace tests {
+namespace safeunion {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::tests::safeunion::V1_0::ISafeUnion;
+
+struct SafeUnion : public ISafeUnion {
+    // Methods from ::android::hardware::tests::safeunion::V1_0::ISafeUnion follow.
+    Return<void> newLargeSafeUnion(newLargeSafeUnion_cb _hidl_cb) override;
+    Return<void> setA(const LargeSafeUnion& myUnion, int8_t a, setA_cb _hidl_cb) override;
+    Return<void> setB(const LargeSafeUnion& myUnion, uint16_t b, setB_cb _hidl_cb) override;
+    Return<void> setC(const LargeSafeUnion& myUnion, int32_t c, setC_cb _hidl_cb) override;
+    Return<void> setD(const LargeSafeUnion& myUnion, uint64_t d, setD_cb _hidl_cb) override;
+    Return<void> setE(const LargeSafeUnion& myUnion, const hidl_array<int8_t, 13>& e, setE_cb _hidl_cb) override;
+    Return<void> setF(const LargeSafeUnion& myUnion, const hidl_array<int64_t, 5>& f, setF_cb _hidl_cb) override;
+    Return<void> setG(const LargeSafeUnion& myUnion, const hidl_string& g, setG_cb _hidl_cb) override;
+    Return<void> setH(const LargeSafeUnion& myUnion, const hidl_vec<bool>& h, setH_cb _hidl_cb) override;
+    Return<void> setI(const LargeSafeUnion& myUnion, const hidl_vec<uint64_t>& i, setI_cb _hidl_cb) override;
+    Return<void> setJ(const LargeSafeUnion& myUnion, const J& j, setJ_cb _hidl_cb) override;
+    Return<void> setK(const LargeSafeUnion& myUnion, const LargeSafeUnion::K& k, setK_cb _hidl_cb) override;
+    Return<void> setL(const LargeSafeUnion& myUnion, const SmallSafeUnion& l, setL_cb _hidl_cb) override;
+    Return<void> setM(const LargeSafeUnion& myUnion, BitField m, setL_cb _hidl_cb) override;
+    Return<void> setN(const LargeSafeUnion& myUnion, hidl_bitfield<BitField> n,
+                      setL_cb _hidl_cb) override;
+
+    Return<void> newInterfaceTypeSafeUnion(newInterfaceTypeSafeUnion_cb _hidl_cb) override;
+    Return<void> setInterfaceA(const InterfaceTypeSafeUnion& myUnion, uint32_t a, setInterfaceA_cb _hidl_cb) override;
+    Return<void> setInterfaceB(const InterfaceTypeSafeUnion& myUnion, const hidl_array<int8_t, 7>& b, setInterfaceB_cb _hidl_cb) override;
+    Return<void> setInterfaceC(const InterfaceTypeSafeUnion& myUnion, const sp<::android::hardware::tests::safeunion::V1_0::IOtherInterface>& c, setInterfaceC_cb _hidl_cb) override;
+    Return<void> setInterfaceD(const InterfaceTypeSafeUnion& myUnion, const hidl_string& d, setInterfaceD_cb _hidl_cb) override;
+    Return<void> setInterfaceE(const InterfaceTypeSafeUnion& myUnion, const hidl_vec<hidl_string>& e, setInterfaceE_cb _hidl_cb) override;
+    Return<void> setInterfaceF(const InterfaceTypeSafeUnion& myUnion, const hidl_handle& f,
+                               setInterfaceF_cb _hidl_cb) override;
+    Return<void> setInterfaceG(const InterfaceTypeSafeUnion& myUnion,
+                               const hidl_vec<hidl_handle>& g, setInterfaceG_cb _hidl_cb) override;
+
+    Return<void> newHandleTypeSafeUnion(newHandleTypeSafeUnion_cb _hidl_cb) override;
+    Return<void> setHandleA(const HandleTypeSafeUnion& myUnion, const hidl_handle& a,
+                            setHandleA_cb _hidl_cb) override;
+    Return<void> setHandleB(const HandleTypeSafeUnion& myUnion, const hidl_array<hidl_handle, 5>& b,
+                            setHandleB_cb _hidl_cb) override;
+    Return<void> setHandleC(const HandleTypeSafeUnion& myUnion, const hidl_vec<hidl_handle>& c,
+                            setHandleC_cb _hidl_cb) override;
+};
+
+extern "C" ISafeUnion* HIDL_FETCH_ISafeUnion(const char* name);
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace safeunion
+}  // namespace tests
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_TESTS_SAFEUNION_V1_0_SAFEUNION_H
diff --git a/tetheroffload/config/1.0/Android.bp b/tetheroffload/config/1.0/Android.bp
index 9d0dc5f..f20d77c 100644
--- a/tetheroffload/config/1.0/Android.bp
+++ b/tetheroffload/config/1.0/Android.bp
@@ -12,6 +12,6 @@
     interfaces: [
         "android.hidl.base@1.0",
     ],
-    gen_java: false,
+    gen_java: true,
 }
 
diff --git a/usb/1.1/types.hal b/usb/1.1/types.hal
index 2261e09..c9cc292 100644
--- a/usb/1.1/types.hal
+++ b/usb/1.1/types.hal
@@ -18,6 +18,8 @@
 
 import android.hardware.usb@1.0;
 
+// NOTE: suffix '_1_1' is for legacy ABI compatibility. It cannot be
+// changed to 'PortMode' which the convention dictates.
 @export
 enum PortMode_1_1 : PortMode {
     /*
@@ -37,6 +39,8 @@
  * Used as the container to report data back to the caller.
  * Represents the current connection status of a single USB port.
  */
+// NOTE: suffix '_1_1' is for legacy ABI compatibility. It cannot be
+// changed to 'PortStatus' which the convention dictates.
 struct PortStatus_1_1 {
     /*
      * The supportedModes and the currentMode fields of the status
diff --git a/vibrator/1.1/types.hal b/vibrator/1.1/types.hal
index f7a619a..72deb4a 100644
--- a/vibrator/1.1/types.hal
+++ b/vibrator/1.1/types.hal
@@ -18,6 +18,8 @@
 
 import @1.0::Effect;
 
+// NOTE: suffix '_1_1' is for legacy ABI compatibility. It cannot be
+// changed to 'Effect' which the convention dictates.
 @export
 enum Effect_1_1 : @1.0::Effect {
     /**
diff --git a/vibrator/1.2/vts/functional/VtsHalVibratorV1_2TargetTest.cpp b/vibrator/1.2/vts/functional/VtsHalVibratorV1_2TargetTest.cpp
index 3ed689a..d69695a 100644
--- a/vibrator/1.2/vts/functional/VtsHalVibratorV1_2TargetTest.cpp
+++ b/vibrator/1.2/vts/functional/VtsHalVibratorV1_2TargetTest.cpp
@@ -28,7 +28,7 @@
 using ::android::hardware::vibrator::V1_0::EffectStrength;
 using ::android::hardware::vibrator::V1_2::Effect;
 using ::android::hardware::vibrator::V1_2::IVibrator;
-using ::android::hardware::hidl_enum_iterator;
+using ::android::hardware::hidl_enum_range;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
 using ::android::sp;
@@ -86,8 +86,8 @@
  * a valid duration, or are unsupported and return UNSUPPORTED_OPERATION with a duration of 0.
  */
 TEST_F(VibratorHidlTest_1_2, PerformEffect_1_2) {
-    for (const auto& effect : hidl_enum_iterator<Effect>()) {
-        for (const auto& strength : hidl_enum_iterator<EffectStrength>()) {
+    for (const auto& effect : hidl_enum_range<Effect>()) {
+        for (const auto& strength : hidl_enum_range<EffectStrength>()) {
             EXPECT_OK(vibrator->perform_1_2(effect, strength, validatePerformEffect));
         }
     }
@@ -97,7 +97,7 @@
  * Test to make sure effect values above the valid range are rejected.
  */
 TEST_F(VibratorHidlTest_1_2, PerformEffect_1_2_BadEffects_AboveValidRange) {
-    Effect effect = *std::prev(hidl_enum_iterator<Effect>().end());
+    Effect effect = *std::prev(hidl_enum_range<Effect>().end());
     Effect badEffect = static_cast<Effect>(static_cast<int32_t>(effect) + 1);
     EXPECT_OK(
         vibrator->perform_1_2(badEffect, EffectStrength::LIGHT, validatePerformEffectBadInput));
@@ -107,7 +107,7 @@
  * Test to make sure effect values below the valid range are rejected.
  */
 TEST_F(VibratorHidlTest_1_2, PerformEffect_1_2_BadEffects_BelowValidRange) {
-    Effect effect = *hidl_enum_iterator<Effect>().begin();
+    Effect effect = *hidl_enum_range<Effect>().begin();
     Effect badEffect = static_cast<Effect>(static_cast<int32_t>(effect) - 1);
     EXPECT_OK(
         vibrator->perform_1_2(badEffect, EffectStrength::LIGHT, validatePerformEffectBadInput));
@@ -117,7 +117,7 @@
  * Test to make sure strength values above the valid range are rejected.
  */
 TEST_F(VibratorHidlTest_1_2, PerformEffect_1_2_BadStrength_AboveValidRange) {
-    EffectStrength strength = *std::prev(hidl_enum_iterator<EffectStrength>().end());
+    EffectStrength strength = *std::prev(hidl_enum_range<EffectStrength>().end());
     EffectStrength badStrength = static_cast<EffectStrength>(static_cast<int32_t>(strength) + 1);
     EXPECT_OK(vibrator->perform_1_2(Effect::THUD, badStrength, validatePerformEffectBadInput));
 }
@@ -126,7 +126,7 @@
  * Test to make sure strength values below the valid range are rejected.
  */
 TEST_F(VibratorHidlTest_1_2, PerformEffect_1_2_BadStrength_BelowValidRange) {
-    EffectStrength strength = *hidl_enum_iterator<EffectStrength>().begin();
+    EffectStrength strength = *hidl_enum_range<EffectStrength>().begin();
     EffectStrength badStrength = static_cast<EffectStrength>(static_cast<int32_t>(strength) - 1);
     EXPECT_OK(vibrator->perform_1_2(Effect::THUD, badStrength, validatePerformEffectBadInput));
 }
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index b2f76a3..6522f4d 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -16,7 +16,7 @@
 
 cc_library_static {
     name: "VtsHalWifiV1_0TargetTestUtil",
-    defaults: ["hidl_defaults"],
+    defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
         "wifi_hidl_call_util_selftest.cpp",
         "wifi_hidl_test.cpp",
@@ -26,16 +26,9 @@
         "."
     ],
     shared_libs: [
-        "libbase",
-        "liblog",
-        "libcutils",
-        "libhidlbase",
-        "libhidltransport",
         "libnativehelper",
-        "libutils",
-        "android.hardware.wifi@1.0",
     ],
-    static_libs: ["VtsHalHidlTargetTestBase"],
+    static_libs: ["android.hardware.wifi@1.0"],
 }
 
 cc_test {
diff --git a/wifi/1.2/default/wifi_legacy_hal.h b/wifi/1.2/default/wifi_legacy_hal.h
index 60905ab..00dfeef 100644
--- a/wifi/1.2/default/wifi_legacy_hal.h
+++ b/wifi/1.2/default/wifi_legacy_hal.h
@@ -25,6 +25,12 @@
 
 #include <wifi_system/interface_tool.h>
 
+// HACK: The include inside the namespace below also transitively includes a
+// bunch of libc headers into the namespace, which leads to functions like
+// socketpair being defined in android::hardware::wifi::V1_1::implementation::legacy_hal.
+// Include this one particular header as a hacky workaround until that's fixed.
+#include <sys/socket.h>
+
 namespace android {
 namespace hardware {
 namespace wifi {