Merge "Initial commit of public Codec2 HIDL interfaces"
diff --git a/health/filesystem/1.0/Android.bp b/atrace/1.0/Android.bp
similarity index 71%
copy from health/filesystem/1.0/Android.bp
copy to atrace/1.0/Android.bp
index 74b9bc3..f7c9078 100644
--- a/health/filesystem/1.0/Android.bp
+++ b/atrace/1.0/Android.bp
@@ -1,20 +1,21 @@
 // This file is autogenerated by hidl-gen -Landroidbp.
 
 hidl_interface {
-    name: "android.hardware.health.filesystem@1.0",
+    name: "android.hardware.atrace@1.0",
     root: "android.hardware",
     vndk: {
         enabled: true,
     },
     srcs: [
         "types.hal",
-        "IFileSystem.hal",
+        "IAtraceDevice.hal",
     ],
     interfaces: [
         "android.hidl.base@1.0",
     ],
     types: [
-        "Result",
+        "Status",
+        "TracingCategory",
     ],
     gen_java: true,
 }
diff --git a/atrace/1.0/IAtraceDevice.hal b/atrace/1.0/IAtraceDevice.hal
new file mode 100644
index 0000000..b6e78b4
--- /dev/null
+++ b/atrace/1.0/IAtraceDevice.hal
@@ -0,0 +1,51 @@
+/*
+ * 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.atrace@1.0;
+
+interface IAtraceDevice {
+    /**
+     * Get vendor extended atrace points.
+     *
+     *
+     * @return categories of tracing points the device extended.
+     */
+    listCategories() generates (vec<TracingCategory> categories);
+
+    /**
+     * A hook when atrace set to enable specific categories, so HAL
+     * can enable kernel tracing points and/or notify other things
+     * for userspace tracing turning on.
+     *
+     * @param categories A vector of strings of categories (corresponding to
+     *        TracingCategory.name) atrace needs to be enabled.
+     *
+     * @return status SUCCESS on success,
+     *         ERROR_TRACING_POINT on error with enabling categories,
+     *         ERROR_INVALID_ARGUMENT on invalid argument passed.
+     */
+    enableCategories(vec<string> categories) generates (Status status);
+
+    /**
+     * A hook when atrace set to clean up tracing categories, so HAL
+     * can disable all kernel tracing points and/or notify other things
+     * for userspace tracing turning off.
+     *
+     * @return status SUCCESS on success,
+     *         ERROR_TRACING_POINT on error with disabling categories.
+     */
+    disableAllCategories() generates (Status status);
+};
diff --git a/atrace/1.0/default/Android.bp b/atrace/1.0/default/Android.bp
new file mode 100644
index 0000000..bcaf064
--- /dev/null
+++ b/atrace/1.0/default/Android.bp
@@ -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.
+
+cc_binary {
+    name: "android.hardware.atrace@1.0-service",
+    defaults: ["hidl_defaults"],
+    relative_install_path: "hw",
+    vendor: true,
+    init_rc: ["android.hardware.atrace@1.0-service.rc"],
+    vintf_fragments: ["android.hardware.atrace@1.0-service.xml"],
+    srcs: [
+        "AtraceDevice.cpp",
+        "service.cpp",
+    ],
+    shared_libs: [
+        "liblog",
+        "libbase",
+        "libutils",
+        "libhidlbase",
+        "libhidltransport",
+        "android.hardware.atrace@1.0",
+    ],
+}
diff --git a/atrace/1.0/default/AtraceDevice.cpp b/atrace/1.0/default/AtraceDevice.cpp
new file mode 100644
index 0000000..43bcd9a
--- /dev/null
+++ b/atrace/1.0/default/AtraceDevice.cpp
@@ -0,0 +1,110 @@
+/*
+ * 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 <android-base/file.h>
+#include <android-base/logging.h>
+
+#include "AtraceDevice.h"
+
+namespace android {
+namespace hardware {
+namespace atrace {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::hardware::atrace::V1_0::Status;
+using ::android::hardware::atrace::V1_0::TracingCategory;
+
+struct TracingConfig {
+    std::string description;
+    std::vector<std::pair<std::string, bool>> paths;
+};
+
+// This is a map stores categories and their sysfs paths with required flags
+const std::map<std::string, TracingConfig> kTracingMap = {
+    // gfx
+    {
+        "gfx",
+        {"Graphics",
+         {{"/sys/kernel/debug/tracing/events/mdss/enable", false},
+          {"/sys/kernel/debug/tracing/events/sde/enable", false},
+          {"/sys/kernel/debug/tracing/events/mali_systrace/enable", false}}},
+    },
+    {
+        "ion",
+        {"ION allocation",
+         {{"/sys/kernel/debug/tracing/events/kmem/ion_alloc_buffer_start/enable", true}}},
+    },
+};
+
+// Methods from ::android::hardware::atrace::V1_0::IAtraceDevice follow.
+Return<void> AtraceDevice::listCategories(listCategories_cb _hidl_cb) {
+    hidl_vec<TracingCategory> categories;
+    categories.resize(kTracingMap.size());
+    std::size_t i = 0;
+    for (auto& c : kTracingMap) {
+        categories[i].name = c.first;
+        categories[i].description = c.second.description;
+        i++;
+    }
+    _hidl_cb(categories);
+    return Void();
+}
+
+Return<::android::hardware::atrace::V1_0::Status> AtraceDevice::enableCategories(
+    const hidl_vec<hidl_string>& categories) {
+    if (!categories.size()) {
+        return Status::ERROR_INVALID_ARGUMENT;
+    }
+    for (auto& c : categories) {
+        if (kTracingMap.count(c)) {
+            for (auto& p : kTracingMap.at(c).paths) {
+                if (!android::base::WriteStringToFile("1", p.first)) {
+                    LOG(ERROR) << "Failed to enable tracing on: " << p.first;
+                    if (p.second) {
+                        // disable before return
+                        disableAllCategories();
+                        return Status::ERROR_TRACING_POINT;
+                    }
+                }
+            }
+        } else {
+            return Status::ERROR_INVALID_ARGUMENT;
+        }
+    }
+    return Status::SUCCESS;
+}
+
+Return<::android::hardware::atrace::V1_0::Status> AtraceDevice::disableAllCategories() {
+    auto ret = Status::SUCCESS;
+    for (auto& c : kTracingMap) {
+        for (auto& p : c.second.paths) {
+            if (!android::base::WriteStringToFile("0", p.first)) {
+                LOG(ERROR) << "Failed to enable tracing on: " << p.first;
+                if (p.second) {
+                    ret = Status::ERROR_TRACING_POINT;
+                }
+            }
+        }
+    }
+    return ret;
+}
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace atrace
+}  // namespace hardware
+}  // namespace android
diff --git a/atrace/1.0/default/AtraceDevice.h b/atrace/1.0/default/AtraceDevice.h
new file mode 100644
index 0000000..e700f89
--- /dev/null
+++ b/atrace/1.0/default/AtraceDevice.h
@@ -0,0 +1,54 @@
+/*
+ * 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_ATRACE_V1_0_ATRACEDEVICE_H
+#define ANDROID_HARDWARE_ATRACE_V1_0_ATRACEDEVICE_H
+
+#include <android/hardware/atrace/1.0/IAtraceDevice.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace atrace {
+namespace V1_0 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::hidl_array;
+using ::android::hardware::hidl_memory;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+struct AtraceDevice : public IAtraceDevice {
+    // Methods from ::android::hardware::atrace::V1_0::IAtraceDevice follow.
+    Return<void> listCategories(listCategories_cb _hidl_cb) override;
+    Return<::android::hardware::atrace::V1_0::Status> enableCategories(
+        const hidl_vec<hidl_string>& categories) override;
+    Return<::android::hardware::atrace::V1_0::Status> disableAllCategories() override;
+
+    // Methods from ::android::hidl::base::V1_0::IBase follow.
+};
+
+}  // namespace implementation
+}  // namespace V1_0
+}  // namespace atrace
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_ATRACE_V1_0_ATRACEDEVICE_H
diff --git a/atrace/1.0/default/android.hardware.atrace@1.0-service.rc b/atrace/1.0/default/android.hardware.atrace@1.0-service.rc
new file mode 100644
index 0000000..eb54c39
--- /dev/null
+++ b/atrace/1.0/default/android.hardware.atrace@1.0-service.rc
@@ -0,0 +1,13 @@
+on late-init
+    # vendor graphics trace points
+    chmod 0666 /sys/kernel/debug/tracing/events/sde/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/mdss/enable
+    chmod 0666 /sys/kernel/debug/tracing/events/mali_systrace/enable
+    # ion allocation trace point
+    chmod 0666 /sys/kernel/debug/tracing/events/kmem/ion_alloc_buffer_start/enable
+
+service vendor.atrace-hal-1-0 /vendor/bin/hw/android.hardware.atrace@1.0-service
+    interface android.hardware.atrace@1.0::IAtraceDevice default
+    class early_hal
+    user system
+    group system
diff --git a/atrace/1.0/default/android.hardware.atrace@1.0-service.xml b/atrace/1.0/default/android.hardware.atrace@1.0-service.xml
new file mode 100644
index 0000000..fd3631c
--- /dev/null
+++ b/atrace/1.0/default/android.hardware.atrace@1.0-service.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.atrace</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IAtraceDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/atrace/1.0/default/service.cpp b/atrace/1.0/default/service.cpp
new file mode 100644
index 0000000..662fd73
--- /dev/null
+++ b/atrace/1.0/default/service.cpp
@@ -0,0 +1,44 @@
+/*
+ * 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 "android.hardware.atrace@1.0-service"
+
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "AtraceDevice.h"
+
+using ::android::OK;
+using ::android::sp;
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::joinRpcThreadpool;
+using ::android::hardware::atrace::V1_0::IAtraceDevice;
+using ::android::hardware::atrace::V1_0::Status;
+using ::android::hardware::atrace::V1_0::TracingCategory;
+using ::android::hardware::atrace::V1_0::implementation::AtraceDevice;
+
+int main(int /* argc */, char* /* argv */ []) {
+    sp<IAtraceDevice> atrace = new AtraceDevice;
+    configureRpcThreadpool(1, true /* will join */);
+    if (atrace->registerAsService() != OK) {
+        ALOGE("Could not register service.");
+        return 1;
+    }
+    joinRpcThreadpool();
+
+    ALOGE("Service exited!");
+    return 1;
+}
diff --git a/health/filesystem/1.0/types.hal b/atrace/1.0/types.hal
similarity index 60%
copy from health/filesystem/1.0/types.hal
copy to atrace/1.0/types.hal
index 00431f7..f137ef6 100644
--- a/health/filesystem/1.0/types.hal
+++ b/atrace/1.0/types.hal
@@ -14,26 +14,30 @@
  * limitations under the License.
  */
 
-package android.hardware.health.filesystem@1.0;
+package android.hardware.atrace@1.0;
 
-/**
- * Status values for HAL methods.
- */
-enum Result : uint32_t {
+enum Status : uint32_t {
     /**
-     * Execution of the method is successful.
+     * Operation completed without errors.
      */
     SUCCESS = 0,
     /**
-     * Execution of the method timed out.
+     * Operation failed with errors on enabling tracing point.
      */
-    TIMEOUT,
+    ERROR_TRACING_POINT = 1,
     /**
-     * An IO error is encountered when the HAL communicates with the device.
+     * Operation failed because of invalid argument.
      */
-    IO_ERROR,
+    ERROR_INVALID_ARGUMENT = 2
+};
+
+struct TracingCategory {
     /**
-     * An unknown error is encountered.
+     * Tracing category name, unique to frameworks's category.
      */
-    UNKNOWN_ERROR,
+    string name;
+    /**
+     * Tracing category description.
+     */
+    string description;
 };
diff --git a/atrace/1.0/vts/functional/Android.bp b/atrace/1.0/vts/functional/Android.bp
new file mode 100644
index 0000000..6b50fb5
--- /dev/null
+++ b/atrace/1.0/vts/functional/Android.bp
@@ -0,0 +1,22 @@
+//
+// 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: "VtsHalAtraceV1_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalAtraceV1_0TargetTest.cpp"],
+    static_libs: ["android.hardware.atrace@1.0"],
+}
diff --git a/atrace/1.0/vts/functional/VtsHalAtraceV1_0TargetTest.cpp b/atrace/1.0/vts/functional/VtsHalAtraceV1_0TargetTest.cpp
new file mode 100644
index 0000000..c62c2f0
--- /dev/null
+++ b/atrace/1.0/vts/functional/VtsHalAtraceV1_0TargetTest.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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 <unordered_set>
+
+#include <android/hardware/atrace/1.0/IAtraceDevice.h>
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::atrace::V1_0::IAtraceDevice;
+using ::android::hardware::atrace::V1_0::Status;
+
+// Test environment for Boot HIDL HAL.
+class AtraceHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static AtraceHidlEnvironment* Instance() {
+        static AtraceHidlEnvironment* instance = new AtraceHidlEnvironment;
+        return instance;
+    }
+
+    virtual void registerTestServices() override { registerTestService<IAtraceDevice>(); }
+
+   private:
+    AtraceHidlEnvironment() {}
+};
+
+/**
+ * There is no expected behaviour that can be tested so these tests check the
+ * HAL doesn't crash with different execution orders.
+ */
+struct AtraceHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+    virtual void SetUp() override {
+        atrace = ::testing::VtsHalHidlTargetTestBase::getService<IAtraceDevice>(
+            AtraceHidlEnvironment::Instance()->getServiceName<IAtraceDevice>());
+        ASSERT_NE(atrace, nullptr);
+    }
+
+    sp<IAtraceDevice> atrace;
+};
+
+hidl_vec<hidl_string> getVendorCategoryName(sp<IAtraceDevice> atrace) {
+    std::unordered_set<std::string> categories_set;
+    Return<void> ret = atrace->listCategories([&](const auto& list) {
+        for (const auto& category : list) {
+            std::string name = category.name;
+            if (categories_set.count(name)) {
+                ADD_FAILURE() << "Duplicate category: " << name;
+            } else {
+                categories_set.emplace(name);
+            }
+        }
+    });
+    if (!ret.isOk()) {
+        ADD_FAILURE();
+    }
+    hidl_vec<hidl_string> categories;
+    categories.resize(categories_set.size());
+    std::size_t i = 0;
+    for (auto& c : categories_set) {
+        categories[i++] = c;
+    }
+    return categories;
+}
+
+/* list categories from vendors. */
+TEST_F(AtraceHidlTest, listCategories) {
+    hidl_vec<hidl_string> vnd_categories = getVendorCategoryName(atrace);
+    EXPECT_NE(0, vnd_categories.size());
+}
+
+/* enable categories. */
+TEST_F(AtraceHidlTest, enableCategories) {
+    hidl_vec<hidl_string> vnd_categories = getVendorCategoryName(atrace);
+    // empty Category with ERROR_INVALID_ARGUMENT
+    hidl_vec<hidl_string> empty_categories;
+    auto ret = atrace->enableCategories(empty_categories);
+    ASSERT_TRUE(ret.isOk());
+    EXPECT_EQ(Status::ERROR_INVALID_ARGUMENT, ret);
+    // non-empty categories SUCCESS
+    ret = atrace->enableCategories(vnd_categories);
+    ASSERT_TRUE(ret.isOk());
+    EXPECT_EQ(Status::SUCCESS, ret);
+}
+
+/* enable categories. */
+TEST_F(AtraceHidlTest, disableAllCategories) {
+    auto ret = atrace->disableAllCategories();
+    ASSERT_TRUE(ret.isOk());
+    EXPECT_EQ(Status::SUCCESS, ret);
+}
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(AtraceHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    AtraceHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
+}
diff --git a/audio/4.1/config/audio_policy_configuration.xsd b/audio/4.1/config/audio_policy_configuration.xsd
new file mode 100644
index 0000000..311b9c1
--- /dev/null
+++ b/audio/4.1/config/audio_policy_configuration.xsd
@@ -0,0 +1,595 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Copyright (C) 2017 The Android Open Source Project
+
+         Licensed under the Apache License, Version 2.0 (the "License");
+         you may not use this file except in compliance with the License.
+         You may obtain a copy of the License at
+
+                    http://www.apache.org/licenses/LICENSE-2.0
+
+         Unless required by applicable law or agreed to in writing, software
+         distributed under the License is distributed on an "AS IS" BASIS,
+         WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+         See the License for the specific language governing permissions and
+         limitations under the License.
+-->
+<!-- TODO: define a targetNamespace. Note that it will break retrocompatibility -->
+<xs:schema version="2.0"
+           elementFormDefault="qualified"
+           attributeFormDefault="unqualified"
+           xmlns:xs="http://www.w3.org/2001/XMLSchema">
+    <!-- List the config versions supported by audio policy. -->
+    <xs:simpleType name="version">
+        <xs:restriction base="xs:decimal">
+            <xs:enumeration value="1.0"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="halVersion">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Version of the interface the hal implements.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:decimal">
+            <!-- List of HAL versions supported by the framework. -->
+            <xs:enumeration value="2.0"/>
+            <xs:enumeration value="3.0"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:element name="audioPolicyConfiguration">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element name="globalConfiguration" type="globalConfiguration"/>
+                <xs:element name="modules" type="modules" maxOccurs="unbounded"/>
+                <xs:element name="volumes" type="volumes" maxOccurs="unbounded"/>
+                <xs:element name="surroundSound" type="surroundSound" />
+            </xs:sequence>
+            <xs:attribute name="version" type="version"/>
+        </xs:complexType>
+        <xs:key name="moduleNameKey">
+            <xs:selector xpath="modules/module"/>
+            <xs:field xpath="@name"/>
+        </xs:key>
+        <xs:unique name="volumeTargetUniqueness">
+            <xs:selector xpath="volumes/volume"/>
+            <xs:field xpath="@stream"/>
+            <xs:field xpath="@deviceCategory"/>
+        </xs:unique>
+        <xs:key name="volumeCurveNameKey">
+            <xs:selector xpath="volumes/reference"/>
+            <xs:field xpath="@name"/>
+        </xs:key>
+        <xs:keyref name="volumeCurveRef" refer="volumeCurveNameKey">
+            <xs:selector xpath="volumes/volume"/>
+            <xs:field xpath="@ref"/>
+        </xs:keyref>
+    </xs:element>
+    <xs:complexType name="globalConfiguration">
+        <xs:attribute name="speaker_drc_enabled" type="xs:boolean" use="required"/>
+    </xs:complexType>
+    <xs:complexType name="modules">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                There should be one section per audio HW module present on the platform.
+                Each <module/> contains two mandatory tags: “halVersion” and “name”.
+                The module "name" is the same as in previous .conf file.
+                Each module must contain the following sections:
+                 - <devicePorts/>: a list of device descriptors for all
+                   input and output devices accessible via this module.
+                   This contains both permanently attached devices and removable devices.
+                 - <mixPorts/>: listing all output and input streams exposed by the audio HAL
+                 - <routes/>: list of possible connections between input
+                   and output devices or between stream and devices.
+                   A <route/> is defined by a set of 3 attributes:
+                        -"type": mux|mix means all sources are mutual exclusive (mux) or can be mixed (mix)
+                        -"sink": the sink involved in this route
+                        -"sources": all the sources than can be connected to the sink via this route
+                 - <attachedDevices/>: permanently attached devices.
+                   The attachedDevices section is a list of devices names.
+                   Their names correspond to device names defined in "devicePorts" section.
+                 - <defaultOutputDevice/> is the device to be used when no policy rule applies
+            </xs:documentation>
+        </xs:annotation>
+        <xs:sequence>
+            <xs:element name="module" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="attachedDevices" type="attachedDevices" minOccurs="0">
+                            <xs:unique name="attachedDevicesUniqueness">
+                                <xs:selector xpath="item"/>
+                                <xs:field xpath="."/>
+                            </xs:unique>
+                        </xs:element>
+                        <xs:element name="defaultOutputDevice" type="xs:token" minOccurs="0"/>
+                        <xs:element name="mixPorts" type="mixPorts" minOccurs="0"/>
+                        <xs:element name="devicePorts" type="devicePorts" minOccurs="0"/>
+                        <xs:element name="routes" type="routes" minOccurs="0"/>
+                    </xs:sequence>
+                    <xs:attribute name="name" type="xs:string" use="required"/>
+                    <xs:attribute name="halVersion" type="halVersion" use="required"/>
+                </xs:complexType>
+                <xs:unique name="mixPortNameUniqueness">
+                    <xs:selector xpath="mixPorts/mixPort"/>
+                    <xs:field xpath="@name"/>
+                </xs:unique>
+                <xs:key name="devicePortNameKey">
+                    <xs:selector xpath="devicePorts/devicePort"/>
+                    <xs:field xpath="@tagName"/>
+                </xs:key>
+                <xs:unique name="devicePortUniqueness">
+                    <xs:selector xpath="devicePorts/devicePort"/>
+                    <xs:field xpath="@type"/>
+                    <xs:field xpath="@address"/>
+                </xs:unique>
+                <xs:keyref name="defaultOutputDeviceRef" refer="devicePortNameKey">
+                    <xs:selector xpath="defaultOutputDevice"/>
+                    <xs:field xpath="."/>
+                </xs:keyref>
+                <xs:keyref name="attachedDeviceRef" refer="devicePortNameKey">
+                    <xs:selector xpath="attachedDevices/item"/>
+                    <xs:field xpath="."/>
+                </xs:keyref>
+                <!-- The following 3 constraints try to make sure each sink port
+                     is reference in one an only one route. -->
+                <xs:key name="routeSinkKey">
+                    <!-- predicate [@type='sink'] does not work in xsd 1.0 -->
+                    <xs:selector xpath="devicePorts/devicePort|mixPorts/mixPort"/>
+                    <xs:field xpath="@tagName|@name"/>
+                </xs:key>
+                <xs:keyref name="routeSinkRef" refer="routeSinkKey">
+                    <xs:selector xpath="routes/route"/>
+                    <xs:field xpath="@sink"/>
+                </xs:keyref>
+                <xs:unique name="routeUniqueness">
+                    <xs:selector xpath="routes/route"/>
+                    <xs:field xpath="@sink"/>
+                </xs:unique>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="attachedDevices">
+        <xs:sequence>
+            <xs:element name="item" type="xs:token" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+    </xs:complexType>
+    <!-- TODO: separate values by space for better xsd validations. -->
+    <xs:simpleType name="audioInOutFlags">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                "|" separated list of audio_output_flags_t or audio_input_flags_t.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:pattern value="|[_A-Z]+(\|[_A-Z]+)*"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="role">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="sink"/>
+            <xs:enumeration value="source"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="mixPorts">
+        <xs:sequence>
+            <xs:element name="mixPort" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="profile" type="profile" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="gains" type="gains" minOccurs="0"/>
+                    </xs:sequence>
+                    <xs:attribute name="name" type="xs:token" use="required"/>
+                    <xs:attribute name="role" type="role" use="required"/>
+                    <xs:attribute name="flags" type="audioInOutFlags"/>
+                    <xs:attribute name="maxOpenCount" type="xs:unsignedInt"/>
+                    <xs:attribute name="maxActiveCount" type="xs:unsignedInt"/>
+                    <xs:attribute name="preferredUsage" type="audioUsageList">
+                        <xs:annotation>
+                            <xs:documentation xml:lang="en">
+                                When choosing the mixPort of an audio track, the audioPolicy
+                                first considers the mixPorts with a preferredUsage including
+                                the track AudioUsage preferred .
+                                If non support the track format, the other mixPorts are considered.
+                                Eg: a <mixPort preferredUsage="AUDIO_USAGE_MEDIA" /> will receive
+                                    the audio of all apps playing with a MEDIA usage.
+                                    It may receive audio from ALARM if there are no audio compatible
+                                    <mixPort preferredUsage="AUDIO_USAGE_ALARM" />.
+                             </xs:documentation>
+                        </xs:annotation>
+                    </xs:attribute>
+                </xs:complexType>
+                <xs:unique name="mixPortProfileUniqueness">
+                    <xs:selector xpath="profile"/>
+                    <xs:field xpath="format"/>
+                    <xs:field xpath="samplingRate"/>
+                    <xs:field xpath="channelMasks"/>
+                </xs:unique>
+                <xs:unique name="mixPortGainUniqueness">
+                    <xs:selector xpath="gains/gain"/>
+                    <xs:field xpath="@name"/>
+                </xs:unique>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <!-- Enum values of audio_device_t in audio.h
+         TODO: generate from hidl to avoid manual sync.
+         TODO: separate source and sink in the xml for better xsd validations. -->
+    <xs:simpleType name="audioDevice">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_DEVICE_NONE"/>
+
+            <xs:enumeration value="AUDIO_DEVICE_OUT_EARPIECE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_WIRED_HEADPHONE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_SCO_CARKIT"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_DIGITAL"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_ANLG_DOCK_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_DGTL_DOCK_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_USB_ACCESSORY"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_USB_DEVICE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_REMOTE_SUBMIX"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_TELEPHONY_TX"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_LINE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_HDMI_ARC"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_SPDIF"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_FM"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_AUX_LINE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_SPEAKER_SAFE"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_IP"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_BUS"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_PROXY"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_USB_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_HEARING_AID"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_ECHO_CANCELLER"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_DEFAULT"/>
+            <xs:enumeration value="AUDIO_DEVICE_OUT_STUB"/>
+
+            <!-- Due to the xml format, IN types can not be a separated from OUT types -->
+            <xs:enumeration value="AUDIO_DEVICE_IN_COMMUNICATION"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_AMBIENT"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BUILTIN_MIC"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_SCO_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_WIRED_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_AUX_DIGITAL"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_HDMI"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_VOICE_CALL"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_TELEPHONY_RX"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BACK_MIC"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_REMOTE_SUBMIX"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_ANLG_DOCK_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_DGTL_DOCK_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_USB_ACCESSORY"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_USB_DEVICE"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_FM_TUNER"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_TV_TUNER"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_LINE"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_SPDIF"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_A2DP"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_LOOPBACK"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_IP"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BUS"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_PROXY"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_USB_HEADSET"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_BLUETOOTH_BLE"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_DEFAULT"/>
+            <xs:enumeration value="AUDIO_DEVICE_IN_STUB"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- Enum values of audio_format_t in audio.h
+         TODO: generate from hidl to avoid manual sync. -->
+    <xs:simpleType name="audioFormat">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_FORMAT_PCM_16_BIT" />
+            <xs:enumeration value="AUDIO_FORMAT_PCM_8_BIT"/>
+            <xs:enumeration value="AUDIO_FORMAT_PCM_32_BIT"/>
+            <xs:enumeration value="AUDIO_FORMAT_PCM_8_24_BIT"/>
+            <xs:enumeration value="AUDIO_FORMAT_PCM_FLOAT"/>
+            <xs:enumeration value="AUDIO_FORMAT_PCM_24_BIT_PACKED"/>
+            <xs:enumeration value="AUDIO_FORMAT_MP3"/>
+            <xs:enumeration value="AUDIO_FORMAT_AMR_NB"/>
+            <xs:enumeration value="AUDIO_FORMAT_AMR_WB"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_MAIN"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_LC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_SSR"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_LTP"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_HE_V1"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_SCALABLE"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ERLC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_LD"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_HE_V2"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ELD"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_MAIN"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_SSR"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LTP"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_HE_V1"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_SCALABLE"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_ERLC"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_LD"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_HE_V2"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_ELD"/>
+            <xs:enumeration value="AUDIO_FORMAT_VORBIS"/>
+            <xs:enumeration value="AUDIO_FORMAT_HE_AAC_V1"/>
+            <xs:enumeration value="AUDIO_FORMAT_HE_AAC_V2"/>
+            <xs:enumeration value="AUDIO_FORMAT_OPUS"/>
+            <xs:enumeration value="AUDIO_FORMAT_AC3"/>
+            <xs:enumeration value="AUDIO_FORMAT_E_AC3"/>
+            <xs:enumeration value="AUDIO_FORMAT_DTS"/>
+            <xs:enumeration value="AUDIO_FORMAT_DTS_HD"/>
+            <xs:enumeration value="AUDIO_FORMAT_IEC61937"/>
+            <xs:enumeration value="AUDIO_FORMAT_DOLBY_TRUEHD"/>
+            <xs:enumeration value="AUDIO_FORMAT_EVRC"/>
+            <xs:enumeration value="AUDIO_FORMAT_EVRCB"/>
+            <xs:enumeration value="AUDIO_FORMAT_EVRCWB"/>
+            <xs:enumeration value="AUDIO_FORMAT_EVRCNW"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADIF"/>
+            <xs:enumeration value="AUDIO_FORMAT_WMA"/>
+            <xs:enumeration value="AUDIO_FORMAT_WMA_PRO"/>
+            <xs:enumeration value="AUDIO_FORMAT_AMR_WB_PLUS"/>
+            <xs:enumeration value="AUDIO_FORMAT_MP2"/>
+            <xs:enumeration value="AUDIO_FORMAT_QCELP"/>
+            <xs:enumeration value="AUDIO_FORMAT_DSD"/>
+            <xs:enumeration value="AUDIO_FORMAT_FLAC"/>
+            <xs:enumeration value="AUDIO_FORMAT_ALAC"/>
+            <xs:enumeration value="AUDIO_FORMAT_APE"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS"/>
+            <xs:enumeration value="AUDIO_FORMAT_SBC"/>
+            <xs:enumeration value="AUDIO_FORMAT_APTX"/>
+            <xs:enumeration value="AUDIO_FORMAT_APTX_HD"/>
+            <xs:enumeration value="AUDIO_FORMAT_AC4"/>
+            <xs:enumeration value="AUDIO_FORMAT_LDAC"/>
+            <xs:enumeration value="AUDIO_FORMAT_E_AC3_JOC"/>
+            <xs:enumeration value="AUDIO_FORMAT_MAT_1_0"/>
+            <xs:enumeration value="AUDIO_FORMAT_MAT_2_0"/>
+            <xs:enumeration value="AUDIO_FORMAT_MAT_2_1"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_XHE"/>
+            <xs:enumeration value="AUDIO_FORMAT_AAC_ADTS_XHE"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- Enum values of audio::common::4_0::AudioUsage
+         TODO: generate from HIDL to avoid manual sync. -->
+    <xs:simpleType name="audioUsage">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_USAGE_UNKNOWN" />
+            <xs:enumeration value="AUDIO_USAGE_MEDIA" />
+            <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION" />
+            <xs:enumeration value="AUDIO_USAGE_VOICE_COMMUNICATION_SIGNALLING" />
+            <xs:enumeration value="AUDIO_USAGE_ALARM" />
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION" />
+            <xs:enumeration value="AUDIO_USAGE_NOTIFICATION_TELEPHONY_RINGTONE" />
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_ACCESSIBILITY" />
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_NAVIGATION_GUIDANCE" />
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANCE_SONIFICATION" />
+            <xs:enumeration value="AUDIO_USAGE_GAME" />
+            <xs:enumeration value="AUDIO_USAGE_VIRTUAL_SOURCE" />
+            <xs:enumeration value="AUDIO_USAGE_ASSISTANT" />
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="audioUsageList">
+        <xs:list itemType="audioUsage"/>
+    </xs:simpleType>
+    <!-- TODO: Change to a space separated list to xsd enforce correctness. -->
+    <xs:simpleType name="samplingRates">
+        <xs:restriction base="xs:string">
+            <xs:pattern value="[0-9]+(,[0-9]+)*"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- TODO: Change to a space separated list to xsd enforce correctness. -->
+    <xs:simpleType name="channelMask">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Comma (",") separated list of channel flags
+                from audio_channel_mask_t.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:pattern value="[_A-Z][_A-Z0-9]*(,[_A-Z][_A-Z0-9]*)*"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="profile">
+        <xs:attribute name="name" type="xs:token" use="optional"/>
+        <xs:attribute name="format" type="audioFormat" use="optional"/>
+        <xs:attribute name="samplingRates" type="samplingRates" use="optional"/>
+        <xs:attribute name="channelMasks" type="channelMask" use="optional"/>
+    </xs:complexType>
+    <xs:simpleType name="gainMode">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_GAIN_MODE_JOINT"/>
+            <xs:enumeration value="AUDIO_GAIN_MODE_CHANNELS"/>
+            <xs:enumeration value="AUDIO_GAIN_MODE_RAMP"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="gains">
+        <xs:sequence>
+            <xs:element name="gain" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:attribute name="name" type="xs:token" use="required"/>
+                    <xs:attribute name="mode" type="gainMode" use="required"/>
+                    <xs:attribute name="channel_mask" type="channelMask" use="optional"/>
+                    <xs:attribute name="minValueMB" type="xs:int" use="optional"/>
+                    <xs:attribute name="maxValueMB" type="xs:int" use="optional"/>
+                    <xs:attribute name="defaultValueMB" type="xs:int" use="optional"/>
+                    <xs:attribute name="stepValueMB" type="xs:int" use="optional"/>
+                    <xs:attribute name="minRampMs" type="xs:int" use="optional"/>
+                    <xs:attribute name="maxRampMs" type="xs:int" use="optional"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="devicePorts">
+        <xs:sequence>
+            <xs:element name="devicePort" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:sequence>
+                        <xs:element name="profile" type="profile" minOccurs="0" maxOccurs="unbounded"/>
+                        <xs:element name="gains" type="gains" minOccurs="0"/>
+                    </xs:sequence>
+                    <xs:attribute name="tagName" type="xs:token" use="required"/>
+                    <xs:attribute name="type" type="audioDevice" use="required"/>
+                    <xs:attribute name="role" type="role" use="required"/>
+                    <xs:attribute name="address" type="xs:string" use="optional" default=""/>
+                    <!-- Note that XSD 1.0 can not check that a type only has one default. -->
+                    <xs:attribute name="default" type="xs:boolean" use="optional">
+                        <xs:annotation>
+                            <xs:documentation xml:lang="en">
+                                The default device will be used if multiple have the same type
+                                and no explicit route request exists for a specific device of
+                                that type.
+                            </xs:documentation>
+                        </xs:annotation>
+                    </xs:attribute>
+                </xs:complexType>
+                <xs:unique name="devicePortProfileUniqueness">
+                    <xs:selector xpath="profile"/>
+                    <xs:field xpath="format"/>
+                    <xs:field xpath="samplingRate"/>
+                    <xs:field xpath="channelMasks"/>
+                </xs:unique>
+                <xs:unique name="devicePortGainUniqueness">
+                    <xs:selector xpath="gains/gain"/>
+                    <xs:field xpath="@name"/>
+                </xs:unique>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:simpleType name="mixType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="mix"/>
+            <xs:enumeration value="mux"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="routes">
+        <xs:sequence>
+            <xs:element name="route" minOccurs="0" maxOccurs="unbounded">
+                <xs:annotation>
+                    <xs:documentation xml:lang="en">
+                        List all available sources for a given sink.
+                    </xs:documentation>
+                </xs:annotation>
+                <xs:complexType>
+                    <xs:attribute name="type" type="mixType" use="required"/>
+                    <xs:attribute name="sink" type="xs:string" use="required"/>
+                    <xs:attribute name="sources" type="xs:string" use="required"/>
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="volumes">
+        <xs:sequence>
+            <xs:element name="volume" type="volume" minOccurs="0" maxOccurs="unbounded"/>
+            <xs:element name="reference" type="reference" minOccurs="0" maxOccurs="unbounded">
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+    <!-- TODO: Always require a ref for better xsd validations.
+               Currently a volume could have no points nor ref
+               as it can not be forbidden by xsd 1.0.-->
+    <xs:simpleType name="volumePoint">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Comma separated pair of number.
+                The fist one is the framework level (between 0 and 100).
+                The second one is the volume to send to the HAL.
+                The framework will interpolate volumes not specified.
+                Their MUST be at least 2 points specified.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:restriction base="xs:string">
+            <xs:pattern value="([0-9]{1,2}|100),-?[0-9]+"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- Enum values of audio_stream_type_t in audio-base.h
+         TODO: generate from hidl to avoid manual sync. -->
+    <xs:simpleType name="stream">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="AUDIO_STREAM_VOICE_CALL"/>
+            <xs:enumeration value="AUDIO_STREAM_SYSTEM"/>
+            <xs:enumeration value="AUDIO_STREAM_RING"/>
+            <xs:enumeration value="AUDIO_STREAM_MUSIC"/>
+            <xs:enumeration value="AUDIO_STREAM_ALARM"/>
+            <xs:enumeration value="AUDIO_STREAM_NOTIFICATION"/>
+            <xs:enumeration value="AUDIO_STREAM_BLUETOOTH_SCO"/>
+            <xs:enumeration value="AUDIO_STREAM_ENFORCED_AUDIBLE"/>
+            <xs:enumeration value="AUDIO_STREAM_DTMF"/>
+            <xs:enumeration value="AUDIO_STREAM_TTS"/>
+            <xs:enumeration value="AUDIO_STREAM_ACCESSIBILITY"/>
+            <xs:enumeration value="AUDIO_STREAM_REROUTING"/>
+            <xs:enumeration value="AUDIO_STREAM_PATCH"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <!-- Enum values of device_category from Volume.h.
+         TODO: generate from hidl to avoid manual sync. -->
+    <xs:simpleType name="deviceCategory">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="DEVICE_CATEGORY_HEADSET"/>
+            <xs:enumeration value="DEVICE_CATEGORY_SPEAKER"/>
+            <xs:enumeration value="DEVICE_CATEGORY_EARPIECE"/>
+            <xs:enumeration value="DEVICE_CATEGORY_EXT_MEDIA"/>
+            <xs:enumeration value="DEVICE_CATEGORY_HEARING_AID"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:complexType name="volume">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Volume section defines a volume curve for a given use case and device category.
+                It contains a list of points of this curve expressing the attenuation in Millibels
+                for a given volume index from 0 to 100.
+                <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER">
+                    <point>0,-9600</point>
+                    <point>100,0</point>
+                </volume>
+
+                It may also reference a reference/@name to avoid duplicating curves.
+                <volume stream="AUDIO_STREAM_MUSIC" deviceCategory="DEVICE_CATEGORY_SPEAKER"
+                        ref="DEFAULT_MEDIA_VOLUME_CURVE"/>
+                <reference name="DEFAULT_MEDIA_VOLUME_CURVE">
+                    <point>0,-9600</point>
+                    <point>100,0</point>
+                </reference>
+            </xs:documentation>
+        </xs:annotation>
+        <xs:sequence>
+            <xs:element name="point" type="volumePoint" minOccurs="0" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="stream" type="stream"/>
+        <xs:attribute name="deviceCategory" type="deviceCategory"/>
+        <xs:attribute name="ref" type="xs:token" use="optional"/>
+    </xs:complexType>
+    <xs:complexType name="reference">
+        <xs:sequence>
+            <xs:element name="point" type="volumePoint" minOccurs="2" maxOccurs="unbounded"/>
+        </xs:sequence>
+        <xs:attribute name="name" type="xs:token" use="required"/>
+    </xs:complexType>
+    <xs:complexType name="surroundSound">
+        <xs:annotation>
+            <xs:documentation xml:lang="en">
+                Surround Sound section provides configuration related to handling of
+                multi-channel formats.
+            </xs:documentation>
+        </xs:annotation>
+        <xs:sequence>
+            <xs:element name="formats" type="surroundFormats"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:simpleType name="surroundFormatsList">
+        <xs:list itemType="audioFormat" />
+    </xs:simpleType>
+    <xs:complexType name="surroundFormats">
+        <xs:sequence>
+            <xs:element name="format" minOccurs="0" maxOccurs="unbounded">
+                <xs:complexType>
+                    <xs:attribute name="name" type="audioFormat" use="required"/>
+                    <xs:attribute name="subformats" type="surroundFormatsList" />
+                </xs:complexType>
+            </xs:element>
+        </xs:sequence>
+    </xs:complexType>
+</xs:schema>
diff --git a/audio/common/all-versions/default/service/Android.mk b/audio/common/all-versions/default/service/Android.mk
index 43d7fe1..84de75e 100644
--- a/audio/common/all-versions/default/service/Android.mk
+++ b/audio/common/all-versions/default/service/Android.mk
@@ -31,12 +31,14 @@
 LOCAL_CFLAGS := -Wall -Werror
 
 LOCAL_SHARED_LIBRARIES := \
+    libcutils \
     libbinder \
     libhidlbase \
     libhidltransport \
     liblog \
     libutils \
     libhardware \
+    libhwbinder \
     android.hardware.audio@2.0 \
     android.hardware.audio@4.0 \
     android.hardware.audio.common@2.0 \
@@ -55,4 +57,7 @@
 LOCAL_MULTILIB := $(AUDIOSERVER_MULTILIB)
 endif
 
+# b/117506164
+LOCAL_SANITIZE := never
+
 include $(BUILD_EXECUTABLE)
diff --git a/audio/common/all-versions/default/service/service.cpp b/audio/common/all-versions/default/service/service.cpp
index c7ce638..ff1394e 100644
--- a/audio/common/all-versions/default/service/service.cpp
+++ b/audio/common/all-versions/default/service/service.cpp
@@ -24,16 +24,26 @@
 #include <android/hardware/soundtrigger/2.0/ISoundTriggerHw.h>
 #include <android/hardware/soundtrigger/2.1/ISoundTriggerHw.h>
 #include <binder/ProcessState.h>
+#include <cutils/properties.h>
 #include <hidl/HidlTransportSupport.h>
 #include <hidl/LegacySupport.h>
+#include <hwbinder/ProcessState.h>
 
 using namespace android::hardware;
 using android::OK;
 
 int main(int /* argc */, char* /* argv */ []) {
-    android::ProcessState::initWithDriver("/dev/vndbinder");
+    ::android::ProcessState::initWithDriver("/dev/vndbinder");
     // start a threadpool for vndbinder interactions
-    android::ProcessState::self()->startThreadPool();
+    ::android::ProcessState::self()->startThreadPool();
+
+    const int32_t defaultValue = -1;
+    int32_t value =
+        property_get_int32("persist.vendor.audio.service.hwbinder.size_kbyte", defaultValue);
+    if (value != defaultValue) {
+        ALOGD("Configuring hwbinder with mmap size %d KBytes", value);
+        ProcessState::initWithMmapSize(static_cast<size_t>(value) * 1024);
+    }
     configureRpcThreadpool(16, true /*callerWillJoin*/);
 
     bool fail = registerPassthroughServiceImplementation<audio::V4_0::IDevicesFactory>() != OK &&
diff --git a/audio/core/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp b/audio/core/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp
index bb1d26f..a08a2d6 100644
--- a/audio/core/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/2.0/vts/functional/AudioPrimaryHidlHalTest.cpp
@@ -661,8 +661,8 @@
         code;                                          \
     }
 
-TEST_IO_STREAM(GetFrameCount, "Check that the stream frame count == the one it was opened with",
-               ASSERT_EQ(audioConfig.frameCount, extract(stream->getFrameCount())))
+TEST_IO_STREAM(GetFrameCount, "Check that getting stream frame count does not crash the HAL.",
+               ASSERT_TRUE(stream->getFrameCount().isOk()))
 
 TEST_IO_STREAM(GetSampleRate, "Check that the stream sample rate == the one it was opened with",
                ASSERT_EQ(audioConfig.sampleRateHz, extract(stream->getSampleRate())))
diff --git a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
index f4ab542..f1e0b21 100644
--- a/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
+++ b/audio/core/4.0/vts/functional/AudioPrimaryHidlHalTest.cpp
@@ -29,6 +29,8 @@
 #include <fcntl.h>
 #include <unistd.h>
 
+#include <hwbinder/IPCThreadState.h>
+
 #include <VtsHalHidlTargetTestBase.h>
 
 #include <android-base/logging.h>
@@ -63,6 +65,7 @@
 using ::android::hardware::hidl_handle;
 using ::android::hardware::hidl_string;
 using ::android::hardware::hidl_vec;
+using ::android::hardware::IPCThreadState;
 using ::android::hardware::kSynchronizedReadWrite;
 using ::android::hardware::MessageQueue;
 using ::android::hardware::MQDescriptorSync;
@@ -170,15 +173,25 @@
 
 TEST_F(AudioHidlTest, OpenPrimaryDeviceUsingGetDevice) {
     doc::test("Calling openDevice(\"primary\") should return the primary device.");
-    Result result;
-    sp<IDevice> baseDevice;
-    ASSERT_OK(devicesFactory->openDevice("primary", returnIn(result, baseDevice)));
-    ASSERT_OK(result);
-    ASSERT_TRUE(baseDevice != nullptr);
+    {
+        Result result;
+        sp<IDevice> baseDevice;
+        ASSERT_OK(devicesFactory->openDevice("primary", returnIn(result, baseDevice)));
+        ASSERT_OK(result);
+        ASSERT_TRUE(baseDevice != nullptr);
 
-    Return<sp<IPrimaryDevice>> primaryDevice = IPrimaryDevice::castFrom(baseDevice);
-    ASSERT_TRUE(primaryDevice.isOk());
-    ASSERT_TRUE(sp<IPrimaryDevice>(primaryDevice) != nullptr);
+        Return<sp<IPrimaryDevice>> primaryDevice = IPrimaryDevice::castFrom(baseDevice);
+        ASSERT_TRUE(primaryDevice.isOk());
+        ASSERT_TRUE(sp<IPrimaryDevice>(primaryDevice) != nullptr);
+    }  // Destroy local IDevice proxy
+    // FIXME: there is no way to know when the remote IDevice is being destroyed
+    //        Binder does not support testing if an object is alive, thus
+    //        wait for 100ms to let the binder destruction propagates and
+    //        the remote device has the time to be destroyed.
+    //        flushCommand makes sure all local command are sent, thus should reduce
+    //        the latency between local and remote destruction.
+    IPCThreadState::self()->flushCommands();
+    usleep(100);
 }
 
 //////////////////////////////////////////////////////////////////////////////
@@ -810,8 +823,8 @@
         code;                                          \
     }
 
-TEST_IO_STREAM(GetFrameCount, "Check that the stream frame count == the one it was opened with",
-               ASSERT_EQ(audioConfig.frameCount, extract(stream->getFrameCount())))
+TEST_IO_STREAM(GetFrameCount, "Check that getting stream frame count does not crash the HAL.",
+               ASSERT_TRUE(stream->getFrameCount().isOk()))
 
 TEST_IO_STREAM(GetSampleRate, "Check that the stream sample rate == the one it was opened with",
                ASSERT_EQ(audioConfig.sampleRateHz, extract(stream->getSampleRate())))
@@ -1470,6 +1483,7 @@
         "Make sure setBtHfpVolume is either not supported or "
         "only succeed if volume is in [0,1]");
     auto ret = device->setBtHfpVolume(0.0);
+    ASSERT_TRUE(ret.isOk());
     if (ret == Result::NOT_SUPPORTED) {
         doc::partialTest("setBtHfpVolume is not supported");
         return;
diff --git a/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h b/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h
index f27c739..f3256f1 100644
--- a/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h
+++ b/audio/effect/all-versions/default/include/effect/all-versions/default/EffectsFactory.impl.h
@@ -101,6 +101,7 @@
                 case -ENOENT: {
                     // No more effects available.
                     result.resize(i);
+                    break;
                 }
                 default: {
                     result.resize(0);
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
index 74bbfb4..ae4ead4 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/DefaultConfig.h
@@ -36,6 +36,9 @@
 constexpr int DOOR_1_RIGHT = (int)VehicleAreaDoor::ROW_1_RIGHT;
 constexpr int DOOR_2_LEFT = (int)VehicleAreaDoor::ROW_2_LEFT;
 constexpr int DOOR_2_RIGHT = (int)VehicleAreaDoor::ROW_2_RIGHT;
+constexpr int WINDOW_1_LEFT = (int)VehicleAreaWindow::ROW_1_LEFT;
+constexpr int WINDOW_2_LEFT = (int)VehicleAreaWindow::ROW_2_LEFT;
+constexpr int WINDOW_2_RIGHT = (int)VehicleAreaWindow::ROW_2_RIGHT;
 constexpr int FAN_DIRECTION_FACE = (int)VehicleHvacFanDirection::FACE;
 constexpr int FAN_DIRECTION_FLOOR = (int)VehicleHvacFanDirection::FLOOR;
 constexpr int OBD2_LIVE_FRAME = (int)VehicleProperty::OBD2_LIVE_FRAME;
@@ -227,6 +230,16 @@
 
     {.config =
          {
+             .prop = toInt(VehicleProperty::INFO_DRIVER_SEAT),
+             .access = VehiclePropertyAccess::READ,
+             .changeMode = VehiclePropertyChangeMode::STATIC,
+             // this was a zoned property on an old vhal, but it is meant to be global
+             .areaConfigs = {VehicleAreaConfig{.areaId = (0)}},
+         },
+     .initialValue = {.int32Values = {SEAT_1_LEFT}}},
+
+    {.config =
+         {
              .prop = toInt(VehicleProperty::PERF_ODOMETER),
              .access = VehiclePropertyAccess::READ,
              .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
@@ -559,13 +572,20 @@
     },
 
     {.config = {.prop = toInt(VehicleProperty::DOOR_LOCK),
-                .access = VehiclePropertyAccess::READ,
+                .access = VehiclePropertyAccess::READ_WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .areaConfigs = {VehicleAreaConfig{.areaId = DOOR_1_LEFT},
                                 VehicleAreaConfig{.areaId = DOOR_1_RIGHT}}},
      .initialAreaValues = {{DOOR_1_LEFT, {.int32Values = {1}}},
                            {DOOR_1_RIGHT, {.int32Values = {1}}}}},
 
+    {.config = {.prop = toInt(VehicleProperty::WINDOW_LOCK),
+                .access = VehiclePropertyAccess::READ_WRITE,
+                .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
+                .areaConfigs = {VehicleAreaConfig{.areaId = WINDOW_1_LEFT | WINDOW_2_LEFT |
+                                                            WINDOW_2_RIGHT}}},
+     .initialAreaValues = {{WINDOW_1_LEFT | WINDOW_2_LEFT | WINDOW_2_RIGHT, {.int32Values = {0}}}}},
+
     {.config =
          {
              .prop = WHEEL_TICK,
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 7fe8377..4d07386 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -322,6 +322,21 @@
         | VehicleArea:GLOBAL),
 
     /**
+     * Steering angle of the vehicle
+     *
+     * Angle is in degrees.  Left is negative.
+     *
+     * @change_mode VehiclePropertyChangeMode:CONTINUOUS
+     * @access VehiclePropertyAccess:READ
+     * @unit VehicleUnit:DEGREES
+     */
+    PERF_STEERING_ANGLE = (
+        0x0209
+        | VehiclePropertyGroup:SYSTEM
+        | VehiclePropertyType:FLOAT
+        | VehicleArea:GLOBAL),
+
+    /**
      * Temperature of engine coolant
      *
      * @change_mode VehiclePropertyChangeMode:CONTINUOUS
@@ -2421,13 +2436,15 @@
     NANO_SECS      = 0x50,
     SECS           = 0x53,
     YEAR           = 0x59,
-    KILOPASCAL     = 0x70,
 
     // Electrical Units
     WATT_HOUR      = 0x60,
     MILLIAMPERE    = 0x61,
     MILLIVOLT      = 0x62,
     MILLIWATTS     = 0x63,
+
+    KILOPASCAL     = 0x70,
+    DEGREES        = 0x80,
 };
 
 /**
diff --git a/biometrics/face/1.0/Android.bp b/biometrics/face/1.0/Android.bp
index 61bf247..45dbad9 100644
--- a/biometrics/face/1.0/Android.bp
+++ b/biometrics/face/1.0/Android.bp
@@ -17,6 +17,7 @@
     types: [
         "FaceAcquiredInfo",
         "FaceError",
+        "OptionalBool",
         "OptionalUint64",
         "Status",
         "UserHandle",
diff --git a/biometrics/face/1.0/IBiometricsFace.hal b/biometrics/face/1.0/IBiometricsFace.hal
index fbdb210..0ac788e 100644
--- a/biometrics/face/1.0/IBiometricsFace.hal
+++ b/biometrics/face/1.0/IBiometricsFace.hal
@@ -60,29 +60,33 @@
      *     persistent for a given user.
      * @param storePath filesystem path to the template storage directory.
      */
-    @callflow(next={"authenticate", "preEnroll", "enumerate", "remove"})
+    @callflow(next={"authenticate", "generateChallenge", "enumerate", "remove"})
     setActiveUser(int32_t userId, string storePath) generates (Status status);
 
     /**
-     * Begins a pre-enrollment request.
+     * Begins a secure transaction request, e.g. enrollment.
      *
      * Generates a unique and cryptographically secure random token used to
-     * indicate the start of an enrollment transaction. preEnroll() and
-     * postEnroll() specify a pin/pattern/password cleared time window where
-     * enrollment is allowed.
+     * indicate the start of a secure transaction. generateChallenge() and
+     * revokeChallenge() specify a pin/pattern/password cleared time window where
+     * the secure transaction is allowed.
      *
-     * preEnroll() generates a challenge which must then be wrapped by the
+     * generateChallenge() generates a challenge which must then be wrapped by the
      * gatekeeper after verifying a successful strong authentication attempt,
      * which generates a Hardware Authentication Token. The challenge prevents
      * spoofing and replay attacks and ensures that we only update a user’s face
      * template if the operation was preceded by some kind of strong credential
      * confirmation (e.g. device password).
      *
+     * @param challengeTimeoutSec A timeout in seconds, after which the driver
+     *     must invalidate the challenge. This is to prevent bugs or crashes in
+     *     the system from leaving a challenge enabled indefinitely.
      * @return result, with its "value" parameter representing a "challenge": a
      *     unique and cryptographically secure random token.
      */
-    @callflow(next={"enroll", "postEnroll"})
-    preEnroll() generates (OptionalUint64 result);
+    @callflow(next={"enroll", "revokeChallenge", "setRequireAttention"})
+    generateChallenge(uint32_t challengeTimeoutSec)
+        generates (OptionalUint64 result);
 
     /**
      * Enrolls a user's face.
@@ -95,28 +99,38 @@
      * necessity for a shared use case, e.g. TVs or cars.
      *
      * Note that the Hardware Authentication Token must still be valid after
-     * this call, and must be explicitly invalidated by a call to postEnroll().
-     * This allows clients to immediately reattempt enrollment (for example, if
-     * a user wasn’t satisfied with their enrollment) without having to go
-     * through another strong authentication flow.
+     * this call, and must be explicitly invalidated by a call to
+     * revokeChallenge(). This allows clients to immediately reattempt
+     * enrollment (for example, if a user wasn’t satisfied with their enrollment)
+     * without having to go through another strong authentication flow.
      *
      * This method triggers the IBiometricsFaceClientCallback#onEnrollResult()
      * method.
      *
      * @param hat A valid Hardware Authentication Token, generated as a result
-     *     of a preEnroll() challenge being wrapped by the gatekeeper after a
-     *     sucessful strong authentication request.
+     *     of a generateChallenge() challenge being wrapped by the gatekeeper
+     *     after a sucessful strong authentication request.
      * @param timeoutSec A timeout in seconds, after which this enrollment
      *     attempt is cancelled. Note that the client still needs to
-     *     call postEnroll() to terminate the enrollment session.
+     *     call revokeChallenge() to terminate the enrollment session.
+     * @param requireAttention When set to true, requires user attention (e.g.
+     *     eyes open and looking at the device) for enrollment to complete, as
+     *     well as subsequent authentication. This is expected to be enabled by
+     *     default to improve security and decrease falsing (unintentional face
+     *     detection). This feature can be disabled at the user's request
+     *     during enrollment, e.g. for accessibility reasons. When enabled,
+     *     the FaceAcquiredInfo#POOR_GAZE message must be sent when the user's
+     *     attention has not been established. The UI should inform the user
+     *     to look at the device.
      * @return status The status of this method call.
      */
-    @callflow(next={"cancel", "enroll", "postEnroll", "remove"})
-    enroll(vec<uint8_t> hat, uint32_t timeoutSec) generates (Status status);
+    @callflow(next={"cancel", "enroll", "revokeChallenge", "remove"})
+    enroll(vec<uint8_t> hat, uint32_t timeoutSec, bool requireAttention)
+        generates (Status status);
 
     /**
-     * Finishes the enrollment session and invalidates the challenge generated
-     * by preEnroll().
+     * Finishes the secure transaction by invalidating the challenge generated
+     * by generateChallenge().
      *
      * Clients must call this method once enrollment is complete, and the user's
      * face template no longer needs to be updated.
@@ -124,7 +138,38 @@
      * @return status The status of this method call.
      */
     @callflow(next={"authenticate", "setActiveUser", "enumerate", "remove"})
-    postEnroll() generates (Status status);
+    revokeChallenge() generates (Status status);
+
+    /**
+     * Requires that all subsequent authenticate calls to first have the
+     * user's attention. This method does not affect enroll, which has its
+     * own requireAttention parameter.
+     *
+     * Changes the state of previous enrollment setting. Because this may
+     * decrease security, the user must enter their password before this method
+     * is invoked (see @param HAT). The driver must verify the HAT before
+     * changing the requireAttention state.
+     * Note: In some cases it may not be possible to change the state of this
+     * flag without re-enrolling. For example, if the user didn't provide
+     * attention during the original enrollment. This flag reflects the same
+     * persistent state as the one passed to enroll().
+     *
+     * @param requireAttention When set to true, requires user attention for
+     *     authentication to succeed.
+     * @param hat A valid Hardware Authentication Token, generated as a result
+     *     of getChallenge().
+     * @return status The status of this method call.
+     */
+    setRequireAttention(bool requireAttention, vec<uint8_t> hat)
+        generates(Status status);
+
+    /**
+     * Retrieves the current requireAttention state.
+     *
+     * @return result, with its value parameter representing the current
+     *     requireAttention state.
+     */
+    getRequireAttention(vec<uint8_t> hat) generates (OptionalBool result);
 
     /**
      * Returns an identifier associated with the current face set.
@@ -180,12 +225,28 @@
      * Authenticates the active user.
      *
      * An optional operationId can be specified as a token from the transaction
-     * being authorized.
+     * being authorized. The hardware may enter a standby state during
+     * authentication, where the device is idle to conserve power while
+     * authenticating, e.g. after 3 seconds without finding a face. See
+     * IBiometricsFace#userActivity() for more info.
      *
      * @param operationId A non-zero operation id associated with a crypto
      * object instance; or 0 if not being used.
      * @return status The status of this method call.
      */
-    @callflow(next={"cancel", "preEnroll", "remove"})
+    @callflow(next={"cancel", "generateChallenge", "remove"})
     authenticate(uint64_t operationId) generates (Status status);
+
+    /**
+     * A hint to the HAL to continue looking for faces.
+     *
+     * This method should only be used when the HAL is in the authenticating
+     * or standby state. Using this method when the HAL is not in one of the
+     * mentioned states must return OPERATION_NOT_SUPPORTED. Calling this
+     * method while the HAL is already authenticating may extend the duration
+     * where it's looking for a face.
+     *
+     * @return status The status of this method call.
+     */
+    userActivity() generates (Status status);
 };
diff --git a/biometrics/face/1.0/types.hal b/biometrics/face/1.0/types.hal
index 08af919..2628af9 100644
--- a/biometrics/face/1.0/types.hal
+++ b/biometrics/face/1.0/types.hal
@@ -48,7 +48,13 @@
     /**
      * The HAL has encountered an internal error and cannot complete the request.
      */
-    INTERNAL_ERROR = 3
+    INTERNAL_ERROR = 3,
+
+    /**
+     * The operation could not be completed because there are no enrolled
+     * templates.
+     */
+    NOT_ENROLLED = 4
 };
 
 /**
@@ -206,8 +212,10 @@
     FACE_TOO_LEFT = 9,
 
     /**
-     * The user's face was directed away from the sensor. The user should be
-     * informed to face the sensor when this is returned.
+     * The user's eyes have strayed away from the sensor. If this message is
+     * sent, the user should be informed to look at the device. If the user
+     * can't be found in the frame, one of the other acquisition messages
+     * must be sent, e.g. NOT_DETECTED.
      */
     POOR_GAZE = 10,
 
@@ -228,7 +236,11 @@
     TOO_MUCH_MOTION = 12,
 
     /**
-     * The sensor needs to be recalibrated.
+     * The sensor needs to be re-calibrated. This is an unexpected condition,
+     * and must only be sent if a serious, uncorrectable, and unrecoverable
+     * calibration issue is detected which requires user intervention, e.g.
+     * re-enrolling. The expected response to this message is to direct the
+     * user to re-enroll.
      */
     RECALIBRATE = 13,
 
@@ -253,3 +265,19 @@
      */
     uint64_t value;
 };
+
+/**
+ * Result structure with an addition bool field. See documentation in
+ * getRequireAttention() for usage of the value.
+ */
+struct OptionalBool {
+    /**
+     * The return status.
+     */
+    Status status;
+
+    /**
+     * This value is only meaningful if status is OK.
+     */
+    bool value;
+};
\ No newline at end of file
diff --git a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
index bf8b547..439c5fb 100644
--- a/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
+++ b/bluetooth/1.0/vts/functional/VtsHalBluetoothV1_0TargetTest.cpp
@@ -170,8 +170,9 @@
     acl_cb_count = 0;
     sco_cb_count = 0;
 
-    ASSERT_EQ(initialized, false);
-    bluetooth->initialize(bluetooth_cb);
+    ASSERT_FALSE(initialized);
+    // Should not be checked in production code
+    ASSERT_TRUE(bluetooth->initialize(bluetooth_cb).isOk());
 
     bluetooth_cb->SetWaitTimeout(kCallbackNameInitializationComplete,
                                  WAIT_FOR_INIT_TIMEOUT);
@@ -186,15 +187,16 @@
         bluetooth_cb->WaitForCallback(kCallbackNameInitializationComplete)
             .no_timeout);
 
-    ASSERT_EQ(initialized, true);
+    ASSERT_TRUE(initialized);
   }
 
   virtual void TearDown() override {
-    bluetooth->close();
-    handle_no_ops();
-    EXPECT_EQ(static_cast<size_t>(0), event_queue.size());
-    EXPECT_EQ(static_cast<size_t>(0), sco_queue.size());
-    EXPECT_EQ(static_cast<size_t>(0), acl_queue.size());
+      // Should not be checked in production code
+      ASSERT_TRUE(bluetooth->close().isOk());
+      handle_no_ops();
+      EXPECT_EQ(static_cast<size_t>(0), event_queue.size());
+      EXPECT_EQ(static_cast<size_t>(0), sco_queue.size());
+      EXPECT_EQ(static_cast<size_t>(0), acl_queue.size());
   }
 
   void setBufferSizes();
diff --git a/boot/1.0/default/Android.bp b/boot/1.0/default/Android.bp
index 67dee08..397c56d 100644
--- a/boot/1.0/default/Android.bp
+++ b/boot/1.0/default/Android.bp
@@ -2,7 +2,7 @@
     name: "android.hardware.boot@1.0-impl",
     defaults: ["hidl_defaults"],
     relative_install_path: "hw",
-    vendor_available: true,
+    vendor: true,
     recovery_available: true,
     srcs: ["BootControl.cpp"],
 
diff --git a/boot/1.0/default/Android.mk b/boot/1.0/default/Android.mk
new file mode 100644
index 0000000..cd4b499
--- /dev/null
+++ b/boot/1.0/default/Android.mk
@@ -0,0 +1,29 @@
+# TODO(connoro): Remove this file once we eliminate existing usage of
+# PRODUCT_STATIC_BOOT_CONTROL_HAL
+
+LOCAL_PATH := $(call my-dir)
+
+ifneq ($(strip $(PRODUCT_STATIC_BOOT_CONTROL_HAL)),)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := android.hardware.boot@1.0-impl-wrapper.recovery
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_MULTILIB := first
+ifeq ($(TARGET_IS_64_BIT),true)
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/lib64/hw
+else
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/lib/hw
+endif
+LOCAL_SRC_FILES := BootControl.cpp
+LOCAL_CFLAGS := -DBOOT_CONTROL_RECOVERY
+LOCAL_SHARED_LIBRARIES := \
+    liblog.recovery \
+    libhidlbase.recovery \
+    libhidltransport.recovery \
+    libhardware.recovery \
+    libutils.recovery \
+    android.hardware.boot@1.0.recovery
+LOCAL_STATIC_LIBRARIES := $(PRODUCT_STATIC_BOOT_CONTROL_HAL)
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/boot/1.0/default/BootControl.cpp b/boot/1.0/default/BootControl.cpp
index 9a90076..e36407f 100644
--- a/boot/1.0/default/BootControl.cpp
+++ b/boot/1.0/default/BootControl.cpp
@@ -21,6 +21,10 @@
 #include <hardware/boot_control.h>
 #include "BootControl.h"
 
+#ifdef BOOT_CONTROL_RECOVERY
+extern const hw_module_t HAL_MODULE_INFO_SYM;
+#endif
+
 namespace android {
 namespace hardware {
 namespace boot {
@@ -92,7 +96,23 @@
     return Void();
 }
 
+#ifdef BOOT_CONTROL_RECOVERY
+IBootControl* HIDL_FETCH_IBootControl(const char * /* hal */) {
+    boot_control_module_t* module;
 
+    // For devices that don't build a standalone libhardware bootctrl impl for recovery,
+    // we simulate the hw_get_module() by accessing it from the current process directly.
+    const hw_module_t* hw_module = &HAL_MODULE_INFO_SYM;
+    if (!hw_module ||
+        strcmp(BOOT_CONTROL_HARDWARE_MODULE_ID, hw_module->id) != 0) {
+        ALOGE("Error loading boot_control HAL implementation: %d.", -EINVAL);
+        return nullptr;
+    }
+    module = reinterpret_cast<boot_control_module_t*>(const_cast<hw_module_t*>(hw_module));
+    module->init(module);
+    return new BootControl(module);
+}
+#else
 IBootControl* HIDL_FETCH_IBootControl(const char* /* hal */) {
     int ret = 0;
     boot_control_module_t* module = NULL;
@@ -106,7 +126,7 @@
     module->init(module);
     return new BootControl(module);
 }
-
+#endif
 } // namespace implementation
 }  // namespace V1_0
 }  // namespace boot
diff --git a/camera/common/1.0/default/CameraModule.cpp b/camera/common/1.0/default/CameraModule.cpp
index dc4e0f0..392ebbc 100644
--- a/camera/common/1.0/default/CameraModule.cpp
+++ b/camera/common/1.0/default/CameraModule.cpp
@@ -235,7 +235,7 @@
     chars.update(keyTag, availableKeys);
 }
 
-CameraModule::CameraModule(camera_module_t *module) {
+CameraModule::CameraModule(camera_module_t *module) : mNumberOfCameras(0) {
     if (module == NULL) {
         ALOGE("%s: camera hardware module must not be null", __FUNCTION__);
         assert(0);
@@ -264,7 +264,8 @@
         res = mModule->init();
         ATRACE_END();
     }
-    mCameraInfoMap.setCapacity(getNumberOfCameras());
+    mNumberOfCameras = getNumberOfCameras();
+    mCameraInfoMap.setCapacity(mNumberOfCameras);
     return res;
 }
 
@@ -319,6 +320,45 @@
     return OK;
 }
 
+int CameraModule::getPhysicalCameraInfo(int physicalCameraId, camera_metadata_t **physicalInfo) {
+    ATRACE_CALL();
+    Mutex::Autolock lock(mCameraInfoLock);
+    if (physicalCameraId < mNumberOfCameras) {
+        ALOGE("%s: Invalid physical camera ID %d", __FUNCTION__, physicalCameraId);
+        return -EINVAL;
+    }
+
+    // Only query physical camera info for 2.5 version for newer
+    int apiVersion = mModule->common.module_api_version;
+    if (apiVersion < CAMERA_MODULE_API_VERSION_2_5) {
+        ALOGE("%s: Module version must be at least 2.5 to handle getPhysicalCameraInfo",
+                __FUNCTION__);
+        return -ENODEV;
+    }
+    if (mModule->get_physical_camera_info == nullptr) {
+        ALOGE("%s: get_physical_camera is NULL for module version 2.5", __FUNCTION__);
+        return -EINVAL;
+    }
+
+    ssize_t index = mPhysicalCameraInfoMap.indexOfKey(physicalCameraId);
+    if (index == NAME_NOT_FOUND) {
+        // Get physical camera characteristics, and cache it
+        camera_metadata_t *info = nullptr;
+        ATRACE_BEGIN("camera_module->get_physical_camera_info");
+        int ret = mModule->get_physical_camera_info(physicalCameraId, &info);
+        ATRACE_END();
+        if (ret != 0) {
+            return ret;
+        }
+
+        index = mPhysicalCameraInfoMap.add(physicalCameraId, info);
+    }
+
+    assert(index != NAME_NOT_FOUND);
+    *physicalInfo = mPhysicalCameraInfoMap[index];
+    return OK;
+}
+
 int CameraModule::getDeviceVersion(int cameraId) {
     ssize_t index = mDeviceVersionMap.indexOfKey(cameraId);
     if (index == NAME_NOT_FOUND) {
diff --git a/camera/common/1.0/default/OWNERS b/camera/common/1.0/default/OWNERS
index 18acfee..369b204 100644
--- a/camera/common/1.0/default/OWNERS
+++ b/camera/common/1.0/default/OWNERS
@@ -1,6 +1,7 @@
 cychen@google.com
 epeev@google.com
 etalvala@google.com
+jchowdhary@google.com
 shuzhenwang@google.com
 yinchiayeh@google.com
 zhijunhe@google.com
diff --git a/camera/common/1.0/default/include/CameraModule.h b/camera/common/1.0/default/include/CameraModule.h
index deebd09..aee9654 100644
--- a/camera/common/1.0/default/include/CameraModule.h
+++ b/camera/common/1.0/default/include/CameraModule.h
@@ -65,6 +65,7 @@
     void *getDso();
     // Only used by CameraProvider
     void removeCamera(int cameraId);
+    int getPhysicalCameraInfo(int physicalCameraId, camera_metadata_t **physicalInfo);
 
 private:
     // Derive camera characteristics keys defined after HAL device version
@@ -74,8 +75,10 @@
             int32_t keyTag, const Vector<int32_t>& appendKeys);
     status_t filterOpenErrorCode(status_t err);
     camera_module_t *mModule;
+    int mNumberOfCameras;
     KeyedVector<int, camera_info> mCameraInfoMap;
     KeyedVector<int, int> mDeviceVersionMap;
+    KeyedVector<int, camera_metadata_t*> mPhysicalCameraInfoMap;
     Mutex mCameraInfoLock;
 };
 
diff --git a/camera/device/1.0/default/OWNERS b/camera/device/1.0/default/OWNERS
index 18acfee..369b204 100644
--- a/camera/device/1.0/default/OWNERS
+++ b/camera/device/1.0/default/OWNERS
@@ -1,6 +1,7 @@
 cychen@google.com
 epeev@google.com
 etalvala@google.com
+jchowdhary@google.com
 shuzhenwang@google.com
 yinchiayeh@google.com
 zhijunhe@google.com
diff --git a/camera/device/3.2/ICameraDevice.hal b/camera/device/3.2/ICameraDevice.hal
index 1f523e4..5236bb1 100644
--- a/camera/device/3.2/ICameraDevice.hal
+++ b/camera/device/3.2/ICameraDevice.hal
@@ -148,7 +148,9 @@
      * session handle for active operations.
      *
      * @param callback Interface to invoke by the HAL for device asynchronous
-     *     events.
+     *     events. For HALs newer than version 3.2, HAL must use castFrom
+     *     method to check the exact version of callback sent by camera service.
+     *
      * @return status Status code for the operation, one of:
      *     OK:
      *         On a successful open of the camera device.
diff --git a/camera/device/3.2/ICameraDeviceSession.hal b/camera/device/3.2/ICameraDeviceSession.hal
index 477a3cc..225e52b 100644
--- a/camera/device/3.2/ICameraDeviceSession.hal
+++ b/camera/device/3.2/ICameraDeviceSession.hal
@@ -149,9 +149,8 @@
      *           - Including too many output streams of a certain format.
      *           - Unsupported rotation configuration
      *           - Stream sizes/formats don't satisfy the
-     *             camera3_stream_configuration_t->operation_mode requirements
-     *             for non-NORMAL mode, or the requested operation_mode is not
-     *             supported by the HAL.
+     *             StreamConfigurationMode requirements for non-NORMAL mode, or
+     *             the requested operation_mode is not supported by the HAL.
      *           - Unsupported usage flag
      *         The camera service cannot filter out all possible illegal stream
      *         configurations, since some devices may support more simultaneous
diff --git a/camera/device/3.2/default/CameraDevice.cpp b/camera/device/3.2/default/CameraDevice.cpp
index dfbb976..2e80ce8 100644
--- a/camera/device/3.2/default/CameraDevice.cpp
+++ b/camera/device/3.2/default/CameraDevice.cpp
@@ -101,7 +101,7 @@
 }
 
 // Methods from ::android::hardware::camera::device::V3_2::ICameraDevice follow.
-Return<void> CameraDevice::getResourceCost(getResourceCost_cb _hidl_cb)  {
+Return<void> CameraDevice::getResourceCost(ICameraDevice::getResourceCost_cb _hidl_cb)  {
     Status status = initStatus();
     CameraResourceCost resCost;
     if (status == Status::OK) {
@@ -141,7 +141,8 @@
     return Void();
 }
 
-Return<void> CameraDevice::getCameraCharacteristics(getCameraCharacteristics_cb _hidl_cb)  {
+Return<void> CameraDevice::getCameraCharacteristics(
+        ICameraDevice::getCameraCharacteristics_cb _hidl_cb)  {
     Status status = initStatus();
     CameraMetadata cameraCharacteristics;
     if (status == Status::OK) {
@@ -172,7 +173,8 @@
     return status;
 }
 
-Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb)  {
+Return<void> CameraDevice::open(const sp<ICameraDeviceCallback>& callback,
+        ICameraDevice::open_cb _hidl_cb)  {
     Status status = initStatus();
     sp<CameraDeviceSession> session = nullptr;
 
diff --git a/camera/device/3.2/default/CameraDevice_3_2.h b/camera/device/3.2/default/CameraDevice_3_2.h
index 9534707..f474533 100644
--- a/camera/device/3.2/default/CameraDevice_3_2.h
+++ b/camera/device/3.2/default/CameraDevice_3_2.h
@@ -51,7 +51,7 @@
 /*
  * The camera device HAL implementation is opened lazily (via the open call)
  */
-struct CameraDevice : public ICameraDevice {
+struct CameraDevice : public virtual RefBase {
     // Called by provider HAL. Provider HAL must ensure the uniqueness of
     // CameraDevice object per cameraId, or there could be multiple CameraDevice
     // trying to access the same physical camera.
@@ -60,7 +60,14 @@
     CameraDevice(sp<CameraModule> module,
                  const std::string& cameraId,
                  const SortedVector<std::pair<std::string, std::string>>& cameraDeviceNames);
-    ~CameraDevice();
+    virtual ~CameraDevice();
+
+    // Retrieve the HIDL interface, split into its own class to avoid inheritance issues when
+    // dealing with minor version revs and simultaneous implementation and interface inheritance
+    virtual sp<ICameraDevice> getInterface() {
+        return new TrampolineDeviceInterface_3_2(this);
+    }
+
     // Caller must use this method to check if CameraDevice ctor failed
     bool isInitFailed() { return mInitFail; }
     // Used by provider HAL to signal external camera disconnected
@@ -68,16 +75,16 @@
 
     /* Methods from ::android::hardware::camera::device::V3_2::ICameraDevice follow. */
     // The following method can be called without opening the actual camera device
-    Return<void> getResourceCost(getResourceCost_cb _hidl_cb) override;
-    Return<void> getCameraCharacteristics(getCameraCharacteristics_cb _hidl_cb) override;
-    Return<Status> setTorchMode(TorchMode mode) override;
+    Return<void> getResourceCost(ICameraDevice::getResourceCost_cb _hidl_cb);
+    Return<void> getCameraCharacteristics(ICameraDevice::getCameraCharacteristics_cb _hidl_cb);
+    Return<Status> setTorchMode(TorchMode mode);
 
     // Open the device HAL and also return a default capture session
-    Return<void> open(const sp<ICameraDeviceCallback>& callback, open_cb _hidl_cb) override;
+    Return<void> open(const sp<ICameraDeviceCallback>& callback, ICameraDevice::open_cb _hidl_cb);
 
 
     // Forward the dump call to the opened session, or do nothing
-    Return<void> dumpState(const ::android::hardware::hidl_handle& fd) override;
+    Return<void> dumpState(const ::android::hardware::hidl_handle& fd);
     /* End of Methods from ::android::hardware::camera::device::V3_2::ICameraDevice */
 
 protected:
@@ -106,6 +113,39 @@
     static Status getHidlStatus(int);
 
     Status initStatus() const;
+
+private:
+    struct TrampolineDeviceInterface_3_2 : public ICameraDevice {
+        TrampolineDeviceInterface_3_2(sp<CameraDevice> parent) :
+            mParent(parent) {}
+
+        virtual Return<void> getResourceCost(V3_2::ICameraDevice::getResourceCost_cb _hidl_cb)
+                override {
+            return mParent->getResourceCost(_hidl_cb);
+        }
+
+        virtual Return<void> getCameraCharacteristics(
+                V3_2::ICameraDevice::getCameraCharacteristics_cb _hidl_cb) override {
+            return mParent->getCameraCharacteristics(_hidl_cb);
+        }
+
+        virtual Return<Status> setTorchMode(TorchMode mode) override {
+            return mParent->setTorchMode(mode);
+        }
+
+        virtual Return<void> open(const sp<V3_2::ICameraDeviceCallback>& callback,
+                V3_2::ICameraDevice::open_cb _hidl_cb) override {
+            return mParent->open(callback, _hidl_cb);
+        }
+
+        virtual Return<void> dumpState(const hidl_handle& fd) override {
+            return mParent->dumpState(fd);
+        }
+
+    private:
+        sp<CameraDevice> mParent;
+    };
+
 };
 
 }  // namespace implementation
diff --git a/camera/device/3.2/default/OWNERS b/camera/device/3.2/default/OWNERS
index 18acfee..369b204 100644
--- a/camera/device/3.2/default/OWNERS
+++ b/camera/device/3.2/default/OWNERS
@@ -1,6 +1,7 @@
 cychen@google.com
 epeev@google.com
 etalvala@google.com
+jchowdhary@google.com
 shuzhenwang@google.com
 yinchiayeh@google.com
 zhijunhe@google.com
diff --git a/camera/device/3.3/default/OWNERS b/camera/device/3.3/default/OWNERS
index 18acfee..369b204 100644
--- a/camera/device/3.3/default/OWNERS
+++ b/camera/device/3.3/default/OWNERS
@@ -1,6 +1,7 @@
 cychen@google.com
 epeev@google.com
 etalvala@google.com
+jchowdhary@google.com
 shuzhenwang@google.com
 yinchiayeh@google.com
 zhijunhe@google.com
diff --git a/camera/device/3.4/ICameraDeviceSession.hal b/camera/device/3.4/ICameraDeviceSession.hal
index c41d90e..e1663e6 100644
--- a/camera/device/3.4/ICameraDeviceSession.hal
+++ b/camera/device/3.4/ICameraDeviceSession.hal
@@ -54,7 +54,7 @@
      *           - Including too many output streams of a certain format.
      *           - Unsupported rotation configuration
      *           - Stream sizes/formats don't satisfy the
-     *             camera3_stream_configuration_t->operation_mode requirements
+     *             StreamConfigurationMode requirements
      *             for non-NORMAL mode, or the requested operation_mode is not
      *             supported by the HAL.
      *           - Unsupported usage flag
diff --git a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
index 350f48b..7c11c61 100644
--- a/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
+++ b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
@@ -1752,7 +1752,11 @@
     // TODO: see if we can save some computation by converting to YV12 here
     uint8_t* inData;
     size_t inDataSize;
-    req->frameIn->map(&inData, &inDataSize);
+    if (req->frameIn->map(&inData, &inDataSize) != 0) {
+        lk.unlock();
+        return onDeviceError("%s: V4L2 buffer map failed", __FUNCTION__);
+    }
+
     // TODO: in some special case maybe we can decode jpg directly to gralloc output?
     ATRACE_BEGIN("MJPGtoI420");
     int res = libyuv::MJPGToI420(
diff --git a/camera/device/3.4/default/OWNERS b/camera/device/3.4/default/OWNERS
index 18acfee..369b204 100644
--- a/camera/device/3.4/default/OWNERS
+++ b/camera/device/3.4/default/OWNERS
@@ -1,6 +1,7 @@
 cychen@google.com
 epeev@google.com
 etalvala@google.com
+jchowdhary@google.com
 shuzhenwang@google.com
 yinchiayeh@google.com
 zhijunhe@google.com
diff --git a/camera/device/3.5/Android.bp b/camera/device/3.5/Android.bp
new file mode 100644
index 0000000..2a9ba05
--- /dev/null
+++ b/camera/device/3.5/Android.bp
@@ -0,0 +1,33 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.camera.device@3.5",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "ICameraDevice.hal",
+        "ICameraDeviceCallback.hal",
+        "ICameraDeviceSession.hal",
+    ],
+    interfaces: [
+        "android.hardware.camera.common@1.0",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.camera.device@3.3",
+        "android.hardware.camera.device@3.4",
+        "android.hardware.graphics.common@1.0",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "BufferRequest",
+        "BufferRequestStatus",
+        "StreamBufferRequestError",
+        "StreamBufferRet",
+        "StreamBuffersVal",
+        "StreamConfiguration",
+    ],
+    gen_java: false,
+}
+
diff --git a/camera/device/3.5/ICameraDevice.hal b/camera/device/3.5/ICameraDevice.hal
new file mode 100644
index 0000000..a77380f
--- /dev/null
+++ b/camera/device/3.5/ICameraDevice.hal
@@ -0,0 +1,78 @@
+/*
+ * 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.camera.device@3.5;
+
+import android.hardware.camera.common@1.0::Status;
+import @3.2::CameraMetadata;
+import @3.2::ICameraDevice;
+
+/**
+ * Camera device interface
+ *
+ * Supports the android.hardware.Camera API, and the android.hardware.camera2
+ * API at LIMITED or better hardware level.
+ *
+ */
+interface ICameraDevice extends @3.2::ICameraDevice {
+
+    /**
+     * getPhysicalCameraCharacteristics:
+     *
+     * Return the static camera information for a physical camera ID backing
+     * this logical camera device. This information may not change between consecutive calls.
+     *
+     * Note that HAL must support this function for physical camera IDs that are
+     * not exposed via ICameraProvider::getCameraIdList(). Calling
+     * getCameraDeviceInterface_V3_x() on these camera IDs must return ILLEGAL_ARGUMENT.
+     *
+     * The characteristics of all cameras returned by
+     * ICameraProvider::getCameraIdList() must be queried via
+     * getCameraCharacteristics(). Calling getPhysicalCameraCharacteristics() on
+     * those cameras must return ILLEGAL_ARGUMENT.
+     *
+     * @param physicalCameraId The physical camera id parsed from the logical
+     *     camera's ANDROID_LOGICAL_MULTI_CAMERA_PHYSICAL_IDS static metadata
+     *     key. The framework assumes that this ID is just the <id> part of fully
+     *     qualified camera device name "device@<major>.<minor>/<type>/<id>". And
+     *     the physical camera must be of the same version and type as the parent
+     *     logical camera device.
+     *
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On a successful query of the physical camera device characteristics
+     *     INTERNAL_ERROR:
+     *         The camera device cannot be opened due to an internal
+     *         error.
+     *     CAMERA_DISCONNECTED:
+     *         An external camera device has been disconnected, and is no longer
+     *         available. This camera device interface is now stale, and a new
+     *         instance must be acquired if the device is reconnected. All
+     *         subsequent calls on this interface must return
+     *         CAMERA_DISCONNECTED.
+     *     ILLEGAL_ARGUMENT:
+     *         If the physicalCameraId is not a valid physical camera Id outside
+     *         of ICameraProvider::getCameraIdList().
+     *
+     * @return cameraCharacteristics
+     *     The static metadata for this logical camera device's physical device, or an empty
+     *     metadata structure if status is not OK.
+     *
+     */
+    getPhysicalCameraCharacteristics(string physicalCameraId)
+            generates (Status status, CameraMetadata cameraCharacteristics);
+
+};
diff --git a/camera/device/3.5/ICameraDeviceCallback.hal b/camera/device/3.5/ICameraDeviceCallback.hal
new file mode 100644
index 0000000..aa4ad22
--- /dev/null
+++ b/camera/device/3.5/ICameraDeviceCallback.hal
@@ -0,0 +1,70 @@
+/*
+ * 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.camera.device@3.5;
+
+import @3.2::StreamBuffer;
+import @3.4::ICameraDeviceCallback;
+
+/**
+ * Callback methods for the HAL to call into the framework.
+ */
+interface ICameraDeviceCallback extends @3.4::ICameraDeviceCallback {
+
+    /**
+     * requestStreamBuffers:
+     *
+     * Synchronous callback for HAL to ask for output buffers from camera service.
+     *
+     * This call may be serialized in camera service so it is strongly
+     * recommended to only call this method from one thread.
+     *
+     * When camera device advertises
+     * (CameraMetadataEnumAndroidInfoSupportedBufferManagementVersion ==
+     * ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5), HAL
+     * can use this method to request buffers from camera service.
+     *
+     * @return status Status code for the operation, one of:
+     *     OK: all requested buffers are returned
+     *     FAILED_PARTIAL: some streams failed while some succeeds. Check
+     *             individual StreamBufferRet for details.
+     *     FAILED_CONFIGURING: the request failed because camera servicve is
+     *             performing configureStreams and no buffers are returned.
+     *     FAILED_UNKNOWN: the request failed for unknown reason and no buffers
+     *             are returned.
+     *
+     * Performance requirements:
+     * This is a blocking call that takes more time with more buffers requested.
+     * HAL must not request large amount of buffers on a latency critical code
+     * path. It is highly recommended to use a dedicated thread to perform
+     * all requestStreamBuffers calls, and adjust the thread priority and/or
+     * timing of making the call in order for buffers to arrive before HAL is
+     * ready to fill the buffer.
+     */
+    requestStreamBuffers(vec<BufferRequest> bufReqs)
+            generates (BufferRequestStatus st, vec<StreamBufferRet> buffers);
+
+    /**
+     * returnStreamBuffers:
+     *
+     * Synchronous callback for HAL to return output buffers to camera service.
+     *
+     * If this method is called during a configureStreams call, it must be blocked
+     * until camera service finishes the ongoing configureStreams call.
+     */
+    returnStreamBuffers(vec<StreamBuffer> buffers);
+
+};
diff --git a/camera/device/3.5/ICameraDeviceSession.hal b/camera/device/3.5/ICameraDeviceSession.hal
new file mode 100644
index 0000000..b2b71cd
--- /dev/null
+++ b/camera/device/3.5/ICameraDeviceSession.hal
@@ -0,0 +1,102 @@
+/*
+ * 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.camera.device@3.5;
+
+import android.hardware.camera.common@1.0::Status;
+import @3.4::ICameraDeviceSession;
+import @3.4::HalStreamConfiguration;
+
+/**
+ * Camera device active session interface.
+ *
+ * Obtained via ICameraDevice::open(), this interface contains the methods to
+ * configure and request captures from an active camera device.
+ */
+interface ICameraDeviceSession extends @3.4::ICameraDeviceSession {
+
+    /**
+     * configureStreams_3_5:
+     *
+     * Identical to @3.4::ICameraDeviceSession.configureStreams, except that:
+     *
+     * - a streamConfigCounter counter is provided to check for race condition
+     *   between configureStreams_3_5 and signalStreamFlush call.
+     *
+     * @return status Status code for the operation, one of:
+     *     OK:
+     *         On successful stream configuration.
+     *     INTERNAL_ERROR:
+     *         If there has been a fatal error and the device is no longer
+     *         operational. Only close() can be called successfully by the
+     *         framework after this error is returned.
+     *     ILLEGAL_ARGUMENT:
+     *         If the requested stream configuration is invalid. Some examples
+     *         of invalid stream configurations include:
+     *           - Including more than 1 INPUT stream
+     *           - Not including any OUTPUT streams
+     *           - Including streams with unsupported formats, or an unsupported
+     *             size for that format.
+     *           - Including too many output streams of a certain format.
+     *           - Unsupported rotation configuration
+     *           - Stream sizes/formats don't satisfy the
+     *             StreamConfigurationMode requirements
+     *             for non-NORMAL mode, or the requested operation_mode is not
+     *             supported by the HAL.
+     *           - Unsupported usage flag
+     *         The camera service cannot filter out all possible illegal stream
+     *         configurations, since some devices may support more simultaneous
+     *         streams or larger stream resolutions than the minimum required
+     *         for a given camera device hardware level. The HAL must return an
+     *         ILLEGAL_ARGUMENT for any unsupported stream set, and then be
+     *         ready to accept a future valid stream configuration in a later
+     *         configureStreams call.
+     * @return halConfiguration The stream parameters desired by the HAL for
+     *     each stream, including maximum buffers, the usage flags, and the
+     *     override format.
+     */
+    configureStreams_3_5(@3.5::StreamConfiguration requestedConfiguration)
+            generates (Status status,
+                       @3.4::HalStreamConfiguration halConfiguration);
+
+
+    /**
+     * signalStreamFlush:
+     *
+     * Signaling HAL camera service is about to perform configureStreams_3_5 and
+     * HAL must return all buffers of designated streams. HAL must finish
+     * inflight requests normally and return all buffers that belongs to the
+     * designated streams through processCaptureResult or returnStreamBuffer
+     * API in a timely manner, or camera service will run into a fatal error.
+     *
+     * Note that this call serves as an optional hint and camera service may
+     * skip sending this call if all buffers are already returned.
+     *
+     * @param streamIds The ID of streams camera service need all of its
+     *     buffers returned.
+     *
+     * @param streamConfigCounter Note that due to concurrency nature, it is
+     *     possible the signalStreamFlush call arrives later than the
+     *     corresponding configureStreams_3_5 call, HAL must check
+     *     streamConfigCounter for such race condition. If the counter is less
+     *     than the counter in the last configureStreams_3_5 call HAL last
+     *     received, the call is stale and HAL should just return this call.
+     */
+    oneway signalStreamFlush(
+        vec<int32_t> streamIds,
+        uint32_t streamConfigCounter
+    );
+};
diff --git a/camera/device/3.5/default/Android.bp b/camera/device/3.5/default/Android.bp
new file mode 100644
index 0000000..09cf3a4
--- /dev/null
+++ b/camera/device/3.5/default/Android.bp
@@ -0,0 +1,54 @@
+//
+// 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_library_headers {
+    name: "camera.device@3.5-impl_headers",
+    vendor: true,
+    export_include_dirs: ["include/device_v3_5_impl"]
+}
+
+cc_library_shared {
+    name: "camera.device@3.5-impl",
+    defaults: ["hidl_defaults"],
+    proprietary: true,
+    vendor: true,
+    srcs: [
+        "CameraDevice.cpp",
+        "CameraDeviceSession.cpp",
+    ],
+    shared_libs: [
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+        "libcutils",
+        "camera.device@3.2-impl",
+        "camera.device@3.3-impl",
+        "camera.device@3.4-impl",
+        "android.hardware.camera.device@3.2",
+        "android.hardware.camera.device@3.3",
+        "android.hardware.camera.device@3.4",
+        "android.hardware.camera.device@3.5",
+        "android.hardware.camera.provider@2.4",
+        "android.hardware.graphics.mapper@2.0",
+        "liblog",
+        "libhardware",
+        "libcamera_metadata",
+    ],
+    static_libs: [
+        "android.hardware.camera.common@1.0-helper",
+    ],
+    local_include_dirs: ["include/device_v3_5_impl"],
+}
diff --git a/camera/device/3.5/default/CameraDevice.cpp b/camera/device/3.5/default/CameraDevice.cpp
new file mode 100644
index 0000000..a6969af
--- /dev/null
+++ b/camera/device/3.5/default/CameraDevice.cpp
@@ -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.
+ */
+
+#define LOG_TAG "CamDev@3.5-impl"
+#include <log/log.h>
+
+#include "CameraModule.h"
+#include "CameraDevice_3_5.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_5 {
+namespace implementation {
+
+using namespace ::android::hardware::camera::device;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::device::V3_2::CameraMetadata;
+
+CameraDevice::CameraDevice(sp<CameraModule> module, const std::string& cameraId,
+        const SortedVector<std::pair<std::string, std::string>>& cameraDeviceNames) :
+        V3_4::implementation::CameraDevice(module, cameraId, cameraDeviceNames) {
+}
+
+CameraDevice::~CameraDevice() {
+}
+
+sp<V3_2::implementation::CameraDeviceSession> CameraDevice::createSession(camera3_device_t* device,
+        const camera_metadata_t* deviceInfo,
+        const sp<V3_2::ICameraDeviceCallback>& callback) {
+    sp<CameraDeviceSession> session = new CameraDeviceSession(device, deviceInfo, callback);
+    IF_ALOGV() {
+        session->getInterface()->interfaceChain([](
+            ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
+                ALOGV("Session interface chain:");
+                for (auto iface : interfaceChain) {
+                    ALOGV("  %s", iface.c_str());
+                }
+            });
+    }
+    return session;
+}
+
+Return<void> CameraDevice::getPhysicalCameraCharacteristics(const hidl_string& physicalCameraId,
+        V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb) {
+    Status status = initStatus();
+    CameraMetadata cameraCharacteristics;
+    if (status == Status::OK) {
+        // Require module 2.5+ version.
+        if (mModule->getModuleApiVersion() < CAMERA_MODULE_API_VERSION_2_5) {
+            ALOGE("%s: get_physical_camera_info must be called on camera module 2.5 or newer",
+                    __FUNCTION__);
+            status = Status::INTERNAL_ERROR;
+        } else {
+            char *end;
+            errno = 0;
+            long id = strtol(physicalCameraId.c_str(), &end, 0);
+            if (id > INT_MAX || (errno == ERANGE && id == LONG_MAX) ||
+                    id < INT_MIN || (errno == ERANGE && id == LONG_MIN) ||
+                    *end != '\0') {
+                ALOGE("%s: Invalid physicalCameraId %s", __FUNCTION__, physicalCameraId.c_str());
+                status = Status::ILLEGAL_ARGUMENT;
+            } else {
+                camera_metadata_t *physicalInfo = nullptr;
+                int ret = mModule->getPhysicalCameraInfo((int)id, &physicalInfo);
+                if (ret == OK) {
+                    V3_2::implementation::convertToHidl(physicalInfo, &cameraCharacteristics);
+                } else if (ret == -EINVAL) {
+                    ALOGE("%s: %s is not a valid physical camera Id outside of getCameraIdList()",
+                            __FUNCTION__, physicalCameraId.c_str());
+                    status = Status::ILLEGAL_ARGUMENT;
+                } else {
+                    ALOGE("%s: Failed to get physical camera %s info: %s (%d)!", __FUNCTION__,
+                            physicalCameraId.c_str(), strerror(-ret), ret);
+                    status = Status::INTERNAL_ERROR;
+                }
+            }
+        }
+    }
+    _hidl_cb(status, cameraCharacteristics);
+    return Void();
+}
+
+// End of methods from ::android::hardware::camera::device::V3_2::ICameraDevice.
+
+} // namespace implementation
+}  // namespace V3_5
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
diff --git a/camera/device/3.5/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp
new file mode 100644
index 0000000..963893a
--- /dev/null
+++ b/camera/device/3.5/default/CameraDeviceSession.cpp
@@ -0,0 +1,66 @@
+/*
+ * 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 "CamDevSession@3.5-impl"
+#include <android/log.h>
+
+#include <utils/Trace.h>
+#include "CameraDeviceSession.h"
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_5 {
+namespace implementation {
+
+CameraDeviceSession::CameraDeviceSession(
+    camera3_device_t* device,
+    const camera_metadata_t* deviceInfo,
+    const sp<V3_2::ICameraDeviceCallback>& callback) :
+        V3_4::implementation::CameraDeviceSession(device, deviceInfo, callback) {
+
+    mHasCallback_3_5 = false;
+
+    auto castResult = ICameraDeviceCallback::castFrom(callback);
+    if (castResult.isOk()) {
+        sp<ICameraDeviceCallback> callback3_5 = castResult;
+        if (callback3_5 != nullptr) {
+            mHasCallback_3_5 = true;
+        }
+    }
+}
+
+CameraDeviceSession::~CameraDeviceSession() {
+}
+
+Return<void> CameraDeviceSession::configureStreams_3_5(
+        const StreamConfiguration& requestedConfiguration,
+        ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb)  {
+    return configureStreams_3_4(requestedConfiguration.v3_4, _hidl_cb);
+}
+
+Return<void> CameraDeviceSession::signalStreamFlush(
+        const hidl_vec<int32_t>& /*requests*/, uint32_t /*streamConfigCounter*/) {
+    return Void();
+}
+
+} // namespace implementation
+}  // namespace V3_5
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
diff --git a/camera/device/3.5/default/OWNERS b/camera/device/3.5/default/OWNERS
new file mode 100644
index 0000000..369b204
--- /dev/null
+++ b/camera/device/3.5/default/OWNERS
@@ -0,0 +1,7 @@
+cychen@google.com
+epeev@google.com
+etalvala@google.com
+jchowdhary@google.com
+shuzhenwang@google.com
+yinchiayeh@google.com
+zhijunhe@google.com
diff --git a/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h
new file mode 100644
index 0000000..ec34769
--- /dev/null
+++ b/camera/device/3.5/default/include/device_v3_5_impl/CameraDeviceSession.h
@@ -0,0 +1,157 @@
+/*
+ * 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_CAMERA_DEVICE_V3_5_CAMERADEVICE3SESSION_H
+#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_CAMERADEVICE3SESSION_H
+
+#include <android/hardware/camera/device/3.5/ICameraDevice.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceSession.h>
+#include <android/hardware/camera/device/3.5/ICameraDeviceCallback.h>
+#include <../../3.4/default/include/device_v3_4_impl/CameraDeviceSession.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_5 {
+namespace implementation {
+
+using namespace ::android::hardware::camera::device;
+using ::android::hardware::camera::device::V3_2::CaptureRequest;
+using ::android::hardware::camera::device::V3_5::StreamConfiguration;
+using ::android::hardware::camera::device::V3_4::HalStreamConfiguration;
+using ::android::hardware::camera::device::V3_5::ICameraDeviceSession;
+using ::android::hardware::camera::device::V3_5::ICameraDeviceCallback;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::hardware::camera::common::V1_0::helper::HandleImporter;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::hidl_string;
+using ::android::sp;
+using ::android::Mutex;
+
+struct CameraDeviceSession : public V3_4::implementation::CameraDeviceSession {
+
+    CameraDeviceSession(camera3_device_t*,
+            const camera_metadata_t* deviceInfo,
+            const sp<V3_2::ICameraDeviceCallback>&);
+    virtual ~CameraDeviceSession();
+
+    virtual sp<V3_2::ICameraDeviceSession> getInterface() override {
+        return new TrampolineSessionInterface_3_5(this);
+    }
+
+protected:
+    // Methods from v3.4 and earlier will trampoline to inherited implementation
+    Return<void> configureStreams_3_5(
+            const StreamConfiguration& requestedConfiguration,
+            ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb);
+
+    Return<void> signalStreamFlush(
+            const hidl_vec<int32_t>& requests,
+            uint32_t streamConfigCounter);
+
+
+    // Whether this camera device session is created with version 3.5 callback.
+    bool mHasCallback_3_5;
+
+private:
+
+    struct TrampolineSessionInterface_3_5 : public ICameraDeviceSession {
+        TrampolineSessionInterface_3_5(sp<CameraDeviceSession> parent) :
+                mParent(parent) {}
+
+        virtual Return<void> constructDefaultRequestSettings(
+                V3_2::RequestTemplate type,
+                V3_3::ICameraDeviceSession::constructDefaultRequestSettings_cb _hidl_cb) override {
+            return mParent->constructDefaultRequestSettings(type, _hidl_cb);
+        }
+
+        virtual Return<void> configureStreams(
+                const V3_2::StreamConfiguration& requestedConfiguration,
+                V3_3::ICameraDeviceSession::configureStreams_cb _hidl_cb) override {
+            return mParent->configureStreams(requestedConfiguration, _hidl_cb);
+        }
+
+        virtual Return<void> processCaptureRequest_3_4(
+                const hidl_vec<V3_4::CaptureRequest>& requests,
+                const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+                ICameraDeviceSession::processCaptureRequest_3_4_cb _hidl_cb) override {
+            return mParent->processCaptureRequest_3_4(requests, cachesToRemove, _hidl_cb);
+        }
+
+        virtual Return<void> processCaptureRequest(const hidl_vec<V3_2::CaptureRequest>& requests,
+                const hidl_vec<V3_2::BufferCache>& cachesToRemove,
+                V3_3::ICameraDeviceSession::processCaptureRequest_cb _hidl_cb) override {
+            return mParent->processCaptureRequest(requests, cachesToRemove, _hidl_cb);
+        }
+
+        virtual Return<void> getCaptureRequestMetadataQueue(
+                V3_3::ICameraDeviceSession::getCaptureRequestMetadataQueue_cb _hidl_cb) override  {
+            return mParent->getCaptureRequestMetadataQueue(_hidl_cb);
+        }
+
+        virtual Return<void> getCaptureResultMetadataQueue(
+                V3_3::ICameraDeviceSession::getCaptureResultMetadataQueue_cb _hidl_cb) override  {
+            return mParent->getCaptureResultMetadataQueue(_hidl_cb);
+        }
+
+        virtual Return<Status> flush() override {
+            return mParent->flush();
+        }
+
+        virtual Return<void> close() override {
+            return mParent->close();
+        }
+
+        virtual Return<void> configureStreams_3_3(
+                const V3_2::StreamConfiguration& requestedConfiguration,
+                configureStreams_3_3_cb _hidl_cb) override {
+            return mParent->configureStreams_3_3(requestedConfiguration, _hidl_cb);
+        }
+
+        virtual Return<void> configureStreams_3_4(
+                const V3_4::StreamConfiguration& requestedConfiguration,
+                configureStreams_3_4_cb _hidl_cb) override {
+            return mParent->configureStreams_3_4(requestedConfiguration, _hidl_cb);
+        }
+
+        virtual Return<void> configureStreams_3_5(
+                const StreamConfiguration& requestedConfiguration,
+                configureStreams_3_5_cb _hidl_cb) override {
+            return mParent->configureStreams_3_5(requestedConfiguration, _hidl_cb);
+        }
+
+        virtual Return<void> signalStreamFlush(
+                const hidl_vec<int32_t>& requests,
+                uint32_t streamConfigCounter) override {
+            return mParent->signalStreamFlush(requests, streamConfigCounter);
+        }
+
+    private:
+        sp<CameraDeviceSession> mParent;
+    };
+};
+
+}  // namespace implementation
+}  // namespace V3_5
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_CAMERADEVICE3SESSION_H
diff --git a/camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h b/camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h
new file mode 100644
index 0000000..6bdc60f
--- /dev/null
+++ b/camera/device/3.5/default/include/device_v3_5_impl/CameraDevice_3_5.h
@@ -0,0 +1,111 @@
+/*
+ * 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_CAMERA_DEVICE_V3_5_CAMERADEVICE_H
+#define ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_CAMERADEVICE_H
+
+#include "CameraDeviceSession.h"
+#include <../../../../3.4/default/include/device_v3_4_impl/CameraDevice_3_4.h>
+
+#include <android/hardware/camera/device/3.5/ICameraDevice.h>
+
+namespace android {
+namespace hardware {
+namespace camera {
+namespace device {
+namespace V3_5 {
+namespace implementation {
+
+using namespace ::android::hardware::camera::device;
+
+using ::android::hardware::camera::common::V1_0::helper::CameraModule;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::hidl_string;
+using ::android::hardware::camera::common::V1_0::TorchMode;
+using ::android::hardware::camera::common::V1_0::helper::CameraModule;
+using ::android::hardware::camera::common::V1_0::Status;
+using ::android::sp;
+
+struct CameraDevice : public V3_4::implementation::CameraDevice {
+    // Called by provider HAL.
+    // Provider HAL must ensure the uniqueness of CameraDevice object per cameraId, or there could
+    // be multiple CameraDevice trying to access the same physical camera.  Also, provider will have
+    // to keep track of all CameraDevice objects in order to notify CameraDevice when the underlying
+    // camera is detached.
+    // Delegates nearly all work to CameraDevice_3_4
+    CameraDevice(sp<CameraModule> module,
+                 const std::string& cameraId,
+                 const SortedVector<std::pair<std::string, std::string>>& cameraDeviceNames);
+    virtual ~CameraDevice();
+
+    virtual sp<V3_2::ICameraDevice> getInterface() override {
+        return new TrampolineDeviceInterface_3_5(this);
+    }
+
+protected:
+    virtual sp<V3_2::implementation::CameraDeviceSession> createSession(camera3_device_t*,
+            const camera_metadata_t* deviceInfo,
+            const sp<V3_2::ICameraDeviceCallback>&) override;
+
+    Return<void> getPhysicalCameraCharacteristics(const hidl_string& physicalCameraId,
+            V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb);
+
+private:
+    struct TrampolineDeviceInterface_3_5 : public ICameraDevice {
+        TrampolineDeviceInterface_3_5(sp<CameraDevice> parent) :
+            mParent(parent) {}
+
+        virtual Return<void> getResourceCost(V3_2::ICameraDevice::getResourceCost_cb _hidl_cb)
+                override {
+            return mParent->getResourceCost(_hidl_cb);
+        }
+
+        virtual Return<void> getCameraCharacteristics(
+                V3_2::ICameraDevice::getCameraCharacteristics_cb _hidl_cb) override {
+            return mParent->getCameraCharacteristics(_hidl_cb);
+        }
+
+        virtual Return<Status> setTorchMode(TorchMode mode) override {
+            return mParent->setTorchMode(mode);
+        }
+
+        virtual Return<void> open(const sp<V3_2::ICameraDeviceCallback>& callback,
+                V3_2::ICameraDevice::open_cb _hidl_cb) override {
+            return mParent->open(callback, _hidl_cb);
+        }
+
+        virtual Return<void> dumpState(const hidl_handle& fd) override {
+            return mParent->dumpState(fd);
+        }
+
+        virtual Return<void> getPhysicalCameraCharacteristics(const hidl_string& physicalCameraId,
+                V3_5::ICameraDevice::getPhysicalCameraCharacteristics_cb _hidl_cb) override {
+            return mParent->getPhysicalCameraCharacteristics(physicalCameraId, _hidl_cb);
+        }
+    private:
+        sp<CameraDevice> mParent;
+    };
+};
+
+}  // namespace implementation
+}  // namespace V3_5
+}  // namespace device
+}  // namespace camera
+}  // namespace hardware
+}  // namespace android
+
+#endif // ANDROID_HARDWARE_CAMERA_DEVICE_V3_5_CAMERADEVICE_H
diff --git a/camera/device/3.5/types.hal b/camera/device/3.5/types.hal
new file mode 100644
index 0000000..613187d
--- /dev/null
+++ b/camera/device/3.5/types.hal
@@ -0,0 +1,131 @@
+/*
+ * 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.camera.device@3.5;
+
+import @3.2::StreamBuffer;
+import @3.4::StreamConfiguration;
+
+/**
+ * StreamConfiguration:
+ *
+ * Identical to @3.4::StreamConfiguration, except that it contains streamConfigCounter
+ */
+struct StreamConfiguration {
+    @3.4::StreamConfiguration v3_4;
+
+    /**
+     * An incrementing counter used for HAL to keep track of the stream
+     * configuration and the paired oneway signalStreamFlush call. When the
+     * counter in signalStreamFlush call is less than the counter here, that
+     * signalStreamFlush call is stale.
+     */
+    uint32_t streamConfigCounter;
+};
+
+enum StreamBufferRequestError : uint32_t {
+    /**
+     * Get buffer failed due to timeout waiting for an available buffer. This is
+     * likely due to the client application holding too many buffers, or the
+     * system is under memory pressure.
+     * This is not a fatal error. HAL may try to request buffer for this stream
+     * later. If HAL cannot get a buffer for certain capture request in time
+     * due to this error, HAL can send an ERROR_REQUEST to camera service and
+     * drop processing that request.
+     */
+    NO_BUFFER_AVAILABLE = 1,
+
+    /**
+     * Get buffer failed due to HAL has reached its maxBuffer count. This is not
+     * a fatal error. HAL may try to request buffer for this stream again after
+     * it returns at least one buffer of that stream to camera service.
+     */
+    MAX_BUFFER_EXCEEDED = 2,
+
+    /**
+     * Get buffer failed due to the stream is disconnected by client
+     * application, has been removed, or not recognized by camera service.
+     * This means application is no longer interested in this stream.
+     * Requesting buffer for this stream must never succeed after this error is
+     * returned. HAL must safely return all buffers of this stream after
+     * getting this error. If HAL gets another capture request later targeting
+     * a disconnected stream, HAL must send an ERROR_REQUEST to camera service
+     * and drop processing that request.
+     */
+    STREAM_DISCONNECTED = 3,
+
+    /**
+     * Get buffer failed for unknown reasons. This is a fatal error and HAL must
+     * send ERROR_DEVICE to camera service and be ready to be closed.
+     */
+    UNKNOWN_ERROR = 4
+};
+
+/**
+ * Per-stream return value for requestStreamBuffers.
+ * For each stream, either an StreamBufferRequestError error code, or all
+ * requested buffers for this stream is returned, so buffers.size() must be
+ * equal to BufferRequest::numBuffersRequested of corresponding stream.
+ */
+safe_union StreamBuffersVal {
+    StreamBufferRequestError error;
+    vec<@3.2::StreamBuffer> buffers;
+};
+
+struct StreamBufferRet {
+    int32_t streamId;
+    StreamBuffersVal val;
+};
+
+enum BufferRequestStatus : uint32_t {
+    /**
+     * Method call succeeded and all requested buffers are returned.
+     */
+    OK = 0,
+
+    /**
+     * Method call failed for some streams. Check per stream status for each
+     * returned StreamBufferRet.
+     */
+    FAILED_PARTIAL = 1,
+
+    /**
+     * Method call failed for all streams and no buffers are returned at all.
+     * Camera service is about to or is performing configureStreams. HAL must
+     * wait until next configureStreams call is finished before requesting
+     * buffers again.
+     */
+    FAILED_CONFIGURING = 2,
+
+    /**
+     * Method call failed for all streams and no buffers are returned at all.
+     * Failure due to bad BufferRequest input, eg: unknown streamId or repeated
+     * streamId.
+     */
+    FAILED_ILLEGAL_ARGUMENTS = 3,
+
+    /**
+     * Method call failed for all streams and no buffers are returned at all.
+     * Failure due to unknown reason.
+     */
+    FAILED_UNKNOWN = 4,
+};
+
+struct BufferRequest {
+    int32_t streamId;
+    uint32_t numBuffersRequested;
+};
+
diff --git a/camera/metadata/3.3/types.hal b/camera/metadata/3.3/types.hal
index a37e132..d21bb7c 100644
--- a/camera/metadata/3.3/types.hal
+++ b/camera/metadata/3.3/types.hal
@@ -100,7 +100,7 @@
 
     /** android.request.availablePhysicalCameraRequestKeys [static, int32[], hidden]
      *
-     * <p>A subset of the available request keys that can be overriden for
+     * <p>A subset of the available request keys that can be overridden for
      * physical devices backing a logical multi-camera.</p>
      */
     ANDROID_REQUEST_AVAILABLE_PHYSICAL_CAMERA_REQUEST_KEYS,
diff --git a/camera/metadata/3.4/Android.bp b/camera/metadata/3.4/Android.bp
new file mode 100644
index 0000000..388df68
--- /dev/null
+++ b/camera/metadata/3.4/Android.bp
@@ -0,0 +1,22 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.camera.metadata@3.4",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+    ],
+    interfaces: [
+        "android.hardware.camera.metadata@3.2",
+        "android.hardware.camera.metadata@3.3",
+    ],
+    types: [
+        "CameraMetadataEnumAndroidInfoSupportedBufferManagementVersion",
+        "CameraMetadataTag",
+    ],
+    gen_java: true,
+}
+
diff --git a/camera/metadata/3.4/types.hal b/camera/metadata/3.4/types.hal
new file mode 100644
index 0000000..b228de8
--- /dev/null
+++ b/camera/metadata/3.4/types.hal
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
+package android.hardware.camera.metadata@3.4;
+
+/* Include definitions from all prior minor HAL metadata revisions */
+import android.hardware.camera.metadata@3.2;
+import android.hardware.camera.metadata@3.3;
+
+// No new metadata sections added in this revision
+
+/**
+ * Main enumeration for defining camera metadata tags added in this revision
+ *
+ * <p>Partial documentation is included for each tag; for complete documentation, reference
+ * '/system/media/camera/docs/docs.html' in the corresponding Android source tree.</p>
+ */
+enum CameraMetadataTag : @3.3::CameraMetadataTag {
+    /** android.request.characteristicKeysNeedingPermission [static, int32[], hidden]
+     *
+     * <p>A list of camera characteristics keys that are only available
+     * in case the camera client has camera permission.</p>
+     */
+    ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION = android.hardware.camera.metadata@3.3::CameraMetadataTag:ANDROID_REQUEST_END_3_3,
+
+    ANDROID_REQUEST_END_3_4,
+
+    /** android.info.supportedBufferManagementVersion [static, enum, system]
+     *
+     * <p>The version of buffer management API this camera device supports and opts into.</p>
+     */
+    ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION = android.hardware.camera.metadata@3.3::CameraMetadataTag:ANDROID_INFO_END_3_3,
+
+    ANDROID_INFO_END_3_4,
+
+};
+
+/*
+ * Enumeration definitions for the various entries that need them
+ */
+
+/** android.info.supportedBufferManagementVersion enumeration values
+ * @see ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION
+ */
+enum CameraMetadataEnumAndroidInfoSupportedBufferManagementVersion : uint32_t {
+    ANDROID_INFO_SUPPORTED_BUFFER_MANAGEMENT_VERSION_HIDL_DEVICE_3_5,
+};
diff --git a/camera/provider/2.4/default/Android.bp b/camera/provider/2.4/default/Android.bp
index ae24d78..de02d78 100644
--- a/camera/provider/2.4/default/Android.bp
+++ b/camera/provider/2.4/default/Android.bp
@@ -14,10 +14,12 @@
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.device@3.3",
         "android.hardware.camera.device@3.4",
+        "android.hardware.camera.device@3.5",
         "camera.device@1.0-impl",
         "camera.device@3.2-impl",
         "camera.device@3.3-impl",
         "camera.device@3.4-impl",
+        "camera.device@3.5-impl",
         "camera.device@3.4-external-impl",
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.common@1.0",
@@ -31,6 +33,7 @@
     ],
     header_libs: [
         "camera.device@3.4-impl_headers",
+        "camera.device@3.5-impl_headers",
         "camera.device@3.4-external-impl_headers"
     ],
     static_libs: [
@@ -56,6 +59,7 @@
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.device@3.3",
         "android.hardware.camera.device@3.4",
+        "android.hardware.camera.device@3.5",
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.common@1.0",
     ],
@@ -80,6 +84,7 @@
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.device@3.3",
         "android.hardware.camera.device@3.4",
+        "android.hardware.camera.device@3.5",
         "android.hardware.camera.provider@2.4",
         "android.hardware.camera.common@1.0",
     ],
diff --git a/camera/provider/2.4/default/CameraProvider.cpp b/camera/provider/2.4/default/CameraProvider.cpp
index 6313939..488b9af 100644
--- a/camera/provider/2.4/default/CameraProvider.cpp
+++ b/camera/provider/2.4/default/CameraProvider.cpp
@@ -23,6 +23,7 @@
 #include "CameraDevice_1_0.h"
 #include "CameraDevice_3_3.h"
 #include "CameraDevice_3_4.h"
+#include "CameraDevice_3_5.h"
 #include <cutils/properties.h>
 #include <string.h>
 #include <utils/Trace.h>
@@ -43,6 +44,7 @@
 const char *kHAL3_2 = "3.2";
 const char *kHAL3_3 = "3.3";
 const char *kHAL3_4 = "3.4";
+const char *kHAL3_5 = "3.5";
 const char *kHAL1_0 = "1.0";
 const int kMaxCameraDeviceNameLen = 128;
 const int kMaxCameraIdLen = 16;
@@ -250,7 +252,11 @@
     int versionMajor = isV1 ? 1 : 3;
     int versionMinor = isV1 ? 0 : mPreferredHal3MinorVersion;
     if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_5) {
-        versionMinor = 4;
+        if (mModule->getModuleApiVersion() == CAMERA_MODULE_API_VERSION_2_5) {
+            versionMinor = 5;
+        } else {
+            versionMinor = 4;
+        }
     }
     char deviceName[kMaxCameraDeviceNameLen];
     snprintf(deviceName, sizeof(deviceName), "device@%d.%d/legacy/%s",
@@ -546,63 +552,69 @@
         return Void();
     }
 
-    sp<android::hardware::camera::device::V3_2::ICameraDevice> device;
-    if (deviceVersion == kHAL3_4) {
+    // ICameraDevice 3.4 or upper
+    sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> deviceImpl;
+    if (deviceVersion >= kHAL3_4) {
         ALOGV("Constructing v3.4 camera device");
-        sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> deviceImpl =
-            new android::hardware::camera::device::V3_4::implementation::CameraDevice(
+        if (deviceVersion == kHAL3_4) {
+            deviceImpl = new android::hardware::camera::device::V3_4::implementation::CameraDevice(
                     mModule, cameraId, mCameraDeviceNames);
+        } else if (deviceVersion == kHAL3_5) {
+            deviceImpl = new android::hardware::camera::device::V3_5::implementation::CameraDevice(
+                    mModule, cameraId, mCameraDeviceNames);
+        }
         if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
             ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
-            device = nullptr;
             _hidl_cb(Status::INTERNAL_ERROR, nullptr);
             return Void();
         }
-
-        device = deviceImpl;
-        _hidl_cb (Status::OK, device);
+        IF_ALOGV() {
+            deviceImpl->getInterface()->interfaceChain([](
+                ::android::hardware::hidl_vec<::android::hardware::hidl_string> interfaceChain) {
+                    ALOGV("Device interface chain:");
+                    for (auto iface : interfaceChain) {
+                        ALOGV("  %s", iface.c_str());
+                    }
+                });
+        }
+        _hidl_cb (Status::OK, deviceImpl->getInterface());
         return Void();
     }
 
+    // ICameraDevice 3.2 and 3.3
     // Since some Treble HAL revisions can map to the same legacy HAL version(s), we default
     // to the newest possible Treble HAL revision, but allow for override if needed via
     // system property.
     switch (mPreferredHal3MinorVersion) {
         case 2: { // Map legacy camera device v3 HAL to Treble camera device HAL v3.2
             ALOGV("Constructing v3.2 camera device");
-            sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> deviceImpl =
-                    new android::hardware::camera::device::V3_2::implementation::CameraDevice(
+            deviceImpl = new android::hardware::camera::device::V3_2::implementation::CameraDevice(
                     mModule, cameraId, mCameraDeviceNames);
             if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
                 ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
-                device = nullptr;
                 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
                 return Void();
             }
-            device = deviceImpl;
             break;
         }
         case 3: { // Map legacy camera device v3 HAL to Treble camera device HAL v3.3
             ALOGV("Constructing v3.3 camera device");
-            sp<android::hardware::camera::device::V3_2::implementation::CameraDevice> deviceImpl =
-                    new android::hardware::camera::device::V3_3::implementation::CameraDevice(
+            deviceImpl = new android::hardware::camera::device::V3_3::implementation::CameraDevice(
                     mModule, cameraId, mCameraDeviceNames);
             if (deviceImpl == nullptr || deviceImpl->isInitFailed()) {
                 ALOGE("%s: camera device %s init failed!", __FUNCTION__, cameraId.c_str());
-                device = nullptr;
                 _hidl_cb(Status::INTERNAL_ERROR, nullptr);
                 return Void();
             }
-            device = deviceImpl;
             break;
         }
         default:
             ALOGE("%s: Unknown HAL minor version %d!", __FUNCTION__, mPreferredHal3MinorVersion);
-            device = nullptr;
             _hidl_cb(Status::INTERNAL_ERROR, nullptr);
             return Void();
     }
-    _hidl_cb (Status::OK, device);
+
+    _hidl_cb (Status::OK, deviceImpl->getInterface());
     return Void();
 }
 
diff --git a/camera/provider/2.4/default/OWNERS b/camera/provider/2.4/default/OWNERS
index 18acfee..369b204 100644
--- a/camera/provider/2.4/default/OWNERS
+++ b/camera/provider/2.4/default/OWNERS
@@ -1,6 +1,7 @@
 cychen@google.com
 epeev@google.com
 etalvala@google.com
+jchowdhary@google.com
 shuzhenwang@google.com
 yinchiayeh@google.com
 zhijunhe@google.com
diff --git a/camera/provider/2.4/vts/functional/Android.bp b/camera/provider/2.4/vts/functional/Android.bp
index ead4083..eb8d43e 100644
--- a/camera/provider/2.4/vts/functional/Android.bp
+++ b/camera/provider/2.4/vts/functional/Android.bp
@@ -37,6 +37,7 @@
         "android.hardware.camera.device@3.2",
         "android.hardware.camera.device@3.3",
         "android.hardware.camera.device@3.4",
+        "android.hardware.camera.device@3.5",
         "android.hardware.camera.provider@2.4",
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.common@1.0",
diff --git a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
index 439333d..94d06e8 100644
--- a/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
+++ b/camera/provider/2.4/vts/functional/VtsHalCameraProviderV2_4TargetTest.cpp
@@ -28,6 +28,7 @@
 
 #include <android/hardware/camera/device/1.0/ICameraDevice.h>
 #include <android/hardware/camera/device/3.2/ICameraDevice.h>
+#include <android/hardware/camera/device/3.5/ICameraDevice.h>
 #include <android/hardware/camera/device/3.3/ICameraDeviceSession.h>
 #include <android/hardware/camera/device/3.4/ICameraDeviceSession.h>
 #include <android/hardware/camera/device/3.4/ICameraDeviceCallback.h>
@@ -144,10 +145,12 @@
 namespace {
     // "device@<version>/legacy/<id>"
     const char *kDeviceNameRE = "device@([0-9]+\\.[0-9]+)/%s/(.+)";
+    const int CAMERA_DEVICE_API_VERSION_3_5 = 0x305;
     const int CAMERA_DEVICE_API_VERSION_3_4 = 0x304;
     const int CAMERA_DEVICE_API_VERSION_3_3 = 0x303;
     const int CAMERA_DEVICE_API_VERSION_3_2 = 0x302;
     const int CAMERA_DEVICE_API_VERSION_1_0 = 0x100;
+    const char *kHAL3_5 = "3.5";
     const char *kHAL3_4 = "3.4";
     const char *kHAL3_3 = "3.3";
     const char *kHAL3_2 = "3.2";
@@ -182,7 +185,9 @@
             return -1;
         }
 
-        if (version.compare(kHAL3_4) == 0) {
+        if (version.compare(kHAL3_5) == 0) {
+            return CAMERA_DEVICE_API_VERSION_3_5;
+        } else if (version.compare(kHAL3_4) == 0) {
             return CAMERA_DEVICE_API_VERSION_3_4;
         } else if (version.compare(kHAL3_3) == 0) {
             return CAMERA_DEVICE_API_VERSION_3_3;
@@ -670,12 +675,19 @@
             HalStreamConfiguration *halStreamConfig /*out*/,
             bool *supportsPartialResults /*out*/,
             uint32_t *partialResultCount /*out*/);
+
+    void verifyLogicalCameraMetadata(const std::string& cameraName,
+            const ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice>& device,
+            const CameraMetadata& chars, int deviceVersion,
+            const hidl_vec<hidl_string>& deviceNames);
+    void verifyCameraCharacteristics(Status status, const CameraMetadata& chars);
+
     static Status getAvailableOutputStreams(camera_metadata_t *staticMeta,
             std::vector<AvailableStream> &outputStreams,
             const AvailableStream *threshold = nullptr);
     static Status isConstrainedModeAvailable(camera_metadata_t *staticMeta);
-    static Status isLogicalMultiCamera(camera_metadata_t *staticMeta);
-    static Status getPhysicalCameraIds(camera_metadata_t *staticMeta,
+    static Status isLogicalMultiCamera(const camera_metadata_t *staticMeta);
+    static Status getPhysicalCameraIds(const camera_metadata_t *staticMeta,
             std::unordered_set<std::string> *physicalIds/*out*/);
     static Status getSupportedKeys(camera_metadata_t *staticMeta,
             uint32_t tagId, std::unordered_set<int32_t> *requestIDs/*out*/);
@@ -1172,6 +1184,14 @@
     }
     ASSERT_GT(firstApiLevel, 0); // first_api_level must exist
 
+    // all devices with first API level == 28 and <= 1GB of RAM must set low_ram
+    // and thus be allowed to continue using HAL1
+    if ((firstApiLevel == HAL1_PHASE_OUT_API_LEVEL) &&
+        (property_get_bool("ro.config.low_ram", /*default*/ false))) {
+        ALOGI("Hal1 allowed for low ram device");
+        return;
+    }
+
     if (firstApiLevel >= HAL1_PHASE_OUT_API_LEVEL) {
         hidl_vec<hidl_string> cameraDeviceNames = getCameraDeviceNames(mProvider);
         for (const auto& name : cameraDeviceNames) {
@@ -1258,6 +1278,7 @@
     for (const auto& name : cameraDeviceNames) {
         int deviceVersion = getCameraDeviceVersion(name, mProviderType);
         switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_5:
             case CAMERA_DEVICE_API_VERSION_3_4:
             case CAMERA_DEVICE_API_VERSION_3_3:
             case CAMERA_DEVICE_API_VERSION_3_2: {
@@ -1299,6 +1320,7 @@
     for (const auto& name : cameraDeviceNames) {
         int deviceVersion = getCameraDeviceVersion(name, mProviderType);
         switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_5:
             case CAMERA_DEVICE_API_VERSION_3_4:
             case CAMERA_DEVICE_API_VERSION_3_3:
             case CAMERA_DEVICE_API_VERSION_3_2: {
@@ -2039,6 +2061,7 @@
     for (const auto& name : cameraDeviceNames) {
         int deviceVersion = getCameraDeviceVersion(name, mProviderType);
         switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_5:
             case CAMERA_DEVICE_API_VERSION_3_4:
             case CAMERA_DEVICE_API_VERSION_3_3:
             case CAMERA_DEVICE_API_VERSION_3_2: {
@@ -2055,33 +2078,31 @@
                 ASSERT_TRUE(ret.isOk());
 
                 ret = device3_x->getCameraCharacteristics([&](auto status, const auto& chars) {
-                    ALOGI("getCameraCharacteristics returns status:%d", (int)status);
-                    ASSERT_EQ(Status::OK, status);
-                    const camera_metadata_t* metadata = (camera_metadata_t*)chars.data();
-                    size_t expectedSize = chars.size();
-                    int result = validate_camera_metadata_structure(metadata, &expectedSize);
-                    ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
-                    size_t entryCount = get_camera_metadata_entry_count(metadata);
-                    // TODO: we can do better than 0 here. Need to check how many required
-                    // characteristics keys we've defined.
-                    ASSERT_GT(entryCount, 0u);
-                    ALOGI("getCameraCharacteristics metadata entry count is %zu", entryCount);
+                    verifyCameraCharacteristics(status, chars);
 
-                    camera_metadata_ro_entry entry;
-                    int retcode = find_camera_metadata_ro_entry(metadata,
-                            ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &entry);
-                    if ((0 == retcode) && (entry.count > 0)) {
-                        uint8_t hardwareLevel = entry.data.u8[0];
-                        ASSERT_TRUE(
-                                hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED ||
-                                hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL ||
-                                hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3 ||
-                                hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL);
-                    } else {
-                        ADD_FAILURE() << "Get camera hardware level failed!";
-                    }
+                    verifyLogicalCameraMetadata(name, device3_x, chars, deviceVersion,
+                            cameraDeviceNames);
                 });
                 ASSERT_TRUE(ret.isOk());
+
+                //getPhysicalCameraCharacteristics will fail for publicly
+                //advertised camera IDs.
+                if (deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5) {
+                    auto castResult = device::V3_5::ICameraDevice::castFrom(device3_x);
+                    ASSERT_TRUE(castResult.isOk());
+                    ::android::sp<::android::hardware::camera::device::V3_5::ICameraDevice>
+                            device3_5 = castResult;
+                    ASSERT_NE(device3_5, nullptr);
+
+                    std::string version, cameraId;
+                    ASSERT_TRUE(::matchDeviceName(name, mProviderType, &version, &cameraId));
+                    Return<void> ret = device3_5->getPhysicalCameraCharacteristics(cameraId,
+                            [&](auto status, const auto& chars) {
+                        ASSERT_TRUE(Status::ILLEGAL_ARGUMENT == status);
+                        ASSERT_EQ(0, chars.size());
+                    });
+                    ASSERT_TRUE(ret.isOk());
+                }
             }
             break;
             case CAMERA_DEVICE_API_VERSION_1_0: {
@@ -2118,6 +2139,7 @@
     for (const auto& name : cameraDeviceNames) {
         int deviceVersion = getCameraDeviceVersion(name, mProviderType);
         switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_5:
             case CAMERA_DEVICE_API_VERSION_3_4:
             case CAMERA_DEVICE_API_VERSION_3_3:
             case CAMERA_DEVICE_API_VERSION_3_2: {
@@ -2243,6 +2265,7 @@
     for (const auto& name : cameraDeviceNames) {
         int deviceVersion = getCameraDeviceVersion(name, mProviderType);
         switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_5:
             case CAMERA_DEVICE_API_VERSION_3_4:
             case CAMERA_DEVICE_API_VERSION_3_3:
             case CAMERA_DEVICE_API_VERSION_3_2: {
@@ -2307,6 +2330,7 @@
     for (const auto& name : cameraDeviceNames) {
         int deviceVersion = getCameraDeviceVersion(name, mProviderType);
         switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_5:
             case CAMERA_DEVICE_API_VERSION_3_4:
             case CAMERA_DEVICE_API_VERSION_3_3:
             case CAMERA_DEVICE_API_VERSION_3_2: {
@@ -2335,7 +2359,8 @@
                 sp<device::V3_3::ICameraDeviceSession> sessionV3_3;
                 sp<device::V3_4::ICameraDeviceSession> sessionV3_4;
                 castSession(session, deviceVersion, &sessionV3_3, &sessionV3_4);
-                if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_4) {
+                if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_4 ||
+                        deviceVersion == CAMERA_DEVICE_API_VERSION_3_5) {
                     ASSERT_TRUE(sessionV3_4.get() != nullptr);
                 } else if (deviceVersion == CAMERA_DEVICE_API_VERSION_3_3) {
                     ASSERT_TRUE(sessionV3_3.get() != nullptr);
@@ -2393,6 +2418,7 @@
     for (const auto& name : cameraDeviceNames) {
         int deviceVersion = getCameraDeviceVersion(name, mProviderType);
         switch (deviceVersion) {
+            case CAMERA_DEVICE_API_VERSION_3_5:
             case CAMERA_DEVICE_API_VERSION_3_4:
             case CAMERA_DEVICE_API_VERSION_3_3:
             case CAMERA_DEVICE_API_VERSION_3_2: {
@@ -4136,7 +4162,7 @@
 }
 
 // Check if the camera device has logical multi-camera capability.
-Status CameraHidlTest::isLogicalMultiCamera(camera_metadata_t *staticMeta) {
+Status CameraHidlTest::isLogicalMultiCamera(const camera_metadata_t *staticMeta) {
     Status ret = Status::METHOD_NOT_SUPPORTED;
     if (nullptr == staticMeta) {
         return Status::ILLEGAL_ARGUMENT;
@@ -4160,7 +4186,7 @@
 }
 
 // Generate a list of physical camera ids backing a logical multi-camera.
-Status CameraHidlTest::getPhysicalCameraIds(camera_metadata_t *staticMeta,
+Status CameraHidlTest::getPhysicalCameraIds(const camera_metadata_t *staticMeta,
         std::unordered_set<std::string> *physicalIds) {
     if ((nullptr == staticMeta) || (nullptr == physicalIds)) {
         return Status::ILLEGAL_ARGUMENT;
@@ -4633,6 +4659,7 @@
     ASSERT_NE(nullptr, session3_4);
 
     switch (deviceVersion) {
+        case CAMERA_DEVICE_API_VERSION_3_5:
         case CAMERA_DEVICE_API_VERSION_3_4: {
             auto castResult = device::V3_4::ICameraDeviceSession::castFrom(session);
             ASSERT_TRUE(castResult.isOk());
@@ -4651,6 +4678,101 @@
     }
 }
 
+// Verify logical camera static metadata
+void CameraHidlTest::verifyLogicalCameraMetadata(const std::string& cameraName,
+        const ::android::sp<::android::hardware::camera::device::V3_2::ICameraDevice>& device,
+        const CameraMetadata &chars, int deviceVersion,
+        const hidl_vec<hidl_string>& deviceNames) {
+    const camera_metadata_t* metadata = (camera_metadata_t*)chars.data();
+    ASSERT_NE(nullptr, metadata);
+
+    Status rc = isLogicalMultiCamera(metadata);
+    ASSERT_TRUE(Status::OK == rc || Status::METHOD_NOT_SUPPORTED == rc);
+    if (Status::METHOD_NOT_SUPPORTED == rc) {
+        return;
+    }
+
+    std::string version, cameraId;
+    ASSERT_TRUE(::matchDeviceName(cameraName, mProviderType, &version, &cameraId));
+    std::unordered_set<std::string> physicalIds;
+    ASSERT_TRUE(Status::OK == getPhysicalCameraIds(metadata, &physicalIds));
+    for (auto physicalId : physicalIds) {
+        ASSERT_NE(physicalId, cameraId);
+        bool isPublicId = false;
+        for (auto& deviceName : deviceNames) {
+            std::string publicVersion, publicId;
+            ASSERT_TRUE(::matchDeviceName(deviceName, mProviderType, &publicVersion, &publicId));
+            if (physicalId == publicId) {
+                isPublicId = true;
+                break;
+            }
+        }
+        if (isPublicId) {
+            continue;
+        }
+
+        ASSERT_TRUE(deviceVersion >= CAMERA_DEVICE_API_VERSION_3_5);
+        auto castResult = device::V3_5::ICameraDevice::castFrom(device);
+        ASSERT_TRUE(castResult.isOk());
+        ::android::sp<::android::hardware::camera::device::V3_5::ICameraDevice> device3_5 =
+                castResult;
+        ASSERT_NE(device3_5, nullptr);
+
+        // Check camera characteristics for hidden camera id
+        Return<void> ret = device3_5->getPhysicalCameraCharacteristics(physicalId,
+                [&](auto status, const auto& chars) {
+            verifyCameraCharacteristics(status, chars);
+        });
+        ASSERT_TRUE(ret.isOk());
+
+        // Check calling getCameraDeviceInterface_V3_x() on hidden camera id returns
+        // ILLEGAL_ARGUMENT.
+        std::stringstream s;
+        s << "device@" << version << "/" << mProviderType << "/" << physicalId;
+        hidl_string fullPhysicalId(s.str());
+        ret = mProvider->getCameraDeviceInterface_V3_x(fullPhysicalId,
+                [&](auto status, const auto& device3_x) {
+            ASSERT_EQ(Status::ILLEGAL_ARGUMENT, status);
+            ASSERT_EQ(device3_x, nullptr);
+        });
+        ASSERT_TRUE(ret.isOk());
+    }
+}
+
+void CameraHidlTest::verifyCameraCharacteristics(Status status, const CameraMetadata& chars) {
+    ASSERT_EQ(Status::OK, status);
+    const camera_metadata_t* metadata = (camera_metadata_t*)chars.data();
+    size_t expectedSize = chars.size();
+    int result = validate_camera_metadata_structure(metadata, &expectedSize);
+    ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
+    size_t entryCount = get_camera_metadata_entry_count(metadata);
+    // TODO: we can do better than 0 here. Need to check how many required
+    // characteristics keys we've defined.
+    ASSERT_GT(entryCount, 0u);
+
+    camera_metadata_ro_entry entry;
+    int retcode = find_camera_metadata_ro_entry(metadata,
+            ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL, &entry);
+    if ((0 == retcode) && (entry.count > 0)) {
+        uint8_t hardwareLevel = entry.data.u8[0];
+        ASSERT_TRUE(
+                hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED ||
+                hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_FULL ||
+                hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_3 ||
+                hardwareLevel == ANDROID_INFO_SUPPORTED_HARDWARE_LEVEL_EXTERNAL);
+    } else {
+        ADD_FAILURE() << "Get camera hardware level failed!";
+    }
+
+    entry.count = 0;
+    retcode = find_camera_metadata_ro_entry(metadata,
+            ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION, &entry);
+    if ((0 == retcode) || (entry.count > 0)) {
+        ADD_FAILURE() << "ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION "
+            << " per API contract should never be set by Hal!";
+    }
+}
+
 // Open a device session with empty callbacks and return static metadata.
 void CameraHidlTest::openEmptyDeviceSession(const std::string &name,
         sp<ICameraProvider> provider,
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
new file mode 100644
index 0000000..49674e3
--- /dev/null
+++ b/compatibility_matrices/Android.bp
@@ -0,0 +1,77 @@
+// 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.
+
+vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.legacy.xml",
+    stem: "compatibility_matrix.legacy.xml",
+    srcs: [
+        "compatibility_matrix.legacy.xml",
+    ],
+    kernel_configs: [
+        // legacy uses O kernel requirements
+        "kernel_config_o_3.18",
+        "kernel_config_o_4.4",
+        "kernel_config_o_4.9",
+    ]
+}
+vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.1.xml",
+    stem: "compatibility_matrix.1.xml",
+    srcs: [
+        "compatibility_matrix.1.xml",
+    ],
+    kernel_configs: [
+        "kernel_config_o_3.18",
+        "kernel_config_o_4.4",
+        "kernel_config_o_4.9",
+    ]
+}
+vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.2.xml",
+    stem: "compatibility_matrix.2.xml",
+    srcs: [
+        "compatibility_matrix.2.xml",
+    ],
+    kernel_configs: [
+        "kernel_config_o_mr1_3.18",
+        "kernel_config_o_mr1_4.4",
+        "kernel_config_o_mr1_4.9",
+    ]
+}
+
+vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.3.xml",
+    stem: "compatibility_matrix.3.xml",
+    srcs: [
+        "compatibility_matrix.3.xml",
+    ],
+    kernel_configs: [
+        "kernel_config_p_4.4",
+        "kernel_config_p_4.9",
+        "kernel_config_p_4.14",
+    ]
+}
+
+vintf_compatibility_matrix {
+    name: "framework_compatibility_matrix.current.xml",
+    stem: "compatibility_matrix.current.xml",
+    srcs: [
+        "compatibility_matrix.current.xml",
+    ],
+    kernel_configs: [
+        "kernel_config_current_4.4",
+        "kernel_config_current_4.9",
+        "kernel_config_current_4.14",
+    ]
+}
diff --git a/compatibility_matrices/Android.mk b/compatibility_matrices/Android.mk
index 22d0412..6be6930 100644
--- a/compatibility_matrices/Android.mk
+++ b/compatibility_matrices/Android.mk
@@ -18,72 +18,6 @@
 
 BUILD_FRAMEWORK_COMPATIBILITY_MATRIX := $(LOCAL_PATH)/compatibility_matrix.mk
 
-my_kernel_config_data := kernel/configs
-
-# Install all compatibility_matrix.*.xml to /system/etc/vintf
-
-include $(CLEAR_VARS)
-include $(LOCAL_PATH)/clear_vars.mk
-LOCAL_MODULE := framework_compatibility_matrix.legacy.xml
-LOCAL_MODULE_STEM := compatibility_matrix.legacy.xml
-LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
-LOCAL_KERNEL_CONFIG_DATA_PATHS := \
-    3.18.0:$(my_kernel_config_data)/o/android-3.18 \
-    4.4.0:$(my_kernel_config_data)/o/android-4.4 \
-    4.9.0:$(my_kernel_config_data)/o/android-4.9 \
-
-include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
-
-include $(CLEAR_VARS)
-include $(LOCAL_PATH)/clear_vars.mk
-LOCAL_MODULE := framework_compatibility_matrix.1.xml
-LOCAL_MODULE_STEM := compatibility_matrix.1.xml
-LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
-LOCAL_KERNEL_CONFIG_DATA_PATHS := \
-    3.18.0:$(my_kernel_config_data)/o/android-3.18 \
-    4.4.0:$(my_kernel_config_data)/o/android-4.4 \
-    4.9.0:$(my_kernel_config_data)/o/android-4.9 \
-
-include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
-
-include $(CLEAR_VARS)
-include $(LOCAL_PATH)/clear_vars.mk
-LOCAL_MODULE := framework_compatibility_matrix.2.xml
-LOCAL_MODULE_STEM := compatibility_matrix.2.xml
-LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
-LOCAL_KERNEL_CONFIG_DATA_PATHS := \
-    3.18.0:$(my_kernel_config_data)/o-mr1/android-3.18 \
-    4.4.0:$(my_kernel_config_data)/o-mr1/android-4.4 \
-    4.9.0:$(my_kernel_config_data)/o-mr1/android-4.9 \
-
-include $(BUILD_FRAMEWORK_COMPATIBILITY_MATRIX)
-
-include $(CLEAR_VARS)
-include $(LOCAL_PATH)/clear_vars.mk
-LOCAL_MODULE := framework_compatibility_matrix.3.xml
-LOCAL_MODULE_STEM := compatibility_matrix.3.xml
-LOCAL_SRC_FILES := $(LOCAL_MODULE_STEM)
-LOCAL_KERNEL_CONFIG_DATA_PATHS := \
-    4.4.107:$(my_kernel_config_data)/p/android-4.4 \
-    4.9.84:$(my_kernel_config_data)/p/android-4.9 \
-    4.14.42:$(my_kernel_config_data)/p/android-4.14 \
-
-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)
 
 include $(CLEAR_VARS)
diff --git a/compatibility_matrices/build/Android.bp b/compatibility_matrices/build/Android.bp
new file mode 100644
index 0000000..42dc886
--- /dev/null
+++ b/compatibility_matrices/build/Android.bp
@@ -0,0 +1,29 @@
+// 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.
+
+bootstrap_go_package {
+    name: "vintf-compatibility-matrix-soong-rules",
+    pkgPath: "android/soong/vintf-compatibility-matrix",
+    deps: [
+        "blueprint",
+        "blueprint-proptools",
+        "kernel-config-soong-rules",
+        "soong",
+        "soong-android",
+    ],
+    srcs: [
+        "vintf_compatibility_matrix.go",
+    ],
+    pluginFor: ["soong_build"],
+}
diff --git a/compatibility_matrices/build/vintf_compatibility_matrix.go b/compatibility_matrices/build/vintf_compatibility_matrix.go
new file mode 100644
index 0000000..e48f993
--- /dev/null
+++ b/compatibility_matrices/build/vintf_compatibility_matrix.go
@@ -0,0 +1,132 @@
+// 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 vintf
+
+import (
+	"fmt"
+	"io"
+	"strings"
+
+	"github.com/google/blueprint"
+	"github.com/google/blueprint/proptools"
+
+	"android/soong/android"
+	"android/soong/kernel/configs"
+)
+
+type dependencyTag struct {
+	blueprint.BaseDependencyTag
+	name string
+}
+
+var (
+	pctx = android.NewPackageContext("android/vintf")
+
+	assembleVintfRule = pctx.AndroidStaticRule("assemble_vintf", blueprint.RuleParams{
+		Command:     `${assembleVintfCmd} -i ${inputs} -o ${out}`,
+		CommandDeps: []string{"${assembleVintfCmd}"},
+		Description: "assemble_vintf -i ${inputs}",
+	}, "inputs")
+
+	kernelConfigTag = dependencyTag{name: "kernel-config"}
+)
+
+const (
+	relpath = "vintf"
+)
+
+type vintfCompatibilityMatrixProperties struct {
+	// set the name of the output
+	Stem *string
+
+	// list of source compatibility matrix XML files
+	Srcs []string
+
+	// list of kernel_config modules to be combined to final output
+	Kernel_configs []string
+}
+
+type vintfCompatibilityMatrixRule struct {
+	android.ModuleBase
+	properties vintfCompatibilityMatrixProperties
+
+	genFile android.WritablePath
+}
+
+func init() {
+	pctx.HostBinToolVariable("assembleVintfCmd", "assemble_vintf")
+	android.RegisterModuleType("vintf_compatibility_matrix", vintfCompatibilityMatrixFactory)
+}
+
+func vintfCompatibilityMatrixFactory() android.Module {
+	g := &vintfCompatibilityMatrixRule{}
+	g.AddProperties(&g.properties)
+	android.InitAndroidArchModule(g, android.DeviceSupported, android.MultilibCommon)
+	return g
+}
+
+var _ android.AndroidMkDataProvider = (*vintfCompatibilityMatrixRule)(nil)
+
+func (g *vintfCompatibilityMatrixRule) DepsMutator(ctx android.BottomUpMutatorContext) {
+	android.ExtractSourcesDeps(ctx, g.properties.Srcs)
+	ctx.AddDependency(ctx.Module(), kernelConfigTag, g.properties.Kernel_configs...)
+}
+
+func (g *vintfCompatibilityMatrixRule) GenerateAndroidBuildActions(ctx android.ModuleContext) {
+
+	outputFilename := proptools.String(g.properties.Stem)
+	if outputFilename == "" {
+		outputFilename = g.Name()
+	}
+
+	inputPaths := android.PathsForModuleSrc(ctx, g.properties.Srcs)
+	ctx.VisitDirectDepsWithTag(kernelConfigTag, func(m android.Module) {
+		if k, ok := m.(*configs.KernelConfigRule); ok {
+			inputPaths = append(inputPaths, k.OutputPath())
+		} else {
+			ctx.PropertyErrorf("kernel_config",
+				"module %q is not a kernel_config", ctx.OtherModuleName(m))
+		}
+	})
+
+	g.genFile = android.PathForModuleGen(ctx, outputFilename)
+
+	ctx.Build(pctx, android.BuildParams{
+		Rule:        assembleVintfRule,
+		Description: "Framework Compatibility Matrix",
+		Implicits:   inputPaths,
+		Output:      g.genFile,
+		Args: map[string]string{
+			"inputs": strings.Join(inputPaths.Strings(), ":"),
+		},
+	})
+
+	ctx.InstallFile(android.PathForModuleInstall(ctx, "etc", relpath), outputFilename, g.genFile)
+}
+
+func (g *vintfCompatibilityMatrixRule) AndroidMk() android.AndroidMkData {
+	return android.AndroidMkData{
+		Class:      "ETC",
+		OutputFile: android.OptionalPathForPath(g.genFile),
+		Extra: []android.AndroidMkExtraFunc{
+			func(w io.Writer, outputFile android.Path) {
+				fmt.Fprintln(w, "LOCAL_MODULE_RELATIVE_PATH :=", relpath)
+				if proptools.String(g.properties.Stem) != "" {
+					fmt.Fprintln(w, "LOCAL_MODULE_STEM :=", proptools.String(g.properties.Stem))
+				}
+			},
+		},
+	}
+}
diff --git a/compatibility_matrices/compatibility_matrix.3.xml b/compatibility_matrices/compatibility_matrix.3.xml
index fc7bad6..e13d293 100644
--- a/compatibility_matrices/compatibility_matrix.3.xml
+++ b/compatibility_matrices/compatibility_matrix.3.xml
@@ -445,7 +445,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.wifi.hostapd</name>
-        <version>1.0-1</version>
+        <version>1.0</version>
         <interface>
             <name>IHostapd</name>
             <instance>default</instance>
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index b9cb093..b64ff86 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -1,5 +1,13 @@
 <compatibility-matrix version="1.0" type="framework" level="4">
     <hal format="hidl" optional="false">
+        <name>android.hardware.atrace</name>
+        <version>1.0</version>
+        <interface>
+            <name>IAtraceDevice</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="false">
         <name>android.hardware.audio</name>
         <version>4.0</version>
         <interface>
@@ -48,6 +56,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.biometrics.face</name>
+        <version>1.0</version>
+        <interface>
+            <name>IBiometricsFace</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.biometrics.fingerprint</name>
         <version>2.1</version>
         <interface>
@@ -208,10 +224,10 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
-        <name>android.hardware.health.filesystem</name>
+        <name>android.hardware.health.storage</name>
         <version>1.0</version>
         <interface>
-            <name>IFileSystem</name>
+            <name>IStorage</name>
             <instance>default</instance>
         </interface>
     </hal>
@@ -301,6 +317,14 @@
         </interface>
     </hal>
     <hal format="hidl" optional="true">
+        <name>android.hardware.power.stats</name>
+        <version>1.0</version>
+        <interface>
+            <name>IPowerStats</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl" optional="true">
         <name>android.hardware.radio</name>
         <version>1.0-2</version>
         <interface>
@@ -445,7 +469,7 @@
     </hal>
     <hal format="hidl" optional="true">
         <name>android.hardware.wifi.hostapd</name>
-        <version>1.0</version>
+        <version>1.0-1</version>
         <interface>
             <name>IHostapd</name>
             <instance>default</instance>
diff --git a/configstore/1.0/ISurfaceFlingerConfigs.hal b/configstore/1.0/ISurfaceFlingerConfigs.hal
index 0790905..1de7570 100644
--- a/configstore/1.0/ISurfaceFlingerConfigs.hal
+++ b/configstore/1.0/ISurfaceFlingerConfigs.hal
@@ -61,7 +61,7 @@
     hasWideColorDisplay() generates (OptionalBool value);
 
     /**
-     * hwHdrDisplay indicates that the device has an High Dynamic Range display.
+     * 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
diff --git a/configstore/1.2/Android.bp b/configstore/1.2/Android.bp
index a20eb34..cc5644c 100644
--- a/configstore/1.2/Android.bp
+++ b/configstore/1.2/Android.bp
@@ -12,6 +12,7 @@
     interfaces: [
         "android.hardware.configstore@1.1",
         "android.hardware.configstore@1.0",
+        "android.hardware.graphics.common@1.1",
         "android.hidl.base@1.0",
     ],
     gen_java: true,
diff --git a/configstore/1.2/ISurfaceFlingerConfigs.hal b/configstore/1.2/ISurfaceFlingerConfigs.hal
index c32cc82..c879155 100644
--- a/configstore/1.2/ISurfaceFlingerConfigs.hal
+++ b/configstore/1.2/ISurfaceFlingerConfigs.hal
@@ -15,6 +15,8 @@
  */
 package android.hardware.configstore@1.2;
 
+import android.hardware.graphics.common@1.1::Dataspace;
+import android.hardware.graphics.common@1.1::PixelFormat;
 import @1.1::ISurfaceFlingerConfigs;
 import @1.0::OptionalBool;
 
@@ -30,4 +32,27 @@
      * return true.
      */
     useColorManagement() generates (OptionalBool value);
+
+    /**
+     * Returns the default data space and default pixel format that
+     * SurfaceFlinger expects to receive and output.
+     * To determine the default data space and default pixel format,
+     * there are a few things we recommend to consider:
+     *
+     *   1. Hardware composer's capability to composite contents with the
+     *      data space and pixel format efficiently;
+     *   2. Hardware composer's ability to composite contents when sRGB contents
+     *      and the chosen data space contents coexist;
+     *   3. For better blending, consider using pixel format where the alpha
+     *      channel has as many bits as the RGB color channel.
+     *
+     * @return dataSpace is the default data space that SurfaceFlinger expects.
+     *         The data space must not be Dataspace::UNKNOWN, if unspecified,
+     *         the default data space is Dataspace::V0_SRGB;
+     * @return pixelFormat is the default pixel format that SurfaceFlinger
+     *         expects. If unspecified, the default pixel format is
+     *         PixelFormat::RGBA_8888.
+     */
+    getCompositionPreference()
+        generates (Dataspace dataSpace, PixelFormat pixelFormat);
 };
diff --git a/configstore/1.2/default/SurfaceFlingerConfigs.cpp b/configstore/1.2/default/SurfaceFlingerConfigs.cpp
index c7bd567..ae19dc0 100644
--- a/configstore/1.2/default/SurfaceFlingerConfigs.cpp
+++ b/configstore/1.2/default/SurfaceFlingerConfigs.cpp
@@ -17,6 +17,7 @@
 #include "SurfaceFlingerConfigs.h"
 
 #include <android/hardware/configstore/1.1/types.h>
+#include <android/hardware/graphics/common/1.1/types.h>
 #include <log/log.h>
 
 namespace android {
@@ -25,6 +26,9 @@
 namespace V1_2 {
 namespace implementation {
 
+using ::android::hardware::graphics::common::V1_1::Dataspace;
+using ::android::hardware::graphics::common::V1_1::PixelFormat;
+
 // ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs implementation.
 Return<void> SurfaceFlingerConfigs::vsyncEventPhaseOffsetNs(vsyncEventPhaseOffsetNs_cb _hidl_cb) {
 #ifdef VSYNC_EVENT_PHASE_OFFSET_NS
@@ -199,6 +203,25 @@
     return Void();
 }
 
+#ifdef COMPOSITION_DATA_SPACE
+static_assert(COMPOSITION_DATA_SPACE != 0, "Expected composition data space must not be UNKNOWN");
+#endif
+
+Return<void> SurfaceFlingerConfigs::getCompositionPreference(getCompositionPreference_cb _hidl_cb) {
+    Dataspace dataSpace = Dataspace::V0_SRGB;
+    PixelFormat pixelFormat = PixelFormat::RGBA_8888;
+
+#ifdef COMPOSITION_DATA_SPACE
+    dataSpace = static_cast<Dataspace>(COMPOSITION_DATA_SPACE);
+#endif
+
+#ifdef COMPOSITION_PIXEL_FORMAT
+    pixelFormat = static_cast<PixelFormat>(COMPOSITION_PIXEL_FORMAT);
+#endif
+    _hidl_cb(dataSpace, pixelFormat);
+    return Void();
+}
+
 }  // namespace implementation
 }  // namespace V1_2
 }  // namespace configstore
diff --git a/configstore/1.2/default/SurfaceFlingerConfigs.h b/configstore/1.2/default/SurfaceFlingerConfigs.h
index fe78789..7dd8f6d 100644
--- a/configstore/1.2/default/SurfaceFlingerConfigs.h
+++ b/configstore/1.2/default/SurfaceFlingerConfigs.h
@@ -52,6 +52,7 @@
 
     // ::android::hardware::configstore::V1_2::ISurfaceFlingerConfigs follow implementation.
     Return<void> useColorManagement(useColorManagement_cb _hidl_cb) override;
+    Return<void> getCompositionPreference(getCompositionPreference_cb _hidl_cb) override;
 };
 
 }  // namespace implementation
diff --git a/configstore/1.2/default/surfaceflinger.mk b/configstore/1.2/default/surfaceflinger.mk
index 70be450..f323999 100644
--- a/configstore/1.2/default/surfaceflinger.mk
+++ b/configstore/1.2/default/surfaceflinger.mk
@@ -58,3 +58,11 @@
 ifeq ($(TARGET_USE_COLOR_MANAGEMENT),true)
     LOCAL_CFLAGS += -DUSE_COLOR_MANAGEMENT
 endif
+
+ifneq ($(SF_COMPOSITION_DATA_SPACE),)
+    LOCAL_CFLAGS += -DCOMPOSITION_DATA_SPACE=$(SF_COMPOSITION_DATA_SPACE)
+endif
+
+ifneq ($(SF_COMPOSITION_PIXEL_FORMAT),)
+    LOCAL_CFLAGS += -DCOMPOSITION_PIXEL_FORMAT=$(SF_COMPOSITION_PIXEL_FORMAT)
+endif
diff --git a/confirmationui/support/src/cbor.cpp b/confirmationui/support/src/cbor.cpp
index e7ea164..3685521 100644
--- a/confirmationui/support/src/cbor.cpp
+++ b/confirmationui/support/src/cbor.cpp
@@ -36,11 +36,14 @@
             *pos++ = getByte(value, 6);
             *pos++ = getByte(value, 5);
             *pos++ = getByte(value, 4);
+            [[fallthrough]];
         case 4:
             *pos++ = getByte(value, 3);
             *pos++ = getByte(value, 2);
+            [[fallthrough]];
         case 2:
             *pos++ = getByte(value, 1);
+            [[fallthrough]];
         case 1:
             *pos++ = value;
             break;
diff --git a/current.txt b/current.txt
index 35143af..a7989d4 100644
--- a/current.txt
+++ b/current.txt
@@ -385,10 +385,18 @@
 10ff2fae516346b86121368ce5790d5accdfcb73983246b813f3d488b66db45a android.hardware.wifi.supplicant@1.1::ISupplicantStaNetwork
 
 # ABI preserving changes to HALs during Android Q
-a95745bbf76aea16a76518bd7efe70cabc5886d09eaeffc993c2e1787a22ed23 android.hardware.camera.metadata@3.3::types
-5f936a5befde7af8d2a683670f80a836b4741e94d84b7b39026da3ed78be9906 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
+2a55e224aa9bc62c0387cd85ad3c97e33f0c33a4e1489cbae86b2523e6f9df35 android.hardware.camera.device@3.2::ICameraDevice
+f61b616732d8f374e030f90575d7eba3ecc99d209a05b945949ba892bcb81e1d android.hardware.camera.device@3.2::ICameraDeviceSession
+684702a60deef03a1e8093961dc0a18c555c857ad5a77ba7340b0635ae01eb70 android.hardware.camera.device@3.4::ICameraDeviceSession
+dd2436f251a90f3e5e7ed773b1aeae21e381b00ae26b10ebe3a1001c894e5980 android.hardware.camera.metadata@3.3::types
+da33234403ff5d60f3473711917b9948e6484a4260b5247acdafb111193a9de2 android.hardware.configstore@1.0::ISurfaceFlingerConfigs
+78886339f2c848cf13c1edd3ebba63f89796b2620d3bf3b5c21d038a53519ba0 android.hardware.gnss@1.0::IGnssMeasurementCallback
+b7ecf29927055ec422ec44bf776223f07d79ad9f92ccf9becf167e62c2607e7a android.hardware.keymaster@4.0::IKeymasterDevice
 574e8f1499436fb4075894dcae0b36682427956ecb114f17f1fe22d116a83c6b android.hardware.neuralnetworks@1.0::IPreparedModel
-1a5ae9793223658174258b523763c557abad6fb917df0b8e3cc097fc89035811 android.hardware.neuralnetworks@1.0::types
-4310eb8272f085914952f3bfb73a8f8bb477a80e8b93596f0ea5acb58546b66d android.hardware.neuralnetworks@1.1::types
+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/health/filesystem/1.0/Android.bp b/fastboot/1.0/Android.bp
similarity index 72%
copy from health/filesystem/1.0/Android.bp
copy to fastboot/1.0/Android.bp
index 74b9bc3..467fc6d 100644
--- a/health/filesystem/1.0/Android.bp
+++ b/fastboot/1.0/Android.bp
@@ -1,20 +1,22 @@
 // This file is autogenerated by hidl-gen -Landroidbp.
 
 hidl_interface {
-    name: "android.hardware.health.filesystem@1.0",
+    name: "android.hardware.fastboot@1.0",
     root: "android.hardware",
     vndk: {
         enabled: true,
     },
     srcs: [
         "types.hal",
-        "IFileSystem.hal",
+        "IFastboot.hal",
     ],
     interfaces: [
         "android.hidl.base@1.0",
     ],
     types: [
+        "FileSystemType",
         "Result",
+        "Status",
     ],
     gen_java: true,
 }
diff --git a/fastboot/1.0/IFastboot.hal b/fastboot/1.0/IFastboot.hal
new file mode 100644
index 0000000..dce3ad7
--- /dev/null
+++ b/fastboot/1.0/IFastboot.hal
@@ -0,0 +1,72 @@
+/*
+ * 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.
+     * @return 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);
+
+    /**
+     * Returns an OEM-defined string indicating the variant of the device, for
+     * example, US and ROW.
+     *
+     * @return variant Indicates the device variant.
+     * @return result Returns the status SUCCESS if the operation is successful,
+     *     FAILURE_UNKNOWN otherwise.
+     */
+    getVariant() generates (string variant, Result result);
+
+    /**
+     * Returns whether off-mode-charging is enabled. If enabled, the device
+     * autoboots into a special mode when power is applied.
+     *
+     * @return state Returns whether off mode charging is enabled.
+     * @return result Returns the status SUCCESS if the operation is successful,
+     *     FAILURE_UNKNOWN otherwise.
+     */
+    getOffModeChargeState() generates (bool state, Result result);
+
+    /**
+     * Returns the minimum battery voltage required for flashing in mV.
+     *
+     * @return batteryVoltage Minimum batterery voltage (in mV) required for
+     *     flashing to be successful.
+     * @return result Returns the status SUCCESS if the operation is successful,
+     *     FAILURE_UNKNOWN otherwise.
+     */
+    getBatteryVoltageFlashingThreshold() generates (int32_t batteryVoltage, 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/gnss/1.0/IGnssMeasurementCallback.hal b/gnss/1.0/IGnssMeasurementCallback.hal
index b27c2e0..d3489e6 100644
--- a/gnss/1.0/IGnssMeasurementCallback.hal
+++ b/gnss/1.0/IGnssMeasurementCallback.hal
@@ -124,6 +124,12 @@
         /**
          * A set of flags indicating the validity of the fields in this data
          * structure.
+         *
+         * Fields for which there is no corresponding flag must be filled in
+         * with a valid value.  For convenience, these are marked as mandatory.
+         *
+         * Others fields may have invalid information in them, if not marked as
+         * valid by the corresponding bit in gnssClockFlags.
          */
         bitfield<GnssClockFlags> gnssClockFlags;
 
@@ -155,7 +161,7 @@
          * Sub-nanosecond accuracy can be provided by means of the 'biasNs' field.
          * The value contains the timeUncertaintyNs in it.
          *
-         * This field is mandatory.
+         * This value is mandatory.
          */
         int64_t timeNs;
 
@@ -172,29 +178,31 @@
 
         /**
          * The difference between hardware clock ('time' field) inside GNSS receiver
-         * and the true GNSS time since 0000Z, January 6, 1980, in nanoseconds.
+         * and the true GPS time since 0000Z, January 6, 1980, in nanoseconds.
          *
          * The sign of the value is defined by the following equation:
-         *      local estimate of GNSS time = timeNs - (fullBiasNs + biasNs)
+         *      local estimate of GPS time = timeNs - (fullBiasNs + biasNs)
          *
-         * This value is mandatory if the receiver has estimated GNSS time. If the
-         * computed time is for a non-GNSS constellation, the time offset of that
-         * constellation to GNSS has to be applied to fill this value. The error
-         * estimate for the sum of this and the biasNs is the biasUncertaintyNs,
-         * and the caller is responsible for using this uncertainty (it can be very
-         * large before the GNSS time has been solved for.) If the data is available
-         * gnssClockFlags must contain HAS_FULL_BIAS.
+         * If receiver has computed time for a non-GPS constellation, the time offset of
+         * that constellation versus GPS time must be applied to fill this value.
+         *
+         * The error estimate for the sum of this and the biasNs is the biasUncertaintyNs.
+         *
+         * If the data is available gnssClockFlags must contain HAS_FULL_BIAS.
+         *
+         * This value is mandatory if the receiver has estimated GPS time.
          */
         int64_t fullBiasNs;
 
         /**
-         * Sub-nanosecond bias.
+         * Sub-nanosecond bias - used with fullBiasNS, see fullBiasNs for details.
+         *
          * The error estimate for the sum of this and the fullBiasNs is the
          * biasUncertaintyNs.
          *
-         * If the data is available gnssClockFlags must contain HAS_BIAS. If GNSS
-         * has computed a position fix. This value is mandatory if the receiver has
-         * estimated GNSS time.
+         * If the data is available gnssClockFlags must contain HAS_BIAS.
+         *
+         * This value is mandatory if the receiver has estimated GPS time.
          */
         double biasNs;
 
@@ -203,9 +211,12 @@
          * bias) in nanoseconds. The uncertainty is represented as an absolute
          * (single sided) value.
          *
-         * If the data is available gnssClockFlags must contain
-         * HAS_BIAS_UNCERTAINTY. This value is mandatory if the receiver
-         * has estimated GNSS time.
+         * The caller is responsible for using this uncertainty (it can be very
+         * large before the GPS time has been fully resolved.)
+         *
+         * If the data is available gnssClockFlags must contain HAS_BIAS_UNCERTAINTY.
+         *
+         * This value is mandatory if the receiver has estimated GPS time.
          */
         double biasUncertaintyNs;
 
@@ -216,10 +227,9 @@
          * frequency, and that the (fullBiasNs + biasNs) is growing more positive
          * over time.
          *
-         * The value contains the 'drift uncertainty' in it.
          * If the data is available gnssClockFlags must contain HAS_DRIFT.
          *
-         * This value is mandatory if the receiver has estimated GNSS time.
+         * This value is mandatory if the receiver has estimated GPS time.
          */
         double driftNsps;
 
@@ -228,15 +238,15 @@
          * second).
          * The uncertainty is represented as an absolute (single sided) value.
          *
-         * If the data is available gnssClockFlags must contain
-         * HAS_DRIFT_UNCERTAINTY. If GNSS has computed a position fix this
-         * field is mandatory and must be populated.
+         * If the data is available gnssClockFlags must contain HAS_DRIFT_UNCERTAINTY.
+         *
+         * This value is mandatory if the receiver has estimated GPS time.
          */
         double driftUncertaintyNsps;
 
         /**
-         * When there are any discontinuities in the HW clock, this field is
-         * mandatory.
+         * This field must be incremented, when there are discontinuities in the
+         * hardware clock.
          *
          * A "discontinuity" is meant to cover the case of a switch from one source
          * of clock to another.  A single free-running crystal oscillator (XO)
@@ -262,6 +272,8 @@
          * as this avoids the need to use (waste) a GNSS measurement to fully
          * re-solve for the GNSS clock bias and drift, when using the accompanying
          * measurements, from consecutive GnssData reports.
+         *
+         * This value is mandatory.
          */
         uint32_t hwClockDiscontinuityCount;
 
@@ -280,17 +292,26 @@
         /**
          * A set of flags indicating the validity of the fields in this data
          * structure.
+         *
+         * Fields for which there is no corresponding flag must be filled in
+         * with a valid value.  For convenience, these are marked as mandatory.
+         *
+         * Others fields may have invalid information in them, if not marked as
+         * valid by the corresponding bit in flags.
          */
         bitfield<GnssMeasurementFlags> flags;
 
         /**
          * Satellite vehicle ID number, as defined in GnssSvInfo::svid
-         * This is a mandatory value.
+         *
+         * This value is mandatory.
          */
         int16_t svid;
 
         /**
          * Defines the constellation of the given SV.
+         *
+         * This value is mandatory.
          */
         GnssConstellationType constellation;
 
@@ -302,8 +323,10 @@
          *      measurement time = GnssClock::timeNs + timeOffsetNs
          *
          * It provides an individual time-stamp for the measurement, and allows
-         * sub-nanosecond accuracy.
-         * This is a mandatory value.
+         * sub-nanosecond accuracy. It may be zero if all measurements are
+         * aligned to a common time.
+         *
+         * This value is mandatory.
          */
         double timeOffsetNs;
 
@@ -313,7 +336,7 @@
          * Based on the sync state, the 'received GNSS tow' field must be interpreted
          * accordingly.
          *
-         * This is a mandatory value.
+         * This value is mandatory.
          */
         bitfield<GnssMeasurementState> state;
 
@@ -413,7 +436,7 @@
          * Carrier-to-noise density in dB-Hz, typically in the range [0, 63].
          * It contains the measured C/N0 value for the signal at the antenna port.
          *
-         * This is a mandatory value.
+         * This value is mandatory.
          */
         double cN0DbHz;
 
@@ -449,7 +472,7 @@
          * 1-Sigma uncertainty of the pseudorangeRateMps.
          * The uncertainty is represented as an absolute (single sided) value.
          *
-         * This is a mandatory value.
+         * This value is mandatory.
          */
         double pseudorangeRateUncertaintyMps;
 
@@ -457,7 +480,7 @@
          * Accumulated delta range's state. It indicates whether ADR is reset or
          * there is a cycle slip(indicating loss of lock).
          *
-         * This is a mandatory value.
+         * This value is mandatory.
          */
         bitfield<GnssAccumulatedDeltaRangeState> accumulatedDeltaRangeState;
 
diff --git a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
index c9f840e..2d901f3 100644
--- a/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
+++ b/gnss/1.1/vts/functional/gnss_hal_test_cases.cpp
@@ -119,6 +119,11 @@
     struct ComparableBlacklistedSource {
         IGnssConfiguration::BlacklistedSource id;
 
+        ComparableBlacklistedSource() {
+            id.constellation = GnssConstellationType::UNKNOWN;
+            id.svid = 0;
+        }
+
         bool operator<(const ComparableBlacklistedSource& compare) const {
             return ((id.svid < compare.id.svid) || ((id.svid == compare.id.svid) &&
                                                     (id.constellation < compare.id.constellation)));
@@ -191,18 +196,21 @@
  * 3) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
  * GnssStatus does not use those satellites.
  * 4a & b) Turns off location, and send in empty blacklist.
- * 5) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
+ * 5a) Restart location, wait for 3 locations, ensuring they are valid, and checks corresponding
  * GnssStatus does re-use at least the previously strongest satellite
+ * 5b) Retry a few times, in case GNSS search strategy takes a while to reacquire even the
+ * formerly strongest satellite
  */
 TEST_F(GnssHalTest, BlacklistIndividualSatellites) {
     const int kLocationsToAwait = 3;
+    const int kRetriesToUnBlacklist = 10;
 
     StartAndCheckLocations(kLocationsToAwait);
 
     // Tolerate 1 less sv status to handle edge cases in reporting.
     EXPECT_GE((int)list_gnss_sv_status_.size() + 1, kLocationsToAwait);
-    ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations", (int)list_gnss_sv_status_.size(),
-          kLocationsToAwait);
+    ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
+          (int)list_gnss_sv_status_.size(), kLocationsToAwait, location_called_count_);
 
     /*
      * Identify strongest SV seen at least kLocationsToAwait -1 times
@@ -237,13 +245,18 @@
     // retry and ensure satellite not used
     list_gnss_sv_status_.clear();
 
-    location_called_count_ = 0;
     StartAndCheckLocations(kLocationsToAwait);
 
+    // early exit if test is being run with insufficient signal
+    if (location_called_count_ == 0) {
+        ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
+    }
+    ASSERT_TRUE(location_called_count_ > 0);
+
     // Tolerate 1 less sv status to handle edge cases in reporting.
     EXPECT_GE((int)list_gnss_sv_status_.size() + 1, kLocationsToAwait);
-    ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations", (int)list_gnss_sv_status_.size(),
-          kLocationsToAwait);
+    ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
+          (int)list_gnss_sv_status_.size(), kLocationsToAwait, location_called_count_);
     for (const auto& gnss_sv_status : list_gnss_sv_status_) {
         for (uint32_t iSv = 0; iSv < gnss_sv_status.numSvs; iSv++) {
             const auto& gnss_sv = gnss_sv_status.gnssSvList[iSv];
@@ -260,28 +273,40 @@
     ASSERT_TRUE(result.isOk());
     EXPECT_TRUE(result);
 
-    StopAndClearLocations();
-    list_gnss_sv_status_.clear();
-
-    StartAndCheckLocations(kLocationsToAwait);
-
-    // Tolerate 1 less sv status to handle edge cases in reporting.
-    EXPECT_GE((int)list_gnss_sv_status_.size() + 1, kLocationsToAwait);
-    ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations", (int)list_gnss_sv_status_.size(),
-          kLocationsToAwait);
-
     bool strongest_sv_is_reobserved = false;
-    for (const auto& gnss_sv_status : list_gnss_sv_status_) {
-        for (uint32_t iSv = 0; iSv < gnss_sv_status.numSvs; iSv++) {
-            const auto& gnss_sv = gnss_sv_status.gnssSvList[iSv];
-            if ((gnss_sv.svid == source_to_blacklist.svid) &&
-                (gnss_sv.constellation == source_to_blacklist.constellation) &&
-                (gnss_sv.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX)) {
-                strongest_sv_is_reobserved = true;
-                break;
-            }
+    // do several loops awaiting a few locations, allowing non-immediate reacquisition strategies
+    int unblacklist_loops_remaining = kRetriesToUnBlacklist;
+    while (!strongest_sv_is_reobserved && (unblacklist_loops_remaining-- > 0)) {
+        StopAndClearLocations();
+        list_gnss_sv_status_.clear();
+
+        StartAndCheckLocations(kLocationsToAwait);
+
+        // early exit loop if test is being run with insufficient signal
+        if (location_called_count_ == 0) {
+            ALOGE("0 Gnss locations received - ensure sufficient signal and retry");
         }
-        if (strongest_sv_is_reobserved) break;
+        ASSERT_TRUE(location_called_count_ > 0);
+
+        // Tolerate 1 less sv status to handle edge cases in reporting.
+        EXPECT_GE((int)list_gnss_sv_status_.size() + 1, kLocationsToAwait);
+        ALOGD(
+            "Clear blacklist, observed %d GnssSvStatus, while awaiting %d Locations"
+            ", tries remaining %d",
+            (int)list_gnss_sv_status_.size(), kLocationsToAwait, unblacklist_loops_remaining);
+
+        for (const auto& gnss_sv_status : list_gnss_sv_status_) {
+            for (uint32_t iSv = 0; iSv < gnss_sv_status.numSvs; iSv++) {
+                const auto& gnss_sv = gnss_sv_status.gnssSvList[iSv];
+                if ((gnss_sv.svid == source_to_blacklist.svid) &&
+                    (gnss_sv.constellation == source_to_blacklist.constellation) &&
+                    (gnss_sv.svFlag & IGnssCallback::GnssSvFlags::USED_IN_FIX)) {
+                    strongest_sv_is_reobserved = true;
+                    break;
+                }
+            }
+            if (strongest_sv_is_reobserved) break;
+        }
     }
     EXPECT_TRUE(strongest_sv_is_reobserved);
     StopAndClearLocations();
@@ -304,8 +329,8 @@
 
     // Tolerate 1 less sv status to handle edge cases in reporting.
     EXPECT_GE((int)list_gnss_sv_status_.size() + 1, kLocationsToAwait);
-    ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations", (int)list_gnss_sv_status_.size(),
-          kLocationsToAwait);
+    ALOGD("Observed %d GnssSvStatus, while awaiting %d Locations (%d received)",
+          (int)list_gnss_sv_status_.size(), kLocationsToAwait, location_called_count_);
 
     // Find first non-GPS constellation to blacklist
     GnssConstellationType constellation_to_blacklist = GnssConstellationType::UNKNOWN;
diff --git a/graphics/composer/2.1/utils/vts/ComposerVts.cpp b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
index 1cafafe..250c392 100644
--- a/graphics/composer/2.1/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.1/utils/vts/ComposerVts.cpp
@@ -311,6 +311,8 @@
                                  ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
                                  reader->parse();
                              });
+    reader->reset();
+    writer->reset();
 }
 
 }  // namespace vts
diff --git a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
index 8b8c7ae..0a3e88b 100644
--- a/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
+++ b/graphics/composer/2.1/vts/functional/VtsHalGraphicsComposerV2_1TargetTest.cpp
@@ -71,6 +71,7 @@
 class GraphicsComposerHidlTest : public ::testing::VtsHalHidlTargetTestBase {
    protected:
     void SetUp() override {
+        VtsHalHidlTargetTestBase::SetUp();
         ASSERT_NO_FATAL_FAILURE(
             mComposer = std::make_unique<Composer>(
                 GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
@@ -100,6 +101,7 @@
             EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
             EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
         }
+        VtsHalHidlTargetTestBase::TearDown();
     }
 
     // returns an invalid display id (one that has not been registered to a
@@ -668,6 +670,11 @@
 
         ASSERT_NO_FATAL_FAILURE(mGralloc = std::make_unique<Gralloc>());
 
+        Config activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay);
+        mDisplayWidth = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig,
+                                                             IComposerClient::Attribute::WIDTH);
+        mDisplayHeight = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig,
+                                                              IComposerClient::Attribute::HEIGHT);
         mWriter = std::make_unique<CommandWriterBase>(1024);
         mReader = std::make_unique<TestCommandReader>();
     }
@@ -679,12 +686,13 @@
 
     const native_handle_t* allocate() {
         IMapper::BufferDescriptorInfo info{};
-        info.width = 64;
-        info.height = 64;
+        info.width = mDisplayWidth;
+        info.height = mDisplayHeight;
         info.layerCount = 1;
         info.format = PixelFormat::RGBA_8888;
         info.usage =
-            static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN);
+            static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN |
+                                  BufferUsage::COMPOSER_OVERLAY);
 
         return mGralloc->allocate(info);
     }
@@ -693,6 +701,8 @@
 
     std::unique_ptr<CommandWriterBase> mWriter;
     std::unique_ptr<TestCommandReader> mReader;
+    int32_t mDisplayWidth;
+    int32_t mDisplayHeight;
 
    private:
     std::unique_ptr<Gralloc> mGralloc;
@@ -779,6 +789,60 @@
 }
 
 /**
+ * Test IComposerClient::Command::PRESENT_DISPLAY
+ *
+ * Test that IComposerClient::Command::PRESENT_DISPLAY works without
+ * additional call to validateDisplay when only the layer buffer handle and
+ * surface damage have been set
+ */
+TEST_F(GraphicsComposerHidlCommandTest, PRESENT_DISPLAY_NO_LAYER_STATE_CHANGES) {
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mComposerClient->setPowerMode(mPrimaryDisplay, IComposerClient::PowerMode::ON);
+    mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB);
+
+    auto handle = allocate();
+    ASSERT_NE(nullptr, handle);
+
+    IComposerClient::Rect displayFrame{0, 0, mDisplayWidth, mDisplayHeight};
+
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    mWriter->selectLayer(layer);
+    mWriter->setLayerCompositionType(IComposerClient::Composition::DEVICE);
+    mWriter->setLayerDisplayFrame(displayFrame);
+    mWriter->setLayerPlaneAlpha(1);
+    mWriter->setLayerSourceCrop({0, 0, (float)mDisplayWidth, (float)mDisplayHeight});
+    mWriter->setLayerTransform(static_cast<Transform>(0));
+    mWriter->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, displayFrame));
+    mWriter->setLayerZOrder(10);
+    mWriter->setLayerBlendMode(IComposerClient::BlendMode::NONE);
+    mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, displayFrame));
+    mWriter->setLayerBuffer(0, handle, -1);
+    mWriter->setLayerDataspace(Dataspace::UNKNOWN);
+
+    mWriter->validateDisplay();
+    execute();
+    if (mReader->mCompositionChanges.size() != 0) {
+        GTEST_SUCCEED() << "Composition change requested, skipping test";
+        return;
+    }
+
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    mWriter->selectLayer(layer);
+    auto handle2 = allocate();
+    ASSERT_NE(nullptr, handle2);
+    mWriter->setLayerBuffer(0, handle2, -1);
+    mWriter->setLayerSurfaceDamage(std::vector<IComposerClient::Rect>(1, {0, 0, 10, 10}));
+    mWriter->presentDisplay();
+    execute();
+}
+
+/**
  * Test IComposerClient::Command::SET_LAYER_CURSOR_POSITION.
  */
 TEST_F(GraphicsComposerHidlCommandTest, SET_LAYER_CURSOR_POSITION) {
diff --git a/graphics/composer/2.2/utils/vts/ComposerVts.cpp b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
index d8fb656..da99460 100644
--- a/graphics/composer/2.2/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.2/utils/vts/ComposerVts.cpp
@@ -86,6 +86,8 @@
                                  ASSERT_TRUE(reader->readQueue(tmpOutLength, tmpOutHandles));
                                  reader->parse();
                              });
+    reader->reset();
+    writer->reset();
 }
 
 Display ComposerClient::createVirtualDisplay_2_2(uint32_t width, uint32_t height,
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
index 229c856..da8858e 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2ReadbackTest.cpp
@@ -44,6 +44,12 @@
 using V2_1::Layer;
 using V2_1::vts::TestCommandReader;
 
+static const IComposerClient::Color BLACK = {0, 0, 0, 0xff};
+static const IComposerClient::Color RED = {0xff, 0, 0, 0xff};
+static const IComposerClient::Color TRANSLUCENT_RED = {0xff, 0, 0, 0x33};
+static const IComposerClient::Color GREEN = {0, 0xff, 0, 0xff};
+static const IComposerClient::Color BLUE = {0, 0, 0xff, 0xff};
+
 // Test environment for graphics.composer
 class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
    public:
@@ -61,101 +67,57 @@
 
 class TestLayer {
    public:
-    TestLayer(std::shared_ptr<ComposerClient> const client, Display display)
-        : mLayer(client->createLayer(display, kBufferSlotCount)),
-          mComposerClient(client),
-          mDisplay(display) {}
+    TestLayer(const std::shared_ptr<ComposerClient>& client, Display display)
+        : mLayer(client->createLayer(display, kBufferSlotCount)), mComposerClient(client) {}
 
-    virtual ~TestLayer() { mComposerClient->destroyLayer(mDisplay, mLayer); }
+    // ComposerClient will take care of destroying layers, no need to explicitly
+    // call destroyLayers here
+    virtual ~TestLayer(){};
 
-    virtual void write(std::shared_ptr<CommandWriterBase> writer) {
+    virtual void write(const std::shared_ptr<CommandWriterBase>& writer) {
         writer->selectLayer(mLayer);
         writer->setLayerDisplayFrame(mDisplayFrame);
+        writer->setLayerSourceCrop(mSourceCrop);
         writer->setLayerZOrder(mZOrder);
+        writer->setLayerSurfaceDamage(mSurfaceDamage);
+        writer->setLayerTransform(mTransform);
+        writer->setLayerPlaneAlpha(mAlpha);
+        writer->setLayerBlendMode(mBlendMode);
     }
 
     void setDisplayFrame(IComposerClient::Rect frame) { mDisplayFrame = frame; }
+    void setSourceCrop(IComposerClient::FRect crop) { mSourceCrop = crop; }
     void setZOrder(uint32_t z) { mZOrder = z; }
 
+    void setSurfaceDamage(std::vector<IComposerClient::Rect> surfaceDamage) {
+        mSurfaceDamage = surfaceDamage;
+    }
+
+    void setTransform(Transform transform) { mTransform = transform; }
+    void setAlpha(float alpha) { mAlpha = alpha; }
+    void setBlendMode(IComposerClient::BlendMode blendMode) { mBlendMode = blendMode; }
+
+    static constexpr uint32_t kBufferSlotCount = 64;
+
+    IComposerClient::Rect mDisplayFrame = {0, 0, 0, 0};
+    uint32_t mZOrder = 0;
+    std::vector<IComposerClient::Rect> mSurfaceDamage;
+    Transform mTransform = static_cast<Transform>(0);
+    IComposerClient::FRect mSourceCrop = {0, 0, 0, 0};
+    float mAlpha = 1.0;
+    IComposerClient::BlendMode mBlendMode = IComposerClient::BlendMode::NONE;
+
    protected:
     Layer mLayer;
-    IComposerClient::Rect mDisplayFrame = {0, 0, 0, 0};
-    uint32_t mZOrder = 0;
 
    private:
     std::shared_ptr<ComposerClient> const mComposerClient;
-    const Display mDisplay;
-    static constexpr uint32_t kBufferSlotCount = 64;
-};
-
-class TestColorLayer : public TestLayer {
-   public:
-    TestColorLayer(std::shared_ptr<ComposerClient> const client, Display display)
-        : TestLayer{client, display} {}
-
-    void write(std::shared_ptr<CommandWriterBase> writer) override {
-        TestLayer::write(writer);
-        writer->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR);
-        writer->setLayerColor(mColor);
-    }
-
-    void setColor(IComposerClient::Color color) { mColor = color; }
-
-   private:
-    IComposerClient::Color mColor = {0xff, 0xff, 0xff, 0xff};
 };
 
 class GraphicsComposerReadbackTest : public ::testing::VtsHalHidlTargetTestBase {
-   protected:
-    using PowerMode = V2_1::IComposerClient::PowerMode;
-    void SetUp() override {
-        ASSERT_NO_FATAL_FAILURE(
-            mComposer = std::make_unique<Composer>(
-                GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
-        ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
-        mComposerCallback = new V2_1::vts::GraphicsComposerCallback;
-        mComposerClient->registerCallback(mComposerCallback);
-
-        // assume the first display is primary and is never removed
-        mPrimaryDisplay = waitForFirstDisplay();
-        Config activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay);
-        width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig,
-                                                     IComposerClient::Attribute::WIDTH);
-        height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, activeConfig,
-                                                      IComposerClient::Attribute::HEIGHT);
-
-        // explicitly disable vsync
-        mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
-        mComposerCallback->setVsyncAllowed(false);
-
-        // set up command writer/reader and gralloc
-        mWriter = std::make_shared<CommandWriterBase>(1024);
-        mReader = std::make_unique<TestCommandReader>();
-        mGralloc = std::make_unique<Gralloc>();
-    }
-
-    ~GraphicsComposerReadbackTest() override {
-        if (mComposerCallback != nullptr) {
-            EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
-            EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
-            EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
-        }
-    }
-
-    void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
-
-    void render(const std::vector<std::shared_ptr<TestLayer>>& layers) {
-        for (auto layer : layers) {
-            layer->write(mWriter);
-        }
-        execute();
-        mWriter->validateDisplay();
-        mWriter->presentDisplay();
-        execute();
-    }
-
-    int32_t GetBytesPerPixel(PixelFormat format) {
-        switch (format) {
+   public:
+    static int32_t GetBytesPerPixel(PixelFormat pixelFormat) {
+        switch (pixelFormat) {
             case PixelFormat::RGBA_8888:
                 return 4;
             case PixelFormat::RGB_888:
@@ -165,9 +127,122 @@
         }
     }
 
+    static void fillBuffer(int32_t width, int32_t height, uint32_t stride, void* bufferData,
+                           PixelFormat pixelFormat,
+                           std::vector<IComposerClient::Color> desiredPixelColors) {
+        ASSERT_TRUE(pixelFormat == PixelFormat::RGB_888 || pixelFormat == PixelFormat::RGBA_8888);
+        int32_t bytesPerPixel = GetBytesPerPixel(pixelFormat);
+        ASSERT_NE(-1, bytesPerPixel);
+        for (int row = 0; row < height; row++) {
+            for (int col = 0; col < width; col++) {
+                int pixel = row * width + col;
+                IComposerClient::Color srcColor = desiredPixelColors[pixel];
+
+                int offset = (row * stride + col) * bytesPerPixel;
+                uint8_t* pixelColor = (uint8_t*)bufferData + offset;
+                pixelColor[0] = srcColor.r;
+                pixelColor[1] = srcColor.g;
+                pixelColor[2] = srcColor.b;
+
+                if (bytesPerPixel == 4) {
+                    pixelColor[3] = srcColor.a;
+                }
+            }
+        }
+    }
+
+   protected:
+    using PowerMode = V2_1::IComposerClient::PowerMode;
+    void SetUp() override {
+        VtsHalHidlTargetTestBase::SetUp();
+        ASSERT_NO_FATAL_FAILURE(
+            mComposer = std::make_unique<Composer>(
+                GraphicsComposerHidlEnvironment::Instance()->getServiceName<IComposer>()));
+        ASSERT_NO_FATAL_FAILURE(mComposerClient = mComposer->createClient());
+        mComposerCallback = new V2_1::vts::GraphicsComposerCallback;
+        mComposerClient->registerCallback(mComposerCallback);
+
+        // assume the first display is primary and is never removed
+        mPrimaryDisplay = waitForFirstDisplay();
+        Config activeConfig;
+        ASSERT_NO_FATAL_FAILURE(activeConfig = mComposerClient->getActiveConfig(mPrimaryDisplay));
+        ASSERT_NO_FATAL_FAILURE(
+            mDisplayWidth = mComposerClient->getDisplayAttribute(
+                mPrimaryDisplay, activeConfig, IComposerClient::Attribute::WIDTH));
+        ASSERT_NO_FATAL_FAILURE(
+            mDisplayHeight = mComposerClient->getDisplayAttribute(
+                mPrimaryDisplay, activeConfig, IComposerClient::Attribute::HEIGHT));
+
+        // explicitly disable vsync
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setVsyncEnabled(mPrimaryDisplay, false));
+        mComposerCallback->setVsyncAllowed(false);
+
+        // set up command writer/reader and gralloc
+        mWriter = std::make_shared<CommandWriterBase>(1024);
+        mReader = std::make_unique<TestCommandReader>();
+        mGralloc = std::make_shared<Gralloc>();
+
+        mComposerClient->getRaw()->getReadbackBufferAttributes(
+            mPrimaryDisplay,
+            [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
+                mHasReadbackBuffer = readbackSupported(tmpPixelFormat, tmpDataspace, tmpError);
+                mPixelFormat = tmpPixelFormat;
+                mDataspace = tmpDataspace;
+            });
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON));
+    }
+
+    void TearDown() override {
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::OFF));
+        EXPECT_EQ(0, mReader->mErrors.size());
+        EXPECT_EQ(0, mReader->mCompositionChanges.size());
+        if (mComposerCallback != nullptr) {
+            EXPECT_EQ(0, mComposerCallback->getInvalidHotplugCount());
+            EXPECT_EQ(0, mComposerCallback->getInvalidRefreshCount());
+            EXPECT_EQ(0, mComposerCallback->getInvalidVsyncCount());
+        }
+        VtsHalHidlTargetTestBase::TearDown();
+    }
+
+    void clearCommandReaderState() {
+        mReader->mCompositionChanges.clear();
+        mReader->mErrors.clear();
+    }
+
+    void execute() {
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->execute(mReader.get(), mWriter.get()));
+    }
+
+    void writeLayers(const std::vector<std::shared_ptr<TestLayer>>& layers) {
+        for (auto layer : layers) {
+            layer->write(mWriter);
+        }
+        execute();
+    }
+
+    void clearColors(std::vector<IComposerClient::Color>& expectedColors, int32_t width,
+                     int32_t height) {
+        for (int row = 0; row < height; row++) {
+            for (int col = 0; col < width; col++) {
+                int pixel = row * mDisplayWidth + col;
+                expectedColors[pixel] = BLACK;
+            }
+        }
+    }
+
+    void fillColorsArea(std::vector<IComposerClient::Color>& expectedColors, int32_t stride,
+                        IComposerClient::Rect area, IComposerClient::Color color) {
+        for (int row = area.top; row < area.bottom; row++) {
+            for (int col = area.left; col < area.right; col++) {
+                int pixel = row * stride + col;
+                expectedColors[pixel] = color;
+            }
+        }
+    }
+
     bool readbackSupported(const PixelFormat& pixelFormat, const Dataspace& dataspace,
-                           const Error& error) {
-        if (error == Error::UNSUPPORTED) {
+                           const Error error) {
+        if (error != Error::NONE) {
             return false;
         }
         // TODO: add support for RGBA_1010102
@@ -180,40 +255,6 @@
         return true;
     }
 
-    void getReadbackBufferAttributes(Display display, PixelFormat* outPixelFormat,
-                                     Dataspace* outDataspace, Error* outError) {
-        mComposerClient->getRaw()->getReadbackBufferAttributes(
-            display,
-            [&](const auto& tmpError, const auto& tmpOutPixelFormat, const auto& tmpOutDataspace) {
-                *outError = tmpError;
-                *outPixelFormat = tmpOutPixelFormat;
-                *outDataspace = tmpOutDataspace;
-            });
-
-        // Not all devices support readback.  Pass test if this is the case
-        if (!readbackSupported(*outPixelFormat, *outDataspace, *outError)) {
-            GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
-        }
-    }
-
-    void checkReadbackBuffer(IMapper::BufferDescriptorInfo info, uint32_t stride, void* bufferData,
-                             std::vector<IComposerClient::Color> expectedColors) {
-        int32_t bytesPerPixel = GetBytesPerPixel(info.format);
-        ASSERT_NE(-1, bytesPerPixel)
-            << "unexpected pixel format " << static_cast<int32_t>(info.format)
-            << "(expected RGBA_8888 or RGB_888)";
-        for (int row = 0; row < height; row++) {
-            for (int col = 0; col < width; col++) {
-                int pixel = row * width + col;
-                int offset = (row * stride + col) * bytesPerPixel;
-                uint8_t* pixelColor = (uint8_t*)bufferData + offset;
-
-                EXPECT_EQ(expectedColors[pixel].r, pixelColor[0]);
-                EXPECT_EQ(expectedColors[pixel].g, pixelColor[1]);
-                EXPECT_EQ(expectedColors[pixel].b, pixelColor[2]);
-            }
-        }
-    }
 
     std::unique_ptr<Composer> mComposer;
     std::shared_ptr<ComposerClient> mComposerClient;
@@ -221,11 +262,17 @@
     sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
     // the first display and is assumed never to be removed
     Display mPrimaryDisplay;
-    int32_t width;
-    int32_t height;
+    int32_t mDisplayWidth;
+    int32_t mDisplayHeight;
     std::shared_ptr<CommandWriterBase> mWriter;
     std::unique_ptr<TestCommandReader> mReader;
-    std::unique_ptr<Gralloc> mGralloc;
+    std::shared_ptr<Gralloc> mGralloc;
+
+    bool mHasReadbackBuffer;
+    PixelFormat mPixelFormat;
+    Dataspace mDataspace;
+
+    static constexpr uint32_t kClientTargetSlotCount = 64;
 
    private:
     Display waitForFirstDisplay() {
@@ -239,75 +286,1045 @@
         }
     }
 };
+class ReadbackBuffer {
+   public:
+    ReadbackBuffer(Display display, const std::shared_ptr<ComposerClient>& client,
+                   const std::shared_ptr<Gralloc>& gralloc, uint32_t width, uint32_t height,
+                   PixelFormat pixelFormat, Dataspace dataspace) {
+        mDisplay = display;
+
+        mComposerClient = client;
+        mGralloc = gralloc;
+
+        mPixelFormat = pixelFormat;
+        mDataspace = dataspace;
+
+        mInfo.width = width;
+        mInfo.height = height;
+        mInfo.layerCount = 1;
+        mInfo.format = mPixelFormat;
+        mInfo.usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE);
+
+        mAccessRegion.top = 0;
+        mAccessRegion.left = 0;
+        mAccessRegion.width = width;
+        mAccessRegion.height = height;
+    };
+
+    ~ReadbackBuffer() {
+        if (mBufferHandle != nullptr) {
+            mGralloc->freeBuffer(mBufferHandle);
+        }
+    }
+
+    void setReadbackBuffer() {
+        if (mBufferHandle != nullptr) {
+            mGralloc->freeBuffer(mBufferHandle);
+            mBufferHandle = nullptr;
+        }
+        mBufferHandle = mGralloc->allocate(mInfo, /*import*/ true, &mStride);
+        ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mInfo, mStride));
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setReadbackBuffer(mDisplay, mBufferHandle, -1));
+    }
+
+    void checkReadbackBuffer(std::vector<IComposerClient::Color> expectedColors) {
+        // lock buffer for reading
+        int32_t fenceHandle;
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferFence(mDisplay, &fenceHandle));
+
+        void* bufData = mGralloc->lock(mBufferHandle, mInfo.usage, mAccessRegion, fenceHandle);
+        ASSERT_TRUE(mPixelFormat == PixelFormat::RGB_888 || mPixelFormat == PixelFormat::RGBA_8888);
+        int32_t bytesPerPixel = GraphicsComposerReadbackTest::GetBytesPerPixel(mPixelFormat);
+        ASSERT_NE(-1, bytesPerPixel);
+        for (int row = 0; row < mInfo.height; row++) {
+            for (int col = 0; col < mInfo.width; col++) {
+                int pixel = row * mInfo.width + col;
+                int offset = (row * mStride + col) * bytesPerPixel;
+                uint8_t* pixelColor = (uint8_t*)bufData + offset;
+
+                ASSERT_EQ(expectedColors[pixel].r, pixelColor[0]);
+                ASSERT_EQ(expectedColors[pixel].g, pixelColor[1]);
+                ASSERT_EQ(expectedColors[pixel].b, pixelColor[2]);
+            }
+        }
+        int32_t unlockFence = mGralloc->unlock(mBufferHandle);
+        if (unlockFence != -1) {
+            sync_wait(unlockFence, -1);
+            close(unlockFence);
+        }
+    }
+
+   protected:
+    IMapper::BufferDescriptorInfo mInfo;
+    IMapper::Rect mAccessRegion;
+    uint32_t mStride;
+    const native_handle_t* mBufferHandle = nullptr;
+    PixelFormat mPixelFormat;
+    Dataspace mDataspace;
+    Display mDisplay;
+    std::shared_ptr<Gralloc> mGralloc;
+    std::shared_ptr<ComposerClient> mComposerClient;
+};
+
+class TestColorLayer : public TestLayer {
+   public:
+    TestColorLayer(const std::shared_ptr<ComposerClient>& client, Display display)
+        : TestLayer{client, display} {}
+
+    void write(const std::shared_ptr<CommandWriterBase>& writer) override {
+        TestLayer::write(writer);
+        writer->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR);
+        writer->setLayerColor(mColor);
+    }
+
+    void setColor(IComposerClient::Color color) { mColor = color; }
+
+   private:
+    IComposerClient::Color mColor = {0xff, 0xff, 0xff, 0xff};
+};
+
+class TestBufferLayer : public TestLayer {
+   public:
+    TestBufferLayer(const std::shared_ptr<ComposerClient>& client,
+                    const std::shared_ptr<Gralloc>& gralloc, Display display, int32_t width,
+                    int32_t height, PixelFormat format,
+                    IComposerClient::Composition composition = IComposerClient::Composition::DEVICE)
+        : TestLayer{client, display} {
+        mGralloc = gralloc;
+        mComposition = composition;
+        mInfo.width = width;
+        mInfo.height = height;
+        mInfo.layerCount = 1;
+        mInfo.format = format;
+        mInfo.usage =
+            static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                                  BufferUsage::COMPOSER_OVERLAY);
+
+        mAccessRegion.top = 0;
+        mAccessRegion.left = 0;
+        mAccessRegion.width = width;
+        mAccessRegion.height = height;
+
+        setSourceCrop({0, 0, (float)width, (float)height});
+    }
+
+    ~TestBufferLayer() {
+        if (mBufferHandle != nullptr) {
+            mGralloc->freeBuffer(mBufferHandle);
+        }
+    }
+
+    void write(const std::shared_ptr<CommandWriterBase>& writer) override {
+        TestLayer::write(writer);
+        writer->setLayerCompositionType(mComposition);
+        writer->setLayerDataspace(Dataspace::UNKNOWN);
+        writer->setLayerVisibleRegion(std::vector<IComposerClient::Rect>(1, mDisplayFrame));
+        if (mBufferHandle != nullptr) writer->setLayerBuffer(0, mBufferHandle, mFillFence);
+    }
+
+    void fillBuffer(std::vector<IComposerClient::Color> expectedColors) {
+        void* bufData = mGralloc->lock(mBufferHandle, mInfo.usage, mAccessRegion, -1);
+        ASSERT_NO_FATAL_FAILURE(GraphicsComposerReadbackTest::fillBuffer(
+            mInfo.width, mInfo.height, mStride, bufData, mInfo.format, expectedColors));
+        mFillFence = mGralloc->unlock(mBufferHandle);
+        if (mFillFence != -1) {
+            sync_wait(mFillFence, -1);
+            close(mFillFence);
+        }
+    }
+    void setBuffer(std::vector<IComposerClient::Color> colors) {
+        if (mBufferHandle != nullptr) {
+            mGralloc->freeBuffer(mBufferHandle);
+            mBufferHandle = nullptr;
+        }
+        mBufferHandle = mGralloc->allocate(mInfo, /*import*/ true, &mStride);
+        ASSERT_NE(nullptr, mBufferHandle);
+        ASSERT_NO_FATAL_FAILURE(fillBuffer(colors));
+        ASSERT_NE(false, mGralloc->validateBufferSize(mBufferHandle, mInfo, mStride));
+    }
+
+    void setToClientComposition(const std::shared_ptr<CommandWriterBase>& writer) {
+        writer->selectLayer(mLayer);
+        writer->setLayerCompositionType(IComposerClient::Composition::CLIENT);
+    }
+
+    IMapper::BufferDescriptorInfo mInfo;
+    IMapper::Rect mAccessRegion;
+    uint32_t mStride;
+
+   protected:
+    IComposerClient::Composition mComposition;
+    std::shared_ptr<Gralloc> mGralloc;
+    int32_t mFillFence;
+    const native_handle_t* mBufferHandle = nullptr;
+};
 
 TEST_F(GraphicsComposerReadbackTest, SingleSolidColorLayer) {
+    if (!mHasReadbackBuffer) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
+    }
     mWriter->selectDisplay(mPrimaryDisplay);
-    mComposerClient->setPowerMode(mPrimaryDisplay, PowerMode::ON);
-    mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB, RenderIntent::COLORIMETRIC);
+    ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB,
+                                                          RenderIntent::COLORIMETRIC));
 
     auto layer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
-    IComposerClient::Color color({0, 0, 0xff, 0xff});
-    IComposerClient::Rect coloredSquare({100, 100, 500, 500});
-    layer->setColor(color);
+    IComposerClient::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight});
+    layer->setColor(BLUE);
     layer->setDisplayFrame(coloredSquare);
     layer->setZOrder(10);
 
     std::vector<std::shared_ptr<TestLayer>> layers = {layer};
 
     // expected color for each pixel
-    std::vector<IComposerClient::Color> expectedColors(width * height);
-    for (int row = 0; row < height; row++) {
-        for (int col = 0; col < width; col++) {
-            int pixel = row * width + col;
-            if (row >= coloredSquare.top && row < coloredSquare.bottom &&
-                col >= coloredSquare.left && col < coloredSquare.right) {
-                expectedColors[pixel] = color;
-            } else {
-                expectedColors[pixel] = {0, 0, 0, 0xff};
+    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+    fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE);
+
+    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                  mDisplayHeight, mPixelFormat, mDataspace);
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+    writeLayers(layers);
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->validateDisplay();
+    execute();
+    // if hwc cannot handle and asks for composition change,
+    // just succeed the test
+    if (mReader->mCompositionChanges.size() != 0) {
+        clearCommandReaderState();
+        GTEST_SUCCEED();
+        return;
+    }
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+}
+
+TEST_F(GraphicsComposerReadbackTest, SetLayerBuffer) {
+    if (!mHasReadbackBuffer) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
+    }
+
+    mWriter->selectDisplay(mPrimaryDisplay);
+
+    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                  mDisplayHeight, mPixelFormat, mDataspace);
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+    fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED);
+    fillColorsArea(expectedColors, mDisplayWidth,
+                   {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight / 2}, GREEN);
+    fillColorsArea(expectedColors, mDisplayWidth,
+                   {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, BLUE);
+
+    auto layer =
+        std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth,
+                                          mDisplayHeight, PixelFormat::RGBA_8888);
+    layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+    layer->setZOrder(10);
+    ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
+
+    std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+    writeLayers(layers);
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->validateDisplay();
+    execute();
+
+    if (mReader->mCompositionChanges.size() != 0) {
+        clearCommandReaderState();
+        GTEST_SUCCEED();
+        return;
+    }
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    mWriter->presentDisplay();
+    execute();
+
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+}
+
+TEST_F(GraphicsComposerReadbackTest, SetLayerBufferNoEffect) {
+    if (!mHasReadbackBuffer) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
+    }
+
+    mWriter->selectDisplay(mPrimaryDisplay);
+    ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB,
+                                                          RenderIntent::COLORIMETRIC));
+
+    auto layer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+    IComposerClient::Rect coloredSquare({0, 0, mDisplayWidth, mDisplayHeight});
+    layer->setColor(BLUE);
+    layer->setDisplayFrame(coloredSquare);
+    layer->setZOrder(10);
+    layer->write(mWriter);
+
+    // This following buffer call should have no effect
+    IMapper::BufferDescriptorInfo bufferInfo{};
+    bufferInfo.width = mDisplayWidth;
+    bufferInfo.height = mDisplayHeight;
+    bufferInfo.layerCount = 1;
+    bufferInfo.format = PixelFormat::RGBA_8888;
+    bufferInfo.usage =
+        static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN);
+    const native_handle_t* bufferHandle = mGralloc->allocate(bufferInfo);
+    mWriter->setLayerBuffer(0, bufferHandle, -1);
+
+    // expected color for each pixel
+    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+    fillColorsArea(expectedColors, mDisplayWidth, coloredSquare, BLUE);
+
+    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                  mDisplayHeight, mPixelFormat, mDataspace);
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+    mWriter->validateDisplay();
+    execute();
+
+    if (mReader->mCompositionChanges.size() != 0) {
+        clearCommandReaderState();
+        GTEST_SUCCEED();
+        return;
+    }
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+}
+
+TEST_F(GraphicsComposerReadbackTest, ClientComposition) {
+    if (!mHasReadbackBuffer) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
+    }
+
+    mWriter->selectDisplay(mPrimaryDisplay);
+
+    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+    fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED);
+    fillColorsArea(expectedColors, mDisplayWidth,
+                   {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight / 2}, GREEN);
+    fillColorsArea(expectedColors, mDisplayWidth,
+                   {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, BLUE);
+
+    auto layer =
+        std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth,
+                                          mDisplayHeight, PixelFormat::RGBA_FP16);
+    layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+    layer->setZOrder(10);
+
+    std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                  mDisplayHeight, mPixelFormat, mDataspace);
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+    writeLayers(layers);
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->validateDisplay();
+    execute();
+
+    if (mReader->mCompositionChanges.size() != 0) {
+        ASSERT_EQ(1, mReader->mCompositionChanges.size());
+        ASSERT_EQ(1, mReader->mCompositionChanges[0].second);
+
+        ASSERT_NO_FATAL_FAILURE(
+            mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount));
+
+        // create client target buffer
+        uint32_t clientStride;
+        IMapper::BufferDescriptorInfo clientInfo;
+        clientInfo.width = layer->mInfo.width;
+        clientInfo.height = layer->mInfo.height;
+        clientInfo.layerCount = layer->mInfo.layerCount;
+        clientInfo.format = PixelFormat::RGBA_8888;
+        clientInfo.usage =
+            static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                                  BufferUsage::COMPOSER_CLIENT_TARGET);
+        const native_handle_t* clientBufferHandle =
+            mGralloc->allocate(clientInfo, /*import*/ true, &clientStride);
+        ASSERT_NE(nullptr, clientBufferHandle);
+
+        void* clientBufData =
+            mGralloc->lock(clientBufferHandle, clientInfo.usage, layer->mAccessRegion, -1);
+
+        ASSERT_NO_FATAL_FAILURE(fillBuffer(clientInfo.width, clientInfo.height, clientStride,
+                                           clientBufData, clientInfo.format, expectedColors));
+        int clientFence = mGralloc->unlock(clientBufferHandle);
+        if (clientFence != -1) {
+            sync_wait(clientFence, -1);
+            close(clientFence);
+        }
+
+        IComposerClient::Rect damage{0, 0, mDisplayWidth, mDisplayHeight};
+        mWriter->setClientTarget(0, clientBufferHandle, clientFence, Dataspace::UNKNOWN,
+                                 std::vector<IComposerClient::Rect>(1, damage));
+
+        layer->setToClientComposition(mWriter);
+        mWriter->validateDisplay();
+        execute();
+        ASSERT_EQ(0, mReader->mCompositionChanges.size());
+    }
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    mWriter->presentDisplay();
+    execute();
+
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+}
+
+TEST_F(GraphicsComposerReadbackTest, DeviceAndClientComposition) {
+    if (!mHasReadbackBuffer) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
+    }
+
+    mWriter->selectDisplay(mPrimaryDisplay);
+    ASSERT_NO_FATAL_FAILURE(
+        mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kClientTargetSlotCount));
+
+    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+    fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 2}, GREEN);
+    fillColorsArea(expectedColors, mDisplayWidth,
+                   {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, RED);
+
+    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                  mDisplayHeight, mPixelFormat, mDataspace);
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+    auto deviceLayer =
+        std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth,
+                                          mDisplayHeight / 2, PixelFormat::RGBA_8888);
+    std::vector<IComposerClient::Color> deviceColors(deviceLayer->mInfo.width *
+                                                     deviceLayer->mInfo.height);
+    fillColorsArea(deviceColors, deviceLayer->mInfo.width,
+                   {0, 0, static_cast<int32_t>(deviceLayer->mInfo.width),
+                    static_cast<int32_t>(deviceLayer->mInfo.height)},
+                   GREEN);
+    deviceLayer->setDisplayFrame({0, 0, static_cast<int32_t>(deviceLayer->mInfo.width),
+                                  static_cast<int32_t>(deviceLayer->mInfo.height)});
+    deviceLayer->setZOrder(10);
+    ASSERT_NO_FATAL_FAILURE(deviceLayer->setBuffer(deviceColors));
+    deviceLayer->write(mWriter);
+
+    auto clientLayer = std::make_shared<TestBufferLayer>(
+        mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth, mDisplayHeight / 2,
+        PixelFormat::RGBA_8888, IComposerClient::Composition::CLIENT);
+    IComposerClient::Rect clientFrame = {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight};
+    clientLayer->setDisplayFrame(clientFrame);
+    clientLayer->setZOrder(0);
+    clientLayer->write(mWriter);
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    IMapper::BufferDescriptorInfo clientInfo;
+    clientInfo.width = mDisplayWidth;
+    clientInfo.height = mDisplayHeight;
+    clientInfo.layerCount = 1;
+    clientInfo.format = PixelFormat::RGBA_8888;
+    clientInfo.usage =
+        static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::CPU_WRITE_OFTEN |
+                              BufferUsage::COMPOSER_CLIENT_TARGET);
+
+    uint32_t clientStride;
+    const native_handle_t* clientBufferHandle =
+        mGralloc->allocate(clientInfo, /*import*/ true, &clientStride);
+    ASSERT_NE(nullptr, clientBufferHandle);
+
+    IMapper::Rect clientAccessRegion;
+    clientAccessRegion.left = 0;
+    clientAccessRegion.top = 0;
+    clientAccessRegion.width = mDisplayWidth;
+    clientAccessRegion.height = mDisplayHeight;
+    void* clientData = mGralloc->lock(clientBufferHandle, clientInfo.usage, clientAccessRegion, -1);
+    std::vector<IComposerClient::Color> clientColors(clientInfo.width * clientInfo.height);
+    fillColorsArea(clientColors, clientInfo.width, clientFrame, RED);
+    ASSERT_NO_FATAL_FAILURE(fillBuffer(clientInfo.width, clientInfo.height, clientStride,
+                                       clientData, clientInfo.format, clientColors));
+    int clientFence = mGralloc->unlock(clientBufferHandle);
+    if (clientFence != -1) {
+        sync_wait(clientFence, -1);
+        close(clientFence);
+    }
+
+    mWriter->setClientTarget(0, clientBufferHandle, clientFence, Dataspace::UNKNOWN,
+                             std::vector<IComposerClient::Rect>(1, clientFrame));
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->validateDisplay();
+    execute();
+    if (mReader->mCompositionChanges.size() != 0) {
+        clearCommandReaderState();
+        GTEST_SUCCEED();
+        return;
+    }
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+}
+
+TEST_F(GraphicsComposerReadbackTest, SetLayerDamage) {
+    if (!mHasReadbackBuffer) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelformat/dataspace";
+        return;
+    }
+
+    mWriter->selectDisplay(mPrimaryDisplay);
+
+    IComposerClient::Rect redRect = {0, 0, mDisplayWidth / 4, mDisplayHeight / 4};
+
+    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+    fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
+
+    auto layer =
+        std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth,
+                                          mDisplayHeight, PixelFormat::RGBA_8888);
+    layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+    layer->setZOrder(10);
+    ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
+
+    std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                  mDisplayHeight, mPixelFormat, mDataspace);
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+    writeLayers(layers);
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->validateDisplay();
+    execute();
+    if (mReader->mCompositionChanges.size() != 0) {
+        clearCommandReaderState();
+        GTEST_SUCCEED();
+        return;
+    }
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+
+    // update surface damage and recheck
+    redRect = {mDisplayWidth / 4, mDisplayHeight / 4, mDisplayWidth / 2, mDisplayHeight / 2};
+    clearColors(expectedColors, mDisplayWidth, mDisplayHeight);
+    fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
+
+    ASSERT_NO_FATAL_FAILURE(layer->fillBuffer(expectedColors));
+    layer->setSurfaceDamage(
+        std::vector<IComposerClient::Rect>(1, {0, 0, mDisplayWidth / 2, mDisplayWidth / 2}));
+
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+    writeLayers(layers);
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->validateDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+    ASSERT_EQ(0, mReader->mCompositionChanges.size());
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+}
+
+TEST_F(GraphicsComposerReadbackTest, SetLayerPlaneAlpha) {
+    if (!mHasReadbackBuffer) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
+    }
+
+    mWriter->selectDisplay(mPrimaryDisplay);
+    ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB,
+                                                          RenderIntent::COLORIMETRIC));
+
+    auto layer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+    layer->setColor(RED);
+    layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+    layer->setZOrder(10);
+    layer->setAlpha(0);
+    layer->setBlendMode(IComposerClient::BlendMode::PREMULTIPLIED);
+
+    std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                  mDisplayHeight, mPixelFormat, mDataspace);
+
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+    writeLayers(layers);
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->validateDisplay();
+    execute();
+    if (mReader->mCompositionChanges.size() != 0) {
+        clearCommandReaderState();
+        GTEST_SUCCEED();
+        return;
+    }
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+}
+
+TEST_F(GraphicsComposerReadbackTest, SetLayerSourceCrop) {
+    if (!mHasReadbackBuffer) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
+    }
+
+    mWriter->selectDisplay(mPrimaryDisplay);
+
+    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+    fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight / 4}, RED);
+    fillColorsArea(expectedColors, mDisplayWidth,
+                   {0, mDisplayHeight / 2, mDisplayWidth, mDisplayHeight}, BLUE);
+
+    auto layer =
+        std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay, mDisplayWidth,
+                                          mDisplayHeight, PixelFormat::RGBA_8888);
+    layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+    layer->setZOrder(10);
+    layer->setSourceCrop({0, static_cast<float>(mDisplayHeight / 2),
+                          static_cast<float>(mDisplayWidth), static_cast<float>(mDisplayHeight)});
+    ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
+
+    std::vector<std::shared_ptr<TestLayer>> layers = {layer};
+
+    // update expected colors to match crop
+    fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight}, BLUE);
+    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                  mDisplayHeight, mPixelFormat, mDataspace);
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+    writeLayers(layers);
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->validateDisplay();
+    execute();
+    if (mReader->mCompositionChanges.size() != 0) {
+        clearCommandReaderState();
+        GTEST_SUCCEED();
+        return;
+    }
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+}
+
+TEST_F(GraphicsComposerReadbackTest, SetLayerZOrder) {
+    if (!mHasReadbackBuffer) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
+    }
+
+    mWriter->selectDisplay(mPrimaryDisplay);
+    ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB,
+                                                          RenderIntent::COLORIMETRIC));
+
+    IComposerClient::Rect redRect = {0, 0, mDisplayWidth, mDisplayHeight / 2};
+    IComposerClient::Rect blueRect = {0, mDisplayHeight / 4, mDisplayWidth, mDisplayHeight};
+    auto redLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+    redLayer->setColor(RED);
+    redLayer->setDisplayFrame(redRect);
+
+    auto blueLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+    blueLayer->setColor(BLUE);
+    blueLayer->setDisplayFrame(blueRect);
+    blueLayer->setZOrder(5);
+
+    std::vector<std::shared_ptr<TestLayer>> layers = {redLayer, blueLayer};
+    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+
+    // red in front of blue
+    redLayer->setZOrder(10);
+
+    // fill blue first so that red will overwrite on overlap
+    fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE);
+    fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
+
+    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                  mDisplayHeight, mPixelFormat, mDataspace);
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+    writeLayers(layers);
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->validateDisplay();
+    execute();
+    if (mReader->mCompositionChanges.size() != 0) {
+        clearCommandReaderState();
+        GTEST_SUCCEED();
+        return;
+    }
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+
+    redLayer->setZOrder(1);
+    clearColors(expectedColors, mDisplayWidth, mDisplayHeight);
+    fillColorsArea(expectedColors, mDisplayWidth, redRect, RED);
+    fillColorsArea(expectedColors, mDisplayWidth, blueRect, BLUE);
+
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+    writeLayers(layers);
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->validateDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mCompositionChanges.size());
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+}
+
+class GraphicsComposerBlendModeReadbackTest : public GraphicsComposerReadbackTest,
+                                              public ::testing::WithParamInterface<float> {
+   public:
+    void SetUp() override {
+        GraphicsComposerReadbackTest::SetUp();
+        mBackgroundColor = BLACK;
+        mTopLayerColor = RED;
+    }
+
+    void TearDown() override { GraphicsComposerReadbackTest::TearDown(); }
+
+    void setBackgroundColor(IComposerClient::Color color) { mBackgroundColor = color; }
+
+    void setTopLayerColor(IComposerClient::Color color) { mTopLayerColor = color; }
+
+    void setUpLayers(IComposerClient::BlendMode blendMode) {
+        mLayers.clear();
+        std::vector<IComposerClient::Color> topLayerPixelColors(mDisplayWidth * mDisplayHeight);
+        fillColorsArea(topLayerPixelColors, mDisplayWidth, {0, 0, mDisplayWidth, mDisplayHeight},
+                       mTopLayerColor);
+
+        auto backgroundLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+        backgroundLayer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+        backgroundLayer->setZOrder(0);
+        backgroundLayer->setColor(mBackgroundColor);
+
+        auto layer = std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay,
+                                                       mDisplayWidth, mDisplayHeight,
+                                                       PixelFormat::RGBA_8888);
+        layer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+        layer->setZOrder(10);
+        ASSERT_NO_FATAL_FAILURE(layer->setBuffer(topLayerPixelColors));
+
+        layer->setBlendMode(blendMode);
+        layer->setAlpha(GetParam());
+
+        mLayers.push_back(backgroundLayer);
+        mLayers.push_back(layer);
+    }
+
+    void setExpectedColors(std::vector<IComposerClient::Color>& expectedColors) {
+        ASSERT_EQ(2, mLayers.size());
+        clearColors(expectedColors, mDisplayWidth, mDisplayHeight);
+
+        auto layer = mLayers[1];
+        IComposerClient::BlendMode blendMode = layer->mBlendMode;
+        float alpha = mTopLayerColor.a / 255.0 * layer->mAlpha;
+        if (blendMode == IComposerClient::BlendMode::NONE) {
+            for (int i = 0; i < expectedColors.size(); i++) {
+                expectedColors[i].r = mTopLayerColor.r * layer->mAlpha;
+                expectedColors[i].g = mTopLayerColor.g * layer->mAlpha;
+                expectedColors[i].b = mTopLayerColor.b * layer->mAlpha;
+                expectedColors[i].a = alpha * 255.0;
+            }
+        } else if (blendMode == IComposerClient::BlendMode::PREMULTIPLIED) {
+            for (int i = 0; i < expectedColors.size(); i++) {
+                expectedColors[i].r =
+                    mTopLayerColor.r * layer->mAlpha + mBackgroundColor.r * (1.0 - alpha);
+                expectedColors[i].g =
+                    mTopLayerColor.g * layer->mAlpha + mBackgroundColor.g * (1.0 - alpha);
+                expectedColors[i].b =
+                    mTopLayerColor.b * layer->mAlpha + mBackgroundColor.b * (1.0 - alpha);
+                expectedColors[i].a = alpha + mBackgroundColor.a * (1.0 - alpha);
+            }
+        } else if (blendMode == IComposerClient::BlendMode::COVERAGE) {
+            for (int i = 0; i < expectedColors.size(); i++) {
+                expectedColors[i].r = mTopLayerColor.r * alpha + mBackgroundColor.r * (1.0 - alpha);
+                expectedColors[i].g = mTopLayerColor.g * alpha + mBackgroundColor.g * (1.0 - alpha);
+                expectedColors[i].b = mTopLayerColor.b * alpha + mBackgroundColor.b * (1.0 - alpha);
+                expectedColors[i].a = mTopLayerColor.a * alpha + mBackgroundColor.a * (1.0 - alpha);
             }
         }
     }
 
-    PixelFormat pixelFormat;
-    Dataspace dataspace;
-    Error error;
-    getReadbackBufferAttributes(mPrimaryDisplay, &pixelFormat, &dataspace, &error);
+   protected:
+    std::vector<std::shared_ptr<TestLayer>> mLayers;
+    IComposerClient::Color mBackgroundColor;
+    IComposerClient::Color mTopLayerColor;
+};
 
-    IMapper::BufferDescriptorInfo info;
-    info.width = width;
-    info.height = height;
-    info.layerCount = 1;
-    info.format = pixelFormat;
-    info.usage = static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN | BufferUsage::GPU_TEXTURE);
-
-    uint32_t stride;
-    const native_handle_t* buffer = mGralloc->allocate(info, /*import*/ true, &stride);
-    mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer, -1);
-
-    render(layers);
-
-    int32_t fenceHandle;
-    mComposerClient->getReadbackBufferFence(mPrimaryDisplay, &fenceHandle);
-
-    // lock buffer
-    // Create Rect accessRegion to specify reading the entire buffer
-    IMapper::Rect accessRegion;
-    accessRegion.left = 0;
-    accessRegion.top = 0;
-    accessRegion.width = info.width;
-    accessRegion.height = info.height;
-
-    void* bufData = mGralloc->lock(buffer, info.usage, accessRegion, fenceHandle);
-    checkReadbackBuffer(info, stride, bufData, expectedColors);
-    int unlockFence = mGralloc->unlock(buffer);
-
-    if (unlockFence != -1) {
-        close(unlockFence);
+TEST_P(GraphicsComposerBlendModeReadbackTest, None) {
+    if (!mHasReadbackBuffer) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
     }
 
+    mWriter->selectDisplay(mPrimaryDisplay);
+
+    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+
+    setBackgroundColor(BLACK);
+    setTopLayerColor(TRANSLUCENT_RED);
+    setUpLayers(IComposerClient::BlendMode::NONE);
+    setExpectedColors(expectedColors);
+
+    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                  mDisplayHeight, mPixelFormat, mDataspace);
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+    writeLayers(mLayers);
+    ASSERT_EQ(0, mReader->mErrors.size());
     mWriter->validateDisplay();
+    execute();
+    if (mReader->mCompositionChanges.size() != 0) {
+        clearCommandReaderState();
+        GTEST_SUCCEED();
+        return;
+    }
+    ASSERT_EQ(0, mReader->mErrors.size());
     mWriter->presentDisplay();
     execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+}
+
+// TODO: bug 116865056: Readback returns (245, 0, 0) for layer plane
+// alpha of .2, expected 10.2
+TEST_P(GraphicsComposerBlendModeReadbackTest, DISABLED_Coverage) {
+    if (!mHasReadbackBuffer) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
+    }
+
+    mWriter->selectDisplay(mPrimaryDisplay);
+
+    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+
+    setBackgroundColor(BLACK);
+    setTopLayerColor(TRANSLUCENT_RED);
+
+    setUpLayers(IComposerClient::BlendMode::COVERAGE);
+    setExpectedColors(expectedColors);
+
+    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                  mDisplayHeight, mPixelFormat, mDataspace);
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+    writeLayers(mLayers);
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->validateDisplay();
+    execute();
+    if (mReader->mCompositionChanges.size() != 0) {
+        clearCommandReaderState();
+        GTEST_SUCCEED();
+        return;
+    }
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+}
+
+TEST_P(GraphicsComposerBlendModeReadbackTest, Premultiplied) {
+    if (!mHasReadbackBuffer) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
+    }
+
+    mWriter->selectDisplay(mPrimaryDisplay);
+
+    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+
+    setBackgroundColor(BLACK);
+    setTopLayerColor(TRANSLUCENT_RED);
+    setUpLayers(IComposerClient::BlendMode::PREMULTIPLIED);
+    setExpectedColors(expectedColors);
+
+    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                  mDisplayHeight, mPixelFormat, mDataspace);
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+    writeLayers(mLayers);
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->validateDisplay();
+    execute();
+    if (mReader->mCompositionChanges.size() != 0) {
+        clearCommandReaderState();
+        GTEST_SUCCEED();
+        return;
+    }
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+}
+
+INSTANTIATE_TEST_CASE_P(BlendModeTest, GraphicsComposerBlendModeReadbackTest,
+                        ::testing::Values(.2, 1.0));
+
+class GraphicsComposerTransformReadbackTest : public GraphicsComposerReadbackTest {
+   protected:
+    void SetUp() override {
+        GraphicsComposerReadbackTest::SetUp();
+
+        mWriter->selectDisplay(mPrimaryDisplay);
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::SRGB,
+                                                              RenderIntent::COLORIMETRIC));
+
+        auto backgroundLayer = std::make_shared<TestColorLayer>(mComposerClient, mPrimaryDisplay);
+        backgroundLayer->setColor({0, 0, 0, 0});
+        backgroundLayer->setDisplayFrame({0, 0, mDisplayWidth, mDisplayHeight});
+        backgroundLayer->setZOrder(0);
+
+        mSideLength = mDisplayWidth < mDisplayHeight ? mDisplayWidth : mDisplayHeight;
+        IComposerClient::Rect redRect = {0, 0, mSideLength / 2, mSideLength / 2};
+        IComposerClient::Rect blueRect = {mSideLength / 2, mSideLength / 2, mSideLength,
+                                          mSideLength};
+
+        mLayer =
+            std::make_shared<TestBufferLayer>(mComposerClient, mGralloc, mPrimaryDisplay,
+                                              mSideLength, mSideLength, PixelFormat::RGBA_8888);
+        mLayer->setDisplayFrame({0, 0, mSideLength, mSideLength});
+        mLayer->setZOrder(10);
+
+        std::vector<IComposerClient::Color> baseColors(mSideLength * mSideLength);
+        fillColorsArea(baseColors, mSideLength, redRect, RED);
+        fillColorsArea(baseColors, mSideLength, blueRect, BLUE);
+        ASSERT_NO_FATAL_FAILURE(mLayer->setBuffer(baseColors));
+
+        mLayers = {backgroundLayer, mLayer};
+    }
+
+   protected:
+    std::shared_ptr<TestBufferLayer> mLayer;
+    std::vector<IComposerClient::Color> baseColors;
+    std::vector<std::shared_ptr<TestLayer>> mLayers;
+    int mSideLength;
+};
+
+TEST_F(GraphicsComposerTransformReadbackTest, FLIP_H) {
+    if (!mHasReadbackBuffer) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
+    }
+    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                  mDisplayHeight, mPixelFormat, mDataspace);
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+    mLayer->setTransform(Transform::FLIP_H);
+    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+    fillColorsArea(expectedColors, mDisplayWidth,
+                   {mSideLength / 2, 0, mSideLength, mSideLength / 2}, RED);
+    fillColorsArea(expectedColors, mDisplayWidth,
+                   {0, mSideLength / 2, mSideLength / 2, mSideLength}, BLUE);
+
+    writeLayers(mLayers);
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->validateDisplay();
+    execute();
+    if (mReader->mCompositionChanges.size() != 0) {
+        clearCommandReaderState();
+        GTEST_SUCCEED();
+        return;
+    }
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+}
+
+TEST_F(GraphicsComposerTransformReadbackTest, FLIP_V) {
+    if (!mHasReadbackBuffer) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
+    }
+    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                  mDisplayHeight, mPixelFormat, mDataspace);
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+    mLayer->setTransform(Transform::FLIP_V);
+
+    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+    fillColorsArea(expectedColors, mDisplayWidth,
+                   {0, mSideLength / 2, mSideLength / 2, mSideLength}, RED);
+    fillColorsArea(expectedColors, mDisplayWidth,
+                   {mSideLength / 2, 0, mSideLength, mSideLength / 2}, BLUE);
+
+    writeLayers(mLayers);
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->validateDisplay();
+    execute();
+    if (mReader->mCompositionChanges.size() != 0) {
+        clearCommandReaderState();
+        GTEST_SUCCEED();
+        return;
+    }
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
+}
+
+TEST_F(GraphicsComposerTransformReadbackTest, ROT_180) {
+    if (!mHasReadbackBuffer) {
+        GTEST_SUCCEED() << "Readback not supported or unsupported pixelFormat/dataspace";
+        return;
+    }
+    ReadbackBuffer readbackBuffer(mPrimaryDisplay, mComposerClient, mGralloc, mDisplayWidth,
+                                  mDisplayHeight, mPixelFormat, mDataspace);
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
+
+    mLayer->setTransform(Transform::ROT_180);
+
+    std::vector<IComposerClient::Color> expectedColors(mDisplayWidth * mDisplayHeight);
+    fillColorsArea(expectedColors, mDisplayWidth,
+                   {mSideLength / 2, mSideLength / 2, mSideLength, mSideLength}, RED);
+    fillColorsArea(expectedColors, mDisplayWidth, {0, 0, mSideLength / 2, mSideLength / 2}, BLUE);
+
+    writeLayers(mLayers);
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->validateDisplay();
+    execute();
+    if (mReader->mCompositionChanges.size() != 0) {
+        clearCommandReaderState();
+        GTEST_SUCCEED();
+        return;
+    }
+    ASSERT_EQ(0, mReader->mErrors.size());
+    mWriter->presentDisplay();
+    execute();
+    ASSERT_EQ(0, mReader->mErrors.size());
+    ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
 }
 
 }  // anonymous namespace
diff --git a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
index ffd6daf..7834b94 100644
--- a/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
+++ b/graphics/composer/2.2/vts/functional/VtsHalGraphicsComposerV2_2TargetTest.cpp
@@ -73,14 +73,29 @@
         // assume the first display is primary and is never removed
         mPrimaryDisplay = waitForFirstDisplay();
 
+        Config config = mComposerClient->getActiveConfig(mPrimaryDisplay);
+        mDisplayWidth = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+                                                             IComposerClient::Attribute::WIDTH);
+        mDisplayHeight = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+                                                              IComposerClient::Attribute::HEIGHT);
+
         // explicitly disable vsync
         mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
         mComposerCallback->setVsyncAllowed(false);
 
         mComposerClient->getRaw()->getReadbackBufferAttributes(
-            mPrimaryDisplay, [&](const auto& tmpError, const auto&, const auto&) {
+            mPrimaryDisplay,
+            [&](const auto& tmpError, const auto& tmpPixelFormat, const auto& tmpDataspace) {
                 mHasReadbackBuffer = tmpError == Error::NONE;
+                if (mHasReadbackBuffer) {
+                    mReadbackPixelFormat = tmpPixelFormat;
+                    mReadbackDataspace = tmpDataspace;
+                    ASSERT_LT(static_cast<PixelFormat>(0), mReadbackPixelFormat);
+                    ASSERT_NE(Dataspace::UNKNOWN, mReadbackDataspace);
+                }
             });
+
+        mInvalidDisplayId = GetInvalidDisplayId();
     }
 
     void TearDown() override {
@@ -91,6 +106,22 @@
         }
     }
 
+    // returns an invalid display id (one that has not been registered to a
+    // display.  Currently assuming that a device will never have close to
+    // std::numeric_limit<uint64_t>::max() displays registered while running tests
+    Display GetInvalidDisplayId() {
+        std::vector<Display> validDisplays = mComposerCallback->getDisplays();
+        uint64_t id = std::numeric_limits<uint64_t>::max();
+        while (id > 0) {
+            if (std::find(validDisplays.begin(), validDisplays.end(), id) == validDisplays.end()) {
+                return id;
+            }
+            id--;
+        }
+
+        return 0;
+    }
+
     // use the slot count usually set by SF
     static constexpr uint32_t kBufferSlotCount = 64;
 
@@ -99,8 +130,15 @@
     sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
     // the first display and is assumed never to be removed
     Display mPrimaryDisplay;
+    int32_t mDisplayWidth;
+    int32_t mDisplayHeight;
+
     bool mHasReadbackBuffer;
 
+    uint64_t mInvalidDisplayId;
+    PixelFormat mReadbackPixelFormat;
+    Dataspace mReadbackDataspace;
+
    private:
     Display waitForFirstDisplay() {
         while (true) {
@@ -197,7 +235,11 @@
         static_cast<Error>(mReader->mErrors[0].second) == Error::UNSUPPORTED) {
         mReader->mErrors.clear();
         GTEST_SUCCEED() << "SetLayerPerFrameMetadata is not supported";
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->destroyLayer(mPrimaryDisplay, layer));
+        return;
     }
+
+    ASSERT_NO_FATAL_FAILURE(mComposerClient->destroyLayer(mPrimaryDisplay, layer));
 }
 
 /**
@@ -256,9 +298,35 @@
 }
 
 /**
+ * Test IComposerClient::getClientTargetSupport_2_2
+ *
+ * Test that IComposerClient::getClientTargetSupport_2_2 returns
+ * Error::BAD_DISPLAY when passed in an invalid display handle
+ */
+
+TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport_2_2BadDisplay) {
+    std::vector<Config> configs = mComposerClient->getDisplayConfigs(mPrimaryDisplay);
+    for (auto config : configs) {
+        int32_t width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+                                                             IComposerClient::Attribute::WIDTH);
+        int32_t height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
+                                                              IComposerClient::Attribute::HEIGHT);
+        ASSERT_LT(0, width);
+        ASSERT_LT(0, height);
+
+        mComposerClient->setActiveConfig(mPrimaryDisplay, config);
+
+        Error error = mComposerClient->getRaw()->getClientTargetSupport_2_2(
+            mInvalidDisplayId, width, height, PixelFormat::RGBA_8888, Dataspace::UNKNOWN);
+
+        EXPECT_EQ(Error::BAD_DISPLAY, error);
+    }
+}
+
+/**
  * Test IComposerClient::setPowerMode_2_2.
  */
-TEST_F(GraphicsComposerHidlTest, setPowerMode_2_2) {
+TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2) {
     std::vector<IComposerClient::PowerMode> modes;
     modes.push_back(IComposerClient::PowerMode::OFF);
     modes.push_back(IComposerClient::PowerMode::ON_SUSPEND);
@@ -269,25 +337,118 @@
     }
 }
 
-TEST_F(GraphicsComposerHidlTest, setReadbackBuffer) {
+/**
+ * Test IComposerClient::setPowerMode_2_2
+ *
+ * Test that IComposerClient::setPowerMode_2_2 succeeds for different varations
+ * of PowerMode
+ */
+TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2Variations) {
+    std::vector<IComposerClient::PowerMode> modes;
+
+    modes.push_back(IComposerClient::PowerMode::OFF);
+    modes.push_back(IComposerClient::PowerMode::OFF);
+
+    for (auto mode : modes) {
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode_2_2(mPrimaryDisplay, mode));
+    }
+
+    modes.clear();
+
+    modes.push_back(IComposerClient::PowerMode::ON);
+    modes.push_back(IComposerClient::PowerMode::ON);
+
+    for (auto mode : modes) {
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode_2_2(mPrimaryDisplay, mode));
+    }
+
+    modes.clear();
+
+    modes.push_back(IComposerClient::PowerMode::ON_SUSPEND);
+    modes.push_back(IComposerClient::PowerMode::ON_SUSPEND);
+
+    for (auto mode : modes) {
+        ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode_2_2(mPrimaryDisplay, mode));
+    }
+
+    if (mComposerClient->getDozeSupport(mPrimaryDisplay)) {
+        modes.clear();
+
+        modes.push_back(IComposerClient::PowerMode::DOZE);
+        modes.push_back(IComposerClient::PowerMode::DOZE);
+
+        for (auto mode : modes) {
+            ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode_2_2(mPrimaryDisplay, mode));
+        }
+
+        modes.clear();
+
+        modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND);
+        modes.push_back(IComposerClient::PowerMode::DOZE_SUSPEND);
+
+        for (auto mode : modes) {
+            ASSERT_NO_FATAL_FAILURE(mComposerClient->setPowerMode_2_2(mPrimaryDisplay, mode));
+        }
+    }
+}
+
+/**
+ * Test IComposerClient::setPowerMode_2_2
+ *
+ * Tests that IComposerClient::setPowerMode_2_2 returns BAD_DISPLAY when passed an
+ * invalid display handle
+ */
+TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2BadDisplay) {
+    Error error = mComposerClient->getRaw()->setPowerMode_2_2(mInvalidDisplayId,
+                                                              IComposerClient::PowerMode::ON);
+    ASSERT_EQ(Error::BAD_DISPLAY, error);
+}
+
+/**
+ * Test IComposerClient::setPowerMode_2_2
+ *
+ * Test that IComposerClient::setPowerMode_2_2 returns BAD_PARAMETER when passed
+ * an invalid PowerMode
+ */
+TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2BadParameter) {
+    Error error = mComposerClient->getRaw()->setPowerMode_2_2(
+        mPrimaryDisplay, static_cast<IComposerClient::PowerMode>(-1));
+    ASSERT_EQ(Error::BAD_PARAMETER, error);
+}
+
+/**
+ * Test IComposerClient::setPowerMode_2_2
+ *
+ * Test that IComposerClient::setPowerMode_2_2 returns UNSUPPORTED when passed
+ * DOZE or DOZE_SUPPORT on a device that does not support these modes
+ */
+TEST_F(GraphicsComposerHidlTest, SetPowerMode_2_2Unsupported) {
+    if (!mComposerClient->getDozeSupport(mPrimaryDisplay)) {
+        Error error = mComposerClient->getRaw()->setPowerMode_2_2(mPrimaryDisplay,
+                                                                  IComposerClient::PowerMode::DOZE);
+        EXPECT_EQ(Error::UNSUPPORTED, error);
+
+        error = mComposerClient->getRaw()->setPowerMode_2_2(
+            mPrimaryDisplay, IComposerClient::PowerMode::DOZE_SUSPEND);
+        EXPECT_EQ(Error::UNSUPPORTED, error);
+    }
+}
+
+/**
+ * Test IComposerClient::setReadbackBuffer
+ *
+ * Test IComposerClient::setReadbackBuffer
+ */
+TEST_F(GraphicsComposerHidlTest, SetReadbackBuffer) {
     if (!mHasReadbackBuffer) {
         return;
     }
 
-    PixelFormat pixelFormat;
-    Dataspace dataspace;
-    mComposerClient->getReadbackBufferAttributes(mPrimaryDisplay, &pixelFormat, &dataspace);
-    ASSERT_LT(static_cast<PixelFormat>(0), pixelFormat);
-    ASSERT_NE(Dataspace::UNKNOWN, dataspace);
-
     IMapper::BufferDescriptorInfo info{};
-    Config config = mComposerClient->getActiveConfig(mPrimaryDisplay);
-    info.width = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
-                                                      IComposerClient::Attribute::WIDTH);
-    info.height = mComposerClient->getDisplayAttribute(mPrimaryDisplay, config,
-                                                       IComposerClient::Attribute::HEIGHT);
+    info.width = mDisplayWidth;
+    info.height = mDisplayHeight;
     info.layerCount = 1;
-    info.format = static_cast<common::V1_0::PixelFormat>(pixelFormat);
+    info.format = static_cast<common::V1_0::PixelFormat>(mReadbackPixelFormat);
     // BufferUsage::COMPOSER_OUTPUT is missing
     info.usage = static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
 
@@ -299,7 +460,49 @@
     mComposerClient->setReadbackBuffer(mPrimaryDisplay, buffer, -1);
 }
 
-TEST_F(GraphicsComposerHidlTest, getReadbackBufferFenceInactive) {
+/**
+ * Test IComposerClient::setReadbackBuffer
+ *
+ * Test that IComposerClient::setReadbackBuffer returns an Error::BAD_DISPLAY
+ * when passed an invalid display handle
+ */
+TEST_F(GraphicsComposerHidlTest, SetReadbackBufferBadDisplay) {
+    if (!mHasReadbackBuffer) {
+        return;
+    }
+
+    IMapper::BufferDescriptorInfo info{};
+    info.width = mDisplayWidth;
+    info.height = mDisplayHeight;
+    info.layerCount = 1;
+    info.format = static_cast<common::V1_0::PixelFormat>(mReadbackPixelFormat);
+    info.usage = static_cast<uint64_t>(BufferUsage::COMPOSER_OVERLAY | BufferUsage::CPU_READ_OFTEN);
+
+    std::unique_ptr<Gralloc> gralloc;
+    const native_handle_t* buffer;
+    ASSERT_NO_FATAL_FAILURE(gralloc = std::make_unique<Gralloc>());
+    ASSERT_NO_FATAL_FAILURE(buffer = gralloc->allocate(info));
+
+    Error error = mComposerClient->getRaw()->setReadbackBuffer(mInvalidDisplayId, buffer, nullptr);
+    ASSERT_EQ(Error::BAD_DISPLAY, error);
+}
+
+/**
+ * Test IComposerClient::setReadbackBuffer
+ *
+ * Test that IComposerClient::setReadbackBuffer returns Error::BAD_PARAMETER
+ * when passed an invalid buffer handle
+ */
+TEST_F(GraphicsComposerHidlTest, SetReadbackBufferBadParameter) {
+    if (!mHasReadbackBuffer) {
+        return;
+    }
+
+    Error error = mComposerClient->getRaw()->setReadbackBuffer(mPrimaryDisplay, nullptr, nullptr);
+    ASSERT_EQ(Error::BAD_PARAMETER, error);
+}
+
+TEST_F(GraphicsComposerHidlTest, GetReadbackBufferFenceInactive) {
     if (!mHasReadbackBuffer) {
         return;
     }
@@ -320,6 +523,7 @@
 
     mWriter->selectDisplay(mPrimaryDisplay);
     mWriter->selectLayer(layer);
+    mWriter->setLayerCompositionType(IComposerClient::Composition::SOLID_COLOR);
     mWriter->setLayerFloatColor(IComposerClient::FloatColor{1.0, 1.0, 1.0, 1.0});
     mWriter->setLayerFloatColor(IComposerClient::FloatColor{0.0, 0.0, 0.0, 0.0});
     execute();
@@ -329,13 +533,28 @@
         static_cast<Error>(mReader->mErrors[1].second) == Error::UNSUPPORTED) {
         mReader->mErrors.clear();
         GTEST_SUCCEED() << "SetLayerFloatColor is not supported";
+        return;
     }
+
+    // ensure setting float color on layer with composition type that is not
+    // SOLID_COLOR does not fail
+    V2_1::Layer clientLayer;
+    ASSERT_NO_FATAL_FAILURE(clientLayer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(clientLayer);
+    mWriter->setLayerCompositionType(IComposerClient::Composition::CLIENT);
+    mWriter->setLayerFloatColor(IComposerClient::FloatColor{1.0, 1.0, 1.0, 1.0});
+    execute();
+
+    // At this point we know that this function is supported so there should be
+    // no errors (checked upon TearDown)
 }
 
 /**
  * Test IComposerClient::getDataspaceSaturationMatrix.
  */
-TEST_F(GraphicsComposerHidlTest, getDataspaceSaturationMatrix) {
+TEST_F(GraphicsComposerHidlTest, GetDataspaceSaturationMatrix) {
     auto matrix = mComposerClient->getDataspaceSaturationMatrix(Dataspace::SRGB_LINEAR);
     // the last row is known
     ASSERT_EQ(0.0f, matrix[12]);
@@ -344,6 +563,19 @@
     ASSERT_EQ(1.0f, matrix[15]);
 }
 
+/*
+ * Test IComposerClient::getDataspaceSaturationMatrix
+ *
+ * Test that IComposerClient::getDataspaceSaturationMatrix returns
+ * Error::BAD_PARAMETER when passed a dataspace other than
+ * Dataspace::SRGB_LINEAR
+ */
+TEST_F(GraphicsComposerHidlTest, GetDataspaceSaturationMatrixBadParameter) {
+    mComposerClient->getRaw()->getDataspaceSaturationMatrix(
+        Dataspace::UNKNOWN,
+        [&](const auto& tmpError, const auto&) { ASSERT_EQ(Error::BAD_PARAMETER, tmpError); });
+}
+
 /**
  * Test IComposerClient::getColorMode_2_2.
  */
@@ -354,10 +586,22 @@
     EXPECT_NE(modes.cend(), nativeMode);
 }
 
-/**
- * Test IComposerClient::getRenderIntent.
+/*
+ * Test IComposerClient::getColorMode_2_2
+ *
+ * Test that IComposerClient::getColorMode returns Error::BAD_DISPLAY when
+ * passed an invalid display handle
  */
-TEST_F(GraphicsComposerHidlTest, GetRenderIntent) {
+TEST_F(GraphicsComposerHidlTest, GetColorMode_2_2BadDisplay) {
+    mComposerClient->getRaw()->getColorModes_2_2(
+        mInvalidDisplayId,
+        [&](const auto& tmpError, const auto&) { ASSERT_EQ(Error::BAD_DISPLAY, tmpError); });
+}
+
+/**
+ * Test IComposerClient::getRenderIntents.
+ */
+TEST_F(GraphicsComposerHidlTest, GetRenderIntents) {
     std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
     for (auto mode : modes) {
         std::vector<RenderIntent> intents =
@@ -381,6 +625,33 @@
     }
 }
 
+/*
+ * Test IComposerClient::getRenderIntents
+ *
+ * Test that IComposerClient::getRenderIntent returns Error::BAD_DISPLAY when
+ * passed an invalid display handle
+ */
+TEST_F(GraphicsComposerHidlTest, GetRenderIntentsBadDisplay) {
+    std::vector<ColorMode> modes = mComposerClient->getColorModes(mPrimaryDisplay);
+    for (auto mode : modes) {
+        mComposerClient->getRaw()->getRenderIntents(
+            mInvalidDisplayId, mode,
+            [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_DISPLAY, tmpError); });
+    }
+}
+
+/*
+ * Test IComposerClient::getRenderIntents
+ *
+ * Test that IComposerClient::getRenderIntents returns Error::BAD_PARAMETER when
+ * pased either an invalid Color mode or an invalid Render Intent
+ */
+TEST_F(GraphicsComposerHidlTest, GetRenderIntentsBadParameter) {
+    mComposerClient->getRaw()->getRenderIntents(
+        mPrimaryDisplay, static_cast<ColorMode>(-1),
+        [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_PARAMETER, tmpError); });
+}
+
 /**
  * Test IComposerClient::setColorMode_2_2.
  */
@@ -393,6 +664,37 @@
             mComposerClient->setColorMode(mPrimaryDisplay, mode, intent);
         }
     }
+
+    mComposerClient->setColorMode(mPrimaryDisplay, ColorMode::NATIVE, RenderIntent::COLORIMETRIC);
+}
+
+/*
+ * Test IComposerClient::setColorMode_2_2
+ *
+ * Test that IComposerClient::setColorMode_2_2 returns an Error::BAD_DISPLAY
+ * when passed an invalid display handle
+ */
+TEST_F(GraphicsComposerHidlTest, SetColorMode_2_2BadDisplay) {
+    Error error = mComposerClient->getRaw()->setColorMode_2_2(mInvalidDisplayId, ColorMode::NATIVE,
+                                                              RenderIntent::COLORIMETRIC);
+
+    ASSERT_EQ(Error::BAD_DISPLAY, error);
+}
+
+/*
+ * Test IComposerClient::setColorMode_2_2
+ *
+ * Test that IComposerClient::setColorMode_2_2 returns Error::BAD_PARAMETER when
+ * passed an invalid Color mode or an invalid render intent
+ */
+TEST_F(GraphicsComposerHidlTest, SetColorMode_2_2BadParameter) {
+    Error colorModeError = mComposerClient->getRaw()->setColorMode_2_2(
+        mPrimaryDisplay, static_cast<ColorMode>(-1), RenderIntent::COLORIMETRIC);
+    EXPECT_EQ(Error::BAD_PARAMETER, colorModeError);
+
+    Error renderIntentError = mComposerClient->getRaw()->setColorMode_2_2(
+        mPrimaryDisplay, ColorMode::NATIVE, static_cast<RenderIntent>(-1));
+    EXPECT_EQ(Error::BAD_PARAMETER, renderIntentError);
 }
 
 }  // namespace
diff --git a/graphics/composer/2.3/Android.bp b/graphics/composer/2.3/Android.bp
index 23061dd..78da099 100644
--- a/graphics/composer/2.3/Android.bp
+++ b/graphics/composer/2.3/Android.bp
@@ -12,6 +12,7 @@
     ],
     interfaces: [
         "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.common@1.1",
         "android.hardware.graphics.composer@2.1",
         "android.hardware.graphics.composer@2.2",
         "android.hidl.base@1.0",
diff --git a/graphics/composer/2.3/IComposerClient.hal b/graphics/composer/2.3/IComposerClient.hal
index 77dd3ee..089438e 100644
--- a/graphics/composer/2.3/IComposerClient.hal
+++ b/graphics/composer/2.3/IComposerClient.hal
@@ -16,12 +16,58 @@
 
 package android.hardware.graphics.composer@2.3;
 
+import android.hardware.graphics.composer@2.1::IComposerClient.Command;
 import @2.2::IComposerClient;
 import @2.1::Display;
 import @2.1::Error;
 
 interface IComposerClient extends @2.2::IComposerClient {
 
+    enum Command : @2.2::IComposerClient.Command {
+        /**
+         * SET_LAYER_COLOR_TRANSFORM has this pseudo prototype
+         *
+         *   setLayerColorTransform(float[16] matrix);
+         *
+         * This command has the following binary layout in bytes:
+         *
+         *     0 - 16 * 4: matrix
+         *
+         * Sets a matrix for color transform which will be applied on this layer
+         * before composition.
+         *
+         * If the device is not capable of apply the matrix on this layer, it must force
+         * this layer to client composition during VALIDATE_DISPLAY.
+         *
+         * The matrix provided is an affine color transformation of the following
+         * form:
+         *
+         * |r.r r.g r.b 0|
+         * |g.r g.g g.b 0|
+         * |b.r b.g b.b 0|
+         * |Tr  Tg  Tb  1|
+         *
+         * This matrix must be provided in row-major form:
+         *
+         * {r.r, r.g, r.b, 0, g.r, ...}.
+         *
+         * Given a matrix of this form and an input color [R_in, G_in, B_in],
+         * the input color must first be converted to linear space
+         * [R_linear, G_linear, B_linear], then the output linear color
+         * [R_out_linear, G_out_linear, B_out_linear] will be:
+         *
+         * R_out_linear = R_linear * r.r + G_linear * g.r + B_linear * b.r + Tr
+         * G_out_linear = R_linear * r.g + G_linear * g.g + B_linear * b.g + Tg
+         * B_out_linear = R_linear * r.b + G_linear * g.b + B_linear * b.b + Tb
+         *
+         * [R_out_linear, G_out_linear, B_out_linear] must then be converted to
+         * gamma space: [R_out, G_out, B_out] before blending.
+         *
+         * @param matrix is a 4x4 transform matrix (16 floats) as described above.
+         */
+        SET_LAYER_COLOR_TRANSFORM = 0x40d << @2.1::IComposerClient.Command:OPCODE_SHIFT,
+    };
+
     /**
      * Returns the port and data that describe a physical display. The port is
      * a unique number that identifies a physical connector (e.g. eDP, HDMI)
@@ -42,4 +88,29 @@
                           uint8_t port,
                           vec<uint8_t> data);
 
+    /**
+     * Executes commands from the input command message queue. Return values
+     * generated by the input commands are written to the output command
+     * message queue in the form of value commands.
+     *
+     * @param inLength is the length of input commands.
+     * @param inHandles is an array of handles referenced by the input
+     *        commands.
+     * @return error is NONE upon success. Otherwise,
+     *         BAD_PARAMETER when inLength is not equal to the length of
+     *                       commands in the input command message queue.
+     *         NO_RESOURCES when the output command message queue was not
+     *                      properly drained.
+     * @param outQueueChanged indicates whether the output command message
+     *        queue has changed.
+     * @param outLength is the length of output commands.
+     * @param outHandles is an array of handles referenced by the output
+     *        commands.
+     */
+    executeCommands_2_3(uint32_t inLength,
+                        vec<handle> inHandles)
+             generates (Error error,
+                        bool outQueueChanged,
+                        uint32_t outLength,
+                        vec<handle> outHandles);
 };
diff --git a/graphics/composer/2.3/utils/command-buffer/Android.bp b/graphics/composer/2.3/utils/command-buffer/Android.bp
new file mode 100644
index 0000000..c48fe7a
--- /dev/null
+++ b/graphics/composer/2.3/utils/command-buffer/Android.bp
@@ -0,0 +1,15 @@
+cc_library_headers {
+    name: "android.hardware.graphics.composer@2.3-command-buffer",
+    defaults: ["hidl_defaults"],
+    vendor_available: true,
+    shared_libs: [
+        "android.hardware.graphics.composer@2.1",
+        "android.hardware.graphics.composer@2.2",
+        "android.hardware.graphics.composer@2.3",
+    ],
+    header_libs: [
+        "android.hardware.graphics.composer@2.1-command-buffer",
+        "android.hardware.graphics.composer@2.2-command-buffer",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h b/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h
new file mode 100644
index 0000000..3f7b2c9
--- /dev/null
+++ b/graphics/composer/2.3/utils/command-buffer/include/composer-command-buffer/2.3/ComposerCommandBuffer.h
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warn "ComposerCommandBuffer.h included without LOG_TAG"
+#endif
+
+#undef LOG_NDEBUG
+#define LOG_NDEBUG 0
+
+#include <android/hardware/graphics/composer/2.3/IComposer.h>
+#include <android/hardware/graphics/composer/2.3/IComposerClient.h>
+#include <composer-command-buffer/2.2/ComposerCommandBuffer.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+
+using android::hardware::MessageQueue;
+using android::hardware::graphics::composer::V2_1::Error;
+using android::hardware::graphics::composer::V2_1::IComposerCallback;
+using android::hardware::graphics::composer::V2_1::Layer;
+using android::hardware::graphics::composer::V2_3::IComposerClient;
+
+// This class helps build a command queue.  Note that all sizes/lengths are in
+// units of uint32_t's.
+class CommandWriterBase : public V2_2::CommandWriterBase {
+   public:
+    CommandWriterBase(uint32_t initialMaxSize) : V2_2::CommandWriterBase(initialMaxSize) {}
+
+    static constexpr uint16_t kSetLayerColorTransformLength = 16;
+    void setLayerColorTransform(const float* matrix) {
+        beginCommand_2_3(IComposerClient::Command::SET_LAYER_COLOR_TRANSFORM,
+                         kSetLayerColorTransformLength);
+        for (int i = 0; i < 16; i++) {
+            writeFloat(matrix[i]);
+        }
+        endCommand();
+    }
+
+   protected:
+    void beginCommand_2_3(IComposerClient::Command command, uint16_t length) {
+        V2_2::CommandWriterBase::beginCommand_2_2(
+            static_cast<V2_2::IComposerClient::Command>(static_cast<int32_t>(command)), length);
+    }
+};
+
+// This class helps parse a command queue.  Note that all sizes/lengths are in
+// units of uint32_t's.
+class CommandReaderBase : public V2_2::CommandReaderBase {
+   public:
+    CommandReaderBase() : V2_2::CommandReaderBase(){};
+};
+
+}  // namespace V2_3
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.3/utils/hal/Android.bp b/graphics/composer/2.3/utils/hal/Android.bp
index aa46df1..3ee9300 100644
--- a/graphics/composer/2.3/utils/hal/Android.bp
+++ b/graphics/composer/2.3/utils/hal/Android.bp
@@ -26,9 +26,11 @@
     ],
     header_libs: [
         "android.hardware.graphics.composer@2.2-hal",
+        "android.hardware.graphics.composer@2.3-command-buffer",
     ],
     export_header_lib_headers: [
         "android.hardware.graphics.composer@2.2-hal",
+        "android.hardware.graphics.composer@2.3-command-buffer",
     ],
     export_include_dirs: ["include"],
 }
diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
index e717d84..c805472 100644
--- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerClient.h
@@ -22,6 +22,7 @@
 
 #include <android/hardware/graphics/composer/2.3/IComposerClient.h>
 #include <composer-hal/2.3/ComposerClient.h>
+#include <composer-hal/2.3/ComposerCommandEngine.h>
 #include <composer-hal/2.3/ComposerHal.h>
 
 namespace android {
@@ -55,10 +56,27 @@
         return Void();
     }
 
+    Return<void> executeCommands_2_3(uint32_t inLength, const hidl_vec<hidl_handle>& inHandles,
+                                     IComposerClient::executeCommands_2_2_cb hidl_cb) override {
+        std::lock_guard<std::mutex> lock(mCommandEngineMutex);
+        bool outChanged = false;
+        uint32_t outLength = 0;
+        hidl_vec<hidl_handle> outHandles;
+        Error error =
+            mCommandEngine->execute(inLength, inHandles, &outChanged, &outLength, &outHandles);
+
+        hidl_cb(error, outChanged, outLength, outHandles);
+
+        mCommandEngine->reset();
+
+        return Void();
+    }
+
    private:
     using BaseType2_2 = V2_2::hal::detail::ComposerClientImpl<Interface, Hal>;
     using BaseType2_1 = V2_1::hal::detail::ComposerClientImpl<Interface, Hal>;
-
+    using BaseType2_1::mCommandEngine;
+    using BaseType2_1::mCommandEngineMutex;
     using BaseType2_1::mHal;
 };
 
diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerCommandEngine.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerCommandEngine.h
new file mode 100644
index 0000000..c3dcbcd
--- /dev/null
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerCommandEngine.h
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#ifndef LOG_TAG
+#warning "ComposerCommandEngine.h included without LOG_TAG"
+#endif
+
+#include <composer-command-buffer/2.3/ComposerCommandBuffer.h>
+#include <composer-hal/2.1/ComposerCommandEngine.h>
+#include <composer-hal/2.2/ComposerCommandEngine.h>
+#include <composer-hal/2.2/ComposerResources.h>
+#include <composer-hal/2.3/ComposerHal.h>
+
+namespace android {
+namespace hardware {
+namespace graphics {
+namespace composer {
+namespace V2_3 {
+namespace hal {
+
+class ComposerCommandEngine : public V2_2::hal::ComposerCommandEngine {
+   public:
+    ComposerCommandEngine(ComposerHal* hal, V2_2::hal::ComposerResources* resources)
+        : BaseType2_2(hal, resources), mHal(hal) {}
+
+   protected:
+    bool executeCommand(V2_1::IComposerClient::Command command, uint16_t length) override {
+        switch (static_cast<IComposerClient::Command>(command)) {
+            case IComposerClient::Command::SET_LAYER_COLOR_TRANSFORM:
+                return executeSetLayerColorTransform(length);
+            default:
+                return BaseType2_2::executeCommand(command, length);
+        }
+    }
+
+    bool executeSetLayerColorTransform(uint16_t length) {
+        if (length != CommandWriterBase::kSetLayerColorTransformLength) {
+            return false;
+        }
+
+        float matrix[16];
+        for (int i = 0; i < 16; i++) {
+            matrix[i] = readFloat();
+        }
+        auto err = mHal->setLayerColorTransform(mCurrentDisplay, mCurrentLayer, matrix);
+        if (err != Error::NONE) {
+            mWriter.setError(getCommandLoc(), err);
+        }
+
+        return true;
+    }
+
+   private:
+    using BaseType2_1 = V2_1::hal::ComposerCommandEngine;
+    using BaseType2_1::mWriter;
+    using BaseType2_2 = V2_2::hal::ComposerCommandEngine;
+
+    ComposerHal* mHal;
+};
+
+}  // namespace hal
+}  // namespace V2_3
+}  // namespace composer
+}  // namespace graphics
+}  // namespace hardware
+}  // namespace android
diff --git a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
index 37ea0a3..0f6205a 100644
--- a/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
+++ b/graphics/composer/2.3/utils/hal/include/composer-hal/2.3/ComposerHal.h
@@ -27,11 +27,13 @@
 
 using V2_1::Display;
 using V2_1::Error;
+using V2_1::Layer;
 
 class ComposerHal : public V2_2::hal::ComposerHal {
    public:
     virtual Error getDisplayIdentificationData(Display display, uint8_t* outPort,
                                                std::vector<uint8_t>* outData) = 0;
+    virtual Error setLayerColorTransform(Display display, Layer layer, const float* matrix) = 0;
 };
 
 }  // namespace hal
diff --git a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
index 53f2d1b..ed1878b 100644
--- a/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
+++ b/graphics/composer/2.3/utils/passthrough/include/composer-passthrough/2.3/HwcHal.h
@@ -66,6 +66,14 @@
         return Error::NONE;
     }
 
+    Error setLayerColorTransform(Display display, Layer layer, const float* matrix) override {
+        if (!mDispatch.setLayerColorTransform) {
+            return Error::UNSUPPORTED;
+        }
+        int32_t err = mDispatch.setLayerColorTransform(mDevice, display, layer, matrix);
+        return static_cast<Error>(err);
+    }
+
    protected:
     bool initDispatch() override {
         if (!BaseType2_2::initDispatch()) {
@@ -74,12 +82,15 @@
 
         this->initOptionalDispatch(HWC2_FUNCTION_GET_DISPLAY_IDENTIFICATION_DATA,
                                    &mDispatch.getDisplayIdentificationData);
+        this->initOptionalDispatch(HWC2_FUNCTION_SET_LAYER_COLOR_TRANSFORM,
+                                   &mDispatch.setLayerColorTransform);
         return true;
     }
 
    private:
     struct {
         HWC2_PFN_GET_DISPLAY_IDENTIFICATION_DATA getDisplayIdentificationData;
+        HWC2_PFN_SET_LAYER_COLOR_TRANSFORM setLayerColorTransform;
     } mDispatch = {};
 
     using BaseType2_2 = V2_2::passthrough::detail::HwcHalImpl<Hal>;
diff --git a/graphics/composer/2.3/utils/vts/Android.bp b/graphics/composer/2.3/utils/vts/Android.bp
index 0553258..19438cb 100644
--- a/graphics/composer/2.3/utils/vts/Android.bp
+++ b/graphics/composer/2.3/utils/vts/Android.bp
@@ -31,6 +31,7 @@
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
         "android.hardware.graphics.composer@2.2-command-buffer",
+        "android.hardware.graphics.composer@2.3-command-buffer",
     ],
     cflags: [
         "-O0",
diff --git a/graphics/composer/2.3/vts/functional/Android.bp b/graphics/composer/2.3/vts/functional/Android.bp
index df696c9..7548cb5 100644
--- a/graphics/composer/2.3/vts/functional/Android.bp
+++ b/graphics/composer/2.3/vts/functional/Android.bp
@@ -40,5 +40,6 @@
     header_libs: [
         "android.hardware.graphics.composer@2.1-command-buffer",
         "android.hardware.graphics.composer@2.2-command-buffer",
+        "android.hardware.graphics.composer@2.3-command-buffer",
     ],
 }
diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
index f4e34f0..1030ddc 100644
--- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
+++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
@@ -20,7 +20,9 @@
 
 #include <VtsHalHidlTargetTestBase.h>
 #include <android-base/logging.h>
+#include <composer-command-buffer/2.3/ComposerCommandBuffer.h>
 #include <composer-vts/2.1/GraphicsComposerCallback.h>
+#include <composer-vts/2.1/TestCommandReader.h>
 #include <composer-vts/2.3/ComposerVts.h>
 
 namespace android {
@@ -65,6 +67,9 @@
         // explicitly disable vsync
         mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
         mComposerCallback->setVsyncAllowed(false);
+
+        mWriter = std::make_unique<CommandWriterBase>(1024);
+        mReader = std::make_unique<V2_1::vts::TestCommandReader>();
     }
 
     void TearDown() override {
@@ -75,11 +80,18 @@
         }
     }
 
+    void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
+
+    // use the slot count usually set by SF
+    static constexpr uint32_t kBufferSlotCount = 64;
+
     std::unique_ptr<Composer> mComposer;
     std::unique_ptr<ComposerClient> mComposerClient;
     sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
     // the first display and is assumed never to be removed
     Display mPrimaryDisplay;
+    std::unique_ptr<CommandWriterBase> mWriter;
+    std::unique_ptr<V2_1::vts::TestCommandReader> mReader;
 
    private:
     Display waitForFirstDisplay() {
@@ -115,6 +127,31 @@
     }
 }
 
+/**
+ * Test IComposerClient::Command::SET_LAYER_COLOR_TRANSFORM.
+ * TODO Add color to the layer, use matrix to keep only red component,
+ * and check.
+ */
+TEST_F(GraphicsComposerHidlTest, SetLayerColorTransform) {
+    Layer layer;
+    ASSERT_NO_FATAL_FAILURE(layer =
+                                mComposerClient->createLayer(mPrimaryDisplay, kBufferSlotCount));
+    mWriter->selectDisplay(mPrimaryDisplay);
+    mWriter->selectLayer(layer);
+
+    // clang-format off
+    const std::array<float, 16> matrix = {{
+        1.0f, 0.0f, 0.0f, 0.0f,
+        0.0f, 1.0f, 0.0f, 0.0f,
+        0.0f, 0.0f, 1.0f, 0.0f,
+        0.0f, 0.0f, 0.0f, 1.0f,
+    }};
+    // clang-format on
+
+    mWriter->setLayerColorTransform(matrix.data());
+    execute();
+}
+
 }  // namespace
 }  // namespace vts
 }  // namespace V2_3
diff --git a/health/2.0/default/Health.cpp b/health/2.0/default/Health.cpp
index 6d3be99..a2b81d1 100644
--- a/health/2.0/default/Health.cpp
+++ b/health/2.0/default/Health.cpp
@@ -46,7 +46,7 @@
     }
 
     {
-        std::lock_guard<std::mutex> _lock(callbacks_lock_);
+        std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
         callbacks_.push_back(callback);
         // unlock
     }
@@ -58,14 +58,14 @@
         // ignore the error
     }
 
-    return update();
+    return updateAndNotify(callback);
 }
 
 bool Health::unregisterCallbackInternal(const sp<IBase>& callback) {
     if (callback == nullptr) return false;
 
     bool removed = false;
-    std::lock_guard<std::mutex> _lock(callbacks_lock_);
+    std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
     for (auto it = callbacks_.begin(); it != callbacks_.end();) {
         if (interfacesEqual(*it, callback)) {
             it = callbacks_.erase(it);
@@ -142,7 +142,7 @@
 Return<Result> Health::update() {
     if (!healthd_mode_ops || !healthd_mode_ops->battery_update) {
         LOG(WARNING) << "health@2.0: update: not initialized. "
-                     << "update() should not be called in charger / recovery.";
+                     << "update() should not be called in charger";
         return Result::UNKNOWN;
     }
 
@@ -156,6 +156,18 @@
     return Result::SUCCESS;
 }
 
+Return<Result> Health::updateAndNotify(const sp<IHealthInfoCallback>& callback) {
+    std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
+    std::vector<sp<IHealthInfoCallback>> storedCallbacks{std::move(callbacks_)};
+    callbacks_.clear();
+    if (callback != nullptr) {
+        callbacks_.push_back(callback);
+    }
+    Return<Result> result = update();
+    callbacks_ = std::move(storedCallbacks);
+    return result;
+}
+
 void Health::notifyListeners(HealthInfo* healthInfo) {
     std::vector<StorageInfo> info;
     get_storage_info(info);
@@ -175,7 +187,7 @@
     healthInfo->diskStats = stats;
     healthInfo->storageInfos = info;
 
-    std::lock_guard<std::mutex> _lock(callbacks_lock_);
+    std::lock_guard<decltype(callbacks_lock_)> lock(callbacks_lock_);
     for (auto it = callbacks_.begin(); it != callbacks_.end();) {
         auto ret = (*it)->healthInfoChanged(*healthInfo);
         if (!ret.isOk() && ret.isDeadObject()) {
@@ -233,7 +245,7 @@
 Return<void> Health::getHealthInfo(getHealthInfo_cb _hidl_cb) {
     using android::hardware::health::V1_0::hal_conversion::convertToHealthInfo;
 
-    update();
+    updateAndNotify(nullptr);
     struct android::BatteryProperties p = getBatteryProperties(battery_monitor_.get());
 
     V1_0::HealthInfo batteryInfo;
diff --git a/health/2.0/default/HealthImplDefault.cpp b/health/2.0/default/HealthImplDefault.cpp
index 15346bf..e3cbefd 100644
--- a/health/2.0/default/HealthImplDefault.cpp
+++ b/health/2.0/default/HealthImplDefault.cpp
@@ -46,9 +46,32 @@
     return 0;
 }
 
+void healthd_mode_default_impl_init(struct healthd_config*) {
+    // noop
+}
+
+int healthd_mode_default_impl_preparetowait(void) {
+    return -1;
+}
+
+void healthd_mode_default_impl_heartbeat(void) {
+    // noop
+}
+
+void healthd_mode_default_impl_battery_update(struct android::BatteryProperties*) {
+    // noop
+}
+
+static struct healthd_mode_ops healthd_mode_default_impl_ops = {
+    .init = healthd_mode_default_impl_init,
+    .preparetowait = healthd_mode_default_impl_preparetowait,
+    .heartbeat = healthd_mode_default_impl_heartbeat,
+    .battery_update = healthd_mode_default_impl_battery_update,
+};
+
 extern "C" IHealth* HIDL_FETCH_IHealth(const char* name) {
     const static std::string providedInstance{"backup"};
-
+    healthd_mode_ops = &healthd_mode_default_impl_ops;
     if (providedInstance == name) {
         // use defaults
         // Health class stores static instance
diff --git a/health/2.0/default/include/health2/Health.h b/health/2.0/default/include/health2/Health.h
index 134cdc6..6410474 100644
--- a/health/2.0/default/include/health2/Health.h
+++ b/health/2.0/default/include/health2/Health.h
@@ -31,12 +31,10 @@
     // Should only be called by implementation itself (-impl, -service).
     // Clients should not call this function. Instead, initInstance() initializes and returns the
     // global instance that has fewer functions.
-    // TODO(b/62229583): clean up and hide these functions after update() logic is simplified.
     static sp<Health> getImplementation();
 
     Health(struct healthd_config* c);
 
-    // TODO(b/62229583): clean up and hide these functions after update() logic is simplified.
     void notifyListeners(HealthInfo* info);
 
     // Methods from IHealth follow.
@@ -61,11 +59,15 @@
    private:
     static sp<Health> instance_;
 
-    std::mutex callbacks_lock_;
+    std::recursive_mutex callbacks_lock_;
     std::vector<sp<IHealthInfoCallback>> callbacks_;
     std::unique_ptr<BatteryMonitor> battery_monitor_;
 
     bool unregisterCallbackInternal(const sp<IBase>& cb);
+
+    // update() and only notify the given callback, but none of the other callbacks.
+    // If cb is null, do not notify any callback at all.
+    Return<Result> updateAndNotify(const sp<IHealthInfoCallback>& cb);
 };
 
 }  // namespace implementation
diff --git a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
index bba4661..f895aec 100644
--- a/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
+++ b/health/2.0/vts/functional/VtsHalHealthV2_0TargetTest.cpp
@@ -222,38 +222,83 @@
 }
 
 /*
- * Tests the values returned by getChargeCounter(),
- * getCurrentNow(), getCurrentAverage(), getCapacity(), getEnergyCounter(),
- * getChargeStatus(), getStorageInfo(), getDiskStats() and getHealthInfo() from
- * interface IHealth.
+ * Tests the values returned by getChargeCounter() from interface IHealth.
  */
-TEST_F(HealthHidlTest, Properties) {
+TEST_F(HealthHidlTest, getChargeCounter) {
     EXPECT_OK(mHealth->getChargeCounter([](auto result, auto value) {
         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value > 0);
     }));
+}
+
+/*
+ * Tests the values returned by getCurrentNow() from interface IHealth.
+ */
+TEST_F(HealthHidlTest, getCurrentNow) {
     EXPECT_OK(mHealth->getCurrentNow([](auto result, auto value) {
         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
     }));
+}
+
+/*
+ * Tests the values returned by getCurrentAverage() from interface IHealth.
+ */
+TEST_F(HealthHidlTest, getCurrentAverage) {
     EXPECT_OK(mHealth->getCurrentAverage([](auto result, auto value) {
         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT32_MIN);
     }));
+}
+
+/*
+ * Tests the values returned by getCapacity() from interface IHealth.
+ */
+TEST_F(HealthHidlTest, getCapacity) {
     EXPECT_OK(mHealth->getCapacity([](auto result, auto value) {
         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), 0 <= value && value <= 100);
     }));
+}
+
+/*
+ * Tests the values returned by getEnergyCounter() from interface IHealth.
+ */
+TEST_F(HealthHidlTest, getEnergyCounter) {
     EXPECT_OK(mHealth->getEnergyCounter([](auto result, auto value) {
         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, std::to_string(value), value != INT64_MIN);
     }));
+}
+
+/*
+ * Tests the values returned by getChargeStatus() from interface IHealth.
+ */
+TEST_F(HealthHidlTest, getChargeStatus) {
     EXPECT_OK(mHealth->getChargeStatus([](auto result, auto value) {
         EXPECT_VALID_OR_UNSUPPORTED_PROP(
             result, toString(value),
             value != BatteryStatus::UNKNOWN && verifyEnum<BatteryStatus>(value));
     }));
+}
+
+/*
+ * Tests the values returned by getStorageInfo() from interface IHealth.
+ */
+TEST_F(HealthHidlTest, getStorageInfo) {
     EXPECT_OK(mHealth->getStorageInfo([](auto result, auto& value) {
         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyStorageInfo(value));
     }));
+}
+
+/*
+ * Tests the values returned by getDiskStats() from interface IHealth.
+ */
+TEST_F(HealthHidlTest, getDiskStats) {
     EXPECT_OK(mHealth->getDiskStats([](auto result, auto& value) {
         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), true);
     }));
+}
+
+/*
+ * Tests the values returned by getHealthInfo() from interface IHealth.
+ */
+TEST_F(HealthHidlTest, getHealthInfo) {
     EXPECT_OK(mHealth->getHealthInfo([](auto result, auto& value) {
         EXPECT_VALID_OR_UNSUPPORTED_PROP(result, toString(value), verifyHealthInfo(value));
     }));
diff --git a/health/filesystem/1.0/Android.bp b/health/storage/1.0/Android.bp
similarity index 72%
rename from health/filesystem/1.0/Android.bp
rename to health/storage/1.0/Android.bp
index 74b9bc3..35ee34f 100644
--- a/health/filesystem/1.0/Android.bp
+++ b/health/storage/1.0/Android.bp
@@ -1,14 +1,15 @@
 // This file is autogenerated by hidl-gen -Landroidbp.
 
 hidl_interface {
-    name: "android.hardware.health.filesystem@1.0",
+    name: "android.hardware.health.storage@1.0",
     root: "android.hardware",
     vndk: {
         enabled: true,
     },
     srcs: [
         "types.hal",
-        "IFileSystem.hal",
+        "IGarbageCollectCallback.hal",
+        "IStorage.hal",
     ],
     interfaces: [
         "android.hidl.base@1.0",
diff --git a/health/filesystem/1.0/IFileSystem.hal b/health/storage/1.0/IGarbageCollectCallback.hal
similarity index 63%
rename from health/filesystem/1.0/IFileSystem.hal
rename to health/storage/1.0/IGarbageCollectCallback.hal
index 33ea3ff..2c24ead 100644
--- a/health/filesystem/1.0/IFileSystem.hal
+++ b/health/storage/1.0/IGarbageCollectCallback.hal
@@ -13,21 +13,18 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-
-package android.hardware.health.filesystem@1.0;
+package android.hardware.health.storage@1.0;
 
 /**
- * IFileSystem is an interface that provides operations on underlying storage
- * devices, including flash memory.
+ * Callback interface to IStorage.garbageCollect.
  */
-interface IFileSystem {
+interface IGarbageCollectCallback {
     /**
-     * Start garbage collection on the driver of storage devices. This function
-     * must be called at regular intervals when it is a good time for a
-     * longer-running cleanup tasks.
+     * 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.
      */
-    garbageCollect() generates (Result result);
+    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/filesystem/1.0/types.hal b/health/storage/1.0/types.hal
similarity index 88%
rename from health/filesystem/1.0/types.hal
rename to health/storage/1.0/types.hal
index 00431f7..2da0871 100644
--- a/health/filesystem/1.0/types.hal
+++ b/health/storage/1.0/types.hal
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.hardware.health.filesystem@1.0;
+package android.hardware.health.storage@1.0;
 
 /**
  * Status values for HAL methods.
@@ -25,10 +25,6 @@
      */
     SUCCESS = 0,
     /**
-     * Execution of the method timed out.
-     */
-    TIMEOUT,
-    /**
      * An IO error is encountered when the HAL communicates with the device.
      */
     IO_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/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..193e4ea 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/authorization_set.h
@@ -46,7 +46,7 @@
     AuthorizationSet(const AuthorizationSet& other) : data_(other.data_) {}
 
     // Move constructor.
-    AuthorizationSet(AuthorizationSet&& other) : data_(std::move(other.data_)) {}
+    AuthorizationSet(AuthorizationSet&& other) noexcept : data_(std::move(other.data_)) {}
 
     // Constructor from hidl_vec<KeyParameter>
     AuthorizationSet(const hidl_vec<KeyParameter>& other) { *this = other; }
@@ -58,7 +58,7 @@
     }
 
     // Move assignment.
-    AuthorizationSet& operator=(AuthorizationSet&& other) {
+    AuthorizationSet& operator=(AuthorizationSet&& other) noexcept {
         data_ = std::move(other.data_);
         return *this;
     }
@@ -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 6ed61da..995ae4f 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
@@ -672,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 89bcca6..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)
diff --git a/media/bufferpool/2.0/Android.bp b/media/bufferpool/2.0/Android.bp
index 405990e..1f8bbdb 100644
--- a/media/bufferpool/2.0/Android.bp
+++ b/media/bufferpool/2.0/Android.bp
@@ -11,12 +11,14 @@
         "IAccessor.hal",
         "IClientManager.hal",
         "IConnection.hal",
+        "IObserver.hal",
     ],
     interfaces: [
         "android.hidl.base@1.0",
     ],
     types: [
         "Buffer",
+        "BufferInvalidationMessage",
         "BufferStatus",
         "BufferStatusMessage",
         "ResultStatus",
diff --git a/media/bufferpool/2.0/IAccessor.hal b/media/bufferpool/2.0/IAccessor.hal
index 07ea99d..66707fe 100644
--- a/media/bufferpool/2.0/IAccessor.hal
+++ b/media/bufferpool/2.0/IAccessor.hal
@@ -17,6 +17,7 @@
 package android.hardware.media.bufferpool@2.0;
 
 import IConnection;
+import IObserver;
 /**
  * IAccessor creates IConnection which is used from IClientManager in order to
  * use functionality of the specified buffer pool.
@@ -49,6 +50,13 @@
      * made and kept private. Also part of transaction ID is a sender ID in
      * order to prevent fake transactions from other clients. This must be
      * verified with an FMQ message from a buffer pool.
+
+     * @param observer The buffer pool event observer from the client.
+     *     Observer is provided to ensure FMQ messages are processed even when
+     *     client processes are idle. Buffer invalidation caused by
+     *     reconfiguration does not call observer. Buffer invalidation caused
+     *     by termination of pipeline call observer in order to ensure
+     *     invalidation is done after pipeline completion.
      *
      * @return status The status of the call.
      *     OK               - A connection is made successfully.
@@ -59,10 +67,14 @@
      *     to get shared buffers from the buffer pool.
      * @return connectionId Id of IConnection. The Id identifies
      *     sender and receiver in FMQ messages during buffer transfer.
-     * @return mqDesc FMQ descriptor. The descriptor can be used to
-     *     send/receive FMQ messages.
+     * @return toFmqDesc FMQ descriptor. The descriptor is used to
+     *     post buffer status messages.
+     * @return fromFmqDesc FMQ descriptor. The descriptor is used to
+     *     receive buffer invalidation messages from the buffer pool.
      */
-    connect()
+    connect(IObserver observer)
         generates (ResultStatus status, IConnection connection,
-                   int64_t connectionId, fmq_sync<BufferStatusMessage> mqDesc);
+                   int64_t connectionId,
+                   fmq_sync<BufferStatusMessage> toFmqDesc,
+                   fmq_unsync<BufferInvalidationMessage> fromFmqDesc);
 };
diff --git a/media/bufferpool/2.0/IObserver.hal b/media/bufferpool/2.0/IObserver.hal
new file mode 100644
index 0000000..a998836
--- /dev/null
+++ b/media/bufferpool/2.0/IObserver.hal
@@ -0,0 +1,34 @@
+/*
+ * 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.media.bufferpool@2.0;
+
+/**
+ * IObserver listens on notifications from the buffer pool. On receiving
+ * notifications, FMQ messages from the specific buffer pool which are already
+ * in the FMQ are processed.
+ */
+interface IObserver {
+
+    /**
+     * The specific buffer pool sent a message to the client. Calling this
+     * method from the buffer pool enforces a buffer pool client process the
+     * message.
+     *
+     * @param connectionId the connection Id of the specific buffer pool client
+     */
+    oneway onMessage(int64_t connectionId);
+};
diff --git a/media/bufferpool/2.0/types.hal b/media/bufferpool/2.0/types.hal
index d5b3937..597e7b3 100644
--- a/media/bufferpool/2.0/types.hal
+++ b/media/bufferpool/2.0/types.hal
@@ -65,6 +65,8 @@
     TRANSFER_OK         = 7,
     /** Buffer transaction failure. */
     TRANSFER_ERROR      = 8,
+    /** Buffer invalidation ack. */
+    INVALIDATION_ACK    = 9,
 };
 
 /**
@@ -91,3 +93,20 @@
      */
     int64_t timestampUs;
 };
+
+/*
+ * Buffer pool sends a buffer invalidation message to clients in order to
+ * ensure fast reclamation of the buffers. Clients must free the invalidated
+ * buffers as soon as possible upon receiving the message.
+ */
+struct BufferInvalidationMessage {
+    uint32_t messageId;
+    /**
+     * Buffers from fromBufferId to toBufferId must be invalidated.
+     * fromBufferId is inclusive, but toBufferId is not inclusive.
+     * If fromBufferId > toBufferID, wrap happens. In that case
+     * the wrap is based on UINT32_MAX.
+     */
+    uint32_t fromBufferId;
+    uint32_t toBufferId;
+};
diff --git a/neuralnetworks/1.0/types.hal b/neuralnetworks/1.0/types.hal
index 887fdf1..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,
 
@@ -598,6 +622,8 @@
      * Outputs:
      * * 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,
 
@@ -1284,6 +1340,8 @@
      * Outputs:
      * * 0: The output 4-D tensor, of shape [batches, height/block_size,
      *      width/block_size, depth_in*block_size*block_size].
+     *
+     * Available since API level 27.
      */
     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,
 
diff --git a/neuralnetworks/1.0/vts/OWNERS b/neuralnetworks/1.0/vts/OWNERS
index 87e322b..b5a8e1f 100644
--- a/neuralnetworks/1.0/vts/OWNERS
+++ b/neuralnetworks/1.0/vts/OWNERS
@@ -2,9 +2,14 @@
 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
+vddang@google.com
+xusongw@google.com
 
 # VTS team
 yim@google.com
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 0682ab9..b8046c7 100644
--- a/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
+++ b/neuralnetworks/1.0/vts/functional/GeneratedTestHarness.cpp
@@ -66,8 +66,8 @@
 // Top level driver for models and examples generated by test_generator.py
 // Test driver for those generated from ml/nn/runtime/test/spec
 void EvaluatePreparedModel(sp<IPreparedModel>& preparedModel, std::function<bool(int)> is_ignored,
-                           const std::vector<MixedTypedExampleType>& examples,
-                           float fpRange = 1e-5f) {
+                           const std::vector<MixedTypedExampleType>& examples, float fpAtol = 1e-5f,
+                           float fpRtol = 1e-5f) {
     const uint32_t INPUT = 0;
     const uint32_t OUTPUT = 1;
 
@@ -175,7 +175,7 @@
         MixedTyped filtered_test = filter(test, is_ignored);
 
         // We want "close-enough" results for float
-        compare(filtered_golden, filtered_test, fpRange);
+        compare(filtered_golden, filtered_test, fpAtol, fpRtol);
     }
 }
 
@@ -220,7 +220,8 @@
     EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
     ASSERT_NE(nullptr, preparedModel.get());
 
-    EvaluatePreparedModel(preparedModel, is_ignored, examples);
+    float fpAtol = 1e-5f, fpRtol = 5.0f * 1.1920928955078125e-7f;
+    EvaluatePreparedModel(preparedModel, is_ignored, examples, fpAtol, fpRtol);
 }
 
 void Execute(const sp<V1_1::IDevice>& device, std::function<V1_1::Model(void)> create_model,
@@ -265,9 +266,65 @@
     EXPECT_EQ(ErrorStatus::NONE, prepareReturnStatus);
     ASSERT_NE(nullptr, preparedModel.get());
 
-    // If in relaxed mode, set the error range to be 5ULP of FP16.
-    float fpRange = !model.relaxComputationFloat32toFloat16 ? 1e-5f : 5.0f * 0.0009765625f;
-    EvaluatePreparedModel(preparedModel, is_ignored, examples, fpRange);
+    // 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);
+}
+
+// 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
diff --git a/neuralnetworks/1.1/types.hal b/neuralnetworks/1.1/types.hal
index 7b2a21a..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,
 
@@ -150,6 +157,8 @@
      *      of the padding:
      *          output0.dimension[i] =
      *              padding[i, 0] + input0.dimension[i] + padding[i, 1]
+     *
+     * Available since API level 28.
      */
     PAD = 32,
 
@@ -185,6 +194,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *
+     * Available since API level 28.
      */
     SPACE_TO_BATCH_ND = 33,
 
@@ -214,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,
 
@@ -234,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,
 
@@ -294,6 +311,8 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *
+     * Available since API level 28.
      */
     SUB = 36,
 
@@ -319,8 +338,11 @@
      *
      * Outputs:
      * * 0: A tensor of the same {@link OperandType} as input0.
+     *
+     * Available since API level 28.
      */
     TRANSPOSE = 37,
+
 };
 
 /**
diff --git a/neuralnetworks/1.1/vts/OWNERS b/neuralnetworks/1.1/vts/OWNERS
index 87e322b..b5a8e1f 100644
--- a/neuralnetworks/1.1/vts/OWNERS
+++ b/neuralnetworks/1.1/vts/OWNERS
@@ -2,9 +2,14 @@
 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
+vddang@google.com
+xusongw@google.com
 
 # VTS team
 yim@google.com
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/VtsHalNeuralnetworks.h b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
index 0050e52..a64268f 100644
--- a/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
+++ b/neuralnetworks/1.1/vts/functional/VtsHalNeuralnetworks.h
@@ -34,9 +34,11 @@
 namespace neuralnetworks {
 namespace V1_1 {
 
-using V1_0::Request;
 using V1_0::DeviceStatus;
 using V1_0::ErrorStatus;
+using V1_0::Operand;
+using V1_0::OperandType;
+using V1_0::Request;
 
 namespace vts {
 namespace functional {
diff --git a/neuralnetworks/1.2/Android.bp b/neuralnetworks/1.2/Android.bp
new file mode 100644
index 0000000..5a661e0
--- /dev/null
+++ b/neuralnetworks/1.2/Android.bp
@@ -0,0 +1,27 @@
+// 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",
+        "Operand",
+        "OperandType",
+        "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..aff4cf3
--- /dev/null
+++ b/neuralnetworks/1.2/IDevice.hal
@@ -0,0 +1,136 @@
+/*
+ * 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 {
+    /**
+     * Get the version string of the driver implementation.
+     *
+     * The version string must be a unique token among the set of version strings of
+     * drivers of a specific device. The token identifies the device driver's
+     * implementation. The token must not be confused with the feature level which is solely
+     * defined by the interface version. This API is opaque to the Android framework, but the
+     * Android framework may use the information for debugging or to pass on to NNAPI applications.
+     *
+     * Application developers sometimes have specific requirements to ensure good user experiences,
+     * and they need more information to make intelligent decisions when the Android framework cannot.
+     * For example, combined with the device name and other information, the token can help
+     * NNAPI applications filter devices based on their needs:
+     *     - An application demands a certain level of performance, but a specific version of
+     *       the driver cannot meet that requirement because of a performance regression.
+     *       The application can blacklist the driver based on the version provided.
+     *     - An application has a minimum precision requirement, but certain versions of
+     *       the driver cannot meet that requirement because of bugs or certain optimizations.
+     *       The application can filter out versions of these drivers.
+     *
+     * @return status Error status returned from querying the version string. Must be:
+     *     - NONE if the query was successful
+     *     - DEVICE_UNAVAILABLE if driver is offline or busy
+     *     - GENERAL_FAILURE if the query resulted in an
+     *       unspecified error
+     * @return version The version string of the device implementation.
+     *     Must have nonzero length
+     */
+    getVersionString() generates (ErrorStatus status, string version);
+
+    /**
+     * 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..4a1e7a8
--- /dev/null
+++ b/neuralnetworks/1.2/types.hal
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.neuralnetworks@1.2;
+
+import @1.0::DataLocation;
+import @1.0::OperandLifeTime;
+import @1.0::OperandType;
+import @1.0::PerformanceInfo;
+import @1.1::OperationType;
+
+enum OperandType : @1.0::OperandType {
+    /**
+     * An 8 bit boolean scalar value.
+     *
+     * Values of this operand type are either true or false. A zero value
+     * represents false; any other value represents true.
+     */
+    BOOL = 6,
+    /**
+     * A tensor of 16 bit signed integers that represent real numbers.
+     *
+     * Attached to this tensor are two numbers that are used to convert the 16
+     * bit integer to the real value and vice versa. These two numbers are:
+     * - scale: a 32 bit floating point value greater than zero.
+     * - zeroPoint: a 32 bit integer, in range [-32768, 32767].
+     *
+     * The formula is:
+     * realValue = (integerValue - zeroPoint) * scale.
+     */
+    TENSOR_QUANT16_ASYMM = 7,
+    /** A tensor of 16 bit floating point values. */
+    TENSOR_FLOAT16 = 8,
+};
+
+/**
+ * Operation types.
+ *
+ * The type of an operation in a model.
+ */
+enum OperationType : @1.1::OperationType {
+    // TODO(b/116445845): Sync docs when all ops are implemented.
+    ARGMAX = 38,
+    ARGMIN = 39,
+    PAD_V2 = 40,
+    AXIS_ALIGNED_BBOX_TRANSFORM = 41,
+    BIDIRECTIONAL_SEQUENCE_LSTM = 42,
+    BIDIRECTIONAL_SEQUENCE_RNN = 43,
+    BOX_WITH_NMS_LIMIT = 44,
+    CAST = 45,
+    CHANNEL_SHUFFLE = 46,
+    DETECTION_OUTPUT = 47,
+    EMBEDDING_LOOKUP_SPARSE = 48,
+    EXP = 49,
+    EXPAND_DIMS = 50,
+    GATHER = 51,
+    GENERATE_PROPOSALS = 52,
+    GREATER = 53,
+    GREATER_EQUAL = 54,
+    GROUPED_CONV_2D = 55,
+    HEATMAP_MAX_KEYPOINT = 56,
+    LESS = 57,
+    LESS_EQUAL = 58,
+    LOG = 59,
+    LOGICAL_AND = 60,
+    LOGICAL_NOT = 61,
+    LOGICAL_OR = 62,
+    LOG_SOFTMAX = 63,
+    MAXIMUM = 64,
+    MINIMUM = 65,
+    NEG = 66,
+    POW = 67,
+    PRELU = 68,
+    PRIOR_BOX = 69,
+    QUANTIZE = 70,
+    QUANTIZED_16BIT_LSTM = 71,
+    RANDOM_MULTINOMIAL = 72,
+    REDUCE = 73,
+    ROI_ALIGN = 74,
+    RSQRT = 75,
+    SELECT = 76,
+    SIN = 77,
+    SLICE = 78,
+    SPARSE_TO_DENSE = 79,
+    SPLIT = 80,
+    SQRT = 81,
+    TILE = 82,
+    TOPK_V2 = 83,
+    TRANSPOSE_CONV_2D = 84,
+    UNIDIRECTIONAL_SEQUENCE_LSTM = 85,
+    UNIDIRECTIONAL_SEQUENCE_RNN = 86,
+    ROTATED_BBOX_TRANSFORM = 87,
+};
+
+/**
+ * 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;
+};
+
+/**
+ * Describes one operand of the model's graph.
+ */
+struct Operand {
+    /**
+     * Data type of the operand.
+     */
+    OperandType type;
+
+    /**
+     * Dimensions of the operand.
+     *
+     * For a scalar operand, dimensions.size() must be 0.
+     *
+     * For a tensor operand, dimensions.size() must be at least 1;
+     * however, any of the dimensions may be unspecified.
+     *
+     * A tensor operand with all dimensions specified has "fully
+     * specified" dimensions. Whenever possible (i.e., whenever the
+     * dimensions are known at model construction time), a tensor
+     * operand should have (but is not required to have) fully
+     * specified dimensions, in order to enable the best possible
+     * performance.
+     *
+     * If a tensor operand's dimensions are not fully specified, the
+     * dimensions of the operand are deduced from the operand
+     * dimensions and values of the operation for which that operand
+     * is an output.
+     *
+     * In the following situations, a tensor operand's dimensions must
+     * be fully specified:
+     *
+     *     . The operand has lifetime CONSTANT_COPY or
+     *       CONSTANT_REFERENCE.
+     *
+     *     . The operand has lifetime MODEL_INPUT or MODEL_OUTPUT. Fully
+     *       specified dimensions must either be present in the
+     *       Operand or they must be provided in the corresponding
+     *       RequestArgument.
+     *       EXCEPTION: If the input or output is optional and omitted
+     *       (by setting the hasNoValue field of the corresponding
+     *       RequestArgument to true) then it need not have fully
+     *       specified dimensions.
+     *
+     * A tensor operand with some number of unspecified dimensions is
+     * represented by setting each unspecified dimension to 0.
+     */
+    vec<uint32_t> dimensions;
+
+    /**
+     * The number of times this operand appears as an operation input.
+     *
+     * (For example, if this operand appears once in one operation's
+     * input list, and three times in another operation's input list,
+     * then numberOfConsumers = 4.)
+     */
+    uint32_t numberOfConsumers;
+
+    /**
+     * Quantized scale of the operand.
+     *
+     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM or
+     * TENSOR_INT32.
+     */
+    float scale;
+
+    /**
+     * Quantized zero-point offset of the operand.
+     *
+     * Only applicable if the operand is of type TENSOR_QUANT8_ASYMM.
+     */
+    int32_t zeroPoint;
+
+    /**
+     * How the operand is used.
+     */
+    OperandLifeTime lifetime;
+
+    /**
+     * Where to find the data for this operand.
+     * If the lifetime is TEMPORARY_VARIABLE, MODEL_INPUT, MODEL_OUTPUT, or
+     * NO_VALUE:
+     * - All the fields must be 0.
+     * If the lifetime is CONSTANT_COPY:
+     * - location.poolIndex is 0.
+     * - location.offset is the offset in bytes into Model.operandValues.
+     * - location.length is set.
+     * If the lifetime is CONSTANT_REFERENCE:
+     * - location.poolIndex is set.
+     * - location.offset is the offset in bytes into the specified pool.
+     * - location.length is set.
+     */
+    DataLocation location;
+};
+
+/**
+ * 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..b5a8e1f
--- /dev/null
+++ b/neuralnetworks/1.2/vts/OWNERS
@@ -0,0 +1,16 @@
+# 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
+vddang@google.com
+xusongw@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..eb3ebd3
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/BasicTests.cpp
@@ -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.
+ */
+
+#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));
+}
+
+// device version test
+TEST_F(NeuralnetworksHidlTest, GetDeviceVersionStringTest) {
+    Return<void> ret = device->getVersionString([](ErrorStatus status, const hidl_string& version) {
+        EXPECT_EQ(ErrorStatus::NONE, status);
+        EXPECT_LT(0, version.size());
+    });
+    EXPECT_TRUE(ret.isOk());
+}
+}  // 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..b840199
--- /dev/null
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -0,0 +1,548 @@
+/*
+ * 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::OperandLifeTime;
+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_QUANT16_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:
+        case OperandType::BOOL:
+            return 1;
+        case OperandType::TENSOR_FLOAT16:
+        case OperandType::TENSOR_FLOAT32:
+        case OperandType::TENSOR_INT32:
+        case OperandType::TENSOR_QUANT8_ASYMM:
+        case OperandType::TENSOR_QUANT16_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::BOOL:
+        case OperandType::TENSOR_FLOAT16:
+        case OperandType::TENSOR_FLOAT32:
+            return 1.0f;
+        case OperandType::TENSOR_INT32:
+            return -1.0f;
+        case OperandType::TENSOR_QUANT8_ASYMM:
+        case OperandType::TENSOR_QUANT16_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::BOOL:
+        case OperandType::TENSOR_FLOAT16:
+        case OperandType::TENSOR_FLOAT32:
+        case OperandType::TENSOR_INT32:
+            return {1};
+        case OperandType::TENSOR_QUANT8_ASYMM:
+        case OperandType::TENSOR_QUANT16_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:
+        case OperandType::BOOL:
+            newOperand.dimensions = hidl_vec<uint32_t>();
+            newOperand.scale = 0.0f;
+            newOperand.zeroPoint = 0;
+            break;
+        case OperandType::TENSOR_FLOAT16:
+        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:
+        case OperandType::TENSOR_QUANT16_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/health/filesystem/1.0/Android.bp b/power/stats/1.0/Android.bp
similarity index 63%
copy from health/filesystem/1.0/Android.bp
copy to power/stats/1.0/Android.bp
index 74b9bc3..2f16a21 100644
--- a/health/filesystem/1.0/Android.bp
+++ b/power/stats/1.0/Android.bp
@@ -1,21 +1,23 @@
 // This file is autogenerated by hidl-gen -Landroidbp.
 
 hidl_interface {
-    name: "android.hardware.health.filesystem@1.0",
+    name: "android.hardware.power.stats@1.0",
     root: "android.hardware",
     vndk: {
         enabled: true,
     },
     srcs: [
         "types.hal",
-        "IFileSystem.hal",
+        "IPowerStats.hal",
     ],
     interfaces: [
         "android.hidl.base@1.0",
     ],
     types: [
-        "Result",
+        "Status",
+        "RailInfo",
+        "EnergyData",
     ],
-    gen_java: true,
+    gen_java: false,
 }
 
diff --git a/power/stats/1.0/IPowerStats.hal b/power/stats/1.0/IPowerStats.hal
new file mode 100644
index 0000000..d75e170
--- /dev/null
+++ b/power/stats/1.0/IPowerStats.hal
@@ -0,0 +1,95 @@
+/*
+ * 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.power.stats@1.0;
+
+interface IPowerStats {
+
+    /**
+     * Rail information:
+     * Reports information related to the rails being monitored.
+     *
+     * @return rails Information about monitored rails.
+     * @return status SUCCESS on success or NOT_SUPPORTED if
+     *     feature is not enabled or FILESYSTEM_ERROR on filesystem nodes
+     *     access error.
+     */
+    getRailInfo()
+        generates(vec<RailInfo> rails, Status status);
+
+    /**
+     * Rail level energy measurements for low frequency clients:
+     * Reports accumulated energy since boot on each rail.
+     *
+     * @param railIndices Indices of rails for which data is required.
+     *     To get data for all rails pass an empty vector. Rail name to
+     *     index mapping can be queried from getRailInfo() API.
+     * @return data Energy values since boot for all requested rails.
+     * @return status SUCCESS on success or NOT_SUPPORTED if
+     *     feature is not enabled or FILESYSTEM_ERROR on filesystem nodes
+     *     access error.
+     */
+    getEnergyData(vec<uint32_t> railIndices)
+        generates(vec<EnergyData> data, Status status);
+
+    /**
+     * Stream rail level power measurements for high frequency clients:
+     * Streams accumulated energy since boot on each rail. This API is
+     * asynchronous.
+     *
+     * @param timeMs Time(in ms) for which energyData should be streamed
+     * @return mqDesc Unsynchronous Fast Message Queue descriptor - One
+     *     writer(power.stats HAL) multiple readers are supported. Reader
+     *     should read faster than writer otherwise data might be
+     *     overwritten. Data is present in following format in the queue:
+     *     +-----------------------+       <--
+     *     | EnergyData for rail 1 |         |
+     *     +-----------------------+         |
+     *     | EnergyData for rail 2 |         |
+     *     +-----------------------+         |
+     *     |          .            |         |-- 1st Sample
+     *     |          .            |         |
+     *     |          .            |         |
+     *     +-----------------------+         |
+     *     | EnergyData for rail n |         |
+     *     +-----------------------+       <--
+     *     |          .            |
+     *     |          .            |
+     *     |          .            |
+     *     +-----------------------+       <--
+     *     | EnergyData for rail 1 |         |
+     *     +-----------------------+         |
+     *     | EnergyData for rail 2 |         |
+     *     +-----------------------+         |
+     *     |          .            |         |-- kth Sample
+     *     |          .            |         |
+     *     |          .            |         |
+     *     +-----------------------+         |
+     *     | EnergyData for rail n |         |
+     *     +-----------------------+       <--
+     *
+     *     where,
+     *     n = railsPerSample
+     *     k = numSamples
+     *
+     * @return numSamples Number of samples which will be generated in timeMs.
+     * @return railsPerSample Number of rails measured per sample.
+     * @return status SUCCESS on success or FILESYSTEM_ERROR on filesystem
+     *     nodes access or NOT_SUPPORTED if feature is not enabled.
+     */
+    streamEnergyData(uint32_t timeMs)
+        generates(fmq_unsync<EnergyData> mqDesc, uint32_t numSamples,
+                uint32_t railsPerSample, Status status);
+};
diff --git a/power/stats/1.0/types.hal b/power/stats/1.0/types.hal
new file mode 100644
index 0000000..826c29b
--- /dev/null
+++ b/power/stats/1.0/types.hal
@@ -0,0 +1,46 @@
+/*
+ * 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.power.stats@1.0;
+
+enum Status : uint32_t {
+    SUCCESS = 0,
+    NOT_SUPPORTED = 1,
+    INVALID_INPUT = 2,
+    FILESYSTEM_ERROR = 3,
+};
+
+struct RailInfo {
+    /** Index corresponding to the rail */
+    uint32_t index;
+    /** Name of the rail */
+    string railName;
+    /** Name of the subsystem to which this rail belongs */
+    string subsysName;
+    /** Hardware sampling rate */
+    uint32_t samplingRate;
+};
+
+struct EnergyData {
+    /**
+     * Index corrensponding to the rail. This index matches
+     * the index returned in RailInfo
+     */
+    uint32_t index;
+    /** Time since device boot(CLOCK_BOOTTIME) in milli-seconds */
+    uint64_t timestamp;
+    /** Accumulated energy since device boot in microwatt-seconds (uWs) */
+    uint64_t energy;
+};
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
index 3c7b5c5..b6610e0 100644
--- a/radio/1.3/Android.bp
+++ b/radio/1.3/Android.bp
@@ -9,15 +9,24 @@
     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",
+        "android.hidl.safe_union@1.0",
     ],
     types: [
         "AccessNetwork",
+        "DataProfileInfo",
+        "DataRegStateResult",
+        "EmergencyNumber",
+        "EmergencyNumberSource",
+        "EmergencyServiceCategory",
+        "LteVopsInfo",
     ],
     gen_java: true,
 }
diff --git a/radio/1.3/IRadio.hal b/radio/1.3/IRadio.hal
index 16e6684..dde9d71 100644
--- a/radio/1.3/IRadio.hal
+++ b/radio/1.3/IRadio.hal
@@ -16,10 +16,12 @@
 
 package android.hardware.radio@1.3;
 
-import @1.0::DataProfileInfo;
+import @1.3::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.
@@ -54,13 +56,7 @@
      * @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
@@ -80,6 +76,50 @@
      * 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);
+            DataProfileInfo dataProfileInfo, bool roamingAllowed,
+            DataRequestReason reason, vec<string> addresses, vec<string> dnses);
+
+    /**
+     * Set an apn to initial attach network
+     *
+     * @param serial Serial number of request.
+     * @param dataProfileInfo data profile containing APN settings
+     *
+     * Response callback is IRadioResponse.setInitialAttachApnResponse()
+     */
+    oneway setInitialAttachApn_1_3(int32_t serial, DataProfileInfo dataProfileInfo);
+
+    /**
+     * Send data profiles of the current carrier to the modem.
+     *
+     * @param serial Serial number of request.
+     * @param profiles Array of DataProfile to set.
+     *
+     * Response callback is IRadioResponse.setDataProfileResponse()
+     */
+    oneway setDataProfile_1_3(int32_t serial, vec<DataProfileInfo> profiles);
+
+    /**
+     * Initiate emergency voice call, with zero 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.
+     *
+     * If the dialed emergency number does not have a specified emergency service category, the
+     * 'categories' field is set to @1.3::EmergencyServiceCategory#UNSPECIFIED; iff either the
+     * 'categories' field is set to @1.3::EmergencyServiceCategory#UNSPECIFIED or the underlying
+     * technology used to request emergency services does not support the emergency service
+     * category, the interpretation of the categories is defined by implementation.
+     *
+     * Reference: 3gpp TS 22.101, Section 10 - Emergency Calls
+     *
+     * @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..509eef8
--- /dev/null
+++ b/radio/1.3/IRadioIndication.hal
@@ -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.
+ */
+
+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 {
+    /**
+     * Report the current list of emergency numbers
+     *
+     * Each emergency number (@1.3::EmergencyNumber) in the emergency number list contains a
+     * dialing number, zero or more service category(s), mobile country code, and source(s) that
+     * indicate where it comes from.
+     *
+     * Radio must report all the valid emergency numbers with known mobile country code and
+     * emergency service categories from all available sources including network signaling, sim,
+     * modem/oem configuration, and default configuration (112 and 911 must be always available;
+     * additionally, 000, 08, 110, 999, 118 and 119 must be available when sim is not present).
+     * Radio shall not report emergency numbers that are invalid in the current locale. The
+     * reported emergency number list must not have duplicate @1.3::EmergencyNumber entries. Please
+     * refer the documentation of @1.3::EmergencyNumber to construct each emergency number to
+     * report.
+     *
+     * Radio must report the complete list of emergency numbers whenever the emergency numbers in
+     * the list are changed or whenever the client and the radio server are connected.
+     *
+     * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+     *
+     * @param type Type of radio indication
+     * @param emergencyNumberList Current list of emergency numbers known to radio.
+     */
+    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..10e7d63
--- /dev/null
+++ b/radio/1.3/IRadioResponse.hal
@@ -0,0 +1,64 @@
+/*
+ * 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
+     *
+     * 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
index b80aabd..8b0891c 100644
--- a/radio/1.3/types.hal
+++ b/radio/1.3/types.hal
@@ -16,7 +16,17 @@
 
 package android.hardware.radio@1.3;
 
+import @1.0::ApnAuthType;
+import @1.0::ApnTypes;
+import @1.0::DataProfileId;
+import @1.0::DataProfileInfoType;
+import @1.0::RadioAccessFamily;
+import @1.0::RegState;
 import @1.2::AccessNetwork;
+import @1.2::CellIdentity;
+import @1.2::DataRegStateResult;
+
+import android.hidl.safe_union@1.0::Monostate;
 
 enum AccessNetwork : @1.2::AccessNetwork {
     /**
@@ -24,3 +34,212 @@
      */
     UNKNOWN = 0,
 };
+
+/**
+ * Emergency number contains information of number, one or more service category(s), mobile country
+ * code (mcc), and source(s) that indicate where it comes from.
+ *
+ * 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’, ‘mcc’ and 'categories' fields.
+ * Multiple @1.3::EmergencyNumberSource 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;
+    /**
+     * The bitfield of @1.3::EmergencyNumberSource(s). See @1.3::EmergencyNumberSource for the
+     * value of each bit.
+     */
+    bitfield<EmergencyNumberSource> sources;
+};
+
+/**
+ * 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);
+ *
+ * Category UNSPECIFIED (General emergency call, all categories) indicates that no specific
+ * services are associated with this emergency number.
+ *
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+ */
+enum EmergencyServiceCategory : int32_t {
+    /**
+     * General emergency call, all categories
+     */
+    UNSPECIFIED = 0,
+    POLICE = 1 << 0,
+    AMBULANCE = 1 << 1,
+    FIRE_BRIGADE = 1 << 2,
+    MARINE_GUARD = 1 << 3,
+    MOUNTAIN_RESCUE = 1 << 4,
+    /**
+     * Manually Initiated eCall (MIeC)
+     */
+    MIEC = 1 << 5,
+    /**
+     * Automatically Initiated eCall (AIeC)
+     */
+    AIEC = 1 << 6,
+};
+
+/**
+ * The source to tell where the corresponding @1.3::EmergencyNumber comes from.
+ *
+ * Reference: 3gpp 22.101, Section 10 - Emergency Calls
+ */
+enum EmergencyNumberSource : int32_t {
+    /**
+     * Indicates the number is from the network signal.
+     */
+    NETWORK_SIGNALING = 1 << 0,
+    /**
+     * Indicates the number is from the sim card.
+     */
+    SIM = 1 << 1,
+    /**
+     * Indicates the number is from the modem config.
+     */
+    MODEM_CONFIG = 1 << 2,
+    /**
+     * Indicates the number is available as default. Per the reference, 112, 911 must always be
+     * available; additionally, 000, 08, 110, 999, 118 and 119 must be available when sim is not
+     * present.
+     */
+    DEFAULT = 1 << 3,
+};
+
+/**
+ * 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 {
+        Monostate noinit;
+
+        LteVopsInfo lteVopsInfo; // LTE network capability
+    } vopsInfo;
+};
+
+/**
+ * Overwritten from @1.0::DataProfileInfo in order to deprecate 'mvnoType', and 'mvnoMatchData'.
+ * In the future, this must be extended instead of overwritten.
+ * Also added 'preferred' and 'persistent' in this version.
+ */
+struct DataProfileInfo {
+    /** id of the data profile */
+    DataProfileId profileId;
+
+    /** The APN name */
+    string apn;
+
+    /**
+     * One of the PDP_type values in TS 27.007 section 10.1.1. For example, "IP", "IPV6", "IPV4V6",
+     * or "PPP".
+     */
+    string protocol;
+
+    /**
+     * one of the PDP_type values in TS 27.007 section 10.1.1 used on roaming network. For example,
+     * "IP", "IPV6", "IPV4V6", or "PPP".
+     */
+    string roamingProtocol;
+
+    /** APN authentication type */
+    ApnAuthType authType;
+
+    /** The username for APN, or empty string */
+    string user;
+
+    /** The password for APN, or empty string */
+    string password;
+
+    /** Data profile technology type */
+    DataProfileInfoType type;
+
+    /** The period in seconds to limit the maximum connections */
+    int32_t maxConnsTime;
+
+    /** The maximum connections during maxConnsTime */
+    int32_t maxConns;
+
+    /**
+     * The required wait time in seconds after a successful UE initiated disconnect of a given PDN
+     * connection before the device can send a new PDN connection request for that given PDN.
+     */
+    int32_t waitTime;
+
+    /** True to enable the profile, false to disable */
+    bool enabled;
+
+    /** Supported APN types bitmap. See ApnTypes for the value of each bit. */
+    bitfield<ApnTypes> supportedApnTypesBitmap;
+
+    /** The bearer bitmap. See RadioAccessFamily for the value of each bit. */
+    bitfield<RadioAccessFamily> bearerBitmap;
+
+    /** Maximum transmission unit (MTU) size in bytes */
+    int32_t mtu;
+
+    /**
+     * True if this data profile was used to bring up the last default (i.e internet) data
+     * connection successfully.
+     */
+    bool preferred;
+
+    /**
+     * If true, modem must persist this data profile and profileId must not be
+     * set to DataProfileId.INVALID. If the same data profile exists, this data profile must
+     * overwrite it.
+     */
+    bool persistent;
+};
diff --git a/sensors/1.0/default/convert.cpp b/sensors/1.0/default/convert.cpp
index a5747d4..52f5e4f 100644
--- a/sensors/1.0/default/convert.cpp
+++ b/sensors/1.0/default/convert.cpp
@@ -74,8 +74,7 @@
     };
 
     switch (dst->sensorType) {
-        case SensorType::META_DATA:
-        {
+        case SensorType::META_DATA: {
             dst->u.meta.what = (MetaDataEventType)src.meta_data.what;
             // Legacy HALs contain the handle reference in the meta data field.
             // Copy that over to the handle of the event. In legacy HALs this
@@ -89,8 +88,7 @@
         case SensorType::ORIENTATION:
         case SensorType::GYROSCOPE:
         case SensorType::GRAVITY:
-        case SensorType::LINEAR_ACCELERATION:
-        {
+        case SensorType::LINEAR_ACCELERATION: {
             dst->u.vec3.x = src.acceleration.x;
             dst->u.vec3.y = src.acceleration.y;
             dst->u.vec3.z = src.acceleration.z;
@@ -98,10 +96,7 @@
             break;
         }
 
-        case SensorType::ROTATION_VECTOR:
-        case SensorType::GAME_ROTATION_VECTOR:
-        case SensorType::GEOMAGNETIC_ROTATION_VECTOR:
-        {
+        case SensorType::GAME_ROTATION_VECTOR: {
             dst->u.vec4.x = src.data[0];
             dst->u.vec4.y = src.data[1];
             dst->u.vec4.z = src.data[2];
@@ -109,151 +104,150 @@
             break;
         }
 
-      case SensorType::MAGNETIC_FIELD_UNCALIBRATED:
-      case SensorType::GYROSCOPE_UNCALIBRATED:
-      case SensorType::ACCELEROMETER_UNCALIBRATED:
-      {
-          dst->u.uncal.x = src.uncalibrated_gyro.x_uncalib;
-          dst->u.uncal.y = src.uncalibrated_gyro.y_uncalib;
-          dst->u.uncal.z = src.uncalibrated_gyro.z_uncalib;
-          dst->u.uncal.x_bias = src.uncalibrated_gyro.x_bias;
-          dst->u.uncal.y_bias = src.uncalibrated_gyro.y_bias;
-          dst->u.uncal.z_bias = src.uncalibrated_gyro.z_bias;
-          break;
-      }
+        case SensorType::ROTATION_VECTOR:
+        case SensorType::GEOMAGNETIC_ROTATION_VECTOR: {
+            dst->u.data[0] = src.data[0];
+            dst->u.data[1] = src.data[1];
+            dst->u.data[2] = src.data[2];
+            dst->u.data[3] = src.data[3];
+            dst->u.data[4] = src.data[4];
+            break;
+        }
 
-      case SensorType::DEVICE_ORIENTATION:
-      case SensorType::LIGHT:
-      case SensorType::PRESSURE:
-      case SensorType::TEMPERATURE:
-      case SensorType::PROXIMITY:
-      case SensorType::RELATIVE_HUMIDITY:
-      case SensorType::AMBIENT_TEMPERATURE:
-      case SensorType::SIGNIFICANT_MOTION:
-      case SensorType::STEP_DETECTOR:
-      case SensorType::TILT_DETECTOR:
-      case SensorType::WAKE_GESTURE:
-      case SensorType::GLANCE_GESTURE:
-      case SensorType::PICK_UP_GESTURE:
-      case SensorType::WRIST_TILT_GESTURE:
-      case SensorType::STATIONARY_DETECT:
-      case SensorType::MOTION_DETECT:
-      case SensorType::HEART_BEAT:
-      case SensorType::LOW_LATENCY_OFFBODY_DETECT:
-      {
-          dst->u.scalar = src.data[0];
-          break;
-      }
+        case SensorType::MAGNETIC_FIELD_UNCALIBRATED:
+        case SensorType::GYROSCOPE_UNCALIBRATED:
+        case SensorType::ACCELEROMETER_UNCALIBRATED: {
+            dst->u.uncal.x = src.uncalibrated_gyro.x_uncalib;
+            dst->u.uncal.y = src.uncalibrated_gyro.y_uncalib;
+            dst->u.uncal.z = src.uncalibrated_gyro.z_uncalib;
+            dst->u.uncal.x_bias = src.uncalibrated_gyro.x_bias;
+            dst->u.uncal.y_bias = src.uncalibrated_gyro.y_bias;
+            dst->u.uncal.z_bias = src.uncalibrated_gyro.z_bias;
+            break;
+        }
 
-      case SensorType::STEP_COUNTER:
-      {
-          dst->u.stepCount = src.u64.step_counter;
-          break;
-      }
+        case SensorType::DEVICE_ORIENTATION:
+        case SensorType::LIGHT:
+        case SensorType::PRESSURE:
+        case SensorType::TEMPERATURE:
+        case SensorType::PROXIMITY:
+        case SensorType::RELATIVE_HUMIDITY:
+        case SensorType::AMBIENT_TEMPERATURE:
+        case SensorType::SIGNIFICANT_MOTION:
+        case SensorType::STEP_DETECTOR:
+        case SensorType::TILT_DETECTOR:
+        case SensorType::WAKE_GESTURE:
+        case SensorType::GLANCE_GESTURE:
+        case SensorType::PICK_UP_GESTURE:
+        case SensorType::WRIST_TILT_GESTURE:
+        case SensorType::STATIONARY_DETECT:
+        case SensorType::MOTION_DETECT:
+        case SensorType::HEART_BEAT:
+        case SensorType::LOW_LATENCY_OFFBODY_DETECT: {
+            dst->u.scalar = src.data[0];
+            break;
+        }
 
-      case SensorType::HEART_RATE:
-      {
-          dst->u.heartRate.bpm = src.heart_rate.bpm;
-          dst->u.heartRate.status = (SensorStatus)src.heart_rate.status;
-          break;
-      }
+        case SensorType::STEP_COUNTER: {
+            dst->u.stepCount = src.u64.step_counter;
+            break;
+        }
 
-      case SensorType::POSE_6DOF:  // 15 floats
-      {
-          for (size_t i = 0; i < 15; ++i) {
-              dst->u.pose6DOF[i] = src.data[i];
-          }
-          break;
-      }
+        case SensorType::HEART_RATE: {
+            dst->u.heartRate.bpm = src.heart_rate.bpm;
+            dst->u.heartRate.status = (SensorStatus)src.heart_rate.status;
+            break;
+        }
 
-      case SensorType::DYNAMIC_SENSOR_META:
-      {
-          dst->u.dynamic.connected = src.dynamic_sensor_meta.connected;
-          dst->u.dynamic.sensorHandle = src.dynamic_sensor_meta.handle;
+        case SensorType::POSE_6DOF: {  // 15 floats
+            for (size_t i = 0; i < 15; ++i) {
+                dst->u.pose6DOF[i] = src.data[i];
+            }
+            break;
+        }
 
-          memcpy(dst->u.dynamic.uuid.data(),
-                 src.dynamic_sensor_meta.uuid,
-                 16);
+        case SensorType::DYNAMIC_SENSOR_META: {
+            dst->u.dynamic.connected = src.dynamic_sensor_meta.connected;
+            dst->u.dynamic.sensorHandle = src.dynamic_sensor_meta.handle;
 
-          break;
-      }
+            memcpy(dst->u.dynamic.uuid.data(), src.dynamic_sensor_meta.uuid, 16);
 
-      case SensorType::ADDITIONAL_INFO:
-      {
-          ::android::hardware::sensors::V1_0::AdditionalInfo *dstInfo =
-              &dst->u.additional;
+            break;
+        }
 
-          const additional_info_event_t &srcInfo = src.additional_info;
+        case SensorType::ADDITIONAL_INFO: {
+            ::android::hardware::sensors::V1_0::AdditionalInfo* dstInfo = &dst->u.additional;
 
-          dstInfo->type =
-              (::android::hardware::sensors::V1_0::AdditionalInfoType)
-                  srcInfo.type;
+            const additional_info_event_t& srcInfo = src.additional_info;
 
-          dstInfo->serial = srcInfo.serial;
+            dstInfo->type = (::android::hardware::sensors::V1_0::AdditionalInfoType)srcInfo.type;
 
-          CHECK_EQ(sizeof(dstInfo->u), sizeof(srcInfo.data_int32));
-          memcpy(&dstInfo->u, srcInfo.data_int32, sizeof(srcInfo.data_int32));
-          break;
-      }
+            dstInfo->serial = srcInfo.serial;
 
-      default:
-      {
-          CHECK_GE((int32_t)dst->sensorType,
-                   (int32_t)SensorType::DEVICE_PRIVATE_BASE);
+            CHECK_EQ(sizeof(dstInfo->u), sizeof(srcInfo.data_int32));
+            memcpy(&dstInfo->u, srcInfo.data_int32, sizeof(srcInfo.data_int32));
+            break;
+        }
 
-          memcpy(dst->u.data.data(), src.data, 16 * sizeof(float));
-          break;
-      }
-  }
+        default: {
+            CHECK_GE((int32_t)dst->sensorType, (int32_t)SensorType::DEVICE_PRIVATE_BASE);
+
+            memcpy(dst->u.data.data(), src.data, 16 * sizeof(float));
+            break;
+        }
+    }
 }
 
 void convertToSensorEvent(const Event &src, sensors_event_t *dst) {
-  *dst = {
-      .version = sizeof(sensors_event_t),
-      .sensor = src.sensorHandle,
-      .type = (int32_t)src.sensorType,
-      .reserved0 = 0,
-      .timestamp = src.timestamp
-  };
+    *dst = {.version = sizeof(sensors_event_t),
+            .sensor = src.sensorHandle,
+            .type = (int32_t)src.sensorType,
+            .reserved0 = 0,
+            .timestamp = src.timestamp};
 
-  switch (src.sensorType) {
-      case SensorType::META_DATA:
-      {
-          // Legacy HALs expect the handle reference in the meta data field.
-          // Copy it over from the handle of the event.
-          dst->meta_data.what = (int32_t)src.u.meta.what;
-          dst->meta_data.sensor = src.sensorHandle;
-          // Set the sensor handle to 0 to maintain compatibility.
-          dst->sensor = 0;
-          break;
-      }
+    switch (src.sensorType) {
+        case SensorType::META_DATA: {
+            // Legacy HALs expect the handle reference in the meta data field.
+            // Copy it over from the handle of the event.
+            dst->meta_data.what = (int32_t)src.u.meta.what;
+            dst->meta_data.sensor = src.sensorHandle;
+            // Set the sensor handle to 0 to maintain compatibility.
+            dst->sensor = 0;
+            break;
+        }
 
-      case SensorType::ACCELEROMETER:
-      case SensorType::MAGNETIC_FIELD:
-      case SensorType::ORIENTATION:
-      case SensorType::GYROSCOPE:
-      case SensorType::GRAVITY:
-      case SensorType::LINEAR_ACCELERATION:
-      {
-          dst->acceleration.x = src.u.vec3.x;
-          dst->acceleration.y = src.u.vec3.y;
-          dst->acceleration.z = src.u.vec3.z;
-          dst->acceleration.status = (int8_t)src.u.vec3.status;
-          break;
-      }
+        case SensorType::ACCELEROMETER:
+        case SensorType::MAGNETIC_FIELD:
+        case SensorType::ORIENTATION:
+        case SensorType::GYROSCOPE:
+        case SensorType::GRAVITY:
+        case SensorType::LINEAR_ACCELERATION: {
+            dst->acceleration.x = src.u.vec3.x;
+            dst->acceleration.y = src.u.vec3.y;
+            dst->acceleration.z = src.u.vec3.z;
+            dst->acceleration.status = (int8_t)src.u.vec3.status;
+            break;
+        }
 
-      case SensorType::ROTATION_VECTOR:
-      case SensorType::GAME_ROTATION_VECTOR:
-      case SensorType::GEOMAGNETIC_ROTATION_VECTOR:
-      {
-          dst->data[0] = src.u.vec4.x;
-          dst->data[1] = src.u.vec4.y;
-          dst->data[2] = src.u.vec4.z;
-          dst->data[3] = src.u.vec4.w;
-          break;
-      }
+        case SensorType::GAME_ROTATION_VECTOR: {
+            dst->data[0] = src.u.vec4.x;
+            dst->data[1] = src.u.vec4.y;
+            dst->data[2] = src.u.vec4.z;
+            dst->data[3] = src.u.vec4.w;
+            break;
+        }
 
-      case SensorType::MAGNETIC_FIELD_UNCALIBRATED:
+        case SensorType::ROTATION_VECTOR:
+        case SensorType::GEOMAGNETIC_ROTATION_VECTOR: {
+            dst->data[0] = src.u.data[0];
+            dst->data[1] = src.u.data[1];
+            dst->data[2] = src.u.data[2];
+            dst->data[3] = src.u.data[3];
+            dst->data[4] = src.u.data[4];
+            break;
+        }
+
+        case SensorType::MAGNETIC_FIELD_UNCALIBRATED:
         case SensorType::GYROSCOPE_UNCALIBRATED:
         case SensorType::ACCELEROMETER_UNCALIBRATED:
         {
@@ -283,35 +277,30 @@
         case SensorType::STATIONARY_DETECT:
         case SensorType::MOTION_DETECT:
         case SensorType::HEART_BEAT:
-        case SensorType::LOW_LATENCY_OFFBODY_DETECT:
-        {
+        case SensorType::LOW_LATENCY_OFFBODY_DETECT: {
             dst->data[0] = src.u.scalar;
             break;
         }
 
-        case SensorType::STEP_COUNTER:
-        {
+        case SensorType::STEP_COUNTER: {
             dst->u64.step_counter = src.u.stepCount;
             break;
         }
 
-        case SensorType::HEART_RATE:
-        {
+        case SensorType::HEART_RATE: {
             dst->heart_rate.bpm = src.u.heartRate.bpm;
             dst->heart_rate.status = (int8_t)src.u.heartRate.status;
             break;
         }
 
-        case SensorType::POSE_6DOF:  // 15 floats
-        {
+        case SensorType::POSE_6DOF: {  // 15 floats
             for (size_t i = 0; i < 15; ++i) {
                 dst->data[i] = src.u.pose6DOF[i];
             }
             break;
         }
 
-        case SensorType::DYNAMIC_SENSOR_META:
-        {
+        case SensorType::DYNAMIC_SENSOR_META: {
             dst->dynamic_sensor_meta.connected = src.u.dynamic.connected;
             dst->dynamic_sensor_meta.handle = src.u.dynamic.sensorHandle;
             dst->dynamic_sensor_meta.sensor = NULL;  // to be filled in later
@@ -323,8 +312,7 @@
             break;
         }
 
-        case SensorType::ADDITIONAL_INFO:
-        {
+        case SensorType::ADDITIONAL_INFO: {
             const ::android::hardware::sensors::V1_0::AdditionalInfo &srcInfo =
                 src.u.additional;
 
@@ -341,8 +329,7 @@
             break;
         }
 
-        default:
-        {
+        default: {
             CHECK_GE((int32_t)src.sensorType,
                      (int32_t)SensorType::DEVICE_PRIVATE_BASE);
 
diff --git a/sensors/1.0/vts/functional/Android.bp b/sensors/1.0/vts/functional/Android.bp
index 0ea400e..6563e3c 100644
--- a/sensors/1.0/vts/functional/Android.bp
+++ b/sensors/1.0/vts/functional/Android.bp
@@ -18,13 +18,14 @@
     name: "VtsHalSensorsV1_0TargetTest",
     defaults: ["VtsHalTargetTestDefaults"],
     srcs: [
-        "GrallocWrapper.cpp",
+        "SensorsHidlEnvironmentV1_0.cpp",
         "VtsHalSensorsV1_0TargetTest.cpp"
     ],
     static_libs: [
         "android.hardware.graphics.allocator@2.0",
         "android.hardware.graphics.mapper@2.0",
         "android.hardware.sensors@1.0",
+        "VtsHalSensorsTargetTestUtils",
     ],
 }
 
diff --git a/sensors/1.0/vts/functional/GrallocWrapper.cpp b/sensors/1.0/vts/functional/GrallocWrapper.cpp
deleted file mode 100644
index e422d62..0000000
--- a/sensors/1.0/vts/functional/GrallocWrapper.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "GrallocWrapper"
-
-#include "GrallocWrapper.h"
-
-#include <utils/Log.h>
-
-namespace android {
-
-GrallocWrapper::GrallocWrapper() { init(); }
-
-void GrallocWrapper::init() {
-  mAllocator = allocator2::IAllocator::getService();
-  if (mAllocator == nullptr) {
-    ALOGE("Failed to get allocator service");
-  }
-
-  mMapper = mapper2::IMapper::getService();
-  if (mMapper == nullptr) {
-    ALOGE("Failed to get mapper service");
-  }
-  if (mMapper->isRemote()) {
-    ALOGE("Mapper is not in passthrough mode");
-  }
-}
-
-GrallocWrapper::~GrallocWrapper() {
-  for (auto bufferHandle : mClonedBuffers) {
-    auto buffer = const_cast<native_handle_t*>(bufferHandle);
-    native_handle_close(buffer);
-    native_handle_delete(buffer);
-  }
-  mClonedBuffers.clear();
-
-  for (auto bufferHandle : mImportedBuffers) {
-    auto buffer = const_cast<native_handle_t*>(bufferHandle);
-    if (mMapper->freeBuffer(buffer) != mapper2::Error::NONE) {
-      ALOGE("Failed to free buffer %p", buffer);
-    }
-  }
-  mImportedBuffers.clear();
-}
-
-sp<allocator2::IAllocator> GrallocWrapper::getAllocator() const {
-  return mAllocator;
-}
-
-std::string GrallocWrapper::dumpDebugInfo() {
-  std::string debugInfo;
-  mAllocator->dumpDebugInfo(
-      [&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
-
-  return debugInfo;
-}
-
-const native_handle_t* GrallocWrapper::cloneBuffer(
-    const hardware::hidl_handle& rawHandle) {
-  const native_handle_t* bufferHandle =
-      native_handle_clone(rawHandle.getNativeHandle());
-
-  if (bufferHandle) {
-    mClonedBuffers.insert(bufferHandle);
-  }
-  return bufferHandle;
-}
-
-std::vector<const native_handle_t*> GrallocWrapper::allocate(
-    const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import,
-    uint32_t* outStride) {
-  std::vector<const native_handle_t*> bufferHandles;
-  bufferHandles.reserve(count);
-  mAllocator->allocate(
-      descriptor, count,
-      [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
-        if (mapper2::Error::NONE != tmpError) {
-          ALOGE("Failed to allocate buffers");
-        }
-        if (count != tmpBuffers.size()) {
-          ALOGE("Invalid buffer array");
-        }
-
-        for (uint32_t i = 0; i < count; i++) {
-          if (import) {
-            bufferHandles.push_back(importBuffer(tmpBuffers[i]));
-          } else {
-            bufferHandles.push_back(cloneBuffer(tmpBuffers[i]));
-          }
-        }
-
-        if (outStride) {
-          *outStride = tmpStride;
-        }
-      });
-
-  return bufferHandles;
-}
-
-const native_handle_t* GrallocWrapper::allocate(
-    const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import,
-    uint32_t* outStride) {
-  mapper2::BufferDescriptor descriptor = createDescriptor(descriptorInfo);
-  ALOGE("QQ");
-  auto buffers = allocate(descriptor, 1, import, outStride);
-  return buffers[0];
-}
-
-sp<mapper2::IMapper> GrallocWrapper::getMapper() const { return mMapper; }
-
-mapper2::BufferDescriptor GrallocWrapper::createDescriptor(
-    const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo) {
-  mapper2::BufferDescriptor descriptor;
-  mMapper->createDescriptor(
-      descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
-        if (tmpError != mapper2::Error::NONE) {
-          ALOGE("Failed to create descriptor");
-        }
-        descriptor = tmpDescriptor;
-      });
-
-  return descriptor;
-}
-
-const native_handle_t* GrallocWrapper::importBuffer(
-    const hardware::hidl_handle& rawHandle) {
-  const native_handle_t* bufferHandle = nullptr;
-  mMapper->importBuffer(
-      rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
-        if (tmpError != mapper2::Error::NONE) {
-          ALOGE("Failed to import buffer %p", rawHandle.getNativeHandle());
-        }
-        bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
-      });
-
-  if (bufferHandle) {
-    mImportedBuffers.insert(bufferHandle);
-  }
-
-  return bufferHandle;
-}
-
-void GrallocWrapper::freeBuffer(const native_handle_t* bufferHandle) {
-  auto buffer = const_cast<native_handle_t*>(bufferHandle);
-
-  if (mImportedBuffers.erase(bufferHandle)) {
-    mapper2::Error error = mMapper->freeBuffer(buffer);
-    if (error != mapper2::Error::NONE) {
-      ALOGE("Failed to free %p", buffer);
-    }
-  } else {
-    mClonedBuffers.erase(bufferHandle);
-    native_handle_close(buffer);
-    native_handle_delete(buffer);
-  }
-}
-
-void* GrallocWrapper::lock(const native_handle_t* bufferHandle,
-                           uint64_t cpuUsage,
-                           const mapper2::IMapper::Rect& accessRegion,
-                           int acquireFence) {
-  auto buffer = const_cast<native_handle_t*>(bufferHandle);
-
-  NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
-  hardware::hidl_handle acquireFenceHandle;
-  if (acquireFence >= 0) {
-    auto h = native_handle_init(acquireFenceStorage, 1, 0);
-    h->data[0] = acquireFence;
-    acquireFenceHandle = h;
-  }
-
-  void* data = nullptr;
-  mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
-                [&](const auto& tmpError, const auto& tmpData) {
-                  if (tmpError != mapper2::Error::NONE) {
-                    ALOGE("Failed to lock buffer %p", buffer);
-                  }
-                  data = tmpData;
-                });
-
-  if (acquireFence >= 0) {
-    close(acquireFence);
-  }
-
-  return data;
-}
-
-int GrallocWrapper::unlock(const native_handle_t* bufferHandle) {
-  auto buffer = const_cast<native_handle_t*>(bufferHandle);
-
-  int releaseFence = -1;
-  mMapper->unlock(buffer, [&](const auto& tmpError,
-                              const auto& tmpReleaseFence) {
-    if (tmpError != mapper2::Error::NONE) {
-      ALOGE("Failed to unlock buffer %p", buffer);
-    }
-
-    auto fenceHandle = tmpReleaseFence.getNativeHandle();
-    if (fenceHandle) {
-      if (fenceHandle->numInts != 0) {
-        ALOGE("Invalid fence handle %p", fenceHandle);
-      }
-      if (fenceHandle->numFds == 1) {
-        releaseFence = dup(fenceHandle->data[0]);
-        if (releaseFence < 0){
-          ALOGE("Failed to dup fence fd");
-        }
-      } else {
-        if (fenceHandle->numFds != 0) {
-          ALOGE("Invalid fence handle %p", fenceHandle);
-        }
-      }
-    }
-  });
-
-  return releaseFence;
-}
-
-}  // namespace android
diff --git a/sensors/1.0/vts/functional/GrallocWrapper.h b/sensors/1.0/vts/functional/GrallocWrapper.h
deleted file mode 100644
index e506fe1..0000000
--- a/sensors/1.0/vts/functional/GrallocWrapper.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef GRALLO_WRAPPER_H_
-#define GRALLO_WRAPPER_H_
-
-#include <unordered_set>
-
-#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
-#include <android/hardware/graphics/mapper/2.0/IMapper.h>
-
-namespace allocator2 = ::android::hardware::graphics::allocator::V2_0;
-namespace mapper2 = ::android::hardware::graphics::mapper::V2_0;
-
-namespace android {
-
-// Modified from hardware/interfaces/graphics/mapper/2.0/vts/functional/
-class GrallocWrapper {
- public:
-  GrallocWrapper();
-  ~GrallocWrapper();
-
-  sp<allocator2::IAllocator> getAllocator() const;
-  sp<mapper2::IMapper> getMapper() const;
-
-  std::string dumpDebugInfo();
-
-  // When import is false, this simply calls IAllocator::allocate. When import
-  // is true, the returned buffers are also imported into the mapper.
-  //
-  // Either case, the returned buffers must be freed with freeBuffer.
-  std::vector<const native_handle_t*> allocate(
-      const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import = true,
-      uint32_t* outStride = nullptr);
-  const native_handle_t* allocate(
-      const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import = true,
-      uint32_t* outStride = nullptr);
-
-  mapper2::BufferDescriptor createDescriptor(
-      const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo);
-
-  const native_handle_t* importBuffer(const hardware::hidl_handle& rawHandle);
-  void freeBuffer(const native_handle_t* bufferHandle);
-
-  // We use fd instead of hardware::hidl_handle in these functions to pass fences
-  // in and out of the mapper.  The ownership of the fd is always transferred
-  // with each of these functions.
-  void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
-             const mapper2::IMapper::Rect& accessRegion, int acquireFence);
-
-  int unlock(const native_handle_t* bufferHandle);
-
- private:
-  void init();
-  const native_handle_t* cloneBuffer(const hardware::hidl_handle& rawHandle);
-
-  sp<allocator2::IAllocator> mAllocator;
-  sp<mapper2::IMapper> mMapper;
-
-  // Keep track of all cloned and imported handles.  When a test fails with
-  // ASSERT_*, the destructor will free the handles for the test.
-  std::unordered_set<const native_handle_t*> mClonedBuffers;
-  std::unordered_set<const native_handle_t*> mImportedBuffers;
-};
-
-}  // namespace android
-#endif  // GRALLO_WRAPPER_H_
diff --git a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
new file mode 100644
index 0000000..f8b021e
--- /dev/null
+++ b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.cpp
@@ -0,0 +1,121 @@
+/*
+ * 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 "SensorsHidlEnvironmentV1_0.h"
+
+#include <log/log.h>
+
+#include <vector>
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::sensors::V1_0::ISensors;
+using ::android::hardware::sensors::V1_0::Result;
+using ::android::hardware::sensors::V1_0::SensorInfo;
+
+bool SensorsHidlEnvironmentV1_0::resetHal() {
+    // wait upto 100ms * 10 = 1s for hidl service.
+    constexpr auto RETRY_DELAY = std::chrono::milliseconds(100);
+
+    std::string step;
+    bool succeed = false;
+    for (size_t retry = 10; retry > 0; --retry) {
+        // this do ... while is for easy error handling
+        do {
+            step = "getService()";
+            sensors = ISensors::getService(
+                SensorsHidlEnvironmentV1_0::Instance()->getServiceName<ISensors>());
+            if (sensors == nullptr) {
+                break;
+            }
+
+            step = "poll() check";
+            // Poke ISensor service. If it has lingering connection from previous generation of
+            // system server, it will kill itself. There is no intention to handle the poll result,
+            // which will be done since the size is 0.
+            if (!sensors->poll(0, [](auto, const auto&, const auto&) {}).isOk()) {
+                break;
+            }
+
+            step = "getSensorList";
+            std::vector<SensorInfo> sensorList;
+            if (!sensors
+                     ->getSensorsList([&](const hidl_vec<SensorInfo>& list) {
+                         sensorList.reserve(list.size());
+                         for (size_t i = 0; i < list.size(); ++i) {
+                             sensorList.push_back(list[i]);
+                         }
+                     })
+                     .isOk()) {
+                break;
+            }
+
+            // stop each sensor individually
+            step = "stop each sensor";
+            bool ok = true;
+            for (const auto& i : sensorList) {
+                if (!sensors->activate(i.sensorHandle, false).isOk()) {
+                    ok = false;
+                    break;
+                }
+            }
+            if (!ok) {
+                break;
+            }
+
+            // mark it done
+            step = "done";
+            succeed = true;
+        } while (0);
+
+        if (succeed) {
+            return true;
+        }
+
+        // Delay 100ms before retry, hidl service is expected to come up in short time after crash.
+        ALOGI("%s unsuccessful, try again soon (remaining retry %zu).", step.c_str(), retry - 1);
+        std::this_thread::sleep_for(RETRY_DELAY);
+    }
+
+    sensors = nullptr;
+    return false;
+}
+
+void SensorsHidlEnvironmentV1_0::startPollingThread() {
+    stopThread = false;
+    pollThread = std::thread(pollingThread, this, std::ref(stopThread));
+    events.reserve(128);
+}
+
+void SensorsHidlEnvironmentV1_0::pollingThread(SensorsHidlEnvironmentV1_0* env,
+                                               std::atomic_bool& stop) {
+    ALOGD("polling thread start");
+
+    while (!stop) {
+        env->sensors->poll(
+            64, [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
+                if (result != Result::OK ||
+                    (events.size() == 0 && dynamicSensorsAdded.size() == 0) || stop) {
+                    stop = true;
+                    return;
+                }
+
+                for (const auto& e : events) {
+                    env->addEvent(e);
+                }
+            });
+    }
+    ALOGD("polling thread end");
+}
\ No newline at end of file
diff --git a/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
new file mode 100644
index 0000000..0a9e59f
--- /dev/null
+++ b/sensors/1.0/vts/functional/SensorsHidlEnvironmentV1_0.h
@@ -0,0 +1,59 @@
+/*
+ * 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_SENSORS_HIDL_ENVIRONMENT_V1_0_H
+#define ANDROID_SENSORS_HIDL_ENVIRONMENT_V1_0_H
+
+#include "sensors-vts-utils/SensorsHidlEnvironmentBase.h"
+
+#include <android/hardware/sensors/1.0/ISensors.h>
+#include <android/hardware/sensors/1.0/types.h>
+#include <utils/StrongPointer.h>
+
+#include <atomic>
+#include <memory>
+
+using ::android::sp;
+
+class SensorsHidlTest;
+class SensorsHidlEnvironmentV1_0 : public SensorsHidlEnvironmentBase {
+   public:
+    using Event = ::android::hardware::sensors::V1_0::Event;
+    // get the test environment singleton
+    static SensorsHidlEnvironmentV1_0* Instance() {
+        static SensorsHidlEnvironmentV1_0* instance = new SensorsHidlEnvironmentV1_0();
+        return instance;
+    }
+
+    virtual void registerTestServices() override {
+        registerTestService<android::hardware::sensors::V1_0::ISensors>();
+    }
+
+   private:
+    friend SensorsHidlTest;
+    // sensors hidl service
+    sp<android::hardware::sensors::V1_0::ISensors> sensors;
+
+    SensorsHidlEnvironmentV1_0() {}
+
+    bool resetHal() override;
+    void startPollingThread() override;
+    static void pollingThread(SensorsHidlEnvironmentV1_0* env, std::atomic_bool& stop);
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentV1_0);
+};
+
+#endif  // ANDROID_SENSORS_HIDL_ENVIRONMENT_V1_0_H
\ No newline at end of file
diff --git a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
index c18eedd..47308e1 100644
--- a/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
+++ b/sensors/1.0/vts/functional/VtsHalSensorsV1_0TargetTest.cpp
@@ -15,583 +15,66 @@
  */
 
 #define LOG_TAG "sensors_hidl_hal_test"
-#include <VtsHalHidlTargetTestBase.h>
-#include <VtsHalHidlTargetTestEnvBase.h>
-#include <android-base/logging.h>
+
+#include "SensorsHidlEnvironmentV1_0.h"
+#include "sensors-vts-utils/SensorsHidlTestBase.h"
+
 #include <android/hardware/sensors/1.0/ISensors.h>
 #include <android/hardware/sensors/1.0/types.h>
-#include <cutils/ashmem.h>
-#include <hardware/sensors.h>  // for sensor type strings
 #include <log/log.h>
 #include <utils/SystemClock.h>
-#include "GrallocWrapper.h"
 
-#include <algorithm>
 #include <cinttypes>
-#include <cmath>
-#include <memory>
-#include <mutex>
-#include <thread>
-#include <unordered_set>
 #include <vector>
 
-#include <sys/mman.h>
-#include <unistd.h>
-
-using ::android::GrallocWrapper;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using ::android::hardware::hidl_string;
 using ::android::sp;
 using namespace ::android::hardware::sensors::V1_0;
 
-// Test environment for sensors
-class SensorsHidlTest;
-class SensorsHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
-   public:
-    // get the test environment singleton
-    static SensorsHidlEnvironment* Instance() {
-        static SensorsHidlEnvironment* instance = new SensorsHidlEnvironment;
-        return instance;
-    }
-
-    virtual void HidlSetUp() override;
-    virtual void HidlTearDown() override;
-
-    virtual void registerTestServices() override { registerTestService<ISensors>(); }
-
-    // Get and clear all events collected so far (like "cat" shell command).
-    // If output is nullptr, it clears all collected events.
-    void catEvents(std::vector<Event>* output);
-
-    // set sensor event collection status
-    void setCollection(bool enable);
-
-   private:
-    friend SensorsHidlTest;
-    // sensors hidl service
-    sp<ISensors> sensors;
-
-    SensorsHidlEnvironment() {}
-
-    void addEvent(const Event& ev);
-    void startPollingThread();
-    void resetHal();
-    static void pollingThread(SensorsHidlEnvironment* env, std::shared_ptr<bool> stop);
-
-    bool collectionEnabled;
-    std::shared_ptr<bool> stopThread;
-    std::thread pollThread;
-    std::vector<Event> events;
-    std::mutex events_mutex;
-
-    GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironment);
-};
-
-void SensorsHidlEnvironment::HidlSetUp() {
-    resetHal();
-
-    ASSERT_NE(sensors, nullptr) << "sensors is nullptr, cannot get hidl service";
-
-    collectionEnabled = false;
-    startPollingThread();
-
-    // In case framework just stopped for test and there is sensor events in the pipe,
-    // wait some time for those events to be cleared to avoid them messing up the test.
-    std::this_thread::sleep_for(std::chrono::seconds(3));
-}
-
-void SensorsHidlEnvironment::HidlTearDown() {
-    if (stopThread) {
-        *stopThread = true;
-    }
-    pollThread.detach();
-}
-
-void SensorsHidlEnvironment::resetHal() {
-  // wait upto 100ms * 10 = 1s for hidl service.
-  constexpr auto RETRY_DELAY = std::chrono::milliseconds(100);
-
-  std::string step;
-  bool succeed = false;
-  for (size_t retry = 10; retry > 0; --retry) {
-    // this do ... while is for easy error handling
-    do {
-      step = "getService()";
-      sensors = ISensors::getService(
-          SensorsHidlEnvironment::Instance()->getServiceName<ISensors>());
-      if (sensors == nullptr) {
-        break;
-      }
-
-      step = "poll() check";
-      // Poke ISensor service. If it has lingering connection from previous generation of
-      // system server, it will kill itself. There is no intention to handle the poll result,
-      // which will be done since the size is 0.
-      if(!sensors->poll(0, [](auto, const auto &, const auto &) {}).isOk()) {
-        break;
-      }
-
-      step = "getSensorList";
-      std::vector<SensorInfo> sensorList;
-      if (!sensors->getSensorsList(
-          [&] (const ::android::hardware::hidl_vec<SensorInfo> &list) {
-            sensorList.reserve(list.size());
-            for (size_t i = 0; i < list.size(); ++i) {
-              sensorList.push_back(list[i]);
-            }
-          }).isOk()) {
-        break;
-      }
-
-      // stop each sensor individually
-      step = "stop each sensor";
-      bool ok = true;
-      for (const auto &i : sensorList) {
-        if (!sensors->activate(i.sensorHandle, false).isOk()) {
-          ok = false;
-          break;
-        }
-      }
-      if (!ok) {
-        break;
-      }
-
-      // mark it done
-      step = "done";
-      succeed = true;
-    } while(0);
-
-    if (succeed) {
-      return;
-    }
-
-    // Delay 100ms before retry, hidl service is expected to come up in short time after crash.
-    ALOGI("%s unsuccessful, try again soon (remaining retry %zu).", step.c_str(), retry - 1);
-    std::this_thread::sleep_for(RETRY_DELAY);
-  }
-
-  sensors = nullptr;
-}
-
-void SensorsHidlEnvironment::catEvents(std::vector<Event>* output) {
-  std::lock_guard<std::mutex> lock(events_mutex);
-  if (output) {
-    output->insert(output->end(), events.begin(), events.end());
-  }
-  events.clear();
-}
-
-void SensorsHidlEnvironment::setCollection(bool enable) {
-  std::lock_guard<std::mutex> lock(events_mutex);
-  collectionEnabled = enable;
-}
-
-void SensorsHidlEnvironment::addEvent(const Event& ev) {
-  std::lock_guard<std::mutex> lock(events_mutex);
-  if (collectionEnabled) {
-    events.push_back(ev);
-  }
-}
-
-void SensorsHidlEnvironment::startPollingThread() {
-  stopThread = std::shared_ptr<bool>(new bool(false));
-  pollThread = std::thread(pollingThread, this, stopThread);
-  events.reserve(128);
-}
-
-void SensorsHidlEnvironment::pollingThread(
-    SensorsHidlEnvironment* env, std::shared_ptr<bool> stop) {
-  ALOGD("polling thread start");
-  bool needExit = *stop;
-
-  while(!needExit) {
-      env->sensors->poll(64, [&](auto result, const auto& events, const auto& dynamicSensorsAdded) {
-          if (result != Result::OK
-              || (events.size() == 0 && dynamicSensorsAdded.size() == 0)
-              || *stop) {
-              needExit = true;
-              return;
-          }
-
-          for (const auto& e : events) {
-              env->addEvent(e);
-          }
-      });
-  }
-  ALOGD("polling thread end");
-}
-
-class SensorsTestSharedMemory {
- public:
-  static SensorsTestSharedMemory* create(SharedMemType type, size_t size);
-  SharedMemInfo getSharedMemInfo() const;
-  char * getBuffer() const;
-  std::vector<Event> parseEvents(int64_t lastCounter = -1, size_t offset = 0) const;
-  virtual ~SensorsTestSharedMemory();
- private:
-  SensorsTestSharedMemory(SharedMemType type, size_t size);
-
-  SharedMemType mType;
-  native_handle_t* mNativeHandle;
-  size_t mSize;
-  char* mBuffer;
-  std::unique_ptr<GrallocWrapper> mGrallocWrapper;
-
-  DISALLOW_COPY_AND_ASSIGN(SensorsTestSharedMemory);
-};
-
-SharedMemInfo SensorsTestSharedMemory::getSharedMemInfo() const {
-  SharedMemInfo mem = {
-    .type = mType,
-    .format = SharedMemFormat::SENSORS_EVENT,
-    .size = static_cast<uint32_t>(mSize),
-    .memoryHandle = mNativeHandle
-  };
-  return mem;
-}
-
-char * SensorsTestSharedMemory::getBuffer() const {
-  return mBuffer;
-}
-
-std::vector<Event> SensorsTestSharedMemory::parseEvents(int64_t lastCounter, size_t offset) const {
-
-  constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
-  constexpr size_t kOffsetSize = static_cast<size_t>(SensorsEventFormatOffset::SIZE_FIELD);
-  constexpr size_t kOffsetToken = static_cast<size_t>(SensorsEventFormatOffset::REPORT_TOKEN);
-  constexpr size_t kOffsetType = static_cast<size_t>(SensorsEventFormatOffset::SENSOR_TYPE);
-  constexpr size_t kOffsetAtomicCounter =
-      static_cast<size_t>(SensorsEventFormatOffset::ATOMIC_COUNTER);
-  constexpr size_t kOffsetTimestamp = static_cast<size_t>(SensorsEventFormatOffset::TIMESTAMP);
-  constexpr size_t kOffsetData = static_cast<size_t>(SensorsEventFormatOffset::DATA);
-
-  std::vector<Event> events;
-  std::vector<float> data(16);
-
-  while (offset + kEventSize <= mSize) {
-    int64_t atomicCounter = *reinterpret_cast<uint32_t *>(mBuffer + offset + kOffsetAtomicCounter);
-    if (atomicCounter <= lastCounter) {
-      ALOGV("atomicCounter = %" PRId64 ", lastCounter = %" PRId64, atomicCounter, lastCounter);
-      break;
-    }
-
-    int32_t size = *reinterpret_cast<int32_t *>(mBuffer + offset + kOffsetSize);
-    if (size != kEventSize) {
-      // unknown error, events parsed may be wrong, remove all
-      events.clear();
-      break;
-    }
-
-    int32_t token = *reinterpret_cast<int32_t *>(mBuffer + offset + kOffsetToken);
-    int32_t type = *reinterpret_cast<int32_t *>(mBuffer + offset + kOffsetType);
-    int64_t timestamp = *reinterpret_cast<int64_t *>(mBuffer + offset + kOffsetTimestamp);
-
-    ALOGV("offset = %zu, cnt %" PRId64 ", token %" PRId32 ", type %" PRId32 ", timestamp %" PRId64,
-        offset, atomicCounter, token, type, timestamp);
-
-    Event event = {
-      .timestamp = timestamp,
-      .sensorHandle = token,
-      .sensorType = static_cast<SensorType>(type),
-    };
-    event.u.data = android::hardware::hidl_array<float, 16>
-        (reinterpret_cast<float*>(mBuffer + offset + kOffsetData));
-
-    events.push_back(event);
-
-    lastCounter = atomicCounter;
-    offset += kEventSize;
-  }
-
-  return events;
-}
-
-SensorsTestSharedMemory::SensorsTestSharedMemory(SharedMemType type, size_t size)
-    : mType(type), mSize(0), mBuffer(nullptr) {
-  native_handle_t *handle = nullptr;
-  char *buffer = nullptr;
-  switch(type) {
-    case SharedMemType::ASHMEM: {
-      int fd;
-      handle = ::native_handle_create(1 /*nFds*/, 0/*nInts*/);
-      if (handle != nullptr) {
-        handle->data[0] = fd = ::ashmem_create_region("SensorsTestSharedMemory", size);
-        if (handle->data[0] > 0) {
-          // memory is pinned by default
-          buffer = static_cast<char *>
-              (::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
-          if (buffer != reinterpret_cast<char*>(MAP_FAILED)) {
-            break;
-          }
-          ::native_handle_close(handle);
-        }
-        ::native_handle_delete(handle);
-        handle = nullptr;
-      }
-      break;
-    }
-    case SharedMemType::GRALLOC: {
-      mGrallocWrapper = std::make_unique<GrallocWrapper>();
-      if (mGrallocWrapper->getAllocator() == nullptr || mGrallocWrapper->getMapper() == nullptr) {
-        break;
-      }
-      using android::hardware::graphics::common::V1_0::BufferUsage;
-      using android::hardware::graphics::common::V1_0::PixelFormat;
-      mapper2::IMapper::BufferDescriptorInfo buf_desc_info = {
-        .width = static_cast<uint32_t>(size),
-        .height = 1,
-        .layerCount = 1,
-        .usage = static_cast<uint64_t> (BufferUsage::SENSOR_DIRECT_DATA |
-            BufferUsage::CPU_READ_OFTEN),
-        .format = PixelFormat::BLOB
-      };
-
-      handle = const_cast<native_handle_t *>(mGrallocWrapper->allocate(buf_desc_info));
-      if (handle != nullptr) {
-        mapper2::IMapper::Rect region{0, 0,
-            static_cast<int32_t>(buf_desc_info.width),
-            static_cast<int32_t>(buf_desc_info.height)};
-        buffer = static_cast<char *>
-                (mGrallocWrapper->lock(handle, buf_desc_info.usage, region, /*fence=*/-1));
-        if (buffer != nullptr) {
-          break;
-        }
-        mGrallocWrapper->freeBuffer(handle);
-        handle = nullptr;
-      }
-      break;
-    }
-    default:
-      break;
-  }
-
-  if (buffer != nullptr) {
-    mNativeHandle = handle;
-    mSize = size;
-    mBuffer = buffer;
-  }
-}
-
-SensorsTestSharedMemory::~SensorsTestSharedMemory() {
-  switch(mType) {
-    case SharedMemType::ASHMEM: {
-      if (mSize != 0) {
-        ::munmap(mBuffer, mSize);
-        mBuffer = nullptr;
-
-        ::native_handle_close(mNativeHandle);
-        ::native_handle_delete(mNativeHandle);
-
-        mNativeHandle = nullptr;
-        mSize = 0;
-      }
-      break;
-    }
-    case SharedMemType::GRALLOC: {
-      if (mSize != 0) {
-        mGrallocWrapper->unlock(mNativeHandle);
-        mGrallocWrapper->freeBuffer(mNativeHandle);
-
-        mNativeHandle = nullptr;
-        mSize = 0;
-      }
-      break;
-    }
-    default: {
-      if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr) {
-        ALOGE("SensorsTestSharedMemory %p not properly destructed: "
-            "type %d, native handle %p, size %zu, buffer %p",
-            this, static_cast<int>(mType), mNativeHandle, mSize, mBuffer);
-      }
-      break;
-    }
-  }
-}
-
-SensorsTestSharedMemory* SensorsTestSharedMemory::create(SharedMemType type, size_t size) {
-  constexpr size_t kMaxSize = 128*1024*1024; // sensor test should not need more than 128M
-  if (size == 0 || size >= kMaxSize) {
-    return nullptr;
-  }
-
-  auto m = new SensorsTestSharedMemory(type, size);
-  if (m->mSize != size || m->mBuffer == nullptr) {
-    delete m;
-    m = nullptr;
-  }
-  return m;
-}
-
-class SensorEventsChecker {
- public:
-  virtual bool check(const std::vector<Event> &events, std::string *out) const = 0;
-  virtual ~SensorEventsChecker() {}
-};
-
-class NullChecker : public SensorEventsChecker {
- public:
-  virtual bool check(const std::vector<Event> &, std::string *) const {
-    return true;
-  }
-};
-
-class SensorEventPerEventChecker : public SensorEventsChecker {
- public:
-  virtual bool checkEvent(const Event &event, std::string *out) const = 0;
-  virtual bool check(const std::vector<Event> &events, std::string *out) const {
-    for (const auto &e : events) {
-      if (!checkEvent(e, out)) {
-        return false;
-      }
-    }
-    return true;
-  }
-};
-
-class Vec3NormChecker : public SensorEventPerEventChecker {
- public:
-  Vec3NormChecker(float min, float max) : mRange(min, max) {}
-  static Vec3NormChecker byNominal(float nominal, float allowedError) {
-    return Vec3NormChecker(nominal - allowedError, nominal + allowedError);
-  }
-
-  virtual bool checkEvent(const Event &event, std::string *out) const {
-    Vec3 v = event.u.vec3;
-    float norm = std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
-    if (norm < mRange.first || norm > mRange.second) {
-      if (out != nullptr) {
-        std::ostringstream ss;
-        ss << "Event @ " << event.timestamp << " (" << v.x << ", " << v.y << ", " << v.z << ")"
-           << " has norm " << norm << ", which is beyond range"
-           << " [" << mRange.first << ", " << mRange.second << "]";
-        *out = ss.str();
-      }
-      return false;
-    }
-    return true;
-  }
- protected:
-  std::pair<float, float> mRange;
-};
-
 // The main test class for SENSORS HIDL HAL.
-class SensorsHidlTest : public ::testing::VtsHalHidlTargetTestBase {
- public:
-  virtual void SetUp() override {
-  }
 
-  virtual void TearDown() override {
-    // stop all sensors
-    for (auto s : mSensorHandles) {
-      S()->activate(s, false);
+class SensorsHidlTest : public SensorsHidlTestBase {
+   protected:
+    SensorInfo defaultSensorByType(SensorType type) override;
+    std::vector<SensorInfo> getSensorsList();
+    // implementation wrapper
+    Return<void> getSensorsList(ISensors::getSensorsList_cb _hidl_cb) override {
+        return S()->getSensorsList(_hidl_cb);
     }
-    mSensorHandles.clear();
 
-    // stop all direct report and channels
-    for (auto c : mDirectChannelHandles) {
-      // disable all reports
-      S()->configDirectReport(-1, c, RateLevel::STOP, [] (auto, auto){});
-      S()->unregisterDirectChannel(c);
+    Return<Result> activate(int32_t sensorHandle, bool enabled) override;
+
+    Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+                         int64_t maxReportLatencyNs) override {
+        return S()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs);
     }
-    mDirectChannelHandles.clear();
-  }
 
- protected:
-  SensorInfo defaultSensorByType(SensorType type);
-  std::vector<SensorInfo> getSensorsList();
-  std::vector<Event> collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
-        bool clearBeforeStart = true, bool changeCollection = true);
+    Return<Result> flush(int32_t sensorHandle) override { return S()->flush(sensorHandle); }
 
-  // implementation wrapper
-  Return<void> getSensorsList(ISensors::getSensorsList_cb _hidl_cb) {
-    return S()->getSensorsList(_hidl_cb);
-  }
+    Return<Result> injectSensorData(const Event& event) override {
+        return S()->injectSensorData(event);
+    }
 
-  Return<Result> activate(
-          int32_t sensorHandle, bool enabled);
+    Return<void> registerDirectChannel(const SharedMemInfo& mem,
+                                       ISensors::registerDirectChannel_cb _hidl_cb) override;
 
-  Return<Result> batch(
-          int32_t sensorHandle,
-          int64_t samplingPeriodNs,
-          int64_t maxReportLatencyNs) {
-    return S()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs);
-  }
+    Return<Result> unregisterDirectChannel(int32_t channelHandle) override {
+        return S()->unregisterDirectChannel(channelHandle);
+    }
 
-  Return<Result> flush(int32_t sensorHandle) {
-    return S()->flush(sensorHandle);
-  }
+    Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
+                                    ISensors::configDirectReport_cb _hidl_cb) override {
+        return S()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
+    }
 
-  Return<Result> injectSensorData(const Event& event) {
-    return S()->injectSensorData(event);
-  }
+    inline sp<ISensors>& S() { return SensorsHidlEnvironmentV1_0::Instance()->sensors; }
 
-  Return<void> registerDirectChannel(
-          const SharedMemInfo& mem, ISensors::registerDirectChannel_cb _hidl_cb);
-
-  Return<Result> unregisterDirectChannel(int32_t channelHandle) {
-    return S()->unregisterDirectChannel(channelHandle);
-  }
-
-  Return<void> configDirectReport(
-          int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
-          ISensors::configDirectReport_cb _hidl_cb) {
-    return S()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
-  }
-
-  inline sp<ISensors>& S() {
-    return SensorsHidlEnvironment::Instance()->sensors;
-  }
-
-  inline static SensorFlagBits extractReportMode(uint64_t flag) {
-    return (SensorFlagBits) (flag
-        & ((uint64_t) SensorFlagBits::CONTINUOUS_MODE
-          | (uint64_t) SensorFlagBits::ON_CHANGE_MODE
-          | (uint64_t) SensorFlagBits::ONE_SHOT_MODE
-          | (uint64_t) SensorFlagBits::SPECIAL_REPORTING_MODE));
-  }
-
-  inline static bool isMetaSensorType(SensorType type) {
-    return (type == SensorType::META_DATA
-            || type == SensorType::DYNAMIC_SENSOR_META
-            || type == SensorType::ADDITIONAL_INFO);
-  }
-
-  inline static bool isValidType(SensorType type) {
-    return (int32_t) type > 0;
-  }
-
-  void testStreamingOperation(SensorType type,
-                              std::chrono::nanoseconds samplingPeriod,
-                              std::chrono::seconds duration,
-                              const SensorEventsChecker &checker);
-  void testSamplingRateHotSwitchOperation(SensorType type, bool fastToSlow = true);
-  void testBatchingOperation(SensorType type);
-  void testDirectReportOperation(
-      SensorType type, SharedMemType memType, RateLevel rate, const SensorEventsChecker &checker);
-
-  static void assertTypeMatchStringType(SensorType type, const hidl_string& stringType);
-  static void assertTypeMatchReportMode(SensorType type, SensorFlagBits reportMode);
-  static void assertDelayMatchReportMode(
-          int32_t minDelay, int32_t maxDelay, SensorFlagBits reportMode);
-  static SensorFlagBits expectedReportModeForType(SensorType type);
-  static bool isDirectReportRateSupported(SensorInfo sensor, RateLevel rate);
-  static bool isDirectChannelTypeSupported(SensorInfo sensor, SharedMemType type);
-
-  // checkers
-  static const Vec3NormChecker sAccelNormChecker;
-  static const Vec3NormChecker sGyroNormChecker;
-
-  // all sensors and direct channnels used
-  std::unordered_set<int32_t> mSensorHandles;
-  std::unordered_set<int32_t> mDirectChannelHandles;
+    SensorsHidlEnvironmentBase* getEnvironment() override {
+        return SensorsHidlEnvironmentV1_0::Instance();
+    }
 };
 
-const Vec3NormChecker SensorsHidlTest::sAccelNormChecker(
-        Vec3NormChecker::byNominal(GRAVITY_EARTH, 1.0f/*m/s^2*/));
-const Vec3NormChecker SensorsHidlTest::sGyroNormChecker(
-        Vec3NormChecker::byNominal(0.f, 0.1f/*rad/s*/));
-
 Return<Result> SensorsHidlTest::activate(int32_t sensorHandle, bool enabled) {
   // If activating a sensor, add the handle in a set so that when test fails it can be turned off.
   // The handle is not removed when it is deactivating on purpose so that it is not necessary to
@@ -618,195 +101,6 @@
   return Void();
 }
 
-std::vector<Event> SensorsHidlTest::collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
-      bool clearBeforeStart, bool changeCollection) {
-  std::vector<Event> events;
-  constexpr useconds_t SLEEP_GRANULARITY = 100*1000; //granularity 100 ms
-
-  ALOGI("collect max of %zu events for %d us, clearBeforeStart %d",
-        nEventLimit, timeLimitUs, clearBeforeStart);
-
-  if (changeCollection) {
-    SensorsHidlEnvironment::Instance()->setCollection(true);
-  }
-  if (clearBeforeStart) {
-    SensorsHidlEnvironment::Instance()->catEvents(nullptr);
-  }
-
-  while (timeLimitUs > 0) {
-    useconds_t duration = std::min(SLEEP_GRANULARITY, timeLimitUs);
-    usleep(duration);
-    timeLimitUs -= duration;
-
-    SensorsHidlEnvironment::Instance()->catEvents(&events);
-    if (events.size() >= nEventLimit) {
-      break;
-    }
-    ALOGV("time to go = %d, events to go = %d",
-          (int)timeLimitUs, (int)(nEventLimit - events.size()));
-  }
-
-  if (changeCollection) {
-    SensorsHidlEnvironment::Instance()->setCollection(false);
-  }
-  return events;
-}
-
-void SensorsHidlTest::assertTypeMatchStringType(SensorType type, const hidl_string& stringType) {
-
-  if (type >= SensorType::DEVICE_PRIVATE_BASE) {
-    return;
-  }
-
-  switch (type) {
-#define CHECK_TYPE_STRING_FOR_SENSOR_TYPE(type) \
-    case SensorType::type: ASSERT_STREQ(SENSOR_STRING_TYPE_ ## type, stringType.c_str()); break;
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER_UNCALIBRATED);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ADDITIONAL_INFO);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(AMBIENT_TEMPERATURE);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DEVICE_ORIENTATION);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DYNAMIC_SENSOR_META);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GAME_ROTATION_VECTOR);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GEOMAGNETIC_ROTATION_VECTOR);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GLANCE_GESTURE);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GRAVITY);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE_UNCALIBRATED);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_BEAT);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_RATE);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LIGHT);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LINEAR_ACCELERATION);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LOW_LATENCY_OFFBODY_DETECT);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD_UNCALIBRATED);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MOTION_DETECT);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ORIENTATION);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PICK_UP_GESTURE);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(POSE_6DOF);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PRESSURE);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PROXIMITY);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(RELATIVE_HUMIDITY);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ROTATION_VECTOR);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(SIGNIFICANT_MOTION);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STATIONARY_DETECT);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_COUNTER);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_DETECTOR);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TEMPERATURE);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TILT_DETECTOR);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WAKE_GESTURE);
-    CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WRIST_TILT_GESTURE);
-    default:
-      FAIL() << "Type " << static_cast<int>(type) << " in android defined range is not checked, "
-             << "stringType = " << stringType;
-#undef CHECK_TYPE_STRING_FOR_SENSOR_TYPE
-  }
-}
-
-void SensorsHidlTest::assertTypeMatchReportMode(SensorType type, SensorFlagBits reportMode) {
-  if (type >= SensorType::DEVICE_PRIVATE_BASE) {
-    return;
-  }
-
-  SensorFlagBits expected = expectedReportModeForType(type);
-
-  ASSERT_TRUE(expected == (SensorFlagBits) -1 || expected == reportMode)
-      << "reportMode=" << static_cast<int>(reportMode)
-      << "expected=" << static_cast<int>(expected);
-}
-
-void SensorsHidlTest::assertDelayMatchReportMode(
-    int32_t minDelay, int32_t maxDelay, SensorFlagBits reportMode) {
-  switch(reportMode) {
-    case SensorFlagBits::CONTINUOUS_MODE:
-      ASSERT_LT(0, minDelay);
-      ASSERT_LE(0, maxDelay);
-      break;
-    case SensorFlagBits::ON_CHANGE_MODE:
-      ASSERT_LE(0, minDelay);
-      ASSERT_LE(0, maxDelay);
-      break;
-    case SensorFlagBits::ONE_SHOT_MODE:
-      ASSERT_EQ(-1, minDelay);
-      ASSERT_EQ(0, maxDelay);
-      break;
-    case SensorFlagBits::SPECIAL_REPORTING_MODE:
-      // do not enforce anything for special reporting mode
-      break;
-    default:
-      FAIL() << "Report mode " << static_cast<int>(reportMode) << " not checked";
-  }
-}
-
-// return -1 means no expectation for this type
-SensorFlagBits SensorsHidlTest::expectedReportModeForType(SensorType type) {
-  switch (type) {
-    case SensorType::ACCELEROMETER:
-    case SensorType::ACCELEROMETER_UNCALIBRATED:
-    case SensorType::GYROSCOPE:
-    case SensorType::MAGNETIC_FIELD:
-    case SensorType::ORIENTATION:
-    case SensorType::PRESSURE:
-    case SensorType::TEMPERATURE:
-    case SensorType::GRAVITY:
-    case SensorType::LINEAR_ACCELERATION:
-    case SensorType::ROTATION_VECTOR:
-    case SensorType::MAGNETIC_FIELD_UNCALIBRATED:
-    case SensorType::GAME_ROTATION_VECTOR:
-    case SensorType::GYROSCOPE_UNCALIBRATED:
-    case SensorType::GEOMAGNETIC_ROTATION_VECTOR:
-    case SensorType::POSE_6DOF:
-    case SensorType::HEART_BEAT:
-      return SensorFlagBits::CONTINUOUS_MODE;
-
-    case SensorType::LIGHT:
-    case SensorType::PROXIMITY:
-    case SensorType::RELATIVE_HUMIDITY:
-    case SensorType::AMBIENT_TEMPERATURE:
-    case SensorType::HEART_RATE:
-    case SensorType::DEVICE_ORIENTATION:
-    case SensorType::STEP_COUNTER:
-    case SensorType::LOW_LATENCY_OFFBODY_DETECT:
-      return SensorFlagBits::ON_CHANGE_MODE;
-
-    case SensorType::SIGNIFICANT_MOTION:
-    case SensorType::WAKE_GESTURE:
-    case SensorType::GLANCE_GESTURE:
-    case SensorType::PICK_UP_GESTURE:
-    case SensorType::MOTION_DETECT:
-    case SensorType::STATIONARY_DETECT:
-      return SensorFlagBits::ONE_SHOT_MODE;
-
-    case SensorType::STEP_DETECTOR:
-    case SensorType::TILT_DETECTOR:
-    case SensorType::WRIST_TILT_GESTURE:
-    case SensorType::DYNAMIC_SENSOR_META:
-      return SensorFlagBits::SPECIAL_REPORTING_MODE;
-
-    default:
-      ALOGW("Type %d is not implemented in expectedReportModeForType", (int)type);
-      return (SensorFlagBits)-1;
-  }
-}
-
-bool SensorsHidlTest::isDirectReportRateSupported(SensorInfo sensor, RateLevel rate) {
-  unsigned int r =
-      static_cast<unsigned int>(sensor.flags & SensorFlagBits::MASK_DIRECT_REPORT)
-        >> static_cast<unsigned int>(SensorFlagShift::DIRECT_REPORT);
-  return r >= static_cast<unsigned int>(rate);
-}
-
-bool SensorsHidlTest::isDirectChannelTypeSupported(SensorInfo sensor, SharedMemType type) {
-  switch (type) {
-    case SharedMemType::ASHMEM:
-      return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_ASHMEM) != 0;
-    case SharedMemType::GRALLOC:
-      return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_GRALLOC) != 0;
-    default:
-      return false;
-  }
-}
-
 SensorInfo SensorsHidlTest::defaultSensorByType(SensorType type) {
   SensorInfo ret;
 
@@ -951,69 +245,6 @@
     ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::NORMAL));
 }
 
-void SensorsHidlTest::testStreamingOperation(SensorType type,
-                                             std::chrono::nanoseconds samplingPeriod,
-                                             std::chrono::seconds duration,
-                                             const SensorEventsChecker &checker) {
-  std::vector<Event> events;
-  std::vector<Event> sensorEvents;
-
-  const int64_t samplingPeriodInNs = samplingPeriod.count();
-  const int64_t batchingPeriodInNs = 0; // no batching
-  const useconds_t minTimeUs = std::chrono::microseconds(duration).count();
-  const size_t minNEvent = duration / samplingPeriod;
-
-  SensorInfo sensor = defaultSensorByType(type);
-
-  if (!isValidType(sensor.type)) {
-    // no default sensor of this type
-    return;
-  }
-
-  if (std::chrono::microseconds(sensor.minDelay) > samplingPeriod) {
-    // rate not supported
-    return;
-  }
-
-  int32_t handle = sensor.sensorHandle;
-
-  ASSERT_EQ(batch(handle, samplingPeriodInNs, batchingPeriodInNs), Result::OK);
-  ASSERT_EQ(activate(handle, 1), Result::OK);
-  events = collectEvents(minTimeUs, minNEvent, true /*clearBeforeStart*/);
-  ASSERT_EQ(activate(handle, 0), Result::OK);
-
-  ALOGI("Collected %zu samples", events.size());
-
-  ASSERT_GT(events.size(), 0u);
-
-  bool handleMismatchReported = false;
-  bool metaSensorTypeErrorReported = false;
-  for (auto & e : events) {
-    if (e.sensorType == type) {
-      // avoid generating hundreds of error
-      if (!handleMismatchReported) {
-        EXPECT_EQ(e.sensorHandle, handle)
-            << (handleMismatchReported = true,
-                "Event of the same type must come from the sensor registered");
-      }
-      sensorEvents.push_back(e);
-    } else {
-      // avoid generating hundreds of error
-      if (!metaSensorTypeErrorReported) {
-        EXPECT_TRUE(isMetaSensorType(e.sensorType))
-            << (metaSensorTypeErrorReported = true,
-                "Only meta types are allowed besides the type registered");
-      }
-    }
-  }
-
-  std::string s;
-  EXPECT_TRUE(checker.check(sensorEvents, &s)) << s;
-
-  EXPECT_GE(sensorEvents.size(),
-            minNEvent / 2);  // make sure returned events are not all meta
-}
-
 // Test if sensor hal can do UI speed accelerometer streaming properly
 TEST_F(SensorsHidlTest, AccelerometerStreamingOperationSlow) {
   testStreamingOperation(SensorType::ACCELEROMETER,
@@ -1086,103 +317,6 @@
                          NullChecker());
 }
 
-void SensorsHidlTest::testSamplingRateHotSwitchOperation(SensorType type, bool fastToSlow) {
-  std::vector<Event> events1, events2;
-
-  constexpr int64_t batchingPeriodInNs = 0; // no batching
-  constexpr int64_t collectionTimeoutUs = 60000000; // 60s
-  constexpr size_t minNEvent = 50;
-
-  SensorInfo sensor = defaultSensorByType(type);
-
-  if (!isValidType(sensor.type)) {
-    // no default sensor of this type
-    return;
-  }
-
-  int32_t handle = sensor.sensorHandle;
-  int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll;
-  int64_t maxSamplingPeriodInNs = sensor.maxDelay * 1000ll;
-
-  if (minSamplingPeriodInNs == maxSamplingPeriodInNs) {
-    // only support single rate
-    return;
-  }
-
-  int64_t firstCollectionPeriod = fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs;
-  int64_t secondCollectionPeriod = !fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs;
-
-  // first collection
-  ASSERT_EQ(batch(handle, firstCollectionPeriod, batchingPeriodInNs), Result::OK);
-  ASSERT_EQ(activate(handle, 1), Result::OK);
-
-  usleep(500000); // sleep 0.5 sec to wait for change rate to happen
-  events1 = collectEvents(collectionTimeoutUs, minNEvent);
-
-  // second collection, without stop sensor
-  ASSERT_EQ(batch(handle, secondCollectionPeriod, batchingPeriodInNs), Result::OK);
-
-  usleep(500000); // sleep 0.5 sec to wait for change rate to happen
-  events2 = collectEvents(collectionTimeoutUs, minNEvent);
-
-  // end of collection, stop sensor
-  ASSERT_EQ(activate(handle, 0), Result::OK);
-
-  ALOGI("Collected %zu fast samples and %zu slow samples", events1.size(), events2.size());
-
-  ASSERT_GT(events1.size(), 0u);
-  ASSERT_GT(events2.size(), 0u);
-
-  int64_t minDelayAverageInterval, maxDelayAverageInterval;
-  std::vector<Event> &minDelayEvents(fastToSlow ? events1 : events2);
-  std::vector<Event> &maxDelayEvents(fastToSlow ? events2 : events1);
-
-  size_t nEvent = 0;
-  int64_t prevTimestamp = -1;
-  int64_t timestampInterval = 0;
-  for (auto & e : minDelayEvents) {
-    if (e.sensorType == type) {
-      ASSERT_EQ(e.sensorHandle, handle);
-      if (prevTimestamp > 0) {
-        timestampInterval += e.timestamp - prevTimestamp;
-      }
-      prevTimestamp = e.timestamp;
-      ++ nEvent;
-    }
-  }
-  ASSERT_GT(nEvent, 2u);
-  minDelayAverageInterval = timestampInterval / (nEvent - 1);
-
-  nEvent = 0;
-  prevTimestamp = -1;
-  timestampInterval = 0;
-  for (auto & e : maxDelayEvents) {
-    if (e.sensorType == type) {
-      ASSERT_EQ(e.sensorHandle, handle);
-      if (prevTimestamp > 0) {
-        timestampInterval += e.timestamp - prevTimestamp;
-      }
-      prevTimestamp = e.timestamp;
-      ++ nEvent;
-    }
-  }
-  ASSERT_GT(nEvent, 2u);
-  maxDelayAverageInterval = timestampInterval / (nEvent - 1);
-
-  // change of rate is significant.
-  ALOGI("min/maxDelayAverageInterval = %" PRId64 " %" PRId64,
-      minDelayAverageInterval, maxDelayAverageInterval);
-  EXPECT_GT((maxDelayAverageInterval - minDelayAverageInterval), minDelayAverageInterval / 10);
-
-  // fastest rate sampling time is close to spec
-  EXPECT_LT(std::abs(minDelayAverageInterval - minSamplingPeriodInNs),
-      minSamplingPeriodInNs / 10);
-
-  // slowest rate sampling time is close to spec
-  EXPECT_LT(std::abs(maxDelayAverageInterval - maxSamplingPeriodInNs),
-      maxSamplingPeriodInNs / 10);
-}
-
 // Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active
 TEST_F(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) {
   testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER);
@@ -1201,74 +335,6 @@
   testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD, false /*fastToSlow*/);
 }
 
-void SensorsHidlTest::testBatchingOperation(SensorType type) {
-  std::vector<Event> events;
-
-  constexpr int64_t maxBatchingTestTimeNs = 30ull * 1000 * 1000 * 1000;
-  constexpr int64_t oneSecondInNs = 1ull * 1000 * 1000 * 1000;
-
-  SensorInfo sensor = defaultSensorByType(type);
-
-  if (!isValidType(sensor.type)) {
-    // no default sensor of this type
-    return;
-  }
-
-  int32_t handle = sensor.sensorHandle;
-  int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll;
-  uint32_t minFifoCount = sensor.fifoReservedEventCount;
-  int64_t batchingPeriodInNs = minFifoCount * minSamplingPeriodInNs;
-
-  if (batchingPeriodInNs < oneSecondInNs) {
-    // batching size too small to test reliably
-    return;
-  }
-
-  batchingPeriodInNs = std::min(batchingPeriodInNs, maxBatchingTestTimeNs);
-
-  ALOGI("Test batching for %d ms", (int)(batchingPeriodInNs / 1000 / 1000));
-
-  int64_t allowedBatchDeliverTimeNs =
-      std::max(oneSecondInNs, batchingPeriodInNs / 10);
-
-  ASSERT_EQ(batch(handle, minSamplingPeriodInNs, INT64_MAX), Result::OK);
-  ASSERT_EQ(activate(handle, 1), Result::OK);
-
-  usleep(500000); // sleep 0.5 sec to wait for initialization
-  ASSERT_EQ(flush(handle), Result::OK);
-
-  // wait for 80% of the reserved batching period
-  // there should not be any significant amount of events
-  // since collection is not enabled all events will go down the drain
-  usleep(batchingPeriodInNs / 1000 * 8 / 10);
-
-  SensorsHidlEnvironment::Instance()->setCollection(true);
-  // clean existing collections
-  collectEvents(0 /*timeLimitUs*/, 0/*nEventLimit*/,
-        true /*clearBeforeStart*/, false /*change collection*/);
-
-  // 0.8 + 0.2 times the batching period
-  usleep(batchingPeriodInNs / 1000 * 8 / 10);
-  ASSERT_EQ(flush(handle), Result::OK);
-
-  // plus some time for the event to deliver
-  events = collectEvents(allowedBatchDeliverTimeNs / 1000,
-        minFifoCount, false /*clearBeforeStart*/, false /*change collection*/);
-
-  SensorsHidlEnvironment::Instance()->setCollection(false);
-  ASSERT_EQ(activate(handle, 0), Result::OK);
-
-  size_t nEvent = 0;
-  for (auto & e : events) {
-    if (e.sensorType == type && e.sensorHandle == handle) {
-      ++ nEvent;
-    }
-  }
-
-  // at least reach 90% of advertised capacity
-  ASSERT_GT(nEvent, (size_t)(minFifoCount * 9 / 10));
-}
-
 // Test if sensor hal can do accelerometer batching properly
 TEST_F(SensorsHidlTest, AccelerometerBatchingOperation) {
   testBatchingOperation(SensorType::ACCELEROMETER);
@@ -1284,124 +350,6 @@
   testBatchingOperation(SensorType::MAGNETIC_FIELD);
 }
 
-void SensorsHidlTest::testDirectReportOperation(
-    SensorType type, SharedMemType memType, RateLevel rate, const SensorEventsChecker &checker) {
-  constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
-  constexpr size_t kNEvent = 4096;
-  constexpr size_t kMemSize = kEventSize * kNEvent;
-
-  constexpr float kNormalNominal = 50;
-  constexpr float kFastNominal = 200;
-  constexpr float kVeryFastNominal = 800;
-
-  constexpr float kNominalTestTimeSec = 1.f;
-  constexpr float kMaxTestTimeSec = kNominalTestTimeSec + 0.5f; // 0.5 second for initialization
-
-  SensorInfo sensor = defaultSensorByType(type);
-
-  if (!isValidType(sensor.type)) {
-    // no default sensor of this type
-    return;
-  }
-
-  if (!isDirectReportRateSupported(sensor, rate)) {
-    return;
-  }
-
-  if (!isDirectChannelTypeSupported(sensor, memType)) {
-    return;
-  }
-
-  std::unique_ptr<SensorsTestSharedMemory>
-      mem(SensorsTestSharedMemory::create(memType, kMemSize));
-  ASSERT_NE(mem, nullptr);
-
-  char* buffer = mem->getBuffer();
-  // fill memory with data
-  for (size_t i = 0; i < kMemSize; ++i) {
-    buffer[i] = '\xcc';
-  }
-
-  int32_t channelHandle;
-  registerDirectChannel(mem->getSharedMemInfo(),
-      [&channelHandle] (auto result, auto channelHandle_) {
-          ASSERT_EQ(result, Result::OK);
-          channelHandle = channelHandle_;
-      });
-
-  // check memory is zeroed
-  for (size_t i = 0; i < kMemSize; ++i) {
-    ASSERT_EQ(buffer[i], '\0');
-  }
-
-  int32_t eventToken;
-  configDirectReport(sensor.sensorHandle, channelHandle, rate,
-      [&eventToken] (auto result, auto token) {
-          ASSERT_EQ(result, Result::OK);
-          eventToken = token;
-      });
-
-  usleep(static_cast<useconds_t>(kMaxTestTimeSec * 1e6f));
-  auto events = mem->parseEvents();
-
-  // find norminal rate
-  float nominalFreq = 0.f;
-  switch (rate) {
-      case RateLevel::NORMAL:
-          nominalFreq = kNormalNominal;
-          break;
-      case RateLevel::FAST:
-          nominalFreq = kFastNominal;
-          break;
-      case RateLevel::VERY_FAST:
-          nominalFreq = kVeryFastNominal;
-          break;
-      case RateLevel::STOP:
-          FAIL();
-  }
-
-  // allowed to be between 55% and 220% of nominal freq
-  ASSERT_GT(events.size(), static_cast<size_t>(nominalFreq * 0.55f * kNominalTestTimeSec));
-  ASSERT_LT(events.size(), static_cast<size_t>(nominalFreq * 2.2f * kMaxTestTimeSec));
-
-  int64_t lastTimestamp = 0;
-  bool typeErrorReported = false;
-  bool tokenErrorReported = false;
-  bool timestampErrorReported = false;
-  std::vector<Event> sensorEvents;
-  for (auto &e : events) {
-    if (!tokenErrorReported) {
-      EXPECT_EQ(eventToken, e.sensorHandle)
-          << (tokenErrorReported = true,
-            "Event token does not match that retured from configDirectReport");
-    }
-
-    if (isMetaSensorType(e.sensorType)) {
-        continue;
-    }
-    sensorEvents.push_back(e);
-
-    if (!typeErrorReported) {
-      EXPECT_EQ(type, e.sensorType)
-          << (typeErrorReported = true,
-              "Type in event does not match type of sensor registered.");
-    }
-    if (!timestampErrorReported) {
-      EXPECT_GT(e.timestamp, lastTimestamp)
-          << (timestampErrorReported = true, "Timestamp not monotonically increasing");
-    }
-    lastTimestamp = e.timestamp;
-  }
-
-  std::string s;
-  EXPECT_TRUE(checker.check(sensorEvents, &s)) << s;
-
-  // stop sensor and unregister channel
-  configDirectReport(sensor.sensorHandle, channelHandle, RateLevel::STOP,
-                     [](auto result, auto) { EXPECT_EQ(result, Result::OK); });
-  EXPECT_EQ(unregisterDirectChannel(channelHandle), Result::OK);
-}
-
 // Test sensor event direct report with ashmem for accel sensor at normal rate
 TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) {
   testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::NORMAL,
@@ -1511,11 +459,11 @@
 }
 
 int main(int argc, char **argv) {
-  ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironment::Instance());
-  ::testing::InitGoogleTest(&argc, argv);
-  SensorsHidlEnvironment::Instance()->init(&argc, argv);
-  int status = RUN_ALL_TESTS();
-  ALOGI("Test result = %d", status);
-  return status;
+    ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironmentV1_0::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    SensorsHidlEnvironmentV1_0::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
 }
 // vim: set ts=2 sw=2
diff --git a/sensors/2.0/Android.bp b/sensors/2.0/Android.bp
new file mode 100644
index 0000000..3b948a9
--- /dev/null
+++ b/sensors/2.0/Android.bp
@@ -0,0 +1,24 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.sensors@2.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "ISensors.hal",
+        "ISensorsCallback.hal",
+    ],
+    interfaces: [
+        "android.hardware.sensors@1.0",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "EventQueueFlagBits",
+        "SensorTimeout",
+    ],
+    gen_java: false,
+}
+
diff --git a/sensors/2.0/ISensors.hal b/sensors/2.0/ISensors.hal
new file mode 100644
index 0000000..939bf73
--- /dev/null
+++ b/sensors/2.0/ISensors.hal
@@ -0,0 +1,255 @@
+/*
+ * 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.sensors@2.0;
+
+import @1.0::Event;
+import @1.0::OperationMode;
+import @1.0::RateLevel;
+import @1.0::Result;
+import @1.0::SensorInfo;
+import @1.0::SharedMemInfo;
+import @2.0::ISensorsCallback;
+
+interface ISensors {
+    /**
+     * Enumerate all available (static) sensors.
+     *
+     * The SensorInfo for each sensor returned by getSensorsList must be stable
+     * from the initial call to getSensorsList after a device boot until the
+     * entire system restarts. The SensorInfo for each sensor must not change
+     * between subsequent calls to getSensorsList, even across restarts of the
+     * HAL and its dependencies (for example, the sensor handle for a given
+     * sensor must not change across HAL restarts).
+     */
+    getSensorsList() generates (vec<SensorInfo> list);
+
+    /**
+     * Place the module in a specific mode. The following modes are defined
+     *
+     *  SENSOR_HAL_NORMAL_MODE - Normal operation. Default state of the module.
+     *
+     *  SENSOR_HAL_DATA_INJECTION_MODE - Loopback mode.
+     *    Data is injected for the supported sensors by the sensor service in
+     *    this mode.
+     *
+     * @return OK on success
+     *     BAD_VALUE if requested mode is not supported
+     *     PERMISSION_DENIED if operation is not allowed
+     */
+    setOperationMode(OperationMode mode) generates (Result result);
+
+    /**
+     * Activate/de-activate one sensor.
+     *
+     * After sensor de-activation, existing sensor events that have not
+     * been written to the event queue must be abandoned immediately so that
+     * subsequent activations do not get stale sensor events (events
+     * that are generated prior to the latter activation).
+     *
+     * @param sensorHandle is the handle of the sensor to change.
+     * @param enabled set to true to enable, or false to disable the sensor.
+     * @return result OK on success, BAD_VALUE if sensorHandle is invalid.
+     */
+    activate(int32_t sensorHandle, bool enabled) generates (Result result);
+
+    /**
+     * Initialize the Sensors HAL's Fast Message Queues (FMQ) and callback.
+     *
+     * The Fast Message Queues (FMQ) that are used to send data between the
+     * framework and the HAL. The callback is used by the HAL to notify the
+     * framework of asynchronous events, such as a dynamic sensor connection.
+     *
+     * The Event FMQ is used to transport sensor events from the HAL to the
+     * framework. The Event FMQ is created using the eventQueueDescriptor.
+     * Data may only be written to the Event FMQ. Data must not be read from
+     * the Event FMQ since the framework is the only reader. Upon receiving
+     * sensor events, the HAL should write the sensor events to the Event FMQ.
+     * Once the HAL is finished writing sensor events to the Event FMQ, the HAL
+     * must call the Event FMQ's EventFlag wake() function with the
+     * EventQueueFlagBits::READ_AND_PROCESS mask which notifies the framework
+     * that sensor events are available to be read and processed.
+     *
+     * The Wake Lock FMQ is used by the framework to notify the HAL when it is
+     * safe to release its wake_lock. When the framework receives WAKE_UP events
+     * from the Event FMQ and the framework has acquired a wake_lock, the
+     * framework must write a WakeLockEvent to the Wake Lock FMQ with the number
+     * of WAKE_UP events processed. When the HAL reads the WakeLockEvent from
+     * the Wake Lock FMQ, the HAL should decrement its current count of
+     * unprocessed WAKE_UP events and release its wake_lock if the current
+     * count of unprocessed WAKE_UP events is zero.
+     *
+     * The ISensorsCallback is used by the HAL to notify the framework of
+     * asynchronous events, such as a dynamic sensor connection.
+     *
+     * The name of any wake_lock acquired by the Sensors HAL for WAKE_UP events
+     * must begin with "SensorsHAL_WAKEUP".
+     *
+     * If WAKE_LOCK_TIMEOUT_SECONDS has elapsed since the most recent WAKE_UP
+     * event was written to the Event FMQ without receiving a message on the
+     * Wake Lock FMQ, then any held wake_lock for WAKE_UP events must be
+     * released.
+     *
+     * If either the Event FMQ or the Wake Lock FMQ is already initialized when
+     * initialize is invoked, then both existing FMQs must be discarded and the
+     * new descriptors must be used to create new FMQs within the HAL. The
+     * number of outstanding WAKE_UP events should also be reset to zero, and
+     * any outstanding wake_locks held as a result of WAKE_UP events should be
+     * released.
+     *
+     * initialize must be thread safe and prevent concurrent calls
+     * to initialize from simultaneously modifying state.
+     *
+     * @param eventQueueDescriptor Fast Message Queue descriptor that is used to
+     *     create the Event FMQ which is where sensor events are written. The
+     *     descriptor is obtained from the framework's FMQ that is used to read
+     *     sensor events.
+     * @param wakeLockDescriptor Fast Message Queue descriptor that is used to
+     *     create the Wake Lock FMQ which is where wake_lock events are read
+     *     from. The descriptor is obtained from the framework's FMQ that is
+     *     used to write wake_lock events.
+     * @param sensorsCallback sensors callback that receives asynchronous data
+     *     from the Sensors HAL.
+     * @return result OK on success; BAD_VALUE if descriptor is invalid (such
+     *     as null)
+     */
+    @entry
+    @callflow(next = {"getSensorsList"})
+    initialize(fmq_sync<Event> eventQueueDescriptor,
+               fmq_sync<uint32_t> wakeLockDescriptor,
+               ISensorsCallback sensorsCallback)
+        generates
+              (Result result);
+
+    /**
+     * Sets a sensor’s parameters, including sampling frequency and maximum
+     * report latency. This function can be called while the sensor is
+     * activated, in which case it must not cause any sensor measurements to
+     * be lost: transitioning from one sampling rate to the other cannot cause
+     * lost events, nor can transitioning from a high maximum report latency to
+     * a low maximum report latency.
+     *
+     * @param sensorHandle handle of sensor to be changed.
+     * @param samplingPeriodNs specifies sensor sample period in nanoseconds.
+     * @param maxReportLatencyNs allowed delay time before an event is sampled
+     *     to time of report.
+     * @return result OK on success, BAD_VALUE if any parameters are invalid.
+     */
+    batch(int32_t sensorHandle,
+          int64_t samplingPeriodNs,
+          int64_t maxReportLatencyNs)
+        generates (
+          Result result);
+
+    /**
+     * Trigger a flush of internal FIFO.
+     *
+     * Flush adds a FLUSH_COMPLETE metadata event to the end of the "batch mode"
+     * FIFO for the specified sensor and flushes the FIFO.  If the FIFO is empty
+     * or if the sensor doesn't support batching (FIFO size zero), return
+     * SUCCESS and add a trivial FLUSH_COMPLETE event added to the event stream.
+     * This applies to all sensors other than one-shot sensors. If the sensor
+     * is a one-shot sensor, flush must return BAD_VALUE and not generate any
+     * flush complete metadata.  If the sensor is not active at the time flush()
+     * is called, flush() return BAD_VALUE.
+     *
+     * @param sensorHandle handle of sensor to be flushed.
+     * @return result OK on success and BAD_VALUE if sensorHandle is invalid.
+     */
+    flush(int32_t sensorHandle) generates (Result result);
+
+    /**
+     * Inject a single sensor event or push operation environment parameters to
+     * device.
+     *
+     * When device is in NORMAL mode, this function is called to push operation
+     * environment data to device. In this operation, Event is always of
+     * SensorType::AdditionalInfo type. See operation evironment parameters
+     * section in AdditionalInfoType.
+     *
+     * When device is in DATA_INJECTION mode, this function is also used for
+     * injecting sensor events.
+     *
+     * Regardless of OperationMode, injected SensorType::ADDITIONAL_INFO
+     * type events should not be routed back to the sensor event queue.
+     *
+     * @see AdditionalInfoType
+     * @see OperationMode
+     * @param event sensor event to be injected
+     * @return result OK on success; PERMISSION_DENIED if operation is not
+     *     allowed; INVALID_OPERATION, if this functionality is unsupported;
+     *     BAD_VALUE if sensor event cannot be injected.
+     */
+    injectSensorData(Event event) generates (Result result);
+
+    /**
+     * Register direct report channel.
+     *
+     * Register a direct channel with supplied shared memory information. Upon
+     * return, the sensor hardware is responsible for resetting the memory
+     * content to initial value (depending on memory format settings).
+     *
+     * @param mem shared memory info data structure.
+     * @return result OK on success; BAD_VALUE if shared memory information is
+     *     not consistent; NO_MEMORY if shared memory cannot be used by sensor
+     *     system; INVALID_OPERATION if functionality is not supported.
+     * @return channelHandle a positive integer used for referencing registered
+     *     direct channel (>0) in configureDirectReport and
+     *     unregisterDirectChannel if result is OK, -1 otherwise.
+     */
+    registerDirectChannel(SharedMemInfo mem)
+               generates (Result result,
+                          int32_t channelHandle);
+
+    /**
+     * Unregister direct report channel.
+     *
+     * Unregister a direct channel previously registered using
+     * registerDirectChannel, and remove all active sensor report configured in
+     * still active sensor report configured in the direct channel.
+     *
+     * @param channelHandle handle of direct channel to be unregistered.
+     * @return result OK if direct report is supported; INVALID_OPERATION
+     *     otherwise.
+     */
+    unregisterDirectChannel(int32_t channelHandle) generates (Result result);
+
+    /**
+     * Configure direct sensor event report in direct channel.
+     *
+     * This function start, modify rate or stop direct report of a sensor in a
+     * certain direct channel.
+     *
+     * @param sensorHandle handle of sensor to be configured. When combined
+     *     with STOP rate, sensorHandle can be -1 to denote all active sensors
+     *     in the direct channel specified by channel Handle.
+     * @param channelHandle handle of direct channel to be configured.
+     * @param rate rate level, see RateLevel enum.
+     * @return result OK on success; BAD_VALUE if parameter is invalid (such as
+     *     rate level is not supported by sensor, channelHandle does not exist,
+     *     etc); INVALID_OPERATION if functionality is not supported.
+     * @return reportToken positive integer to identify multiple sensors of
+     *     the same type in a single direct channel. Ignored if rate is STOP.
+     *     See SharedMemFormat.
+     */
+    configDirectReport(
+            int32_t sensorHandle,
+            int32_t channelHandle,
+            RateLevel rate
+        ) generates (
+            Result result,
+            int32_t reportToken);
+};
diff --git a/sensors/2.0/ISensorsCallback.hal b/sensors/2.0/ISensorsCallback.hal
new file mode 100644
index 0000000..e0bd98f
--- /dev/null
+++ b/sensors/2.0/ISensorsCallback.hal
@@ -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.
+ */
+
+package android.hardware.sensors@2.0;
+
+import @1.0::SensorInfo;
+
+interface ISensorsCallback {
+    /**
+     * Notify the framework that new dynamic sensors have been connected.
+     *
+     * If a dynamic sensor was previously connected and has not been
+     * disconnected, then that sensor must not be included in sensorInfos.
+     *
+     * @param sensorInfos vector of SensorInfo for each dynamic sensor that
+     *     was connected.
+     */
+    oneway onDynamicSensorsConnected(vec<SensorInfo> sensorInfos);
+
+    /**
+     * Notify the framework that previously connected dynamic sensors have been
+     * disconnected.
+     *
+     * If a dynamic sensor was previously disconnected and has not been
+     * reconnected, then that sensor must not be included in sensorHandles.
+     *
+     * The HAL must ensure that all sensor events from departing dynamic
+     * sensors have been written to the Event FMQ before calling
+     * onDynamicSensorsDisconnected.
+     *
+     * @param sensorHandles vector of sensor handles for each dynamic sensors
+     *     that was disconnected.
+     */
+    oneway onDynamicSensorsDisconnected(vec<int32_t> sensorHandles);
+};
diff --git a/health/filesystem/1.0/types.hal b/sensors/2.0/types.hal
similarity index 61%
copy from health/filesystem/1.0/types.hal
copy to sensors/2.0/types.hal
index 00431f7..e1a029a 100644
--- a/health/filesystem/1.0/types.hal
+++ b/sensors/2.0/types.hal
@@ -14,26 +14,19 @@
  * limitations under the License.
  */
 
-package android.hardware.health.filesystem@1.0;
+package android.hardware.sensors@2.0;
 
-/**
- * Status values for HAL methods.
- */
-enum Result : uint32_t {
+enum SensorTimeout : int32_t {
     /**
-     * Execution of the method is successful.
+     * The maximum number of seconds to wait for a message on the Wake Lock FMQ
+     * before automatically releasing any wake_lock held for a WAKE_UP event.
      */
-    SUCCESS = 0,
+    WAKE_LOCK_SECONDS = 1,
+};
+
+enum EventQueueFlagBits : uint32_t {
     /**
-     * Execution of the method timed out.
+     * Used to notify the Event FMQ that events should be read and processed.
      */
-    TIMEOUT,
-    /**
-     * An IO error is encountered when the HAL communicates with the device.
-     */
-    IO_ERROR,
-    /**
-     * An unknown error is encountered.
-     */
-    UNKNOWN_ERROR,
+    READ_AND_PROCESS = 1 << 0,
 };
diff --git a/sensors/2.0/vts/functional/Android.bp b/sensors/2.0/vts/functional/Android.bp
new file mode 100644
index 0000000..9b8e3d4
--- /dev/null
+++ b/sensors/2.0/vts/functional/Android.bp
@@ -0,0 +1,32 @@
+//
+// 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: "VtsHalSensorsV2_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "SensorsHidlEnvironmentV2_0.cpp",
+        "VtsHalSensorsV2_0TargetTest.cpp"
+    ],
+    static_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.sensors@1.0",
+        "android.hardware.sensors@2.0",
+        "VtsHalSensorsTargetTestUtils",
+    ],
+}
+
diff --git a/sensors/2.0/vts/functional/OWNERS b/sensors/2.0/vts/functional/OWNERS
new file mode 100644
index 0000000..759d87b
--- /dev/null
+++ b/sensors/2.0/vts/functional/OWNERS
@@ -0,0 +1,7 @@
+# Sensors team
+bduddie@google.com
+bstack@google.com
+
+# VTS team
+trong@google.com
+yim@google.com
diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
new file mode 100644
index 0000000..20d0838
--- /dev/null
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
@@ -0,0 +1,93 @@
+/*
+ * 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 "SensorsHidlEnvironmentV2_0.h"
+
+#include <log/log.h>
+
+#include <vector>
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::sensors::V1_0::Result;
+using ::android::hardware::sensors::V1_0::SensorInfo;
+using ::android::hardware::sensors::V2_0::ISensors;
+
+bool SensorsHidlEnvironmentV2_0::resetHal() {
+    std::string step;
+    bool succeed = false;
+    do {
+        step = "getService()";
+        sensors = ISensors::getService(
+            SensorsHidlEnvironmentV2_0::Instance()->getServiceName<ISensors>());
+        if (sensors == nullptr) {
+            break;
+        }
+
+        step = "getSensorList";
+        std::vector<SensorInfo> sensorList;
+        if (!sensors
+                 ->getSensorsList([&](const hidl_vec<SensorInfo>& list) {
+                     sensorList.reserve(list.size());
+                     for (size_t i = 0; i < list.size(); ++i) {
+                         sensorList.push_back(list[i]);
+                     }
+                 })
+                 .isOk()) {
+            break;
+        }
+
+        // stop each sensor individually
+        step = "stop each sensor";
+        bool ok = true;
+        for (const auto& i : sensorList) {
+            if (!sensors->activate(i.sensorHandle, false).isOk()) {
+                ok = false;
+                break;
+            }
+        }
+        if (!ok) {
+            break;
+        }
+
+        // mark it done
+        step = "done";
+        succeed = true;
+    } while (0);
+
+    if (succeed) {
+        return true;
+    }
+
+    sensors = nullptr;
+    return false;
+}
+
+void SensorsHidlEnvironmentV2_0::startPollingThread() {
+    stopThread = false;
+    pollThread = std::thread(pollingThread, this, std::ref(stopThread));
+    events.reserve(128);
+}
+
+void SensorsHidlEnvironmentV2_0::pollingThread(SensorsHidlEnvironmentV2_0* /*env*/,
+                                               std::atomic_bool& stop) {
+    ALOGD("polling thread start");
+
+    while (!stop) {
+        // TODO: implement reading event queue
+        stop = true;
+    }
+    ALOGD("polling thread end");
+}
diff --git a/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h
new file mode 100644
index 0000000..43ddd23
--- /dev/null
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h
@@ -0,0 +1,59 @@
+/*
+ * 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_SENSORS_HIDL_ENVIRONMENT_V2_0_H
+#define ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_0_H
+
+#include "sensors-vts-utils/SensorsHidlEnvironmentBase.h"
+
+#include <android/hardware/sensors/1.0/types.h>
+#include <android/hardware/sensors/2.0/ISensors.h>
+#include <utils/StrongPointer.h>
+
+#include <atomic>
+#include <memory>
+
+using ::android::sp;
+
+class SensorsHidlTest;
+class SensorsHidlEnvironmentV2_0 : public SensorsHidlEnvironmentBase {
+   public:
+    using Event = ::android::hardware::sensors::V1_0::Event;
+    // get the test environment singleton
+    static SensorsHidlEnvironmentV2_0* Instance() {
+        static SensorsHidlEnvironmentV2_0* instance = new SensorsHidlEnvironmentV2_0();
+        return instance;
+    }
+
+    virtual void registerTestServices() override {
+        registerTestService<android::hardware::sensors::V2_0::ISensors>();
+    }
+
+   private:
+    friend SensorsHidlTest;
+    // sensors hidl service
+    sp<android::hardware::sensors::V2_0::ISensors> sensors;
+
+    SensorsHidlEnvironmentV2_0() {}
+
+    bool resetHal() override;
+    void startPollingThread() override;
+    static void pollingThread(SensorsHidlEnvironmentV2_0* env, std::atomic_bool& stop);
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentV2_0);
+};
+
+#endif  // ANDROID_SENSORS_HIDL_ENVIRONMENT_V2_0_H
diff --git a/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
new file mode 100644
index 0000000..204d7b2
--- /dev/null
+++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
@@ -0,0 +1,446 @@
+/*
+ * 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 "sensors_hidl_hal_test"
+
+#include "SensorsHidlEnvironmentV2_0.h"
+#include "sensors-vts-utils/SensorsHidlTestBase.h"
+
+#include <android/hardware/sensors/2.0/ISensors.h>
+#include <android/hardware/sensors/2.0/types.h>
+#include <log/log.h>
+#include <utils/SystemClock.h>
+
+#include <cinttypes>
+#include <vector>
+
+using ::android::sp;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::sensors::V1_0::OperationMode;
+using ::android::hardware::sensors::V1_0::SensorStatus;
+using ::android::hardware::sensors::V1_0::Vec3;
+
+// The main test class for SENSORS HIDL HAL.
+
+class SensorsHidlTest : public SensorsHidlTestBase {
+   protected:
+    SensorInfo defaultSensorByType(SensorType type) override;
+    std::vector<SensorInfo> getSensorsList();
+    // implementation wrapper
+    Return<void> getSensorsList(ISensors::getSensorsList_cb _hidl_cb) override {
+        return S()->getSensorsList(_hidl_cb);
+    }
+
+    Return<Result> activate(int32_t sensorHandle, bool enabled) override;
+
+    Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+                         int64_t maxReportLatencyNs) override {
+        return S()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs);
+    }
+
+    Return<Result> flush(int32_t sensorHandle) override { return S()->flush(sensorHandle); }
+
+    Return<Result> injectSensorData(const Event& event) override {
+        return S()->injectSensorData(event);
+    }
+
+    Return<void> registerDirectChannel(const SharedMemInfo& mem,
+                                       ISensors::registerDirectChannel_cb _hidl_cb) override;
+
+    Return<Result> unregisterDirectChannel(int32_t channelHandle) override {
+        return S()->unregisterDirectChannel(channelHandle);
+    }
+
+    Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
+                                    ISensors::configDirectReport_cb _hidl_cb) override {
+        return S()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
+    }
+
+    inline sp<::android::hardware::sensors::V2_0::ISensors>& S() {
+        return SensorsHidlEnvironmentV2_0::Instance()->sensors;
+    }
+
+    SensorsHidlEnvironmentBase* getEnvironment() override {
+        return SensorsHidlEnvironmentV2_0::Instance();
+    }
+};
+
+Return<Result> SensorsHidlTest::activate(int32_t sensorHandle, bool enabled) {
+    // If activating a sensor, add the handle in a set so that when test fails it can be turned off.
+    // The handle is not removed when it is deactivating on purpose so that it is not necessary to
+    // check the return value of deactivation. Deactivating a sensor more than once does not have
+    // negative effect.
+    if (enabled) {
+        mSensorHandles.insert(sensorHandle);
+    }
+    return S()->activate(sensorHandle, enabled);
+}
+
+Return<void> SensorsHidlTest::registerDirectChannel(const SharedMemInfo& mem,
+                                                    ISensors::registerDirectChannel_cb cb) {
+    // If registeration of a channel succeeds, add the handle of channel to a set so that it can be
+    // unregistered when test fails. Unregister a channel does not remove the handle on purpose.
+    // Unregistering a channel more than once should not have negative effect.
+    S()->registerDirectChannel(mem, [&](auto result, auto channelHandle) {
+        if (result == Result::OK) {
+            mDirectChannelHandles.insert(channelHandle);
+        }
+        cb(result, channelHandle);
+    });
+    return Void();
+}
+
+SensorInfo SensorsHidlTest::defaultSensorByType(SensorType type) {
+    SensorInfo ret;
+
+    ret.type = (SensorType)-1;
+    S()->getSensorsList([&](const auto& list) {
+        const size_t count = list.size();
+        for (size_t i = 0; i < count; ++i) {
+            if (list[i].type == type) {
+                ret = list[i];
+                return;
+            }
+        }
+    });
+
+    return ret;
+}
+
+std::vector<SensorInfo> SensorsHidlTest::getSensorsList() {
+    std::vector<SensorInfo> ret;
+
+    S()->getSensorsList([&](const auto& list) {
+        const size_t count = list.size();
+        ret.reserve(list.size());
+        for (size_t i = 0; i < count; ++i) {
+            ret.push_back(list[i]);
+        }
+    });
+
+    return ret;
+}
+
+// Test if sensor list returned is valid
+TEST_F(SensorsHidlTest, SensorListValid) {
+    S()->getSensorsList([&](const auto& list) {
+        const size_t count = list.size();
+        for (size_t i = 0; i < count; ++i) {
+            const auto& s = list[i];
+            SCOPED_TRACE(::testing::Message()
+                         << i << "/" << count << ": "
+                         << " handle=0x" << std::hex << std::setw(8) << std::setfill('0')
+                         << s.sensorHandle << std::dec << " type=" << static_cast<int>(s.type)
+                         << " name=" << s.name);
+
+            // Test non-empty type string
+            EXPECT_FALSE(s.typeAsString.empty());
+
+            // Test defined type matches defined string type
+            EXPECT_NO_FATAL_FAILURE(assertTypeMatchStringType(s.type, s.typeAsString));
+
+            // Test if all sensor has name and vendor
+            EXPECT_FALSE(s.name.empty());
+            EXPECT_FALSE(s.vendor.empty());
+
+            // Test power > 0, maxRange > 0
+            EXPECT_LE(0, s.power);
+            EXPECT_LT(0, s.maxRange);
+
+            // Info type, should have no sensor
+            EXPECT_FALSE(s.type == SensorType::ADDITIONAL_INFO || s.type == SensorType::META_DATA);
+
+            // Test fifoMax >= fifoReserved
+            EXPECT_GE(s.fifoMaxEventCount, s.fifoReservedEventCount)
+                << "max=" << s.fifoMaxEventCount << " reserved=" << s.fifoReservedEventCount;
+
+            // Test Reporting mode valid
+            EXPECT_NO_FATAL_FAILURE(assertTypeMatchReportMode(s.type, extractReportMode(s.flags)));
+
+            // Test min max are in the right order
+            EXPECT_LE(s.minDelay, s.maxDelay);
+            // Test min/max delay matches reporting mode
+            EXPECT_NO_FATAL_FAILURE(
+                assertDelayMatchReportMode(s.minDelay, s.maxDelay, extractReportMode(s.flags)));
+        }
+    });
+}
+
+// Test if sensor list returned is valid
+TEST_F(SensorsHidlTest, SetOperationMode) {
+    std::vector<SensorInfo> sensorList = getSensorsList();
+
+    bool needOperationModeSupport =
+        std::any_of(sensorList.begin(), sensorList.end(),
+                    [](const auto& s) { return (s.flags & SensorFlagBits::DATA_INJECTION) != 0; });
+    if (!needOperationModeSupport) {
+        return;
+    }
+
+    ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::NORMAL));
+    ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::DATA_INJECTION));
+    ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::NORMAL));
+}
+
+// Test if sensor list returned is valid
+TEST_F(SensorsHidlTest, InjectSensorEventData) {
+    std::vector<SensorInfo> sensorList = getSensorsList();
+    std::vector<SensorInfo> sensorSupportInjection;
+
+    bool needOperationModeSupport =
+        std::any_of(sensorList.begin(), sensorList.end(), [&sensorSupportInjection](const auto& s) {
+            bool ret = (s.flags & SensorFlagBits::DATA_INJECTION) != 0;
+            if (ret) {
+                sensorSupportInjection.push_back(s);
+            }
+            return ret;
+        });
+    if (!needOperationModeSupport) {
+        return;
+    }
+
+    ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::NORMAL));
+    ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::DATA_INJECTION));
+
+    for (const auto& s : sensorSupportInjection) {
+        switch (s.type) {
+            case SensorType::ACCELEROMETER:
+            case SensorType::GYROSCOPE:
+            case SensorType::MAGNETIC_FIELD: {
+                usleep(100000);  // sleep 100ms
+
+                Event dummy;
+                dummy.timestamp = android::elapsedRealtimeNano();
+                dummy.sensorType = s.type;
+                dummy.sensorHandle = s.sensorHandle;
+                Vec3 v = {1, 2, 3, SensorStatus::ACCURACY_HIGH};
+                dummy.u.vec3 = v;
+
+                EXPECT_EQ(Result::OK, S()->injectSensorData(dummy));
+                break;
+            }
+            default:
+                break;
+        }
+    }
+    ASSERT_EQ(Result::OK, S()->setOperationMode(OperationMode::NORMAL));
+}
+
+// Test if sensor hal can do UI speed accelerometer streaming properly
+TEST_F(SensorsHidlTest, AccelerometerStreamingOperationSlow) {
+    testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(200),
+                           std::chrono::seconds(5), sAccelNormChecker);
+}
+
+// Test if sensor hal can do normal speed accelerometer streaming properly
+TEST_F(SensorsHidlTest, AccelerometerStreamingOperationNormal) {
+    testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(20),
+                           std::chrono::seconds(5), sAccelNormChecker);
+}
+
+// Test if sensor hal can do game speed accelerometer streaming properly
+TEST_F(SensorsHidlTest, AccelerometerStreamingOperationFast) {
+    testStreamingOperation(SensorType::ACCELEROMETER, std::chrono::milliseconds(5),
+                           std::chrono::seconds(5), sAccelNormChecker);
+}
+
+// Test if sensor hal can do UI speed gyroscope streaming properly
+TEST_F(SensorsHidlTest, GyroscopeStreamingOperationSlow) {
+    testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(200),
+                           std::chrono::seconds(5), sGyroNormChecker);
+}
+
+// Test if sensor hal can do normal speed gyroscope streaming properly
+TEST_F(SensorsHidlTest, GyroscopeStreamingOperationNormal) {
+    testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(20),
+                           std::chrono::seconds(5), sGyroNormChecker);
+}
+
+// Test if sensor hal can do game speed gyroscope streaming properly
+TEST_F(SensorsHidlTest, GyroscopeStreamingOperationFast) {
+    testStreamingOperation(SensorType::GYROSCOPE, std::chrono::milliseconds(5),
+                           std::chrono::seconds(5), sGyroNormChecker);
+}
+
+// Test if sensor hal can do UI speed magnetometer streaming properly
+TEST_F(SensorsHidlTest, MagnetometerStreamingOperationSlow) {
+    testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(200),
+                           std::chrono::seconds(5), NullChecker());
+}
+
+// Test if sensor hal can do normal speed magnetometer streaming properly
+TEST_F(SensorsHidlTest, MagnetometerStreamingOperationNormal) {
+    testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(20),
+                           std::chrono::seconds(5), NullChecker());
+}
+
+// Test if sensor hal can do game speed magnetometer streaming properly
+TEST_F(SensorsHidlTest, MagnetometerStreamingOperationFast) {
+    testStreamingOperation(SensorType::MAGNETIC_FIELD, std::chrono::milliseconds(5),
+                           std::chrono::seconds(5), NullChecker());
+}
+
+// Test if sensor hal can do accelerometer sampling rate switch properly when sensor is active
+TEST_F(SensorsHidlTest, AccelerometerSamplingPeriodHotSwitchOperation) {
+    testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER);
+    testSamplingRateHotSwitchOperation(SensorType::ACCELEROMETER, false /*fastToSlow*/);
+}
+
+// Test if sensor hal can do gyroscope sampling rate switch properly when sensor is active
+TEST_F(SensorsHidlTest, GyroscopeSamplingPeriodHotSwitchOperation) {
+    testSamplingRateHotSwitchOperation(SensorType::GYROSCOPE);
+    testSamplingRateHotSwitchOperation(SensorType::GYROSCOPE, false /*fastToSlow*/);
+}
+
+// Test if sensor hal can do magnetometer sampling rate switch properly when sensor is active
+TEST_F(SensorsHidlTest, MagnetometerSamplingPeriodHotSwitchOperation) {
+    testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD);
+    testSamplingRateHotSwitchOperation(SensorType::MAGNETIC_FIELD, false /*fastToSlow*/);
+}
+
+// Test if sensor hal can do accelerometer batching properly
+TEST_F(SensorsHidlTest, AccelerometerBatchingOperation) {
+    testBatchingOperation(SensorType::ACCELEROMETER);
+}
+
+// Test if sensor hal can do gyroscope batching properly
+TEST_F(SensorsHidlTest, GyroscopeBatchingOperation) {
+    testBatchingOperation(SensorType::GYROSCOPE);
+}
+
+// Test if sensor hal can do magnetometer batching properly
+TEST_F(SensorsHidlTest, MagnetometerBatchingOperation) {
+    testBatchingOperation(SensorType::MAGNETIC_FIELD);
+}
+
+// Test sensor event direct report with ashmem for accel sensor at normal rate
+TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::NORMAL,
+                              sAccelNormChecker);
+}
+
+// Test sensor event direct report with ashmem for accel sensor at fast rate
+TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM, RateLevel::FAST,
+                              sAccelNormChecker);
+}
+
+// Test sensor event direct report with ashmem for accel sensor at very fast rate
+TEST_F(SensorsHidlTest, AccelerometerAshmemDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::ASHMEM,
+                              RateLevel::VERY_FAST, sAccelNormChecker);
+}
+
+// Test sensor event direct report with ashmem for gyro sensor at normal rate
+TEST_F(SensorsHidlTest, GyroscopeAshmemDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::NORMAL,
+                              sGyroNormChecker);
+}
+
+// Test sensor event direct report with ashmem for gyro sensor at fast rate
+TEST_F(SensorsHidlTest, GyroscopeAshmemDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::FAST,
+                              sGyroNormChecker);
+}
+
+// Test sensor event direct report with ashmem for gyro sensor at very fast rate
+TEST_F(SensorsHidlTest, GyroscopeAshmemDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::ASHMEM, RateLevel::VERY_FAST,
+                              sGyroNormChecker);
+}
+
+// Test sensor event direct report with ashmem for mag sensor at normal rate
+TEST_F(SensorsHidlTest, MagnetometerAshmemDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::NORMAL,
+                              NullChecker());
+}
+
+// Test sensor event direct report with ashmem for mag sensor at fast rate
+TEST_F(SensorsHidlTest, MagnetometerAshmemDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM, RateLevel::FAST,
+                              NullChecker());
+}
+
+// Test sensor event direct report with ashmem for mag sensor at very fast rate
+TEST_F(SensorsHidlTest, MagnetometerAshmemDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::ASHMEM,
+                              RateLevel::VERY_FAST, NullChecker());
+}
+
+// Test sensor event direct report with gralloc for accel sensor at normal rate
+TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::NORMAL,
+                              sAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for accel sensor at fast rate
+TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC, RateLevel::FAST,
+                              sAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for accel sensor at very fast rate
+TEST_F(SensorsHidlTest, AccelerometerGrallocDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::ACCELEROMETER, SharedMemType::GRALLOC,
+                              RateLevel::VERY_FAST, sAccelNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at normal rate
+TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::NORMAL,
+                              sGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at fast rate
+TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::FAST,
+                              sGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for gyro sensor at very fast rate
+TEST_F(SensorsHidlTest, GyroscopeGrallocDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::GYROSCOPE, SharedMemType::GRALLOC, RateLevel::VERY_FAST,
+                              sGyroNormChecker);
+}
+
+// Test sensor event direct report with gralloc for mag sensor at normal rate
+TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationNormal) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::NORMAL,
+                              NullChecker());
+}
+
+// Test sensor event direct report with gralloc for mag sensor at fast rate
+TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationFast) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC, RateLevel::FAST,
+                              NullChecker());
+}
+
+// Test sensor event direct report with gralloc for mag sensor at very fast rate
+TEST_F(SensorsHidlTest, MagnetometerGrallocDirectReportOperationVeryFast) {
+    testDirectReportOperation(SensorType::MAGNETIC_FIELD, SharedMemType::GRALLOC,
+                              RateLevel::VERY_FAST, NullChecker());
+}
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(SensorsHidlEnvironmentV2_0::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    SensorsHidlEnvironmentV2_0::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    ALOGI("Test result = %d", status);
+    return status;
+}
+// vim: set ts=2 sw=2
diff --git a/sensors/common/vts/OWNERS b/sensors/common/vts/OWNERS
new file mode 100644
index 0000000..759d87b
--- /dev/null
+++ b/sensors/common/vts/OWNERS
@@ -0,0 +1,7 @@
+# Sensors team
+bduddie@google.com
+bstack@google.com
+
+# VTS team
+trong@google.com
+yim@google.com
diff --git a/sensors/common/vts/utils/Android.bp b/sensors/common/vts/utils/Android.bp
new file mode 100644
index 0000000..95df425
--- /dev/null
+++ b/sensors/common/vts/utils/Android.bp
@@ -0,0 +1,37 @@
+//
+// 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_library_static {
+    name: "VtsHalSensorsTargetTestUtils",
+    srcs: [
+        "GrallocWrapper.cpp",
+        "SensorsHidlEnvironmentBase.cpp",
+        "SensorsHidlTestBase.cpp",
+        "SensorsTestSharedMemory.cpp",
+    ],
+    export_include_dirs: [
+        "include",
+    ],
+    local_include_dirs: [
+        "include/sensors-vts-utils",
+    ],
+    static_libs: [
+        "android.hardware.graphics.allocator@2.0",
+        "android.hardware.graphics.mapper@2.0",
+        "android.hardware.sensors@1.0",
+        "VtsHalHidlTargetTestBase",
+    ],
+}
diff --git a/sensors/common/vts/utils/GrallocWrapper.cpp b/sensors/common/vts/utils/GrallocWrapper.cpp
new file mode 100644
index 0000000..7bed16d
--- /dev/null
+++ b/sensors/common/vts/utils/GrallocWrapper.cpp
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "GrallocWrapper"
+
+#include "GrallocWrapper.h"
+
+#include <utils/Log.h>
+
+namespace android {
+
+GrallocWrapper::GrallocWrapper() {
+    init();
+}
+
+void GrallocWrapper::init() {
+    mAllocator = allocator2::IAllocator::getService();
+    if (mAllocator == nullptr) {
+        ALOGE("Failed to get allocator service");
+    }
+
+    mMapper = mapper2::IMapper::getService();
+    if (mMapper == nullptr) {
+        ALOGE("Failed to get mapper service");
+    }
+    if (mMapper->isRemote()) {
+        ALOGE("Mapper is not in passthrough mode");
+    }
+}
+
+GrallocWrapper::~GrallocWrapper() {
+    for (auto bufferHandle : mClonedBuffers) {
+        auto buffer = const_cast<native_handle_t*>(bufferHandle);
+        native_handle_close(buffer);
+        native_handle_delete(buffer);
+    }
+    mClonedBuffers.clear();
+
+    for (auto bufferHandle : mImportedBuffers) {
+        auto buffer = const_cast<native_handle_t*>(bufferHandle);
+        if (mMapper->freeBuffer(buffer) != mapper2::Error::NONE) {
+            ALOGE("Failed to free buffer %p", buffer);
+        }
+    }
+    mImportedBuffers.clear();
+}
+
+sp<allocator2::IAllocator> GrallocWrapper::getAllocator() const {
+    return mAllocator;
+}
+
+std::string GrallocWrapper::dumpDebugInfo() {
+    std::string debugInfo;
+    mAllocator->dumpDebugInfo([&](const auto& tmpDebugInfo) { debugInfo = tmpDebugInfo.c_str(); });
+
+    return debugInfo;
+}
+
+const native_handle_t* GrallocWrapper::cloneBuffer(const hardware::hidl_handle& rawHandle) {
+    const native_handle_t* bufferHandle = native_handle_clone(rawHandle.getNativeHandle());
+
+    if (bufferHandle) {
+        mClonedBuffers.insert(bufferHandle);
+    }
+    return bufferHandle;
+}
+
+std::vector<const native_handle_t*> GrallocWrapper::allocate(
+    const mapper2::BufferDescriptor& descriptor, uint32_t count, bool import, uint32_t* outStride) {
+    std::vector<const native_handle_t*> bufferHandles;
+    bufferHandles.reserve(count);
+    mAllocator->allocate(descriptor, count,
+                         [&](const auto& tmpError, const auto& tmpStride, const auto& tmpBuffers) {
+                             if (mapper2::Error::NONE != tmpError) {
+                                 ALOGE("Failed to allocate buffers");
+                             }
+                             if (count != tmpBuffers.size()) {
+                                 ALOGE("Invalid buffer array");
+                             }
+
+                             for (uint32_t i = 0; i < count; i++) {
+                                 if (import) {
+                                     bufferHandles.push_back(importBuffer(tmpBuffers[i]));
+                                 } else {
+                                     bufferHandles.push_back(cloneBuffer(tmpBuffers[i]));
+                                 }
+                             }
+
+                             if (outStride) {
+                                 *outStride = tmpStride;
+                             }
+                         });
+
+    return bufferHandles;
+}
+
+const native_handle_t* GrallocWrapper::allocate(
+    const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo, bool import,
+    uint32_t* outStride) {
+    mapper2::BufferDescriptor descriptor = createDescriptor(descriptorInfo);
+    auto buffers = allocate(descriptor, 1, import, outStride);
+    return buffers[0];
+}
+
+sp<mapper2::IMapper> GrallocWrapper::getMapper() const {
+    return mMapper;
+}
+
+mapper2::BufferDescriptor GrallocWrapper::createDescriptor(
+    const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo) {
+    mapper2::BufferDescriptor descriptor;
+    mMapper->createDescriptor(descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
+        if (tmpError != mapper2::Error::NONE) {
+            ALOGE("Failed to create descriptor");
+        }
+        descriptor = tmpDescriptor;
+    });
+
+    return descriptor;
+}
+
+const native_handle_t* GrallocWrapper::importBuffer(const hardware::hidl_handle& rawHandle) {
+    const native_handle_t* bufferHandle = nullptr;
+    mMapper->importBuffer(rawHandle, [&](const auto& tmpError, const auto& tmpBuffer) {
+        if (tmpError != mapper2::Error::NONE) {
+            ALOGE("Failed to import buffer %p", rawHandle.getNativeHandle());
+        }
+        bufferHandle = static_cast<const native_handle_t*>(tmpBuffer);
+    });
+
+    if (bufferHandle) {
+        mImportedBuffers.insert(bufferHandle);
+    }
+
+    return bufferHandle;
+}
+
+void GrallocWrapper::freeBuffer(const native_handle_t* bufferHandle) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    if (mImportedBuffers.erase(bufferHandle)) {
+        mapper2::Error error = mMapper->freeBuffer(buffer);
+        if (error != mapper2::Error::NONE) {
+            ALOGE("Failed to free %p", buffer);
+        }
+    } else {
+        mClonedBuffers.erase(bufferHandle);
+        native_handle_close(buffer);
+        native_handle_delete(buffer);
+    }
+}
+
+void* GrallocWrapper::lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+                           const mapper2::IMapper::Rect& accessRegion, int acquireFence) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    NATIVE_HANDLE_DECLARE_STORAGE(acquireFenceStorage, 1, 0);
+    hardware::hidl_handle acquireFenceHandle;
+    if (acquireFence >= 0) {
+        auto h = native_handle_init(acquireFenceStorage, 1, 0);
+        h->data[0] = acquireFence;
+        acquireFenceHandle = h;
+    }
+
+    void* data = nullptr;
+    mMapper->lock(buffer, cpuUsage, accessRegion, acquireFenceHandle,
+                  [&](const auto& tmpError, const auto& tmpData) {
+                      if (tmpError != mapper2::Error::NONE) {
+                          ALOGE("Failed to lock buffer %p", buffer);
+                      }
+                      data = tmpData;
+                  });
+
+    if (acquireFence >= 0) {
+        close(acquireFence);
+    }
+
+    return data;
+}
+
+int GrallocWrapper::unlock(const native_handle_t* bufferHandle) {
+    auto buffer = const_cast<native_handle_t*>(bufferHandle);
+
+    int releaseFence = -1;
+    mMapper->unlock(buffer, [&](const auto& tmpError, const auto& tmpReleaseFence) {
+        if (tmpError != mapper2::Error::NONE) {
+            ALOGE("Failed to unlock buffer %p", buffer);
+        }
+
+        auto fenceHandle = tmpReleaseFence.getNativeHandle();
+        if (fenceHandle) {
+            if (fenceHandle->numInts != 0) {
+                ALOGE("Invalid fence handle %p", fenceHandle);
+            }
+            if (fenceHandle->numFds == 1) {
+                releaseFence = dup(fenceHandle->data[0]);
+                if (releaseFence < 0) {
+                    ALOGE("Failed to dup fence fd");
+                }
+            } else {
+                if (fenceHandle->numFds != 0) {
+                    ALOGE("Invalid fence handle %p", fenceHandle);
+                }
+            }
+        }
+    });
+
+    return releaseFence;
+}
+
+}  // namespace android
diff --git a/sensors/common/vts/utils/OWNERS b/sensors/common/vts/utils/OWNERS
new file mode 100644
index 0000000..759d87b
--- /dev/null
+++ b/sensors/common/vts/utils/OWNERS
@@ -0,0 +1,7 @@
+# Sensors team
+bduddie@google.com
+bstack@google.com
+
+# VTS team
+trong@google.com
+yim@google.com
diff --git a/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp b/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp
new file mode 100644
index 0000000..21c08d2
--- /dev/null
+++ b/sensors/common/vts/utils/SensorsHidlEnvironmentBase.cpp
@@ -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.
+ */
+
+#include "SensorsHidlEnvironmentBase.h"
+
+void SensorsHidlEnvironmentBase::HidlSetUp() {
+    ASSERT_TRUE(resetHal()) << "could not get hidl service";
+
+    collectionEnabled = false;
+    startPollingThread();
+
+    // In case framework just stopped for test and there is sensor events in the pipe,
+    // wait some time for those events to be cleared to avoid them messing up the test.
+    std::this_thread::sleep_for(std::chrono::seconds(3));
+}
+
+void SensorsHidlEnvironmentBase::HidlTearDown() {
+    stopThread = true;
+    pollThread.detach();
+}
+
+void SensorsHidlEnvironmentBase::catEvents(std::vector<Event>* output) {
+    std::lock_guard<std::mutex> lock(events_mutex);
+    if (output) {
+        output->insert(output->end(), events.begin(), events.end());
+    }
+    events.clear();
+}
+
+void SensorsHidlEnvironmentBase::setCollection(bool enable) {
+    std::lock_guard<std::mutex> lock(events_mutex);
+    collectionEnabled = enable;
+}
+
+void SensorsHidlEnvironmentBase::addEvent(const Event& ev) {
+    std::lock_guard<std::mutex> lock(events_mutex);
+    if (collectionEnabled) {
+        events.push_back(ev);
+    }
+}
diff --git a/sensors/common/vts/utils/SensorsHidlTestBase.cpp b/sensors/common/vts/utils/SensorsHidlTestBase.cpp
new file mode 100644
index 0000000..b72fdfd
--- /dev/null
+++ b/sensors/common/vts/utils/SensorsHidlTestBase.cpp
@@ -0,0 +1,576 @@
+/*
+ * 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 "SensorsHidlTestBase.h"
+
+#include "sensors-vts-utils/GrallocWrapper.h"
+#include "sensors-vts-utils/SensorsTestSharedMemory.h"
+
+#include <hardware/sensors.h>  // for sensor type strings
+#include <log/log.h>
+#include <utils/SystemClock.h>
+
+#include <cinttypes>
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::sensors::V1_0::SensorFlagShift;
+using ::android::hardware::sensors::V1_0::SensorsEventFormatOffset;
+
+const Vec3NormChecker SensorsHidlTestBase::sAccelNormChecker(
+    Vec3NormChecker::byNominal(GRAVITY_EARTH, 1.0f /*m/s^2*/));
+const Vec3NormChecker SensorsHidlTestBase::sGyroNormChecker(
+    Vec3NormChecker::byNominal(0.f, 0.1f /*rad/s*/));
+
+std::vector<Event> SensorsHidlTestBase::collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
+                                                      bool clearBeforeStart,
+                                                      bool changeCollection) {
+    std::vector<Event> events;
+    constexpr useconds_t SLEEP_GRANULARITY = 100 * 1000;  // granularity 100 ms
+
+    ALOGI("collect max of %zu events for %d us, clearBeforeStart %d", nEventLimit, timeLimitUs,
+          clearBeforeStart);
+
+    if (changeCollection) {
+        getEnvironment()->setCollection(true);
+    }
+    if (clearBeforeStart) {
+        getEnvironment()->catEvents(nullptr);
+    }
+
+    while (timeLimitUs > 0) {
+        useconds_t duration = std::min(SLEEP_GRANULARITY, timeLimitUs);
+        usleep(duration);
+        timeLimitUs -= duration;
+
+        getEnvironment()->catEvents(&events);
+        if (events.size() >= nEventLimit) {
+            break;
+        }
+        ALOGV("time to go = %d, events to go = %d", (int)timeLimitUs,
+              (int)(nEventLimit - events.size()));
+    }
+
+    if (changeCollection) {
+        getEnvironment()->setCollection(false);
+    }
+    return events;
+}
+
+void SensorsHidlTestBase::assertTypeMatchStringType(SensorType type,
+                                                    const hidl_string& stringType) {
+    if (type >= SensorType::DEVICE_PRIVATE_BASE) {
+        return;
+    }
+
+    switch (type) {
+#define CHECK_TYPE_STRING_FOR_SENSOR_TYPE(type)                      \
+    case SensorType::type:                                           \
+        ASSERT_STREQ(SENSOR_STRING_TYPE_##type, stringType.c_str()); \
+        break;
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ACCELEROMETER_UNCALIBRATED);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ADDITIONAL_INFO);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(AMBIENT_TEMPERATURE);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DEVICE_ORIENTATION);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(DYNAMIC_SENSOR_META);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GAME_ROTATION_VECTOR);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GEOMAGNETIC_ROTATION_VECTOR);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GLANCE_GESTURE);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GRAVITY);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(GYROSCOPE_UNCALIBRATED);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_BEAT);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(HEART_RATE);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LIGHT);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LINEAR_ACCELERATION);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(LOW_LATENCY_OFFBODY_DETECT);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MAGNETIC_FIELD_UNCALIBRATED);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(MOTION_DETECT);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ORIENTATION);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PICK_UP_GESTURE);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(POSE_6DOF);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PRESSURE);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(PROXIMITY);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(RELATIVE_HUMIDITY);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(ROTATION_VECTOR);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(SIGNIFICANT_MOTION);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STATIONARY_DETECT);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_COUNTER);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(STEP_DETECTOR);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TEMPERATURE);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(TILT_DETECTOR);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WAKE_GESTURE);
+        CHECK_TYPE_STRING_FOR_SENSOR_TYPE(WRIST_TILT_GESTURE);
+        default:
+            FAIL() << "Type " << static_cast<int>(type)
+                   << " in android defined range is not checked, "
+                   << "stringType = " << stringType;
+#undef CHECK_TYPE_STRING_FOR_SENSOR_TYPE
+    }
+}
+
+void SensorsHidlTestBase::assertTypeMatchReportMode(SensorType type, SensorFlagBits reportMode) {
+    if (type >= SensorType::DEVICE_PRIVATE_BASE) {
+        return;
+    }
+
+    SensorFlagBits expected = expectedReportModeForType(type);
+
+    ASSERT_TRUE(expected == (SensorFlagBits)-1 || expected == reportMode)
+        << "reportMode=" << static_cast<int>(reportMode)
+        << "expected=" << static_cast<int>(expected);
+}
+
+void SensorsHidlTestBase::assertDelayMatchReportMode(int32_t minDelay, int32_t maxDelay,
+                                                     SensorFlagBits reportMode) {
+    switch (reportMode) {
+        case SensorFlagBits::CONTINUOUS_MODE:
+            ASSERT_LT(0, minDelay);
+            ASSERT_LE(0, maxDelay);
+            break;
+        case SensorFlagBits::ON_CHANGE_MODE:
+            ASSERT_LE(0, minDelay);
+            ASSERT_LE(0, maxDelay);
+            break;
+        case SensorFlagBits::ONE_SHOT_MODE:
+            ASSERT_EQ(-1, minDelay);
+            ASSERT_EQ(0, maxDelay);
+            break;
+        case SensorFlagBits::SPECIAL_REPORTING_MODE:
+            // do not enforce anything for special reporting mode
+            break;
+        default:
+            FAIL() << "Report mode " << static_cast<int>(reportMode) << " not checked";
+    }
+}
+
+// return -1 means no expectation for this type
+SensorFlagBits SensorsHidlTestBase::expectedReportModeForType(SensorType type) {
+    switch (type) {
+        case SensorType::ACCELEROMETER:
+        case SensorType::ACCELEROMETER_UNCALIBRATED:
+        case SensorType::GYROSCOPE:
+        case SensorType::MAGNETIC_FIELD:
+        case SensorType::ORIENTATION:
+        case SensorType::PRESSURE:
+        case SensorType::TEMPERATURE:
+        case SensorType::GRAVITY:
+        case SensorType::LINEAR_ACCELERATION:
+        case SensorType::ROTATION_VECTOR:
+        case SensorType::MAGNETIC_FIELD_UNCALIBRATED:
+        case SensorType::GAME_ROTATION_VECTOR:
+        case SensorType::GYROSCOPE_UNCALIBRATED:
+        case SensorType::GEOMAGNETIC_ROTATION_VECTOR:
+        case SensorType::POSE_6DOF:
+        case SensorType::HEART_BEAT:
+            return SensorFlagBits::CONTINUOUS_MODE;
+
+        case SensorType::LIGHT:
+        case SensorType::PROXIMITY:
+        case SensorType::RELATIVE_HUMIDITY:
+        case SensorType::AMBIENT_TEMPERATURE:
+        case SensorType::HEART_RATE:
+        case SensorType::DEVICE_ORIENTATION:
+        case SensorType::STEP_COUNTER:
+        case SensorType::LOW_LATENCY_OFFBODY_DETECT:
+            return SensorFlagBits::ON_CHANGE_MODE;
+
+        case SensorType::SIGNIFICANT_MOTION:
+        case SensorType::WAKE_GESTURE:
+        case SensorType::GLANCE_GESTURE:
+        case SensorType::PICK_UP_GESTURE:
+        case SensorType::MOTION_DETECT:
+        case SensorType::STATIONARY_DETECT:
+            return SensorFlagBits::ONE_SHOT_MODE;
+
+        case SensorType::STEP_DETECTOR:
+        case SensorType::TILT_DETECTOR:
+        case SensorType::WRIST_TILT_GESTURE:
+        case SensorType::DYNAMIC_SENSOR_META:
+            return SensorFlagBits::SPECIAL_REPORTING_MODE;
+
+        default:
+            ALOGW("Type %d is not implemented in expectedReportModeForType", (int)type);
+            return (SensorFlagBits)-1;
+    }
+}
+
+bool SensorsHidlTestBase::isDirectReportRateSupported(SensorInfo sensor, RateLevel rate) {
+    unsigned int r = static_cast<unsigned int>(sensor.flags & SensorFlagBits::MASK_DIRECT_REPORT) >>
+                     static_cast<unsigned int>(SensorFlagShift::DIRECT_REPORT);
+    return r >= static_cast<unsigned int>(rate);
+}
+
+bool SensorsHidlTestBase::isDirectChannelTypeSupported(SensorInfo sensor, SharedMemType type) {
+    switch (type) {
+        case SharedMemType::ASHMEM:
+            return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_ASHMEM) != 0;
+        case SharedMemType::GRALLOC:
+            return (sensor.flags & SensorFlagBits::DIRECT_CHANNEL_GRALLOC) != 0;
+        default:
+            return false;
+    }
+}
+
+void SensorsHidlTestBase::testDirectReportOperation(SensorType type, SharedMemType memType,
+                                                    RateLevel rate,
+                                                    const SensorEventsChecker& checker) {
+    constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
+    constexpr size_t kNEvent = 4096;
+    constexpr size_t kMemSize = kEventSize * kNEvent;
+
+    constexpr float kNormalNominal = 50;
+    constexpr float kFastNominal = 200;
+    constexpr float kVeryFastNominal = 800;
+
+    constexpr float kNominalTestTimeSec = 1.f;
+    constexpr float kMaxTestTimeSec = kNominalTestTimeSec + 0.5f;  // 0.5 second for initialization
+
+    SensorInfo sensor = defaultSensorByType(type);
+
+    if (!isValidType(sensor.type)) {
+        // no default sensor of this type
+        return;
+    }
+
+    if (!isDirectReportRateSupported(sensor, rate)) {
+        return;
+    }
+
+    if (!isDirectChannelTypeSupported(sensor, memType)) {
+        return;
+    }
+
+    std::unique_ptr<SensorsTestSharedMemory> mem(
+        SensorsTestSharedMemory::create(memType, kMemSize));
+    ASSERT_NE(mem, nullptr);
+
+    char* buffer = mem->getBuffer();
+    // fill memory with data
+    for (size_t i = 0; i < kMemSize; ++i) {
+        buffer[i] = '\xcc';
+    }
+
+    int32_t channelHandle;
+    registerDirectChannel(mem->getSharedMemInfo(),
+                          [&channelHandle](auto result, auto channelHandle_) {
+                              ASSERT_EQ(result, Result::OK);
+                              channelHandle = channelHandle_;
+                          });
+
+    // check memory is zeroed
+    for (size_t i = 0; i < kMemSize; ++i) {
+        ASSERT_EQ(buffer[i], '\0');
+    }
+
+    int32_t eventToken;
+    configDirectReport(sensor.sensorHandle, channelHandle, rate,
+                       [&eventToken](auto result, auto token) {
+                           ASSERT_EQ(result, Result::OK);
+                           eventToken = token;
+                       });
+
+    usleep(static_cast<useconds_t>(kMaxTestTimeSec * 1e6f));
+    auto events = mem->parseEvents();
+
+    // find norminal rate
+    float nominalFreq = 0.f;
+    switch (rate) {
+        case RateLevel::NORMAL:
+            nominalFreq = kNormalNominal;
+            break;
+        case RateLevel::FAST:
+            nominalFreq = kFastNominal;
+            break;
+        case RateLevel::VERY_FAST:
+            nominalFreq = kVeryFastNominal;
+            break;
+        case RateLevel::STOP:
+            FAIL();
+    }
+
+    // allowed to be between 55% and 220% of nominal freq
+    ASSERT_GT(events.size(), static_cast<size_t>(nominalFreq * 0.55f * kNominalTestTimeSec));
+    ASSERT_LT(events.size(), static_cast<size_t>(nominalFreq * 2.2f * kMaxTestTimeSec));
+
+    int64_t lastTimestamp = 0;
+    bool typeErrorReported = false;
+    bool tokenErrorReported = false;
+    bool timestampErrorReported = false;
+    std::vector<Event> sensorEvents;
+    for (auto& e : events) {
+        if (!tokenErrorReported) {
+            EXPECT_EQ(eventToken, e.sensorHandle)
+                << (tokenErrorReported = true,
+                    "Event token does not match that retured from configDirectReport");
+        }
+
+        if (isMetaSensorType(e.sensorType)) {
+            continue;
+        }
+        sensorEvents.push_back(e);
+
+        if (!typeErrorReported) {
+            EXPECT_EQ(type, e.sensorType)
+                << (typeErrorReported = true,
+                    "Type in event does not match type of sensor registered.");
+        }
+        if (!timestampErrorReported) {
+            EXPECT_GT(e.timestamp, lastTimestamp)
+                << (timestampErrorReported = true, "Timestamp not monotonically increasing");
+        }
+        lastTimestamp = e.timestamp;
+    }
+
+    std::string s;
+    EXPECT_TRUE(checker.check(sensorEvents, &s)) << s;
+
+    // stop sensor and unregister channel
+    configDirectReport(sensor.sensorHandle, channelHandle, RateLevel::STOP,
+                       [](auto result, auto) { EXPECT_EQ(result, Result::OK); });
+    EXPECT_EQ(unregisterDirectChannel(channelHandle), Result::OK);
+}
+
+void SensorsHidlTestBase::testStreamingOperation(SensorType type,
+                                                 std::chrono::nanoseconds samplingPeriod,
+                                                 std::chrono::seconds duration,
+                                                 const SensorEventsChecker& checker) {
+    std::vector<Event> events;
+    std::vector<Event> sensorEvents;
+
+    const int64_t samplingPeriodInNs = samplingPeriod.count();
+    const int64_t batchingPeriodInNs = 0;  // no batching
+    const useconds_t minTimeUs = std::chrono::microseconds(duration).count();
+    const size_t minNEvent = duration / samplingPeriod;
+
+    SensorInfo sensor = defaultSensorByType(type);
+
+    if (!isValidType(sensor.type)) {
+        // no default sensor of this type
+        return;
+    }
+
+    if (std::chrono::microseconds(sensor.minDelay) > samplingPeriod) {
+        // rate not supported
+        return;
+    }
+
+    int32_t handle = sensor.sensorHandle;
+
+    ASSERT_EQ(batch(handle, samplingPeriodInNs, batchingPeriodInNs), Result::OK);
+    ASSERT_EQ(activate(handle, 1), Result::OK);
+    events = collectEvents(minTimeUs, minNEvent, true /*clearBeforeStart*/);
+    ASSERT_EQ(activate(handle, 0), Result::OK);
+
+    ALOGI("Collected %zu samples", events.size());
+
+    ASSERT_GT(events.size(), 0u);
+
+    bool handleMismatchReported = false;
+    bool metaSensorTypeErrorReported = false;
+    for (auto& e : events) {
+        if (e.sensorType == type) {
+            // avoid generating hundreds of error
+            if (!handleMismatchReported) {
+                EXPECT_EQ(e.sensorHandle, handle)
+                    << (handleMismatchReported = true,
+                        "Event of the same type must come from the sensor registered");
+            }
+            sensorEvents.push_back(e);
+        } else {
+            // avoid generating hundreds of error
+            if (!metaSensorTypeErrorReported) {
+                EXPECT_TRUE(isMetaSensorType(e.sensorType))
+                    << (metaSensorTypeErrorReported = true,
+                        "Only meta types are allowed besides the type registered");
+            }
+        }
+    }
+
+    std::string s;
+    EXPECT_TRUE(checker.check(sensorEvents, &s)) << s;
+
+    EXPECT_GE(sensorEvents.size(),
+              minNEvent / 2);  // make sure returned events are not all meta
+}
+
+void SensorsHidlTestBase::testSamplingRateHotSwitchOperation(SensorType type, bool fastToSlow) {
+    std::vector<Event> events1, events2;
+
+    constexpr int64_t batchingPeriodInNs = 0;          // no batching
+    constexpr int64_t collectionTimeoutUs = 60000000;  // 60s
+    constexpr size_t minNEvent = 50;
+
+    SensorInfo sensor = defaultSensorByType(type);
+
+    if (!isValidType(sensor.type)) {
+        // no default sensor of this type
+        return;
+    }
+
+    int32_t handle = sensor.sensorHandle;
+    int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll;
+    int64_t maxSamplingPeriodInNs = sensor.maxDelay * 1000ll;
+
+    if (minSamplingPeriodInNs == maxSamplingPeriodInNs) {
+        // only support single rate
+        return;
+    }
+
+    int64_t firstCollectionPeriod = fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs;
+    int64_t secondCollectionPeriod = !fastToSlow ? minSamplingPeriodInNs : maxSamplingPeriodInNs;
+
+    // first collection
+    ASSERT_EQ(batch(handle, firstCollectionPeriod, batchingPeriodInNs), Result::OK);
+    ASSERT_EQ(activate(handle, 1), Result::OK);
+
+    usleep(500000);  // sleep 0.5 sec to wait for change rate to happen
+    events1 = collectEvents(collectionTimeoutUs, minNEvent);
+
+    // second collection, without stop sensor
+    ASSERT_EQ(batch(handle, secondCollectionPeriod, batchingPeriodInNs), Result::OK);
+
+    usleep(500000);  // sleep 0.5 sec to wait for change rate to happen
+    events2 = collectEvents(collectionTimeoutUs, minNEvent);
+
+    // end of collection, stop sensor
+    ASSERT_EQ(activate(handle, 0), Result::OK);
+
+    ALOGI("Collected %zu fast samples and %zu slow samples", events1.size(), events2.size());
+
+    ASSERT_GT(events1.size(), 0u);
+    ASSERT_GT(events2.size(), 0u);
+
+    int64_t minDelayAverageInterval, maxDelayAverageInterval;
+    std::vector<Event>& minDelayEvents(fastToSlow ? events1 : events2);
+    std::vector<Event>& maxDelayEvents(fastToSlow ? events2 : events1);
+
+    size_t nEvent = 0;
+    int64_t prevTimestamp = -1;
+    int64_t timestampInterval = 0;
+    for (auto& e : minDelayEvents) {
+        if (e.sensorType == type) {
+            ASSERT_EQ(e.sensorHandle, handle);
+            if (prevTimestamp > 0) {
+                timestampInterval += e.timestamp - prevTimestamp;
+            }
+            prevTimestamp = e.timestamp;
+            ++nEvent;
+        }
+    }
+    ASSERT_GT(nEvent, 2u);
+    minDelayAverageInterval = timestampInterval / (nEvent - 1);
+
+    nEvent = 0;
+    prevTimestamp = -1;
+    timestampInterval = 0;
+    for (auto& e : maxDelayEvents) {
+        if (e.sensorType == type) {
+            ASSERT_EQ(e.sensorHandle, handle);
+            if (prevTimestamp > 0) {
+                timestampInterval += e.timestamp - prevTimestamp;
+            }
+            prevTimestamp = e.timestamp;
+            ++nEvent;
+        }
+    }
+    ASSERT_GT(nEvent, 2u);
+    maxDelayAverageInterval = timestampInterval / (nEvent - 1);
+
+    // change of rate is significant.
+    ALOGI("min/maxDelayAverageInterval = %" PRId64 " %" PRId64, minDelayAverageInterval,
+          maxDelayAverageInterval);
+    EXPECT_GT((maxDelayAverageInterval - minDelayAverageInterval), minDelayAverageInterval / 10);
+
+    // fastest rate sampling time is close to spec
+    EXPECT_LT(std::abs(minDelayAverageInterval - minSamplingPeriodInNs),
+              minSamplingPeriodInNs / 10);
+
+    // slowest rate sampling time is close to spec
+    EXPECT_LT(std::abs(maxDelayAverageInterval - maxSamplingPeriodInNs),
+              maxSamplingPeriodInNs / 10);
+}
+
+void SensorsHidlTestBase::testBatchingOperation(SensorType type) {
+    std::vector<Event> events;
+
+    constexpr int64_t maxBatchingTestTimeNs = 30ull * 1000 * 1000 * 1000;
+    constexpr int64_t oneSecondInNs = 1ull * 1000 * 1000 * 1000;
+
+    SensorInfo sensor = defaultSensorByType(type);
+
+    if (!isValidType(sensor.type)) {
+        // no default sensor of this type
+        return;
+    }
+
+    int32_t handle = sensor.sensorHandle;
+    int64_t minSamplingPeriodInNs = sensor.minDelay * 1000ll;
+    uint32_t minFifoCount = sensor.fifoReservedEventCount;
+    int64_t batchingPeriodInNs = minFifoCount * minSamplingPeriodInNs;
+
+    if (batchingPeriodInNs < oneSecondInNs) {
+        // batching size too small to test reliably
+        return;
+    }
+
+    batchingPeriodInNs = std::min(batchingPeriodInNs, maxBatchingTestTimeNs);
+
+    ALOGI("Test batching for %d ms", (int)(batchingPeriodInNs / 1000 / 1000));
+
+    int64_t allowedBatchDeliverTimeNs = std::max(oneSecondInNs, batchingPeriodInNs / 10);
+
+    ASSERT_EQ(batch(handle, minSamplingPeriodInNs, INT64_MAX), Result::OK);
+    ASSERT_EQ(activate(handle, 1), Result::OK);
+
+    usleep(500000);  // sleep 0.5 sec to wait for initialization
+    ASSERT_EQ(flush(handle), Result::OK);
+
+    // wait for 80% of the reserved batching period
+    // there should not be any significant amount of events
+    // since collection is not enabled all events will go down the drain
+    usleep(batchingPeriodInNs / 1000 * 8 / 10);
+
+    getEnvironment()->setCollection(true);
+    // clean existing collections
+    collectEvents(0 /*timeLimitUs*/, 0 /*nEventLimit*/, true /*clearBeforeStart*/,
+                  false /*change collection*/);
+
+    // 0.8 + 0.2 times the batching period
+    usleep(batchingPeriodInNs / 1000 * 8 / 10);
+    ASSERT_EQ(flush(handle), Result::OK);
+
+    // plus some time for the event to deliver
+    events = collectEvents(allowedBatchDeliverTimeNs / 1000, minFifoCount,
+                           false /*clearBeforeStart*/, false /*change collection*/);
+
+    getEnvironment()->setCollection(false);
+    ASSERT_EQ(activate(handle, 0), Result::OK);
+
+    size_t nEvent = 0;
+    for (auto& e : events) {
+        if (e.sensorType == type && e.sensorHandle == handle) {
+            ++nEvent;
+        }
+    }
+
+    // at least reach 90% of advertised capacity
+    ASSERT_GT(nEvent, (size_t)(minFifoCount * 9 / 10));
+}
diff --git a/sensors/common/vts/utils/SensorsTestSharedMemory.cpp b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp
new file mode 100644
index 0000000..5096498
--- /dev/null
+++ b/sensors/common/vts/utils/SensorsTestSharedMemory.cpp
@@ -0,0 +1,206 @@
+/*
+ * 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 "SensorsTestSharedMemory.h"
+
+#include <log/log.h>
+
+#include <sys/mman.h>
+#include <cinttypes>
+
+using namespace ::android::hardware::sensors::V1_0;
+
+SharedMemInfo SensorsTestSharedMemory::getSharedMemInfo() const {
+    SharedMemInfo mem = {.type = mType,
+                         .format = SharedMemFormat::SENSORS_EVENT,
+                         .size = static_cast<uint32_t>(mSize),
+                         .memoryHandle = mNativeHandle};
+    return mem;
+}
+
+char* SensorsTestSharedMemory::getBuffer() const {
+    return mBuffer;
+}
+
+std::vector<Event> SensorsTestSharedMemory::parseEvents(int64_t lastCounter, size_t offset) const {
+    constexpr size_t kEventSize = static_cast<size_t>(SensorsEventFormatOffset::TOTAL_LENGTH);
+    constexpr size_t kOffsetSize = static_cast<size_t>(SensorsEventFormatOffset::SIZE_FIELD);
+    constexpr size_t kOffsetToken = static_cast<size_t>(SensorsEventFormatOffset::REPORT_TOKEN);
+    constexpr size_t kOffsetType = static_cast<size_t>(SensorsEventFormatOffset::SENSOR_TYPE);
+    constexpr size_t kOffsetAtomicCounter =
+        static_cast<size_t>(SensorsEventFormatOffset::ATOMIC_COUNTER);
+    constexpr size_t kOffsetTimestamp = static_cast<size_t>(SensorsEventFormatOffset::TIMESTAMP);
+    constexpr size_t kOffsetData = static_cast<size_t>(SensorsEventFormatOffset::DATA);
+
+    std::vector<Event> events;
+    std::vector<float> data(16);
+
+    while (offset + kEventSize <= mSize) {
+        int64_t atomicCounter =
+            *reinterpret_cast<uint32_t*>(mBuffer + offset + kOffsetAtomicCounter);
+        if (atomicCounter <= lastCounter) {
+            ALOGV("atomicCounter = %" PRId64 ", lastCounter = %" PRId64, atomicCounter,
+                  lastCounter);
+            break;
+        }
+
+        int32_t size = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetSize);
+        if (size != kEventSize) {
+            // unknown error, events parsed may be wrong, remove all
+            events.clear();
+            break;
+        }
+
+        int32_t token = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetToken);
+        int32_t type = *reinterpret_cast<int32_t*>(mBuffer + offset + kOffsetType);
+        int64_t timestamp = *reinterpret_cast<int64_t*>(mBuffer + offset + kOffsetTimestamp);
+
+        ALOGV("offset = %zu, cnt %" PRId64 ", token %" PRId32 ", type %" PRId32
+              ", timestamp %" PRId64,
+              offset, atomicCounter, token, type, timestamp);
+
+        Event event = {
+            .timestamp = timestamp,
+            .sensorHandle = token,
+            .sensorType = static_cast<SensorType>(type),
+        };
+        event.u.data = android::hardware::hidl_array<float, 16>(
+            reinterpret_cast<float*>(mBuffer + offset + kOffsetData));
+
+        events.push_back(event);
+
+        lastCounter = atomicCounter;
+        offset += kEventSize;
+    }
+
+    return events;
+}
+
+SensorsTestSharedMemory::SensorsTestSharedMemory(SharedMemType type, size_t size)
+    : mType(type), mSize(0), mBuffer(nullptr) {
+    native_handle_t* handle = nullptr;
+    char* buffer = nullptr;
+    switch (type) {
+        case SharedMemType::ASHMEM: {
+            int fd;
+            handle = ::native_handle_create(1 /*nFds*/, 0 /*nInts*/);
+            if (handle != nullptr) {
+                handle->data[0] = fd = ::ashmem_create_region("SensorsTestSharedMemory", size);
+                if (handle->data[0] > 0) {
+                    // memory is pinned by default
+                    buffer = static_cast<char*>(
+                        ::mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
+                    if (buffer != reinterpret_cast<char*>(MAP_FAILED)) {
+                        break;
+                    }
+                    ::native_handle_close(handle);
+                }
+                ::native_handle_delete(handle);
+                handle = nullptr;
+            }
+            break;
+        }
+        case SharedMemType::GRALLOC: {
+            mGrallocWrapper = std::make_unique<::android::GrallocWrapper>();
+            if (mGrallocWrapper->getAllocator() == nullptr ||
+                mGrallocWrapper->getMapper() == nullptr) {
+                break;
+            }
+            using android::hardware::graphics::common::V1_0::BufferUsage;
+            using android::hardware::graphics::common::V1_0::PixelFormat;
+            mapper2::IMapper::BufferDescriptorInfo buf_desc_info = {
+                .width = static_cast<uint32_t>(size),
+                .height = 1,
+                .layerCount = 1,
+                .usage = static_cast<uint64_t>(BufferUsage::SENSOR_DIRECT_DATA |
+                                               BufferUsage::CPU_READ_OFTEN),
+                .format = PixelFormat::BLOB};
+
+            handle = const_cast<native_handle_t*>(mGrallocWrapper->allocate(buf_desc_info));
+            if (handle != nullptr) {
+                mapper2::IMapper::Rect region{0, 0, static_cast<int32_t>(buf_desc_info.width),
+                                              static_cast<int32_t>(buf_desc_info.height)};
+                buffer = static_cast<char*>(
+                    mGrallocWrapper->lock(handle, buf_desc_info.usage, region, /*fence=*/-1));
+                if (buffer != nullptr) {
+                    break;
+                }
+                mGrallocWrapper->freeBuffer(handle);
+                handle = nullptr;
+            }
+            break;
+        }
+        default:
+            break;
+    }
+
+    if (buffer != nullptr) {
+        mNativeHandle = handle;
+        mSize = size;
+        mBuffer = buffer;
+    }
+}
+
+SensorsTestSharedMemory::~SensorsTestSharedMemory() {
+    switch (mType) {
+        case SharedMemType::ASHMEM: {
+            if (mSize != 0) {
+                ::munmap(mBuffer, mSize);
+                mBuffer = nullptr;
+
+                ::native_handle_close(mNativeHandle);
+                ::native_handle_delete(mNativeHandle);
+
+                mNativeHandle = nullptr;
+                mSize = 0;
+            }
+            break;
+        }
+        case SharedMemType::GRALLOC: {
+            if (mSize != 0) {
+                mGrallocWrapper->unlock(mNativeHandle);
+                mGrallocWrapper->freeBuffer(mNativeHandle);
+
+                mNativeHandle = nullptr;
+                mSize = 0;
+            }
+            break;
+        }
+        default: {
+            if (mNativeHandle != nullptr || mSize != 0 || mBuffer != nullptr) {
+                ALOGE(
+                    "SensorsTestSharedMemory %p not properly destructed: "
+                    "type %d, native handle %p, size %zu, buffer %p",
+                    this, static_cast<int>(mType), mNativeHandle, mSize, mBuffer);
+            }
+            break;
+        }
+    }
+}
+
+SensorsTestSharedMemory* SensorsTestSharedMemory::create(SharedMemType type, size_t size) {
+    constexpr size_t kMaxSize = 128 * 1024 * 1024;  // sensor test should not need more than 128M
+    if (size == 0 || size >= kMaxSize) {
+        return nullptr;
+    }
+
+    auto m = new SensorsTestSharedMemory(type, size);
+    if (m->mSize != size || m->mBuffer == nullptr) {
+        delete m;
+        m = nullptr;
+    }
+    return m;
+}
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h b/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h
new file mode 100644
index 0000000..3bd73c3
--- /dev/null
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/GrallocWrapper.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef GRALLO_WRAPPER_H_
+#define GRALLO_WRAPPER_H_
+
+#include <unordered_set>
+
+#include <android/hardware/graphics/allocator/2.0/IAllocator.h>
+#include <android/hardware/graphics/mapper/2.0/IMapper.h>
+
+namespace allocator2 = ::android::hardware::graphics::allocator::V2_0;
+namespace mapper2 = ::android::hardware::graphics::mapper::V2_0;
+
+namespace android {
+
+// Modified from hardware/interfaces/graphics/mapper/2.0/vts/functional/
+class GrallocWrapper {
+   public:
+    GrallocWrapper();
+    ~GrallocWrapper();
+
+    sp<allocator2::IAllocator> getAllocator() const;
+    sp<mapper2::IMapper> getMapper() const;
+
+    std::string dumpDebugInfo();
+
+    // When import is false, this simply calls IAllocator::allocate. When import
+    // is true, the returned buffers are also imported into the mapper.
+    //
+    // Either case, the returned buffers must be freed with freeBuffer.
+    std::vector<const native_handle_t*> allocate(const mapper2::BufferDescriptor& descriptor,
+                                                 uint32_t count, bool import = true,
+                                                 uint32_t* outStride = nullptr);
+    const native_handle_t* allocate(const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo,
+                                    bool import = true, uint32_t* outStride = nullptr);
+
+    mapper2::BufferDescriptor createDescriptor(
+        const mapper2::IMapper::BufferDescriptorInfo& descriptorInfo);
+
+    const native_handle_t* importBuffer(const hardware::hidl_handle& rawHandle);
+    void freeBuffer(const native_handle_t* bufferHandle);
+
+    // We use fd instead of hardware::hidl_handle in these functions to pass fences
+    // in and out of the mapper.  The ownership of the fd is always transferred
+    // with each of these functions.
+    void* lock(const native_handle_t* bufferHandle, uint64_t cpuUsage,
+               const mapper2::IMapper::Rect& accessRegion, int acquireFence);
+
+    int unlock(const native_handle_t* bufferHandle);
+
+   private:
+    void init();
+    const native_handle_t* cloneBuffer(const hardware::hidl_handle& rawHandle);
+
+    sp<allocator2::IAllocator> mAllocator;
+    sp<mapper2::IMapper> mMapper;
+
+    // Keep track of all cloned and imported handles.  When a test fails with
+    // ASSERT_*, the destructor will free the handles for the test.
+    std::unordered_set<const native_handle_t*> mClonedBuffers;
+    std::unordered_set<const native_handle_t*> mImportedBuffers;
+};
+
+}  // namespace android
+#endif  // GRALLO_WRAPPER_H_
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorEventsChecker.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorEventsChecker.h
new file mode 100644
index 0000000..b5daccc
--- /dev/null
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorEventsChecker.h
@@ -0,0 +1,78 @@
+/*
+ * 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_SENSOR_EVENTS_CHECKER_H
+#define ANDROID_SENSOR_EVENTS_CHECKER_H
+
+#include <android/hardware/sensors/1.0/types.h>
+
+#include <cmath>
+
+class SensorEventsChecker {
+   public:
+    using Event = ::android::hardware::sensors::V1_0::Event;
+    virtual bool check(const std::vector<Event>& events, std::string* out) const = 0;
+    virtual ~SensorEventsChecker() {}
+};
+
+class NullChecker : public SensorEventsChecker {
+   public:
+    virtual bool check(const std::vector<Event>&, std::string*) const { return true; }
+};
+
+class SensorEventPerEventChecker : public SensorEventsChecker {
+   public:
+    virtual bool checkEvent(const Event& event, std::string* out) const = 0;
+    virtual bool check(const std::vector<Event>& events, std::string* out) const {
+        for (const auto& e : events) {
+            if (!checkEvent(e, out)) {
+                return false;
+            }
+        }
+        return true;
+    }
+};
+
+class Vec3NormChecker : public SensorEventPerEventChecker {
+   public:
+    Vec3NormChecker(float min, float max) : mLowerLimit(min), mUpperLimit(max) {}
+    static Vec3NormChecker byNominal(float nominal, float allowedError) {
+        return Vec3NormChecker(nominal - allowedError, nominal + allowedError);
+    }
+
+    virtual bool checkEvent(const Event& event, std::string* out) const {
+        android::hardware::sensors::V1_0::Vec3 v = event.u.vec3;
+        float norm = std::sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
+        if (norm < mLowerLimit || norm > mUpperLimit) {
+            if (out != nullptr) {
+                std::ostringstream ss;
+                ss << "Event @ " << event.timestamp << " (" << v.x << ", " << v.y << ", " << v.z
+                   << ")"
+                   << " has norm " << norm << ", which is beyond range"
+                   << " [" << mLowerLimit << ", " << mUpperLimit << "]";
+                *out = ss.str();
+            }
+            return false;
+        }
+        return true;
+    }
+
+   protected:
+    float mLowerLimit;
+    float mUpperLimit;
+};
+
+#endif  // ANDROID_SENSOR_EVENTS_CHECKER_H
\ No newline at end of file
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
new file mode 100644
index 0000000..4a6f713
--- /dev/null
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
@@ -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.
+ */
+
+#ifndef ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H
+#define ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H
+
+#include <VtsHalHidlTargetTestEnvBase.h>
+
+#include <android/hardware/sensors/1.0/types.h>
+
+#include <atomic>
+#include <memory>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+class SensorsHidlEnvironmentBase : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    using Event = ::android::hardware::sensors::V1_0::Event;
+    void HidlSetUp() override;
+    void HidlTearDown() override;
+
+    // Get and clear all events collected so far (like "cat" shell command).
+    // If output is nullptr, it clears all collected events.
+    void catEvents(std::vector<Event>* output);
+
+    // set sensor event collection status
+    void setCollection(bool enable);
+
+   protected:
+    SensorsHidlEnvironmentBase() {}
+
+    void addEvent(const Event& ev);
+
+    virtual void startPollingThread() = 0;
+    virtual bool resetHal() = 0;
+
+    bool collectionEnabled;
+    std::atomic_bool stopThread;
+    std::thread pollThread;
+    std::vector<Event> events;
+    std::mutex events_mutex;
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentBase);
+};
+
+#endif  // ANDROID_SENSORS_HIDL_ENVIRONMENT_BASE_H
\ No newline at end of file
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
new file mode 100644
index 0000000..f4b259f
--- /dev/null
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
@@ -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.
+ */
+
+#ifndef ANDROID_SENSORS_HIDL_TEST_BASE_H
+#define ANDROID_SENSORS_HIDL_TEST_BASE_H
+
+#include "sensors-vts-utils/SensorEventsChecker.h"
+#include "sensors-vts-utils/SensorsHidlEnvironmentBase.h"
+
+#include <VtsHalHidlTargetTestBase.h>
+#include <android/hardware/sensors/1.0/ISensors.h>
+#include <android/hardware/sensors/1.0/types.h>
+
+#include <unordered_set>
+#include <vector>
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::sensors::V1_0::Event;
+using ::android::hardware::sensors::V1_0::ISensors;
+using ::android::hardware::sensors::V1_0::RateLevel;
+using ::android::hardware::sensors::V1_0::Result;
+using ::android::hardware::sensors::V1_0::SensorFlagBits;
+using ::android::hardware::sensors::V1_0::SensorInfo;
+using ::android::hardware::sensors::V1_0::SensorType;
+using ::android::hardware::sensors::V1_0::SharedMemInfo;
+using ::android::hardware::sensors::V1_0::SharedMemType;
+
+class SensorsHidlTestBase : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual SensorsHidlEnvironmentBase* getEnvironment() = 0;
+    virtual void SetUp() override {}
+
+    virtual void TearDown() override {
+        // stop all sensors
+        for (auto s : mSensorHandles) {
+            activate(s, false);
+        }
+        mSensorHandles.clear();
+
+        // stop all direct report and channels
+        for (auto c : mDirectChannelHandles) {
+            // disable all reports
+            configDirectReport(-1, c, RateLevel::STOP, [](auto, auto) {});
+            unregisterDirectChannel(c);
+        }
+        mDirectChannelHandles.clear();
+    }
+
+    // implementation wrapper
+    virtual SensorInfo defaultSensorByType(SensorType type) = 0;
+    virtual Return<void> getSensorsList(ISensors::getSensorsList_cb _hidl_cb) = 0;
+
+    virtual Return<Result> activate(int32_t sensorHandle, bool enabled) = 0;
+
+    virtual Return<Result> batch(int32_t sensorHandle, int64_t samplingPeriodNs,
+                                 int64_t maxReportLatencyNs) = 0;
+
+    virtual Return<Result> flush(int32_t sensorHandle) = 0;
+    virtual Return<Result> injectSensorData(const Event& event) = 0;
+    virtual Return<void> registerDirectChannel(const SharedMemInfo& mem,
+                                               ISensors::registerDirectChannel_cb _hidl_cb) = 0;
+    virtual Return<Result> unregisterDirectChannel(int32_t channelHandle) = 0;
+    virtual Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle,
+                                            RateLevel rate,
+                                            ISensors::configDirectReport_cb _hidl_cb) = 0;
+
+    std::vector<Event> collectEvents(useconds_t timeLimitUs, size_t nEventLimit,
+                                     bool clearBeforeStart = true, bool changeCollection = true);
+
+    inline static SensorFlagBits extractReportMode(uint64_t flag) {
+        return (SensorFlagBits)(flag & ((uint64_t)SensorFlagBits::CONTINUOUS_MODE |
+                                        (uint64_t)SensorFlagBits::ON_CHANGE_MODE |
+                                        (uint64_t)SensorFlagBits::ONE_SHOT_MODE |
+                                        (uint64_t)SensorFlagBits::SPECIAL_REPORTING_MODE));
+    }
+
+    inline static bool isMetaSensorType(SensorType type) {
+        return (type == SensorType::META_DATA || type == SensorType::DYNAMIC_SENSOR_META ||
+                type == SensorType::ADDITIONAL_INFO);
+    }
+
+    inline static bool isValidType(SensorType type) { return (int32_t)type > 0; }
+
+    void testStreamingOperation(SensorType type, std::chrono::nanoseconds samplingPeriod,
+                                std::chrono::seconds duration, const SensorEventsChecker& checker);
+    void testSamplingRateHotSwitchOperation(SensorType type, bool fastToSlow = true);
+    void testBatchingOperation(SensorType type);
+    void testDirectReportOperation(SensorType type, SharedMemType memType, RateLevel rate,
+                                   const SensorEventsChecker& checker);
+
+    static void assertTypeMatchStringType(SensorType type, const hidl_string& stringType);
+    static void assertTypeMatchReportMode(SensorType type, SensorFlagBits reportMode);
+    static void assertDelayMatchReportMode(int32_t minDelay, int32_t maxDelay,
+                                           SensorFlagBits reportMode);
+    static SensorFlagBits expectedReportModeForType(SensorType type);
+    static bool isDirectReportRateSupported(SensorInfo sensor, RateLevel rate);
+    static bool isDirectChannelTypeSupported(SensorInfo sensor, SharedMemType type);
+
+   protected:
+    // checkers
+    static const Vec3NormChecker sAccelNormChecker;
+    static const Vec3NormChecker sGyroNormChecker;
+
+    // all sensors and direct channnels used
+    std::unordered_set<int32_t> mSensorHandles;
+    std::unordered_set<int32_t> mDirectChannelHandles;
+};
+
+#endif  // ANDROID_SENSORS_HIDL_TEST_BASE_H
\ No newline at end of file
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h
new file mode 100644
index 0000000..055b8e7
--- /dev/null
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsTestSharedMemory.h
@@ -0,0 +1,51 @@
+/*
+ * 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_SENSORS_TEST_SHARED_MEMORY_H
+#define ANDROID_SENSORS_TEST_SHARED_MEMORY_H
+
+#include "GrallocWrapper.h"
+
+#include <android-base/macros.h>
+#include <android/hardware/sensors/1.0/types.h>
+
+#include <cutils/ashmem.h>
+
+class SensorsTestSharedMemory {
+    using SharedMemType = ::android::hardware::sensors::V1_0::SharedMemType;
+    using SharedMemInfo = ::android::hardware::sensors::V1_0::SharedMemInfo;
+    using Event = ::android::hardware::sensors::V1_0::Event;
+
+   public:
+    static SensorsTestSharedMemory* create(SharedMemType type, size_t size);
+    SharedMemInfo getSharedMemInfo() const;
+    char* getBuffer() const;
+    std::vector<Event> parseEvents(int64_t lastCounter = -1, size_t offset = 0) const;
+    virtual ~SensorsTestSharedMemory();
+
+   private:
+    SensorsTestSharedMemory(SharedMemType type, size_t size);
+
+    SharedMemType mType;
+    native_handle_t* mNativeHandle;
+    size_t mSize;
+    char* mBuffer;
+    std::unique_ptr<::android::GrallocWrapper> mGrallocWrapper;
+
+    DISALLOW_COPY_AND_ASSIGN(SensorsTestSharedMemory);
+};
+
+#endif  // ANDROID_SENSORS_TEST_SHARED_MEMORY_H
diff --git a/tests/bar/1.0/default/Bar.cpp b/tests/bar/1.0/default/Bar.cpp
index 4614428..0a57b40 100644
--- a/tests/bar/1.0/default/Bar.cpp
+++ b/tests/bar/1.0/default/Bar.cpp
@@ -149,6 +149,10 @@
     return mFoo->closeHandles();
 }
 
+Return<void> Bar::repeatWithFmq(const IFoo::WithFmq& withFmq, repeatWithFmq_cb _hidl_cb) {
+    return mFoo->repeatWithFmq(withFmq, _hidl_cb);
+}
+
 Return<void> Bar::echoNullInterface(const sp<IFooCallback> &cb, echoNullInterface_cb _hidl_cb) {
     return mFoo->echoNullInterface(cb, _hidl_cb);
 }
diff --git a/tests/bar/1.0/default/Bar.h b/tests/bar/1.0/default/Bar.h
index acb976f..4372266 100644
--- a/tests/bar/1.0/default/Bar.h
+++ b/tests/bar/1.0/default/Bar.h
@@ -56,6 +56,8 @@
     virtual Return<void> createMyHandle(createMyHandle_cb _hidl_cb)  override;
     virtual Return<void> createHandles(uint32_t size, createHandles_cb _hidl_cb)  override;
     virtual Return<void> closeHandles()  override;
+    virtual Return<void> repeatWithFmq(const IFoo::WithFmq& withFmq,
+                                       repeatWithFmq_cb _hidl_cb) override;
 
     Return<void> haveAVectorOfInterfaces(
             const hidl_vec<sp<ISimple> > &in,
diff --git a/tests/baz/1.0/IBaz.hal b/tests/baz/1.0/IBaz.hal
index 8118d8b..91ed1f2 100644
--- a/tests/baz/1.0/IBaz.hal
+++ b/tests/baz/1.0/IBaz.hal
@@ -36,6 +36,17 @@
     typedef SomeOtherEnum thisIsAnAlias;
     typedef IBaz anIBazByAnyOtherName;
 
+    struct NastyNester {
+        struct NestersNasty {
+            struct NestersNastyNester {
+                IBaz baz;
+                vec<NestersNasty> nasties;
+            };
+        };
+
+        IBaz baz;
+    };
+
     enum SomeEnum : SomeOtherEnum {
         quux = 33,
         goober = 192,
diff --git a/tests/foo/1.0/IFoo.hal b/tests/foo/1.0/IFoo.hal
index 4a930a2..4c54427 100644
--- a/tests/foo/1.0/IFoo.hal
+++ b/tests/foo/1.0/IFoo.hal
@@ -103,7 +103,6 @@
         union U {
             int8_t number;
             int8_t[1][2] multidimArray;
-            pointer p;
             Fumble anotherStruct;
             bitfield<BitField> bf;
         } u;
@@ -122,6 +121,17 @@
         bitfield<BitField> bf;
     };
 
+    struct WithFmq {
+        struct ScatterGather {
+            fmq_sync<uint8_t> descSync;
+        } scatterGathered;
+
+        struct ContainsPointer {
+            fmq_sync<uint8_t> descSync;
+            interface foo;
+        } containsPointer;
+    };
+
     enum Discriminator : uint8_t {
         BOOL,
         INT,
@@ -205,4 +215,6 @@
     createMyHandle() generates (MyHandle h);
     createHandles(uint32_t size) generates (vec<handle> handles);
     closeHandles();
+
+    repeatWithFmq(WithFmq withFmq) generates (WithFmq withFmq);
 };
diff --git a/tests/foo/1.0/default/Foo.cpp b/tests/foo/1.0/default/Foo.cpp
index a31ab9f..461568b 100644
--- a/tests/foo/1.0/default/Foo.cpp
+++ b/tests/foo/1.0/default/Foo.cpp
@@ -379,6 +379,11 @@
     return Void();
 }
 
+Return<void> Foo::repeatWithFmq(const IFoo::WithFmq& withFmq, repeatWithFmq_cb _hidl_cb) {
+    _hidl_cb(withFmq);
+    return Void();
+}
+
 IFoo* HIDL_FETCH_IFoo(const char* /* name */) {
     return new Foo();
 }
diff --git a/tests/foo/1.0/default/Foo.h b/tests/foo/1.0/default/Foo.h
index 7dd672b..d73179a 100644
--- a/tests/foo/1.0/default/Foo.h
+++ b/tests/foo/1.0/default/Foo.h
@@ -53,6 +53,8 @@
     virtual Return<void> createMyHandle(createMyHandle_cb _hidl_cb)  override;
     virtual Return<void> createHandles(uint32_t size, createHandles_cb _hidl_cb)  override;
     virtual Return<void> closeHandles()  override;
+    virtual Return<void> repeatWithFmq(const IFoo::WithFmq& withFmq,
+                                       repeatWithFmq_cb _hidl_cb) override;
 
     Return<void> haveAVectorOfInterfaces(
             const hidl_vec<sp<ISimple> > &in,
@@ -63,6 +65,7 @@
             haveAVectorOfGenericInterfaces_cb _hidl_cb) override;
 
     Return<void> echoNullInterface(const sp<IFooCallback> &cb, echoNullInterface_cb _hidl_cb) override;
+
 private:
     std::vector<::native_handle_t *> mHandles;
 };
diff --git a/tests/safeunion/1.0/Android.bp b/tests/safeunion/1.0/Android.bp
index ede8401..87edd53 100644
--- a/tests/safeunion/1.0/Android.bp
+++ b/tests/safeunion/1.0/Android.bp
@@ -9,6 +9,7 @@
     ],
     interfaces: [
         "android.hidl.base@1.0",
+        "android.hidl.safe_union@1.0",
     ],
     gen_java: true,
 }
diff --git a/tests/safeunion/1.0/ISafeUnion.hal b/tests/safeunion/1.0/ISafeUnion.hal
index c38777a..58c08c6 100644
--- a/tests/safeunion/1.0/ISafeUnion.hal
+++ b/tests/safeunion/1.0/ISafeUnion.hal
@@ -18,6 +18,8 @@
 
 import IOtherInterface;
 
+import android.hidl.safe_union@1.0::Monostate;
+
 interface ISafeUnion {
 
     enum BitField : uint8_t {
@@ -33,14 +35,15 @@
         string j3;
     };
 
-    safe_union EmptySafeUnion {
-    };
-
     safe_union SmallSafeUnion {
+        Monostate noinit;
+
         uint8_t a;
     };
 
     safe_union LargeSafeUnion {
+        Monostate noinit;
+
         int8_t a;
         uint16_t b;
         int32_t c;
@@ -60,9 +63,14 @@
         } k;
 
         SmallSafeUnion l;
+
+        BitField m;
+        bitfield<BitField> n;
     };
 
     safe_union InterfaceTypeSafeUnion {
+        Monostate noinit;
+
         uint32_t a;
         int8_t[7] b;
         IOtherInterface c;
@@ -73,6 +81,8 @@
     };
 
     safe_union HandleTypeSafeUnion {
+        Monostate noinit;
+
         handle a;
         handle[5] b;
         vec<handle> c;
@@ -91,6 +101,8 @@
     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);
diff --git a/tests/safeunion/1.0/default/SafeUnion.cpp b/tests/safeunion/1.0/default/SafeUnion.cpp
index c395664..4fb0974 100644
--- a/tests/safeunion/1.0/default/SafeUnion.cpp
+++ b/tests/safeunion/1.0/default/SafeUnion.cpp
@@ -153,6 +153,27 @@
     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()";
 
diff --git a/tests/safeunion/1.0/default/SafeUnion.h b/tests/safeunion/1.0/default/SafeUnion.h
index e774e09..ee3a954 100644
--- a/tests/safeunion/1.0/default/SafeUnion.h
+++ b/tests/safeunion/1.0/default/SafeUnion.h
@@ -47,6 +47,9 @@
     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;
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/wifi/1.3/Android.bp b/wifi/1.3/Android.bp
index 95fbf83..5e87c1c 100644
--- a/wifi/1.3/Android.bp
+++ b/wifi/1.3/Android.bp
@@ -7,7 +7,9 @@
         enabled: true,
     },
     srcs: [
+        "types.hal",
         "IWifi.hal",
+        "IWifiStaIface.hal",
     ],
     interfaces: [
         "android.hardware.wifi@1.0",
@@ -15,6 +17,10 @@
         "android.hardware.wifi@1.2",
         "android.hidl.base@1.0",
     ],
+    types: [
+      "StaLinkLayerRadioStats",
+      "StaLinkLayerStats",
+    ],
     gen_java: true,
 }
 
diff --git a/wifi/1.3/IWifiStaIface.hal b/wifi/1.3/IWifiStaIface.hal
new file mode 100644
index 0000000..0dc6128
--- /dev/null
+++ b/wifi/1.3/IWifiStaIface.hal
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi@1.3;
+
+import @1.0::WifiStatus;
+import @1.2::IWifiStaIface;
+
+/**
+ * Interface used to represent a single STA iface.
+ *
+ * IWifiChip.createStaIface() may return a @1.3::IWifiStaIface when supported.
+ */
+interface IWifiStaIface extends @1.2::IWifiStaIface {
+    /**
+     * Retrieve the latest link layer stats.
+     * Must fail if |StaIfaceCapabilityMask.LINK_LAYER_STATS| is not set or if
+     * link layer stats collection hasn't been explicitly enabled.
+     *
+     * @return status WifiStatus of the operation.
+     *     Possible status codes:
+     *     |WifiStatusCode.SUCCESS|,
+     *     |WifiStatusCode.ERROR_WIFI_IFACE_INVALID|,
+     *     |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *     |WifiStatusCode.ERROR_NOT_STARTED|,
+     *     |WifiStatusCode.ERROR_NOT_AVAILABLE|,
+     *     |WifiStatusCode.ERROR_UNKNOWN|
+     * @return stats Instance of |LinkLayerStats|.
+     */
+    getLinkLayerStats_1_3() generates (WifiStatus status, StaLinkLayerStats stats);
+};
diff --git a/wifi/1.3/default/hidl_struct_util.cpp b/wifi/1.3/default/hidl_struct_util.cpp
index e793236..c88ddaa 100644
--- a/wifi/1.3/default/hidl_struct_util.cpp
+++ b/wifi/1.3/default/hidl_struct_util.cpp
@@ -785,7 +785,7 @@
 
 bool convertLegacyLinkLayerStatsToHidl(
     const legacy_hal::LinkLayerStats& legacy_stats,
-    StaLinkLayerStats* hidl_stats) {
+    V1_3::StaLinkLayerStats* hidl_stats) {
     if (!hidl_stats) {
         return false;
     }
@@ -826,16 +826,26 @@
     hidl_stats->iface.wmeVoPktStats.retries =
         legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries;
     // radio legacy_stats conversion.
-    std::vector<StaLinkLayerRadioStats> hidl_radios_stats;
+    std::vector<V1_3::StaLinkLayerRadioStats> hidl_radios_stats;
     for (const auto& legacy_radio_stats : legacy_stats.radios) {
-        StaLinkLayerRadioStats hidl_radio_stats;
-        hidl_radio_stats.onTimeInMs = legacy_radio_stats.stats.on_time;
-        hidl_radio_stats.txTimeInMs = legacy_radio_stats.stats.tx_time;
-        hidl_radio_stats.rxTimeInMs = legacy_radio_stats.stats.rx_time;
-        hidl_radio_stats.onTimeInMsForScan =
+        V1_3::StaLinkLayerRadioStats hidl_radio_stats;
+        hidl_radio_stats.V1_0.onTimeInMs = legacy_radio_stats.stats.on_time;
+        hidl_radio_stats.V1_0.txTimeInMs = legacy_radio_stats.stats.tx_time;
+        hidl_radio_stats.V1_0.rxTimeInMs = legacy_radio_stats.stats.rx_time;
+        hidl_radio_stats.V1_0.onTimeInMsForScan =
             legacy_radio_stats.stats.on_time_scan;
-        hidl_radio_stats.txTimeInMsPerLevel =
+        hidl_radio_stats.V1_0.txTimeInMsPerLevel =
             legacy_radio_stats.tx_time_per_levels;
+        hidl_radio_stats.onTimeInMsForNanScan =
+            legacy_radio_stats.stats.on_time_nbd;
+        hidl_radio_stats.onTimeInMsForBgScan =
+            legacy_radio_stats.stats.on_time_gscan;
+        hidl_radio_stats.onTimeInMsForRoamScan =
+            legacy_radio_stats.stats.on_time_roam_scan;
+        hidl_radio_stats.onTimeInMsForPnoScan =
+            legacy_radio_stats.stats.on_time_pno_scan;
+        hidl_radio_stats.onTimeInMsForHs20Scan =
+            legacy_radio_stats.stats.on_time_hs20;
         hidl_radios_stats.push_back(hidl_radio_stats);
     }
     hidl_stats->radios = hidl_radios_stats;
diff --git a/wifi/1.3/default/hidl_struct_util.h b/wifi/1.3/default/hidl_struct_util.h
index e2ba00c..8df484d 100644
--- a/wifi/1.3/default/hidl_struct_util.h
+++ b/wifi/1.3/default/hidl_struct_util.h
@@ -24,6 +24,7 @@
 #include <android/hardware/wifi/1.2/IWifiChip.h>
 #include <android/hardware/wifi/1.2/IWifiChipEventCallback.h>
 #include <android/hardware/wifi/1.2/types.h>
+#include <android/hardware/wifi/1.3/types.h>
 
 #include "wifi_legacy_hal.h"
 
@@ -89,7 +90,7 @@
     std::vector<StaScanData>* hidl_scan_datas);
 bool convertLegacyLinkLayerStatsToHidl(
     const legacy_hal::LinkLayerStats& legacy_stats,
-    StaLinkLayerStats* hidl_stats);
+    V1_3::StaLinkLayerStats* hidl_stats);
 bool convertLegacyRoamingCapabilitiesToHidl(
     const legacy_hal::wifi_roaming_capabilities& legacy_caps,
     StaRoamingCapabilities* hidl_caps);
diff --git a/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp b/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp
index 4cd3719..d600a2b 100644
--- a/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp
+++ b/wifi/1.3/default/tests/hidl_struct_util_unit_tests.cpp
@@ -126,6 +126,118 @@
     EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info2.channel),
               hidl_iface_info2.channel);
 }
+
+TEST_F(HidlStructUtilTest, canConvertLegacyLinkLayerStatsToHidl) {
+    legacy_hal::LinkLayerStats legacy_stats{};
+    legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{});
+    legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{});
+    legacy_stats.iface.beacon_rx = rand();
+    legacy_stats.iface.rssi_mgmt = rand();
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu = rand();
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu = rand();
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost = rand();
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries = rand();
+
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu = rand();
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu = rand();
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost = rand();
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries = rand();
+
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu = rand();
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu = rand();
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost = rand();
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries = rand();
+
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu = rand();
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu = rand();
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost = rand();
+    legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries = rand();
+
+    for (auto& radio : legacy_stats.radios) {
+        radio.stats.on_time = rand();
+        radio.stats.tx_time = rand();
+        radio.stats.rx_time = rand();
+        radio.stats.on_time_scan = rand();
+        radio.stats.on_time_nbd = rand();
+        radio.stats.on_time_gscan = rand();
+        radio.stats.on_time_roam_scan = rand();
+        radio.stats.on_time_pno_scan = rand();
+        radio.stats.on_time_hs20 = rand();
+        for (int i = 0; i < 4; i++) {
+            radio.tx_time_per_levels.push_back(rand());
+        }
+    }
+
+    V1_3::StaLinkLayerStats converted{};
+    hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats,
+                                                        &converted);
+    EXPECT_EQ(legacy_stats.iface.beacon_rx, converted.iface.beaconRx);
+    EXPECT_EQ(legacy_stats.iface.rssi_mgmt, converted.iface.avgRssiMgmt);
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu,
+              converted.iface.wmeBePktStats.rxMpdu);
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu,
+              converted.iface.wmeBePktStats.txMpdu);
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost,
+              converted.iface.wmeBePktStats.lostMpdu);
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries,
+              converted.iface.wmeBePktStats.retries);
+
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu,
+              converted.iface.wmeBkPktStats.rxMpdu);
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu,
+              converted.iface.wmeBkPktStats.txMpdu);
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost,
+              converted.iface.wmeBkPktStats.lostMpdu);
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries,
+              converted.iface.wmeBkPktStats.retries);
+
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu,
+              converted.iface.wmeViPktStats.rxMpdu);
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu,
+              converted.iface.wmeViPktStats.txMpdu);
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost,
+              converted.iface.wmeViPktStats.lostMpdu);
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries,
+              converted.iface.wmeViPktStats.retries);
+
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu,
+              converted.iface.wmeVoPktStats.rxMpdu);
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu,
+              converted.iface.wmeVoPktStats.txMpdu);
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost,
+              converted.iface.wmeVoPktStats.lostMpdu);
+    EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries,
+              converted.iface.wmeVoPktStats.retries);
+
+    EXPECT_EQ(legacy_stats.radios.size(), converted.radios.size());
+    for (int i = 0; i < legacy_stats.radios.size(); i++) {
+        EXPECT_EQ(legacy_stats.radios[i].stats.on_time,
+                  converted.radios[i].V1_0.onTimeInMs);
+        EXPECT_EQ(legacy_stats.radios[i].stats.tx_time,
+                  converted.radios[i].V1_0.txTimeInMs);
+        EXPECT_EQ(legacy_stats.radios[i].stats.rx_time,
+                  converted.radios[i].V1_0.rxTimeInMs);
+        EXPECT_EQ(legacy_stats.radios[i].stats.on_time_scan,
+                  converted.radios[i].V1_0.onTimeInMsForScan);
+        EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels.size(),
+                  converted.radios[i].V1_0.txTimeInMsPerLevel.size());
+        for (int j = 0; j < legacy_stats.radios[i].tx_time_per_levels.size();
+             j++) {
+            EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels[j],
+                      converted.radios[i].V1_0.txTimeInMsPerLevel[j]);
+        }
+        EXPECT_EQ(legacy_stats.radios[i].stats.on_time_nbd,
+                  converted.radios[i].onTimeInMsForNanScan);
+        EXPECT_EQ(legacy_stats.radios[i].stats.on_time_gscan,
+                  converted.radios[i].onTimeInMsForBgScan);
+        EXPECT_EQ(legacy_stats.radios[i].stats.on_time_roam_scan,
+                  converted.radios[i].onTimeInMsForRoamScan);
+        EXPECT_EQ(legacy_stats.radios[i].stats.on_time_pno_scan,
+                  converted.radios[i].onTimeInMsForPnoScan);
+        EXPECT_EQ(legacy_stats.radios[i].stats.on_time_hs20,
+                  converted.radios[i].onTimeInMsForHs20Scan);
+    }
+}
 }  // namespace implementation
 }  // namespace V1_3
 }  // namespace wifi
diff --git a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
index 2d9050d..61060b5 100644
--- a/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
+++ b/wifi/1.3/default/tests/wifi_chip_unit_tests.cpp
@@ -204,6 +204,19 @@
         }
     }
 
+    bool createRttController() {
+        bool success = false;
+        chip_->createRttController(
+            NULL, [&success](const WifiStatus& status,
+                             const sp<IWifiRttController>& rtt) {
+                if (WifiStatusCode::SUCCESS == status.code) {
+                    ASSERT_NE(rtt.get(), nullptr);
+                    success = true;
+                }
+            });
+        return success;
+    }
+
    public:
     void SetUp() override {
         chip_ = new WifiChip(chip_id_, legacy_hal_, mode_controller_,
@@ -386,6 +399,29 @@
     ASSERT_TRUE(createIface(IfaceType::NAN).empty());
 }
 
+TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowStaModeNoSta) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowStaModeWithSta) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, RttControllerFlowApToSta) {
+    findModeAndConfigureForIfaceType(IfaceType::AP);
+    const auto ap_iface_name = createIface(IfaceType::AP);
+    ASSERT_FALSE(ap_iface_name.empty());
+    ASSERT_FALSE(createRttController());
+
+    removeIface(IfaceType::AP, ap_iface_name);
+
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_TRUE(createRttController());
+}
+
 ////////// V2 + Aware Iface Combinations ////////////
 // Mode 1 - STA + STA/AP
 //        - STA + P2P/NAN
@@ -540,6 +576,24 @@
     ASSERT_NE(sta_iface_name, ap_iface_name);
 }
 
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlowStaModeNoSta) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlowStaModeWithSta) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlow) {
+    findModeAndConfigureForIfaceType(IfaceType::STA);
+    ASSERT_FALSE(createIface(IfaceType::STA).empty());
+    ASSERT_FALSE(createIface(IfaceType::AP).empty());
+    ASSERT_TRUE(createRttController());
+}
+
 ////////// V1 Iface Combinations when AP creation is disabled //////////
 class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
    public:
diff --git a/wifi/1.3/default/wifi_chip.cpp b/wifi/1.3/default/wifi_chip.cpp
index cf64e51..faf1862 100644
--- a/wifi/1.3/default/wifi_chip.cpp
+++ b/wifi/1.3/default/wifi_chip.cpp
@@ -930,6 +930,12 @@
 
 std::pair<WifiStatus, sp<IWifiRttController>>
 WifiChip::createRttControllerInternal(const sp<IWifiIface>& bound_iface) {
+    if (sta_ifaces_.size() == 0 &&
+        !canCurrentModeSupportIfaceOfType(IfaceType::STA)) {
+        LOG(ERROR) << "createRttControllerInternal: Chip cannot support STAs "
+                      "(and RTT by extension)";
+        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+    }
     sp<WifiRttController> rtt =
         new WifiRttController(getWlan0IfaceName(), bound_iface, legacy_hal_);
     rtt_controllers_.emplace_back(rtt);
diff --git a/wifi/1.3/default/wifi_sta_iface.cpp b/wifi/1.3/default/wifi_sta_iface.cpp
index 63341df..b0fa1ae 100644
--- a/wifi/1.3/default/wifi_sta_iface.cpp
+++ b/wifi/1.3/default/wifi_sta_iface.cpp
@@ -152,6 +152,13 @@
                            hidl_status_cb);
 }
 
+Return<void> WifiStaIface::getLinkLayerStats_1_3(
+    getLinkLayerStats_1_3_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+                           &WifiStaIface::getLinkLayerStatsInternal_1_3,
+                           hidl_status_cb);
+}
+
 Return<void> WifiStaIface::startRssiMonitoring(
     uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi,
     startRssiMonitoring_cb hidl_status_cb) {
@@ -445,8 +452,13 @@
     return createWifiStatusFromLegacyError(legacy_status);
 }
 
-std::pair<WifiStatus, StaLinkLayerStats>
+std::pair<WifiStatus, V1_0::StaLinkLayerStats>
 WifiStaIface::getLinkLayerStatsInternal() {
+    return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
+}
+
+std::pair<WifiStatus, V1_3::StaLinkLayerStats>
+WifiStaIface::getLinkLayerStatsInternal_1_3() {
     legacy_hal::wifi_error legacy_status;
     legacy_hal::LinkLayerStats legacy_stats;
     std::tie(legacy_status, legacy_stats) =
@@ -454,7 +466,7 @@
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
         return {createWifiStatusFromLegacyError(legacy_status), {}};
     }
-    StaLinkLayerStats hidl_stats;
+    V1_3::StaLinkLayerStats hidl_stats;
     if (!hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats,
                                                              &hidl_stats)) {
         return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
diff --git a/wifi/1.3/default/wifi_sta_iface.h b/wifi/1.3/default/wifi_sta_iface.h
index 0fc61e2..bc3090f 100644
--- a/wifi/1.3/default/wifi_sta_iface.h
+++ b/wifi/1.3/default/wifi_sta_iface.h
@@ -19,7 +19,7 @@
 
 #include <android-base/macros.h>
 #include <android/hardware/wifi/1.0/IWifiStaIfaceEventCallback.h>
-#include <android/hardware/wifi/1.2/IWifiStaIface.h>
+#include <android/hardware/wifi/1.3/IWifiStaIface.h>
 
 #include <wifi_system/interface_tool.h>
 
@@ -36,7 +36,7 @@
 /**
  * HIDL interface object used to control a STA Iface instance.
  */
-class WifiStaIface : public V1_2::IWifiStaIface {
+class WifiStaIface : public V1_3::IWifiStaIface {
    public:
     WifiStaIface(const std::string& ifname,
                  const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
@@ -75,6 +75,8 @@
         disableLinkLayerStatsCollection_cb hidl_status_cb) override;
     Return<void> getLinkLayerStats(
         getLinkLayerStats_cb hidl_status_cb) override;
+    Return<void> getLinkLayerStats_1_3(
+        getLinkLayerStats_1_3_cb hidl_status_cb) override;
     Return<void> startRssiMonitoring(
         uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi,
         startRssiMonitoring_cb hidl_status_cb) override;
@@ -130,7 +132,9 @@
     WifiStatus stopBackgroundScanInternal(uint32_t cmd_id);
     WifiStatus enableLinkLayerStatsCollectionInternal(bool debug);
     WifiStatus disableLinkLayerStatsCollectionInternal();
-    std::pair<WifiStatus, StaLinkLayerStats> getLinkLayerStatsInternal();
+    std::pair<WifiStatus, V1_0::StaLinkLayerStats> getLinkLayerStatsInternal();
+    std::pair<WifiStatus, V1_3::StaLinkLayerStats>
+    getLinkLayerStatsInternal_1_3();
     WifiStatus startRssiMonitoringInternal(uint32_t cmd_id, int32_t max_rssi,
                                            int32_t min_rssi);
     WifiStatus stopRssiMonitoringInternal(uint32_t cmd_id);
diff --git a/wifi/1.3/types.hal b/wifi/1.3/types.hal
new file mode 100644
index 0000000..4585ff3
--- /dev/null
+++ b/wifi/1.3/types.hal
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.wifi@1.3;
+
+import @1.0::StaLinkLayerRadioStats;
+import @1.0::StaLinkLayerIfaceStats;
+import @1.0::TimeStampInMs;
+
+struct StaLinkLayerRadioStats {
+    /**
+     * Baseline information as defined in HAL 1.0.
+     */
+    @1.0::StaLinkLayerRadioStats V1_0;
+
+    /**
+     * Total time for which the radio is awake due to NAN scan since boot or crash.
+     */
+    uint32_t onTimeInMsForNanScan;
+
+    /**
+     * Total time for which the radio is awake due to background scan since boot or crash.
+     */
+    uint32_t onTimeInMsForBgScan;
+
+    /**
+     * Total time for which the radio is awake due to roam scan since boot or crash.
+     */
+    uint32_t onTimeInMsForRoamScan;
+
+    /**
+     * Total time for which the radio is awake due to PNO scan since boot or crash.
+     */
+    uint32_t onTimeInMsForPnoScan;
+
+    /**
+     * Total time for which the radio is awake due to Hotspot 2.0 scans and GAS exchange since boot
+     * or crash.
+     */
+    uint32_t onTimeInMsForHs20Scan;
+};
+
+/**
+ * Link layer stats retrieved via |getLinkLayerStats|.
+ */
+struct StaLinkLayerStats {
+    StaLinkLayerIfaceStats iface;
+    vec<StaLinkLayerRadioStats> radios;
+    /**
+     * TimeStamp for each stats sample.
+     * This is the absolute milliseconds from boot when these stats were
+     * sampled.
+     */
+    TimeStampInMs timeStampInMs;
+};
\ No newline at end of file
diff --git a/wifi/1.3/vts/OWNERS b/wifi/1.3/vts/OWNERS
new file mode 100644
index 0000000..8bfb148
--- /dev/null
+++ b/wifi/1.3/vts/OWNERS
@@ -0,0 +1,2 @@
+rpius@google.com
+etancohen@google.com
diff --git a/wifi/1.3/vts/functional/Android.bp b/wifi/1.3/vts/functional/Android.bp
new file mode 100644
index 0000000..dbe77bd
--- /dev/null
+++ b/wifi/1.3/vts/functional/Android.bp
@@ -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.
+//
+
+cc_test {
+    name: "VtsHalWifiV1_3TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: [
+        "VtsHalWifiV1_3TargetTest.cpp",
+    ],
+    static_libs: [
+        "VtsHalWifiV1_0TargetTestUtil",
+        "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.1",
+        "android.hardware.wifi@1.2",
+        "android.hardware.wifi@1.3",
+    ],
+}
diff --git a/wifi/1.3/vts/functional/VtsHalWifiV1_3TargetTest.cpp b/wifi/1.3/vts/functional/VtsHalWifiV1_3TargetTest.cpp
new file mode 100644
index 0000000..b410a48
--- /dev/null
+++ b/wifi/1.3/vts/functional/VtsHalWifiV1_3TargetTest.cpp
@@ -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.
+ */
+
+#include <android-base/logging.h>
+#include <android/hardware/wifi/1.3/IWifi.h>
+
+#include "wifi_hidl_test_utils.h"
+
+// Test environment for Wifi HIDL HAL.
+class WifiHidlEnvironment_1_3 : public WifiHidlEnvironment {
+   public:
+    // get the test environment singleton
+    static WifiHidlEnvironment_1_3* Instance() {
+        static WifiHidlEnvironment_1_3* instance = new WifiHidlEnvironment_1_3;
+        return instance;
+    }
+
+    virtual void registerTestServices() override {
+        registerTestService<android::hardware::wifi::V1_3::IWifi>();
+    }
+
+   private:
+    WifiHidlEnvironment_1_3() {}
+};
+
+WifiHidlEnvironment_1_3* gEnv = WifiHidlEnvironment_1_3::Instance();
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(gEnv);
+    ::testing::InitGoogleTest(&argc, argv);
+    gEnv->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    LOG(INFO) << "Test result = " << status;
+    return status;
+}