Merge "Adding getModelState API to sound trigger with new build fix. This version copies the V2_0 and V2_1 implementations instead of trying to extend them."
diff --git a/automotive/vehicle/2.0/Android.bp b/automotive/vehicle/2.0/Android.bp
index 6af774e..f64028c 100644
--- a/automotive/vehicle/2.0/Android.bp
+++ b/automotive/vehicle/2.0/Android.bp
@@ -30,7 +30,6 @@
         "StatusCode",
         "SubscribeFlags",
         "SubscribeOptions",
-        "VehicleApPowerBootupReason",
         "VehicleApPowerStateConfigFlag",
         "VehicleApPowerStateReport",
         "VehicleApPowerStateReq",
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 ae4ead4..5007a6d 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
@@ -611,12 +611,12 @@
                 .access = VehiclePropertyAccess::READ,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE,
                 .configArray = {3}},
-     .initialValue = {.int32Values = {toInt(VehicleApPowerStateReq::ON_FULL), 0}}},
+     .initialValue = {.int32Values = {toInt(VehicleApPowerStateReq::ON), 0}}},
 
     {.config = {.prop = toInt(VehicleProperty::AP_POWER_STATE_REPORT),
                 .access = VehiclePropertyAccess::WRITE,
                 .changeMode = VehiclePropertyChangeMode::ON_CHANGE},
-     .initialValue = {.int32Values = {toInt(VehicleApPowerStateReport::BOOT_COMPLETE), 0}}},
+     .initialValue = {.int32Values = {toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL), 0}}},
 
     {.config = {.prop = toInt(VehicleProperty::DISPLAY_BRIGHTNESS),
                 .access = VehiclePropertyAccess::READ_WRITE,
@@ -624,11 +624,6 @@
                 .areaConfigs = {VehicleAreaConfig{.minInt32Value = 0, .maxInt32Value = 100}}},
      .initialValue = {.int32Values = {100}}},
 
-    {.config = {.prop = toInt(VehicleProperty::AP_POWER_BOOTUP_REASON),
-                .access = VehiclePropertyAccess::READ,
-                .changeMode = VehiclePropertyChangeMode::STATIC},
-     .initialValue = {.int32Values = {toInt(VehicleApPowerBootupReason::USER_POWER_ON)}}},
-
     {
         .config = {.prop = OBD2_LIVE_FRAME,
                    .access = VehiclePropertyAccess::READ,
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
index 58d8867..ba81a52 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.cpp
@@ -157,12 +157,28 @@
                 // now, just returns OK; otherwise, hal clients crash with property not supported.
                 return StatusCode::OK;
             case AP_POWER_STATE_REPORT:
-                // This property has different behavior between get/set.  When it is set, the value
-                //  goes to the vehicle but is NOT updated in the property store back to Android.
-                // Commented out for now, because it may mess up automated testing that use the
-                //  emulator interface.
-                // getEmulatorOrDie()->doSetValueFromClient(propValue);
-                return StatusCode::OK;
+                switch (propValue.value.int32Values[0]) {
+                    case toInt(VehicleApPowerStateReport::DEEP_SLEEP_EXIT):
+                    case toInt(VehicleApPowerStateReport::SHUTDOWN_CANCELLED):
+                    case toInt(VehicleApPowerStateReport::WAIT_FOR_VHAL):
+                        // CPMS is in WAIT_FOR_VHAL state, simply move to ON
+                        doHalEvent(createApPowerStateReq(VehicleApPowerStateReq::ON, 0));
+                        break;
+                    case toInt(VehicleApPowerStateReport::DEEP_SLEEP_ENTRY):
+                    case toInt(VehicleApPowerStateReport::SHUTDOWN_START):
+                        // CPMS is in WAIT_FOR_FINISH state, send the FINISHED command
+                        doHalEvent(createApPowerStateReq(VehicleApPowerStateReq::FINISHED, 0));
+                        break;
+                    case toInt(VehicleApPowerStateReport::ON):
+                    case toInt(VehicleApPowerStateReport::SHUTDOWN_POSTPONE):
+                    case toInt(VehicleApPowerStateReport::SHUTDOWN_PREPARE):
+                        // Do nothing
+                        break;
+                    default:
+                        // Unknown state
+                        break;
+                }
+                break;
         }
     }
 
@@ -408,6 +424,18 @@
     return StatusCode::OK;
 }
 
+VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::createApPowerStateReq(
+    VehicleApPowerStateReq state, int32_t param) {
+    auto req = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 2);
+    req->prop = toInt(VehicleProperty::AP_POWER_STATE_REQ);
+    req->areaId = 0;
+    req->timestamp = elapsedRealtimeNano();
+    req->status = VehiclePropertyStatus::AVAILABLE;
+    req->value.int32Values[0] = toInt(state);
+    req->value.int32Values[1] = param;
+    return req;
+}
+
 VehicleHal::VehiclePropValuePtr EmulatedVehicleHal::createHwInputKeyProp(
     VehicleHwKeyInputAction action, int32_t keyCode, int32_t targetDisplay) {
     auto keyEvent = getValuePool()->obtain(VehiclePropertyType::INT32_VEC, 3);
diff --git a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
index ec59690..78895e3 100644
--- a/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
+++ b/automotive/vehicle/2.0/default/impl/vhal_v2_0/EmulatedVehicleHal.h
@@ -67,6 +67,7 @@
 
     StatusCode handleGenerateFakeDataRequest(const VehiclePropValue& request);
     void onFakeValueGenerated(const VehiclePropValue& value);
+    VehiclePropValuePtr createApPowerStateReq(VehicleApPowerStateReq req, int32_t param);
     VehiclePropValuePtr createHwInputKeyProp(VehicleHwKeyInputAction action, int32_t keyCode,
                                              int32_t targetDisplay);
 
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 4d07386..4751a76 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -1125,7 +1125,7 @@
     /**
      * Property to control power state of application processor
      *
-     * It is assumed that AP's power state is controller by separate power
+     * It is assumed that AP's power state is controlled by a separate power
      * controller.
      *
      * For configuration information, VehiclePropConfig.configArray can have bit flag combining
@@ -1136,7 +1136,7 @@
      *                    0 if not used.
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VEHICLE_PROP_ACCESS_READ
+     * @access VehiclePropertyAccess:READ
      */
     AP_POWER_STATE_REQ = (
         0x0A00
@@ -1155,7 +1155,7 @@
 
      *
      * @change_mode VehiclePropertyChangeMode:ON_CHANGE
-     * @access VEHICLE_PROP_ACCESS_WRITE
+     * @access VehiclePropertyAccess:WRITE
      */
     AP_POWER_STATE_REPORT = (
         0x0A01
@@ -2267,17 +2267,8 @@
 };
 
 enum VehicleApPowerStateReq : int32_t {
-    /** vehicle HAL will never publish this state to AP */
-    OFF = 0,
-
-    /** vehicle HAL will never publish this state to AP */
-    DEEP_SLEEP = 1,
-
-    /** AP is on but display must be off. */
-    ON_DISP_OFF = 2,
-
-    /** AP is on with display on. This state allows full user interaction. */
-    ON_FULL = 3,
+    /** Transition Android from WAIT_FOR_VHAL to ON state */
+    ON = 0,
 
     /**
      * The power controller has requested AP to shutdown. AP can either enter
@@ -2287,8 +2278,16 @@
      * system.
      *
      * int32Values[1] : one of enum_vehicle_ap_power_state_shutdown_param_type
+     *
+     * SHUTDOWN_PRPARE may be requested from either WAIT_FOR_VHAL or ON states.
      */
-    SHUTDOWN_PREPARE = 4,
+    SHUTDOWN_PREPARE = 1,
+
+    /** Cancel the shutdown and transition from SHUTDOWN_PREPARE to WAIT_FOR_VHAL state */
+    CANCEL_SHUTDOWN = 2,
+
+    /** VHAL is finished with shutdown procedures and ready for Android to suspend/shutdown */
+    FINISHED = 3,
 };
 
 /**
@@ -2314,26 +2313,30 @@
 
 enum VehicleApPowerStateReport : int32_t {
     /**
-     * AP has finished boot up, and can start shutdown if requested by power
-     * controller.
+     * Device has booted, CarService has initialized and is ready to accept commands from VHAL.
+     * Device starts in WAIT_FOR_VHAL state.  The user is not logged in, and vendor apps/services
+     * are expected to control the display and audio.
      */
-    BOOT_COMPLETE = 0x1,
+    WAIT_FOR_VHAL = 0x1,
 
     /**
-     * AP is entering deep sleep state. How this state is implemented may vary
-     * depending on each H/W, but AP's power must be kept in this state.
+     * AP is ready to suspend and has entered WAIT_FOR_FINISHED state.
+     *
+     * int32Values[1]: Time to turn on AP in secs. Power controller may turn on
+     *                 AP after specified time so that AP can run tasks like
+     *                 update. If it is set to 0, there is no wake up, and power
+     *                 controller may not necessarily support wake-up.
      */
     DEEP_SLEEP_ENTRY = 0x2,
 
     /**
-     * AP is exiting from deep sleep state, and is in
-     * VehicleApPowerState#SHUTDOWN_PREPARE state.
-     * The power controller may change state to other ON states based on the
-     * current state.
+     * AP is exiting from deep sleep state, and is in WAIT_FOR_VHAL state.
      */
     DEEP_SLEEP_EXIT = 0x3,
 
     /**
+     * AP remains in SHUTDOWN_PREPARE state as idle and cleanup tasks execute.
+     *
      * int32Values[1]: Time to postpone shutdown in ms. Maximum value can be
      *                 5000 ms.
      *                 If AP needs more time, it will send another POSTPONE
@@ -2342,63 +2345,31 @@
     SHUTDOWN_POSTPONE = 0x4,
 
     /**
-     * AP is starting shutting down. When system completes shutdown, everything
-     * will stop in AP as kernel will stop all other contexts. It is
-     * responsibility of vehicle HAL or lower level to synchronize that state
-     * with external power controller. As an example, some kind of ping
-     * with timeout in power controller can be a solution.
+     * AP is ready to shutdown and has entered WAIT_FOR_FINISHED state.
      *
      * int32Values[1]: Time to turn on AP in secs. Power controller may turn on
      *                 AP after specified time so that AP can run tasks like
      *                 update. If it is set to 0, there is no wake up, and power
-     *                 controller may not necessarily support wake-up. If power
-     *                 controller turns on AP due to timer, it must start with
-     *                 VehicleApPowerState#ON_DISP_OFF state, and after
-     *                 receiving VehicleApPowerSetState#BOOT_COMPLETE, it shall
-     *                 do state transition to
-     *                 VehicleApPowerState#SHUTDOWN_PREPARE.
+     *                 controller may not necessarily support wake-up.
      */
     SHUTDOWN_START = 0x5,
 
     /**
-     * User has requested to turn off headunit's display, which is detected in
-     * android side.
-     * The power controller may change the power state to
-     * VehicleApPowerState#ON_DISP_OFF.
+     * AP has transitioned from WAIT_FOR_VHAL state to ON.
      */
-    DISPLAY_OFF = 0x6,
+    ON = 0x6,
 
     /**
-     * User has requested to turn on headunit's display, most probably from power
-     * key input which is attached to headunit. The power controller may change
-     * the power state to VehicleApPowerState#ON_FULL.
+     * AP has transitions to SHUTDOWN_PREPARE state.  In this state, Garage Mode will execute idle
+     * tasks, and other services that have registered for this state transition may execute
+     * cleanup activities.
      */
-    DISPLAY_ON = 0x7,
-};
-
-/**
- * Enum to represent bootup reason.
- */
-enum VehicleApPowerBootupReason : int32_t {
-    /**
-     * Power on due to user's pressing of power key or rotating of ignition
-     * switch.
-     */
-    USER_POWER_ON = 0,
+    SHUTDOWN_PREPARE = 0x7,
 
     /**
-     * Automatic power on triggered by door unlock or any other kind of automatic
-     * user detection.
+     * AP has transitioned from SHUTDOWN_PREPARE state to WAIT_FOR_VHAL.
      */
-    USER_UNLOCK = 1,
-
-    /**
-     * Automatic power on triggered by timer. This only happens when AP has asked
-     * wake-up after
-     * certain time through time specified in
-     * VehicleApPowerSetState#SHUTDOWN_START.
-     */
-    TIMER = 2,
+    SHUTDOWN_CANCELLED = 0x8,
 };
 
 enum VehicleHwKeyInputAction : int32_t {
diff --git a/boot/1.0/default/Android.mk b/boot/1.0/default/Android.mk
new file mode 100644
index 0000000..7ccc4c8
--- /dev/null
+++ b/boot/1.0/default/Android.mk
@@ -0,0 +1,30 @@
+# TODO(connoro): Remove this file once we eliminate existing usage of
+# PRODUCT_STATIC_BOOT_CONTROL_HAL
+
+LOCAL_PATH := $(call my-dir)
+
+ifneq ($(strip $(PRODUCT_STATIC_BOOT_CONTROL_HAL)),)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := android.hardware.boot@1.0-impl-wrapper.recovery
+LOCAL_MODULE_CLASS := SHARED_LIBRARIES
+LOCAL_MULTILIB := first
+ifeq ($(TARGET_IS_64_BIT),true)
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/lib64/hw
+else
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/system/lib/hw
+endif
+LOCAL_SRC_FILES := BootControl.cpp
+LOCAL_CFLAGS := -DBOOT_CONTROL_RECOVERY
+LOCAL_SHARED_LIBRARIES := \
+    libbase.recovery \
+    liblog.recovery \
+    libhidlbase.recovery \
+    libhidltransport.recovery \
+    libhardware.recovery \
+    libutils.recovery \
+    android.hardware.boot@1.0.recovery
+LOCAL_STATIC_LIBRARIES := $(PRODUCT_STATIC_BOOT_CONTROL_HAL)
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/boot/1.0/default/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/broadcastradio/common/utils2x/Android.bp b/broadcastradio/common/utils2x/Android.bp
index aab94f2..df2cefe 100644
--- a/broadcastradio/common/utils2x/Android.bp
+++ b/broadcastradio/common/utils2x/Android.bp
@@ -22,6 +22,7 @@
         "-Wall",
         "-Wextra",
         "-Werror",
+        "-Wno-error=implicit-fallthrough",
     ],
     cppflags: [
         "-std=c++1z",
diff --git a/broadcastradio/common/utils2x/Utils.cpp b/broadcastradio/common/utils2x/Utils.cpp
index 3e20b35..f292c08 100644
--- a/broadcastradio/common/utils2x/Utils.cpp
+++ b/broadcastradio/common/utils2x/Utils.cpp
@@ -215,7 +215,7 @@
             break;
         case IdentifierType::DAB_FREQUENCY:
             expect(val > 100000u, "f > 100MHz");
-        // fallthrough
+            [[fallthrough]];
         case IdentifierType::AMFM_FREQUENCY:
         case IdentifierType::DRMO_FREQUENCY:
             expect(val > 100u, "f > 100kHz");
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/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/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/default/ExternalCameraDeviceSession.cpp b/camera/device/3.4/default/ExternalCameraDeviceSession.cpp
index 350f48b..653ad59 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(
@@ -2088,6 +2092,7 @@
                 ALOGI("%s: BLOB format does not support dataSpace %x", __FUNCTION__, ds);
                 return false;
             }
+            break;
         case PixelFormat::IMPLEMENTATION_DEFINED:
         case PixelFormat::YCBCR_420_888:
         case PixelFormat::YV12:
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/default/CameraDeviceSession.cpp b/camera/device/3.5/default/CameraDeviceSession.cpp
index 5336ca9..963893a 100644
--- a/camera/device/3.5/default/CameraDeviceSession.cpp
+++ b/camera/device/3.5/default/CameraDeviceSession.cpp
@@ -48,11 +48,9 @@
 }
 
 Return<void> CameraDeviceSession::configureStreams_3_5(
-        const StreamConfiguration& /*requestedConfiguration*/,
+        const StreamConfiguration& requestedConfiguration,
         ICameraDeviceSession::configureStreams_3_5_cb _hidl_cb)  {
-    HalStreamConfiguration outStreams;
-    _hidl_cb(Status::OPERATION_NOT_SUPPORTED, outStreams);
-    return Void();
+    return configureStreams_3_4(requestedConfiguration.v3_4, _hidl_cb);
 }
 
 Return<void> CameraDeviceSession::signalStreamFlush(
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/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/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.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 619ba46..bc453d8 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -317,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>
@@ -390,6 +398,7 @@
     <hal format="hidl" optional="true">
         <name>android.hardware.thermal</name>
         <version>1.0-1</version>
+        <version>2.0</version>
         <interface>
             <name>IThermal</name>
             <instance>default</instance>
diff --git a/configstore/1.2/Android.bp b/configstore/1.2/Android.bp
index cc5644c..c525a72 100644
--- a/configstore/1.2/Android.bp
+++ b/configstore/1.2/Android.bp
@@ -12,8 +12,8 @@
     interfaces: [
         "android.hardware.configstore@1.1",
         "android.hardware.configstore@1.0",
-        "android.hardware.graphics.common@1.1",
+        "android.hardware.graphics.common@1.2",
         "android.hidl.base@1.0",
     ],
     gen_java: true,
-}
\ No newline at end of file
+}
diff --git a/configstore/1.2/ISurfaceFlingerConfigs.hal b/configstore/1.2/ISurfaceFlingerConfigs.hal
index c879155..9553fca 100644
--- a/configstore/1.2/ISurfaceFlingerConfigs.hal
+++ b/configstore/1.2/ISurfaceFlingerConfigs.hal
@@ -15,8 +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 android.hardware.graphics.common@1.2::Dataspace;
 import @1.1::ISurfaceFlingerConfigs;
 import @1.0::OptionalBool;
 
diff --git a/configstore/1.2/default/SurfaceFlingerConfigs.cpp b/configstore/1.2/default/SurfaceFlingerConfigs.cpp
index ae19dc0..b78d15e 100644
--- a/configstore/1.2/default/SurfaceFlingerConfigs.cpp
+++ b/configstore/1.2/default/SurfaceFlingerConfigs.cpp
@@ -26,8 +26,8 @@
 namespace V1_2 {
 namespace implementation {
 
-using ::android::hardware::graphics::common::V1_1::Dataspace;
 using ::android::hardware::graphics::common::V1_1::PixelFormat;
+using ::android::hardware::graphics::common::V1_2::Dataspace;
 
 // ::android::hardware::configstore::V1_0::ISurfaceFlingerConfigs implementation.
 Return<void> SurfaceFlingerConfigs::vsyncEventPhaseOffsetNs(vsyncEventPhaseOffsetNs_cb _hidl_cb) {
diff --git a/fastboot/1.0/Android.bp b/fastboot/1.0/Android.bp
index 3267499..467fc6d 100644
--- a/fastboot/1.0/Android.bp
+++ b/fastboot/1.0/Android.bp
@@ -14,9 +14,10 @@
         "android.hidl.base@1.0",
     ],
     types: [
-        "Status",
+        "FileSystemType",
         "Result",
+        "Status",
     ],
-    gen_java: false,
+    gen_java: true,
 }
 
diff --git a/graphics/common/1.2/Android.bp b/graphics/common/1.2/Android.bp
new file mode 100644
index 0000000..a86f3b5
--- /dev/null
+++ b/graphics/common/1.2/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.graphics.common@1.2",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+        support_system_process: true,
+    },
+    srcs: [
+        "types.hal",
+    ],
+    interfaces: [
+        "android.hardware.graphics.common@1.0",
+        "android.hardware.graphics.common@1.1",
+    ],
+    types: [
+        "Dataspace",
+    ],
+    gen_java: true,
+    gen_java_constants: true,
+}
+
diff --git a/graphics/common/1.2/types.hal b/graphics/common/1.2/types.hal
new file mode 100644
index 0000000..cf4e34a
--- /dev/null
+++ b/graphics/common/1.2/types.hal
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.graphics.common@1.2;
+
+import @1.1::BufferUsage;
+import @1.1::ColorMode;
+import @1.1::Dataspace;
+import @1.1::PixelFormat;
+
+@export(name="android_dataspace_v1_2_t", value_prefix="HAL_DATASPACE_",
+        export_parent="false")
+enum Dataspace : @1.1::Dataspace {
+    /**
+     * ITU-R Recommendation 2020 (BT.2020)
+     *
+     * Ultra High-definition television
+     *
+     * Use full range, sRGB transfer and BT2020 standard
+     */
+    DISPLAY_BT2020 = STANDARD_BT2020 | TRANSFER_SRGB | RANGE_FULL,
+};
+
+enum ColorMode : @1.1::ColorMode {
+    /**
+     * DISPLAY_BT2020 corresponds with display settings that implement the ITU-R
+     * Recommendation BT.2020 / Rec. 2020 for UHDTV, but specifies an SRGB
+     * transfer function.
+     *
+     * Primaries:
+     *                  x       y
+     *  green           0.170   0.797
+     *  blue            0.131   0.046
+     *  red             0.708   0.292
+     *  white (D65)     0.3127  0.3290
+     *
+     * Transfer Function is sRGB
+     */
+    DISPLAY_BT2020 = 13,
+};
diff --git a/graphics/composer/2.3/Android.bp b/graphics/composer/2.3/Android.bp
index 78da099..6d29348 100644
--- a/graphics/composer/2.3/Android.bp
+++ b/graphics/composer/2.3/Android.bp
@@ -13,6 +13,7 @@
     interfaces: [
         "android.hardware.graphics.common@1.0",
         "android.hardware.graphics.common@1.1",
+        "android.hardware.graphics.common@1.2",
         "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 089438e..dec3b25 100644
--- a/graphics/composer/2.3/IComposerClient.hal
+++ b/graphics/composer/2.3/IComposerClient.hal
@@ -16,6 +16,10 @@
 
 package android.hardware.graphics.composer@2.3;
 
+import android.hardware.graphics.common@1.1::RenderIntent;
+import android.hardware.graphics.common@1.1::PixelFormat;
+import android.hardware.graphics.common@1.2::ColorMode;
+import android.hardware.graphics.common@1.2::Dataspace;
 import android.hardware.graphics.composer@2.1::IComposerClient.Command;
 import @2.2::IComposerClient;
 import @2.1::Display;
@@ -87,6 +91,75 @@
                generates (Error error,
                           uint8_t port,
                           vec<uint8_t> data);
+    /**
+     * getReadbackBufferAttributes_2_3
+     * Returns the format which should be used when allocating a buffer for use by
+     * device readback as well as the dataspace in which its contents must be
+     * interpreted.
+     *
+     * The width and height of this buffer must be those of the currently-active
+     * display configuration, and the usage flags must consist of the following:
+     *   BufferUsage::CPU_READ | BufferUsage::GPU_TEXTURE |
+     *   BufferUsage::COMPOSER_OUTPUT
+     *
+     * The format and dataspace provided must be sufficient such that if a
+     * correctly-configured buffer is passed into setReadbackBuffer, filled by
+     * the device, and then displayed by the client as a full-screen buffer, the
+     * output of the display remains the same (subject to the note about protected
+     * content in the description of setReadbackBuffer).
+     *
+     * If the active configuration or color mode of this display has changed
+     * since a previous call to this function, it must be called again prior to
+     * setting a readback buffer such that the returned format and dataspace will
+     * be updated accordingly.
+     *
+     * Parameters:
+     * @param display - the display on which to create the layer.
+     *
+     * @return format - the format the client should use when allocating a device
+     *     readback buffer
+     * @return dataspace - the dataspace to use when interpreting the
+     *     contents of a device readback buffer
+     * @return error is NONE upon success. Otherwise,
+     *     BAD_DISPLAY when an invalid display handle was passed in.
+     *     UNSUPPORTED if not supported on underlying HAL
+     *
+     * See also:
+     *   setReadbackBuffer
+     *   getReadbackBufferFence
+     */
+    getReadbackBufferAttributes_2_3(Display display)
+        generates (Error error,
+                   PixelFormat format,
+                   Dataspace dataspace);
+
+    /**
+     * getClientTargetSupport_2_3
+     * Returns whether a client target with the given properties can be
+     * handled by the device.
+     *
+     * This function must return true for a client target with width and
+     * height equal to the active display configuration dimensions,
+     * PixelFormat::RGBA_8888, and Dataspace::UNKNOWN. It is not required to
+     * return true for any other configuration.
+     *
+     * @param display is the display to query.
+     * @param width is the client target width in pixels.
+     * @param height is the client target height in pixels.
+     * @param format is the client target format.
+     * @param dataspace is the client target dataspace, as described in
+     *     setLayerDataspace.
+     * @return error is NONE upon success. Otherwise,
+     *     BAD_DISPLAY when an invalid display handle was passed in.
+     *     UNSUPPORTED when the given configuration is not supported.
+     */
+    @callflow(next="*")
+    getClientTargetSupport_2_3(Display display,
+                               uint32_t width,
+                               uint32_t height,
+                               PixelFormat format,
+                               Dataspace dataspace)
+                    generates (Error error);
 
     /**
      * Executes commands from the input command message queue. Return values
@@ -113,4 +186,58 @@
                         bool outQueueChanged,
                         uint32_t outLength,
                         vec<handle> outHandles);
+
+    /**
+     * Returns the render intents supported by the specified display and color
+     * mode.
+     *
+     * For SDR color modes, RenderIntent::COLORIMETRIC must be supported. For
+     * HDR color modes, RenderIntent::TONE_MAP_COLORIMETRIC must be supported.
+     *
+     * @param display is the display to query.
+     * @param mode is the color mode to query.
+     * @return error is NONE upon success. Otherwise,
+     *     BAD_DISPLAY when an invalid display handle was passed in.
+     *     BAD_PARAMETER when an invalid color mode was passed in.
+     * @return intents is an array of render intents.
+     */
+    getRenderIntents_2_3(Display display, ColorMode mode)
+          generates (Error error,
+                     vec<RenderIntent> intents);
+
+    /**
+     * Returns the color modes supported on this display.
+     *
+     * All devices must support at least ColorMode::NATIVE.
+     *
+     * @param display is the display to query.
+     * @return error is NONE upon success. Otherwise,
+     *     BAD_DISPLAY when an invalid display handle was passed in.
+     * @return modes is an array of color modes.
+     */
+    getColorModes_2_3(Display display)
+           generates (Error error,
+                      vec<ColorMode> modes);
+
+    /**
+     * Sets the color mode and render intent of the given display.
+     *
+     * The color mode and render intent change must take effect on next
+     * presentDisplay.
+     *
+     * All devices must support at least ColorMode::NATIVE and
+     * RenderIntent::COLORIMETRIC, and displays are assumed to be in this mode
+     * upon hotplug.
+     *
+     * @param display is the display to which the color mode is set.
+     * @param mode is the color mode to set to.
+     * @param intent is the render intent to set to.
+     * @return error is NONE upon success. Otherwise,
+     *     BAD_DISPLAY when an invalid display handle was passed in.
+     *     BAD_PARAMETER when mode or intent is invalid
+     *     UNSUPPORTED when mode or intent is not supported on this
+     *         display.
+     */
+    setColorMode_2_3(Display display, ColorMode mode, RenderIntent intent)
+          generates (Error error);
 };
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
index 3f7b2c9..6c95a1f 100644
--- 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
@@ -34,6 +34,7 @@
 namespace V2_3 {
 
 using android::hardware::MessageQueue;
+using android::hardware::graphics::common::V1_2::Dataspace;
 using android::hardware::graphics::composer::V2_1::Error;
 using android::hardware::graphics::composer::V2_1::IComposerCallback;
 using android::hardware::graphics::composer::V2_1::Layer;
@@ -43,6 +44,16 @@
 // units of uint32_t's.
 class CommandWriterBase : public V2_2::CommandWriterBase {
    public:
+    void setLayerDataspace(Dataspace dataspace) {
+        setLayerDataspaceInternal(static_cast<int32_t>(dataspace));
+    }
+
+    void setClientTarget(uint32_t slot, const native_handle_t* target, int acquireFence,
+                         Dataspace dataspace, const std::vector<IComposerClient::Rect>& damage) {
+        setClientTargetInternal(slot, target, acquireFence, static_cast<int32_t>(dataspace),
+                                damage);
+    }
+
     CommandWriterBase(uint32_t initialMaxSize) : V2_2::CommandWriterBase(initialMaxSize) {}
 
     static constexpr uint16_t kSetLayerColorTransformLength = 16;
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 c805472..90603a7 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
@@ -38,6 +38,52 @@
 template <typename Interface, typename Hal>
 class ComposerClientImpl : public V2_2::hal::detail::ComposerClientImpl<Interface, Hal> {
    public:
+    Return<Error> setColorMode_2_3(Display display, ColorMode mode, RenderIntent intent) override {
+#ifndef USES_DISPLAY_RENDER_INTENTS
+        if (intent != RenderIntent::COLORIMETRIC) {
+            return Error::BAD_PARAMETER;
+        }
+#endif
+        return mHal->setColorMode_2_3(display, mode, intent);
+    }
+
+    Return<void> getRenderIntents_2_3(Display display, ColorMode mode,
+                                      IComposerClient::getRenderIntents_2_3_cb hidl_cb) override {
+#ifdef USES_DISPLAY_RENDER_INTENTS
+        std::vector<RenderIntent> intents;
+        Error err = mHal->getRenderIntents_2_3(display, mode, &intents);
+        hidl_cb(err, intents);
+#else
+        (void)display;
+        (void)mode;
+        hidl_cb(Error::NONE, hidl_vec<RenderIntent>({RenderIntent::COLORIMETRIC}));
+#endif
+        return Void();
+    }
+
+    Return<void> getColorModes_2_3(Display display,
+                                   IComposerClient::getColorModes_2_3_cb hidl_cb) override {
+        hidl_vec<ColorMode> modes;
+        Error err = mHal->getColorModes_2_3(display, &modes);
+        hidl_cb(err, modes);
+        return Void();
+    }
+
+    Return<void> getReadbackBufferAttributes_2_3(
+        Display display, IComposerClient::getReadbackBufferAttributes_2_3_cb hidl_cb) override {
+        PixelFormat format = PixelFormat::RGB_888;
+        Dataspace dataspace = Dataspace::UNKNOWN;
+        Error error = mHal->getReadbackBufferAttributes_2_3(display, &format, &dataspace);
+        hidl_cb(error, format, dataspace);
+        return Void();
+    }
+
+    Return<Error> getClientTargetSupport_2_3(Display display, uint32_t width, uint32_t height,
+                                             PixelFormat format, Dataspace dataspace) override {
+        Error err = mHal->getClientTargetSupport_2_3(display, width, height, format, dataspace);
+        return err;
+    }
+
     static std::unique_ptr<ComposerClientImpl> create(Hal* hal) {
         auto client = std::make_unique<ComposerClientImpl>(hal);
         return client->init() ? std::move(client) : nullptr;
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 0f6205a..27efc2b 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
@@ -25,12 +25,50 @@
 namespace V2_3 {
 namespace hal {
 
+using common::V1_1::PixelFormat;
+using common::V1_1::RenderIntent;
+using common::V1_2::ColorMode;
+using common::V1_2::Dataspace;
 using V2_1::Display;
 using V2_1::Error;
 using V2_1::Layer;
 
 class ComposerHal : public V2_2::hal::ComposerHal {
    public:
+    Error setColorMode_2_2(Display display, common::V1_1::ColorMode mode,
+                           RenderIntent intent) override {
+        return setColorMode_2_3(display, static_cast<ColorMode>(mode), intent);
+    }
+
+    Error getColorModes_2_2(Display display, hidl_vec<common::V1_1::ColorMode>* outModes) override {
+        return getColorModes_2_3(display, reinterpret_cast<hidl_vec<ColorMode>*>(outModes));
+    }
+
+    Error getClientTargetSupport_2_2(Display display, uint32_t width, uint32_t height,
+                                     common::V1_1::PixelFormat format,
+                                     common::V1_1::Dataspace dataspace) override {
+        return getClientTargetSupport_2_3(display, width, height, static_cast<PixelFormat>(format),
+                                          static_cast<Dataspace>(dataspace));
+    }
+
+    Error getReadbackBufferAttributes(Display display, common::V1_1::PixelFormat* outFormat,
+                                      common::V1_1::Dataspace* outDataspace) override {
+        return getReadbackBufferAttributes_2_3(display, reinterpret_cast<PixelFormat*>(outFormat),
+                                               reinterpret_cast<Dataspace*>(outDataspace));
+    }
+
+    virtual Error setColorMode_2_3(Display display, ColorMode mode, RenderIntent intent) = 0;
+
+    virtual Error getRenderIntents_2_3(Display display, ColorMode mode,
+                                       std::vector<RenderIntent>* outIntents) = 0;
+
+    virtual Error getColorModes_2_3(Display display, hidl_vec<ColorMode>* outModes) = 0;
+
+    virtual Error getClientTargetSupport_2_3(Display display, uint32_t width, uint32_t height,
+                                             PixelFormat format, Dataspace dataspace) = 0;
+    virtual Error getReadbackBufferAttributes_2_3(Display display, PixelFormat* outFormat,
+                                                  Dataspace* outDataspace) = 0;
+
     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;
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 ed1878b..df68f58 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
@@ -34,6 +34,10 @@
 
 namespace detail {
 
+using common::V1_1::PixelFormat;
+using common::V1_1::RenderIntent;
+using common::V1_2::ColorMode;
+using common::V1_2::Dataspace;
 using V2_1::Display;
 using V2_1::Error;
 
@@ -41,6 +45,32 @@
 template <typename Hal>
 class HwcHalImpl : public V2_2::passthrough::detail::HwcHalImpl<Hal> {
    public:
+    Error setColorMode_2_3(Display display, ColorMode mode, RenderIntent intent) override {
+        return setColorMode_2_2(display, static_cast<common::V1_1::ColorMode>(mode), intent);
+    }
+
+    Error getRenderIntents_2_3(Display display, ColorMode mode,
+                               std::vector<RenderIntent>* outIntents) override {
+        return getRenderIntents(display, static_cast<common::V1_1::ColorMode>(mode), outIntents);
+    }
+
+    Error getColorModes_2_3(Display display, hidl_vec<ColorMode>* outModes) override {
+        return getColorModes_2_2(display,
+                                 reinterpret_cast<hidl_vec<common::V1_1::ColorMode>*>(outModes));
+    }
+
+    Error getClientTargetSupport_2_3(Display display, uint32_t width, uint32_t height,
+                                     PixelFormat format, Dataspace dataspace) override {
+        return getClientTargetSupport_2_2(display, width, height, format,
+                                          static_cast<common::V1_1::Dataspace>(dataspace));
+    }
+
+    Error getReadbackBufferAttributes_2_3(Display display, PixelFormat* outFormat,
+                                          Dataspace* outDataspace) override {
+        return getReadbackBufferAttributes(
+            display, outFormat, reinterpret_cast<common::V1_1::Dataspace*>(outDataspace));
+    }
+
     Error getDisplayIdentificationData(Display display, uint8_t* outPort,
                                        std::vector<uint8_t>* outData) override {
         if (!mDispatch.getDisplayIdentificationData) {
@@ -96,6 +126,11 @@
     using BaseType2_2 = V2_2::passthrough::detail::HwcHalImpl<Hal>;
     using BaseType2_1 = V2_1::passthrough::detail::HwcHalImpl<Hal>;
     using BaseType2_1::mDevice;
+    using BaseType2_2::getClientTargetSupport_2_2;
+    using BaseType2_2::getColorModes_2_2;
+    using BaseType2_2::getReadbackBufferAttributes;
+    using BaseType2_2::getRenderIntents;
+    using BaseType2_2::setColorMode_2_2;
 };
 
 }  // namespace detail
diff --git a/graphics/composer/2.3/utils/vts/ComposerVts.cpp b/graphics/composer/2.3/utils/vts/ComposerVts.cpp
index f1d3a50..656c8c4 100644
--- a/graphics/composer/2.3/utils/vts/ComposerVts.cpp
+++ b/graphics/composer/2.3/utils/vts/ComposerVts.cpp
@@ -45,6 +45,10 @@
     return client;
 }
 
+sp<IComposerClient> ComposerClient::getRaw() const {
+    return mClient;
+}
+
 bool ComposerClient::getDisplayIdentificationData(Display display, uint8_t* outPort,
                                                   std::vector<uint8_t>* outData) {
     bool supported = true;
@@ -64,6 +68,46 @@
     return supported;
 }
 
+std::vector<ColorMode> ComposerClient::getColorModes_2_3(Display display) {
+    std::vector<ColorMode> modes;
+    mClient->getColorModes_2_3(display, [&](const auto& tmpError, const auto& tmpModes) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get color modes";
+        modes = tmpModes;
+    });
+    return modes;
+}
+
+void ComposerClient::setColorMode_2_3(Display display, ColorMode mode, RenderIntent intent) {
+    Error error = mClient->setColorMode_2_3(display, mode, intent);
+    ASSERT_TRUE(error == Error::NONE || error == Error::UNSUPPORTED) << "failed to set color mode";
+}
+
+std::vector<RenderIntent> ComposerClient::getRenderIntents_2_3(Display display, ColorMode mode) {
+    std::vector<RenderIntent> intents;
+    mClient->getRenderIntents_2_3(display, mode, [&](const auto& tmpError, const auto& tmpIntents) {
+        ASSERT_EQ(Error::NONE, tmpError) << "failed to get render intents";
+        intents = tmpIntents;
+    });
+    return intents;
+}
+
+void ComposerClient::getReadbackBufferAttributes_2_3(Display display, PixelFormat* outPixelFormat,
+                                                     Dataspace* outDataspace) {
+    mClient->getReadbackBufferAttributes_2_3(
+        display,
+        [&](const auto& tmpError, const auto& tmpOutPixelFormat, const auto& tmpOutDataspace) {
+            ASSERT_EQ(Error::NONE, tmpError) << "failed to get readback buffer attributes";
+            *outPixelFormat = tmpOutPixelFormat;
+            *outDataspace = tmpOutDataspace;
+        });
+}
+
+bool ComposerClient::getClientTargetSupport_2_3(Display display, uint32_t width, uint32_t height,
+                                                PixelFormat format, Dataspace dataspace) {
+    Error error = mClient->getClientTargetSupport_2_3(display, width, height, format, dataspace);
+    return error == Error::NONE;
+}
+
 }  // namespace vts
 }  // namespace V2_3
 }  // namespace composer
diff --git a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
index 103b85a..ec1a2a1 100644
--- a/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
+++ b/graphics/composer/2.3/utils/vts/include/composer-vts/2.3/ComposerVts.h
@@ -32,6 +32,10 @@
 namespace V2_3 {
 namespace vts {
 
+using common::V1_1::PixelFormat;
+using common::V1_1::RenderIntent;
+using common::V1_2::ColorMode;
+using common::V1_2::Dataspace;
 using V2_1::Display;
 using V2_3::IComposer;
 using V2_3::IComposerClient;
@@ -59,9 +63,23 @@
     explicit ComposerClient(const sp<IComposerClient>& client)
         : V2_2::vts::ComposerClient(client), mClient(client) {}
 
+    sp<IComposerClient> getRaw() const;
+
     bool getDisplayIdentificationData(Display display, uint8_t* outPort,
                                       std::vector<uint8_t>* outData);
 
+    std::vector<ColorMode> getColorModes_2_3(Display display);
+
+    void setColorMode_2_3(Display display, ColorMode mode, RenderIntent intent);
+
+    std::vector<RenderIntent> getRenderIntents_2_3(Display display, ColorMode mode);
+
+    void getReadbackBufferAttributes_2_3(Display display, PixelFormat* outPixelFormat,
+                                         Dataspace* outDataspace);
+
+    bool getClientTargetSupport_2_3(Display display, uint32_t width, uint32_t height,
+                                    PixelFormat format, Dataspace dataspace);
+
    private:
     const sp<IComposerClient> mClient;
 };
diff --git a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
index 1030ddc..3ca21aa 100644
--- a/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
+++ b/graphics/composer/2.3/vts/functional/VtsHalGraphicsComposerV2_3TargetTest.cpp
@@ -33,6 +33,11 @@
 namespace vts {
 namespace {
 
+using common::V1_1::PixelFormat;
+using common::V1_1::RenderIntent;
+using common::V1_2::ColorMode;
+using common::V1_2::Dataspace;
+
 // Test environment for graphics.composer
 class GraphicsComposerHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
    public:
@@ -64,6 +69,8 @@
         // assume the first display is primary and is never removed
         mPrimaryDisplay = waitForFirstDisplay();
 
+        mInvalidDisplayId = GetInvalidDisplayId();
+
         // explicitly disable vsync
         mComposerClient->setVsyncEnabled(mPrimaryDisplay, false);
         mComposerCallback->setVsyncAllowed(false);
@@ -80,6 +87,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;
+    }
+
     void execute() { mComposerClient->execute(mReader.get(), mWriter.get()); }
 
     // use the slot count usually set by SF
@@ -90,6 +113,7 @@
     sp<V2_1::vts::GraphicsComposerCallback> mComposerCallback;
     // the first display and is assumed never to be removed
     Display mPrimaryDisplay;
+    Display mInvalidDisplayId;
     std::unique_ptr<CommandWriterBase> mWriter;
     std::unique_ptr<V2_1::vts::TestCommandReader> mReader;
 
@@ -128,6 +152,185 @@
 }
 
 /**
+ * TestIComposerClient::getReadbackBufferAttributes_2_3
+ */
+TEST_F(GraphicsComposerHidlTest, GetReadbackBufferAttributes_2_3) {
+    Dataspace dataspace;
+    PixelFormat pixelFormat;
+
+    ASSERT_NO_FATAL_FAILURE(mComposerClient->getReadbackBufferAttributes_2_3(
+        mPrimaryDisplay, &pixelFormat, &dataspace));
+}
+
+/**
+ * Test IComposerClient::getClientTargetSupport_2_3
+ */
+TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport_2_3) {
+    std::vector<V2_1::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);
+
+        ASSERT_TRUE(mComposerClient->getClientTargetSupport_2_3(
+            mPrimaryDisplay, width, height, PixelFormat::RGBA_8888, Dataspace::UNKNOWN));
+    }
+}
+/**
+ * Test IComposerClient::getClientTargetSupport_2_3
+ *
+ * Test that IComposerClient::getClientTargetSupport_2_3 returns
+ * Error::BAD_DISPLAY when passed in an invalid display handle
+ */
+
+TEST_F(GraphicsComposerHidlTest, GetClientTargetSupport_2_3BadDisplay) {
+    std::vector<V2_1::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_3(
+            mInvalidDisplayId, width, height, PixelFormat::RGBA_8888, Dataspace::UNKNOWN);
+
+        EXPECT_EQ(Error::BAD_DISPLAY, error);
+    }
+}
+
+/**
+ * Test IComposerClient::getRenderIntents_2_3
+ */
+TEST_F(GraphicsComposerHidlTest, GetRenderIntents_2_3) {
+    std::vector<ColorMode> modes = mComposerClient->getColorModes_2_3(mPrimaryDisplay);
+    for (auto mode : modes) {
+        std::vector<RenderIntent> intents =
+            mComposerClient->getRenderIntents_2_3(mPrimaryDisplay, mode);
+
+        bool isHdr;
+        switch (mode) {
+            case ColorMode::BT2100_PQ:
+            case ColorMode::BT2100_HLG:
+                isHdr = true;
+                break;
+            default:
+                isHdr = false;
+                break;
+        }
+        RenderIntent requiredIntent =
+            isHdr ? RenderIntent::TONE_MAP_COLORIMETRIC : RenderIntent::COLORIMETRIC;
+
+        auto iter = std::find(intents.cbegin(), intents.cend(), requiredIntent);
+        EXPECT_NE(intents.cend(), iter);
+    }
+}
+
+/*
+ * Test IComposerClient::getRenderIntents_2_3
+ *
+ * Test that IComposerClient::getRenderIntents_2_3 returns Error::BAD_DISPLAY when
+ * passed an invalid display handle
+ */
+TEST_F(GraphicsComposerHidlTest, GetRenderIntents_2_3BadDisplay) {
+    std::vector<ColorMode> modes = mComposerClient->getColorModes_2_3(mPrimaryDisplay);
+    for (auto mode : modes) {
+        mComposerClient->getRaw()->getRenderIntents_2_3(
+            mInvalidDisplayId, mode,
+            [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_DISPLAY, tmpError); });
+    }
+}
+
+/*
+ * Test IComposerClient::getRenderIntents_2_3
+ *
+ * Test that IComposerClient::getRenderIntents_2_3 returns Error::BAD_PARAMETER when
+ * pased either an invalid Color mode or an invalid Render Intent
+ */
+TEST_F(GraphicsComposerHidlTest, GetRenderIntents_2_3BadParameter) {
+    mComposerClient->getRaw()->getRenderIntents_2_3(
+        mPrimaryDisplay, static_cast<ColorMode>(-1),
+        [&](const auto& tmpError, const auto&) { EXPECT_EQ(Error::BAD_PARAMETER, tmpError); });
+}
+
+/**
+ * IComposerClient::getColorModes_2_3
+ */
+TEST_F(GraphicsComposerHidlTest, GetColorModes_2_3) {
+    std::vector<ColorMode> colorModes = mComposerClient->getColorModes_2_3(mPrimaryDisplay);
+
+    auto native = std::find(colorModes.cbegin(), colorModes.cend(), ColorMode::NATIVE);
+    ASSERT_NE(colorModes.cend(), native);
+}
+
+/*
+ * Test IComposerClient::getColorModes_2_3
+ *
+ * Test that IComposerClient::getColorModes_2_3 returns Error::BAD_DISPLAY when
+ * passed an invalid display handle
+ */
+TEST_F(GraphicsComposerHidlTest, GetColorMode_2_3BadDisplay) {
+    mComposerClient->getRaw()->getColorModes_2_3(
+        mInvalidDisplayId,
+        [&](const auto& tmpError, const auto&) { ASSERT_EQ(Error::BAD_DISPLAY, tmpError); });
+}
+
+/**
+ * IComposerClient::setColorMode_2_3
+ */
+TEST_F(GraphicsComposerHidlTest, SetColorMode_2_3) {
+    std::vector<ColorMode> colorModes = mComposerClient->getColorModes_2_3(mPrimaryDisplay);
+    for (auto mode : colorModes) {
+        std::vector<RenderIntent> intents =
+            mComposerClient->getRenderIntents_2_3(mPrimaryDisplay, mode);
+        for (auto intent : intents) {
+            ASSERT_NO_FATAL_FAILURE(
+                mComposerClient->setColorMode_2_3(mPrimaryDisplay, mode, intent));
+        }
+    }
+
+    ASSERT_NO_FATAL_FAILURE(mComposerClient->setColorMode_2_3(mPrimaryDisplay, ColorMode::NATIVE,
+                                                              RenderIntent::COLORIMETRIC));
+}
+
+/*
+ * Test IComposerClient::setColorMode_2_3
+ *
+ * Test that IComposerClient::setColorMode_2_3 returns an Error::BAD_DISPLAY
+ * when passed an invalid display handle
+ */
+TEST_F(GraphicsComposerHidlTest, SetColorMode_2_3BadDisplay) {
+    Error error = mComposerClient->getRaw()->setColorMode_2_3(mInvalidDisplayId, ColorMode::NATIVE,
+                                                              RenderIntent::COLORIMETRIC);
+
+    ASSERT_EQ(Error::BAD_DISPLAY, error);
+}
+
+/*
+ * Test IComposerClient::setColorMode_2_3
+ *
+ * Test that IComposerClient::setColorMode_2_3 returns Error::BAD_PARAMETER when
+ * passed an invalid Color mode or an invalid render intent
+ */
+TEST_F(GraphicsComposerHidlTest, SetColorMode_2_3BadParameter) {
+    Error colorModeError = mComposerClient->getRaw()->setColorMode_2_3(
+        mPrimaryDisplay, static_cast<ColorMode>(-1), RenderIntent::COLORIMETRIC);
+    EXPECT_EQ(Error::BAD_PARAMETER, colorModeError);
+
+    Error renderIntentError = mComposerClient->getRaw()->setColorMode_2_3(
+        mPrimaryDisplay, ColorMode::NATIVE, static_cast<RenderIntent>(-1));
+    EXPECT_EQ(Error::BAD_PARAMETER, renderIntentError);
+}
+
+/**
  * Test IComposerClient::Command::SET_LAYER_COLOR_TRANSFORM.
  * TODO Add color to the layer, use matrix to keep only red component,
  * and check.
diff --git a/media/c2/1.0/Android.bp b/media/c2/1.0/Android.bp
new file mode 100644
index 0000000..c37c22b
--- /dev/null
+++ b/media/c2/1.0/Android.bp
@@ -0,0 +1,51 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.media.c2@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IComponent.hal",
+        "IComponentInterface.hal",
+        "IComponentListener.hal",
+        "IComponentStore.hal",
+        "IConfigurable.hal",
+        "IInputSurface.hal",
+        "IInputSurfaceConnection.hal",
+    ],
+    interfaces: [
+        "android.hardware.graphics.bufferqueue@1.0",
+        "android.hardware.graphics.common@1.0",
+        "android.hardware.media.bufferpool@2.0",
+        "android.hardware.media.omx@1.0",
+        "android.hardware.media@1.0",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "BaseBlock",
+        "Block",
+        "Buffer",
+        "FieldDescriptor",
+        "FieldId",
+        "FieldSupportedValues",
+        "FieldSupportedValuesQuery",
+        "FieldSupportedValuesQueryResult",
+        "FrameData",
+        "InfoBuffer",
+        "ParamDescriptor",
+        "ParamField",
+        "ParamFieldValues",
+        "SettingResult",
+        "Status",
+        "StructDescriptor",
+        "Work",
+        "WorkBundle",
+        "WorkOrdinal",
+        "Worklet",
+    ],
+    gen_java: false,
+}
+
diff --git a/media/c2/1.0/IComponent.hal b/media/c2/1.0/IComponent.hal
new file mode 100644
index 0000000..7fd551f
--- /dev/null
+++ b/media/c2/1.0/IComponent.hal
@@ -0,0 +1,365 @@
+/*
+ * 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.c2@1.0;
+
+import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer;
+import android.hardware.media.omx@1.0::IGraphicBufferSource;
+
+import IConfigurable;
+import IComponentInterface;
+import IComponentListener;
+import IInputSurface;
+import IInputSurfaceConnection;
+
+/**
+ * Interface for a Codec2 component corresponding to API level 1.0 or below.
+ * Components have two states: stopped and running. The running state has three
+ * sub-states: executing, tripped and error.
+ *
+ * All methods in `IComponent` must not block. If a method call cannot be
+ * completed in a timely manner, it must return `TIMED_OUT` in the return
+ * status.
+ */
+interface IComponent {
+
+    // METHODS AVAILABLE WHEN RUNNING
+    // =========================================================================
+
+    /**
+     * Queues up work for the component.
+     *
+     * This method must be supported in running (including tripped) states.
+     *
+     * It is acceptable for this method to return `OK` and return an error value
+     * using the IComponentListener::onWorkDone() callback.
+     *
+     * @param workBundle `WorkBundle` object containing a list of `Work` objects
+     *     to queue to the component.
+     * @return status Status of the call, which may be
+     *   - `OK`        - Works in @p workBundle were successfully queued.
+     *   - `BAD_INDEX` - Some component id in some `Worklet` is not valid.
+     *   - `CANNOT_DO` - The components are not tunneled but some `Work` object
+     *                   contains tunneling information.
+     *   - `NO_MEMORY` - Not enough memory to queue @p workBundle.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    queue(WorkBundle workBundle) generates (Status status);
+
+    /**
+     * Discards and abandons any pending `Work` items for the component.
+     *
+     * This method must be supported in running (including tripped) states.
+     *
+     * `Work` that could be immediately abandoned/discarded must be returned in
+     * @p flushedWorkBundle. The order in which queued `Work` items are
+     * discarded can be arbitrary.
+     *
+     * `Work` that could not be abandoned or discarded immediately must be
+     * marked to be discarded at the earliest opportunity, and must be returned
+     * via IComponentListener::onWorkDone(). This must be completed within
+     * 500ms.
+     *
+     * @return status Status of the call, which may be
+     *   - `OK`        - The component has been successfully flushed.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return flushedWorkBundle `WorkBundle` object containing flushed `Work`
+     *     items.
+     */
+    flush(
+        ) generates (
+            Status status,
+            WorkBundle flushedWorkBundle
+        );
+
+    /**
+     * Drains the component, and optionally downstream components. This is a
+     * signalling method; as such it does not wait for any work completion.
+     *
+     * The last `Work` item is marked as "drain-till-here", so the component is
+     * notified not to wait for further `Work` before it processes what is
+     * already queued. This method can also be used to set the end-of-stream
+     * flag after `Work` has been queued. Client can continue to queue further
+     * `Work` immediately after this method returns.
+     *
+     * This method must be supported in running (including tripped) states.
+     *
+     * `Work` that is completed must be returned via
+     * IComponentListener::onWorkDone().
+     *
+     * @param withEos Whether to drain the component with marking end-of-stream.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The drain request has been successfully recorded.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    drain(bool withEos) generates (Status status);
+
+    /**
+     * Starts using a surface for output.
+     *
+     * This method must not block.
+     *
+     * @param blockPoolId Id of the `C2BlockPool` to be associated with the
+     *     output surface.
+     * @param surface Output surface.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `CANNOT_DO` - The component does not support an output surface.
+     *   - `REFUSED`   - The output surface cannot be accessed.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    setOutputSurface(
+            uint64_t blockPoolId,
+            IGraphicBufferProducer surface
+        ) generates (
+            Status status
+        );
+
+    /**
+     * Starts using an input surface.
+     *
+     * The component must be in running state.
+     *
+     * @param inputSurface Input surface to connect to.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `CANNOT_DO` - The component does not support an input surface.
+     *   - `BAD_STATE` - The component is not in running state.
+     *   - `DUPLICATE` - The component is already connected to an input surface.
+     *   - `REFUSED`   - The input surface is already in use.
+     *   - `NO_MEMORY` - Not enough memory to start the component.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return connection `IInputSurfaceConnection` object, which can be used to
+     *     query and configure properties of the connection. This cannot be
+     *     null.
+     */
+    connectToInputSurface(
+            IInputSurface inputSurface
+        ) generates (
+            Status status,
+            IInputSurfaceConnection connection
+        );
+
+    /**
+     * Starts using an OMX input surface.
+     *
+     * The component must be in running state.
+     *
+     * This method is similar to connectToInputSurface(), but it takes an OMX
+     * input surface (as a pair of `IGraphicBufferProducer` and
+     * `IGraphicBufferSource`) instead of Codec2's own `IInputSurface`.
+     *
+     * @param producer Producer component of an OMX input surface.
+     * @param source Source component of an OMX input surface.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `CANNOT_DO` - The component does not support an OMX input surface.
+     *   - `BAD_STATE` - The component is not in running state.
+     *   - `DUPLICATE` - The component is already connected to an input surface.
+     *   - `REFUSED`   - The input surface is already in use.
+     *   - `NO_MEMORY` - Not enough memory to start the component.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return connection `IInputSurfaceConnection` object, which can be used to
+     *     query and configure properties of the connection. This cannot be
+     *     null.
+     */
+    connectToOmxInputSurface(
+            IGraphicBufferProducer producer,
+            IGraphicBufferSource source
+        ) generates (
+            Status status,
+            IInputSurfaceConnection connection
+        );
+
+    /**
+     * Stops using an input surface.
+     *
+     * The component must be in running state.
+     *
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `CANNOT_DO` - The component does not support an input surface.
+     *   - `BAD_STATE` - The component is not in running state.
+     *   - `NOT_FOUND` - The component is not connected to an input surface.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    disconnectFromInputSurface() generates (Status Status);
+
+    /**
+     * Creates a local `C2BlockPool` backed by the given allocator and returns
+     * its id.
+     *
+     * The returned @p blockPoolId is the only way the client can refer to a
+     * `C2BlockPool` object in the component. The id can be passed to
+     * setOutputSurface() or used in some C2Param objects later.
+     *
+     * The created `C2BlockPool` object can be destroyed by calling
+     * destroyBlockPool(), reset() or release(). reset() and release() must
+     * destroy all `C2BlockPool` objects that have been created.
+     *
+     * @param allocatorId Id of a `C2Allocator`.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `NO_MEMORY` - Not enough memory to create the pool.
+     *   - `BAD_VALUE` - @p allocatorId is not recognized.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return blockPoolId Id of the created C2BlockPool object. This may be
+     *     used in setOutputSurface() if the allocator
+     * @return configurable Configuration interface for the created pool. This
+     *     must not be null.
+     */
+    createBlockPool(uint32_t allocatorId) generates (
+        Status status,
+        uint64_t blockPoolId,
+        IConfigurable configurable
+    );
+
+    /**
+     * Destroys a local block pool previously created by createBlockPool().
+     *
+     * @param blockPoolId Id of a `C2BlockPool` that was previously returned by
+     *      createBlockPool().
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `NOT_FOUND` - The supplied blockPoolId is not valid.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    destroyBlockPool(uint64_t blockPoolId) generates (Status status);
+
+    // STATE CHANGE METHODS
+    // =========================================================================
+
+    /**
+     * Starts the component.
+     *
+     * This method must be supported in stopped state as well as tripped state.
+     *
+     * If the return value is `OK`, the component must be in the running state.
+     * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
+     * expected as a response to this call. Otherwise, the component must be in
+     * the stopped state.
+     *
+     * If a component is in the tripped state and start() is called while the
+     * component configuration still results in a trip, start() must succeed and
+     * a new onTripped() callback must be used to communicate the configuration
+     * conflict that results in the new trip.
+     *
+     * @return status Status of the call, which may be
+     *   - `OK`        - The component has started successfully.
+     *   - `BAD_STATE` - Component is not in stopped or tripped state.
+     *   - `DUPLICATE` - When called during another start call from another
+     *                   thread.
+     *   - `NO_MEMORY` - Not enough memory to start the component.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    start() generates (Status status);
+
+    /**
+     * Stops the component.
+     *
+     * This method must be supported in running (including tripped) state.
+     *
+     * This method must return withing 500ms.
+     *
+     * Upon this call, all pending `Work` must be abandoned.
+     *
+     * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
+     * expected as a response to this call. For all other return values, the
+     * component must be in the stopped state.
+     *
+     * This does not alter any settings and tunings that may have resulted in a
+     * tripped state.
+     *
+     * @return status Status of the call, which may be
+     *   - `OK`        - The component has stopped successfully.
+     *   - `BAD_STATE` - Component is not in running state.
+     *   - `DUPLICATE` - When called during another stop call from another
+     *                   thread.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    stop() generates (Status status);
+
+    /**
+     * Resets the component.
+     *
+     * This method must be supported in all (including tripped) states other
+     * than released.
+     *
+     * This method must be supported during any other blocking call.
+     *
+     * This method must return withing 500ms.
+     *
+     * When this call returns, if @p status is `OK`, all `Work` items must
+     * have been abandoned, and all resources (including `C2BlockPool` objects
+     * previously created by createBlockPool()) must have been released.
+     *
+     * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
+     * expected as a response to this call. For all other return values, the
+     * component must be in the stopped state.
+     *
+     * This brings settings back to their default, "guaranteeing" no tripped
+     * state.
+     *
+     * @return status Status of the call, which may be
+     *   - `OK`        - The component has been reset.
+     *   - `BAD_STATE` - Component is in released state.
+     *   - `DUPLICATE` - When called during another reset call from another
+     *                   thread.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    reset() generates (Status status);
+
+    /**
+     * Releases the component.
+     *
+     * This method must be supported in stopped state.
+     *
+     * This method destroys the component. Upon return, if @p status is `OK` or
+     * `DUPLICATE`, all resources must have been released.
+     *
+     * @return status Status of the call, which may be
+     *   - `OK`        - The component has been released.
+     *   - `BAD_STATE` - The component is running.
+     *   - `DUPLICATE` - The component is already released.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    release() generates (Status status);
+
+    /**
+     * Returns the @ref IComponentInterface instance associated to this
+     * component.
+     *
+     * An @p IConfigurable instance for the component can be obtained by calling
+     * IComponentInterface::getConfigurable() on the returned @p intf.
+     *
+     * @return intf `IComponentInterface` instance. This must not be null.
+     */
+    getInterface() generates (IComponentInterface intf);
+};
+
diff --git a/media/c2/1.0/IComponentInterface.hal b/media/c2/1.0/IComponentInterface.hal
new file mode 100644
index 0000000..a007d02
--- /dev/null
+++ b/media/c2/1.0/IComponentInterface.hal
@@ -0,0 +1,38 @@
+/*
+ * 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.c2@1.0;
+
+import IConfigurable;
+
+/**
+ * Component interface object. This object contains all of the configurations of
+ * a potential or actual component. It can be created and used independently of
+ * an actual Codec2 component to query supported parameters for various
+ * component settings, and configurations for a potential component.
+ *
+ * An actual component exposes this interface via IComponent::getInterface().
+ */
+interface IComponentInterface {
+    /**
+     * Returns the @ref IConfigurable instance associated to this component
+     * interface.
+     *
+     * @return configurable `IConfigurable` instance. This must not be null.
+     */
+    getConfigurable() generates (IConfigurable configurable);
+};
+
diff --git a/media/c2/1.0/IComponentListener.hal b/media/c2/1.0/IComponentListener.hal
new file mode 100644
index 0000000..70d5fb2
--- /dev/null
+++ b/media/c2/1.0/IComponentListener.hal
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2@1.0;
+
+/**
+ * Callback interface for handling notifications from @ref IComponent.
+ */
+interface IComponentListener {
+
+    /**
+     * Notify the listener that some `Work` items have been completed.
+     *
+     * All the input buffers in the returned `Work` objects must not be used by
+     * the component after onWorkDone() is called.
+     *
+     * @param workBundle List of completed `Work` objects.
+     */
+    oneway onWorkDone(WorkBundle workBundle);
+
+    /**
+     * Notify the listener that the component is tripped.
+     *
+     * @param settingResults List of failures.
+     */
+    oneway onTripped(vec<SettingResult> settingResults);
+
+    /**
+     * Notify the listener of an error.
+     *
+     * @param status Error type. @p status may be `OK`, which means that an
+     *     error has occurred, but the error type does not fit into the type
+     *     `Status`. In this case, additional information is provided by
+     *     @p errorCode.
+     * @param errorCode Additional error information. The framework may not
+     *     recognize the meaning of this value.
+     */
+    oneway onError(Status status, uint32_t errorCode);
+
+    /**
+     * Information about rendering of a frame to a `Surface`.
+     */
+    struct RenderedFrame {
+        /**
+         * Id of the `BufferQueue` containing the rendered buffer.
+         *
+         * This value must have been obtained by an earlier call to
+         * IGraphicBufferProducer::getUniqueId().
+         */
+        uint64_t bufferQueueId;
+        /**
+         * Id of the slot of the rendered buffer.
+         *
+         * This value must have been obtained by an earlier call to
+         * IGraphicBufferProducer::dequeueBuffer() or
+         * IGraphicBufferProducer::attachBuffer().
+         */
+        int32_t slotId;
+        /**
+         * Timestamp the rendering happened.
+         *
+         * The reference point for the timestamp is determined by the
+         * `BufferQueue` that performed the rendering.
+         */
+        int64_t timestampNs;
+    };
+
+    /**
+     * Notify the listener that frames have been rendered.
+     *
+     * @param renderedFrames List of @ref RenderedFrame objects.
+     */
+    oneway onFramesRendered(vec<RenderedFrame> renderedFrames);
+
+    /**
+     * Identifying information for an input buffer previously queued to the
+     * component via IComponent::queue().
+     */
+    struct InputBuffer {
+        /**
+         * This value comes from `Work::input.ordinal.frameIndex` in a `Work`
+         * object that was previously queued.
+         */
+        uint64_t frameIndex;
+        /**
+         * This value is an index into `Work::input.buffers` (which is an array)
+         * in a `Work` object that was previously queued.
+         */
+        uint32_t arrayIndex;
+    };
+
+    /**
+     * Notify the listener that some input buffers are no longer needed by the
+     * component, and hence can be released or reused by the client.
+     *
+     * Input buffers that are contained in a `Work` object returned by an
+     * earlier onWorkDone() call are assumed released, so they must not appear
+     * in any onInputBuffersReleased() calls. That means
+     * onInputBuffersReleased() must only report input buffers that are released
+     * before the output in the same `Work` item is produced. However, it is
+     * possible for an input buffer to be returned by onWorkDone() after it has
+     * been reported by onInputBuffersReleased().
+     *
+     * @note onWorkDone() and onInputBuffersReleased() both notify the client
+     * that input buffers are no longer needed. However, in order to minimize
+     * IPC calls, onInputBuffersReleased() should be called only when
+     * onWorkDone() cannot be called, e.g., the component needs more input
+     * before an output can be produced.
+     *
+     * @param inputBuffers List of `InputBuffer` objects, identifying input
+     * buffers that are no longer needed by the component.
+     */
+    oneway onInputBuffersReleased(vec<InputBuffer> inputBuffers);
+};
+
diff --git a/media/c2/1.0/IComponentStore.hal b/media/c2/1.0/IComponentStore.hal
new file mode 100644
index 0000000..6a57c38
--- /dev/null
+++ b/media/c2/1.0/IComponentStore.hal
@@ -0,0 +1,224 @@
+/*
+ * 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.c2@1.0;
+
+import android.hardware.media.bufferpool@2.0::IClientManager;
+import IComponentInterface;
+import IComponentListener;
+import IComponent;
+import IConfigurable;
+import IInputSurface;
+
+/**
+ * Entry point for Codec2 HAL.
+ *
+ * All methods in `IComponentStore` must not block. If a method call cannot be
+ * completed in a timely manner, it must return `TIMED_OUT` in the return
+ * status. The only exceptions are getPoolClientManager() and getConfigurable(),
+ * which must always return immediately.
+ */
+interface IComponentStore {
+
+    /**
+     * Creates a component by name.
+     *
+     * @param name Name of the component to create. This must match one of the
+     *     names returned by listComponents().
+     * @param listener Callback receiver.
+     * @param pool `IClientManager` object of the BufferPool in the client
+     *     process. This may be null if the client does not own a BufferPool.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The component was created successfully.
+     *   - `NOT_FOUND` - There is no component with the given name.
+     *   - `NO_MEMORY` - Not enough memory to create the component.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return comp The created component if @p status is `OK`.
+     *
+     * @sa IComponentListener.
+     */
+    createComponent(
+            string name,
+            IComponentListener listener,
+            IClientManager pool
+        ) generates (
+            Status status,
+            IComponent comp
+        );
+
+    /**
+     * Creates a component interface by name.
+     *
+     * @param name Name of the component interface to create. This should match
+     *     one of the names returned by listComponents().
+     * @return status Status of the call, which may be
+     *   - `OK         - The component interface was created successfully.
+     *   - `NOT_FOUND` - There is no component interface with the given name.
+     *   - `NO_MEMORY` - Not enough memory to create the component interface.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return compIntf The created component interface if @p status is `OK`.
+     */
+    createInterface(
+            string name
+        ) generates (
+            Status status,
+            IComponentInterface compIntf
+        );
+
+    /**
+     * Component traits.
+     */
+    struct ComponentTraits {
+        /**
+         * Name of the component. This must be unique for each component.
+         *
+         * This name is use to identify the component to create in
+         * createComponent() and createComponentInterface().
+         */
+        string name;
+
+        enum Domain : uint32_t {
+            OTHER = 0,
+            VIDEO,
+            AUDIO,
+            IMAGE,
+        };
+        /**
+         * Component domain.
+         */
+        Domain domain;
+
+        enum Kind : uint32_t {
+            OTHER = 0,
+            DECODER,
+            ENCODER,
+        };
+        /**
+         * Component kind.
+         */
+        Kind kind;
+
+        /**
+         * Rank used by `MediaCodecList` to determine component ordering. Lower
+         * value means higher priority.
+         */
+        uint32_t rank;
+
+        /**
+         * MIME type.
+         */
+        string mediaType;
+
+        /**
+         * Aliases for component name for backward compatibility.
+         *
+         * Multiple components can have the same alias (but not the same
+         * component name) as long as their media types differ.
+         */
+        vec<string> aliases;
+    };
+
+    /**
+     * Returns the list of components supported by this component store.
+     *
+     * @return status Status of the call, which may be
+     *   - `OK         - The operation was successful.
+     *   - `NO_MEMORY` - Not enough memory to complete this method.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return traits List of component traits for all components supported by
+     *     this store (in no particular order).
+     */
+    listComponents() generates (
+            Status status,
+            vec<ComponentTraits> traits
+        );
+
+    /**
+     * Creates a persistent input surface that can be used as an input surface
+     * for any IComponent instance
+     *
+     * @return status Status of the call, which may be
+     *   - `OK         - The operation was successful.
+     *   - `NO_MEMORY` - Not enough memory to complete this method.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return surface A persistent input surface. This may be null to indicate
+     *     an error.
+     */
+    createInputSurface() generates (
+            Status status,
+            IInputSurface surface
+        );
+
+    /**
+     * Returns a list of `StructDescriptor` objects for a set of requested
+     * C2Param structure indices that this store is aware of.
+     *
+     * This operation must be performed at best effort, e.g. the component
+     * store must simply ignore all struct indices that it is not aware of.
+     *
+     * @param indices Indices of C2Param structures to describe.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `NOT_FOUND` - Some indices were not known.
+     *   - `NO_MEMORY` - Not enough memory to complete this method.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return structs List of `StructDescriptor` objects.
+     */
+    getStructDescriptors(
+            vec<ParamIndex> indices
+        ) generates (
+            Status status,
+            vec<StructDescriptor> structs
+        );
+
+    /**
+     * Copies the contents of @p src into @p dst without changing the format of
+     * @p dst.
+     *
+     * @param src Source buffer.
+     * @param dst Destination buffer.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The copy is successful.
+     *   - `CANNOT_DO` - @p src and @p dst are not compatible.
+     *   - `REFUSED`   - No permission to copy.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     */
+    copyBuffer(Buffer src, Buffer dst) generates (Status status);
+
+    /**
+     * Returns the `IClientManager` object for the component's BufferPool.
+     *
+     * @return pool If the component store supports receiving buffers via
+     *     BufferPool API, @p pool must be a valid `IClientManager` instance.
+     *     Otherwise, @p pool must be null.
+     */
+    getPoolClientManager() generates (IClientManager pool);
+
+    /**
+     * Returns the @ref IConfigurable instance associated to this component
+     * store.
+     *
+     * @return configurable `IConfigurable` instance. This must not be null.
+     */
+    getConfigurable() generates (IConfigurable configurable);
+};
+
diff --git a/media/c2/1.0/IConfigurable.hal b/media/c2/1.0/IConfigurable.hal
new file mode 100644
index 0000000..31dc4d3
--- /dev/null
+++ b/media/c2/1.0/IConfigurable.hal
@@ -0,0 +1,241 @@
+/*
+ * 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.c2@1.0;
+
+/**
+ * Generic configuration interface presented by all configurable Codec2 objects.
+ *
+ * This interface must be supported in all states of the owning object, and must
+ * not change the state of the owning object.
+ */
+interface IConfigurable {
+    /**
+     * Returns the id of the object. This must be unique among all objects of
+     * the same type hosted by the same store.
+     *
+     * @return id Id of the object.
+     */
+    getId() generates (uint32_t id);
+
+    /**
+     * Returns the name of the object.
+     *
+     * This must match the name that was supplied during the creation of the
+     * object.
+     *
+     * @return name Name of the object.
+     */
+    getName() generates (string name);
+
+    /**
+     * Queries a set of parameters from the object.
+     *
+     * Querying is performed at best effort: the object must query all supported
+     * parameters and skip unsupported ones (which may include parameters that
+     * could not be allocated). Any errors are communicated in the return value.
+     *
+     * If @p mayBlock is false, this method must not block. All parameter
+     * queries that require blocking must be skipped.
+     *
+     * If @p mayBlock is true, a query may block, but the whole method call
+     * has to complete in a timely manner, or `status = TIMED_OUT` is returned.
+     *
+     * If @p mayBlock is false, this method must not block. Otherwise, this
+     * method is allowed to block for a certain period of time before completing
+     * the operation. If the operation is not completed in a timely manner,
+     * `status = TIMED_OUT` is returned.
+     *
+     * @note The order of C2Param objects in @p param does not depend on the
+     *     order of C2Param structure indices in @p indices.
+     *
+     * \par For IComponent
+     *
+     * When the object type is @ref IComponent, this method must be supported in
+     * any state except released. This call must not change the state nor the
+     * internal configuration of the component.
+     *
+     * The blocking behavior of this method differs among states:
+     *   - In the stopped state, this must be non-blocking. @p mayBlock is
+     *     ignored. (The method operates as if @p mayBlock was false.)
+     *   - In any of the running states, this method may block momentarily if
+     *     @p mayBlock is true. However, if the call cannot be completed in a
+     *     timely manner, `status = TIMED_OUT` is returned.
+     *
+     * @param indices List of C2Param structure indices to query.
+     * @param mayBlock Whether this call may block or not.
+     * @return status Status of the call, which may be
+     *   - `OK`        - All parameters could be queried.
+     *   - `BAD_INDEX` - All supported parameters could be queried, but some
+     *                   parameters were not supported.
+     *   - `NO_MEMORY` - Could not allocate memory for a supported parameter.
+     *   - `BLOCKING`  - Querying some parameters requires blocking, but
+     *                   @p mayBlock is false.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return params Flattened representation of C2Param objects.
+     *
+     * @sa Params.
+     */
+    query(
+            vec<ParamIndex> indices,
+            bool mayBlock
+        ) generates (
+            Status status,
+            Params params
+        );
+
+    /**
+     * Sets a set of parameters for the object.
+     *
+     * Tuning is performed at best effort: the object must update all supported
+     * configurations at best effort and skip unsupported parameters. Any errors
+     * are communicated in the return value and in @p failures.
+     *
+     * A non-strict parameter update with an unsupported value shall cause an
+     * update to the closest supported value. A strict parameter update with an
+     * unsupported value shall be skipped and a failure shall be returned.
+     *
+     * If @p mayBlock is false, this method must not block. An update that
+     * requires blocking shall be skipped and a failure shall be returned.
+     *
+     * If @p mayBlock is true, an update may block, but the whole method call
+     * has to complete in a timely manner, or `status = TIMED_OUT` is returned.
+     *
+     * The final values for all parameters set are propagated back to the caller
+     * in @p params.
+     *
+     * \par For IComponent
+     *
+     * When the object type is @ref IComponent, this method must be supported in
+     * any state except released.
+     *
+     * The blocking behavior of this method differs among states:
+     *   - In the stopped state, this must be non-blocking. @p mayBlock is
+     *     ignored. (The method operates as if @p mayBlock was false.)
+     *   - In any of the running states, this method may block momentarily if
+     *     @p mayBlock is true. However, if the call cannot be completed in a
+     *     timely manner, `status = TIMED_OUT` is returned.
+     *
+     * @note Parameter tuning @e does depend on the order of the tuning
+     * parameters, e.g., some parameter update may enable some subsequent
+     * parameter update.
+     *
+     * @param inParams Requested parameter updates.
+     * @param mayBlock Whether this call may block or not.
+     * @return status Status of the call, which may be
+     *   - `OK`        - All parameters could be updated successfully.
+     *   - `BAD_INDEX` - All supported parameters could be updated successfully,
+     *                   but some parameters were not supported.
+     *   - `NO_MEMORY` - Some supported parameters could not be updated
+     *                   successfully because they contained unsupported values.
+     *                   These are returned in @p failures.
+     *   - `BLOCKING`  - Setting some parameters requires blocking, but
+     *                   @p mayBlock is false.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return failures List of update failures.
+     * @return outParams Flattened representation of configured parameters. The
+     *     order of parameters in @p outParams is based on the order of
+     *     requested updates in @p inParams.
+     *
+     * @sa SettingResult.
+     */
+    config(
+            Params inParams,
+            bool mayBlock
+        ) generates (
+            Status status,
+            vec<SettingResult> failures,
+            Params outParams
+        );
+
+    // REFLECTION MECHANISM
+    // =========================================================================
+
+    /**
+     * Returns a list of supported parameters within a selected range of C2Param
+     * structure indices.
+     *
+     * @param start The first index of the selected range.
+     * @param count The length of the selected range.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `NO_MEMORY` - Not enough memory to complete this method.
+     * @return params List of supported parameters in the selected range. This
+     *     list may have fewer than @p count elements if some indices in the
+     *     range are not supported.
+     *
+     * @sa ParamDescriptor.
+     */
+    querySupportedParams(
+            uint32_t start,
+            uint32_t count
+        ) generates (
+            Status status,
+            vec<ParamDescriptor> params
+        );
+
+    /**
+     * Retrieves the supported values for the queried fields.
+     *
+     * The object must process all fields queried even if some queries fail.
+     *
+     * If @p mayBlock is false, this method must not block. Otherwise, this
+     * method is allowed to block for a certain period of time before completing
+     * the operation. If the operation cannot be completed in a timely manner,
+     * `status = TIMED_OUT` is returned.
+     *
+     * \par For IComponent
+     *
+     * When the object type is @ref IComponent, this method must be supported in
+     * any state except released.
+     *
+     * The blocking behavior of this method differs among states:
+     *   - In the stopped state, this must be non-blocking. @p mayBlock is
+     *     ignored. (The method operates as if @p mayBlock was false.)
+     *   - In any of the running states, this method may block momentarily if
+     *     @p mayBlock is true. However, if the call cannot be completed in a
+     *     timely manner, `status = TIMED_OUT` is returned.
+     *
+     * @param inFields List of field queries.
+     * @param mayBlock Whether this call may block or not.
+     * @return status Status of the call, which may be
+     *   - `OK`        - The operation completed successfully.
+     *   - `BLOCKING`  - Querying some parameters requires blocking, but
+     *                   @p mayBlock is false.
+     *   - `NO_MEMORY` - Not enough memory to complete this method.
+     *   - `BAD_INDEX` - At least one field was not recognized as a component
+     *                   field.
+     *   - `BLOCKING`  - Querying some fields requires blocking, but @p mayblock
+     *                   is false.
+     *   - `TIMED_OUT` - The operation cannot be finished in a timely manner.
+     *   - `CORRUPTED` - Some unknown error occurred.
+     * @return outFields List of supported values and results for the
+     *     supplied queries.
+     *
+     * @sa FieldSupportedValuesQuery, FieldSupportedValuesQueryResult.
+     */
+    querySupportedValues(
+            vec<FieldSupportedValuesQuery> inFields,
+            bool mayBlock
+        ) generates (
+            Status status,
+            vec<FieldSupportedValuesQueryResult> outFields
+        );
+
+};
+
diff --git a/media/c2/1.0/IInputSurface.hal b/media/c2/1.0/IInputSurface.hal
new file mode 100644
index 0000000..25c6c8e
--- /dev/null
+++ b/media/c2/1.0/IInputSurface.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.media.c2@1.0;
+
+import android.hardware.graphics.bufferqueue@1.0::IGraphicBufferProducer;
+
+import IConfigurable;
+
+/**
+ * Input surface for a Codec2 component.
+ *
+ * An <em>input surface</em> is an instance of `IInputSurface`, which may be
+ * created by calling IComponentStore::createInputSurface(). Once created, the
+ * client may
+ *   1. write data to it via the `IGraphicBufferProducer` interface; and
+ *   2. use it as input to a Codec2 encoder.
+ *
+ * @sa IInputSurfaceConnection, IComponentStore::createInputSurface(),
+ *     IComponent::connectToInputSurface().
+ */
+interface IInputSurface {
+    /**
+     * Returns the producer interface into the internal buffer queue.
+     *
+     * @return producer `IGraphicBufferProducer` instance. This must not be
+     * null.
+     */
+    getGraphicBufferProducer() generates (IGraphicBufferProducer producer);
+
+    /**
+     * Returns the @ref IConfigurable instance associated to this input surface.
+     *
+     * @return configurable `IConfigurable` instance. This must not be null.
+     */
+    getConfigurable() generates (IConfigurable configurable);
+};
+
diff --git a/media/c2/1.0/IInputSurfaceConnection.hal b/media/c2/1.0/IInputSurfaceConnection.hal
new file mode 100644
index 0000000..efd9c6e
--- /dev/null
+++ b/media/c2/1.0/IInputSurfaceConnection.hal
@@ -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.
+ */
+
+package android.hardware.media.c2@1.0;
+
+import IConfigurable;
+
+/**
+ * Connection between a component and an input surface.
+ *
+ * An instance of `IInputSurfaceConnection` contains an `IConfigurable`
+ * interface for querying and configuring properties of the connection.
+ */
+interface IInputSurfaceConnection {
+    /**
+     * Returns the @ref IConfigurable instance associated to this connection.
+     *
+     * This can be used to customize the connection.
+     *
+     * @return configurable `IConfigurable` instance. This must not be null.
+     */
+    getConfigurable() generates (IConfigurable configurable);
+};
+
diff --git a/media/c2/1.0/types.hal b/media/c2/1.0/types.hal
new file mode 100644
index 0000000..7b75041
--- /dev/null
+++ b/media/c2/1.0/types.hal
@@ -0,0 +1,832 @@
+/*
+ * 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.c2@1.0;
+
+import android.hardware.media.bufferpool@2.0::BufferStatusMessage;
+
+/**
+ * Common return values for Codec2 operations.
+ */
+enum Status : int32_t {
+    /** Operation completed successfully. */
+    OK        = 0,
+
+    // bad input
+
+    /** Argument has invalid value (user error). */
+    BAD_VALUE = -22,
+    /** Argument uses invalid index (user error). */
+    BAD_INDEX = -75,
+    /** Argument/Index is valid but not possible. */
+    CANNOT_DO = -2147483646,
+
+    // bad sequencing of events
+
+    /** Object already exists. */
+    DUPLICATE = -17,
+    /** Object not found. */
+    NOT_FOUND = -2,
+    /** Operation is not permitted in the current state. */
+    BAD_STATE = -38,
+    /** Operation would block but blocking is not permitted. */
+    BLOCKING  = -9930,
+
+    // bad environment
+
+    /** Not enough memory to complete operation. */
+    NO_MEMORY = -12,
+    /** Missing permission to complete operation. */
+    REFUSED   = -1,
+
+    /** Operation did not complete within timeout. */
+    TIMED_OUT = -110,
+
+    // missing functionality
+
+    /** Operation is not implemented/supported (optional only). */
+    OMITTED   = -74,
+
+    // unknown fatal
+
+    /** Some unexpected error prevented the operation. */
+    CORRUPTED = -2147483648,
+
+    // uninitialized
+
+    /** Status has not been initialized. */
+    NO_INIT   = -19,
+};
+
+/**
+ * C2Param structure index.
+ *
+ * This is a number that is unique for each C2Param structure type.
+ *
+ * @sa Codec 2.0 standard.
+ */
+typedef uint32_t ParamIndex;
+
+/**
+ * Flattened representation of C2Param objects.
+ *
+ * The `Params` type is an array of bytes made up by concatenating a list of
+ * C2Param objects. The start index (offset into @ref Params) of each C2Param
+ * object in the list is divisible by 8. Up to 7 padding bytes may be added
+ * after each C2Param object to achieve this 64-bit alignment.
+ *
+ * Each C2Param object has the following layout:
+ * - 4 bytes: C2Param structure index (of type @ref ParamIndex) identifying the
+ *   type of the C2Param object.
+ * - 4 bytes: size of the C2Param object (unsigned 4-byte integer).
+ * - (size - 8) bytes: data of the C2Param object.
+ *
+ * In order to interpret each C2Param object correctly, its structure must be
+ * described by IComponentStore::getStructDescriptors().
+ *
+ * @note Please refer to the Codec 2.0 standard for the list of standard
+ * parameter structures.
+ *
+ * @sa Codec 2.0 standard.
+ */
+typedef vec<uint8_t> Params;
+
+/**
+ * Identifying information of a field relative to a known C2Param structure.
+ *
+ * Within a given C2Param structure, each field is uniquely identified by @ref
+ * FieldId.
+ */
+struct FieldId {
+    /** Offset of the field in bytes. */
+    uint32_t offset;
+    /** Size of the field in bytes. */
+    uint32_t size;
+};
+
+/**
+ * Reference to a field in a C2Param structure.
+ */
+struct ParamField {
+    /** Index of the C2Param structure. */
+    ParamIndex index;
+    /** Identifier of the field inside the C2Param structure. */
+    FieldId fieldId;
+};
+
+/**
+ * Usage description of a C2Param structure.
+ *
+ * @ref ParamDescriptor is returned by IConfigurable::querySupportedParams().
+ */
+struct ParamDescriptor {
+    /**
+     * Index of the C2Param structure being described.
+     */
+    ParamIndex index;
+
+    enum Attrib : uint32_t {
+        /**
+         * The parameter is required to be specified.
+         */
+        REQUIRED   = 1u << 0,
+        /**
+         * The parameter retains its value.
+         */
+        PERSISTENT = 1u << 1,
+        /**
+         * The parameter is strict.
+         */
+        STRICT     = 1u << 2,
+        /**
+         * The parameter is publicly read-only.
+         */
+        READ_ONLY  = 1u << 3,
+        /**
+         * The parameter must not be visible to clients.
+         */
+        HIDDEN     = 1u << 4,
+        /**
+         * The parameter must not be used by framework (other than testing).
+         */
+        INTERNAL   = 1u << 5,
+        /**
+         * The parameter is publicly constant (hence read-only).
+         */
+        CONST      = 1u << 6,
+    };
+    bitfield<Attrib> attrib;
+
+    /**
+     * Name of the structure. This must be unique for each structure.
+     */
+    string name;
+
+    /**
+     * Indices of other C2Param structures that this C2Param structure depends
+     * on.
+     */
+    vec<ParamIndex> dependencies;
+};
+
+// Generic way to describe supported numeric values for Codec2 interfaces.
+
+/**
+ * An untyped value that can fit in 64 bits, the type of which is communicated
+ * via a separate channel (@ref FieldSupportedValues.type).
+ */
+typedef uint64_t PrimitiveValue;
+
+/*
+ * Description of supported values for a field.
+ *
+ * This can be a continuous range or a discrete set of values.
+ */
+struct FieldSupportedValues {
+    /**
+     * Used if #type is `RANGE`.
+     *
+     * If the `step` member is 0, and `num` and `denom` are both 1, the `Range`
+     * structure represents a closed interval bounded by `min` and `max`.
+     *
+     * Otherwise, the #Range structure represents a finite sequence of numbers
+     * produced from the following recurrence relation:
+     *
+     * @code
+     * v[0] = min
+     * v[i] = v[i - 1] * num / denom + step ; i >= 1
+     * @endcode
+     *
+     * Both the ratio `num / denom` and the value `step` must be positive. The
+     * last number in the sequence described by this #Range structure is the
+     * largest number in the sequence that is smaller than or equal to `max`.
+     *
+     * @note
+     * The division in the formula may truncate the result if the data type of
+     * these values is an integral type.
+     */
+    struct Range {
+        /**
+         * Lower end of the range (inclusive).
+         */
+        PrimitiveValue min;
+        /**
+         * Upper end of the range (inclusive).
+         */
+        PrimitiveValue max;
+        /**
+         * The non-homogeneous term in the recurrence relation.
+         */
+        PrimitiveValue step;
+        /**
+         * The numerator of the scale coefficient in the recurrence relation.
+         */
+        PrimitiveValue num;
+        /**
+         * The denominator of the scale coefficient in the recurrence relation.
+         */
+        PrimitiveValue denom;
+    };
+
+    enum Type : int32_t {
+        /** No supported values */
+        EMPTY = 0,
+        /** Numeric range, described in a #Range structure */
+        RANGE,
+        /** List of values */
+        VALUES,
+        /** List of flags that can be OR-ed */
+        FLAGS,
+    };
+    /**
+     * Type of the supported values.
+     */
+    Type type;
+
+    /**
+     * When #type is #Type.RANGE, #range shall specify the range of possible
+     * values.
+     *
+     * The intended type of members of #range shall be clear in the context
+     * where `FieldSupportedValues` is used.
+     */
+    Range range;
+
+    /**
+     * When #type is #Type.VALUES or #Type.FLAGS, #value shall list supported
+     * values/flags.
+     *
+     * The intended type of components of #value shall be clear in the context
+     * where `FieldSupportedValues` is used.
+     */
+    vec<PrimitiveValue> values;
+};
+
+/**
+ * Supported values for a field.
+ *
+ * This is a pair of the field specifier together with an optional supported
+ * values object. This structure is used when reporting parameter configuration
+ * failures and conflicts.
+ */
+struct ParamFieldValues {
+    /**
+     * Reference to a field or a C2Param structure.
+     */
+    ParamField paramOrField;
+
+    /**
+     * Optional supported values for the field if #paramOrField specifies an
+     * actual field that is numeric (non struct, blob or string). Supported
+     * values for arrays (including string and blobs) describe the supported
+     * values for each element (character for string, and bytes for blobs). It
+     * is optional for read-only strings and blobs.
+     */
+    vec<FieldSupportedValues> values;
+};
+
+/**
+ * Description of a field inside a C2Param structure.
+ */
+struct FieldDescriptor {
+
+    /** Location of the field in the C2Param structure */
+    FieldId fieldId;
+
+    /**
+     * Possible types of the field.
+     */
+    enum Type : uint32_t {
+        NO_INIT = 0,
+        INT32,
+        UINT32,
+        CNTR32,
+        INT64,
+        UINT64,
+        CNTR64,
+        FLOAT,
+        /**
+         * Fixed-size string (POD).
+         */
+        STRING = 0x100,
+        /**
+         * A blob has no sub-elements and can be thought of as an array of
+         * bytes. However, bytes cannot be individually addressed by clients.
+         */
+        BLOB,
+        /**
+         * The field is a structure that may contain other fields.
+         */
+        STRUCT = 0x20000,
+    };
+    /**
+     * Type of the field.
+     */
+    bitfield<Type> type;
+
+    /**
+     * If #type is #Type.STRUCT, #structIndex is the C2Param structure index;
+     * otherwise, #structIndex is not used.
+     */
+    ParamIndex structIndex;
+
+    /**
+     * Extent of the field.
+     * - For a non-array field, #extent is 1.
+     * - For a fixed-length array field, #extent is the length. An array field
+     *   of length 1 is indistinguishable from a non-array field.
+     * - For a variable-length array field, #extent is 0. This can only occur as
+     *   the last member of a C2Param structure.
+     */
+    uint32_t extent;
+
+    /**
+     * Name of the field. This must be unique for each field in the same
+     * structure.
+     */
+    string name;
+
+    /**
+     * Named value type. This is used for defining an enum value for a numeric
+     * type.
+     */
+    struct NamedValue {
+        /**
+         * Name of the enum value. This must be unique for each enum value in
+         * the same field.
+         */
+        string name;
+        /**
+         * Underlying value of the enum value. Multiple enum names may have the
+         * same underlying value.
+         */
+        PrimitiveValue value;
+    };
+    /**
+     * List of enum values. This is not used when #type is not one of the
+     * numeric types.
+     */
+    vec<NamedValue> namedValues;
+};
+
+/**
+ * Description of a C2Param structure. It consists of an index and a list of
+ * `FieldDescriptor`s.
+ */
+struct StructDescriptor {
+    /**
+     * Index of the structure.
+     */
+    ParamIndex type;
+    /**
+     * List of fields in the structure.
+     *
+     * Fields are ordered by their offsets. A field that is a structure is
+     * ordered before its members.
+     */
+    vec<FieldDescriptor> fields;
+};
+
+/**
+ * Information describing the reason the parameter settings may fail, or may be
+ * overridden.
+ */
+struct SettingResult {
+    /** Failure code */
+    enum Failure : uint32_t {
+        /** Parameter is not supported. */
+        BAD_TYPE,
+        /** Parameter is not supported on the specific port. */
+        BAD_PORT,
+        /** Parameter is not supported on the specific stream. */
+        BAD_INDEX,
+        /** Parameter is read-only and cannot be set. */
+        READ_ONLY,
+        /** Parameter mismatches input data. */
+        MISMATCH,
+        /** Strict parameter does not accept value for the field at all. */
+        BAD_VALUE,
+        /**
+         * Strict parameter field value is in conflict with an/other
+         * setting(s).
+         */
+        CONFLICT,
+        /**
+         * Parameter field is out of range due to other settings. (This failure
+         * mode can only be used for strict calculated parameters.)
+         */
+        UNSUPPORTED,
+        /**
+         * Field does not access the requested parameter value at all. It has
+         * been corrected to the closest supported value. This failure mode is
+         * provided to give guidance as to what are the currently supported
+         * values for this field (which may be a subset of the at-all-potential
+         * values).
+         */
+        INFO_BAD_VALUE,
+        /**
+         * Requested parameter value is in conflict with an/other setting(s)
+         * and has been corrected to the closest supported value. This failure
+         * mode is given to provide guidance as to what are the currently
+         * supported values as well as to optionally provide suggestion to the
+         * client as to how to enable the requested parameter value.
+         */
+        INFO_CONFLICT,
+    };
+    Failure failure;
+
+    /**
+     * Failing (or corrected) field or parameter and optionally, currently
+     * supported values for the field. Values must only be set for field
+     * failures other than `BAD_VALUE`, and only if they are different from the
+     * globally supported values (e.g. due to restrictions by another parameter
+     * or input data).
+     */
+    ParamFieldValues field;
+
+    /**
+     * Conflicting parameters or fields with (optional) suggested values for any
+     * conflicting fields to avoid the conflict. Values must only be set for
+     * `CONFLICT`, `UNSUPPORTED` or `INFO_CONFLICT` failure code.
+     */
+    vec<ParamFieldValues> conflicts;
+};
+
+/**
+ * Ordering information of @ref FrameData objects. Each member is used for
+ * comparing urgency: a smaller difference from a reference value indicates that
+ * the associated Work object is more urgent. The reference value for each
+ * member is initialized the first time it is communicated between the client
+ * and the codec, and it may be updated to later values that are communicated.
+ *
+ * Each member of `WorkOrdinal` is stored as an unsigned integer, but the actual
+ * order it represents is derived by subtracting the reference value, then
+ * interpreting the result as a signed number with the same storage size (using
+ * two's complement).
+ *
+ * @note `WorkOrdinal` is the HIDL counterpart of `C2WorkOrdinalStruct` in the
+ * Codec 2.0 standard.
+ */
+struct WorkOrdinal {
+    /**
+     * Timestamp in microseconds.
+     */
+    uint64_t timestampUs;
+    /**
+     * Frame index.
+     */
+    uint64_t frameIndex;
+    /**
+     * Component specific frame ordinal.
+     */
+    uint64_t customOrdinal;
+};
+
+/**
+ * Storage type for `BaseBlock`.
+ *
+ * A `BaseBlock` is a representation of a codec memory block. Coded data,
+ * decoded data, codec-specific data, and other codec-related data are all sent
+ * in the form of BaseBlocks.
+ */
+safe_union BaseBlock {
+    /**
+     * #nativeBlock is the opaque representation of a buffer.
+     */
+    handle nativeBlock;
+    /**
+     * #pooledBlock is a reference to a buffer handled by a BufferPool.
+     */
+    BufferStatusMessage pooledBlock;
+};
+
+/**
+ * Reference to a @ref BaseBlock within a @ref WorkBundle.
+ *
+ * `Block` contains additional attributes that `BaseBlock` does not. These
+ * attributes may differ among `Block` objects that refer to the same
+ * `BaseBlock` in the same `WorkBundle`.
+ */
+struct Block {
+    /**
+     * Identity of a `BaseBlock` within a `WorkBundle`. This is an index into
+     * #WorkBundle.baseBlocks.
+     */
+    uint32_t index;
+    /**
+     * Metadata associated with this `Block`.
+     */
+    Params meta;
+    /**
+     * Fence for synchronizing `Block` access.
+     */
+    handle fence;
+};
+
+/**
+ * A codec buffer, which is a collection of @ref Block objects and metadata.
+ *
+ * This is a part of @ref FrameData.
+ */
+struct Buffer {
+    /**
+     * Metadata associated with the buffer.
+     */
+    Params info;
+    /**
+     * Blocks contained in the buffer.
+     */
+    vec<Block> blocks;
+};
+
+/**
+ * An extension of @ref Buffer that also contains a C2Param structure index.
+ *
+ * This is a part of @ref FrameData.
+ */
+struct InfoBuffer {
+    /**
+     * A C2Param structure index.
+     */
+    ParamIndex index;
+    /**
+     * Associated @ref Buffer object.
+     */
+    Buffer buffer;
+};
+
+/**
+ * Data for an input frame or an output frame.
+ *
+ * This structure represents a @e frame with its metadata. A @e frame consists
+ * of an ordered set of buffers, configuration changes, and info buffers along
+ * with some non-configuration metadata.
+ *
+ * @note `FrameData` is the HIDL counterpart of `C2FrameData` in the Codec 2.0
+ * standard.
+ */
+struct FrameData {
+    enum Flags : uint32_t {
+        /**
+         * For input frames: no output frame shall be generated when processing
+         * this frame, but metadata must still be processed.
+         *
+         * For output frames: this frame must be discarded but metadata is still
+         * valid.
+         */
+        DROP_FRAME    = (1 << 0),
+        /**
+         * This frame is the last frame of the current stream. Further frames
+         * are part of a new stream.
+         */
+        END_OF_STREAM = (1 << 1),
+        /**
+         * This frame must be discarded with its metadata.
+         *
+         * This flag is only set by components, e.g. as a response to the flush
+         * command.
+         */
+        DISCARD_FRAME = (1 << 2),
+        /**
+         * This frame is not the last frame produced for the input.
+         *
+         * This flag is normally set by the component - e.g. when an input frame
+         * results in multiple output frames, this flag is set on all but the
+         * last output frame.
+         *
+         * Also, when components are chained, this flag should be propagated
+         * down the work chain. That is, if set on an earlier frame of a
+         * work-chain, it should be propagated to all later frames in that
+         * chain. Additionally, components down the chain could set this flag
+         * even if not set earlier, e.g. if multiple output frames are generated
+         * at that component for the input frame.
+         */
+        FLAG_INCOMPLETE = (1 << 3),
+        /**
+         * This frame contains only codec-specific configuration data, and no
+         * actual access unit.
+         *
+         * @deprecated Pass codec configuration with the codec-specific
+         * configuration info together with the access unit.
+         */
+        CODEC_CONFIG  = (1u << 31),
+    };
+
+    /**
+     * Frame flags, as described in #Flags.
+     */
+    bitfield<Flags> flags;
+
+    /**
+     * @ref WorkOrdinal of the frame.
+     */
+    WorkOrdinal ordinal;
+
+    /**
+     * List of frame buffers.
+     */
+    vec<Buffer> buffers;
+
+    /**
+     * List of configuration updates.
+     */
+    Params configUpdate;
+
+    /**
+     * List of info buffers.
+     */
+    vec<InfoBuffer> infoBuffers;
+};
+
+/**
+ * In/out structure containing some instructions for and results from output
+ * processing.
+ *
+ * This is a part of @ref Work. One `Worklet` corresponds to one output
+ * @ref FrameData. The client must construct an original `Worklet` object inside
+ * a @ref Work object for each expected output before calling
+ * IComponent::queue().
+ */
+struct Worklet {
+    /**
+     * Component id. (Input)
+     *
+     * This is used only when tunneling is enabled.
+     *
+     * When used, this must match the return value from IConfigurable::getId().
+     */
+    uint32_t componentId;
+
+    /**
+     * List of C2Param objects describing tunings to be applied before
+     * processing this `Worklet`. (Input)
+     */
+    Params tunings;
+
+    /**
+     * Flag determining whether this `Worklet` has output or not.
+     */
+    bool hasOutput;
+
+    /**
+     * List of failures. (Output)
+     */
+    vec<SettingResult> failures;
+
+    /**
+     * Output frame data. (Output)
+     */
+    FrameData output;
+};
+
+/**
+ * A collection of input data to and output data from the component.
+ *
+ * A `Work` object holds information about a single work item. It is created by
+ * the client and passed to the component via IComponent::queue(). The component
+ * has two ways of returning a `Work` object to the client:
+ *   1. If the queued `Work` object has been successfully processed,
+ *      IComponentListener::onWorkDone() shall be called to notify the listener,
+ *      and the output shall be included in the returned `Work` object.
+ *   2. If the client calls IComponent::flush(), a `Work` object that has not
+ *      been processed shall be returned.
+ *
+ * `Work` is a part of @ref WorkBundle.
+ */
+struct Work {
+    /**
+     * Additional work chain info not part of this work.
+     */
+    Params chainInfo;
+
+    /**
+     * @ref FrameData for the input.
+     */
+    FrameData input;
+
+    /**
+     * The chain of `Worklet`s.
+     *
+     * The length of #worklets is 1 when tunneling is not enabled.
+     *
+     * If #worklets has more than a single element, the tunnels between
+     * successive components of the work chain must have been successfully
+     * pre-registered at the time that the `Work` is submitted. Allocating the
+     * output buffers in the `Worklet`s is the responsibility of each component
+     * in the chain.
+     *
+     * Upon `Work` submission, #worklets must be an appropriately sized vector
+     * containing `Worklet`s with @ref Worklet.hasOutput set to `false`. After a
+     * successful processing, all but the final `Worklet` in the returned
+     * #worklets must have @ref Worklet.hasOutput set to `false`.
+     */
+    vec<Worklet> worklets;
+
+    /**
+     * The number of `Worklet`s successfully processed in this chain.
+     *
+     * This must be initialized to 0 by the client when the `Work` is submitted,
+     * and it must contain the number of `Worklet`s that were successfully
+     * processed when the `Work` is returned to the client.
+     *
+     * #workletsProcessed cannot exceed the length of #worklets. If
+     * #workletsProcessed is smaller than the length of #worklets, #result
+     * cannot be `OK`.
+     */
+    uint32_t workletsProcessed;
+
+    /**
+     * The final outcome of the `Work` (corresponding to #workletsProcessed).
+     *
+     * The value of @ref Status.OK implies that all `Worklet`s have been
+     * successfully processed.
+     */
+    Status result;
+};
+
+/**
+ * List of `Work` objects.
+ *
+ * `WorkBundle` is used in IComponent::queue(), IComponent::flush() and
+ * IComponentListener::onWorkDone(). A `WorkBundle` object consists of a list of
+ * `Work` objects and a list of `BaseBlock` objects. Bundling multiple `Work`
+ * objects together provides two benefits:
+ *   1. Batching of `Work` objects can reduce the number of IPC calls.
+ *   2. If multiple `Work` objects contain `Block`s that refer to the same
+ *      `BaseBlock`, the number of `BaseBlock`s that is sent between processes
+ *      is also reduced.
+ *
+ * @note `WorkBundle` is the HIDL counterpart of the vector of `C2Work` in the
+ * Codec 2.0 standard. The presence of #baseBlocks helps with minimizing the
+ * data transferred over an IPC.
+ */
+struct WorkBundle {
+    /**
+     * A list of Work items.
+     */
+    vec<Work> works;
+    /**
+     * A list of blocks indexed by elements of #works.
+     */
+    vec<BaseBlock> baseBlocks;
+};
+
+/**
+ * Query information for supported values of a field. This is used as input to
+ * IConfigurable::querySupportedValues().
+ */
+struct FieldSupportedValuesQuery {
+    /**
+     * Identity of the field to query.
+     */
+    ParamField field;
+
+    enum Type : uint32_t {
+        /** Query all possible values regardless of other settings. */
+        POSSIBLE,
+        /** Query currently possible values given dependent settings. */
+        CURRENT,
+    };
+    /**
+     * Type of the query. See #Type for more information.
+     */
+    Type type;
+};
+
+/**
+ * This structure is used to hold the result from
+ * IConfigurable::querySupportedValues().
+ */
+struct FieldSupportedValuesQueryResult {
+    /**
+     * Result of the query. Possible values are
+     * - `OK`: The query was successful.
+     * - `BAD_STATE`: The query was requested when the `IConfigurable` instance
+     *   was in a bad state.
+     * - `BAD_INDEX`: The requested field was not recognized.
+     * - `TIMED_OUT`: The query could not be completed in a timely manner.
+     * - `BLOCKING`: The query must block, but the parameter `mayBlock` in the
+     *   call to `querySupportedValues()` was `false`.
+     * - `CORRUPTED`: Some unknown error occurred.
+     */
+    Status status;
+
+    /**
+     * Supported values. This is meaningful only when #status is `OK`.
+     */
+    FieldSupportedValues values;
+};
+
diff --git a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
index e851a7c..4543c01 100644
--- a/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
+++ b/media/omx/1.0/vts/functional/audio/VtsHalMediaOmxV1_0TargetAudioDecTest.cpp
@@ -297,6 +297,7 @@
             setupAACPort(omxNode, portIndex, OMX_AUDIO_AACObjectNull,
                          OMX_AUDIO_AACStreamFormatMP4FF, nChannels, 0,
                          nSampleRate);
+            break;
         default:
             break;
     }
diff --git a/neuralnetworks/1.2/Android.bp b/neuralnetworks/1.2/Android.bp
index 3c4ff8b..5a661e0 100644
--- a/neuralnetworks/1.2/Android.bp
+++ b/neuralnetworks/1.2/Android.bp
@@ -24,3 +24,4 @@
     ],
     gen_java: false,
 }
+
diff --git a/neuralnetworks/1.2/types.hal b/neuralnetworks/1.2/types.hal
index 0aa7cc2..4a1e7a8 100644
--- a/neuralnetworks/1.2/types.hal
+++ b/neuralnetworks/1.2/types.hal
@@ -42,6 +42,8 @@
      * realValue = (integerValue - zeroPoint) * scale.
      */
     TENSOR_QUANT16_ASYMM = 7,
+    /** A tensor of 16 bit floating point values. */
+    TENSOR_FLOAT16 = 8,
 };
 
 /**
diff --git a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
index 9af6258..c1c6e55 100644
--- a/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
+++ b/neuralnetworks/1.2/vts/functional/ValidateModel.cpp
@@ -157,6 +157,7 @@
         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:
@@ -186,6 +187,7 @@
         case OperandType::INT32:
         case OperandType::UINT32:
         case OperandType::BOOL:
+        case OperandType::TENSOR_FLOAT16:
         case OperandType::TENSOR_FLOAT32:
             return 1.0f;
         case OperandType::TENSOR_INT32:
@@ -217,6 +219,7 @@
         case OperandType::INT32:
         case OperandType::UINT32:
         case OperandType::BOOL:
+        case OperandType::TENSOR_FLOAT16:
         case OperandType::TENSOR_FLOAT32:
         case OperandType::TENSOR_INT32:
             return {1};
@@ -262,6 +265,7 @@
             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});
@@ -475,8 +479,22 @@
 
 ///////////////////////// ADD OPERATION INPUT /////////////////////////
 
+static bool addOperationInputSkip(const Operation& operation) {
+    // Skip addOperationInputTest for the following operations.
+    // L2_NORMALIZATION, LOCAL_RESPONSE_NORMALIZATION, SOFTMAX can have an optional axis parameter.
+    if (operation.type == OperationType::L2_NORMALIZATION ||
+        operation.type == OperationType::LOCAL_RESPONSE_NORMALIZATION ||
+        operation.type == OperationType::SOFTMAX) {
+        return true;
+    }
+    return false;
+}
+
 static void addOperationInputTest(const sp<IDevice>& device, const Model& model) {
     for (size_t operation = 0; operation < model.operations.size(); ++operation) {
+        if (addOperationInputSkip(model.operations[operation])) {
+            continue;
+        }
         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);
diff --git a/power/stats/1.0/Android.bp b/power/stats/1.0/Android.bp
new file mode 100644
index 0000000..2f16a21
--- /dev/null
+++ b/power/stats/1.0/Android.bp
@@ -0,0 +1,23 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.power.stats@1.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IPowerStats.hal",
+    ],
+    interfaces: [
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "Status",
+        "RailInfo",
+        "EnergyData",
+    ],
+    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..b5b3cc9
--- /dev/null
+++ b/power/stats/1.0/IPowerStats.hal
@@ -0,0 +1,99 @@
+/*
+ * 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
+     * @param samplingRate Frequency(in Hz) at which samples should be
+     *     captured. If the requested sampling rate is not supported then
+     *     SUCCESS is returned and numSamples are reported back according
+     *     to the supported sampling rate.
+     * @return mqDesc Blocking Synchronous Fast Message Queue descriptor - One
+     *     writer(power.stats HAL) and one reader are supported. Data is
+     *     present in the 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 or
+     *     INSUFFICIENT_RESOURCES if there are not enough resources.
+     */
+    streamEnergyData(uint32_t timeMs, uint32_t samplingRate)
+        generates(fmq_sync<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..703e542
--- /dev/null
+++ b/power/stats/1.0/types.hal
@@ -0,0 +1,47 @@
+/*
+ * 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,
+    INSUFFICIENT_RESOURCES = 4,
+};
+
+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/sensors/2.0/vts/functional/Android.bp b/sensors/2.0/vts/functional/Android.bp
new file mode 100644
index 0000000..8e8413c
--- /dev/null
+++ b/sensors/2.0/vts/functional/Android.bp
@@ -0,0 +1,33 @@
+//
+// 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",
+        "libfmq",
+        "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..5444287
--- /dev/null
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.cpp
@@ -0,0 +1,141 @@
+/*
+ * 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 <android/hardware/sensors/2.0/types.h>
+#include <log/log.h>
+
+#include <algorithm>
+#include <vector>
+
+using ::android::hardware::EventFlag;
+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::EventQueueFlagBits;
+using ::android::hardware::sensors::V2_0::ISensors;
+
+template <typename EnumType>
+constexpr typename std::underlying_type<EnumType>::type asBaseType(EnumType value) {
+    return static_cast<typename std::underlying_type<EnumType>::type>(value);
+}
+
+constexpr size_t SensorsHidlEnvironmentV2_0::MAX_RECEIVE_BUFFER_EVENT_COUNT;
+
+bool SensorsHidlEnvironmentV2_0::resetHal() {
+    bool succeed = false;
+    do {
+        mSensors = ISensors::getService(
+            SensorsHidlEnvironmentV2_0::Instance()->getServiceName<ISensors>());
+        if (mSensors == nullptr) {
+            break;
+        }
+
+        // Initialize FMQs
+        mEventQueue = std::make_unique<EventMessageQueue>(MAX_RECEIVE_BUFFER_EVENT_COUNT,
+                                                          true /* configureEventFlagWord */);
+
+        mWakeLockQueue = std::make_unique<WakeLockQueue>(MAX_RECEIVE_BUFFER_EVENT_COUNT,
+                                                         true /* configureEventFlagWord */);
+
+        if (mEventQueue == nullptr || mWakeLockQueue == nullptr) {
+            break;
+        }
+
+        EventFlag::deleteEventFlag(&mEventQueueFlag);
+        EventFlag::createEventFlag(mEventQueue->getEventFlagWord(), &mEventQueueFlag);
+        if (mEventQueueFlag == nullptr) {
+            break;
+        }
+
+        mSensors->initialize(*mEventQueue->getDesc(), *mWakeLockQueue->getDesc(),
+                             nullptr /* TODO: callback */);
+
+        std::vector<SensorInfo> sensorList;
+        if (!mSensors->getSensorsList([&](const hidl_vec<SensorInfo>& list) { sensorList = list; })
+                 .isOk()) {
+            break;
+        }
+
+        // stop each sensor individually
+        bool ok = true;
+        for (const auto& i : sensorList) {
+            if (!mSensors->activate(i.sensorHandle, false).isOk()) {
+                ok = false;
+                break;
+            }
+        }
+        if (!ok) {
+            break;
+        }
+
+        // mark it done
+        succeed = true;
+    } while (0);
+
+    if (!succeed) {
+        mSensors = nullptr;
+    }
+
+    return succeed;
+}
+
+void SensorsHidlEnvironmentV2_0::HidlTearDown() {
+    stopThread = true;
+
+    // Wake up the event queue so the poll thread can exit
+    mEventQueueFlag->wake(asBaseType(EventQueueFlagBits::READ_AND_PROCESS));
+    pollThread.join();
+
+    EventFlag::deleteEventFlag(&mEventQueueFlag);
+}
+
+void SensorsHidlEnvironmentV2_0::startPollingThread() {
+    stopThread = false;
+    pollThread = std::thread(pollingThread, this);
+    events.reserve(MAX_RECEIVE_BUFFER_EVENT_COUNT);
+}
+
+void SensorsHidlEnvironmentV2_0::readEvents() {
+    size_t availableEvents = mEventQueue->availableToRead();
+
+    if (availableEvents == 0) {
+        uint32_t eventFlagState = 0;
+
+        mEventQueueFlag->wait(asBaseType(EventQueueFlagBits::READ_AND_PROCESS), &eventFlagState);
+        availableEvents = mEventQueue->availableToRead();
+    }
+
+    size_t eventsToRead = std::min(availableEvents, mEventBuffer.size());
+    if (eventsToRead > 0) {
+        if (mEventQueue->read(mEventBuffer.data(), eventsToRead)) {
+            for (const auto& e : mEventBuffer) {
+                addEvent(e);
+            }
+        }
+    }
+}
+
+void SensorsHidlEnvironmentV2_0::pollingThread(SensorsHidlEnvironmentV2_0* env) {
+    ALOGD("polling thread start");
+
+    while (!env->stopThread.load()) {
+        env->readEvents();
+    }
+
+    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..7241923
--- /dev/null
+++ b/sensors/2.0/vts/functional/SensorsHidlEnvironmentV2_0.h
@@ -0,0 +1,125 @@
+/*
+ * 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 <fmq/MessageQueue.h>
+#include <utils/StrongPointer.h>
+
+#include <array>
+#include <atomic>
+#include <memory>
+
+using ::android::sp;
+using ::android::hardware::MessageQueue;
+
+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>();
+    }
+
+    virtual void HidlTearDown() override;
+
+   private:
+    friend SensorsHidlTest;
+
+    SensorsHidlEnvironmentV2_0() : mEventQueueFlag(nullptr) {}
+
+    /**
+     * Resets the HAL with new FMQs and a new Event Flag
+     *
+     * @return bool true if successful, false otherwise
+     */
+    bool resetHal() override;
+
+    /**
+     * Starts the polling thread that reads sensor events from the Event FMQ
+     */
+    void startPollingThread() override;
+
+    /**
+     * Thread responsible for calling functions to read Event FMQ
+     *
+     * @param env SensorEnvironment to being polling for events on
+     */
+    static void pollingThread(SensorsHidlEnvironmentV2_0* env);
+
+    /**
+     * Reads and saves sensor events from the Event FMQ
+     */
+    void readEvents();
+
+    GTEST_DISALLOW_COPY_AND_ASSIGN_(SensorsHidlEnvironmentV2_0);
+
+    /**
+     * Pointer to the Sensors HAL Interface that allows the test to call HAL functions.
+     */
+    sp<android::hardware::sensors::V2_0::ISensors> mSensors;
+
+    /**
+     * Type used to simplify the creation of the Event FMQ
+     */
+    typedef MessageQueue<Event, ::android::hardware::kSynchronizedReadWrite> EventMessageQueue;
+
+    /**
+     * Type used to simplify the creation of the Wake Lock FMQ
+     */
+    typedef MessageQueue<uint32_t, ::android::hardware::kSynchronizedReadWrite> WakeLockQueue;
+
+    /**
+     * The Event FMQ where the test framework is able to read sensor events that the Sensors HAL
+     * has written.
+     */
+    std::unique_ptr<EventMessageQueue> mEventQueue;
+
+    /**
+     * The Wake Lock FMQ is used by the test to notify the Sensors HAL whenever it has processed
+     * WAKE_UP sensor events.
+     */
+    std::unique_ptr<WakeLockQueue> mWakeLockQueue;
+
+    /**
+     * The Event Queue Flag notifies the test framework when sensor events have been written to the
+     * Event FMQ by the Sensors HAL.
+     */
+    ::android::hardware::EventFlag* mEventQueueFlag;
+
+    /**
+     * The maximum number of sensor events that can be read from the Event FMQ at one time.
+     */
+    static constexpr size_t MAX_RECEIVE_BUFFER_EVENT_COUNT = 128;
+
+    /**
+     * An array that is used to store sensor events read from the Event FMQ
+     */
+    std::array<Event, MAX_RECEIVE_BUFFER_EVENT_COUNT> mEventBuffer;
+};
+
+#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..7c6f010
--- /dev/null
+++ b/sensors/2.0/vts/functional/VtsHalSensorsV2_0TargetTest.cpp
@@ -0,0 +1,448 @@
+/*
+ * 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 getSensors()->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 getSensors()->batch(sensorHandle, samplingPeriodNs, maxReportLatencyNs);
+    }
+
+    Return<Result> flush(int32_t sensorHandle) override {
+        return getSensors()->flush(sensorHandle);
+    }
+
+    Return<Result> injectSensorData(const Event& event) override {
+        return getSensors()->injectSensorData(event);
+    }
+
+    Return<void> registerDirectChannel(const SharedMemInfo& mem,
+                                       ISensors::registerDirectChannel_cb _hidl_cb) override;
+
+    Return<Result> unregisterDirectChannel(int32_t channelHandle) override {
+        return getSensors()->unregisterDirectChannel(channelHandle);
+    }
+
+    Return<void> configDirectReport(int32_t sensorHandle, int32_t channelHandle, RateLevel rate,
+                                    ISensors::configDirectReport_cb _hidl_cb) override {
+        return getSensors()->configDirectReport(sensorHandle, channelHandle, rate, _hidl_cb);
+    }
+
+    inline sp<::android::hardware::sensors::V2_0::ISensors>& getSensors() {
+        return SensorsHidlEnvironmentV2_0::Instance()->mSensors;
+    }
+
+    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 getSensors()->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.
+    getSensors()->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;
+    getSensors()->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;
+
+    getSensors()->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) {
+    getSensors()->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, getSensors()->setOperationMode(OperationMode::NORMAL));
+    ASSERT_EQ(Result::OK, getSensors()->setOperationMode(OperationMode::DATA_INJECTION));
+    ASSERT_EQ(Result::OK, getSensors()->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, getSensors()->setOperationMode(OperationMode::NORMAL));
+    ASSERT_EQ(Result::OK, getSensors()->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, getSensors()->injectSensorData(dummy));
+                break;
+            }
+            default:
+                break;
+        }
+    }
+    ASSERT_EQ(Result::OK, getSensors()->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/utils/SensorsHidlTestBase.cpp b/sensors/common/vts/utils/SensorsHidlTestBase.cpp
index 8497d82..b72fdfd 100644
--- a/sensors/common/vts/utils/SensorsHidlTestBase.cpp
+++ b/sensors/common/vts/utils/SensorsHidlTestBase.cpp
@@ -29,7 +29,8 @@
 using ::android::hardware::hidl_string;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using namespace ::android::hardware::sensors::V1_0;
+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*/));
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
index 4a6f713..96e6085 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlEnvironmentBase.h
@@ -30,8 +30,8 @@
 class SensorsHidlEnvironmentBase : public ::testing::VtsHalHidlTargetTestEnvBase {
    public:
     using Event = ::android::hardware::sensors::V1_0::Event;
-    void HidlSetUp() override;
-    void HidlTearDown() override;
+    virtual void HidlSetUp() override;
+    virtual void HidlTearDown() override;
 
     // Get and clear all events collected so far (like "cat" shell command).
     // If output is nullptr, it clears all collected events.
diff --git a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
index 405dc28..f4b259f 100644
--- a/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
+++ b/sensors/common/vts/utils/include/sensors-vts-utils/SensorsHidlTestBase.h
@@ -31,7 +31,18 @@
 using ::android::hardware::hidl_string;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using namespace ::android::hardware::sensors::V1_0;
+
+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:
diff --git a/thermal/2.0/Android.bp b/thermal/2.0/Android.bp
new file mode 100644
index 0000000..6eb4da0
--- /dev/null
+++ b/thermal/2.0/Android.bp
@@ -0,0 +1,29 @@
+// This file is autogenerated by hidl-gen -Landroidbp.
+
+hidl_interface {
+    name: "android.hardware.thermal@2.0",
+    root: "android.hardware",
+    vndk: {
+        enabled: true,
+    },
+    srcs: [
+        "types.hal",
+        "IThermal.hal",
+        "IThermalChangedCallback.hal",
+    ],
+    interfaces: [
+        "android.hardware.thermal@1.0",
+        "android.hidl.base@1.0",
+    ],
+    types: [
+        "CoolingDevice",
+        "CoolingType",
+        "Temperature",
+        "TemperatureThreshold",
+        "TemperatureType",
+        "ThrottlingSeverity",
+        "ThrottlingSeverityCount",
+    ],
+    gen_java: true,
+}
+
diff --git a/thermal/2.0/IThermal.hal b/thermal/2.0/IThermal.hal
new file mode 100644
index 0000000..548ac9d
--- /dev/null
+++ b/thermal/2.0/IThermal.hal
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.thermal@2.0;
+
+import android.hardware.thermal@1.0::IThermal;
+import android.hardware.thermal@1.0::ThermalStatus;
+import IThermalChangedCallback;
+
+interface IThermal extends @1.0::IThermal {
+
+    /**
+     * Retrieves temperatures in Celsius.
+     *
+     * @param filterType whether to filter the result for a given type.
+     * @param type the TemperatureType such as battery or skin.
+     *
+     * @return status Status of the operation. If status code is FAILURE,
+     *    the status.debugMessage must be populated with a human-readable
+     *    error message.
+     *
+     * @return temperatures If status code is SUCCESS, it's filled with the
+     *    current temperatures. The order of temperatures of built-in
+     *    devices (such as CPUs, GPUs and etc.) in the list must be kept
+     *    the same regardless of the number of calls to this method even if
+     *    they go offline, if these devices exist on boot. The method
+     *    always returns and never removes such temperatures.
+     */
+    getCurrentTemperatures(bool filterType, TemperatureType type)
+        generates (ThermalStatus status, vec<Temperature> temperatures);
+
+    /**
+     * Retrieves temperature thresholds in Celsius.
+     *
+     * @param filterType whether to filter the result for a given type.
+     * @param type the TemperatureType such as battery or skin.
+     *
+     * @return status Status of the operation. If status code is FAILURE,
+     *    the status.debugMessage must be populated with a human-readable error message.
+     * @return temperatureThresholds If status code is SUCCESS, it's filled with the
+     *    temperatures thresholds. The order of temperatures of built-in
+     *    devices (such as CPUs, GPUs and etc.) in the list must be kept
+     *    the same regardless of the number of calls to this method even if
+     *    they go offline, if these devices exist on boot. The method
+     *    always returns and never removes such temperatures.
+     */
+    getTemperatureThresholds(bool filterType, TemperatureType type)
+        generates (ThermalStatus status, vec<TemperatureThreshold> temperatureThresholds);
+
+   /**
+    * Register an IThermalChangedCallback, used by the Thermal HAL
+    * to send thermal events when thermal mitigation status changed.
+    * Multiple registrations with different IThermalChangedCallback must be allowed.
+    * Multiple registrations with same IThermalChangedCallback is not allowed, client
+    * should unregister the given IThermalChangedCallback first.
+    *
+    * @param callback the IThermalChangedCallback to use for sending
+    *    thermal events (cannot be nullptr).
+    * @param filterType if filter for given sensor type.
+    * @param type the type to be filtered.
+    *
+    * @return status Status of the operation. If status code is FAILURE,
+    *    the status.debugMessage must be populated with a human-readable error message.
+    */
+   registerThermalChangedCallback(IThermalChangedCallback callback,
+                                  bool filterType,
+                                  TemperatureType type)
+       generates (ThermalStatus status);
+
+   /**
+    * Register an IThermalChangedCallback, used by the Thermal HAL
+    * to send thermal events when thermal mitigation status changed.
+    *
+    * @param callback the IThermalChangedCallback to use for sending
+    *    thermal events, or nullptr to set no callback.
+    *
+    * @return status Status of the operation. If status code is FAILURE,
+    *    the status.debugMessage must be populated with a human-readable error message.
+    */
+   unregisterThermalChangedCallback(IThermalChangedCallback callback)
+       generates (ThermalStatus status);
+
+    /**
+     * Retrieves the cooling devices information.
+     *
+     * @param filterType whether to filter the result for a given type.
+     * @param type the CoolingDevice such as CPU/GPU.
+     *
+     * @return status Status of the operation. If status code is FAILURE,
+     *    the status.debugMessage must be populated with the human-readable
+     *    error message.
+     * @return devices If status code is SUCCESS, it's filled with the current
+     *    cooling device information. The order of built-in cooling
+     *    devices in the list must be kept the same regardless of the number
+     *    of calls to this method even if they go offline, if these devices
+     *    exist on boot. The method always returns and never removes from
+     *    the list such cooling devices.
+     */
+   getCurrentCoolingDevices(bool filterType, CoolingType type)
+       generates (ThermalStatus status, vec<CoolingDevice> devices);
+};
diff --git a/thermal/2.0/IThermalChangedCallback.hal b/thermal/2.0/IThermalChangedCallback.hal
new file mode 100644
index 0000000..b06bfbf
--- /dev/null
+++ b/thermal/2.0/IThermalChangedCallback.hal
@@ -0,0 +1,33 @@
+/*
+ * 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.thermal@2.0;
+
+import android.hardware.thermal@2.0::Temperature;
+
+/**
+ * IThermalChangedCallback send throttling notification to clients.
+ */
+interface IThermalChangedCallback {
+    /**
+     * Send a thermal throttling event to all ThermalHAL
+     * thermal event listeners.
+     *
+     * @param temperature The temperature associated with the
+     *    throttling event.
+     */
+    oneway notifyThrottling (Temperature temperature);
+};
diff --git a/thermal/2.0/default/Android.bp b/thermal/2.0/default/Android.bp
new file mode 100644
index 0000000..f620e6e
--- /dev/null
+++ b/thermal/2.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.thermal@2.0-service",
+    defaults: ["hidl_defaults"],
+    relative_install_path: "hw",
+    vendor: true,
+    init_rc: ["android.hardware.thermal@2.0-service.rc"],
+    vintf_fragments: ["android.hardware.thermal@2.0-service.xml"],
+    srcs: [
+        "Thermal.cpp",
+        "service.cpp"
+    ],
+    shared_libs: [
+        "libbase",
+        "libhidlbase",
+        "libhidltransport",
+        "libutils",
+        "android.hardware.thermal@2.0",
+        "android.hardware.thermal@1.0",
+    ],
+}
diff --git a/thermal/2.0/default/Thermal.cpp b/thermal/2.0/default/Thermal.cpp
new file mode 100644
index 0000000..442af61
--- /dev/null
+++ b/thermal/2.0/default/Thermal.cpp
@@ -0,0 +1,208 @@
+/*
+ * 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.thermal@2.0-service-mock"
+
+#include <cmath>
+#include <set>
+
+#include <android-base/logging.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "Thermal.h"
+
+namespace android {
+namespace hardware {
+namespace thermal {
+namespace V2_0 {
+namespace implementation {
+
+using ::android::sp;
+using ::android::hardware::interfacesEqual;
+using ::android::hardware::thermal::V1_0::ThermalStatus;
+using ::android::hardware::thermal::V1_0::ThermalStatusCode;
+
+std::set<sp<IThermalChangedCallback>> gCallbacks;
+
+static const Temperature_1_0 kTemp_1_0 = {
+    .type = static_cast<::android::hardware::thermal::V1_0::TemperatureType>(TemperatureType::CPU),
+    .name = "test temperature sensor",
+    .currentValue = 98.6,
+    .throttlingThreshold = 58,
+    .shutdownThreshold = 60.0,
+    .vrThrottlingThreshold = 59.0,
+};
+
+static const Temperature_2_0 kTemp_2_0 = {
+    .type = TemperatureType::SKIN,
+    .name = "test temperature sensor",
+    .value = 98.6,
+    .throttlingStatus = ThrottlingSeverity::CRITICAL,
+};
+
+static const TemperatureThreshold kTempThreshold = {
+    .type = TemperatureType::SKIN,
+    .name = "test temperature sensor",
+    .hotThrottlingThresholds = {{NAN, NAN, NAN, NAN, NAN, NAN, NAN}},
+    .coldThrottlingThresholds = {{NAN, NAN, NAN, NAN, NAN, NAN, NAN}},
+    .vrThrottlingThreshold = NAN,
+};
+
+static const CoolingDevice_1_0 kCooling_1_0 = {
+    .type = ::android::hardware::thermal::V1_0::CoolingType::FAN_RPM,
+    .name = "test cooling device",
+    .currentValue = 100.0,
+};
+
+static const CoolingDevice_2_0 kCooling_2_0 = {
+    .type = CoolingType::CPU,
+    .name = "test cooling device",
+    .value = 1,
+};
+
+static const CpuUsage kCpuUsage = {
+    .name = "cpu_name",
+    .active = 0,
+    .total = 0,
+    .isOnline = true,
+};
+
+// Methods from ::android::hardware::thermal::V1_0::IThermal follow.
+Return<void> Thermal::getTemperatures(getTemperatures_cb _hidl_cb) {
+    ThermalStatus status;
+    status.code = ThermalStatusCode::SUCCESS;
+    std::vector<Temperature_1_0> temperatures = {kTemp_1_0};
+    _hidl_cb(status, temperatures);
+    return Void();
+}
+
+Return<void> Thermal::getCpuUsages(getCpuUsages_cb _hidl_cb) {
+    ThermalStatus status;
+    status.code = ThermalStatusCode::SUCCESS;
+    std::vector<CpuUsage> cpu_usages = {kCpuUsage};
+    _hidl_cb(status, cpu_usages);
+    return Void();
+}
+
+Return<void> Thermal::getCoolingDevices(getCoolingDevices_cb _hidl_cb) {
+    ThermalStatus status;
+    status.code = ThermalStatusCode::SUCCESS;
+    std::vector<CoolingDevice_1_0> cooling_devices = {kCooling_1_0};
+    _hidl_cb(status, cooling_devices);
+    return Void();
+}
+
+// Methods from ::android::hardware::thermal::V2_0::IThermal follow.
+Return<void> Thermal::getCurrentTemperatures(bool filterType, TemperatureType type,
+                                             getCurrentTemperatures_cb _hidl_cb) {
+    ThermalStatus status;
+    status.code = ThermalStatusCode::SUCCESS;
+    std::vector<Temperature_2_0> temperatures;
+    if (filterType && type != kTemp_2_0.type) {
+        status.code = ThermalStatusCode::FAILURE;
+        status.debugMessage = "Failed to read data";
+    } else {
+        temperatures = {kTemp_2_0};
+    }
+    _hidl_cb(status, temperatures);
+    return Void();
+}
+
+Return<void> Thermal::getTemperatureThresholds(bool filterType, TemperatureType type,
+                                               getTemperatureThresholds_cb _hidl_cb) {
+    ThermalStatus status;
+    status.code = ThermalStatusCode::SUCCESS;
+    std::vector<TemperatureThreshold> temperature_thresholds;
+    if (filterType && type != kTempThreshold.type) {
+        status.code = ThermalStatusCode::FAILURE;
+        status.debugMessage = "Failed to read data";
+    } else {
+        temperature_thresholds = {kTempThreshold};
+    }
+    _hidl_cb(status, temperature_thresholds);
+    return Void();
+}
+
+Return<void> Thermal::getCurrentCoolingDevices(bool filterType, CoolingType type,
+                                               getCurrentCoolingDevices_cb _hidl_cb) {
+    ThermalStatus status;
+    status.code = ThermalStatusCode::SUCCESS;
+    std::vector<CoolingDevice_2_0> cooling_devices;
+    if (filterType && type != kCooling_2_0.type) {
+        status.code = ThermalStatusCode::FAILURE;
+        status.debugMessage = "Failed to read data";
+    } else {
+        cooling_devices = {kCooling_2_0};
+    }
+    _hidl_cb(status, cooling_devices);
+    return Void();
+}
+
+Return<void> Thermal::registerThermalChangedCallback(const sp<IThermalChangedCallback>& callback,
+                                                     bool filterType, TemperatureType type,
+                                                     registerThermalChangedCallback_cb _hidl_cb) {
+    ThermalStatus status;
+    status.code = ThermalStatusCode::SUCCESS;
+    std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
+    if (std::any_of(callbacks_.begin(), callbacks_.end(), [&](const CallbackSetting& c) {
+            return interfacesEqual(c.callback, callback);
+        })) {
+        status.code = ThermalStatusCode::FAILURE;
+        status.debugMessage = "Same callback interface registered already";
+        LOG(ERROR) << status.debugMessage;
+    } else {
+        callbacks_.emplace_back(callback, filterType, type);
+        LOG(INFO) << "A callback has been registered to ThermalHAL, isFilter: " << filterType
+                  << " Type: " << android::hardware::thermal::V2_0::toString(type);
+    }
+    _hidl_cb(status);
+    return Void();
+}
+
+Return<void> Thermal::unregisterThermalChangedCallback(
+    const sp<IThermalChangedCallback>& callback, unregisterThermalChangedCallback_cb _hidl_cb) {
+    ThermalStatus status;
+    status.code = ThermalStatusCode::SUCCESS;
+    bool removed = false;
+    std::lock_guard<std::mutex> _lock(thermal_callback_mutex_);
+    callbacks_.erase(
+        std::remove_if(callbacks_.begin(), callbacks_.end(),
+                       [&](const CallbackSetting& c) {
+                           if (interfacesEqual(c.callback, callback)) {
+                               LOG(INFO)
+                                   << "A callback has been unregistered from ThermalHAL, isFilter: "
+                                   << c.is_filter_type << " Type: "
+                                   << android::hardware::thermal::V2_0::toString(c.type);
+                               removed = true;
+                               return true;
+                           }
+                           return false;
+                       }),
+        callbacks_.end());
+    if (!removed) {
+        status.code = ThermalStatusCode::FAILURE;
+        status.debugMessage = "The callback was not registered before";
+        LOG(ERROR) << status.debugMessage;
+    }
+    _hidl_cb(status);
+    return Void();
+}
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace thermal
+}  // namespace hardware
+}  // namespace android
diff --git a/thermal/2.0/default/Thermal.h b/thermal/2.0/default/Thermal.h
new file mode 100644
index 0000000..5fa1abd
--- /dev/null
+++ b/thermal/2.0/default/Thermal.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_HARDWARE_THERMAL_V2_0_THERMAL_H
+#define ANDROID_HARDWARE_THERMAL_V2_0_THERMAL_H
+
+#include <android/hardware/thermal/2.0/IThermal.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+
+namespace android {
+namespace hardware {
+namespace thermal {
+namespace V2_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;
+using ::android::hardware::thermal::V1_0::CpuUsage;
+using ::android::hardware::thermal::V2_0::CoolingType;
+using ::android::hardware::thermal::V2_0::IThermal;
+using CoolingDevice_1_0 = ::android::hardware::thermal::V1_0::CoolingDevice;
+using CoolingDevice_2_0 = ::android::hardware::thermal::V2_0::CoolingDevice;
+using Temperature_1_0 = ::android::hardware::thermal::V1_0::Temperature;
+using Temperature_2_0 = ::android::hardware::thermal::V2_0::Temperature;
+using ::android::hardware::thermal::V2_0::IThermalChangedCallback;
+using ::android::hardware::thermal::V2_0::TemperatureThreshold;
+using ::android::hardware::thermal::V2_0::TemperatureType;
+
+struct CallbackSetting {
+    CallbackSetting(sp<IThermalChangedCallback> callback, bool is_filter_type, TemperatureType type)
+        : callback(callback), is_filter_type(is_filter_type), type(type) {}
+    sp<IThermalChangedCallback> callback;
+    bool is_filter_type;
+    TemperatureType type;
+};
+
+class Thermal : public IThermal {
+   public:
+    // Methods from ::android::hardware::thermal::V1_0::IThermal follow.
+    Return<void> getTemperatures(getTemperatures_cb _hidl_cb) override;
+    Return<void> getCpuUsages(getCpuUsages_cb _hidl_cb) override;
+    Return<void> getCoolingDevices(getCoolingDevices_cb _hidl_cb) override;
+
+    // Methods from ::android::hardware::thermal::V2_0::IThermal follow.
+    Return<void> getCurrentTemperatures(bool filterType, TemperatureType type,
+                                        getCurrentTemperatures_cb _hidl_cb) override;
+    Return<void> getTemperatureThresholds(bool filterType, TemperatureType type,
+                                          getTemperatureThresholds_cb _hidl_cb) override;
+    Return<void> registerThermalChangedCallback(
+        const sp<IThermalChangedCallback>& callback, bool filterType, TemperatureType type,
+        registerThermalChangedCallback_cb _hidl_cb) override;
+    Return<void> unregisterThermalChangedCallback(
+        const sp<IThermalChangedCallback>& callback,
+        unregisterThermalChangedCallback_cb _hidl_cb) override;
+    Return<void> getCurrentCoolingDevices(bool filterType, CoolingType type,
+                                          getCurrentCoolingDevices_cb _hidl_cb) override;
+
+   private:
+    std::mutex thermal_callback_mutex_;
+    std::vector<CallbackSetting> callbacks_;
+};
+
+}  // namespace implementation
+}  // namespace V2_0
+}  // namespace thermal
+}  // namespace hardware
+}  // namespace android
+
+#endif  // ANDROID_HARDWARE_THERMAL_V2_0_THERMAL_H
diff --git a/thermal/2.0/default/android.hardware.thermal@2.0-service.rc b/thermal/2.0/default/android.hardware.thermal@2.0-service.rc
new file mode 100644
index 0000000..de49d20
--- /dev/null
+++ b/thermal/2.0/default/android.hardware.thermal@2.0-service.rc
@@ -0,0 +1,5 @@
+service vendor.thermal-hal-2-0-mock /vendor/bin/hw/android.hardware.thermal@2.0-service
+    interface android.hardware.thermal@2.0::IThermal default
+    class hal
+    user system
+    group system
diff --git a/thermal/2.0/default/android.hardware.thermal@2.0-service.xml b/thermal/2.0/default/android.hardware.thermal@2.0-service.xml
new file mode 100644
index 0000000..c4c7d4d
--- /dev/null
+++ b/thermal/2.0/default/android.hardware.thermal@2.0-service.xml
@@ -0,0 +1,11 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.thermal</name>
+        <transport>hwbinder</transport>
+        <version>2.0</version>
+        <interface>
+            <name>IThermal</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/thermal/2.0/default/service.cpp b/thermal/2.0/default/service.cpp
new file mode 100644
index 0000000..dd24078
--- /dev/null
+++ b/thermal/2.0/default/service.cpp
@@ -0,0 +1,63 @@
+/*
+ * 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.thermal@2.0-service-mock"
+
+#include <android-base/logging.h>
+#include <hidl/HidlTransportSupport.h>
+#include "Thermal.h"
+
+using ::android::OK;
+using ::android::status_t;
+
+// libhwbinder:
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::joinRpcThreadpool;
+
+// Generated HIDL files:
+using ::android::hardware::thermal::V2_0::IThermal;
+using ::android::hardware::thermal::V2_0::implementation::Thermal;
+
+static int shutdown() {
+    LOG(ERROR) << "Thermal Service is shutting down.";
+    return 1;
+}
+
+int main(int /* argc */, char** /* argv */) {
+    status_t status;
+    android::sp<IThermal> service = nullptr;
+
+    LOG(INFO) << "Thermal HAL Service Mock 2.0 starting...";
+
+    service = new Thermal();
+    if (service == nullptr) {
+        LOG(ERROR) << "Error creating an instance of ThermalHAL.  Exiting...";
+        return shutdown();
+    }
+
+    configureRpcThreadpool(1, true /* callerWillJoin */);
+
+    status = service->registerAsService();
+    if (status != OK) {
+        LOG(ERROR) << "Could not register service for ThermalHAL (" << status << ")";
+        return shutdown();
+    }
+
+    LOG(INFO) << "Thermal Service started successfully.";
+    joinRpcThreadpool();
+    // We should not get past the joinRpcThreadpool().
+    return shutdown();
+}
diff --git a/thermal/2.0/types.hal b/thermal/2.0/types.hal
new file mode 100644
index 0000000..7b60d00
--- /dev/null
+++ b/thermal/2.0/types.hal
@@ -0,0 +1,155 @@
+/*
+ * 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.thermal@2.0;
+
+import android.hardware.thermal@1.0::types;
+
+/** Device temperature types */
+enum TemperatureType : @1.0::TemperatureType {
+    USB_PORT = 4,
+    POWER_AMPLIFIER = 5,
+};
+
+
+/** Device cooling device types */
+enum CoolingType : uint32_t {
+    FAN,
+    BATTERY,
+    CPU,
+    GPU,
+    MODEM,
+    NPU,
+    COMPONENT, // for the rest of components
+};
+
+/** Device throttling severity */
+enum ThrottlingSeverity : uint32_t {
+    /**
+     * Not under throttling.
+     */
+    NONE = 0,
+    /**
+     * Light throttling where UX is not impacted.
+     */
+    LIGHT,
+    /**
+     * Moderate throttling where UX is not largily impacted.
+     */
+    MODERATE,
+    /**
+     * Severe throttling where UX is largely impacted.
+     * Similar to 1.0 throttlingThreshold.
+     */
+    SEVERE,
+    /**
+     * Platform has done everything to reduce power.
+     */
+    CRITICAL,
+    /**
+     * User should be warned before shutdown.
+     */
+    WARNING,
+    /**
+     * Need shutdown immediately.
+     */
+    SHUTDOWN,
+};
+
+enum ThrottlingSeverityCount : uint32_t {NUM_THROTTLING_LEVELS = 7};
+
+struct TemperatureThreshold {
+    /**
+     * This temperature's type.
+     */
+    TemperatureType type;
+
+    /**
+     * Name of this temperature matching the Temperature struct.
+     * All temperatures of the same "type" must have a different "name",
+     * e.g., cpu0, battery. Clients use it to match Temperature struct.
+     */
+    string name;
+
+    /**
+     * Hot throttling temperature constant for this temperature sensor in
+     * level defined in ThrottlingSeverity including shutdown. Throttling
+     * happens when temperature >= threshold. If not available, set to NAN.
+     */
+    float[ThrottlingSeverityCount:NUM_THROTTLING_LEVELS] hotThrottlingThresholds;
+
+    /**
+     * Cold throttling temperature constant for this temperature sensor in
+     * level defined in ThrottlingSeverity including shutdown. Throttling
+     * happens when temperature <= threshold. If not available, set to NAN.
+     */
+    float[ThrottlingSeverityCount:NUM_THROTTLING_LEVELS] coldThrottlingThresholds;
+
+    /**
+     * Threshold temperature above which the VR mode clockrate minimums cannot
+     * be maintained for this device.
+     * If not available, set by HAL to NAN.
+     */
+    float vrThrottlingThreshold;
+};
+
+struct Temperature {
+    /**
+     * This temperature's type.
+     */
+    TemperatureType type;
+
+    /**
+     * Name of this temperature matching the TemperatureThreshold.
+     * All temperatures of the same "type" must have a different "name",
+     * e.g., cpu0, battery. Clients use it to match with TemperatureThreshold
+     * struct.
+     */
+    string name;
+
+    /**
+     * Current temperature in Celsius. If not available set by HAL to NAN.
+     */
+    float value;
+
+    /**
+     * The current throttling level of the sensor.
+     */
+    ThrottlingSeverity throttlingStatus;
+};
+
+struct CoolingDevice {
+    /**
+     * This cooling device type, CPU, GPU, BATTERY, and etc.
+     */
+    CoolingType type;
+
+    /**
+     * Name of this cooling device.
+     * All cooling devices of the same "type" must have a different "name".
+     * The name is usually defined in kernel device tree, and this is for client
+     * logging purpose.
+     */
+    string name;
+
+    /**
+     * Current throttle state of the cooling device. The value can any unsigned integer
+     * numbers between 0 and max_state defined in its driver, usually representing the
+     * associated device's power state. 0 means device is not in throttling, higher value
+     * means deeper throttling.
+     */
+    uint64_t value;
+};
diff --git a/thermal/2.0/vts/functional/Android.bp b/thermal/2.0/vts/functional/Android.bp
new file mode 100644
index 0000000..f4e95f8
--- /dev/null
+++ b/thermal/2.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: "VtsHalThermalV2_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalThermalV2_0TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.thermal@1.0",
+        "android.hardware.thermal@2.0",
+    ],
+}
+
diff --git a/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp b/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp
new file mode 100644
index 0000000..535f618
--- /dev/null
+++ b/thermal/2.0/vts/functional/VtsHalThermalV2_0TargetTest.cpp
@@ -0,0 +1,264 @@
+/*
+ * 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/hardware/thermal/2.0/IThermal.h>
+#include <android/hardware/thermal/2.0/IThermalChangedCallback.h>
+#include <android/hardware/thermal/2.0/types.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::thermal::V1_0::ThermalStatus;
+using ::android::hardware::thermal::V1_0::ThermalStatusCode;
+using ::android::hardware::thermal::V2_0::CoolingDevice;
+using ::android::hardware::thermal::V2_0::CoolingType;
+using ::android::hardware::thermal::V2_0::IThermal;
+using ::android::hardware::thermal::V2_0::IThermalChangedCallback;
+using ::android::hardware::thermal::V2_0::Temperature;
+using ::android::hardware::thermal::V2_0::TemperatureThreshold;
+using ::android::hardware::thermal::V2_0::TemperatureType;
+using ::android::hardware::thermal::V2_0::ThrottlingSeverity;
+using ::android::hardware::thermal::V2_0::ThrottlingSeverityCount;
+
+constexpr char kCallbackNameNotifyThrottling[] = "notifyThrottling";
+static const Temperature kThrottleTemp = {
+    .type = TemperatureType::SKIN,
+    .name = "test temperature sensor",
+    .value = 98.6,
+    .throttlingStatus = ThrottlingSeverity::CRITICAL,
+};
+
+class ThermalCallbackArgs {
+   public:
+    Temperature temperature;
+};
+
+// Callback class for receiving thermal event notifications from main class
+class ThermalCallback : public ::testing::VtsHalHidlTargetCallbackBase<ThermalCallbackArgs>,
+                        public IThermalChangedCallback {
+   public:
+    Return<void> notifyThrottling(const Temperature& temperature) override {
+        ThermalCallbackArgs args;
+        args.temperature = temperature;
+        NotifyFromCallback(kCallbackNameNotifyThrottling, args);
+        return Void();
+    }
+};
+
+// Test environment for Thermal HIDL HAL.
+class ThermalHidlEnvironment : public ::testing::VtsHalHidlTargetTestEnvBase {
+   public:
+    // get the test environment singleton
+    static ThermalHidlEnvironment* Instance() {
+        static ThermalHidlEnvironment* instance = new ThermalHidlEnvironment;
+        return instance;
+    }
+
+    void registerTestServices() override { registerTestService<IThermal>(); }
+
+   private:
+    ThermalHidlEnvironment() {}
+};
+
+// The main test class for THERMAL HIDL HAL 2.0.
+class ThermalHidlTest : public ::testing::VtsHalHidlTargetTestBase {
+   public:
+    virtual void SetUp() override {
+        mThermal = ::testing::VtsHalHidlTargetTestBase::getService<IThermal>(
+            ThermalHidlEnvironment::Instance()->getServiceName<IThermal>());
+        ASSERT_NE(mThermal, nullptr);
+        mThermalCallback = new (std::nothrow) ThermalCallback();
+        ASSERT_NE(mThermalCallback, nullptr);
+        auto ret = mThermal->registerThermalChangedCallback(
+            mThermalCallback, false, TemperatureType::SKIN,
+            [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
+        ASSERT_TRUE(ret.isOk());
+        // Expect to fail if register again
+        ret = mThermal->registerThermalChangedCallback(
+            mThermalCallback, false, TemperatureType::SKIN,
+            [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
+        ASSERT_TRUE(ret.isOk());
+    }
+
+    virtual void TearDown() override {
+        auto ret = mThermal->unregisterThermalChangedCallback(
+            mThermalCallback,
+            [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
+        ASSERT_TRUE(ret.isOk());
+        // Expect to fail if unregister again
+        ret = mThermal->unregisterThermalChangedCallback(
+            mThermalCallback,
+            [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
+        ASSERT_TRUE(ret.isOk());
+    }
+
+   protected:
+    sp<IThermal> mThermal;
+    sp<ThermalCallback> mThermalCallback;
+};  // class ThermalHidlTest
+
+// Test ThermalChangedCallback::notifyThrottling().
+// This just calls into and back from our local ThermalChangedCallback impl.
+// Note: a real thermal throttling event from the Thermal HAL could be
+// inadvertently received here.
+TEST_F(ThermalHidlTest, NotifyThrottlingTest) {
+    auto ret = mThermalCallback->notifyThrottling(kThrottleTemp);
+    ASSERT_TRUE(ret.isOk());
+    auto res = mThermalCallback->WaitForCallback(kCallbackNameNotifyThrottling);
+    EXPECT_TRUE(res.no_timeout);
+    ASSERT_TRUE(res.args);
+    EXPECT_EQ(kThrottleTemp, res.args->temperature);
+}
+
+// Test Thermal->registerThermalChangedCallback.
+TEST_F(ThermalHidlTest, RegisterThermalChangedCallbackTest) {
+    // Expect to fail with same callback
+    auto ret = mThermal->registerThermalChangedCallback(
+        mThermalCallback, false, TemperatureType::SKIN,
+        [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
+    ASSERT_TRUE(ret.isOk());
+    sp<ThermalCallback> localThermalCallback = new (std::nothrow) ThermalCallback();
+    // Expect to succeed with different callback
+    ret = mThermal->registerThermalChangedCallback(
+        localThermalCallback, false, TemperatureType::SKIN,
+        [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
+    ASSERT_TRUE(ret.isOk());
+    // Remove the local callback.
+    ret = mThermal->unregisterThermalChangedCallback(
+        localThermalCallback,
+        [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
+    ASSERT_TRUE(ret.isOk());
+}
+
+// Test Thermal->unregisterThermalChangedCallback.
+TEST_F(ThermalHidlTest, UnregisterThermalChangedCallbackTest) {
+    sp<ThermalCallback> localThermalCallback = new (std::nothrow) ThermalCallback();
+    // Expect to fail as the callback was not registered before
+    auto ret = mThermal->unregisterThermalChangedCallback(
+        localThermalCallback,
+        [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
+    ASSERT_TRUE(ret.isOk());
+    // Register a local callback
+    ret = mThermal->registerThermalChangedCallback(
+        localThermalCallback, false, TemperatureType::SKIN,
+        [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
+    ASSERT_TRUE(ret.isOk());
+    // Expect to succeed with callback removed
+    ret = mThermal->unregisterThermalChangedCallback(
+        localThermalCallback,
+        [](ThermalStatus status) { EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code); });
+    ASSERT_TRUE(ret.isOk());
+    // Expect to fail as the callback has been unregistered already
+    ret = mThermal->unregisterThermalChangedCallback(
+        localThermalCallback,
+        [](ThermalStatus status) { EXPECT_NE(ThermalStatusCode::SUCCESS, status.code); });
+    ASSERT_TRUE(ret.isOk());
+}
+
+// Sanity test for Thermal::getCurrentTemperatures().
+TEST_F(ThermalHidlTest, TemperatureTest) {
+    mThermal->getCurrentTemperatures(false, TemperatureType::SKIN,
+                                     [](ThermalStatus status, hidl_vec<Temperature> temperatures) {
+                                         if (temperatures.size()) {
+                                             EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
+                                         } else {
+                                             EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
+                                         }
+                                     });
+    for (int i = static_cast<int>(TemperatureType::UNKNOWN);
+         i <= static_cast<int>(TemperatureType::POWER_AMPLIFIER); ++i) {
+        auto type = static_cast<TemperatureType>(i);
+        mThermal->getCurrentTemperatures(
+            true, type, [&type](ThermalStatus status, hidl_vec<Temperature> temperatures) {
+                if (temperatures.size()) {
+                    EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
+                } else {
+                    EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
+                }
+                for (int i = 0; i < temperatures.size(); ++i) {
+                    EXPECT_EQ(type, temperatures[i].type);
+                }
+            });
+    }
+}
+
+// Sanity test for Thermal::getTemperatureThresholds().
+TEST_F(ThermalHidlTest, TemperatureThresholdTest) {
+    mThermal->getTemperatureThresholds(
+        false, TemperatureType::SKIN,
+        [](ThermalStatus status, hidl_vec<TemperatureThreshold> temperatures) {
+            if (temperatures.size()) {
+                EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
+            } else {
+                EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
+            }
+        });
+    for (int i = static_cast<int>(TemperatureType::UNKNOWN);
+         i <= static_cast<int>(TemperatureType::POWER_AMPLIFIER); ++i) {
+        auto type = static_cast<TemperatureType>(i);
+        mThermal->getTemperatureThresholds(
+            true, type, [&type](ThermalStatus status, hidl_vec<TemperatureThreshold> temperatures) {
+                if (temperatures.size()) {
+                    EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
+                } else {
+                    EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
+                }
+                for (int i = 0; i < temperatures.size(); ++i) {
+                    EXPECT_EQ(type, temperatures[i].type);
+                }
+            });
+    }
+}
+
+// Sanity test for Thermal::getCurrentCoolingDevices().
+TEST_F(ThermalHidlTest, CoolingDeviceTest) {
+    mThermal->getCurrentCoolingDevices(
+        false, CoolingType::CPU, [](ThermalStatus status, hidl_vec<CoolingDevice> cooling_devices) {
+            if (cooling_devices.size()) {
+                EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
+            } else {
+                EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
+            }
+        });
+    for (int i = 0; i <= static_cast<int>(CoolingType::COMPONENT); ++i) {
+        auto type = static_cast<CoolingType>(i);
+        mThermal->getCurrentCoolingDevices(
+            true, type, [&type](ThermalStatus status, hidl_vec<CoolingDevice> cooling_devices) {
+                if (cooling_devices.size()) {
+                    EXPECT_EQ(ThermalStatusCode::SUCCESS, status.code);
+                } else {
+                    EXPECT_NE(ThermalStatusCode::SUCCESS, status.code);
+                }
+                for (int i = 0; i < cooling_devices.size(); ++i) {
+                    EXPECT_EQ(type, cooling_devices[i].type);
+                }
+            });
+    }
+}
+
+int main(int argc, char** argv) {
+    ::testing::AddGlobalTestEnvironment(ThermalHidlEnvironment::Instance());
+    ::testing::InitGoogleTest(&argc, argv);
+    ThermalHidlEnvironment::Instance()->init(&argc, argv);
+    int status = RUN_ALL_TESTS();
+    cout << "Test result = " << status << std::endl;
+    return status;
+}
diff --git a/update-base-files.sh b/update-base-files.sh
index 75d2be5..daaa530 100755
--- a/update-base-files.sh
+++ b/update-base-files.sh
@@ -36,6 +36,9 @@
 hidl-gen $options \
          -o $ANDROID_BUILD_TOP/system/core/include/system/graphics-base-v1.1.h \
          android.hardware.graphics.common@1.1
+hidl-gen $options \
+         -o $ANDROID_BUILD_TOP/system/core/include/system/graphics-base-v1.2.h \
+         android.hardware.graphics.common@1.2
 
 # system/media
 hidl-gen $options \
diff --git a/update-makefiles.sh b/update-makefiles.sh
index b7e4235..14c5b01 100755
--- a/update-makefiles.sh
+++ b/update-makefiles.sh
@@ -1,4 +1,12 @@
 #!/bin/bash
+# Script to update Android make-files for HAL and VTS modules.
+
+set -e
+
+if [ -z "$ANDROID_BUILD_TOP" ]; then
+    echo "Missing ANDROID_BUILD_TOP env variable. Run 'lunch' first."
+    exit 1
+fi
 
 source $ANDROID_BUILD_TOP/system/tools/hidl/update-makefiles-helper.sh
 
@@ -6,3 +14,8 @@
   "android.hardware:hardware/interfaces" \
   "android.hidl:system/libhidl/transport"
 
+echo "Updating files at $ANDROID_BUILD_TOP/test/vts-testcase/hal"
+pushd $ANDROID_BUILD_TOP/test/vts-testcase/hal
+./script/update_makefiles.py
+popd
+
diff --git a/wifi/1.0/vts/functional/Android.bp b/wifi/1.0/vts/functional/Android.bp
index 6522f4d..d0dd915 100644
--- a/wifi/1.0/vts/functional/Android.bp
+++ b/wifi/1.0/vts/functional/Android.bp
@@ -45,6 +45,8 @@
     static_libs: [
         "VtsHalWifiV1_0TargetTestUtil",
         "android.hardware.wifi@1.0",
+        "android.hardware.wifi@1.2",
+        "android.hardware.wifi@1.3",
     ],
 }
 
diff --git a/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
index a341028..a22cd72 100644
--- a/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
+++ b/wifi/1.0/vts/functional/wifi_sta_iface_hidl_test.cpp
@@ -17,6 +17,7 @@
 #include <android-base/logging.h>
 
 #include <android/hardware/wifi/1.0/IWifiStaIface.h>
+#include <android/hardware/wifi/1.3/IWifiStaIface.h>
 
 #include <VtsHalHidlTargetTestBase.h>
 
@@ -143,6 +144,14 @@
         return;
     }
 
+    sp<::android::hardware::wifi::V1_3::IWifiStaIface> iface_converted =
+        ::android::hardware::wifi::V1_3::IWifiStaIface::castFrom(
+            wifi_sta_iface_);
+    if (iface_converted != nullptr) {
+        // Skip this test since this API is deprecated in this newer HAL version
+        return;
+    }
+
     // Enable link layer stats collection.
     EXPECT_EQ(WifiStatusCode::SUCCESS,
               HIDL_INVOKE(wifi_sta_iface_, enableLinkLayerStatsCollection, true)
diff --git a/wifi/1.3/default/Android.mk b/wifi/1.3/default/Android.mk
index 541e5f0..e05d2f0 100644
--- a/wifi/1.3/default/Android.mk
+++ b/wifi/1.3/default/Android.mk
@@ -30,6 +30,8 @@
 ifdef WIFI_HIDL_FEATURE_DISABLE_AP
 LOCAL_CPPFLAGS += -DWIFI_HIDL_FEATURE_DISABLE_AP
 endif
+# Allow implicit fallthroughs in wifi_legacy_hal.cpp until they are fixed.
+LOCAL_CFLAGS += -Wno-error=implicit-fallthrough
 LOCAL_SRC_FILES := \
     hidl_struct_util.cpp \
     hidl_sync_util.cpp \