Merge changes from topic 'test-hwc2' am: 29943c1971 am: 92360b14a0
am: d47b3c13da

Change-Id: I616fe5646001c45933d466ee77824dc435819c5b
diff --git a/services/surfaceflinger/tests/hwc2/Android.mk b/services/surfaceflinger/tests/hwc2/Android.mk
new file mode 100644
index 0000000..b8c2133
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Android.mk
@@ -0,0 +1,53 @@
+#
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := test-hwc2
+LOCAL_MODULE_TAGS := tests
+LOCAL_CFLAGS += \
+    -fstack-protector-all \
+    -g \
+    -Wall -Wextra \
+    -Werror \
+    -fno-builtin \
+    -DEGL_EGLEXT_PROTOTYPES \
+    -DGL_GLEXT_PROTOTYPES
+LOCAL_SHARED_LIBRARIES := \
+    libcutils \
+    libutils \
+    libhardware \
+    libEGL \
+    libGLESv2 \
+    libui \
+    libgui \
+    liblog \
+    libsync
+LOCAL_STATIC_LIBRARIES := \
+    libbase \
+    libadf \
+    libadfhwc
+LOCAL_SRC_FILES := \
+    Hwc2Test.cpp \
+    Hwc2TestProperties.cpp \
+    Hwc2TestLayer.cpp \
+    Hwc2TestLayers.cpp \
+    Hwc2TestBuffer.cpp \
+    Hwc2TestClientTarget.cpp \
+    Hwc2TestVirtualDisplay.cpp
+
+include $(BUILD_NATIVE_TEST)
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
new file mode 100644
index 0000000..062485e
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
@@ -0,0 +1,4556 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <array>
+#include <unordered_set>
+#include <unordered_map>
+#include <gtest/gtest.h>
+#include <dlfcn.h>
+#include <android-base/unique_fd.h>
+#include <hardware/hardware.h>
+#include <sync/sync.h>
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include "Hwc2TestLayer.h"
+#include "Hwc2TestLayers.h"
+#include "Hwc2TestClientTarget.h"
+#include "Hwc2TestVirtualDisplay.h"
+
+void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData,
+        hwc2_display_t display, int32_t connected);
+void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData,
+        hwc2_display_t display, int64_t timestamp);
+
+class Hwc2Test : public testing::Test {
+public:
+
+    virtual void SetUp()
+    {
+        hw_module_t const* hwc2Module;
+
+        int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &hwc2Module);
+        ASSERT_GE(err, 0) << "failed to get hwc hardware module: "
+                << strerror(-err);
+
+        /* The following method will fail if you have not run
+         * "adb shell stop" */
+        err = hwc2_open(hwc2Module, &mHwc2Device);
+        ASSERT_GE(err, 0) << "failed to open hwc hardware module: "
+                << strerror(-err);
+
+        populateDisplays();
+    }
+
+    virtual void TearDown()
+    {
+
+        for (auto itr = mLayers.begin(); itr != mLayers.end();) {
+            hwc2_display_t display = itr->first;
+            hwc2_layer_t layer = itr->second;
+            itr++;
+            /* Destroys and removes the layer from mLayers */
+            destroyLayer(display, layer);
+        }
+
+        for (auto itr = mActiveDisplays.begin(); itr != mActiveDisplays.end();) {
+            hwc2_display_t display = *itr;
+            itr++;
+            /* Sets power mode to off and removes the display from
+             * mActiveDisplays */
+            setPowerMode(display, HWC2_POWER_MODE_OFF);
+        }
+
+        for (auto itr = mVirtualDisplays.begin(); itr != mVirtualDisplays.end();) {
+            hwc2_display_t display = *itr;
+            itr++;
+            /* Destroys virtual displays */
+            destroyVirtualDisplay(display);
+        }
+
+        if (mHwc2Device)
+            hwc2_close(mHwc2Device);
+    }
+
+    void registerCallback(hwc2_callback_descriptor_t descriptor,
+            hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_REGISTER_CALLBACK>(
+                getFunction(HWC2_FUNCTION_REGISTER_CALLBACK));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, descriptor,
+                callbackData, pointer));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to register callback";
+        }
+    }
+
+    void getDisplayType(hwc2_display_t display, hwc2_display_type_t* outType,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_TYPE>(
+                getFunction(HWC2_FUNCTION_GET_DISPLAY_TYPE));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                    reinterpret_cast<int32_t*>(outType)));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display type";
+        }
+    }
+
+    /* If the populateDisplays function is still receiving displays and the
+     * display is connected, the display handle is stored in mDisplays. */
+    void hotplugCallback(hwc2_display_t display, int32_t connected)
+    {
+        std::lock_guard<std::mutex> lock(mHotplugMutex);
+
+        if (mHotplugStatus != Hwc2TestHotplugStatus::Receiving)
+            return;
+
+        if (connected == HWC2_CONNECTION_CONNECTED)
+            mDisplays.insert(display);
+
+        mHotplugCv.notify_all();
+    }
+
+    void createLayer(hwc2_display_t display, hwc2_layer_t* outLayer,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_CREATE_LAYER>(
+                getFunction(HWC2_FUNCTION_CREATE_LAYER));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                outLayer));
+
+        if (err == HWC2_ERROR_NONE)
+            mLayers.insert(std::make_pair(display, *outLayer));
+
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to create layer";
+        }
+    }
+
+    void destroyLayer(hwc2_display_t display, hwc2_layer_t layer,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_DESTROY_LAYER>(
+                getFunction(HWC2_FUNCTION_DESTROY_LAYER));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer));
+
+        if (err == HWC2_ERROR_NONE)
+            mLayers.erase(std::make_pair(display, layer));
+
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to destroy layer "
+                    << layer;
+        }
+    }
+
+    void getDisplayAttribute(hwc2_display_t display, hwc2_config_t config,
+            hwc2_attribute_t attribute, int32_t* outValue,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_ATTRIBUTE>(
+                getFunction(HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, config,
+                attribute, outValue));
+
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display attribute "
+                    << getAttributeName(attribute) << " for config " << config;
+        }
+    }
+
+    void getDisplayConfigs(hwc2_display_t display,
+            std::vector<hwc2_config_t>* outConfigs,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_CONFIGS>(
+                getFunction(HWC2_FUNCTION_GET_DISPLAY_CONFIGS));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        uint32_t numConfigs = 0;
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                &numConfigs, nullptr));
+
+        if (err == HWC2_ERROR_NONE) {
+            outConfigs->resize(numConfigs);
+
+            err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                    &numConfigs, outConfigs->data()));
+        }
+
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get configs for"
+                    " display " << display;
+        }
+    }
+
+    void getActiveConfig(hwc2_display_t display, hwc2_config_t* outConfig,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_GET_ACTIVE_CONFIG>(
+                getFunction(HWC2_FUNCTION_GET_ACTIVE_CONFIG));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                outConfig));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get active config on"
+                    " display " << display;
+        }
+    }
+
+    void setActiveConfig(hwc2_display_t display, hwc2_config_t config,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_ACTIVE_CONFIG>(
+                getFunction(HWC2_FUNCTION_SET_ACTIVE_CONFIG));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, config));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set active config "
+                    << config;
+        }
+    }
+
+    void getDozeSupport(hwc2_display_t display, int32_t* outSupport,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_GET_DOZE_SUPPORT>(
+                getFunction(HWC2_FUNCTION_GET_DOZE_SUPPORT));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                outSupport));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get doze support on"
+                    " display " << display;
+        }
+    }
+
+    void setPowerMode(hwc2_display_t display, hwc2_power_mode_t mode,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_POWER_MODE>(
+                getFunction(HWC2_FUNCTION_SET_POWER_MODE));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                mode));
+        if (outErr) {
+            *outErr = err;
+            if (err != HWC2_ERROR_NONE)
+                return;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set power mode "
+                    << getPowerModeName(mode) << " on display " << display;
+        }
+
+        if (mode == HWC2_POWER_MODE_OFF) {
+            mActiveDisplays.erase(display);
+        } else {
+            mActiveDisplays.insert(display);
+        }
+    }
+
+    void setVsyncEnabled(hwc2_display_t display, hwc2_vsync_t enabled,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_VSYNC_ENABLED>(
+                getFunction(HWC2_FUNCTION_SET_VSYNC_ENABLED));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                enabled));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set vsync enabled "
+                    << getVsyncName(enabled);
+        }
+    }
+
+    void vsyncCallback(hwc2_display_t display, int64_t timestamp)
+    {
+        std::lock_guard<std::mutex> lock(mVsyncMutex);
+        mVsyncDisplay = display;
+        mVsyncTimestamp = timestamp;
+        mVsyncCv.notify_all();
+    }
+
+    void getDisplayName(hwc2_display_t display, std::string* outName,
+                hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_NAME>(
+                getFunction(HWC2_FUNCTION_GET_DISPLAY_NAME));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        uint32_t size = 0;
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, &size,
+                nullptr));
+
+        if (err == HWC2_ERROR_NONE) {
+            std::vector<char> name(size);
+
+            err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, &size,
+                    name.data()));
+
+            outName->assign(name.data());
+        }
+
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display name for "
+                    << display;
+        }
+    }
+
+    void setLayerCompositionType(hwc2_display_t display, hwc2_layer_t layer,
+            hwc2_composition_t composition, hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_COMPOSITION_TYPE>(
+                getFunction(HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+                composition));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer composition"
+                    " type " << getCompositionName(composition);
+        }
+    }
+
+    void setCursorPosition(hwc2_display_t display, hwc2_layer_t layer,
+            int32_t x, int32_t y, hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_CURSOR_POSITION>(
+                getFunction(HWC2_FUNCTION_SET_CURSOR_POSITION));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer, x,
+                y));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set cursor position";
+        }
+    }
+
+    void setLayerBlendMode(hwc2_display_t display, hwc2_layer_t layer,
+            hwc2_blend_mode_t mode, hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_BLEND_MODE>(
+                getFunction(HWC2_FUNCTION_SET_LAYER_BLEND_MODE));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+                mode));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer blend mode "
+                    << getBlendModeName(mode);
+        }
+    }
+
+    void setLayerBuffer(hwc2_display_t display, hwc2_layer_t layer,
+            buffer_handle_t buffer, int32_t acquireFence,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_BUFFER>(
+                getFunction(HWC2_FUNCTION_SET_LAYER_BUFFER));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+                buffer, acquireFence));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer buffer";
+        }
+    }
+
+    void setLayerColor(hwc2_display_t display, hwc2_layer_t layer,
+            hwc_color_t color, hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_COLOR>(
+                getFunction(HWC2_FUNCTION_SET_LAYER_COLOR));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+                color));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer color";
+        }
+    }
+
+    void setLayerDataspace(hwc2_display_t display, hwc2_layer_t layer,
+            android_dataspace_t dataspace, hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_DATASPACE>(
+                getFunction(HWC2_FUNCTION_SET_LAYER_DATASPACE));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                layer, dataspace));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer dataspace";
+        }
+    }
+
+    void setLayerDisplayFrame(hwc2_display_t display, hwc2_layer_t layer,
+            const hwc_rect_t& displayFrame, hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_DISPLAY_FRAME>(
+                getFunction(HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+                displayFrame));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer display"
+                    " frame";
+        }
+    }
+
+    void setLayerPlaneAlpha(hwc2_display_t display, hwc2_layer_t layer,
+            float alpha, hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_PLANE_ALPHA>(
+                getFunction(HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+                alpha));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer plane alpha "
+                    << alpha;
+        }
+    }
+
+    void setLayerSourceCrop(hwc2_display_t display, hwc2_layer_t layer,
+            const hwc_frect_t& sourceCrop, hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_SOURCE_CROP>(
+                getFunction(HWC2_FUNCTION_SET_LAYER_SOURCE_CROP));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+                sourceCrop));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer source crop";
+        }
+    }
+
+    void setLayerSurfaceDamage(hwc2_display_t display, hwc2_layer_t layer,
+            const hwc_region_t& surfaceDamage, hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_SURFACE_DAMAGE>(
+                getFunction(HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+                surfaceDamage));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer surface"
+                    " damage";
+        }
+    }
+
+    void setLayerTransform(hwc2_display_t display, hwc2_layer_t layer,
+            hwc_transform_t transform, hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_TRANSFORM>(
+                getFunction(HWC2_FUNCTION_SET_LAYER_TRANSFORM));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+                transform));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer transform "
+                    << getTransformName(transform);
+        }
+    }
+
+    void setLayerVisibleRegion(hwc2_display_t display, hwc2_layer_t layer,
+            const hwc_region_t& visibleRegion, hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_VISIBLE_REGION>(
+                getFunction(HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+                visibleRegion));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer visible"
+                    " region";
+        }
+    }
+
+    void setLayerZOrder(hwc2_display_t display, hwc2_layer_t layer,
+            uint32_t zOrder, hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_LAYER_Z_ORDER>(
+                getFunction(HWC2_FUNCTION_SET_LAYER_Z_ORDER));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, layer,
+                zOrder));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set layer z order "
+                    << zOrder;
+        }
+    }
+
+    void validateDisplay(hwc2_display_t display, uint32_t* outNumTypes,
+            uint32_t* outNumRequests, hwc2_error_t* outErr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_VALIDATE_DISPLAY>(
+                getFunction(HWC2_FUNCTION_VALIDATE_DISPLAY));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        *outErr = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                outNumTypes, outNumRequests));
+    }
+
+    void validateDisplay(hwc2_display_t display, uint32_t* outNumTypes,
+            uint32_t* outNumRequests, bool* outHasChanges)
+    {
+        hwc2_error_t err = HWC2_ERROR_NONE;
+
+        EXPECT_NO_FATAL_FAILURE(validateDisplay(display, outNumTypes,
+                outNumRequests, &err));
+
+        if (err != HWC2_ERROR_HAS_CHANGES) {
+            *outHasChanges = false;
+            EXPECT_EQ(err, HWC2_ERROR_NONE) << "failed to validate display";
+        } else {
+            *outHasChanges = true;
+        }
+    }
+
+    void getDisplayRequests(hwc2_display_t display,
+            hwc2_display_request_t* outDisplayRequests,
+            std::vector<hwc2_layer_t>* outLayers,
+            std::vector<hwc2_layer_request_t>* outLayerRequests,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_GET_DISPLAY_REQUESTS>(
+                getFunction(HWC2_FUNCTION_GET_DISPLAY_REQUESTS));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        uint32_t numElements = 0;
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                reinterpret_cast<int32_t*>(outDisplayRequests), &numElements,
+                nullptr, nullptr));
+
+        if (err == HWC2_ERROR_NONE && numElements > 0) {
+            outLayers->resize(numElements);
+            outLayerRequests->resize(numElements);
+
+            err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                    reinterpret_cast<int32_t*>(outDisplayRequests), &numElements,
+                    reinterpret_cast<uint64_t*>(outLayers->data()),
+                    reinterpret_cast<int32_t*>(outLayerRequests->data())));
+        }
+
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get display requests";
+        }
+    }
+
+    void handleRequests(hwc2_display_t display,
+            const std::vector<hwc2_layer_t>& layers, uint32_t numRequests,
+            std::set<hwc2_layer_t>* outClearLayers = nullptr,
+            bool* outFlipClientTarget = nullptr)
+    {
+        hwc2_display_request_t displayRequest =
+                static_cast<hwc2_display_request_t>(0);
+        std::vector<hwc2_layer_t> requestedLayers;
+        std::vector<hwc2_layer_request_t> requests;
+
+        ASSERT_NO_FATAL_FAILURE(getDisplayRequests(display, &displayRequest,
+                &requestedLayers, &requests));
+
+        EXPECT_EQ(numRequests, requests.size()) << "validate returned "
+                << numRequests << " requests and get display requests returned "
+                << requests.size() << " requests";
+
+        for (size_t i = 0; i < requests.size(); i++) {
+            hwc2_layer_t requestedLayer = requestedLayers.at(i);
+            hwc2_layer_request_t request = requests.at(i);
+
+            EXPECT_EQ(std::count(layers.begin(), layers.end(), requestedLayer),
+                    0) << "get display requests returned an unknown layer";
+            EXPECT_NE(request, 0) << "returned empty request for layer "
+                    << requestedLayer;
+
+            if (outClearLayers && request
+                    == HWC2_LAYER_REQUEST_CLEAR_CLIENT_TARGET)
+                outClearLayers->insert(requestedLayer);
+        }
+
+        if (outFlipClientTarget)
+            *outFlipClientTarget = displayRequest
+                    & HWC2_DISPLAY_REQUEST_FLIP_CLIENT_TARGET;
+    }
+
+    void getChangedCompositionTypes(hwc2_display_t display,
+            std::vector<hwc2_layer_t>* outLayers,
+            std::vector<hwc2_composition_t>* outTypes,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_GET_CHANGED_COMPOSITION_TYPES>(
+                getFunction(HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        uint32_t numElements = 0;
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                &numElements, nullptr, nullptr));
+
+        if (err == HWC2_ERROR_NONE && numElements > 0) {
+            outLayers->resize(numElements);
+            outTypes->resize(numElements);
+
+            err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                    &numElements, reinterpret_cast<uint64_t*>(outLayers->data()),
+                    reinterpret_cast<int32_t*>(outTypes->data())));
+        }
+
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get changed"
+                    " composition types";
+        }
+    }
+
+    void handleCompositionChanges(hwc2_display_t display,
+            const Hwc2TestLayers& testLayers,
+            const std::vector<hwc2_layer_t>& layers, uint32_t numTypes,
+            std::set<hwc2_layer_t>* outClientLayers = nullptr)
+    {
+        std::vector<hwc2_layer_t> changedLayers;
+        std::vector<hwc2_composition_t> types;
+
+        ASSERT_NO_FATAL_FAILURE(getChangedCompositionTypes(display,
+                &changedLayers, &types));
+
+        EXPECT_EQ(numTypes, types.size()) << "validate returned "
+                << numTypes << " types and get changed composition types"
+                " returned " << types.size() << " types";
+
+        for (size_t i = 0; i < types.size(); i++) {
+
+            auto layer = std::find(layers.begin(), layers.end(),
+                    changedLayers.at(i));
+
+            EXPECT_TRUE(layer != layers.end() || !testLayers.contains(*layer))
+                    << "get changed composition types returned an unknown layer";
+
+            hwc2_composition_t requestedType = testLayers.getComposition(*layer);
+            hwc2_composition_t returnedType = types.at(i);
+
+            EXPECT_NE(returnedType, HWC2_COMPOSITION_INVALID) << "get changed"
+                    " composition types returned invalid composition";
+
+            switch (requestedType) {
+            case HWC2_COMPOSITION_CLIENT:
+                EXPECT_TRUE(false) << getCompositionName(returnedType)
+                        << " cannot be changed";
+                break;
+            case HWC2_COMPOSITION_DEVICE:
+            case HWC2_COMPOSITION_SOLID_COLOR:
+                EXPECT_EQ(returnedType, HWC2_COMPOSITION_CLIENT)
+                        << "composition of type "
+                        << getCompositionName(requestedType)
+                        << " can only be changed to "
+                        << getCompositionName(HWC2_COMPOSITION_CLIENT);
+                break;
+            case HWC2_COMPOSITION_CURSOR:
+            case HWC2_COMPOSITION_SIDEBAND:
+                EXPECT_TRUE(returnedType == HWC2_COMPOSITION_CLIENT
+                        || returnedType == HWC2_COMPOSITION_DEVICE)
+                        << "composition of type "
+                        << getCompositionName(requestedType)
+                        << " can only be changed to "
+                        << getCompositionName(HWC2_COMPOSITION_CLIENT) << " or "
+                        << getCompositionName(HWC2_COMPOSITION_DEVICE);
+                break;
+            default:
+                EXPECT_TRUE(false) << "unknown type "
+                        << getCompositionName(requestedType);
+                break;
+            }
+
+            if (outClientLayers)
+                if (returnedType == HWC2_COMPOSITION_CLIENT)
+                    outClientLayers->insert(*layer);
+        }
+
+        if (outClientLayers) {
+            for (auto layer : layers) {
+                if (testLayers.getComposition(layer) == HWC2_COMPOSITION_CLIENT)
+                    outClientLayers->insert(layer);
+            }
+        }
+    }
+
+    void acceptDisplayChanges(hwc2_display_t display,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_ACCEPT_DISPLAY_CHANGES>(
+                getFunction(HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to accept display changes";
+        }
+    }
+
+    void getClientTargetSupport(hwc2_display_t display, int32_t width,
+            int32_t height, android_pixel_format_t format,
+            android_dataspace_t dataspace, hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_GET_CLIENT_TARGET_SUPPORT>(
+                getFunction(HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, width,
+                height, format, dataspace));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get client target"
+                    " support";
+        }
+    }
+
+    void setClientTarget(hwc2_display_t display, buffer_handle_t handle,
+            int32_t acquireFence, android_dataspace_t dataspace,
+            hwc_region_t damage, hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_CLIENT_TARGET>(
+                getFunction(HWC2_FUNCTION_SET_CLIENT_TARGET));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, handle,
+                acquireFence, dataspace, damage));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set client target";
+        }
+    }
+
+    void presentDisplay(hwc2_display_t display, int32_t* outPresentFence,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_PRESENT_DISPLAY>(
+                getFunction(HWC2_FUNCTION_PRESENT_DISPLAY));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                outPresentFence));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to present display";
+        }
+    }
+
+    void getReleaseFences(hwc2_display_t display,
+            std::vector<hwc2_layer_t>* outLayers,
+            std::vector<int32_t>* outFences, hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_GET_RELEASE_FENCES>(
+                getFunction(HWC2_FUNCTION_GET_RELEASE_FENCES));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        uint32_t numElements = 0;
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                &numElements, nullptr, nullptr));
+
+        if (err == HWC2_ERROR_NONE) {
+            outLayers->resize(numElements);
+            outFences->resize(numElements);
+
+            err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                    &numElements, outLayers->data(), outFences->data()));
+        }
+
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get release fences";
+        }
+    }
+
+    void getColorModes(hwc2_display_t display,
+            std::vector<android_color_mode_t>* outColorModes,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_GET_COLOR_MODES>(
+                getFunction(HWC2_FUNCTION_GET_COLOR_MODES));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        uint32_t numColorModes = 0;
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                &numColorModes, nullptr));
+        if (err == HWC2_ERROR_NONE) {
+            outColorModes->resize(numColorModes);
+
+            err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                    &numColorModes,
+                    reinterpret_cast<int32_t*>(outColorModes->data())));
+        }
+
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get color modes for"
+                    " display " << display;
+        }
+    }
+
+    void setColorMode(hwc2_display_t display, android_color_mode_t colorMode,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_COLOR_MODE>(
+                getFunction(HWC2_FUNCTION_SET_COLOR_MODE));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                static_cast<int32_t>(colorMode)));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set color mode "
+                    << colorMode;
+        }
+    }
+
+    void getHdrCapabilities(hwc2_display_t display,
+            std::vector<android_hdr_t>* outTypes, float* outMaxLuminance,
+            float* outMaxAverageLuminance, float* outMinLuminance,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_GET_HDR_CAPABILITIES>(
+                getFunction(HWC2_FUNCTION_GET_HDR_CAPABILITIES));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        uint32_t numTypes = 0;
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                &numTypes, nullptr, outMaxLuminance, outMaxAverageLuminance,
+                outMinLuminance));
+
+        if (err == HWC2_ERROR_NONE) {
+            outTypes->resize(numTypes);
+
+            err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, &numTypes,
+                    reinterpret_cast<int32_t*>(outTypes->data()), outMaxLuminance,
+                    outMaxAverageLuminance, outMinLuminance));
+        }
+
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to get hdr capabilities"
+                    " for display " << display;
+        }
+    }
+
+    void setColorTransform(hwc2_display_t display,
+            const std::array<float, 16>& matrix, android_color_transform_t hint,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_COLOR_TRANSFORM>(
+                getFunction(HWC2_FUNCTION_SET_COLOR_TRANSFORM));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display,
+                matrix.data(), hint));
+
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set color transform "
+                    << hint;
+        }
+    }
+
+    void createVirtualDisplay(uint32_t width, uint32_t height,
+            android_pixel_format_t* outFormat, hwc2_display_t* outDisplay,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_CREATE_VIRTUAL_DISPLAY>(
+                getFunction(HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, width, height,
+                reinterpret_cast<int32_t*>(outFormat), outDisplay));
+
+        if (err == HWC2_ERROR_NONE)
+            mVirtualDisplays.insert(*outDisplay);
+
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to create virtual display";
+        }
+    }
+
+    void destroyVirtualDisplay(hwc2_display_t display,
+            hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_DESTROY_VIRTUAL_DISPLAY>(
+                getFunction(HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display));
+
+        if (err == HWC2_ERROR_NONE)
+            mVirtualDisplays.erase(display);
+
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to destroy virtual display";
+        }
+    }
+
+    void getMaxVirtualDisplayCount(uint32_t* outMaxCnt)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_GET_MAX_VIRTUAL_DISPLAY_COUNT>(
+                getFunction(HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        *outMaxCnt = pfn(mHwc2Device);
+    }
+
+    void setOutputBuffer(hwc2_display_t display, buffer_handle_t buffer,
+            int32_t releaseFence, hwc2_error_t* outErr = nullptr)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_SET_OUTPUT_BUFFER>(
+                getFunction(HWC2_FUNCTION_SET_OUTPUT_BUFFER));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        auto err = static_cast<hwc2_error_t>(pfn(mHwc2Device, display, buffer,
+                releaseFence));
+        if (outErr) {
+            *outErr = err;
+        } else {
+            ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to set output buffer";
+        }
+    }
+
+    void dump(std::string* outBuffer)
+    {
+        auto pfn = reinterpret_cast<HWC2_PFN_DUMP>(
+                getFunction(HWC2_FUNCTION_DUMP));
+        ASSERT_TRUE(pfn) << "failed to get function";
+
+        uint32_t size = 0;
+
+        pfn(mHwc2Device, &size, nullptr);
+
+        std::vector<char> buffer(size);
+
+        pfn(mHwc2Device, &size, buffer.data());
+
+        outBuffer->assign(buffer.data());
+    }
+
+    void getBadDisplay(hwc2_display_t* outDisplay)
+    {
+        for (hwc2_display_t display = 0; display < UINT64_MAX; display++) {
+            if (mDisplays.count(display) == 0) {
+                *outDisplay = display;
+                return;
+            }
+        }
+        ASSERT_TRUE(false) << "Unable to find bad display. UINT64_MAX displays"
+                " are registered. This should never happen.";
+    }
+
+    void waitForVsync(hwc2_display_t* outDisplay = nullptr,
+            int64_t* outTimestamp = nullptr)
+    {
+        std::unique_lock<std::mutex> lock(mVsyncMutex);
+        ASSERT_EQ(mVsyncCv.wait_for(lock, std::chrono::seconds(3)),
+                std::cv_status::no_timeout) << "timed out attempting to get"
+                " vsync callback";
+        if (outDisplay)
+            *outDisplay = mVsyncDisplay;
+        if (outTimestamp)
+            *outTimestamp = mVsyncTimestamp;
+    }
+
+    void enableVsync(hwc2_display_t display)
+    {
+        ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, this,
+                reinterpret_cast<hwc2_function_pointer_t>(
+                hwc2TestVsyncCallback)));
+        ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
+    }
+
+    void disableVsync(hwc2_display_t display)
+    {
+        ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
+    }
+
+protected:
+    hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor)
+    {
+        return mHwc2Device->getFunction(mHwc2Device, descriptor);
+    }
+
+    void getCapabilities(std::vector<hwc2_capability_t>* outCapabilities)
+    {
+        uint32_t num = 0;
+
+        mHwc2Device->getCapabilities(mHwc2Device, &num, nullptr);
+
+        outCapabilities->resize(num);
+
+        mHwc2Device->getCapabilities(mHwc2Device, &num,
+                reinterpret_cast<int32_t*>(outCapabilities->data()));
+    }
+
+    /* Registers a hotplug callback and waits for hotplug callbacks. This
+     * function will have no effect if called more than once. */
+    void populateDisplays()
+    {
+        /* Sets the hotplug status to receiving */
+        {
+            std::lock_guard<std::mutex> lock(mHotplugMutex);
+
+            if (mHotplugStatus != Hwc2TestHotplugStatus::Init)
+                return;
+            mHotplugStatus = Hwc2TestHotplugStatus::Receiving;
+        }
+
+        /* Registers the callback. This function call cannot be locked because
+         * a callback could happen on the same thread */
+        ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_HOTPLUG, this,
+                reinterpret_cast<hwc2_function_pointer_t>(
+                hwc2TestHotplugCallback)));
+
+        /* Waits for hotplug events. If a hotplug event has not come within 1
+         * second, stop waiting. */
+        std::unique_lock<std::mutex> lock(mHotplugMutex);
+
+        while (mHotplugCv.wait_for(lock, std::chrono::seconds(1)) !=
+                std::cv_status::timeout) { }
+
+        /* Sets the hotplug status to done. Future calls will have no effect */
+        mHotplugStatus = Hwc2TestHotplugStatus::Done;
+    }
+
+    /* NOTE: will create min(newlayerCnt, max supported layers) layers */
+    void createLayers(hwc2_display_t display,
+            std::vector<hwc2_layer_t>* outLayers, size_t newLayerCnt)
+    {
+        std::vector<hwc2_layer_t> newLayers;
+        hwc2_layer_t layer;
+        hwc2_error_t err = HWC2_ERROR_NONE;
+
+        for (size_t i = 0; i < newLayerCnt; i++) {
+
+            EXPECT_NO_FATAL_FAILURE(createLayer(display, &layer, &err));
+            if (err == HWC2_ERROR_NO_RESOURCES)
+                break;
+            if (err != HWC2_ERROR_NONE) {
+                newLayers.clear();
+                ASSERT_EQ(err, HWC2_ERROR_NONE) << "failed to create layer";
+            }
+            newLayers.push_back(layer);
+        }
+
+        *outLayers = std::move(newLayers);
+    }
+
+    void destroyLayers(hwc2_display_t display,
+            std::vector<hwc2_layer_t>&& layers)
+    {
+        for (hwc2_layer_t layer : layers) {
+            EXPECT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+        }
+    }
+
+    void getInvalidConfig(hwc2_display_t display, hwc2_config_t* outConfig)
+    {
+        std::vector<hwc2_config_t> configs;
+
+        ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+        hwc2_config_t CONFIG_MAX = UINT32_MAX;
+
+        ASSERT_LE(configs.size() - 1, CONFIG_MAX) << "every config value"
+                " (2^32 values) has been taken which shouldn't happen";
+
+        hwc2_config_t config;
+        for (config = 0; config < CONFIG_MAX; config++) {
+            if (std::count(configs.begin(), configs.end(), config) == 0)
+                break;
+        }
+
+        *outConfig = config;
+    }
+
+    /* Calls a set property function from Hwc2Test to set a property value from
+     * Hwc2TestLayer to hwc2_layer_t on hwc2_display_t */
+    using TestLayerPropertyFunction = void (*)(Hwc2Test* test,
+            hwc2_display_t display, hwc2_layer_t layer,
+            Hwc2TestLayer* testLayer, hwc2_error_t* outErr);
+
+    /* Calls a set property function from Hwc2Test to set property values from
+     * Hwc2TestLayers to hwc2_layer_t on hwc2_display_t */
+    using TestLayerPropertiesFunction = void (*)(Hwc2Test* test,
+            hwc2_display_t display, hwc2_layer_t layer,
+            Hwc2TestLayers* testLayers);
+
+    /* Calls a set property function from Hwc2Test to set a bad property value
+     * on hwc2_layer_t on hwc2_display_t */
+    using TestLayerPropertyBadLayerFunction = void (*)(Hwc2Test* test,
+            hwc2_display_t display, hwc2_layer_t layer,
+            Hwc2TestLayer* testLayer, hwc2_error_t* outErr);
+
+    /* Calls a set property function from Hwc2Test to set a bad property value
+     * on hwc2_layer_t on hwc2_display_t */
+    using TestLayerPropertyBadParameterFunction = void (*)(Hwc2Test* test,
+            hwc2_display_t display, hwc2_layer_t layer, hwc2_error_t* outErr);
+
+    /* Is called after a display is powered on and all layer properties have
+     * been set. It should be used to test functions such as validate, accepting
+     * changes, present, etc. */
+    using TestDisplayLayersFunction = void (*)(Hwc2Test* test,
+            hwc2_display_t display, const std::vector<hwc2_layer_t>& layers,
+            Hwc2TestLayers* testLayers);
+
+    /* It is called on an non validated display */
+    using TestDisplayNonValidatedLayersFunction = void (*)(Hwc2Test* test,
+            hwc2_display_t display, std::vector<hwc2_layer_t>* layers);
+
+    /* Tests client target support on a particular display and config */
+    using TestClientTargetSupportFunction = void (*)(Hwc2Test* test,
+            hwc2_display_t display,
+            const Hwc2TestClientTargetSupport& testClientTargetSupport);
+
+    /* Tests a particular active display config */
+    using TestActiveDisplayConfigFunction = void (*)(Hwc2Test* test,
+            hwc2_display_t display);
+
+    /* Tests a newly created virtual display */
+    using TestCreateVirtualDisplayFunction = void (*)(Hwc2Test* test,
+            hwc2_display_t display, Hwc2TestVirtualDisplay* testVirtualDisplay);
+
+    /* Advances a property of Hwc2TestLayer */
+    using AdvanceProperty = bool (*)(Hwc2TestLayer* testLayer);
+
+    /* Advances properties of Hwc2TestLayers */
+    using AdvanceProperties = bool (*)(Hwc2TestLayers* testLayer);
+
+    /* Advances properties of Hwc2TestClientTargetSupport */
+    using AdvanceClientTargetSupport = bool (*)(
+            Hwc2TestClientTargetSupport* testClientTargetSupport);
+
+    /* For each active display it cycles through each display config and tests
+     * each property value. It creates a layer, sets the property and then
+     * destroys the layer */
+    void setLayerProperty(Hwc2TestCoverage coverage,
+            TestLayerPropertyFunction function, AdvanceProperty advance)
+    {
+        for (auto display : mDisplays) {
+            std::vector<hwc2_config_t> configs;
+
+            ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+            for (auto config : configs) {
+                hwc2_layer_t layer;
+                Area displayArea;
+
+                ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+                ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
+                        &displayArea));
+                Hwc2TestLayer testLayer(coverage, displayArea);
+
+                do {
+                    ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
+
+                    ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
+                            &testLayer, nullptr));
+
+                    ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+                } while (advance(&testLayer));
+            }
+        }
+    }
+
+    /* For each active display it cycles through each display config and tests
+     * each property value. It creates a layer, cycles through each property
+     * value and updates the layer property value and then destroys the layer */
+    void setLayerPropertyUpdate(Hwc2TestCoverage coverage,
+            TestLayerPropertyFunction function, AdvanceProperty advance)
+    {
+        for (auto display : mDisplays) {
+            std::vector<hwc2_config_t> configs;
+
+            ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+            for (auto config : configs) {
+                hwc2_layer_t layer;
+                Area displayArea;
+
+                ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+                ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
+                        &displayArea));
+                Hwc2TestLayer testLayer(coverage, displayArea);
+
+                ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
+
+                do {
+                    ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
+                            &testLayer, nullptr));
+                } while (advance(&testLayer));
+
+                ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+            }
+        }
+    }
+
+    /* For each active display it cycles through each display config and tests
+     * each property value. It creates multiple layers, calls the
+     * TestLayerPropertiesFunction to set property values and then
+     * destroys the layers */
+    void setLayerProperties(Hwc2TestCoverage coverage, size_t layerCnt,
+            TestLayerPropertiesFunction function, AdvanceProperties advance)
+    {
+        for (auto display : mDisplays) {
+            std::vector<hwc2_config_t> configs;
+
+            ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+            for (auto config : configs) {
+                std::vector<hwc2_layer_t> layers;
+                Area displayArea;
+
+                ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+                ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
+                        &displayArea));
+
+                ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
+                Hwc2TestLayers testLayers(layers, coverage, displayArea);
+
+                do {
+                    for (auto layer : layers) {
+                        EXPECT_NO_FATAL_FAILURE(function(this, display, layer,
+                                &testLayers));
+                    }
+                } while (advance(&testLayers));
+
+                ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers)));
+            }
+        }
+    }
+
+    /* For each active display it cycles through each display config.
+     * 1) It attempts to set a valid property value to bad layer handle.
+     * 2) It creates a layer x and attempts to set a valid property value to
+     *    layer x + 1
+     * 3) It destroys the layer x and attempts to set a valid property value to
+     *    the destroyed layer x.
+     */
+    void setLayerPropertyBadLayer(Hwc2TestCoverage coverage,
+            TestLayerPropertyBadLayerFunction function)
+    {
+        for (auto display : mDisplays) {
+            std::vector<hwc2_config_t> configs;
+
+            ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+            for (auto config : configs) {
+                hwc2_layer_t layer = 0;
+                Area displayArea;
+                hwc2_error_t err = HWC2_ERROR_NONE;
+
+                ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+                ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
+                        &displayArea));
+                Hwc2TestLayer testLayer(coverage, displayArea);
+
+                ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
+                        &testLayer, &err));
+                EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+
+                ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
+
+                ASSERT_NO_FATAL_FAILURE(function(this, display, layer + 1,
+                        &testLayer, &err));
+                EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+
+                ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+
+                ASSERT_NO_FATAL_FAILURE(function(this, display, layer,
+                        &testLayer, &err));
+                EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+            }
+        }
+    }
+
+    /* For each active display it cycles through each display config and tests
+     * each property value. It creates a layer, sets a bad property value and
+     * then destroys the layer */
+    void setLayerPropertyBadParameter(TestLayerPropertyBadParameterFunction function)
+    {
+        for (auto display : mDisplays) {
+            std::vector<hwc2_config_t> configs;
+
+            ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+            for (auto config : configs) {
+                hwc2_layer_t layer;
+                hwc2_error_t err = HWC2_ERROR_NONE;
+
+                ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+
+                ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
+
+                ASSERT_NO_FATAL_FAILURE(function(this, display, layer, &err));
+                EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong"
+                        " error code";
+
+                ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+            }
+        }
+    }
+
+    /* For each active display it powers on the display, cycles through each
+     * config and creates a set of layers with a certain amount of coverage.
+     * For each active display, for each config and for each set of layers,
+     * it calls the TestDisplayLayersFunction */
+    void displayLayers(Hwc2TestCoverage coverage, size_t layerCnt,
+            TestDisplayLayersFunction function)
+    {
+        for (auto display : mDisplays) {
+            std::vector<hwc2_config_t> configs;
+
+            ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+            ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+            for (auto config : configs) {
+                Area displayArea;
+                std::vector<hwc2_layer_t> layers;
+
+                ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+                ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display, &displayArea));
+
+                ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
+                Hwc2TestLayers testLayers(layers, coverage, displayArea);
+
+                do {
+                    bool skip;
+
+                    ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers,
+                            &testLayers, &skip));
+                    if (!skip)
+                        EXPECT_NO_FATAL_FAILURE(function(this, display, layers,
+                                &testLayers));
+
+                } while (testLayers.advance());
+
+                ASSERT_NO_FATAL_FAILURE(destroyLayers(display,
+                        std::move(layers)));
+            }
+
+            ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+        }
+    }
+
+    /* For each active display, it calls the
+     * TestDisplayNonValidatedLayersFunction on a variety on non-validated
+     * layer combinations */
+    void displayNonValidatedLayers(size_t layerCnt,
+            TestDisplayNonValidatedLayersFunction function)
+    {
+        for (auto display : mDisplays) {
+            uint32_t numTypes, numRequests;
+            std::vector<hwc2_layer_t> layers;
+            bool hasChanges;
+
+            ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+            EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
+
+            ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
+
+            EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
+
+            for (auto layer : layers) {
+                ASSERT_NO_FATAL_FAILURE(setLayerCompositionType(display, layer,
+                        HWC2_COMPOSITION_CLIENT));
+            }
+
+            EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
+
+            ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes,
+                    &numRequests, &hasChanges));
+
+            for (auto layer : layers) {
+                ASSERT_NO_FATAL_FAILURE(setLayerCompositionType(display, layer,
+                        HWC2_COMPOSITION_DEVICE));
+            }
+
+            EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
+
+            ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers)));
+
+            EXPECT_NO_FATAL_FAILURE(function(this, display, &layers));
+
+            ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+        }
+    }
+
+    /* Test client target support on each config on each active display */
+    void setClientTargetSupport(Hwc2TestCoverage coverage,
+            TestClientTargetSupportFunction function,
+            AdvanceClientTargetSupport advance)
+    {
+        for (auto display : mDisplays) {
+            std::vector<hwc2_config_t> configs;
+
+            ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+            for (auto config : configs) {
+                Area displayArea;
+
+                ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+                ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
+                        &displayArea));
+                Hwc2TestClientTargetSupport testClientTargetSupport(coverage,
+                        displayArea);
+
+                do {
+                    EXPECT_NO_FATAL_FAILURE(function(this, display,
+                            testClientTargetSupport));
+
+                } while (advance(&testClientTargetSupport));
+            }
+        }
+    }
+
+    /* Cycles through each config on each active display and calls
+     * a TestActiveDisplayConfigFunction */
+    void setActiveDisplayConfig(TestActiveDisplayConfigFunction function)
+    {
+        for (auto display : mDisplays) {
+            std::vector<hwc2_config_t> configs;
+
+            ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+            for (auto config : configs) {
+                ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+
+                EXPECT_NO_FATAL_FAILURE(function(this, display));
+            }
+        }
+    }
+
+    /* Creates a virtual display for testing */
+    void createVirtualDisplay(Hwc2TestCoverage coverage,
+            TestCreateVirtualDisplayFunction function)
+    {
+        Hwc2TestVirtualDisplay testVirtualDisplay(coverage);
+
+        do {
+            hwc2_display_t display;
+            hwc2_error_t err = HWC2_ERROR_NONE;
+
+            const UnsignedArea& dimension =
+                    testVirtualDisplay.getDisplayDimension();
+            android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+
+            ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(dimension.width,
+                    dimension.height, &desiredFormat, &display, &err));
+
+            EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_NO_RESOURCES
+                    || err == HWC2_ERROR_UNSUPPORTED)
+                    << "returned wrong error code";
+            EXPECT_GE(desiredFormat, 0) << "invalid format";
+
+            if (err != HWC2_ERROR_NONE)
+                continue;
+
+            EXPECT_NO_FATAL_FAILURE(function(this, display,
+                    &testVirtualDisplay));
+
+            ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display));
+
+        } while (testVirtualDisplay.advance());
+    }
+
+
+    void getActiveConfigAttribute(hwc2_display_t display,
+            hwc2_attribute_t attribute, int32_t* outValue)
+    {
+        hwc2_config_t config;
+        ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &config));
+        ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
+                attribute, outValue));
+        ASSERT_GE(*outValue, 0) << "failed to get valid "
+                << getAttributeName(attribute);
+    }
+
+    void getActiveDisplayArea(hwc2_display_t display, Area* displayArea)
+    {
+        ASSERT_NO_FATAL_FAILURE(getActiveConfigAttribute(display,
+                HWC2_ATTRIBUTE_WIDTH, &displayArea->width));
+        ASSERT_NO_FATAL_FAILURE(getActiveConfigAttribute(display,
+                HWC2_ATTRIBUTE_HEIGHT, &displayArea->height));
+    }
+
+    void closeFences(hwc2_display_t display, int32_t presentFence)
+    {
+        std::vector<hwc2_layer_t> layers;
+        std::vector<int32_t> fences;
+        const int msWait = 3000;
+
+        if (presentFence >= 0) {
+            ASSERT_GE(sync_wait(presentFence, msWait), 0);
+            close(presentFence);
+        }
+
+        ASSERT_NO_FATAL_FAILURE(getReleaseFences(display, &layers, &fences));
+        EXPECT_EQ(layers.size(), fences.size());
+
+        for (int32_t fence : fences) {
+            EXPECT_GE(sync_wait(fence, msWait), 0);
+            if (fence >= 0)
+                close(fence);
+        }
+    }
+
+    void setLayerProperties(hwc2_display_t display, hwc2_layer_t layer,
+            Hwc2TestLayers* testLayers, bool* outSkip)
+    {
+        hwc2_composition_t composition;
+        buffer_handle_t handle = nullptr;
+        int32_t acquireFence;
+        hwc2_error_t err = HWC2_ERROR_NONE;
+        *outSkip = true;
+
+        if (!testLayers->contains(layer))
+            return;
+
+        composition = testLayers->getComposition(layer);
+
+        /* If the device cannot support a buffer format, then do not continue */
+        if ((composition == HWC2_COMPOSITION_DEVICE
+                || composition == HWC2_COMPOSITION_CURSOR)
+                && testLayers->getBuffer(layer, &handle, &acquireFence) < 0)
+            return;
+
+        EXPECT_NO_FATAL_FAILURE(setLayerCompositionType(display, layer,
+                composition, &err));
+        if (err == HWC2_ERROR_UNSUPPORTED)
+            EXPECT_TRUE(composition != HWC2_COMPOSITION_CLIENT
+                    && composition != HWC2_COMPOSITION_DEVICE);
+
+        const hwc_rect_t cursor = testLayers->getCursorPosition(layer);
+
+        EXPECT_NO_FATAL_FAILURE(setLayerBuffer(display, layer, handle,
+                acquireFence));
+        EXPECT_NO_FATAL_FAILURE(setLayerBlendMode(display, layer,
+                testLayers->getBlendMode(layer)));
+        EXPECT_NO_FATAL_FAILURE(setLayerColor(display, layer,
+                testLayers->getColor(layer)));
+        EXPECT_NO_FATAL_FAILURE(setCursorPosition(display, layer, cursor.left,
+                cursor.top));
+        EXPECT_NO_FATAL_FAILURE(setLayerDataspace(display, layer,
+                testLayers->getDataspace(layer)));
+        EXPECT_NO_FATAL_FAILURE(setLayerDisplayFrame(display, layer,
+                testLayers->getDisplayFrame(layer)));
+        EXPECT_NO_FATAL_FAILURE(setLayerPlaneAlpha(display, layer,
+                testLayers->getPlaneAlpha(layer)));
+        EXPECT_NO_FATAL_FAILURE(setLayerSourceCrop(display, layer,
+                testLayers->getSourceCrop(layer)));
+        EXPECT_NO_FATAL_FAILURE(setLayerSurfaceDamage(display, layer,
+                testLayers->getSurfaceDamage(layer)));
+        EXPECT_NO_FATAL_FAILURE(setLayerTransform(display, layer,
+                testLayers->getTransform(layer)));
+        EXPECT_NO_FATAL_FAILURE(setLayerVisibleRegion(display, layer,
+                testLayers->getVisibleRegion(layer)));
+        EXPECT_NO_FATAL_FAILURE(setLayerZOrder(display, layer,
+                testLayers->getZOrder(layer)));
+
+        *outSkip = false;
+    }
+
+    void setLayerProperties(hwc2_display_t display,
+            const std::vector<hwc2_layer_t>& layers,
+            Hwc2TestLayers* testLayers, bool* outSkip)
+    {
+        for (auto layer : layers) {
+            EXPECT_NO_FATAL_FAILURE(setLayerProperties(display, layer,
+                    testLayers, outSkip));
+            if (*outSkip)
+                return;
+        }
+    }
+
+    void setClientTarget(hwc2_display_t display,
+            Hwc2TestClientTarget* testClientTarget,
+            const Hwc2TestLayers& testLayers,
+            const std::set<hwc2_layer_t>& clientLayers,
+            const std::set<hwc2_layer_t>& clearLayers, bool flipClientTarget,
+            const Area& displayArea)
+    {
+        android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN;
+        hwc_region_t damage = { };
+        buffer_handle_t handle;
+        int32_t acquireFence;
+
+        ASSERT_EQ(testClientTarget->getBuffer(testLayers, clientLayers,
+                clearLayers, flipClientTarget, displayArea, &handle,
+                &acquireFence), 0);
+        EXPECT_NO_FATAL_FAILURE(setClientTarget(display, handle, acquireFence,
+                dataspace, damage));
+    }
+
+    void presentDisplays(size_t layerCnt, Hwc2TestCoverage coverage,
+            const std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>&
+            coverageExceptions, bool optimize)
+    {
+        for (auto display : mDisplays) {
+            std::vector<hwc2_config_t> configs;
+
+            ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+            ASSERT_NO_FATAL_FAILURE(enableVsync(display));
+
+            ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+            for (auto config : configs) {
+                Area displayArea;
+                std::vector<hwc2_layer_t> layers;
+
+                ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+                ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display,
+                        &displayArea));
+
+                ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
+                Hwc2TestLayers testLayers(layers, coverage, displayArea,
+                        coverageExceptions);
+
+                if (optimize && !testLayers.optimizeLayouts())
+                    continue;
+
+                std::set<hwc2_layer_t> clientLayers;
+                std::set<hwc2_layer_t> clearLayers;
+                Hwc2TestClientTarget testClientTarget;
+
+                do {
+                    uint32_t numTypes, numRequests;
+                    bool hasChanges, skip;
+                    bool flipClientTarget;
+                    int32_t presentFence;
+
+                    ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers,
+                            &testLayers, &skip));
+                    if (skip)
+                        continue;
+
+                    ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes,
+                            &numRequests, &hasChanges));
+                    if (hasChanges)
+                        EXPECT_LE(numTypes, static_cast<uint32_t>(layers.size()))
+                                << "wrong number of requests";
+
+                    ASSERT_NO_FATAL_FAILURE(handleCompositionChanges(display,
+                            testLayers, layers, numTypes, &clientLayers));
+                    ASSERT_NO_FATAL_FAILURE(handleRequests(display, layers,
+                            numRequests, &clearLayers, &flipClientTarget));
+                    ASSERT_NO_FATAL_FAILURE(setClientTarget(display,
+                            &testClientTarget, testLayers, clientLayers,
+                            clearLayers, flipClientTarget, displayArea));
+                    ASSERT_NO_FATAL_FAILURE(acceptDisplayChanges(display));
+
+                    ASSERT_NO_FATAL_FAILURE(waitForVsync());
+
+                    EXPECT_NO_FATAL_FAILURE(presentDisplay(display,
+                            &presentFence));
+
+                    ASSERT_NO_FATAL_FAILURE(closeFences(display, presentFence));
+
+                } while (testLayers.advance());
+
+                ASSERT_NO_FATAL_FAILURE(destroyLayers(display,
+                        std::move(layers)));
+            }
+
+            ASSERT_NO_FATAL_FAILURE(disableVsync(display));
+            ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+        }
+    }
+
+    hwc2_device_t* mHwc2Device = nullptr;
+
+    enum class Hwc2TestHotplugStatus {
+        Init = 1,
+        Receiving,
+        Done,
+    };
+
+    std::mutex mHotplugMutex;
+    std::condition_variable mHotplugCv;
+    Hwc2TestHotplugStatus mHotplugStatus = Hwc2TestHotplugStatus::Init;
+    std::unordered_set<hwc2_display_t> mDisplays;
+
+    /* Store all created layers that have not been destroyed. If an ASSERT_*
+     * fails, then destroy the layers on exit */
+    std::set<std::pair<hwc2_display_t, hwc2_layer_t>> mLayers;
+
+    /* Store the power mode state. If it is not HWC2_POWER_MODE_OFF when
+     * tearing down the test cases, change it to HWC2_POWER_MODE_OFF */
+    std::set<hwc2_display_t> mActiveDisplays;
+
+    /* Store all created virtual displays that have not been destroyed. If an
+     * ASSERT_* fails, then destroy the virtual displays on exit */
+    std::set<hwc2_display_t> mVirtualDisplays;
+
+    std::mutex mVsyncMutex;
+    std::condition_variable mVsyncCv;
+    hwc2_display_t mVsyncDisplay;
+    int64_t mVsyncTimestamp = -1;
+};
+
+void hwc2TestHotplugCallback(hwc2_callback_data_t callbackData,
+        hwc2_display_t display, int32_t connection)
+{
+    if (callbackData)
+        static_cast<Hwc2Test*>(callbackData)->hotplugCallback(display,
+                connection);
+}
+
+void hwc2TestVsyncCallback(hwc2_callback_data_t callbackData,
+        hwc2_display_t display, int64_t timestamp)
+{
+    if (callbackData)
+        static_cast<Hwc2Test*>(callbackData)->vsyncCallback(display,
+                timestamp);
+}
+
+void setBlendMode(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+    EXPECT_NO_FATAL_FAILURE(test->setLayerBlendMode(display, layer,
+            testLayer->getBlendMode(), outErr));
+}
+
+void setBuffer(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+    buffer_handle_t handle;
+    android::base::unique_fd acquireFence;
+    hwc2_composition_t composition = testLayer->getComposition();
+
+    if (composition == HWC2_COMPOSITION_CLIENT
+            || composition == HWC2_COMPOSITION_SOLID_COLOR
+            || composition == HWC2_COMPOSITION_SIDEBAND)
+        return;
+
+    if (testLayer->getBuffer(&handle, &acquireFence) < 0)
+        return;
+
+    ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, layer,
+            composition));
+    EXPECT_NO_FATAL_FAILURE(test->setLayerBuffer(display, layer,
+            handle, acquireFence, outErr));
+}
+
+void setColor(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+    ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display,
+            layer, HWC2_COMPOSITION_SOLID_COLOR));
+    ASSERT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display,
+            layer, testLayer->getPlaneAlpha()));
+    ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display,
+            layer, testLayer->getBlendMode()));
+    EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, layer,
+            testLayer->getColor(), outErr));
+}
+
+void setComposition(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+    hwc2_composition_t composition = testLayer->getComposition();
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display, layer,
+            composition, &err));
+    if (outErr) {
+        *outErr = err;
+        return;
+    }
+
+    if (composition != HWC2_COMPOSITION_SIDEBAND) {
+        EXPECT_EQ(err, HWC2_ERROR_NONE) << "returned wrong error code";
+    } else {
+        EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_UNSUPPORTED)
+                 << "returned wrong error code";
+    }
+}
+
+void setCursorPosition(Hwc2Test* test, hwc2_display_t display,
+        hwc2_layer_t layer, Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+    ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display,
+            layer, HWC2_COMPOSITION_CURSOR));
+
+    const hwc_rect_t cursorPosition = testLayer->getCursorPosition();
+    EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display, layer,
+            cursorPosition.left, cursorPosition.top, outErr));
+}
+
+void setDataspace(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+    EXPECT_NO_FATAL_FAILURE(test->setLayerDataspace(display, layer,
+            testLayer->getDataspace(), outErr));
+}
+
+void setDisplayFrame(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+    EXPECT_NO_FATAL_FAILURE(test->setLayerDisplayFrame(display, layer,
+            testLayer->getDisplayFrame(), outErr));
+}
+
+void setPlaneAlpha(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+        Hwc2TestLayer* testLayer, hwc2_error_t *outErr)
+{
+    ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display, layer,
+            testLayer->getBlendMode()));
+    EXPECT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display, layer,
+            testLayer->getPlaneAlpha(), outErr));
+}
+
+void setSourceCrop(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+    EXPECT_NO_FATAL_FAILURE(test->setLayerSourceCrop(display, layer,
+            testLayer->getSourceCrop(), outErr));
+}
+
+void setSurfaceDamage(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+    EXPECT_NO_FATAL_FAILURE(test->setLayerSurfaceDamage(display, layer,
+            testLayer->getSurfaceDamage(), outErr));
+}
+
+void setTransform(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+    EXPECT_NO_FATAL_FAILURE(test->setLayerTransform(display, layer,
+            testLayer->getTransform(), outErr));
+}
+
+void setVisibleRegion(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+    EXPECT_NO_FATAL_FAILURE(test->setLayerVisibleRegion(display, layer,
+            testLayer->getVisibleRegion(), outErr));
+}
+
+void setZOrder(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+        Hwc2TestLayer* testLayer, hwc2_error_t* outErr)
+{
+    EXPECT_NO_FATAL_FAILURE(test->setLayerZOrder(display, layer,
+            testLayer->getZOrder(), outErr));
+}
+
+bool advanceBlendMode(Hwc2TestLayer* testLayer)
+{
+    return testLayer->advanceBlendMode();
+}
+
+bool advanceBuffer(Hwc2TestLayer* testLayer)
+{
+    if (testLayer->advanceComposition())
+        return true;
+    return testLayer->advanceBufferArea();
+}
+
+bool advanceColor(Hwc2TestLayer* testLayer)
+{
+    /* Color depends on blend mode so advance blend mode last so color is not
+     * force to update as often */
+    if (testLayer->advancePlaneAlpha())
+        return true;
+    if (testLayer->advanceColor())
+        return true;
+    return testLayer->advanceBlendMode();
+}
+
+bool advanceComposition(Hwc2TestLayer* testLayer)
+{
+    return testLayer->advanceComposition();
+}
+
+bool advanceCursorPosition(Hwc2TestLayer* testLayer)
+{
+    return testLayer->advanceCursorPosition();
+}
+
+bool advanceDataspace(Hwc2TestLayer* testLayer)
+{
+    return testLayer->advanceDataspace();
+}
+
+bool advanceDisplayFrame(Hwc2TestLayer* testLayer)
+{
+    return testLayer->advanceDisplayFrame();
+}
+
+bool advancePlaneAlpha(Hwc2TestLayer* testLayer)
+{
+    return testLayer->advancePlaneAlpha();
+}
+
+bool advanceSourceCrop(Hwc2TestLayer* testLayer)
+{
+    if (testLayer->advanceSourceCrop())
+        return true;
+    return testLayer->advanceBufferArea();
+}
+
+bool advanceSurfaceDamage(Hwc2TestLayer* testLayer)
+{
+    if (testLayer->advanceSurfaceDamage())
+        return true;
+    return testLayer->advanceBufferArea();
+}
+
+bool advanceTransform(Hwc2TestLayer* testLayer)
+{
+    return testLayer->advanceTransform();
+}
+
+bool advanceVisibleRegions(Hwc2TestLayers* testLayers)
+{
+    return testLayers->advanceVisibleRegions();
+}
+
+bool advanceClientTargetSupport(
+        Hwc2TestClientTargetSupport* testClientTargetSupport)
+{
+    return testClientTargetSupport->advance();
+}
+
+static const std::array<hwc2_function_descriptor_t, 42> requiredFunctions = {{
+    HWC2_FUNCTION_ACCEPT_DISPLAY_CHANGES,
+    HWC2_FUNCTION_CREATE_LAYER,
+    HWC2_FUNCTION_CREATE_VIRTUAL_DISPLAY,
+    HWC2_FUNCTION_DESTROY_LAYER,
+    HWC2_FUNCTION_DESTROY_VIRTUAL_DISPLAY,
+    HWC2_FUNCTION_DUMP,
+    HWC2_FUNCTION_GET_ACTIVE_CONFIG,
+    HWC2_FUNCTION_GET_CHANGED_COMPOSITION_TYPES,
+    HWC2_FUNCTION_GET_CLIENT_TARGET_SUPPORT,
+    HWC2_FUNCTION_GET_COLOR_MODES,
+    HWC2_FUNCTION_GET_DISPLAY_ATTRIBUTE,
+    HWC2_FUNCTION_GET_DISPLAY_CONFIGS,
+    HWC2_FUNCTION_GET_DISPLAY_NAME,
+    HWC2_FUNCTION_GET_DISPLAY_REQUESTS,
+    HWC2_FUNCTION_GET_DISPLAY_TYPE,
+    HWC2_FUNCTION_GET_DOZE_SUPPORT,
+    HWC2_FUNCTION_GET_HDR_CAPABILITIES,
+    HWC2_FUNCTION_GET_MAX_VIRTUAL_DISPLAY_COUNT,
+    HWC2_FUNCTION_GET_RELEASE_FENCES,
+    HWC2_FUNCTION_PRESENT_DISPLAY,
+    HWC2_FUNCTION_REGISTER_CALLBACK,
+    HWC2_FUNCTION_SET_ACTIVE_CONFIG,
+    HWC2_FUNCTION_SET_CLIENT_TARGET,
+    HWC2_FUNCTION_SET_COLOR_MODE,
+    HWC2_FUNCTION_SET_COLOR_TRANSFORM,
+    HWC2_FUNCTION_SET_CURSOR_POSITION,
+    HWC2_FUNCTION_SET_LAYER_BLEND_MODE,
+    HWC2_FUNCTION_SET_LAYER_BUFFER,
+    HWC2_FUNCTION_SET_LAYER_COLOR,
+    HWC2_FUNCTION_SET_LAYER_COMPOSITION_TYPE,
+    HWC2_FUNCTION_SET_LAYER_DATASPACE,
+    HWC2_FUNCTION_SET_LAYER_DISPLAY_FRAME,
+    HWC2_FUNCTION_SET_LAYER_PLANE_ALPHA,
+    HWC2_FUNCTION_SET_LAYER_SOURCE_CROP,
+    HWC2_FUNCTION_SET_LAYER_SURFACE_DAMAGE,
+    HWC2_FUNCTION_SET_LAYER_TRANSFORM,
+    HWC2_FUNCTION_SET_LAYER_VISIBLE_REGION,
+    HWC2_FUNCTION_SET_LAYER_Z_ORDER,
+    HWC2_FUNCTION_SET_OUTPUT_BUFFER,
+    HWC2_FUNCTION_SET_POWER_MODE,
+    HWC2_FUNCTION_SET_VSYNC_ENABLED,
+    HWC2_FUNCTION_VALIDATE_DISPLAY,
+}};
+
+/* TESTCASE: Tests that the HWC2 supports all required functions. */
+TEST_F(Hwc2Test, GET_FUNCTION)
+{
+    for (hwc2_function_descriptor_t descriptor : requiredFunctions) {
+        hwc2_function_pointer_t pfn = getFunction(descriptor);
+        EXPECT_TRUE(pfn) << "failed to get function "
+                << getFunctionDescriptorName(descriptor);
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 fails to retrieve and invalid function. */
+TEST_F(Hwc2Test, GET_FUNCTION_invalid_function)
+{
+    hwc2_function_pointer_t pfn = getFunction(HWC2_FUNCTION_INVALID);
+    EXPECT_FALSE(pfn) << "failed to get invalid function";
+}
+
+/* TESTCASE: Tests that the HWC2 does not return an invalid capability. */
+TEST_F(Hwc2Test, GET_CAPABILITIES)
+{
+    std::vector<hwc2_capability_t> capabilities;
+
+    getCapabilities(&capabilities);
+
+    EXPECT_EQ(std::count(capabilities.begin(), capabilities.end(),
+            HWC2_CAPABILITY_INVALID), 0);
+}
+
+static const std::array<hwc2_callback_descriptor_t, 3> callbackDescriptors = {{
+    HWC2_CALLBACK_HOTPLUG,
+    HWC2_CALLBACK_REFRESH,
+    HWC2_CALLBACK_VSYNC,
+}};
+
+/* TESTCASE: Tests that the HWC2 can successfully register all required
+ * callback functions. */
+TEST_F(Hwc2Test, REGISTER_CALLBACK)
+{
+    hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
+            const_cast<char*>("data"));
+
+    for (auto descriptor : callbackDescriptors) {
+        ASSERT_NO_FATAL_FAILURE(registerCallback(descriptor, data,
+                []() { return; }));
+    }
+}
+
+/* TESTCASE: Test that the HWC2 fails to register invalid callbacks. */
+TEST_F(Hwc2Test, REGISTER_CALLBACK_bad_parameter)
+{
+    hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
+            const_cast<char*>("data"));
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_INVALID, data,
+            []() { return; }, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 can register a callback with null data. */
+TEST_F(Hwc2Test, REGISTER_CALLBACK_null_data)
+{
+    hwc2_callback_data_t data = nullptr;
+
+    for (auto descriptor : callbackDescriptors) {
+        ASSERT_NO_FATAL_FAILURE(registerCallback(descriptor, data,
+                []() { return; }));
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 returns the correct display type for each
+ * physical display. */
+TEST_F(Hwc2Test, GET_DISPLAY_TYPE)
+{
+    for (auto display : mDisplays) {
+        hwc2_display_type_t type;
+
+        ASSERT_NO_FATAL_FAILURE(getDisplayType(display, &type));
+        EXPECT_EQ(type, HWC2_DISPLAY_TYPE_PHYSICAL) << "failed to return"
+                " correct display type";
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 returns an error when the display type of a bad
+ * display is requested. */
+TEST_F(Hwc2Test, GET_DISPLAY_TYPE_bad_display)
+{
+    hwc2_display_t display;
+    hwc2_display_type_t type;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(getDisplayType(display, &type, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 can create and destroy layers. */
+TEST_F(Hwc2Test, CREATE_DESTROY_LAYER)
+{
+    for (auto display : mDisplays) {
+        hwc2_layer_t layer;
+
+        ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
+
+        ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot create a layer for a bad display */
+TEST_F(Hwc2Test, CREATE_LAYER_bad_display)
+{
+    hwc2_display_t display;
+    hwc2_layer_t layer;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 will either support a large number of resources
+ * or will return no resources. */
+TEST_F(Hwc2Test, CREATE_LAYER_no_resources)
+{
+    const size_t layerCnt = 1000;
+
+    for (auto display : mDisplays) {
+        std::vector<hwc2_layer_t> layers;
+
+        ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
+
+        ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers)));
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot destroy a layer for a bad display */
+TEST_F(Hwc2Test, DESTROY_LAYER_bad_display)
+{
+    hwc2_display_t badDisplay;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&badDisplay));
+
+    for (auto display : mDisplays) {
+        hwc2_layer_t layer = 0;
+        hwc2_error_t err = HWC2_ERROR_NONE;
+
+        ASSERT_NO_FATAL_FAILURE(destroyLayer(badDisplay, layer, &err));
+        EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+
+        ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
+
+        ASSERT_NO_FATAL_FAILURE(destroyLayer(badDisplay, layer, &err));
+        EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+
+        ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot destory a bad layer */
+TEST_F(Hwc2Test, DESTROY_LAYER_bad_layer)
+{
+    for (auto display : mDisplays) {
+        hwc2_layer_t layer;
+        hwc2_error_t err = HWC2_ERROR_NONE;
+
+        ASSERT_NO_FATAL_FAILURE(destroyLayer(display, UINT64_MAX / 2, &err));
+        EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+
+        ASSERT_NO_FATAL_FAILURE(destroyLayer(display, 0, &err));
+        EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+
+        ASSERT_NO_FATAL_FAILURE(destroyLayer(display, UINT64_MAX - 1, &err));
+        EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+
+        ASSERT_NO_FATAL_FAILURE(destroyLayer(display, 1, &err));
+        EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+
+        ASSERT_NO_FATAL_FAILURE(destroyLayer(display, UINT64_MAX, &err));
+        EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+
+        ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
+
+        ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer + 1, &err));
+        EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+
+        ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+
+        ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer, &err));
+        EXPECT_EQ(err, HWC2_ERROR_BAD_LAYER) << "returned wrong error code";
+    }
+}
+
+static const std::array<hwc2_attribute_t, 2> requiredAttributes = {{
+    HWC2_ATTRIBUTE_WIDTH,
+    HWC2_ATTRIBUTE_HEIGHT,
+}};
+
+static const std::array<hwc2_attribute_t, 3> optionalAttributes = {{
+    HWC2_ATTRIBUTE_VSYNC_PERIOD,
+    HWC2_ATTRIBUTE_DPI_X,
+    HWC2_ATTRIBUTE_DPI_Y,
+}};
+
+/* TESTCASE: Tests that the HWC2 can return display attributes for a valid
+ * config. */
+TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE)
+{
+    for (auto display : mDisplays) {
+        std::vector<hwc2_config_t> configs;
+
+        ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+        for (auto config : configs) {
+            int32_t value;
+
+            for (auto attribute : requiredAttributes) {
+                ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
+                        attribute, &value));
+                EXPECT_GE(value, 0) << "missing required attribute "
+                        << getAttributeName(attribute) << " for config "
+                        << config;
+            }
+            for (auto attribute : optionalAttributes) {
+                ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
+                        attribute, &value));
+            }
+        }
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 will return a value of -1 for an invalid
+ * attribute */
+TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE_invalid_attribute)
+{
+    const hwc2_attribute_t attribute = HWC2_ATTRIBUTE_INVALID;
+
+    for (auto display : mDisplays) {
+        std::vector<hwc2_config_t> configs;
+
+        ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+        for (auto config : configs) {
+            int32_t value;
+            hwc2_error_t err = HWC2_ERROR_NONE;
+
+            ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
+                    attribute, &value, &err));
+            EXPECT_EQ(value, -1) << "failed to return -1 for an invalid"
+                    " attribute for config " << config;
+        }
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 will fail to get attributes for a bad display */
+TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE_bad_display)
+{
+    hwc2_display_t display;
+    const hwc2_config_t config = 0;
+    int32_t value;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    for (auto attribute : requiredAttributes) {
+        ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config, attribute,
+                &value, &err));
+        EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+    }
+
+    for (auto attribute : optionalAttributes) {
+        ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config, attribute,
+                &value, &err));
+        EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 will fail to get attributes for a bad config */
+TEST_F(Hwc2Test, GET_DISPLAY_ATTRIBUTE_bad_config)
+{
+    for (auto display : mDisplays) {
+        hwc2_config_t config;
+        int32_t value;
+        hwc2_error_t err = HWC2_ERROR_NONE;
+
+        ASSERT_NO_FATAL_FAILURE(getInvalidConfig(display, &config));
+
+        for (auto attribute : requiredAttributes) {
+            ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
+                    attribute, &value, &err));
+            EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code";
+        }
+
+        for (auto attribute : optionalAttributes) {
+            ASSERT_NO_FATAL_FAILURE(getDisplayAttribute(display, config,
+                    attribute, &value, &err));
+            EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code";
+        }
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 will get display configs for active displays */
+TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS)
+{
+    for (auto display : mDisplays) {
+        std::vector<hwc2_config_t> configs;
+
+        ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 will not get display configs for bad displays */
+TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS_bad_display)
+{
+    hwc2_display_t display;
+    std::vector<hwc2_config_t> configs;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs, &err));
+
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+    EXPECT_TRUE(configs.empty()) << "returned configs for bad display";
+}
+
+/* TESTCASE: Tests that the HWC2 will return the same config list multiple
+ * times in a row. */
+TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS_same)
+{
+    for (auto display : mDisplays) {
+        std::vector<hwc2_config_t> configs1, configs2;
+
+        ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs1));
+        ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs2));
+
+        EXPECT_TRUE(std::is_permutation(configs1.begin(), configs1.end(),
+                configs2.begin())) << "returned two different config sets";
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 does not return duplicate display configs */
+TEST_F(Hwc2Test, GET_DISPLAY_CONFIGS_duplicate)
+{
+    for (auto display : mDisplays) {
+        std::vector<hwc2_config_t> configs;
+
+        ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+        std::unordered_set<hwc2_config_t> configsSet(configs.begin(),
+                configs.end());
+        EXPECT_EQ(configs.size(), configsSet.size()) << "returned duplicate"
+                " configs";
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 returns the active config for a display */
+TEST_F(Hwc2Test, GET_ACTIVE_CONFIG)
+{
+    for (auto display : mDisplays) {
+        std::vector<hwc2_config_t> configs;
+
+        ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+        for (auto config : configs) {
+            hwc2_config_t activeConfig;
+
+            ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+            ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &activeConfig));
+
+            EXPECT_EQ(activeConfig, config) << "failed to get active config";
+        }
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 does not return an active config for a bad
+ * display. */
+TEST_F(Hwc2Test, GET_ACTIVE_CONFIG_bad_display)
+{
+    hwc2_display_t display;
+    hwc2_config_t activeConfig;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &activeConfig, &err));
+
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 either begins with a valid active config
+ * or returns an error when getActiveConfig is called. */
+TEST_F(Hwc2Test, GET_ACTIVE_CONFIG_bad_config)
+{
+    for (auto display : mDisplays) {
+        std::vector<hwc2_config_t> configs;
+        hwc2_config_t activeConfig;
+        hwc2_error_t err = HWC2_ERROR_NONE;
+
+        ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+        if (configs.empty())
+            return;
+
+        ASSERT_NO_FATAL_FAILURE(getActiveConfig(display, &activeConfig, &err));
+        if (err == HWC2_ERROR_NONE) {
+            EXPECT_NE(std::count(configs.begin(), configs.end(),
+                    activeConfig), 0) << "active config is not found in "
+                    " configs for display";
+        } else {
+            EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code";
+        }
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 can set every display config as an active
+ * config */
+TEST_F(Hwc2Test, SET_ACTIVE_CONFIG)
+{
+    for (auto display : mDisplays) {
+        std::vector<hwc2_config_t> configs;
+
+        ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+        for (auto config : configs) {
+            EXPECT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+        }
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an active config for a bad display */
+TEST_F(Hwc2Test, SET_ACTIVE_CONFIG_bad_display)
+{
+    hwc2_display_t display;
+    const hwc2_config_t config = 0;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an invalid active config */
+TEST_F(Hwc2Test, SET_ACTIVE_CONFIG_bad_config)
+{
+    for (auto display : mDisplays) {
+        hwc2_config_t config;
+        hwc2_error_t err = HWC2_ERROR_NONE;
+
+        ASSERT_NO_FATAL_FAILURE(getInvalidConfig(display, &config));
+
+        ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config, &err));
+        EXPECT_EQ(err, HWC2_ERROR_BAD_CONFIG) << "returned wrong error code";
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 returns a valid value for getDozeSupport. */
+TEST_F(Hwc2Test, GET_DOZE_SUPPORT)
+{
+    for (auto display : mDisplays) {
+        int32_t support = -1;
+
+        ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support));
+
+        EXPECT_TRUE(support == 0 || support == 1) << "invalid doze support value";
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get doze support for a bad display. */
+TEST_F(Hwc2Test, GET_DOZE_SUPPORT_bad_display)
+{
+    hwc2_display_t display;
+    int32_t support = -1;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support, &err));
+
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 can set all supported power modes */
+TEST_F(Hwc2Test, SET_POWER_MODE)
+{
+    for (auto display : mDisplays) {
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+
+        int32_t support = -1;
+        ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support));
+        if (support != 1)
+            return;
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE));
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display,
+                HWC2_POWER_MODE_DOZE_SUSPEND));
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set a power mode for a bad display. */
+TEST_F(Hwc2Test, SET_POWER_MODE_bad_display)
+{
+    hwc2_display_t display;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+
+    ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+
+    int32_t support = -1;
+    ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support, &err));
+    if (support != 1)
+        return;
+
+    ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+
+    ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE_SUSPEND,
+            &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an invalid power mode value. */
+TEST_F(Hwc2Test, SET_POWER_MODE_bad_parameter)
+{
+    for (auto display : mDisplays) {
+        hwc2_power_mode_t mode = static_cast<hwc2_power_mode_t>(
+                HWC2_POWER_MODE_DOZE_SUSPEND + 1);
+        hwc2_error_t err = HWC2_ERROR_NONE;
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, mode, &err));
+        EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code "
+                << mode;
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 will return unsupported if it does not support
+ * an optional power mode. */
+TEST_F(Hwc2Test, SET_POWER_MODE_unsupported)
+{
+    for (auto display : mDisplays) {
+        int32_t support = -1;
+        hwc2_error_t err = HWC2_ERROR_NONE;
+
+        ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support, &err));
+        if (support == 1)
+            return;
+
+        ASSERT_EQ(support, 0) << "invalid doze support value";
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE,
+                &err));
+        EXPECT_EQ(err, HWC2_ERROR_UNSUPPORTED) << "returned wrong error code";
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display,
+                HWC2_POWER_MODE_DOZE_SUSPEND, &err));
+        EXPECT_EQ(err, HWC2_ERROR_UNSUPPORTED) <<  "returned wrong error code";
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 can set the same power mode multiple times. */
+TEST_F(Hwc2Test, SET_POWER_MODE_stress)
+{
+    for (auto display : mDisplays) {
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+
+        int32_t support = -1;
+        ASSERT_NO_FATAL_FAILURE(getDozeSupport(display, &support));
+        if (support != 1)
+            return;
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE));
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_DOZE));
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display,
+                HWC2_POWER_MODE_DOZE_SUSPEND));
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display,
+                HWC2_POWER_MODE_DOZE_SUSPEND));
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 can enable and disable vsync on active
+ * displays */
+TEST_F(Hwc2Test, SET_VSYNC_ENABLED)
+{
+    for (auto display : mDisplays) {
+        hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
+                const_cast<char*>("data"));
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+        ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data,
+                []() { return; }));
+
+        ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
+
+        ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 issues a valid vsync callback. */
+TEST_F(Hwc2Test, SET_VSYNC_ENABLED_callback)
+{
+    for (auto display : mDisplays) {
+        hwc2_display_t receivedDisplay;
+        int64_t receivedTimestamp;
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+        ASSERT_NO_FATAL_FAILURE(enableVsync(display));
+
+        ASSERT_NO_FATAL_FAILURE(waitForVsync(&receivedDisplay,
+                &receivedTimestamp));
+
+        EXPECT_EQ(receivedDisplay, display) << "failed to get correct display";
+        EXPECT_GE(receivedTimestamp, 0) << "failed to get valid timestamp";
+
+        ASSERT_NO_FATAL_FAILURE(disableVsync(display));
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot enable a vsync for a bad display */
+TEST_F(Hwc2Test, SET_VSYNC_ENABLED_bad_display)
+{
+    hwc2_display_t display;
+    hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
+            const_cast<char*>("data"));
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data,
+            []() { return; }));
+
+    ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+
+    ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot enable an invalid vsync value */
+TEST_F(Hwc2Test, SET_VSYNC_ENABLED_bad_parameter)
+{
+    for (auto display : mDisplays) {
+        hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
+                const_cast<char*>("data"));
+        hwc2_error_t err = HWC2_ERROR_NONE;
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+        ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data,
+                []() { return; }));
+
+        ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_INVALID,
+                &err));
+        EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code";
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 can enable and disable a vsync value multiple
+ * times. */
+TEST_F(Hwc2Test, SET_VSYNC_ENABLED_stress)
+{
+    for (auto display : mDisplays) {
+        hwc2_callback_data_t data = reinterpret_cast<hwc2_callback_data_t>(
+                const_cast<char*>("data"));
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+        ASSERT_NO_FATAL_FAILURE(registerCallback(HWC2_CALLBACK_VSYNC, data,
+                []() { return; }));
+
+        ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
+
+        ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
+        ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
+
+        ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
+        ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 can set a vsync enable value when the display
+ * is off and no callback is registered. */
+TEST_F(Hwc2Test, SET_VSYNC_ENABLED_no_callback_no_power)
+{
+    const uint secs = 1;
+
+    for (auto display : mDisplays) {
+        ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
+
+        sleep(secs);
+
+        ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 can set a vsync enable value when no callback
+ * is registered. */
+TEST_F(Hwc2Test, SET_VSYNC_ENABLED_no_callback)
+{
+    const uint secs = 1;
+
+    for (auto display : mDisplays) {
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+        ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_ENABLE));
+
+        sleep(secs);
+
+        ASSERT_NO_FATAL_FAILURE(setVsyncEnabled(display, HWC2_VSYNC_DISABLE));
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 returns a display name for each display */
+TEST_F(Hwc2Test, GET_DISPLAY_NAME)
+{
+    for (auto display : mDisplays) {
+        std::string name;
+
+        ASSERT_NO_FATAL_FAILURE(getDisplayName(display, &name));
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 does not return a display name for a bad
+ * display */
+TEST_F(Hwc2Test, GET_DISPLAY_NAME_bad_display)
+{
+    hwc2_display_t display;
+    std::string name;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(getDisplayName(display, &name, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 can set basic composition types. */
+TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+            setComposition, advanceComposition));
+}
+
+/* TESTCASE: Tests that the HWC2 can update a basic composition type on a
+ * layer. */
+TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_update)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+            setComposition, advanceComposition));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set a composition type for a bad layer */
+TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_bad_layer)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+            setComposition));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set a bad composition type */
+TEST_F(Hwc2Test, SET_LAYER_COMPOSITION_TYPE_bad_parameter)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadParameter(
+            [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+                    hwc2_error_t* outErr) {
+
+                ASSERT_NO_FATAL_FAILURE(test->setLayerCompositionType(display,
+                        layer, HWC2_COMPOSITION_INVALID, outErr));
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the cursor position of a layer. */
+TEST_F(Hwc2Test, SET_CURSOR_POSITION)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+            ::setCursorPosition, advanceCursorPosition));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the cursor position of a layer. */
+TEST_F(Hwc2Test, SET_CURSOR_POSITION_update)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+            ::setCursorPosition, advanceCursorPosition));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the cursor position of a layer when the
+ * composition type has not been set to HWC2_COMPOSITION_CURSOR. */
+TEST_F(Hwc2Test, SET_CURSOR_POSITION_composition_type_unset)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+            [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+                    Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
+
+                const hwc_rect_t cursorPosition = testLayer->getCursorPosition();
+                EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display, layer,
+                        cursorPosition.left, cursorPosition.top, outErr));
+            },
+
+            advanceCursorPosition));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the cursor position of a bad
+ * display. */
+TEST_F(Hwc2Test, SET_CURSOR_POSITION_bad_display)
+{
+    hwc2_display_t display;
+    hwc2_layer_t layer = 0;
+    int32_t x = 0, y = 0;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(setCursorPosition(display, layer, x, y, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the cursor position of a bad layer. */
+TEST_F(Hwc2Test, SET_CURSOR_POSITION_bad_layer)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+            [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
+                    Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
+
+                const hwc_rect_t cursorPosition = testLayer->getCursorPosition();
+                EXPECT_NO_FATAL_FAILURE(test->setCursorPosition(display,
+                        badLayer, cursorPosition.left, cursorPosition.top,
+                        outErr));
+            }
+   ));
+}
+
+/* TESTCASE: Tests that the HWC2 can set a blend mode value of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+            setBlendMode, advanceBlendMode));
+}
+
+/* TESTCASE: Tests that the HWC2 can update a blend mode value of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_update)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+            setBlendMode, advanceBlendMode));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set a blend mode for a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_bad_layer)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+            setBlendMode));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an invalid blend mode. */
+TEST_F(Hwc2Test, SET_LAYER_BLEND_MODE_bad_parameter)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadParameter(
+            [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+                    hwc2_error_t* outErr) {
+
+                ASSERT_NO_FATAL_FAILURE(test->setLayerBlendMode(display,
+                        layer, HWC2_BLEND_MODE_INVALID, outErr));
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the buffer of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_BUFFER)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+            setBuffer, advanceBuffer));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the buffer of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_BUFFER_update)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+            setBuffer, advanceBuffer));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the buffer of a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_BUFFER_bad_layer)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+            [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
+                    Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
+
+                buffer_handle_t handle = nullptr;
+                android::base::unique_fd acquireFence;
+
+                /* If there is not available buffer for the given buffer
+                 * properties, it should not fail this test case */
+                if (testLayer->getBuffer(&handle, &acquireFence) == 0) {
+                    *outErr = HWC2_ERROR_BAD_LAYER;
+                    return;
+                }
+
+                ASSERT_NO_FATAL_FAILURE(test->setLayerBuffer(display, badLayer,
+                        handle, acquireFence, outErr));
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 can set an invalid buffer for a layer. */
+TEST_F(Hwc2Test, SET_LAYER_BUFFER_bad_parameter)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadParameter(
+            [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+                    hwc2_error_t* outErr) {
+
+                buffer_handle_t handle = nullptr;
+                int32_t acquireFence = -1;
+
+                ASSERT_NO_FATAL_FAILURE(test->setLayerBuffer(display, layer,
+                        handle, acquireFence, outErr));
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the color of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_COLOR)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+            setColor, advanceColor));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the color of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_COLOR_update)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+            setColor, advanceColor));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the color of a layer when the
+ * composition type has not been set to HWC2_COMPOSITION_SOLID_COLOR. */
+TEST_F(Hwc2Test, SET_LAYER_COLOR_composition_type_unset)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Basic,
+            [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+                    Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
+
+                EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, layer,
+                        testLayer->getColor(), outErr));
+            },
+
+            advanceColor));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the color of a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_COLOR_bad_layer)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+            [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
+                    Hwc2TestLayer* testLayer, hwc2_error_t* outErr) {
+
+                EXPECT_NO_FATAL_FAILURE(test->setLayerColor(display, badLayer,
+                        testLayer->getColor(), outErr));
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the dataspace of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_DATASPACE)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+            setDataspace, advanceDataspace));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the dataspace of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_DATASPACE_update)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+            setDataspace, advanceDataspace));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set a dataspace for a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_DATASPACE_bad_layer)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+            setDataspace));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the display frame of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_DISPLAY_FRAME)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+            setDisplayFrame, advanceDisplayFrame));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the display frame of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_DISPLAY_FRAME_update)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+            setDisplayFrame, advanceDisplayFrame));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the display frame of a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_DISPLAY_FRAME_bad_layer)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+            setDisplayFrame));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the plane alpha of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+            setPlaneAlpha, advancePlaneAlpha));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the plane alpha of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA_update)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+            setPlaneAlpha, advancePlaneAlpha));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set a plane alpha for a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_PLANE_ALPHA_bad_layer)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+            [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t badLayer,
+                    Hwc2TestLayer* testLayer, hwc2_error_t *outErr) {
+
+                    EXPECT_NO_FATAL_FAILURE(test->setLayerPlaneAlpha(display,
+                            badLayer, testLayer->getPlaneAlpha(), outErr));
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the source crop of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_SOURCE_CROP)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+            setSourceCrop, advanceSourceCrop));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the source crop of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_SOURCE_CROP_update)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+            setSourceCrop, advanceSourceCrop));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the source crop of a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_SOURCE_CROP_bad_layer)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+            setSourceCrop));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the surface damage of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_SURFACE_DAMAGE)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+            setSurfaceDamage, advanceSurfaceDamage));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the surface damage of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_SURFACE_DAMAGE_update)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+            setSurfaceDamage, advanceSurfaceDamage));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the surface damage of a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_SURFACE_DAMAGE_bad_layer)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+            setSurfaceDamage));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the transform value of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_TRANSFORM)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerProperty(Hwc2TestCoverage::Complete,
+            setTransform, advanceTransform));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the transform value of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_TRANSFORM_update)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyUpdate(Hwc2TestCoverage::Complete,
+            setTransform, advanceTransform));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the transform for a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_TRANSFORM_bad_layer)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+            setTransform));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the visible region of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_VISIBLE_REGION)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerProperties(Hwc2TestCoverage::Basic, 5,
+            [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+                    Hwc2TestLayers* testLayers) {
+
+                EXPECT_NO_FATAL_FAILURE(test->setLayerVisibleRegion(display,
+                        layer, testLayers->getVisibleRegion(layer)));
+            },
+
+            advanceVisibleRegions));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the visible region of a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_VISIBLE_REGION_bad_layer)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+            setVisibleRegion));
+}
+
+/* TESTCASE: Tests that the HWC2 can set the z order of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_Z_ORDER)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerProperties(Hwc2TestCoverage::Complete, 10,
+            [] (Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+                    Hwc2TestLayers* testLayers) {
+
+                EXPECT_NO_FATAL_FAILURE(test->setLayerZOrder(display, layer,
+                        testLayers->getZOrder(layer)));
+            },
+
+            /* TestLayer z orders are set during the construction of TestLayers
+             * and cannot be updated. There is no need (or ability) to cycle
+             * through additional z order configurations. */
+            [] (Hwc2TestLayers* /*testLayers*/) {
+                return false;
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 can update the z order of a layer. */
+TEST_F(Hwc2Test, SET_LAYER_Z_ORDER_update)
+{
+    const std::vector<uint32_t> zOrders = { static_cast<uint32_t>(0),
+            static_cast<uint32_t>(1), static_cast<uint32_t>(UINT32_MAX / 4),
+            static_cast<uint32_t>(UINT32_MAX / 2),
+            static_cast<uint32_t>(UINT32_MAX) };
+
+    for (auto display : mDisplays) {
+        std::vector<hwc2_config_t> configs;
+
+        ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+        for (auto config : configs) {
+            hwc2_layer_t layer;
+
+            ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+
+            ASSERT_NO_FATAL_FAILURE(createLayer(display, &layer));
+
+            for (uint32_t zOrder : zOrders) {
+                EXPECT_NO_FATAL_FAILURE(setLayerZOrder(display, layer, zOrder));
+            }
+
+            ASSERT_NO_FATAL_FAILURE(destroyLayer(display, layer));
+        }
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the z order of a bad layer. */
+TEST_F(Hwc2Test, SET_LAYER_Z_ORDER_bad_layer)
+{
+    ASSERT_NO_FATAL_FAILURE(setLayerPropertyBadLayer(Hwc2TestCoverage::Default,
+            setZOrder));
+}
+
+/* TESTCASE: Tests that the HWC2 can display a layer with basic property
+ * coverage */
+TEST_F(Hwc2Test, VALIDATE_DISPLAY_basic)
+{
+    ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
+            [] (Hwc2Test* test, hwc2_display_t display,
+                    const std::vector<hwc2_layer_t>& layers,
+                    Hwc2TestLayers* /*testLayers*/) {
+
+                uint32_t numTypes, numRequests;
+                bool hasChanges = false;
+
+                EXPECT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
+                        &numRequests, &hasChanges));
+                if (hasChanges)
+                    EXPECT_LE(numTypes, static_cast<uint32_t>(layers.size()))
+                            << "wrong number of requests";
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 can display 5 layers with default coverage. */
+TEST_F(Hwc2Test, VALIDATE_DISPLAY_default_5)
+{
+    ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Default, 5,
+            [] (Hwc2Test* test, hwc2_display_t display,
+                    const std::vector<hwc2_layer_t>& layers,
+                    Hwc2TestLayers* /*testLayers*/) {
+
+                uint32_t numTypes, numRequests;
+                bool hasChanges = false;
+
+                EXPECT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
+                        &numRequests, &hasChanges));
+                if (hasChanges)
+                    EXPECT_LE(numTypes, static_cast<uint32_t>(layers.size()))
+                            << "wrong number of requests";
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot validate a bad display */
+TEST_F(Hwc2Test, VALIDATE_DISPLAY_bad_display)
+{
+    hwc2_display_t display;
+    uint32_t numTypes, numRequests;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes, &numRequests,
+            &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 can get display requests after validating a
+ * basic layer. */
+TEST_F(Hwc2Test, GET_DISPLAY_REQUESTS_basic)
+{
+    ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
+            [] (Hwc2Test* test, hwc2_display_t display,
+                    const std::vector<hwc2_layer_t>& layers,
+                    Hwc2TestLayers* /*testLayers*/) {
+
+                uint32_t numTypes, numRequests;
+                bool hasChanges = false;
+
+                ASSERT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
+                        &numRequests, &hasChanges));
+                if (hasChanges)
+                    EXPECT_LE(numTypes, layers.size())
+                            << "wrong number of requests";
+
+                EXPECT_NO_FATAL_FAILURE(test->handleRequests(display, layers,
+                        numRequests));
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get display requests from a bad display */
+TEST_F(Hwc2Test, GET_DISPLAY_REQUESTS_bad_display)
+{
+    hwc2_display_t display;
+    hwc2_display_request_t displayRequests;
+    std::vector<hwc2_layer_t> layers;
+    std::vector<hwc2_layer_request_t> layerRequests;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    EXPECT_NO_FATAL_FAILURE(getDisplayRequests(display, &displayRequests,
+            &layers, &layerRequests, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get display requests from an non
+ * validated display. */
+TEST_F(Hwc2Test, GET_DISPLAY_REQUESTS_not_validated)
+{
+    ASSERT_NO_FATAL_FAILURE(displayNonValidatedLayers(5,
+            [] (Hwc2Test* test, hwc2_display_t display,
+                    std::vector<hwc2_layer_t>* layers) {
+
+                hwc2_display_request_t displayRequests;
+                std::vector<hwc2_layer_request_t> layerRequests;
+                hwc2_error_t err = HWC2_ERROR_NONE;
+
+                ASSERT_NO_FATAL_FAILURE(test->getDisplayRequests(display,
+                        &displayRequests, layers, &layerRequests, &err));
+                EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED)
+                        << "returned wrong error code";
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 can get changed composition types after
+ * validating a basic layer. */
+TEST_F(Hwc2Test, GET_CHANGED_COMPOSITION_TYPES_basic)
+{
+    ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
+            [] (Hwc2Test* test, hwc2_display_t display,
+                    const std::vector<hwc2_layer_t>& layers,
+                    Hwc2TestLayers* testLayers) {
+
+                uint32_t numTypes, numRequests;
+                bool hasChanges = false;
+
+                ASSERT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
+                        &numRequests, &hasChanges));
+                if (hasChanges)
+                    EXPECT_LE(numTypes, layers.size())
+                            << "wrong number of requests";
+
+                EXPECT_NO_FATAL_FAILURE(test->handleCompositionChanges(display,
+                        *testLayers, layers, numTypes));
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get changed composition types from a bad
+ * display */
+TEST_F(Hwc2Test, GET_CHANGED_COMPOSITION_TYPES_bad_display)
+{
+    hwc2_display_t display;
+    std::vector<hwc2_layer_t> layers;
+    std::vector<hwc2_composition_t> types;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    EXPECT_NO_FATAL_FAILURE(getChangedCompositionTypes(display, &layers,
+            &types, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get changed composition types from an non
+ * validated display. */
+TEST_F(Hwc2Test, GET_CHANGED_COMPOSITION_TYPES_not_validated)
+{
+    ASSERT_NO_FATAL_FAILURE(displayNonValidatedLayers(5,
+            [] (Hwc2Test* test, hwc2_display_t display,
+                    std::vector<hwc2_layer_t>* layers) {
+
+                std::vector<hwc2_composition_t> types;
+                hwc2_error_t err = HWC2_ERROR_NONE;
+
+                ASSERT_NO_FATAL_FAILURE(test->getChangedCompositionTypes(
+                        display, layers, &types, &err));
+                EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED)
+                        << "returned wrong error code";
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 can accept display changes after validating a
+ * basic layer. */
+TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_basic)
+{
+    ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
+            [] (Hwc2Test* test, hwc2_display_t display,
+                    const std::vector<hwc2_layer_t>& layers,
+                    Hwc2TestLayers* testLayers) {
+
+                uint32_t numTypes, numRequests;
+                bool hasChanges = false;
+
+                ASSERT_NO_FATAL_FAILURE(test->validateDisplay(display, &numTypes,
+                        &numRequests, &hasChanges));
+                if (hasChanges)
+                    EXPECT_LE(numTypes, layers.size())
+                            << "wrong number of requests";
+
+                ASSERT_NO_FATAL_FAILURE(test->handleCompositionChanges(display,
+                        *testLayers, layers, numTypes));
+
+                EXPECT_NO_FATAL_FAILURE(test->acceptDisplayChanges(display));
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot accept display changes from a bad
+ * display */
+TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_bad_display)
+{
+    hwc2_display_t display;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    EXPECT_NO_FATAL_FAILURE(acceptDisplayChanges(display, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot accept display changes from an non
+ * validated display. */
+TEST_F(Hwc2Test, ACCEPT_DISPLAY_CHANGES_not_validated)
+{
+    ASSERT_NO_FATAL_FAILURE(displayNonValidatedLayers(5,
+            [] (Hwc2Test* test, hwc2_display_t display,
+                    std::vector<hwc2_layer_t>* /*layers*/) {
+
+                hwc2_error_t err = HWC2_ERROR_NONE;
+
+                ASSERT_NO_FATAL_FAILURE(test->acceptDisplayChanges(display, &err));
+                EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED)
+                        << "returned wrong error code";
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 supports client target with required values */
+TEST_F(Hwc2Test, GET_CLIENT_TARGET_SUPPORT)
+{
+    ASSERT_NO_FATAL_FAILURE(setClientTargetSupport(Hwc2TestCoverage::Default,
+            [] (Hwc2Test* test, hwc2_display_t display,
+                    const Hwc2TestClientTargetSupport& testClientTargetSupport) {
+
+                const Area bufferArea = testClientTargetSupport.getBufferArea();
+                const android_pixel_format_t format = HAL_PIXEL_FORMAT_RGBA_8888;
+
+                ASSERT_NO_FATAL_FAILURE(test->getClientTargetSupport(display,
+                        bufferArea.width, bufferArea.height, format,
+                        testClientTargetSupport.getDataspace()));
+            },
+
+            advanceClientTargetSupport));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get client target support for a bad
+ * display. */
+TEST_F(Hwc2Test, GET_CLIENT_TARGET_SUPPORT_bad_display)
+{
+    ASSERT_NO_FATAL_FAILURE(setClientTargetSupport(Hwc2TestCoverage::Default,
+            [] (Hwc2Test* test, hwc2_display_t /*display*/,
+                    const Hwc2TestClientTargetSupport& testClientTargetSupport) {
+
+                const Area bufferArea = testClientTargetSupport.getBufferArea();
+                const android_pixel_format_t format = HAL_PIXEL_FORMAT_RGBA_8888;
+                hwc2_display_t badDisplay;
+                hwc2_error_t err = HWC2_ERROR_NONE;
+
+                ASSERT_NO_FATAL_FAILURE(test->getBadDisplay(&badDisplay));
+
+                ASSERT_NO_FATAL_FAILURE(test->getClientTargetSupport(badDisplay,
+                        bufferArea.width, bufferArea.height, format,
+                        testClientTargetSupport.getDataspace(), &err));
+                EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+            },
+
+            advanceClientTargetSupport));
+}
+
+/* TESTCASE: Tests that the HWC2 either supports or returns error unsupported
+ * for a variety of client target values. */
+TEST_F(Hwc2Test, GET_CLIENT_TARGET_SUPPORT_unsupported)
+{
+    ASSERT_NO_FATAL_FAILURE(setClientTargetSupport(Hwc2TestCoverage::Complete,
+            [] (Hwc2Test* test, hwc2_display_t display,
+                    const Hwc2TestClientTargetSupport& testClientTargetSupport) {
+
+                const Area bufferArea = testClientTargetSupport.getBufferArea();
+                const android_pixel_format_t format = HAL_PIXEL_FORMAT_RGBA_8888;
+                hwc2_error_t err = HWC2_ERROR_NONE;
+
+                ASSERT_NO_FATAL_FAILURE(test->getClientTargetSupport(display,
+                        bufferArea.width, bufferArea.height, format,
+                        testClientTargetSupport.getDataspace(), &err));
+                EXPECT_TRUE(err == HWC2_ERROR_NONE
+                        || err == HWC2_ERROR_UNSUPPORTED)
+                        << "returned wrong error code";
+            },
+
+            advanceClientTargetSupport));
+}
+
+/* TESTCASE: Tests that the HWC2 can set a client target buffer for a basic
+ * layer. */
+TEST_F(Hwc2Test, SET_CLIENT_TARGET_basic)
+{
+    const android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN;
+    const hwc_region_t damage = { };
+    const size_t layerCnt = 1;
+
+    for (auto display : mDisplays) {
+        std::vector<hwc2_config_t> configs;
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_ON));
+
+        ASSERT_NO_FATAL_FAILURE(getDisplayConfigs(display, &configs));
+
+        for (auto config : configs) {
+            Area displayArea;
+            std::vector<hwc2_layer_t> layers;
+
+            ASSERT_NO_FATAL_FAILURE(setActiveConfig(display, config));
+            ASSERT_NO_FATAL_FAILURE(getActiveDisplayArea(display, &displayArea));
+
+            ASSERT_NO_FATAL_FAILURE(createLayers(display, &layers, layerCnt));
+            Hwc2TestLayers testLayers(layers, Hwc2TestCoverage::Basic,
+                    displayArea);
+
+            if (!testLayers.optimizeLayouts())
+                continue;
+
+            Hwc2TestClientTarget testClientTarget;
+
+            do {
+                std::set<hwc2_layer_t> clientLayers;
+                std::set<hwc2_layer_t> clearLayers;
+                uint32_t numTypes, numRequests;
+                bool hasChanges, skip;
+                bool flipClientTarget;
+                buffer_handle_t handle;
+                int32_t acquireFence;
+
+                ASSERT_NO_FATAL_FAILURE(setLayerProperties(display, layers,
+                        &testLayers, &skip));
+                if (skip)
+                    continue;
+
+                ASSERT_NO_FATAL_FAILURE(validateDisplay(display, &numTypes,
+                        &numRequests, &hasChanges));
+                if (hasChanges)
+                    EXPECT_LE(numTypes, layers.size())
+                            << "wrong number of requests";
+
+                ASSERT_NO_FATAL_FAILURE(handleCompositionChanges(display,
+                        testLayers, layers, numTypes, &clientLayers));
+                ASSERT_NO_FATAL_FAILURE(handleRequests(display, layers,
+                        numRequests, &clearLayers, &flipClientTarget));
+                ASSERT_EQ(testClientTarget.getBuffer(testLayers, clientLayers,
+                        clearLayers, flipClientTarget, displayArea, &handle,
+                        &acquireFence), 0);
+                EXPECT_NO_FATAL_FAILURE(setClientTarget(display, handle,
+                        acquireFence, dataspace, damage));
+
+                if (acquireFence >= 0)
+                    close(acquireFence);
+
+            } while (testLayers.advance());
+
+            ASSERT_NO_FATAL_FAILURE(destroyLayers(display, std::move(layers)));
+        }
+
+        ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set a client target for a bad display. */
+TEST_F(Hwc2Test, SET_CLIENT_TARGET_bad_display)
+{
+    hwc2_display_t display;
+    std::vector<hwc2_layer_t> layers;
+    const Area displayArea = {0, 0};
+    Hwc2TestLayers testLayers(layers, Hwc2TestCoverage::Default, displayArea);
+    std::set<hwc2_layer_t> clientLayers;
+    std::set<hwc2_layer_t> flipClientTargetLayers;
+    bool flipClientTarget = true;
+    const android_dataspace_t dataspace = HAL_DATASPACE_UNKNOWN;
+    const hwc_region_t damage = { };
+    buffer_handle_t handle;
+    int32_t acquireFence;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    Hwc2TestClientTarget testClientTarget;
+
+    ASSERT_EQ(testClientTarget.getBuffer(testLayers, clientLayers,
+            flipClientTargetLayers, flipClientTarget, displayArea, &handle,
+            &acquireFence), 0);
+
+    EXPECT_NO_FATAL_FAILURE(setClientTarget(display, handle, acquireFence,
+            dataspace, damage, &err));
+
+    if (acquireFence >= 0)
+        close(acquireFence);
+
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 default layer. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_default_1)
+{
+    const size_t layerCnt = 1;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
+    bool optimize = false;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 default layers. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_default_2)
+{
+    const size_t layerCnt = 2;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
+    bool optimize = false;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 3 default layers. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_default_3)
+{
+    const size_t layerCnt = 3;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
+    bool optimize = false;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 4 default layers. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_default_4)
+{
+    const size_t layerCnt = 4;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
+    bool optimize = false;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 5 default layers. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_default_5)
+{
+    const size_t layerCnt = 5;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
+    bool optimize = false;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 6 default layers. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_default_6)
+{
+    const size_t layerCnt = 6;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
+    bool optimize = false;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * blend mode. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_blend_mode_1)
+{
+    const size_t layerCnt = 1;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Complete},
+            {Hwc2TestPropertyName::Transform, Hwc2TestCoverage::Basic},
+            {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Basic}};
+    bool optimize = false;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
+ * blend mode. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_blend_mode_2)
+{
+    const size_t layerCnt = 2;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Complete},
+            {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Basic}};
+    bool optimize = false;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * buffer. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_buffer_1)
+{
+    const size_t layerCnt = 1;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::BufferArea, Hwc2TestCoverage::Complete}};
+    bool optimize = true;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * color. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_color_1)
+{
+    const size_t layerCnt = 1;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete},
+            {Hwc2TestPropertyName::Color, Hwc2TestCoverage::Complete}};
+    bool optimize = true;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
+ * color. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_color_2)
+{
+    const size_t layerCnt = 2;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete},
+            {Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Basic},
+            {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Basic},
+            {Hwc2TestPropertyName::Color, Hwc2TestCoverage::Basic}};
+    bool optimize = true;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * composition. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_composition_1)
+{
+    const size_t layerCnt = 1;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete}};
+    bool optimize = true;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * cursor. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_cursor_1)
+{
+    const size_t layerCnt = 1;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete},
+            {Hwc2TestPropertyName::CursorPosition, Hwc2TestCoverage::Complete}};
+    bool optimize = true;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
+ * cursor. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_cursor_2)
+{
+    const size_t layerCnt = 2;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::Composition, Hwc2TestCoverage::Complete},
+            {Hwc2TestPropertyName::CursorPosition, Hwc2TestCoverage::Complete},
+            {Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Basic}};
+    bool optimize = true;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * dataspace. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_dataspace_1)
+{
+    const size_t layerCnt = 1;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::Dataspace, Hwc2TestCoverage::Complete}};
+    bool optimize = true;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * display frame. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_1)
+{
+    const size_t layerCnt = 1;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}};
+    bool optimize = true;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
+ * display frame. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_2)
+{
+    const size_t layerCnt = 2;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}};
+    bool optimize = true;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 3 layers with complete coverage of
+ * display frame. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_3)
+{
+    const size_t layerCnt = 3;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}};
+    bool optimize = true;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 4 layers with complete coverage of
+ * display frame. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_display_frame_4)
+{
+    const size_t layerCnt = 4;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete}};
+    bool optimize = true;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * plane alpha. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_plane_alpha_1)
+{
+    const size_t layerCnt = 1;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Basic},
+            {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Complete}};
+    bool optimize = false;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
+ * plane alpha. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_plane_alpha_2)
+{
+    const size_t layerCnt = 2;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::BlendMode, Hwc2TestCoverage::Basic},
+            {Hwc2TestPropertyName::PlaneAlpha, Hwc2TestCoverage::Complete}};
+    bool optimize = false;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * source crop. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_source_crop_1)
+{
+    const size_t layerCnt = 1;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete},
+            {Hwc2TestPropertyName::SourceCrop, Hwc2TestCoverage::Complete}};
+    bool optimize = true;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
+ * source crop. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_source_crop_2)
+{
+    const size_t layerCnt = 2;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Complete},
+            {Hwc2TestPropertyName::SourceCrop, Hwc2TestCoverage::Complete}};
+    bool optimize = true;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * surface damage. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_surface_damage_1)
+{
+    const size_t layerCnt = 1;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::SurfaceDamage, Hwc2TestCoverage::Complete}};
+    bool optimize = true;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * transform. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_transform_1)
+{
+    const size_t layerCnt = 1;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::Transform, Hwc2TestCoverage::Complete}};
+    bool optimize = true;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 2 layers with complete coverage of
+ * transform. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_transform_2)
+{
+    const size_t layerCnt = 2;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Default;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions =
+            {{Hwc2TestPropertyName::Transform, Hwc2TestCoverage::Complete},
+            {Hwc2TestPropertyName::DisplayFrame, Hwc2TestCoverage::Basic}};
+    bool optimize = true;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 can present 1 layer with complete coverage of
+ * basic. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_basic_1)
+{
+    const size_t layerCnt = 1;
+    Hwc2TestCoverage coverage = Hwc2TestCoverage::Basic;
+    std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage> exceptions;
+    bool optimize = true;
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplays(layerCnt, coverage, exceptions,
+            optimize));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot present a bad display.  */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_bad_display)
+{
+    hwc2_display_t display;
+    int32_t presentFence;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(presentDisplay(display, &presentFence, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot present an unvalidated display. */
+TEST_F(Hwc2Test, PRESENT_DISPLAY_not_validated)
+{
+    ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Default, 1,
+            [] (Hwc2Test* test, hwc2_display_t display,
+                    const std::vector<hwc2_layer_t>& /*layers*/,
+                    Hwc2TestLayers* /*testLayers*/) {
+
+                int32_t presentFence;
+                hwc2_error_t err = HWC2_ERROR_NONE;
+
+                ASSERT_NO_FATAL_FAILURE(test->setPowerMode(display,
+                        HWC2_POWER_MODE_ON));
+                ASSERT_NO_FATAL_FAILURE(test->enableVsync(display));
+
+                ASSERT_NO_FATAL_FAILURE(test->waitForVsync());
+
+                ASSERT_NO_FATAL_FAILURE(test->presentDisplay(display,
+                        &presentFence, &err));
+                EXPECT_EQ(err, HWC2_ERROR_NOT_VALIDATED)
+                        << "returned wrong error code";
+
+                ASSERT_NO_FATAL_FAILURE(test->disableVsync(display));
+                ASSERT_NO_FATAL_FAILURE(test->setPowerMode(display,
+                        HWC2_POWER_MODE_OFF));
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get release fences from a bad display. */
+TEST_F(Hwc2Test, GET_RELEASE_FENCES_bad_display)
+{
+    hwc2_display_t display;
+    std::vector<hwc2_layer_t> layers;
+    std::vector<int32_t> fences;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(getReleaseFences(display, &layers, &fences, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+static const std::array<android_color_mode, 9> androidColorModes = {{
+    HAL_COLOR_MODE_NATIVE,
+    HAL_COLOR_MODE_STANDARD_BT601_625,
+    HAL_COLOR_MODE_STANDARD_BT601_625_UNADJUSTED,
+    HAL_COLOR_MODE_STANDARD_BT601_525,
+    HAL_COLOR_MODE_STANDARD_BT601_525_UNADJUSTED,
+    HAL_COLOR_MODE_STANDARD_BT709,
+    HAL_COLOR_MODE_DCI_P3,
+    HAL_COLOR_MODE_SRGB,
+    HAL_COLOR_MODE_ADOBE_RGB,
+}};
+
+/* TESTCASE: Tests that the HWC2 can get the color modes for a display. The
+ * display must support HAL_COLOR_MODE_NATIVE */
+TEST_F(Hwc2Test, GET_COLOR_MODES)
+{
+    ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
+            [] (Hwc2Test* test, hwc2_display_t display) {
+
+                std::vector<android_color_mode_t> colorModes;
+
+                ASSERT_NO_FATAL_FAILURE(test->getColorModes(display,
+                        &colorModes));
+
+                EXPECT_NE(std::count(colorModes.begin(), colorModes.end(),
+                        HAL_COLOR_MODE_NATIVE), 0) << "all displays"
+                        " must support HAL_COLOR_MODE_NATIVE";
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get color modes from a bad display. */
+TEST_F(Hwc2Test, GET_COLOR_MODES_bad_display)
+{
+    hwc2_display_t display;
+    std::vector<android_color_mode_t> colorModes;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(getColorModes(display, &colorModes, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 can set the required color mode on a display. */
+TEST_F(Hwc2Test, SET_COLOR_MODES)
+{
+    ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
+            [] (Hwc2Test* test, hwc2_display_t display) {
+
+                const android_color_mode_t colorMode = HAL_COLOR_MODE_NATIVE;
+
+                EXPECT_NO_FATAL_FAILURE(test->setColorMode(display, colorMode));
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set a color mode on a bad display. */
+TEST_F(Hwc2Test, SET_COLOR_MODES_bad_display)
+{
+    hwc2_display_t display;
+    const android_color_mode_t colorMode = HAL_COLOR_MODE_NATIVE;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(setColorMode(display, colorMode, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an invalid color mode. */
+TEST_F(Hwc2Test, SET_COLOR_MODES_bad_parameter)
+{
+    ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
+            [] (Hwc2Test* test, hwc2_display_t display) {
+
+                const android_color_mode_t colorMode =
+                        static_cast<android_color_mode_t>(-1);
+                hwc2_error_t err = HWC2_ERROR_NONE;
+
+                ASSERT_NO_FATAL_FAILURE(test->setColorMode(display, colorMode,
+                        &err));
+                EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER)
+                        << "returned wrong error code";
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 either supports or returns error unsupported
+ * for all valid color modes. */
+TEST_F(Hwc2Test, SET_COLOR_MODES_unsupported)
+{
+    ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
+            [] (Hwc2Test* test, hwc2_display_t display) {
+
+                for (auto colorMode : androidColorModes) {
+                    hwc2_error_t err = HWC2_ERROR_NONE;
+
+                    ASSERT_NO_FATAL_FAILURE(test->setColorMode(display,
+                            colorMode, &err));
+
+                    EXPECT_TRUE(err == HWC2_ERROR_NONE
+                            || err == HWC2_ERROR_UNSUPPORTED)
+                            << "returned wrong error code";
+                }
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 gets the HDR capabilities for a display and
+ * test if they are valid. */
+TEST_F(Hwc2Test, GET_HDR_CAPABILITIES)
+{
+    ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
+            [] (Hwc2Test* test, hwc2_display_t display) {
+
+                std::vector<android_hdr_t> hdrCapabilities;
+                float maxLuminance, maxAverageLuminance, minLuminance;
+
+                EXPECT_NO_FATAL_FAILURE(test->getHdrCapabilities(display,
+                        &hdrCapabilities, &maxLuminance, &maxAverageLuminance,
+                        &minLuminance));
+
+                if (hdrCapabilities.empty())
+                    return;
+
+                EXPECT_GE(maxLuminance, maxAverageLuminance);
+                EXPECT_GE(maxAverageLuminance, minLuminance);
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot get hdr capabilities from a bad display */
+TEST_F(Hwc2Test, GET_HDR_CAPABILITIES_bad_display)
+{
+    hwc2_display_t display;
+    std::vector<android_hdr_t> hdrCapabilities;
+    float maxLuminance, maxAverageLuminance, minLuminance;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(getHdrCapabilities(display, &hdrCapabilities,
+            &maxLuminance, &maxAverageLuminance, &minLuminance, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+static const std::array<float, 16> identityMatrix = {{
+    1.0,  0.0,  0.0,  0.0,
+    0.0,  1.0,  0.0,  0.0,
+    0.0,  0.0,  1.0,  0.0,
+    0.0,  0.0,  0.0,  1.0,
+}};
+
+/* Values for the color transform matrices were precomputed using the source code
+ * in surfaceflinger/Effects/Daltonizer.cpp. */
+
+static const std::array<const std::array<float, 16>, 5> exampleMatrices = {{
+    identityMatrix,
+    /* Converts RGB color to the XYZ space */
+    {{ 0.4124, 0.2126, 0.0193, 0,
+       0.3576, 0.7152, 0.1192, 0,
+       0.1805, 0.0722, 0.9505, 0,
+       0     , 0     , 0     , 1 }},
+    /* Protanomaly */
+    {{ 0.068493,  0.931506,  0,  0,
+       0.068493,  0.931507,  0,  0,
+       0.013626, -0.013626,  1,  0,
+       0,         0,         0,  1 }},
+    /* Deuteranomaly */
+    {{ 0.288299, 0.711701,  0,  0,
+       0.052709, 0.947291,  0,  0,
+      -0.257912, 0.257912,  1,  0,
+       0,        0,         0,  1 }},
+    /* Tritanomaly */
+    {{ 1, -0.805712, 0.805712,  0,
+       0,  0.378838, 0.621162,  0,
+       0,  0.104823, 0.895177,  0,
+       0,  0,        0,         1 }},
+}};
+
+/* TESTCASE: Tests that the HWC2 can set the identity color transform */
+TEST_F(Hwc2Test, SET_COLOR_TRANSFORM)
+{
+    ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
+            [] (Hwc2Test* test, hwc2_display_t display) {
+
+                EXPECT_NO_FATAL_FAILURE(test->setColorTransform(display,
+                        identityMatrix, HAL_COLOR_TRANSFORM_IDENTITY));
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set the color transform for a bad
+ * display. */
+TEST_F(Hwc2Test, SET_COLOR_TRANSFORM_bad_display)
+{
+    hwc2_display_t display;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(setColorTransform(display, identityMatrix,
+            HAL_COLOR_TRANSFORM_IDENTITY, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an invalid color transform. */
+TEST_F(Hwc2Test, SET_COLOR_TRANSFORM_bad_parameter)
+{
+    ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
+            [] (Hwc2Test* test, hwc2_display_t display) {
+
+                const android_color_transform_t hint =
+                        static_cast<android_color_transform_t>(-1);
+                hwc2_error_t err = HWC2_ERROR_NONE;
+
+                ASSERT_NO_FATAL_FAILURE(test->setColorTransform(display,
+                        identityMatrix, hint, &err));
+                EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER)
+                        << "returned wrong error code";
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 can set an arbitrary color matrix. */
+TEST_F(Hwc2Test, SET_COLOR_TRANSFORM_arbitrary_matrix)
+{
+    ASSERT_NO_FATAL_FAILURE(setActiveDisplayConfig(
+            [] (Hwc2Test* test, hwc2_display_t display) {
+
+                const android_color_transform_t hint =
+                        HAL_COLOR_TRANSFORM_ARBITRARY_MATRIX;
+
+                for (const std::array<float, 16>& matrix : exampleMatrices) {
+                    EXPECT_NO_FATAL_FAILURE(test->setColorTransform(display,
+                            matrix, hint));
+                }
+            }
+    ));
+}
+
+/* TESTCASE: Tests that the HWC2 create an destory virtual displays. */
+TEST_F(Hwc2Test, CREATE_DESTROY_VIRTUAL_DISPLAY)
+{
+    ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Complete,
+            [] (Hwc2Test* /*test*/, hwc2_display_t /*display*/,
+                    Hwc2TestVirtualDisplay* /*testVirtualDisplay*/) { }));
+}
+
+/* TESTCASE: Tests that the HWC2 can create and destroy multiple virtual
+ * displays. */
+TEST_F(Hwc2Test, CREATE_DESTROY_VIRTUAL_DISPLAY_multiple)
+{
+    Hwc2TestVirtualDisplay testVirtualDisplay(Hwc2TestCoverage::Complete);
+    std::vector<hwc2_display_t> displays;
+
+    do {
+        const UnsignedArea& dimension =
+                testVirtualDisplay.getDisplayDimension();
+        android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+        hwc2_display_t display;
+        hwc2_error_t err = HWC2_ERROR_NONE;
+
+        ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(dimension.width,
+                dimension.height, &desiredFormat, &display, &err));
+
+        EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_NO_RESOURCES
+                || err == HWC2_ERROR_UNSUPPORTED) << "returned wrong error code";
+        EXPECT_GE(desiredFormat, 0) << "invalid format";
+
+        if (err == HWC2_ERROR_NONE)
+            displays.push_back(display);
+
+    } while (testVirtualDisplay.advance());
+
+    for (hwc2_display_t display : displays) {
+        EXPECT_NO_FATAL_FAILURE(destroyVirtualDisplay(display));
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 cannot destroy a bad virtual displays.  */
+TEST_F(Hwc2Test, DESTROY_VIRTUAL_DISPLAY_bad_display)
+{
+    hwc2_display_t display;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(getBadDisplay(&display));
+
+    ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_DISPLAY) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 cannot destroy a physical display. */
+TEST_F(Hwc2Test, DESTROY_VIRTUAL_DISPLAY_bad_parameter)
+{
+    hwc2_display_t display = HWC_DISPLAY_PRIMARY;
+    hwc2_error_t err = HWC2_ERROR_NONE;
+
+    ASSERT_NO_FATAL_FAILURE(destroyVirtualDisplay(display, &err));
+    EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER) << "returned wrong error code";
+}
+
+/* TESTCASE: Tests that the HWC2 can get the max virtual display count. */
+TEST_F(Hwc2Test, GET_MAX_VIRTUAL_DISPLAY_COUNT)
+{
+    uint32_t maxCnt;
+
+    ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt));
+}
+
+/* TESTCASE: Tests that the HWC2 returns the same max virtual display count for
+ * each call. */
+TEST_F(Hwc2Test, GET_MAX_VIRTUAL_DISPLAY_COUNT_duplicate)
+{
+    uint32_t maxCnt1, maxCnt2;
+
+    ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt1));
+    ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt2));
+
+    EXPECT_EQ(maxCnt1, maxCnt2) << "returned two different max virtual display"
+            " counts";
+}
+
+/* TESTCASE: Tests that the HWC2 can create the max number of virtual displays
+ * that it reports. */
+TEST_F(Hwc2Test, GET_MAX_VIRTUAL_DISPLAY_COUNT_create_max)
+{
+    std::vector<hwc2_display_t> displays;
+    uint32_t maxCnt;
+
+    ASSERT_NO_FATAL_FAILURE(getMaxVirtualDisplayCount(&maxCnt));
+
+    while (displays.size() < maxCnt) {
+        uint32_t width = 1920, height = 1080;
+        android_pixel_format_t desiredFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+        hwc2_display_t display;
+        hwc2_error_t err = HWC2_ERROR_NONE;
+
+        ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(width, height,
+                    &desiredFormat, &display, &err));
+
+        EXPECT_TRUE(err == HWC2_ERROR_NONE || err == HWC2_ERROR_UNSUPPORTED)
+                << "returned wrong error code";
+        if (err != HWC2_ERROR_NONE)
+            break;
+
+        displays.push_back(display);
+    }
+
+    for (hwc2_display_t display : displays) {
+        EXPECT_NO_FATAL_FAILURE(destroyVirtualDisplay(display));
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 can set an output buffer for a virtual
+ * display. */
+TEST_F(Hwc2Test, SET_OUTPUT_BUFFER)
+{
+    ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Complete,
+            [] (Hwc2Test* test, hwc2_display_t display,
+                    Hwc2TestVirtualDisplay* testVirtualDisplay) {
+
+                buffer_handle_t handle;
+                android::base::unique_fd acquireFence;
+
+                if (testVirtualDisplay->getBuffer(&handle, &acquireFence) >= 0)
+                    EXPECT_NO_FATAL_FAILURE(test->setOutputBuffer(display,
+                            handle, acquireFence));
+            }));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an output buffer for a bad display */
+TEST_F(Hwc2Test, SET_OUTPUT_BUFFER_bad_display)
+{
+    ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Default,
+            [] (Hwc2Test* test, hwc2_display_t /*display*/,
+                    Hwc2TestVirtualDisplay* testVirtualDisplay) {
+
+                hwc2_display_t badDisplay;
+                buffer_handle_t handle;
+                android::base::unique_fd acquireFence;
+                hwc2_error_t err = HWC2_ERROR_NONE;
+
+                ASSERT_NO_FATAL_FAILURE(test->getBadDisplay(&badDisplay));
+
+                if (testVirtualDisplay->getBuffer(&handle, &acquireFence) < 0)
+                    return;
+
+                ASSERT_NO_FATAL_FAILURE(test->setOutputBuffer(badDisplay,
+                        handle, acquireFence, &err));
+                EXPECT_TRUE(err == HWC2_ERROR_BAD_DISPLAY)
+                        << "returned wrong error code";
+            }));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an invalid output buffer. */
+TEST_F(Hwc2Test, SET_OUTPUT_BUFFER_bad_parameter)
+{
+    ASSERT_NO_FATAL_FAILURE(createVirtualDisplay(Hwc2TestCoverage::Default,
+            [] (Hwc2Test* test, hwc2_display_t display,
+                    Hwc2TestVirtualDisplay* /*testVirtualDisplay*/) {
+
+                const buffer_handle_t handle = nullptr;
+                uint32_t releaseFence = -1;
+                hwc2_error_t err = HWC2_ERROR_NONE;
+
+                ASSERT_NO_FATAL_FAILURE(test->setOutputBuffer(display, handle,
+                        releaseFence, &err));
+                EXPECT_EQ(err, HWC2_ERROR_BAD_PARAMETER)
+                        << "returned wrong error code";
+            }));
+}
+
+/* TESTCASE: Tests that the HWC2 cannot set an output buffer for non virtual
+ * display */
+TEST_F(Hwc2Test, SET_OUTPUT_BUFFER_unsupported)
+{
+    for (auto display : mDisplays) {
+        Hwc2TestVirtualDisplay testVirtualDisplay(Hwc2TestCoverage::Complete);
+
+        do {
+            buffer_handle_t handle;
+            android::base::unique_fd acquireFence;
+            hwc2_error_t err = HWC2_ERROR_NONE;
+
+            if (testVirtualDisplay.getBuffer(&handle, &acquireFence) < 0)
+                continue;
+
+            ASSERT_NO_FATAL_FAILURE(setOutputBuffer(display, handle,
+                    acquireFence, &err));
+            EXPECT_EQ(err, HWC2_ERROR_UNSUPPORTED) << "returned wrong error code";
+
+        } while (testVirtualDisplay.advance());
+    }
+}
+
+/* TESTCASE: Tests that the HWC2 can dump debug information. */
+TEST_F(Hwc2Test, DUMP)
+{
+    std::string buffer;
+
+    ASSERT_NO_FATAL_FAILURE(dump(&buffer));
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp
new file mode 100644
index 0000000..a59f388
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp
@@ -0,0 +1,692 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <mutex>
+#include <array>
+#include <sstream>
+#include <algorithm>
+
+#include <gui/Surface.h>
+#include <gui/BufferItemConsumer.h>
+#include <gui/GraphicBufferAlloc.h>
+
+#include <ui/GraphicBuffer.h>
+#include <ui/vec4.h>
+
+#include <GLES3/gl3.h>
+
+#include "Hwc2TestBuffer.h"
+#include "Hwc2TestLayers.h"
+
+using namespace android;
+
+/* Returns a fence from egl */
+typedef void (*FenceCallback)(int32_t fence, void* callbackArgs);
+
+/* Returns fence to fence generator */
+static void setFence(int32_t fence, void* fenceGenerator);
+
+
+/* Used to receive the surfaces and fences from egl. The egl buffers are thrown
+ * away. The fences are sent to the requester via a callback */
+class Hwc2TestSurfaceManager {
+public:
+    /* Listens for a new frame, detaches the buffer and returns the fence
+     * through saved callback. */
+    class BufferListener : public ConsumerBase::FrameAvailableListener {
+    public:
+        BufferListener(sp<IGraphicBufferConsumer> consumer,
+                FenceCallback callback, void* callbackArgs)
+            : mConsumer(consumer),
+              mCallback(callback),
+              mCallbackArgs(callbackArgs) { }
+
+        void onFrameAvailable(const BufferItem& /*item*/)
+        {
+            BufferItem item;
+
+            if (mConsumer->acquireBuffer(&item, 0))
+                return;
+            if (mConsumer->detachBuffer(item.mSlot))
+                return;
+
+            mCallback(item.mFence->dup(), mCallbackArgs);
+        }
+
+    private:
+        sp<IGraphicBufferConsumer> mConsumer;
+        FenceCallback mCallback;
+        void* mCallbackArgs;
+    };
+
+    /* Creates a buffer listener that waits on a new frame from the buffer
+     * queue. */
+    void initialize(const Area& bufferArea, android_pixel_format_t format,
+            FenceCallback callback, void* callbackArgs)
+    {
+        sp<IGraphicBufferProducer> producer;
+        sp<IGraphicBufferConsumer> consumer;
+        BufferQueue::createBufferQueue(&producer, &consumer);
+
+        consumer->setDefaultBufferSize(bufferArea.width, bufferArea.height);
+        consumer->setDefaultBufferFormat(format);
+
+        mBufferItemConsumer = new BufferItemConsumer(consumer, 0);
+
+        mListener = new BufferListener(consumer, callback, callbackArgs);
+        mBufferItemConsumer->setFrameAvailableListener(mListener);
+
+        mSurface = new Surface(producer, true);
+    }
+
+    /* Used by Egl manager. The surface is never displayed. */
+    sp<Surface> getSurface() const
+    {
+        return mSurface;
+    }
+
+private:
+    sp<BufferItemConsumer> mBufferItemConsumer;
+    sp<BufferListener> mListener;
+    /* Used by Egl manager. The surface is never displayed */
+    sp<Surface> mSurface;
+};
+
+
+/* Used to generate valid fences. It is not possible to create a dummy sync
+ * fence for testing. Egl can generate buffers along with a valid fence.
+ * The buffer cannot be guaranteed to be the same format across all devices so
+ * a CPU filled buffer is used instead. The Egl fence is used along with the
+ * CPU filled buffer. */
+class Hwc2TestEglManager {
+public:
+    Hwc2TestEglManager()
+        : mEglDisplay(EGL_NO_DISPLAY),
+          mEglSurface(EGL_NO_SURFACE),
+          mEglContext(EGL_NO_CONTEXT) { }
+
+    ~Hwc2TestEglManager()
+    {
+        cleanup();
+    }
+
+    int initialize(sp<Surface> surface)
+    {
+        mSurface = surface;
+
+        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+        if (mEglDisplay == EGL_NO_DISPLAY) return false;
+
+        EGLint major;
+        EGLint minor;
+        if (!eglInitialize(mEglDisplay, &major, &minor)) {
+            ALOGW("Could not initialize EGL");
+            return false;
+        }
+
+        /* We're going to use a 1x1 pbuffer surface later on
+         * The configuration distance doesn't really matter for what we're
+         * trying to do */
+        EGLint configAttrs[] = {
+                EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+                EGL_RED_SIZE, 8,
+                EGL_GREEN_SIZE, 8,
+                EGL_BLUE_SIZE, 8,
+                EGL_ALPHA_SIZE, 0,
+                EGL_DEPTH_SIZE, 24,
+                EGL_STENCIL_SIZE, 0,
+                EGL_NONE
+        };
+
+        EGLConfig configs[1];
+        EGLint configCnt;
+        if (!eglChooseConfig(mEglDisplay, configAttrs, configs, 1,
+                &configCnt)) {
+            ALOGW("Could not select EGL configuration");
+            eglReleaseThread();
+            eglTerminate(mEglDisplay);
+            return false;
+        }
+
+        if (configCnt <= 0) {
+            ALOGW("Could not find EGL configuration");
+            eglReleaseThread();
+            eglTerminate(mEglDisplay);
+            return false;
+        }
+
+        /* These objects are initialized below but the default "null" values are
+         * used to cleanup properly at any point in the initialization sequence */
+        EGLint attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+        mEglContext = eglCreateContext(mEglDisplay, configs[0], EGL_NO_CONTEXT,
+                attrs);
+        if (mEglContext == EGL_NO_CONTEXT) {
+            ALOGW("Could not create EGL context");
+            cleanup();
+            return false;
+        }
+
+        EGLint surfaceAttrs[] = { EGL_NONE };
+        mEglSurface = eglCreateWindowSurface(mEglDisplay, configs[0],
+                mSurface.get(), surfaceAttrs);
+        if (mEglSurface == EGL_NO_SURFACE) {
+            ALOGW("Could not create EGL surface");
+            cleanup();
+            return false;
+        }
+
+        if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
+            ALOGW("Could not change current EGL context");
+            cleanup();
+            return false;
+        }
+
+        return true;
+    }
+
+    void makeCurrent() const
+    {
+        eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
+    }
+
+    void present() const
+    {
+        eglSwapBuffers(mEglDisplay, mEglSurface);
+    }
+
+private:
+    void cleanup()
+    {
+        if (mEglDisplay == EGL_NO_DISPLAY)
+            return;
+        if (mEglSurface != EGL_NO_SURFACE)
+            eglDestroySurface(mEglDisplay, mEglSurface);
+        if (mEglContext != EGL_NO_CONTEXT)
+            eglDestroyContext(mEglDisplay, mEglContext);
+
+        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
+                EGL_NO_CONTEXT);
+        eglReleaseThread();
+        eglTerminate(mEglDisplay);
+    }
+
+    sp<Surface> mSurface;
+    EGLDisplay mEglDisplay;
+    EGLSurface mEglSurface;
+    EGLContext mEglContext;
+};
+
+
+static const std::array<vec2, 4> triangles = {{
+    {  1.0f,  1.0f },
+    { -1.0f,  1.0f },
+    {  1.0f, -1.0f },
+    { -1.0f, -1.0f },
+}};
+
+class Hwc2TestFenceGenerator {
+public:
+
+    Hwc2TestFenceGenerator()
+    {
+        mSurfaceManager.initialize({1, 1}, HAL_PIXEL_FORMAT_RGBA_8888,
+                setFence, this);
+
+        if (!mEglManager.initialize(mSurfaceManager.getSurface()))
+            return;
+
+        mEglManager.makeCurrent();
+
+        glClearColor(0.0, 0.0, 0.0, 1.0);
+        glEnableVertexAttribArray(0);
+    }
+
+    ~Hwc2TestFenceGenerator()
+    {
+        if (mFence >= 0)
+            close(mFence);
+        mFence = -1;
+
+        mEglManager.makeCurrent();
+    }
+
+    /* It is not possible to simply generate a fence. The easiest way is to
+     * generate a buffer using egl and use the associated fence. The buffer
+     * cannot be guaranteed to be a certain format across all devices using this
+     * method. Instead the buffer is generated using the CPU */
+    int32_t get()
+    {
+        if (mFence >= 0) {
+            return dup(mFence);
+        }
+
+        std::unique_lock<std::mutex> lock(mMutex);
+
+        /* If the pending is still set to false and times out, we cannot recover.
+         * Set an error and return */
+        while (mPending != false) {
+            if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
+                return -ETIME;
+        }
+
+        /* Generate a fence. The fence will be returned through the setFence
+         * callback */
+        mEglManager.makeCurrent();
+
+        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, triangles.data());
+        glClear(GL_COLOR_BUFFER_BIT);
+
+        mEglManager.present();
+
+        /* Wait for the setFence callback */
+        while (mPending != true) {
+            if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
+                return -ETIME;
+        }
+
+        mPending = false;
+
+        return dup(mFence);
+    }
+
+    /* Callback that sets the fence */
+    void set(int32_t fence)
+    {
+        mFence = fence;
+        mPending = true;
+
+        mCv.notify_all();
+    }
+
+private:
+
+    Hwc2TestSurfaceManager mSurfaceManager;
+    Hwc2TestEglManager mEglManager;
+
+    std::mutex mMutex;
+    std::condition_variable mCv;
+
+    int32_t mFence = -1;
+    bool mPending = false;
+};
+
+
+static void setFence(int32_t fence, void* fenceGenerator)
+{
+    static_cast<Hwc2TestFenceGenerator*>(fenceGenerator)->set(fence);
+}
+
+
+/* Sets the pixel of a buffer given the location, format, stride and color.
+ * Currently only supports RGBA_8888 */
+static void setColor(int32_t x, int32_t y,
+        android_pixel_format_t format, uint32_t stride, uint8_t* img, uint8_t r,
+        uint8_t g, uint8_t b, uint8_t a)
+{
+       switch (format) {
+       case HAL_PIXEL_FORMAT_RGBA_8888:
+           img[(y * stride + x) * 4 + 0] = r;
+           img[(y * stride + x) * 4 + 1] = g;
+           img[(y * stride + x) * 4 + 2] = b;
+           img[(y * stride + x) * 4 + 3] = a;
+           break;
+       default:
+           break;
+       }
+}
+
+Hwc2TestBuffer::Hwc2TestBuffer()
+    : mFenceGenerator(new Hwc2TestFenceGenerator()) { }
+
+Hwc2TestBuffer::~Hwc2TestBuffer() = default;
+
+/* When the buffer changes sizes, save the new size and invalidate the current
+ * buffer */
+void Hwc2TestBuffer::updateBufferArea(const Area& bufferArea)
+{
+    if (mBufferArea.width == bufferArea.width
+            && mBufferArea.height == bufferArea.height)
+        return;
+
+    mBufferArea.width = bufferArea.width;
+    mBufferArea.height = bufferArea.height;
+
+    mValidBuffer = false;
+}
+
+/* Returns a valid buffer handle and fence. The handle is filled using the CPU
+ * to ensure the correct format across all devices. The fence is created using
+ * egl. */
+int Hwc2TestBuffer::get(buffer_handle_t* outHandle, int32_t* outFence)
+{
+    if (mBufferArea.width == -1 || mBufferArea.height == -1)
+        return -EINVAL;
+
+    /* If the current buffer is valid, the previous buffer can be reused.
+     * Otherwise, create new buffer */
+    if (!mValidBuffer) {
+        int ret = generateBuffer();
+        if (ret)
+            return ret;
+    }
+
+    *outFence = mFenceGenerator->get();
+    *outHandle = mHandle;
+
+    mValidBuffer = true;
+
+    return 0;
+}
+
+/* CPU fills a buffer to guarantee the correct buffer format across all
+ * devices */
+int Hwc2TestBuffer::generateBuffer()
+{
+    int ret;
+
+    /* Create new graphic buffer with correct dimensions */
+    mGraphicBuffer = mGraphicBufferAlloc.createGraphicBuffer(
+            mBufferArea.width, mBufferArea.height, mFormat,
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER,
+            "hwc2_test_buffer", &ret);
+    if (ret)
+        return ret;
+
+    /* Locks the buffer for writing */
+    uint8_t* img;
+    mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+
+    uint32_t stride = mGraphicBuffer->getStride();
+
+    /* Iterate from the top row of the buffer to the bottom row */
+    for (int32_t y = 0; y < mBufferArea.height; y++) {
+
+        /* Will be used as R, G and B values for pixel colors */
+        uint8_t max = 255;
+        uint8_t min = 0;
+
+        /* Divide the rows into 3 sections. The first section will contain
+         * the lighest colors. The last section will contain the darkest
+         * colors. */
+        if (y < mBufferArea.height * 1.0 / 3.0) {
+            min = 255 / 2;
+        } else if (y >= mBufferArea.height * 2.0 / 3.0) {
+            max = 255 / 2;
+        }
+
+        /* Divide the columns into 3 sections. The first section is red,
+         * the second is green and the third is blue */
+        int32_t x = 0;
+        for (; x < mBufferArea.width / 3; x++) {
+            setColor(x, y, mFormat, stride, img, max, min, min, 255);
+        }
+
+        for (; x < mBufferArea.width * 2 / 3; x++) {
+            setColor(x, y, mFormat, stride, img, min, max, min, 255);
+        }
+
+        for (; x < mBufferArea.width; x++) {
+            setColor(x, y, mFormat, stride, img, min, min, max, 255);
+        }
+    }
+
+    /* Unlock the buffer for reading */
+    mGraphicBuffer->unlock();
+
+    mHandle = mGraphicBuffer->handle;
+
+    return 0;
+}
+
+
+Hwc2TestClientTargetBuffer::Hwc2TestClientTargetBuffer()
+    : mFenceGenerator(new Hwc2TestFenceGenerator()) { }
+
+Hwc2TestClientTargetBuffer::~Hwc2TestClientTargetBuffer() { }
+
+/* Generates a client target buffer using the layers assigned for client
+ * composition. Takes into account the individual layer properties such as
+ * transform, blend mode, source crop, etc. */
+int Hwc2TestClientTargetBuffer::get(buffer_handle_t* outHandle,
+        int32_t* outFence, const Area& bufferArea,
+        const Hwc2TestLayers* testLayers,
+        const std::set<hwc2_layer_t>* clientLayers,
+        const std::set<hwc2_layer_t>* clearLayers)
+{
+    int err;
+
+    /* Create new graphic buffer with updated size */
+    mGraphicBuffer = mGraphicBufferAlloc.createGraphicBuffer(bufferArea.width,
+            bufferArea.height, mFormat,
+            GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER,
+            "hwc2_test_buffer", &err);
+    if (err)
+        return err;
+
+    uint8_t* img;
+    mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));
+
+    uint32_t stride = mGraphicBuffer->getStride();
+
+    float bWDiv3 = bufferArea.width / 3;
+    float bW2Div3 = bufferArea.width * 2 / 3;
+    float bHDiv3 = bufferArea.height / 3;
+    float bH2Div3 = bufferArea.height * 2 / 3;
+
+    /* Cycle through every pixel in the buffer and determine what color it
+     * should be. */
+    for (int32_t y = 0; y < bufferArea.height; y++) {
+        for (int32_t x = 0; x < bufferArea.width; x++) {
+
+            uint8_t r = 0, g = 0, b = 0;
+            float a = 0.0f;
+
+            /* Cycle through each client layer from back to front and
+             * update the pixel color. */
+            for (auto layer = clientLayers->rbegin();
+                    layer != clientLayers->rend(); ++layer) {
+
+                const hwc_rect_t df = testLayers->getDisplayFrame(*layer);
+
+                float dfL = df.left;
+                float dfT = df.top;
+                float dfR = df.right;
+                float dfB = df.bottom;
+
+                /* If the pixel location falls outside of the layer display
+                 * frame, skip the layer. */
+                if (x < dfL || x >= dfR || y < dfT || y >= dfB)
+                    continue;
+
+                /* If the device has requested the layer be clear, clear
+                 * the pixel and continue. */
+                if (clearLayers->count(*layer) != 0) {
+                    r = 0;
+                    g = 0;
+                    b = 0;
+                    a = 0.0f;
+                    continue;
+                }
+
+                float planeAlpha = testLayers->getPlaneAlpha(*layer);
+
+                /* If the layer is a solid color, fill the color and
+                 * continue. */
+                if (testLayers->getComposition(*layer)
+                        == HWC2_COMPOSITION_SOLID_COLOR) {
+                    const auto color = testLayers->getColor(*layer);
+                    r = color.r;
+                    g = color.g;
+                    b = color.b;
+                    a = color.a * planeAlpha;
+                    continue;
+                }
+
+                float xPos = x;
+                float yPos = y;
+
+                hwc_transform_t transform = testLayers->getTransform(*layer);
+
+                float dfW = dfR - dfL;
+                float dfH = dfB - dfT;
+
+                /* If a layer has a transform, find which location on the
+                 * layer will end up in the current pixel location. We
+                 * can calculate the color of the current pixel using that
+                 * location. */
+                if (transform > 0) {
+                    /* Change origin to be the center of the layer. */
+                    xPos = xPos - dfL - dfW / 2.0;
+                    yPos = yPos - dfT - dfH / 2.0;
+
+                    /* Flip Horizontal by reflecting across the y axis. */
+                    if (transform & HWC_TRANSFORM_FLIP_H)
+                        xPos = -xPos;
+
+                    /* Flip vertical by reflecting across the x axis. */
+                    if (transform & HWC_TRANSFORM_FLIP_V)
+                        yPos = -yPos;
+
+                    /* Rotate 90 by using a basic linear algebra rotation
+                     * and scaling the result so the display frame remains
+                     * the same. For example, a buffer of size 100x50 should
+                     * rotate 90 degress but remain the same dimension
+                     * (100x50) at the end of the transformation. */
+                    if (transform & HWC_TRANSFORM_ROT_90) {
+                        float tmp = xPos;
+                        xPos = -yPos * dfW / dfH;
+                        yPos = tmp * dfH / dfW;
+                    }
+
+                    /* Change origin back to the top left corner of the
+                     * layer. */
+                    xPos = xPos + dfL + dfW / 2.0;
+                    yPos = yPos + dfT + dfH / 2.0;
+                }
+
+                hwc_frect_t sc = testLayers->getSourceCrop(*layer);
+                float scL = sc.left, scT = sc.top;
+
+                float dfWDivScW = dfW / (sc.right - scL);
+                float dfHDivScH = dfH / (sc.bottom - scT);
+
+                float max = 255, min = 0;
+
+                /* Choose the pixel color. Similar to generateBuffer,
+                 * each layer will be divided into 3x3 colors. Because
+                 * both the source crop and display frame must be taken into
+                 * account, the formulas are more complicated.
+                 *
+                 * If the source crop and display frame were not taken into
+                 * account, we would simply divide the buffer into three
+                 * sections by height. Each section would get one color.
+                 * For example the formula for the first section would be:
+                 *
+                 * if (yPos < bufferArea.height / 3)
+                 *        //Select first section color
+                 *
+                 * However the pixel color is chosen based on the source
+                 * crop and displayed based on the display frame.
+                 *
+                 * If the display frame top was 0 and the source crop height
+                 * and display frame height were the same. The only factor
+                 * would be the source crop top. To calculate the new
+                 * section boundary, the section boundary would be moved up
+                 * by the height of the source crop top. The formula would
+                 * be:
+                 * if (yPos < (bufferArea.height / 3 - sourceCrop.top)
+                 *        //Select first section color
+                 *
+                 * If the display frame top could also vary but source crop
+                 * and display frame heights were the same, the formula
+                 * would be:
+                 * if (yPos < (bufferArea.height / 3 - sourceCrop.top
+                 *              + displayFrameTop)
+                 *        //Select first section color
+                 *
+                 * If the heights were not the same, the conversion between
+                 * the source crop and display frame dimensions must be
+                 * taken into account. The formula would be:
+                 * if (yPos < ((bufferArea.height / 3) - sourceCrop.top)
+                 *              * displayFrameHeight / sourceCropHeight
+                 *              + displayFrameTop)
+                 *        //Select first section color
+                 */
+                if (yPos < ((bHDiv3) - scT) * dfHDivScH + dfT) {
+                    min = 255 / 2;
+                } else if (yPos >= ((bH2Div3) - scT) * dfHDivScH + dfT) {
+                    max = 255 / 2;
+                }
+
+                uint8_t rCur = min, gCur = min, bCur = min;
+                float aCur = 1.0f;
+
+                /* This further divides the color sections from 3 to 3x3.
+                 * The math behind it follows the same logic as the previous
+                 * comment */
+                if (xPos < ((bWDiv3) - scL) * (dfWDivScW) + dfL) {
+                    rCur = max;
+                } else if (xPos < ((bW2Div3) - scL) * (dfWDivScW) + dfL) {
+                    gCur = max;
+                } else {
+                    bCur = max;
+                }
+
+
+                /* Blend the pixel color with the previous layers' pixel
+                 * colors using the plane alpha and blend mode. The final
+                 * pixel color is chosen using the plane alpha and blend
+                 * mode formulas found in hwcomposer2.h */
+                hwc2_blend_mode_t blendMode = testLayers->getBlendMode(*layer);
+
+                if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) {
+                    rCur *= planeAlpha;
+                    gCur *= planeAlpha;
+                    bCur *= planeAlpha;
+                }
+
+                aCur *= planeAlpha;
+
+                if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) {
+                    r = rCur + r * (1.0 - aCur);
+                    g = gCur + g * (1.0 - aCur);
+                    b = bCur + b * (1.0 - aCur);
+                    a = aCur + a * (1.0 - aCur);
+                } else if (blendMode == HWC2_BLEND_MODE_COVERAGE) {
+                    r = rCur * aCur + r * (1.0 - aCur);
+                    g = gCur * aCur + g * (1.0 - aCur);
+                    b = bCur * aCur + b * (1.0 - aCur);
+                    a = aCur * aCur + a * (1.0 - aCur);
+                } else {
+                    r = rCur;
+                    g = gCur;
+                    b = bCur;
+                    a = aCur;
+                }
+            }
+
+            /* Set the pixel color */
+            setColor(x, y, mFormat, stride, img, r, g, b, a * 255);
+        }
+    }
+
+    mGraphicBuffer->unlock();
+
+    *outFence = mFenceGenerator->get();
+    *outHandle = mGraphicBuffer->handle;
+
+    return 0;
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h
new file mode 100644
index 0000000..ca60940
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HWC2_TEST_BUFFER_H
+#define _HWC2_TEST_BUFFER_H
+
+#include <android-base/unique_fd.h>
+#include <set>
+
+#include <hardware/hwcomposer2.h>
+
+#include <gui/GraphicBufferAlloc.h>
+#include <ui/GraphicBuffer.h>
+
+#include "Hwc2TestProperties.h"
+
+class Hwc2TestFenceGenerator;
+class Hwc2TestLayers;
+
+class Hwc2TestBuffer {
+public:
+    Hwc2TestBuffer();
+    ~Hwc2TestBuffer();
+
+    void updateBufferArea(const Area& bufferArea);
+
+    int  get(buffer_handle_t* outHandle, int32_t* outFence);
+
+protected:
+    int generateBuffer();
+
+    android::GraphicBufferAlloc mGraphicBufferAlloc;
+    android::sp<android::GraphicBuffer> mGraphicBuffer;
+
+    std::unique_ptr<Hwc2TestFenceGenerator> mFenceGenerator;
+
+    Area mBufferArea = {-1, -1};
+    const android_pixel_format_t mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+
+    bool mValidBuffer = false;
+    buffer_handle_t mHandle = nullptr;
+};
+
+
+class Hwc2TestClientTargetBuffer {
+public:
+    Hwc2TestClientTargetBuffer();
+    ~Hwc2TestClientTargetBuffer();
+
+    int  get(buffer_handle_t* outHandle, int32_t* outFence,
+            const Area& bufferArea, const Hwc2TestLayers* testLayers,
+            const std::set<hwc2_layer_t>* clientLayers,
+            const std::set<hwc2_layer_t>* clearLayers);
+
+protected:
+    android::GraphicBufferAlloc mGraphicBufferAlloc;
+    android::sp<android::GraphicBuffer> mGraphicBuffer;
+
+    std::unique_ptr<Hwc2TestFenceGenerator> mFenceGenerator;
+
+    const android_pixel_format_t mFormat = HAL_PIXEL_FORMAT_RGBA_8888;
+};
+
+#endif /* ifndef _HWC2_TEST_BUFFER_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.cpp
new file mode 100644
index 0000000..6925492
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sstream>
+
+#include <ui/Rect.h>
+
+#include "Hwc2TestClientTarget.h"
+
+int Hwc2TestClientTarget::getBuffer(const Hwc2TestLayers& testLayers,
+        const std::set<hwc2_layer_t>& clientLayers,
+        const std::set<hwc2_layer_t>& clearLayers, bool flipClientTarget,
+        const Area& displayArea, buffer_handle_t* outHandle,
+        int32_t* outAcquireFence)
+{
+    if (!flipClientTarget) {
+        bool needsClientTarget = false;
+
+        for (auto clientLayer : clientLayers) {
+            if (testLayers.getVisibleRegion(clientLayer).numRects > 0) {
+                needsClientTarget = true;
+                break;
+            }
+        }
+
+        if (!needsClientTarget) {
+           *outHandle = nullptr;
+           *outAcquireFence = -1;
+           return 0;
+        }
+    }
+
+    return mBuffer.get(outHandle, outAcquireFence, displayArea,
+            &testLayers, &clientLayers, &clearLayers);
+}
+
+
+Hwc2TestClientTargetSupport::Hwc2TestClientTargetSupport(
+        Hwc2TestCoverage coverage, const Area& displayArea)
+    : mBufferArea(coverage, displayArea),
+      mDataspace(coverage),
+      mSurfaceDamage(coverage)
+{
+    mBufferArea.setDependent(&mSurfaceDamage);
+}
+
+std::string Hwc2TestClientTargetSupport::dump() const
+{
+    std::stringstream dmp;
+
+    dmp << "client target: \n";
+
+    for (auto property : properties) {
+        dmp << property->dump();
+    }
+
+    return dmp.str();
+}
+
+void Hwc2TestClientTargetSupport::reset()
+{
+    for (auto property : properties) {
+        property->reset();
+    }
+}
+
+bool Hwc2TestClientTargetSupport::advance()
+{
+    for (auto property : properties) {
+        if (property->advance())
+            return true;
+    }
+    return false;
+}
+
+Area Hwc2TestClientTargetSupport::getBufferArea() const
+{
+    return mBufferArea.get();
+}
+
+android_dataspace_t Hwc2TestClientTargetSupport::getDataspace() const
+{
+    return mDataspace.get();
+}
+
+const hwc_region_t Hwc2TestClientTargetSupport::getSurfaceDamage() const
+{
+    return mSurfaceDamage.get();
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.h b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.h
new file mode 100644
index 0000000..3b47978
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestClientTarget.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HWC2_TEST_CLIENT_TARGET_H
+#define _HWC2_TEST_CLIENT_TARGET_H
+
+#include <set>
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include "Hwc2TestProperties.h"
+#include "Hwc2TestLayers.h"
+
+/* Generates client target buffers from client composition layers */
+class Hwc2TestClientTarget {
+public:
+    int getBuffer(const Hwc2TestLayers& layers,
+            const std::set<hwc2_layer_t>& clientLayers,
+            const std::set<hwc2_layer_t>& clearLayers,
+            bool clearClientTarget, const Area& displayArea,
+            buffer_handle_t* outHandle, int32_t* outAcquireFence);
+
+private:
+    Hwc2TestClientTargetBuffer mBuffer;
+};
+
+/* Generates valid client targets to test which ones the device will support */
+class Hwc2TestClientTargetSupport {
+public:
+    Hwc2TestClientTargetSupport(Hwc2TestCoverage coverage,
+            const Area& displayArea);
+
+    std::string dump() const;
+
+    void reset();
+    bool advance();
+
+    Area getBufferArea() const;
+    android_dataspace_t getDataspace() const;
+    const hwc_region_t getSurfaceDamage() const;
+
+private:
+    std::array<Hwc2TestContainer*, 3> properties = {{
+        &mDataspace, &mSurfaceDamage, &mBufferArea
+    }};
+
+    Hwc2TestBufferArea mBufferArea;
+    Hwc2TestDataspace mDataspace;
+    Hwc2TestSurfaceDamage mSurfaceDamage;
+};
+
+#endif /* ifndef _HWC2_TEST_CLIENT_TARGET_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp
new file mode 100644
index 0000000..937fce2
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp
@@ -0,0 +1,249 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sstream>
+
+#include "Hwc2TestLayer.h"
+
+Hwc2TestCoverage getCoverage(Hwc2TestPropertyName property,
+        Hwc2TestCoverage coverage, const std::unordered_map<Hwc2TestPropertyName,
+        Hwc2TestCoverage>& coverageExceptions) {
+    auto exception = coverageExceptions.find(property);
+    return (exception != coverageExceptions.end())? exception->second : coverage;
+}
+
+Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage,
+        const Area& displayArea)
+    : Hwc2TestLayer(coverage, displayArea,
+            std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>()) { }
+
+Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage,
+        const Area& displayArea, const std::unordered_map<Hwc2TestPropertyName,
+        Hwc2TestCoverage>& coverageExceptions)
+    : mBlendMode(getCoverage(Hwc2TestPropertyName::BlendMode, coverage,
+           coverageExceptions)),
+      mBufferArea(getCoverage(Hwc2TestPropertyName::BufferArea, coverage,
+           coverageExceptions), displayArea),
+      mColor(getCoverage(Hwc2TestPropertyName::Color, coverage,
+           coverageExceptions)),
+      mComposition(getCoverage(Hwc2TestPropertyName::Composition, coverage,
+           coverageExceptions)),
+      mDataspace(getCoverage(Hwc2TestPropertyName::Dataspace, coverage,
+           coverageExceptions)),
+      mDisplayFrame(getCoverage(Hwc2TestPropertyName::DisplayFrame, coverage,
+           coverageExceptions), displayArea),
+      mPlaneAlpha(getCoverage(Hwc2TestPropertyName::PlaneAlpha, coverage,
+           coverageExceptions)),
+      mSourceCrop(getCoverage(Hwc2TestPropertyName::SourceCrop, coverage,
+           coverageExceptions)),
+      mSurfaceDamage(getCoverage(Hwc2TestPropertyName::SurfaceDamage, coverage,
+           coverageExceptions)),
+      mTransform(getCoverage(Hwc2TestPropertyName::Transform, coverage,
+           coverageExceptions))
+{
+    mBufferArea.setDependent(&mBuffer);
+    mBufferArea.setDependent(&mSourceCrop);
+    mBufferArea.setDependent(&mSurfaceDamage);
+    mBlendMode.setDependent(&mColor);
+}
+
+std::string Hwc2TestLayer::dump() const
+{
+    std::stringstream dmp;
+
+    dmp << "layer: \n";
+
+    for (auto property : mProperties) {
+        dmp << property->dump();
+    }
+
+    dmp << mVisibleRegion.dump();
+    dmp << "\tz order: " << mZOrder << "\n";
+
+    return dmp.str();
+}
+
+int Hwc2TestLayer::getBuffer(buffer_handle_t* outHandle,
+        android::base::unique_fd* outAcquireFence)
+{
+    int32_t acquireFence;
+    int ret = mBuffer.get(outHandle, &acquireFence);
+    outAcquireFence->reset(acquireFence);
+    return ret;
+}
+
+int Hwc2TestLayer::getBuffer(buffer_handle_t* outHandle,
+        int32_t* outAcquireFence)
+{
+    return mBuffer.get(outHandle, outAcquireFence);
+}
+
+void Hwc2TestLayer::setZOrder(uint32_t zOrder)
+{
+    mZOrder = zOrder;
+}
+
+void Hwc2TestLayer::setVisibleRegion(const android::Region& region)
+{
+    return mVisibleRegion.set(region);
+}
+
+void Hwc2TestLayer::reset()
+{
+    mVisibleRegion.release();
+
+    for (auto property : mProperties) {
+        property->reset();
+    }
+}
+
+bool Hwc2TestLayer::advance()
+{
+    for (auto property : mProperties) {
+        if (property->isSupported(mComposition.get()))
+            if (property->advance())
+                return true;
+    }
+    return false;
+}
+
+hwc2_blend_mode_t Hwc2TestLayer::getBlendMode() const
+{
+    return mBlendMode.get();
+}
+
+Area Hwc2TestLayer::getBufferArea() const
+{
+    return mBufferArea.get();
+}
+
+hwc_color_t Hwc2TestLayer::getColor() const
+{
+    return mColor.get();
+}
+
+hwc2_composition_t Hwc2TestLayer::getComposition() const
+{
+    return mComposition.get();
+}
+
+/* The cursor position corresponds to {displayFrame.left, displayFrame.top} */
+hwc_rect_t Hwc2TestLayer::getCursorPosition() const
+{
+    return mDisplayFrame.get();
+}
+
+android_dataspace_t Hwc2TestLayer::getDataspace() const
+{
+    return mDataspace.get();
+}
+
+hwc_rect_t Hwc2TestLayer::getDisplayFrame() const
+{
+    return mDisplayFrame.get();
+}
+
+float Hwc2TestLayer::getPlaneAlpha() const
+{
+    return mPlaneAlpha.get();
+}
+
+hwc_frect_t Hwc2TestLayer::getSourceCrop() const
+{
+    return mSourceCrop.get();
+}
+
+hwc_region_t Hwc2TestLayer::getSurfaceDamage() const
+{
+    return mSurfaceDamage.get();
+}
+
+hwc_transform_t Hwc2TestLayer::getTransform() const
+{
+    return mTransform.get();
+}
+
+hwc_region_t Hwc2TestLayer::getVisibleRegion() const
+{
+    return mVisibleRegion.get();
+}
+
+uint32_t Hwc2TestLayer::getZOrder() const
+{
+    return mZOrder;
+}
+
+bool Hwc2TestLayer::advanceBlendMode()
+{
+    return mBlendMode.advance();
+}
+
+bool Hwc2TestLayer::advanceBufferArea()
+{
+    return mBufferArea.advance();
+}
+
+bool Hwc2TestLayer::advanceColor()
+{
+    return mColor.advance();
+}
+
+bool Hwc2TestLayer::advanceComposition()
+{
+    return mComposition.advance();
+}
+
+bool Hwc2TestLayer::advanceCursorPosition()
+{
+    return mDisplayFrame.advance();
+}
+
+bool Hwc2TestLayer::advanceDataspace()
+{
+    return mDataspace.advance();
+}
+
+bool Hwc2TestLayer::advanceDisplayFrame()
+{
+    return mDisplayFrame.advance();
+}
+
+bool Hwc2TestLayer::advancePlaneAlpha()
+{
+    return mPlaneAlpha.advance();
+}
+
+bool Hwc2TestLayer::advanceSourceCrop()
+{
+    return mSourceCrop.advance();
+}
+
+bool Hwc2TestLayer::advanceSurfaceDamage()
+{
+    return mSurfaceDamage.advance();
+}
+
+bool Hwc2TestLayer::advanceTransform()
+{
+    return mTransform.advance();
+}
+
+bool Hwc2TestLayer::advanceVisibleRegion()
+{
+    if (mPlaneAlpha.advance())
+        return true;
+    return mDisplayFrame.advance();
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h
new file mode 100644
index 0000000..0e7dd22
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HWC2_TEST_LAYER_H
+#define _HWC2_TEST_LAYER_H
+
+#include <android-base/unique_fd.h>
+#include <unordered_map>
+
+#include "Hwc2TestBuffer.h"
+#include "Hwc2TestProperties.h"
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+class Hwc2TestLayer {
+public:
+    Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea);
+
+    Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea,
+            const std::unordered_map<Hwc2TestPropertyName,
+            Hwc2TestCoverage>& coverage_exceptions);
+
+    std::string dump() const;
+
+    int getBuffer(buffer_handle_t* outHandle,
+            android::base::unique_fd* outAcquireFence);
+    int getBuffer(buffer_handle_t* outHandle, int32_t* outAcquireFence);
+
+    void setZOrder(uint32_t zOrder);
+    void setVisibleRegion(const android::Region& region);
+
+    void reset();
+    bool advance();
+
+    hwc2_blend_mode_t      getBlendMode() const;
+    Area                   getBufferArea() const;
+    hwc_color_t            getColor() const;
+    hwc2_composition_t     getComposition() const;
+    hwc_rect_t             getCursorPosition() const;
+    android_dataspace_t    getDataspace() const;
+    hwc_rect_t             getDisplayFrame() const;
+    float                  getPlaneAlpha() const;
+    hwc_frect_t            getSourceCrop() const;
+    hwc_region_t           getSurfaceDamage() const;
+    hwc_transform_t        getTransform() const;
+    hwc_region_t           getVisibleRegion() const;
+    uint32_t               getZOrder() const;
+
+    bool advanceBlendMode();
+    bool advanceBufferArea();
+    bool advanceColor();
+    bool advanceComposition();
+    bool advanceCursorPosition();
+    bool advanceDataspace();
+    bool advanceDisplayFrame();
+    bool advancePlaneAlpha();
+    bool advanceSourceCrop();
+    bool advanceSurfaceDamage();
+    bool advanceTransform();
+    bool advanceVisibleRegion();
+
+private:
+    std::array<Hwc2TestContainer*, 10> mProperties = {{
+        &mTransform, &mColor, &mDataspace, &mPlaneAlpha, &mSourceCrop,
+        &mSurfaceDamage, &mBlendMode, &mBufferArea, &mDisplayFrame,
+        &mComposition
+    }};
+
+    Hwc2TestBuffer mBuffer;
+
+    Hwc2TestBlendMode mBlendMode;
+    Hwc2TestBufferArea mBufferArea;
+    Hwc2TestColor mColor;
+    Hwc2TestComposition mComposition;
+    Hwc2TestDataspace mDataspace;
+    Hwc2TestDisplayFrame mDisplayFrame;
+    Hwc2TestPlaneAlpha mPlaneAlpha;
+    Hwc2TestSourceCrop mSourceCrop;
+    Hwc2TestSurfaceDamage mSurfaceDamage;
+    Hwc2TestTransform mTransform;
+    Hwc2TestVisibleRegion mVisibleRegion;
+
+    uint32_t mZOrder = UINT32_MAX;
+};
+
+#endif /* ifndef _HWC2_TEST_LAYER_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp
new file mode 100644
index 0000000..495ef79
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp
@@ -0,0 +1,281 @@
+/* * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sstream>
+#include <gtest/gtest.h>
+
+#include "Hwc2TestLayers.h"
+
+Hwc2TestLayers::Hwc2TestLayers(const std::vector<hwc2_layer_t>& layers,
+        Hwc2TestCoverage coverage, const Area& displayArea)
+    : Hwc2TestLayers(layers, coverage, displayArea,
+            std::unordered_map<Hwc2TestPropertyName, Hwc2TestCoverage>()) { }
+
+Hwc2TestLayers::Hwc2TestLayers(const std::vector<hwc2_layer_t>& layers,
+        Hwc2TestCoverage coverage, const Area& displayArea,
+        const std::unordered_map<Hwc2TestPropertyName,
+        Hwc2TestCoverage>& coverageExceptions)
+    : mDisplayArea(displayArea)
+{
+    for (auto layer : layers) {
+        mTestLayers.emplace(std::piecewise_construct,
+                std::forward_as_tuple(layer),
+                std::forward_as_tuple(coverage, displayArea, coverageExceptions));
+    }
+
+    /* Iterate over the layers in order and assign z orders in the same order.
+     * This allows us to iterate over z orders in the same way when computing
+     * visible regions */
+    uint32_t nextZOrder = layers.size();
+
+    for (auto& testLayer : mTestLayers) {
+        testLayer.second.setZOrder(nextZOrder--);
+    }
+
+    setVisibleRegions();
+}
+
+std::string Hwc2TestLayers::dump() const
+{
+    std::stringstream dmp;
+    for (auto& testLayer : mTestLayers) {
+        dmp << testLayer.second.dump();
+    }
+    return dmp.str();
+}
+
+void Hwc2TestLayers::reset()
+{
+    for (auto& testLayer : mTestLayers) {
+        testLayer.second.reset();
+    }
+
+    setVisibleRegions();
+}
+
+bool Hwc2TestLayers::advance()
+{
+    auto itr = mTestLayers.begin();
+    bool optimized;
+
+    while (itr != mTestLayers.end()) {
+        if (itr->second.advance()) {
+            optimized = setVisibleRegions();
+            if (!mOptimize || optimized)
+                return true;
+            itr = mTestLayers.begin();
+        } else {
+            itr->second.reset();
+            ++itr;
+        }
+    }
+    return false;
+}
+
+bool Hwc2TestLayers::advanceVisibleRegions()
+{
+    auto itr = mTestLayers.begin();
+    bool optimized;
+
+    while (itr != mTestLayers.end()) {
+        if (itr->second.advanceVisibleRegion()) {
+            optimized = setVisibleRegions();
+            if (!mOptimize || optimized)
+                return true;
+            itr = mTestLayers.begin();
+        } else {
+            itr->second.reset();
+            ++itr;
+        }
+    }
+    return false;
+}
+
+/* Removes layouts that do not cover the entire display.
+ * Also removes layouts where a layer is completely blocked from view.
+ */
+bool Hwc2TestLayers::optimizeLayouts()
+{
+    mOptimize = true;
+
+    if (setVisibleRegions())
+        return true;
+    return advance();
+}
+
+bool Hwc2TestLayers::contains(hwc2_layer_t layer) const
+{
+    return mTestLayers.count(layer) != 0;
+}
+
+int Hwc2TestLayers::getBuffer(hwc2_layer_t layer, buffer_handle_t* outHandle,
+        int32_t* outAcquireFence)
+{
+    if (mTestLayers.count(layer) == 0) {
+        []() { GTEST_FAIL(); }();
+    }
+    return mTestLayers.at(layer).getBuffer(outHandle, outAcquireFence);
+}
+
+hwc2_blend_mode_t Hwc2TestLayers::getBlendMode(hwc2_layer_t layer) const
+{
+    if (mTestLayers.count(layer) == 0) {
+        []() { GTEST_FAIL(); }();
+    }
+    return mTestLayers.at(layer).getBlendMode();
+}
+
+Area Hwc2TestLayers::getBufferArea(hwc2_layer_t layer) const
+{
+    auto testLayer = mTestLayers.find(layer);
+    if (testLayer == mTestLayers.end())
+        [] () { GTEST_FAIL(); }();
+    return testLayer->second.getBufferArea();
+}
+
+hwc_color_t Hwc2TestLayers::getColor(hwc2_layer_t layer) const
+{
+    if (mTestLayers.count(layer) == 0) {
+        []() { GTEST_FAIL(); }();
+    }
+    return mTestLayers.at(layer).getColor();
+}
+
+hwc2_composition_t Hwc2TestLayers::getComposition(hwc2_layer_t layer) const
+{
+    if (mTestLayers.count(layer) == 0) {
+        []() { GTEST_FAIL(); }();
+    }
+    return mTestLayers.at(layer).getComposition();
+}
+
+hwc_rect_t Hwc2TestLayers::getCursorPosition(hwc2_layer_t layer) const
+{
+    if (mTestLayers.count(layer) == 0) {
+        []() { GTEST_FAIL(); }();
+    }
+    return mTestLayers.at(layer).getCursorPosition();
+}
+
+android_dataspace_t Hwc2TestLayers::getDataspace(hwc2_layer_t layer) const
+{
+    if (mTestLayers.count(layer) == 0) {
+        []() { GTEST_FAIL(); }();
+    }
+    return mTestLayers.at(layer).getDataspace();
+}
+
+hwc_rect_t Hwc2TestLayers::getDisplayFrame(hwc2_layer_t layer) const
+{
+    if (mTestLayers.count(layer) == 0) {
+        []() { GTEST_FAIL(); }();
+    }
+    return mTestLayers.at(layer).getDisplayFrame();
+}
+
+float Hwc2TestLayers::getPlaneAlpha(hwc2_layer_t layer) const
+{
+    if (mTestLayers.count(layer) == 0) {
+        []() { GTEST_FAIL(); }();
+    }
+    return mTestLayers.at(layer).getPlaneAlpha();
+}
+
+hwc_frect_t Hwc2TestLayers::getSourceCrop(hwc2_layer_t layer) const
+{
+    if (mTestLayers.count(layer) == 0) {
+        []() { GTEST_FAIL(); }();
+    }
+    return mTestLayers.at(layer).getSourceCrop();
+}
+
+hwc_region_t Hwc2TestLayers::getSurfaceDamage(hwc2_layer_t layer) const
+{
+    if (mTestLayers.count(layer) == 0) {
+        []() { GTEST_FAIL(); }();
+    }
+    return mTestLayers.at(layer).getSurfaceDamage();
+}
+
+hwc_transform_t Hwc2TestLayers::getTransform(hwc2_layer_t layer) const
+{
+    if (mTestLayers.count(layer) == 0) {
+        []() { GTEST_FAIL(); }();
+    }
+    return mTestLayers.at(layer).getTransform();
+}
+
+hwc_region_t Hwc2TestLayers::getVisibleRegion(hwc2_layer_t layer) const
+{
+    if (mTestLayers.count(layer) == 0) {
+        []() { GTEST_FAIL(); }();
+    }
+    return mTestLayers.at(layer).getVisibleRegion();
+}
+
+uint32_t Hwc2TestLayers::getZOrder(hwc2_layer_t layer) const
+{
+    if (mTestLayers.count(layer) == 0) {
+        []() { GTEST_FAIL(); }();
+    }
+    return mTestLayers.at(layer).getZOrder();
+}
+
+/* Sets the visible regions for a display. Returns false if the layers do not
+ * cover the entire display or if a layer is not visible */
+bool Hwc2TestLayers::setVisibleRegions()
+{
+    /* The region of the display that is covered by layers above the current
+     * layer */
+    android::Region aboveOpaqueLayers;
+
+    bool optimized = true;
+
+    /* Iterate over test layers from max z order to min z order. */
+    for (auto& testLayer : mTestLayers) {
+        android::Region visibleRegion;
+
+        /* Set the visible region of this layer */
+        const hwc_rect_t displayFrame = testLayer.second.getDisplayFrame();
+
+        visibleRegion.set(android::Rect(displayFrame.left, displayFrame.top,
+                displayFrame.right, displayFrame.bottom));
+
+        /* Remove the area covered by opaque layers above this layer
+         * from this layer's visible region */
+        visibleRegion.subtractSelf(aboveOpaqueLayers);
+
+        testLayer.second.setVisibleRegion(visibleRegion);
+
+        /* If a layer is not visible, return false */
+        if (visibleRegion.isEmpty())
+            optimized = false;
+
+        /* If this layer is opaque, store the region it covers */
+        if (testLayer.second.getPlaneAlpha() == 1.0f)
+            aboveOpaqueLayers.orSelf(visibleRegion);
+    }
+
+    /* If the opaque region does not cover the entire display return false */
+    if (!aboveOpaqueLayers.isRect())
+        return false;
+
+    const auto rect = aboveOpaqueLayers.begin();
+    if (rect->left != 0 || rect->top != 0 || rect->right != mDisplayArea.width
+            || rect->bottom != mDisplayArea.height)
+        return false;
+
+    return optimized;
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h
new file mode 100644
index 0000000..d95a91f
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HWC2_TEST_LAYERS_H
+#define _HWC2_TEST_LAYERS_H
+
+#include <map>
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include "Hwc2TestProperties.h"
+#include "Hwc2TestLayer.h"
+
+class Hwc2TestLayers {
+public:
+    Hwc2TestLayers(const std::vector<hwc2_layer_t>& layers,
+            Hwc2TestCoverage coverage, const Area& displayArea);
+
+    Hwc2TestLayers(const std::vector<hwc2_layer_t>& layers,
+            Hwc2TestCoverage coverage, const Area& displayArea,
+            const std::unordered_map<Hwc2TestPropertyName,
+            Hwc2TestCoverage>& coverageExceptions);
+
+    std::string dump() const;
+
+    void reset();
+
+    bool advance();
+    bool advanceVisibleRegions();
+
+    /* Test cases with multiple layers and property values can take quite some
+     * time to run. A significant amount of time can be spent on test cases
+     * where one layer is changing property values but is not visible. To
+     * decrease runtime, this function can be called. Removes layouts where a
+     * layer is completely blocked from view. It also removes layouts that do
+     * not cover the entire display.*/
+    bool optimizeLayouts();
+
+    bool contains(hwc2_layer_t layer) const;
+
+    int  getBuffer(hwc2_layer_t layer, buffer_handle_t* outHandle,
+            int32_t* outAcquireFence);
+
+    hwc2_blend_mode_t      getBlendMode(hwc2_layer_t layer) const;
+    Area                   getBufferArea(hwc2_layer_t layer) const;
+    hwc_color_t            getColor(hwc2_layer_t layer) const;
+    hwc2_composition_t     getComposition(hwc2_layer_t layer) const;
+    hwc_rect_t             getCursorPosition(hwc2_layer_t layer) const;
+    android_dataspace_t    getDataspace(hwc2_layer_t layer) const;
+    hwc_rect_t             getDisplayFrame(hwc2_layer_t layer) const;
+    android_pixel_format_t getFormat(hwc2_layer_t layer) const;
+    float                  getPlaneAlpha(hwc2_layer_t layer) const;
+    hwc_frect_t            getSourceCrop(hwc2_layer_t layer) const;
+    hwc_region_t           getSurfaceDamage(hwc2_layer_t layer) const;
+    hwc_transform_t        getTransform(hwc2_layer_t layer) const;
+    hwc_region_t           getVisibleRegion(hwc2_layer_t layer) const;
+    uint32_t               getZOrder(hwc2_layer_t layer) const;
+
+private:
+    bool setVisibleRegions();
+
+    std::map<hwc2_layer_t, Hwc2TestLayer> mTestLayers;
+
+    Area mDisplayArea;
+
+    bool mOptimize = false;
+};
+
+#endif /* ifndef _HWC2_TEST_LAYERS_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
new file mode 100644
index 0000000..b5522de
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
@@ -0,0 +1,782 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sstream>
+#include <cutils/log.h>
+#include <ui/Rect.h>
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+#include "Hwc2TestBuffer.h"
+#include "Hwc2TestProperties.h"
+
+Hwc2TestBufferArea::Hwc2TestBufferArea(Hwc2TestCoverage coverage,
+        const Area& displayArea)
+    : Hwc2TestProperty(mBufferAreas, mCompositionSupport),
+      mScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteScalars:
+            (coverage == Hwc2TestCoverage::Basic)? mBasicScalars:
+            mDefaultScalars),
+      mDisplayArea(displayArea)
+{
+    update();
+}
+
+std::string Hwc2TestBufferArea::dump() const
+{
+    std::stringstream dmp;
+    const Area& curr = get();
+    dmp << "\tbuffer area: width " << curr.width << ", height " << curr.height
+            << "\n";
+    return dmp.str();
+}
+
+void Hwc2TestBufferArea::setDependent(Hwc2TestBuffer* buffer)
+{
+    mBuffer = buffer;
+    if (buffer) {
+        buffer->updateBufferArea(get());
+    }
+}
+
+void Hwc2TestBufferArea::setDependent(Hwc2TestSourceCrop* sourceCrop)
+{
+    mSourceCrop = sourceCrop;
+    if (mSourceCrop) {
+        mSourceCrop->updateBufferArea(get());
+    }
+}
+
+void Hwc2TestBufferArea::setDependent(Hwc2TestSurfaceDamage* surfaceDamage)
+{
+    mSurfaceDamage = surfaceDamage;
+    if (mSurfaceDamage) {
+        mSurfaceDamage->updateBufferArea(get());
+    }
+}
+
+void Hwc2TestBufferArea::update()
+{
+    mBufferAreas.clear();
+
+    if (mDisplayArea.width == 0 && mDisplayArea.height == 0) {
+        mBufferAreas.push_back({0, 0});
+        return;
+    }
+
+    for (auto scalar : mScalars) {
+        mBufferAreas.push_back({static_cast<int32_t>(scalar * mDisplayArea.width),
+                static_cast<int32_t>(scalar * mDisplayArea.height)});
+    }
+
+    updateDependents();
+}
+
+void Hwc2TestBufferArea::updateDependents()
+{
+    const Area& curr = get();
+
+    if (mBuffer)
+        mBuffer->updateBufferArea(curr);
+    if (mSourceCrop)
+        mSourceCrop->updateBufferArea(curr);
+    if (mSurfaceDamage)
+        mSurfaceDamage->updateBufferArea(curr);
+}
+
+const std::vector<float> Hwc2TestBufferArea::mDefaultScalars = {
+    1.0f,
+};
+
+const std::vector<float> Hwc2TestBufferArea::mBasicScalars = {
+    1.0f, 0.5f,
+};
+
+const std::vector<float> Hwc2TestBufferArea::mCompleteScalars = {
+    1.0f, 0.75f, 0.5f
+};
+
+
+Hwc2TestBlendMode::Hwc2TestBlendMode(Hwc2TestCoverage coverage)
+    : Hwc2TestProperty(coverage, mCompleteBlendModes, mBasicBlendModes,
+            mDefaultBlendModes, mCompositionSupport) { }
+
+std::string Hwc2TestBlendMode::dump() const
+{
+    std::stringstream dmp;
+    dmp << "\tblend mode: " << getBlendModeName(get()) << "\n";
+    return dmp.str();
+}
+
+void Hwc2TestBlendMode::setDependent(Hwc2TestColor* color)
+{
+    mColor = color;
+    updateDependents();
+}
+
+void Hwc2TestBlendMode::updateDependents()
+{
+    if (mColor)
+        mColor->updateBlendMode(get());
+}
+
+const std::vector<hwc2_blend_mode_t> Hwc2TestBlendMode::mDefaultBlendModes = {
+    HWC2_BLEND_MODE_NONE,
+};
+
+const std::vector<hwc2_blend_mode_t> Hwc2TestBlendMode::mBasicBlendModes = {
+    HWC2_BLEND_MODE_NONE,
+    HWC2_BLEND_MODE_PREMULTIPLIED,
+};
+
+const std::vector<hwc2_blend_mode_t> Hwc2TestBlendMode::mCompleteBlendModes = {
+    HWC2_BLEND_MODE_NONE,
+    HWC2_BLEND_MODE_PREMULTIPLIED,
+    HWC2_BLEND_MODE_COVERAGE,
+};
+
+
+Hwc2TestColor::Hwc2TestColor(Hwc2TestCoverage coverage,
+        hwc2_blend_mode_t blendMode)
+    : Hwc2TestProperty(mColors, mCompositionSupport),
+      mBaseColors((coverage == Hwc2TestCoverage::Complete)? mCompleteBaseColors:
+            (coverage == Hwc2TestCoverage::Basic)? mBasicBaseColors:
+            mDefaultBaseColors),
+      mBlendMode(blendMode)
+{
+    update();
+}
+
+std::string Hwc2TestColor::dump() const
+{
+    std::stringstream dmp;
+    const hwc_color_t& color = get();
+    dmp << "\tcolor: r " << std::to_string(color.r) << ", g "
+            << std::to_string(color.g) << ", b " << std::to_string(color.b)
+            << ", a " << std::to_string(color.a) << "\n";
+    return dmp.str();
+}
+
+void Hwc2TestColor::updateBlendMode(hwc2_blend_mode_t blendMode)
+{
+    mBlendMode = blendMode;
+    update();
+}
+
+void Hwc2TestColor::update()
+{
+    if (mBlendMode != HWC2_BLEND_MODE_PREMULTIPLIED) {
+        mColors = mBaseColors;
+        return;
+    }
+
+    mColors.clear();
+
+    for (const hwc_color_t& baseColor : mBaseColors) {
+        if (baseColor.a >= baseColor.r && baseColor.a >= baseColor.g
+                && baseColor.a >= baseColor.b) {
+            mColors.push_back(baseColor);
+        }
+    }
+
+}
+
+const std::vector<hwc_color_t> Hwc2TestColor::mDefaultBaseColors = {
+    {UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX},
+};
+
+const std::vector<hwc_color_t> Hwc2TestColor::mBasicBaseColors = {
+    {UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX},
+    {        0,         0,         0,         0},
+};
+
+const std::vector<hwc_color_t> Hwc2TestColor::mCompleteBaseColors = {
+    {UINT8_MAX, UINT8_MAX, UINT8_MAX, UINT8_MAX},
+    {UINT8_MAX, UINT8_MAX, UINT8_MAX,         0},
+    {UINT8_MAX, UINT8_MAX,         0, UINT8_MAX},
+    {UINT8_MAX, UINT8_MAX,         0,         0},
+    {UINT8_MAX,         0, UINT8_MAX, UINT8_MAX},
+    {UINT8_MAX,         0, UINT8_MAX,         0},
+    {UINT8_MAX,         0,         0, UINT8_MAX},
+    {UINT8_MAX,         0,         0,         0},
+    {        0, UINT8_MAX, UINT8_MAX, UINT8_MAX},
+    {        0, UINT8_MAX, UINT8_MAX,         0},
+    {        0, UINT8_MAX,         0, UINT8_MAX},
+    {        0, UINT8_MAX,         0,         0},
+    {        0,         0, UINT8_MAX, UINT8_MAX},
+    {        0,         0, UINT8_MAX,         0},
+    {        0,         0,         0, UINT8_MAX},
+    {        0,         0,         0,         0},
+};
+
+
+Hwc2TestComposition::Hwc2TestComposition(Hwc2TestCoverage coverage)
+    : Hwc2TestProperty(coverage, mCompleteCompositions, mBasicCompositions,
+            mDefaultCompositions, mCompositionSupport) { }
+
+std::string Hwc2TestComposition::dump() const
+{
+    std::stringstream dmp;
+    dmp << "\tcomposition: " << getCompositionName(get()) << "\n";
+    return dmp.str();
+}
+
+const std::vector<hwc2_composition_t> Hwc2TestComposition::mDefaultCompositions = {
+    HWC2_COMPOSITION_DEVICE,
+};
+
+const std::vector<hwc2_composition_t> Hwc2TestComposition::mBasicCompositions = {
+    HWC2_COMPOSITION_CLIENT,
+    HWC2_COMPOSITION_DEVICE,
+};
+
+const std::vector<hwc2_composition_t> Hwc2TestComposition::mCompleteCompositions = {
+    HWC2_COMPOSITION_CLIENT,
+    HWC2_COMPOSITION_DEVICE,
+    HWC2_COMPOSITION_SOLID_COLOR,
+    HWC2_COMPOSITION_CURSOR,
+    HWC2_COMPOSITION_SIDEBAND,
+};
+
+
+Hwc2TestDataspace::Hwc2TestDataspace(Hwc2TestCoverage coverage)
+    : Hwc2TestProperty(coverage, completeDataspaces, basicDataspaces,
+            defaultDataspaces, mCompositionSupport) { }
+
+std::string Hwc2TestDataspace::dump() const
+{
+    std::stringstream dmp;
+    dmp << "\tdataspace: " << get() << "\n";
+    return dmp.str();
+}
+
+const std::vector<android_dataspace_t> Hwc2TestDataspace::defaultDataspaces = {
+    HAL_DATASPACE_UNKNOWN,
+};
+
+const std::vector<android_dataspace_t> Hwc2TestDataspace::basicDataspaces = {
+    HAL_DATASPACE_UNKNOWN,
+    HAL_DATASPACE_V0_SRGB,
+};
+
+const std::vector<android_dataspace_t> Hwc2TestDataspace::completeDataspaces = {
+    HAL_DATASPACE_UNKNOWN,
+    HAL_DATASPACE_ARBITRARY,
+    HAL_DATASPACE_STANDARD_SHIFT,
+    HAL_DATASPACE_STANDARD_MASK,
+    HAL_DATASPACE_STANDARD_UNSPECIFIED,
+    HAL_DATASPACE_STANDARD_BT709,
+    HAL_DATASPACE_STANDARD_BT601_625,
+    HAL_DATASPACE_STANDARD_BT601_625_UNADJUSTED,
+    HAL_DATASPACE_STANDARD_BT601_525,
+    HAL_DATASPACE_STANDARD_BT601_525_UNADJUSTED,
+    HAL_DATASPACE_STANDARD_BT2020,
+    HAL_DATASPACE_STANDARD_BT2020_CONSTANT_LUMINANCE,
+    HAL_DATASPACE_STANDARD_BT470M,
+    HAL_DATASPACE_STANDARD_FILM,
+    HAL_DATASPACE_TRANSFER_SHIFT,
+    HAL_DATASPACE_TRANSFER_MASK,
+    HAL_DATASPACE_TRANSFER_UNSPECIFIED,
+    HAL_DATASPACE_TRANSFER_LINEAR,
+    HAL_DATASPACE_TRANSFER_SRGB,
+    HAL_DATASPACE_TRANSFER_SMPTE_170M,
+    HAL_DATASPACE_TRANSFER_GAMMA2_2,
+    HAL_DATASPACE_TRANSFER_GAMMA2_8,
+    HAL_DATASPACE_TRANSFER_ST2084,
+    HAL_DATASPACE_TRANSFER_HLG,
+    HAL_DATASPACE_RANGE_SHIFT,
+    HAL_DATASPACE_RANGE_MASK,
+    HAL_DATASPACE_RANGE_UNSPECIFIED,
+    HAL_DATASPACE_RANGE_FULL,
+    HAL_DATASPACE_RANGE_LIMITED,
+    HAL_DATASPACE_SRGB_LINEAR,
+    HAL_DATASPACE_V0_SRGB_LINEAR,
+    HAL_DATASPACE_SRGB,
+    HAL_DATASPACE_V0_SRGB,
+    HAL_DATASPACE_JFIF,
+    HAL_DATASPACE_V0_JFIF,
+    HAL_DATASPACE_BT601_625,
+    HAL_DATASPACE_V0_BT601_625,
+    HAL_DATASPACE_BT601_525,
+    HAL_DATASPACE_V0_BT601_525,
+    HAL_DATASPACE_BT709,
+    HAL_DATASPACE_V0_BT709,
+    HAL_DATASPACE_DEPTH,
+};
+
+
+Hwc2TestDisplayDimension::Hwc2TestDisplayDimension(Hwc2TestCoverage coverage)
+    : Hwc2TestProperty(
+            (coverage == Hwc2TestCoverage::Complete)? mCompleteDisplayDimensions:
+            (coverage == Hwc2TestCoverage::Basic)? mBasicDisplayDimensions:
+            mDefaultDisplayDimensions, mCompositionSupport) { }
+
+std::string Hwc2TestDisplayDimension::dump() const
+{
+    std::stringstream dmp;
+    const UnsignedArea& curr = get();
+    dmp << "\tdisplay dimension: " << curr.width<< " x " << curr.height<< "\n";
+    return dmp.str();
+}
+
+void Hwc2TestDisplayDimension::setDependent(Hwc2TestBuffer* buffer)
+{
+    mBuffer = buffer;
+    updateDependents();
+}
+
+void Hwc2TestDisplayDimension::updateDependents()
+{
+    const UnsignedArea& curr = get();
+
+    if (mBuffer)
+        mBuffer->updateBufferArea({static_cast<int32_t>(curr.width),
+                static_cast<int32_t>(curr.height)});
+}
+
+const std::vector<UnsignedArea>
+        Hwc2TestDisplayDimension::mDefaultDisplayDimensions = {
+    {1920, 1080},
+};
+
+const std::vector<UnsignedArea>
+        Hwc2TestDisplayDimension::mBasicDisplayDimensions = {
+    {640, 480},
+    {1280, 720},
+    {1920, 1080},
+    {1920, 1200},
+};
+
+const std::vector<UnsignedArea>
+        Hwc2TestDisplayDimension::mCompleteDisplayDimensions = {
+    {320, 240},
+    {480, 320},
+    {640, 480},
+    {1280, 720},
+    {1920, 1080},
+    {1920, 1200},
+    {2560, 1440},
+    {2560, 1600},
+    {3840, 2160},
+    {4096, 2160},
+};
+
+
+Hwc2TestDisplayFrame::Hwc2TestDisplayFrame(Hwc2TestCoverage coverage,
+        const Area& displayArea)
+    : Hwc2TestProperty(mDisplayFrames, mCompositionSupport),
+      mFrectScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteFrectScalars:
+            (coverage == Hwc2TestCoverage::Basic)? mBasicFrectScalars:
+            mDefaultFrectScalars),
+      mDisplayArea(displayArea)
+{
+    update();
+}
+
+std::string Hwc2TestDisplayFrame::dump() const
+{
+    std::stringstream dmp;
+    const hwc_rect_t& displayFrame = get();
+    dmp << "\tdisplay frame: left " << displayFrame.left << ", top "
+            << displayFrame.top << ", right " << displayFrame.right
+            << ", bottom " << displayFrame.bottom << "\n";
+    return dmp.str();
+}
+
+void Hwc2TestDisplayFrame::update()
+{
+    mDisplayFrames.clear();
+
+    if (mDisplayArea.width == 0 && mDisplayArea.height == 0) {
+        mDisplayFrames.push_back({0, 0, 0, 0});
+        return;
+    }
+
+    for (const auto& frectScalar : mFrectScalars) {
+        mDisplayFrames.push_back({
+                static_cast<int>(frectScalar.left * mDisplayArea.width),
+                static_cast<int>(frectScalar.top * mDisplayArea.height),
+                static_cast<int>(frectScalar.right * mDisplayArea.width),
+                static_cast<int>(frectScalar.bottom * mDisplayArea.height)});
+    }
+}
+
+const std::vector<hwc_frect_t> Hwc2TestDisplayFrame::mDefaultFrectScalars = {
+    {0.0, 0.0, 1.0, 1.0},
+};
+
+const std::vector<hwc_frect_t> Hwc2TestDisplayFrame::mBasicFrectScalars = {
+    {0.0, 0.0, 1.0, 1.0},
+    {0.0, 0.0, 1.0, 0.05},
+    {0.0, 0.95, 1.0, 1.0},
+};
+
+const std::vector<hwc_frect_t> Hwc2TestDisplayFrame::mCompleteFrectScalars = {
+    {0.0, 0.0, 1.0, 1.0},
+    {0.0, 0.05, 1.0, 0.95},
+    {0.0, 0.05, 1.0, 1.0},
+    {0.0, 0.0, 1.0, 0.05},
+    {0.0, 0.95, 1.0, 1.0},
+    {0.25, 0.0, 0.75, 0.35},
+    {0.25, 0.25, 0.75, 0.75},
+};
+
+
+Hwc2TestPlaneAlpha::Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage)
+    : Hwc2TestProperty(coverage, mCompletePlaneAlphas, mBasicPlaneAlphas,
+            mDefaultPlaneAlphas, mCompositionSupport) { }
+
+std::string Hwc2TestPlaneAlpha::dump() const
+{
+    std::stringstream dmp;
+    dmp << "\tplane alpha: " << get() << "\n";
+    return dmp.str();
+}
+
+const std::vector<float> Hwc2TestPlaneAlpha::mDefaultPlaneAlphas = {
+    1.0f,
+};
+
+const std::vector<float> Hwc2TestPlaneAlpha::mBasicPlaneAlphas = {
+    1.0f, 0.0f,
+};
+
+const std::vector<float> Hwc2TestPlaneAlpha::mCompletePlaneAlphas = {
+    1.0f, 0.75f, 0.5f, 0.25f, 0.0f,
+};
+
+
+Hwc2TestSourceCrop::Hwc2TestSourceCrop(Hwc2TestCoverage coverage,
+        const Area& bufferArea)
+    : Hwc2TestProperty(mSourceCrops, mCompositionSupport),
+      mFrectScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteFrectScalars:
+            (coverage == Hwc2TestCoverage::Basic)? mBasicFrectScalars:
+            mDefaultFrectScalars),
+      mBufferArea(bufferArea)
+{
+    update();
+}
+
+std::string Hwc2TestSourceCrop::dump() const
+{
+    std::stringstream dmp;
+    const hwc_frect_t& sourceCrop = get();
+    dmp << "\tsource crop: left " << sourceCrop.left << ", top "
+            << sourceCrop.top << ", right " << sourceCrop.right << ", bottom "
+            << sourceCrop.bottom << "\n";
+    return dmp.str();
+}
+
+void Hwc2TestSourceCrop::updateBufferArea(const Area& bufferArea)
+{
+    mBufferArea = bufferArea;
+    update();
+}
+
+void Hwc2TestSourceCrop::update()
+{
+    mSourceCrops.clear();
+
+    if (mBufferArea.width == 0 && mBufferArea.height == 0) {
+        mSourceCrops.push_back({0, 0, 0, 0});
+        return;
+    }
+
+    for (const auto& frectScalar : mFrectScalars) {
+        mSourceCrops.push_back({
+                frectScalar.left * mBufferArea.width,
+                frectScalar.top * mBufferArea.height,
+                frectScalar.right * mBufferArea.width,
+                frectScalar.bottom * mBufferArea.height});
+    }
+}
+
+const std::vector<hwc_frect_t> Hwc2TestSourceCrop::mDefaultFrectScalars = {
+    {0.0, 0.0, 1.0, 1.0},
+};
+
+const std::vector<hwc_frect_t> Hwc2TestSourceCrop::mBasicFrectScalars = {
+    {0.0, 0.0, 1.0, 1.0},
+    {0.0, 0.0, 0.5, 0.5},
+    {0.5, 0.5, 1.0, 1.0},
+};
+
+const std::vector<hwc_frect_t> Hwc2TestSourceCrop::mCompleteFrectScalars = {
+    {0.0, 0.0, 1.0, 1.0},
+    {0.0, 0.0, 0.5, 0.5},
+    {0.5, 0.5, 1.0, 1.0},
+    {0.0, 0.0, 0.25, 0.25},
+    {0.25, 0.25, 0.75, 0.75},
+};
+
+
+Hwc2TestSurfaceDamage::Hwc2TestSurfaceDamage(Hwc2TestCoverage coverage)
+    : Hwc2TestProperty(mSurfaceDamages, mCompositionSupport),
+      mRegionScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteRegionScalars:
+            (coverage == Hwc2TestCoverage::Basic)? mBasicRegionScalars:
+            mDefaultRegionScalars)
+{
+    update();
+}
+
+Hwc2TestSurfaceDamage::~Hwc2TestSurfaceDamage()
+{
+    freeSurfaceDamages();
+}
+
+std::string Hwc2TestSurfaceDamage::dump() const
+{
+    std::stringstream dmp;
+
+    const hwc_region_t& curr = get();
+    dmp << "\tsurface damage: region count " << curr.numRects << "\n";
+    for (size_t i = 0; i < curr.numRects; i++) {
+        const hwc_rect_t& rect = curr.rects[i];
+        dmp << "\t\trect: left " << rect.left << ", top " << rect.top
+                << ", right " << rect.right << ", bottom " << rect.bottom << "\n";
+    }
+
+    return dmp.str();
+}
+
+void Hwc2TestSurfaceDamage::updateBufferArea(const Area& bufferArea)
+{
+    mBufferArea = bufferArea;
+    update();
+}
+
+void Hwc2TestSurfaceDamage::update()
+{
+    freeSurfaceDamages();
+
+    if (mBufferArea.width == 0 && mBufferArea.height == 0) {
+        mSurfaceDamages.push_back({0, nullptr});
+        return;
+    }
+
+    hwc_region_t damage;
+
+    for (const auto& regionScalar : mRegionScalars) {
+        damage.numRects = regionScalar.size();
+
+        if (damage.numRects > 0) {
+            hwc_rect_t* rects = new hwc_rect_t[damage.numRects];
+            if (!rects) {
+                ALOGW("failed to allocate new hwc_rect_t array");
+                continue;
+            }
+
+            for (size_t i = 0; i < damage.numRects; i++) {
+                rects[i].left = regionScalar[i].left * mBufferArea.width;
+                rects[i].top = regionScalar[i].top * mBufferArea.height;
+                rects[i].right = regionScalar[i].right * mBufferArea.width;
+                rects[i].bottom = regionScalar[i].bottom * mBufferArea.height;
+            }
+
+            damage.rects = static_cast<hwc_rect_t const*>(rects);
+        } else {
+            damage.rects = nullptr;
+        }
+
+        mSurfaceDamages.push_back(damage);
+    }
+}
+
+void Hwc2TestSurfaceDamage::freeSurfaceDamages()
+{
+    for (const auto& surfaceDamage : mSurfaceDamages) {
+        if (surfaceDamage.numRects > 0 && surfaceDamage.rects)
+            delete[] surfaceDamage.rects;
+    }
+    mSurfaceDamages.clear();
+}
+
+const std::vector<std::vector<hwc_frect_t>> Hwc2TestSurfaceDamage::mDefaultRegionScalars = {
+    {{}},
+};
+
+const std::vector<std::vector<hwc_frect_t>> Hwc2TestSurfaceDamage::mBasicRegionScalars = {
+    {{}},
+    {{0.0, 0.0, 1.0, 1.0}},
+};
+
+const std::vector<std::vector<hwc_frect_t>> Hwc2TestSurfaceDamage::mCompleteRegionScalars = {
+    {{}},
+    {{0.0, 0.0, 1.0, 1.0}},
+    {{0.0, 0.0, 0.5, 0.5}, {0.5, 0.5, 1.0, 1.0}},
+};
+
+
+Hwc2TestTransform::Hwc2TestTransform(Hwc2TestCoverage coverage)
+    : Hwc2TestProperty(coverage, mCompleteTransforms, mBasicTransforms,
+            mDefaultTransforms, mCompositionSupport) { }
+
+std::string Hwc2TestTransform::dump() const
+{
+    std::stringstream dmp;
+    dmp << "\ttransform: " << getTransformName(get()) << "\n";
+    return dmp.str();
+}
+
+const std::vector<hwc_transform_t> Hwc2TestTransform::mDefaultTransforms = {
+    static_cast<hwc_transform_t>(0),
+};
+
+const std::vector<hwc_transform_t> Hwc2TestTransform::mBasicTransforms = {
+    static_cast<hwc_transform_t>(0),
+    HWC_TRANSFORM_FLIP_H,
+    HWC_TRANSFORM_FLIP_V,
+    HWC_TRANSFORM_ROT_90,
+};
+
+const std::vector<hwc_transform_t> Hwc2TestTransform::mCompleteTransforms = {
+    static_cast<hwc_transform_t>(0),
+    HWC_TRANSFORM_FLIP_H,
+    HWC_TRANSFORM_FLIP_V,
+    HWC_TRANSFORM_ROT_90,
+    HWC_TRANSFORM_ROT_180,
+    HWC_TRANSFORM_ROT_270,
+    HWC_TRANSFORM_FLIP_H_ROT_90,
+    HWC_TRANSFORM_FLIP_V_ROT_90,
+};
+
+
+Hwc2TestVisibleRegion::~Hwc2TestVisibleRegion()
+{
+    release();
+}
+
+std::string Hwc2TestVisibleRegion::dump() const
+{
+    std::stringstream dmp;
+
+    const hwc_region_t& curr = get();
+    dmp << "\tvisible region: region count " << curr.numRects << "\n";
+    for (size_t i = 0; i < curr.numRects; i++) {
+        const hwc_rect_t& rect = curr.rects[i];
+        dmp << "\t\trect: left " << rect.left << ", top " << rect.top
+                << ", right " << rect.right << ", bottom " << rect.bottom << "\n";
+    }
+
+    return dmp.str();
+}
+
+void Hwc2TestVisibleRegion::set(const android::Region& visibleRegion)
+{
+    release();
+
+    size_t size = 0;
+    const android::Rect* rects = visibleRegion.getArray(&size);
+
+    mVisibleRegion.numRects = size;
+    mVisibleRegion.rects = nullptr;
+
+    if (size > 0) {
+        hwc_rect_t* hwcRects = new hwc_rect_t[size];
+        for (size_t i = 0; i < size; i++) {
+            hwcRects[i].left = rects[i].left;
+            hwcRects[i].top = rects[i].top;
+            hwcRects[i].right = rects[i].right;
+            hwcRects[i].bottom = rects[i].bottom;
+        }
+        mVisibleRegion.rects = hwcRects;
+    }
+}
+
+hwc_region_t Hwc2TestVisibleRegion::get() const
+{
+    return mVisibleRegion;
+}
+
+void Hwc2TestVisibleRegion::release()
+{
+    if (mVisibleRegion.numRects > 0 && mVisibleRegion.rects)
+        delete[] mVisibleRegion.rects;
+    mVisibleRegion.rects = nullptr;
+    mVisibleRegion.numRects = 0;
+}
+
+/* Identifies which layer properties are supported by each composition type.
+ * hwc2_composition_t values range from:
+ *  HWC2_COMPOSITION_INVALID = 0,
+ *  HWC2_COMPOSITION_CLIENT = 1,
+ *  HWC2_COMPOSITION_DEVICE = 2,
+ *  HWC2_COMPOSITION_SOLID_COLOR = 3,
+ *  HWC2_COMPOSITION_CURSOR = 4,
+ *  HWC2_COMPOSITION_SIDEBAND = 5,
+ *
+ * Each property array can be indexed by a hwc2_composition_t value.
+ * By using an array instead of a more complex data structure, runtimes for
+ * some test cases showed a noticeable improvement.
+ */
+
+/*  INVALID  CLIENT   DEVICE   COLOR    CURSOR   SIDEBAND */
+const std::array<bool, 6> Hwc2TestBufferArea::mCompositionSupport = {{
+    false,   true,    true,    false,   true,    true,
+}};
+
+/*  INVALID  CLIENT   DEVICE   COLOR    CURSOR   SIDEBAND */
+const std::array<bool, 6> Hwc2TestBlendMode::mCompositionSupport = {{
+    false,   true,    true,    false,   true,    true,
+}};
+
+/*  INVALID  CLIENT   DEVICE   COLOR    CURSOR   SIDEBAND */
+const std::array<bool, 6> Hwc2TestColor::mCompositionSupport = {{
+    false,   false,   false,   true,    false,   false,
+}};
+
+/*  INVALID  CLIENT   DEVICE   COLOR    CURSOR   SIDEBAND */
+const std::array<bool, 6> Hwc2TestComposition::mCompositionSupport = {{
+    false,   true,    true,    true,    true,    true,
+}};
+
+/*  INVALID  CLIENT   DEVICE   COLOR    CURSOR   SIDEBAND */
+const std::array<bool, 6> Hwc2TestDataspace::mCompositionSupport = {{
+    false,   true,    true,    true,    true,    false,
+}};
+
+/*  INVALID  CLIENT   DEVICE   COLOR    CURSOR   SIDEBAND */
+const std::array<bool, 6> Hwc2TestDisplayDimension::mCompositionSupport = {{
+    false,   true,    true,    true,    true,    true,
+}};
+
+/*  INVALID  CLIENT   DEVICE   COLOR    CURSOR   SIDEBAND */
+const std::array<bool, 6> Hwc2TestDisplayFrame::mCompositionSupport = {{
+    false,   true,    true,    true,    false,   true,
+}};
+
+/*  INVALID  CLIENT   DEVICE   COLOR    CURSOR   SIDEBAND */
+const std::array<bool, 6> Hwc2TestPlaneAlpha::mCompositionSupport = {{
+    false,   true,    true,    true,    true,    true,
+}};
+
+/*  INVALID  CLIENT   DEVICE   COLOR    CURSOR   SIDEBAND */
+const std::array<bool, 6> Hwc2TestSourceCrop::mCompositionSupport = {{
+    false,   true,    true,    false,   true,    false,
+}};
+
+/*  INVALID  CLIENT   DEVICE   COLOR    CURSOR   SIDEBAND */
+const std::array<bool, 6> Hwc2TestSurfaceDamage::mCompositionSupport = {{
+    false,   false,   true,    false,   true,    false,
+}};
+
+/*  INVALID  CLIENT   DEVICE   COLOR    CURSOR   SIDEBAND */
+const std::array<bool, 6> Hwc2TestTransform::mCompositionSupport = {{
+    false,   true,    true,    false,   true,    true,
+}};
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
new file mode 100644
index 0000000..c2029ab
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
@@ -0,0 +1,384 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HWC2_TEST_PROPERTIES_H
+#define _HWC2_TEST_PROPERTIES_H
+
+#include <array>
+#include <vector>
+
+#include <ui/Region.h>
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+enum class Hwc2TestCoverage {
+    Default = 0,
+    Basic,
+    Complete,
+};
+
+enum class Hwc2TestPropertyName {
+    BlendMode = 1,
+    BufferArea,
+    Color,
+    Composition,
+    CursorPosition,
+    Dataspace,
+    DisplayFrame,
+    PlaneAlpha,
+    SourceCrop,
+    SurfaceDamage,
+    Transform,
+};
+
+typedef struct {
+    int32_t width;
+    int32_t height;
+} Area;
+
+
+typedef struct {
+    uint32_t width;
+    uint32_t height;
+} UnsignedArea;
+
+
+class Hwc2TestContainer {
+public:
+    virtual ~Hwc2TestContainer() = default;
+
+    /* Resets the container */
+    virtual void reset() = 0;
+
+    /* Attempts to advance to the next valid value. Returns true if one can be
+     * found */
+    virtual bool advance() = 0;
+
+    virtual std::string dump() const = 0;
+
+    /* Returns true if the container supports the given composition type */
+    virtual bool isSupported(hwc2_composition_t composition) = 0;
+};
+
+
+template <class T>
+class Hwc2TestProperty : public Hwc2TestContainer {
+public:
+    Hwc2TestProperty(Hwc2TestCoverage coverage,
+            const std::vector<T>& completeList, const std::vector<T>& basicList,
+            const std::vector<T>& defaultList,
+            const std::array<bool, 6>& compositionSupport)
+        : Hwc2TestProperty((coverage == Hwc2TestCoverage::Complete)? completeList:
+                (coverage == Hwc2TestCoverage::Basic)? basicList : defaultList,
+                compositionSupport) { }
+
+    Hwc2TestProperty(const std::vector<T>& list,
+            const std::array<bool, 6>& compositionSupport)
+        : mList(list),
+          mCompositionSupport(compositionSupport) { }
+
+    void reset() override
+    {
+        mListIdx = 0;
+    }
+
+    bool advance() override
+    {
+        if (mListIdx + 1 < mList.size()) {
+            mListIdx++;
+            updateDependents();
+            return true;
+        }
+        reset();
+        updateDependents();
+        return false;
+    }
+
+    T get() const
+    {
+        return mList.at(mListIdx);
+    }
+
+    virtual bool isSupported(hwc2_composition_t composition)
+    {
+        return mCompositionSupport.at(composition);
+    }
+
+protected:
+    /* If a derived class has dependents, override this function */
+    virtual void updateDependents() { }
+
+    const std::vector<T>& mList;
+    size_t mListIdx = 0;
+
+    const std::array<bool, 6>& mCompositionSupport;
+};
+
+class Hwc2TestBuffer;
+class Hwc2TestSourceCrop;
+class Hwc2TestSurfaceDamage;
+
+class Hwc2TestBufferArea : public Hwc2TestProperty<Area> {
+public:
+    Hwc2TestBufferArea(Hwc2TestCoverage coverage, const Area& displayArea);
+
+    std::string dump() const override;
+
+    void setDependent(Hwc2TestBuffer* buffer);
+    void setDependent(Hwc2TestSourceCrop* sourceCrop);
+    void setDependent(Hwc2TestSurfaceDamage* surfaceDamage);
+
+protected:
+    void update();
+    void updateDependents() override;
+
+    const std::vector<float>& mScalars;
+    static const std::vector<float> mDefaultScalars;
+    static const std::vector<float> mBasicScalars;
+    static const std::vector<float> mCompleteScalars;
+
+    Area mDisplayArea;
+
+    Hwc2TestBuffer* mBuffer = nullptr;
+    Hwc2TestSourceCrop* mSourceCrop = nullptr;
+    Hwc2TestSurfaceDamage* mSurfaceDamage = nullptr;
+
+    std::vector<Area> mBufferAreas;
+
+    static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestColor;
+
+class Hwc2TestBlendMode : public Hwc2TestProperty<hwc2_blend_mode_t> {
+public:
+    Hwc2TestBlendMode(Hwc2TestCoverage coverage);
+
+    std::string dump() const override;
+
+    void setDependent(Hwc2TestColor* color);
+
+protected:
+    void updateDependents() override;
+
+    Hwc2TestColor* mColor = nullptr;
+
+    static const std::vector<hwc2_blend_mode_t> mDefaultBlendModes;
+    static const std::vector<hwc2_blend_mode_t> mBasicBlendModes;
+    static const std::vector<hwc2_blend_mode_t> mCompleteBlendModes;
+
+    static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestColor : public Hwc2TestProperty<hwc_color_t> {
+public:
+    Hwc2TestColor(Hwc2TestCoverage coverage,
+            hwc2_blend_mode_t blendMode = HWC2_BLEND_MODE_NONE);
+
+    std::string dump() const override;
+
+    void updateBlendMode(hwc2_blend_mode_t blendMode);
+
+protected:
+    void update();
+
+    std::vector<hwc_color_t> mBaseColors;
+    static const std::vector<hwc_color_t> mDefaultBaseColors;
+    static const std::vector<hwc_color_t> mBasicBaseColors;
+    static const std::vector<hwc_color_t> mCompleteBaseColors;
+
+    hwc2_blend_mode_t mBlendMode;
+
+    std::vector<hwc_color_t> mColors;
+
+    static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestComposition : public Hwc2TestProperty<hwc2_composition_t> {
+public:
+    Hwc2TestComposition(Hwc2TestCoverage coverage);
+
+    std::string dump() const override;
+
+protected:
+    static const std::vector<hwc2_composition_t> mDefaultCompositions;
+    static const std::vector<hwc2_composition_t> mBasicCompositions;
+    static const std::vector<hwc2_composition_t> mCompleteCompositions;
+
+    static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestDataspace : public Hwc2TestProperty<android_dataspace_t> {
+public:
+    Hwc2TestDataspace(Hwc2TestCoverage coverage);
+
+    std::string dump() const override;
+
+protected:
+    static const std::vector<android_dataspace_t> defaultDataspaces;
+    static const std::vector<android_dataspace_t> basicDataspaces;
+    static const std::vector<android_dataspace_t> completeDataspaces;
+
+    static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestDisplayDimension : public Hwc2TestProperty<UnsignedArea> {
+public:
+    Hwc2TestDisplayDimension(Hwc2TestCoverage coverage);
+
+    std::string dump() const;
+
+    void setDependent(Hwc2TestBuffer* buffer);
+
+private:
+    void updateDependents();
+
+    Hwc2TestBuffer* mBuffer;
+
+    static const std::vector<UnsignedArea> mDefaultDisplayDimensions;
+    static const std::vector<UnsignedArea> mBasicDisplayDimensions;
+    static const std::vector<UnsignedArea> mCompleteDisplayDimensions;
+
+    static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestDisplayFrame : public Hwc2TestProperty<hwc_rect_t> {
+public:
+    Hwc2TestDisplayFrame(Hwc2TestCoverage coverage, const Area& displayArea);
+
+    std::string dump() const override;
+
+protected:
+    void update();
+
+    const std::vector<hwc_frect_t>& mFrectScalars;
+    const static std::vector<hwc_frect_t> mDefaultFrectScalars;
+    const static std::vector<hwc_frect_t> mBasicFrectScalars;
+    const static std::vector<hwc_frect_t> mCompleteFrectScalars;
+
+    Area mDisplayArea;
+
+    std::vector<hwc_rect_t> mDisplayFrames;
+
+    static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestPlaneAlpha : public Hwc2TestProperty<float> {
+public:
+    Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage);
+
+    std::string dump() const override;
+
+protected:
+    static const std::vector<float> mDefaultPlaneAlphas;
+    static const std::vector<float> mBasicPlaneAlphas;
+    static const std::vector<float> mCompletePlaneAlphas;
+
+    static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestSourceCrop : public Hwc2TestProperty<hwc_frect_t> {
+public:
+    Hwc2TestSourceCrop(Hwc2TestCoverage coverage, const Area& bufferArea = {0, 0});
+
+    std::string dump() const override;
+
+    void updateBufferArea(const Area& bufferArea);
+
+protected:
+    void update();
+
+    const std::vector<hwc_frect_t>& mFrectScalars;
+    const static std::vector<hwc_frect_t> mDefaultFrectScalars;
+    const static std::vector<hwc_frect_t> mBasicFrectScalars;
+    const static std::vector<hwc_frect_t> mCompleteFrectScalars;
+
+    Area mBufferArea;
+
+    std::vector<hwc_frect_t> mSourceCrops;
+
+    static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestSurfaceDamage : public Hwc2TestProperty<hwc_region_t> {
+public:
+    Hwc2TestSurfaceDamage(Hwc2TestCoverage coverage);
+    ~Hwc2TestSurfaceDamage();
+
+    std::string dump() const override;
+
+    void updateBufferArea(const Area& bufferArea);
+
+protected:
+    void update();
+    void freeSurfaceDamages();
+
+    const std::vector<std::vector<hwc_frect_t>> &mRegionScalars;
+    const static std::vector<std::vector<hwc_frect_t>> mDefaultRegionScalars;
+    const static std::vector<std::vector<hwc_frect_t>> mBasicRegionScalars;
+    const static std::vector<std::vector<hwc_frect_t>> mCompleteRegionScalars;
+
+    Area mBufferArea = {0, 0};
+
+    std::vector<hwc_region_t> mSurfaceDamages;
+
+    static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestTransform : public Hwc2TestProperty<hwc_transform_t> {
+public:
+    Hwc2TestTransform(Hwc2TestCoverage coverage);
+
+    std::string dump() const override;
+
+protected:
+    static const std::vector<hwc_transform_t> mDefaultTransforms;
+    static const std::vector<hwc_transform_t> mBasicTransforms;
+    static const std::vector<hwc_transform_t> mCompleteTransforms;
+
+    static const std::array<bool, 6> mCompositionSupport;
+};
+
+
+class Hwc2TestVisibleRegion {
+public:
+    ~Hwc2TestVisibleRegion();
+
+    std::string dump() const;
+
+    void set(const android::Region& visibleRegion);
+    hwc_region_t get() const;
+    void release();
+
+protected:
+    hwc_region_t mVisibleRegion = {0, nullptr};
+};
+
+#endif /* ifndef _HWC2_TEST_PROPERTIES_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp
new file mode 100644
index 0000000..d0fbc0b
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sstream>
+
+#include "Hwc2TestVirtualDisplay.h"
+
+Hwc2TestVirtualDisplay::Hwc2TestVirtualDisplay(
+        Hwc2TestCoverage coverage)
+    : mDisplayDimension(coverage)
+{
+    mDisplayDimension.setDependent(&mBuffer);
+}
+
+std::string Hwc2TestVirtualDisplay::dump() const
+{
+    std::stringstream dmp;
+
+    dmp << "virtual display: \n";
+
+    mDisplayDimension.dump();
+
+    return dmp.str();
+}
+
+int Hwc2TestVirtualDisplay::getBuffer(buffer_handle_t* outHandle,
+        android::base::unique_fd* outAcquireFence)
+{
+    int32_t acquireFence;
+    int ret = mBuffer.get(outHandle, &acquireFence);
+    outAcquireFence->reset(acquireFence);
+    return ret;
+}
+
+void Hwc2TestVirtualDisplay::reset()
+{
+    return mDisplayDimension.reset();
+}
+
+bool Hwc2TestVirtualDisplay::advance()
+{
+    return mDisplayDimension.advance();
+}
+
+UnsignedArea Hwc2TestVirtualDisplay::getDisplayDimension() const
+{
+    return mDisplayDimension.get();
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
new file mode 100644
index 0000000..09420ef
--- /dev/null
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestVirtualDisplay.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HWC2_TEST_VIRTUAL_DISPLAY_H
+#define _HWC2_TEST_VIRTUAL_DISPLAY_H
+
+#include "Hwc2TestBuffer.h"
+#include "Hwc2TestProperties.h"
+
+#define HWC2_INCLUDE_STRINGIFICATION
+#define HWC2_USE_CPP11
+#include <hardware/hwcomposer2.h>
+#undef HWC2_INCLUDE_STRINGIFICATION
+#undef HWC2_USE_CPP11
+
+class Hwc2TestVirtualDisplay {
+public:
+    Hwc2TestVirtualDisplay(Hwc2TestCoverage coverage);
+
+    std::string dump() const;
+
+    int getBuffer(buffer_handle_t* outHandle,
+            android::base::unique_fd* outAcquireFence);
+
+    void reset();
+    bool advance();
+
+    UnsignedArea getDisplayDimension() const;
+
+private:
+    Hwc2TestBuffer mBuffer;
+
+    Hwc2TestDisplayDimension mDisplayDimension;
+};
+
+#endif /* ifndef _HWC2_TEST_VIRTUAL_DISPLAY_H */