test-hwc2: present display

Test: Add "#define HAVE_NO_SURFACE_FLINGER" to
      frameworks/native/libs/gui/BufferQueueCore.cpp.
      Recompile and flash.
      Run "mm" in frameworks/native/services/surfaceflinger/tests/hwc2.
      Push test-hwc2 to device.
      Run "adb root && adb shell stop".
      Run test case. Ex: "./test-hwc2"

Change-Id: I845320afdf635d1716310d1183bcb10515615517
diff --git a/services/surfaceflinger/tests/hwc2/Android.mk b/services/surfaceflinger/tests/hwc2/Android.mk
index 329e124..f7403cf 100644
--- a/services/surfaceflinger/tests/hwc2/Android.mk
+++ b/services/surfaceflinger/tests/hwc2/Android.mk
@@ -35,7 +35,8 @@
     libGLESv2 \
     libui \
     libgui \
-    liblog
+    liblog \
+    libsync
 LOCAL_STATIC_LIBRARIES := \
     libbase \
     libadf \
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
index 9171de2..600c454 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
@@ -16,10 +16,12 @@
 
 #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
@@ -808,6 +810,50 @@
         }
     }
 
+    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 getBadDisplay(hwc2_display_t* outDisplay)
     {
         for (hwc2_display_t display = 0; display < UINT64_MAX; display++) {
@@ -820,6 +866,32 @@
                 " 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)
     {
@@ -919,32 +991,6 @@
         *outConfig = config;
     }
 
-    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));
-    }
-
-    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;
-    }
-
     /* 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,
@@ -973,7 +1019,7 @@
      * changes, present, etc. */
     using TestDisplayLayersFunction = void (*)(Hwc2Test* test,
             hwc2_display_t display, const std::vector<hwc2_layer_t>& layers,
-            const Hwc2TestLayers& testLayers);
+            Hwc2TestLayers* testLayers);
 
     /* It is called on an non validated display */
     using TestDisplayNonValidatedLayersFunction = void (*)(Hwc2Test* test,
@@ -1195,7 +1241,7 @@
                             &testLayers, &skip));
                     if (!skip)
                         EXPECT_NO_FATAL_FAILURE(function(this, display, layers,
-                                testLayers));
+                                &testLayers));
 
                 } while (testLayers.advance());
 
@@ -1298,6 +1344,27 @@
                 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)
     {
@@ -1366,6 +1433,100 @@
         }
     }
 
+    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 {
@@ -2870,7 +3031,7 @@
     ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
             [] (Hwc2Test* test, hwc2_display_t display,
                     const std::vector<hwc2_layer_t>& layers,
-                    const Hwc2TestLayers& /*testLayers*/) {
+                    Hwc2TestLayers* /*testLayers*/) {
 
                 uint32_t numTypes, numRequests;
                 bool hasChanges = false;
@@ -2890,7 +3051,7 @@
     ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Default, 5,
             [] (Hwc2Test* test, hwc2_display_t display,
                     const std::vector<hwc2_layer_t>& layers,
-                    const Hwc2TestLayers& /*testLayers*/) {
+                    Hwc2TestLayers* /*testLayers*/) {
 
                 uint32_t numTypes, numRequests;
                 bool hasChanges = false;
@@ -2925,7 +3086,7 @@
     ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
             [] (Hwc2Test* test, hwc2_display_t display,
                     const std::vector<hwc2_layer_t>& layers,
-                    const Hwc2TestLayers& /*testLayers*/) {
+                    Hwc2TestLayers* /*testLayers*/) {
 
                 uint32_t numTypes, numRequests;
                 bool hasChanges = false;
@@ -2985,7 +3146,7 @@
     ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
             [] (Hwc2Test* test, hwc2_display_t display,
                     const std::vector<hwc2_layer_t>& layers,
-                    const Hwc2TestLayers& testLayers) {
+                    Hwc2TestLayers* testLayers) {
 
                 uint32_t numTypes, numRequests;
                 bool hasChanges = false;
@@ -2997,7 +3158,7 @@
                             << "wrong number of requests";
 
                 EXPECT_NO_FATAL_FAILURE(test->handleCompositionChanges(display,
-                        testLayers, layers, numTypes));
+                        *testLayers, layers, numTypes));
             }
     ));
 }
@@ -3044,7 +3205,7 @@
     ASSERT_NO_FATAL_FAILURE(displayLayers(Hwc2TestCoverage::Basic, 1,
             [] (Hwc2Test* test, hwc2_display_t display,
                     const std::vector<hwc2_layer_t>& layers,
-                    const Hwc2TestLayers& testLayers) {
+                    Hwc2TestLayers* testLayers) {
 
                 uint32_t numTypes, numRequests;
                 bool hasChanges = false;
@@ -3056,7 +3217,7 @@
                             << "wrong number of requests";
 
                 ASSERT_NO_FATAL_FAILURE(test->handleCompositionChanges(display,
-                        testLayers, layers, numTypes));
+                        *testLayers, layers, numTypes));
 
                 EXPECT_NO_FATAL_FAILURE(test->acceptDisplayChanges(display));
             }
@@ -3263,3 +3424,440 @@
 
     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";
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp
index b459cd6..937fce2 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp
@@ -18,17 +18,41 @@
 
 #include "Hwc2TestLayer.h"
 
-Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea)
-    : mBlendMode(coverage),
-      mBufferArea(coverage, displayArea),
-      mColor(coverage),
-      mComposition(coverage),
-      mDataspace(coverage),
-      mDisplayFrame(coverage, displayArea),
-      mPlaneAlpha(coverage),
-      mSourceCrop(coverage),
-      mSurfaceDamage(coverage),
-      mTransform(coverage)
+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);
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h
index 17f5079..0e7dd22 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h
@@ -18,6 +18,7 @@
 #define _HWC2_TEST_LAYER_H
 
 #include <android-base/unique_fd.h>
+#include <unordered_map>
 
 #include "Hwc2TestBuffer.h"
 #include "Hwc2TestProperties.h"
@@ -32,6 +33,10 @@
 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,
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp
index 96cd98d..495ef79 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp
@@ -20,12 +20,19 @@
 
 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));
+                std::forward_as_tuple(coverage, displayArea, coverageExceptions));
     }
 
     /* Iterate over the layers in order and assign z orders in the same order.
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h
index a8579ee..d95a91f 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h
@@ -33,6 +33,11 @@
     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();
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
index f3c614c..d978237 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
@@ -34,6 +34,20 @@
     Complete,
 };
 
+enum class Hwc2TestPropertyName {
+    BlendMode = 1,
+    BufferArea,
+    Color,
+    Composition,
+    CursorPosition,
+    Dataspace,
+    DisplayFrame,
+    PlaneAlpha,
+    SourceCrop,
+    SurfaceDamage,
+    Transform,
+};
+
 typedef struct {
     int32_t width;
     int32_t height;