test-hwc2: validate 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: I9a9df2902213d99d4f043e3bdea1e5e2fc77b01d
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
index 024ba77..44aa330 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
@@ -559,6 +559,33 @@
         }
     }
 
+    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;
+        }
+    }
+
 protected:
     hwc2_function_pointer_t getFunction(hwc2_function_descriptor_t descriptor)
     {
@@ -719,6 +746,12 @@
     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);
+
     /* Advances a property of Hwc2TestLayer */
     using AdvanceProperty = bool (*)(Hwc2TestLayer* testLayer);
 
@@ -895,6 +928,48 @@
         }
     }
 
+    /* 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));
+
+                } while (testLayers.advance());
+
+                ASSERT_NO_FATAL_FAILURE(destroyLayers(display,
+                        std::move(layers)));
+            }
+
+            ASSERT_NO_FATAL_FAILURE(setPowerMode(display, HWC2_POWER_MODE_OFF));
+        }
+    }
+
     void getActiveConfigAttribute(hwc2_display_t display,
             hwc2_attribute_t attribute, int32_t* outValue)
     {
@@ -914,6 +989,74 @@
                 HWC2_ATTRIBUTE_HEIGHT, &displayArea->height));
     }
 
+    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;
+        }
+    }
+
     hwc2_device_t* mHwc2Device = nullptr;
 
     enum class Hwc2TestHotplugStatus {
@@ -2405,3 +2548,56 @@
     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) {
+
+                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) {
+
+                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";
+}
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp
index f9c5aa0..b459cd6 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp
@@ -61,6 +61,12 @@
     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;
@@ -80,6 +86,16 @@
     }
 }
 
+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();
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h
index 86c3649..17f5079 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h
@@ -36,11 +36,13 @@
 
     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;
@@ -71,8 +73,9 @@
 
 private:
     std::array<Hwc2TestContainer*, 10> mProperties = {{
-        &mBlendMode, &mBufferArea, &mColor, &mComposition, &mDataspace,
-        &mDisplayFrame, &mPlaneAlpha, &mSourceCrop, &mSurfaceDamage, &mTransform
+        &mTransform, &mColor, &mDataspace, &mPlaneAlpha, &mSourceCrop,
+        &mSurfaceDamage, &mBlendMode, &mBufferArea, &mDisplayFrame,
+        &mComposition
     }};
 
     Hwc2TestBuffer mBuffer;
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp
index 15a5f77..9d91f88 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp
@@ -20,6 +20,7 @@
 
 Hwc2TestLayers::Hwc2TestLayers(const std::vector<hwc2_layer_t>& layers,
         Hwc2TestCoverage coverage, const Area& displayArea)
+    : mDisplayArea(displayArea)
 {
     for (auto layer : layers) {
         mTestLayers.emplace(std::piecewise_construct,
@@ -57,6 +58,18 @@
     setVisibleRegions();
 }
 
+bool Hwc2TestLayers::advance()
+{
+    for (auto& testLayer : mTestLayers) {
+        if (testLayer.second.advance()) {
+            setVisibleRegions();
+            return true;
+        }
+        testLayer.second.reset();
+    }
+    return false;
+}
+
 bool Hwc2TestLayers::advanceVisibleRegions()
 {
     for (auto& testLayer : mTestLayers) {
@@ -69,6 +82,100 @@
     return false;
 }
 
+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();
+}
+
+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) {
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h
index b246823..b4c3558 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.h
@@ -37,15 +37,34 @@
 
     void reset();
 
+    bool advance();
     bool advanceVisibleRegions();
 
-    hwc_region_t    getVisibleRegion(hwc2_layer_t layer) const;
-    uint32_t        getZOrder(hwc2_layer_t layer) const;
+    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;
+    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:
     void setVisibleRegions();
 
     std::map<hwc2_layer_t, Hwc2TestLayer> mTestLayers;
+
+    Area mDisplayArea;
 };
 
 #endif /* ifndef _HWC2_TEST_LAYERS_H */
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
index a79909a..e00c560 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
@@ -29,7 +29,7 @@
 
 Hwc2TestBufferArea::Hwc2TestBufferArea(Hwc2TestCoverage coverage,
         const Area& displayArea)
-    : Hwc2TestProperty(mBufferAreas),
+    : Hwc2TestProperty(mBufferAreas, mCompositionSupport),
       mScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteScalars:
             (coverage == Hwc2TestCoverage::Basic)? mBasicScalars:
             mDefaultScalars),
@@ -115,7 +115,7 @@
 
 Hwc2TestBlendMode::Hwc2TestBlendMode(Hwc2TestCoverage coverage)
     : Hwc2TestProperty(coverage, mCompleteBlendModes, mBasicBlendModes,
-            mDefaultBlendModes) { }
+            mDefaultBlendModes, mCompositionSupport) { }
 
 std::string Hwc2TestBlendMode::dump() const
 {
@@ -154,7 +154,7 @@
 
 Hwc2TestColor::Hwc2TestColor(Hwc2TestCoverage coverage,
         hwc2_blend_mode_t blendMode)
-    : Hwc2TestProperty(mColors),
+    : Hwc2TestProperty(mColors, mCompositionSupport),
       mBaseColors((coverage == Hwc2TestCoverage::Complete)? mCompleteBaseColors:
             (coverage == Hwc2TestCoverage::Basic)? mBasicBaseColors:
             mDefaultBaseColors),
@@ -228,7 +228,7 @@
 
 Hwc2TestComposition::Hwc2TestComposition(Hwc2TestCoverage coverage)
     : Hwc2TestProperty(coverage, mCompleteCompositions, mBasicCompositions,
-            mDefaultCompositions) { }
+            mDefaultCompositions, mCompositionSupport) { }
 
 std::string Hwc2TestComposition::dump() const
 {
@@ -257,7 +257,7 @@
 
 Hwc2TestDataspace::Hwc2TestDataspace(Hwc2TestCoverage coverage)
     : Hwc2TestProperty(coverage, completeDataspaces, basicDataspaces,
-            defaultDataspaces) { }
+            defaultDataspaces, mCompositionSupport) { }
 
 std::string Hwc2TestDataspace::dump() const
 {
@@ -323,7 +323,7 @@
 
 Hwc2TestDisplayFrame::Hwc2TestDisplayFrame(Hwc2TestCoverage coverage,
         const Area& displayArea)
-    : Hwc2TestProperty(mDisplayFrames),
+    : Hwc2TestProperty(mDisplayFrames, mCompositionSupport),
       mFrectScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteFrectScalars:
             (coverage == Hwc2TestCoverage::Basic)? mBasicFrectScalars:
             mDefaultFrectScalars),
@@ -383,7 +383,7 @@
 
 Hwc2TestPlaneAlpha::Hwc2TestPlaneAlpha(Hwc2TestCoverage coverage)
     : Hwc2TestProperty(coverage, mCompletePlaneAlphas, mBasicPlaneAlphas,
-            mDefaultPlaneAlphas) { }
+            mDefaultPlaneAlphas, mCompositionSupport) { }
 
 std::string Hwc2TestPlaneAlpha::dump() const
 {
@@ -407,7 +407,7 @@
 
 Hwc2TestSourceCrop::Hwc2TestSourceCrop(Hwc2TestCoverage coverage,
         const Area& bufferArea)
-    : Hwc2TestProperty(mSourceCrops),
+    : Hwc2TestProperty(mSourceCrops, mCompositionSupport),
       mFrectScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteFrectScalars:
             (coverage == Hwc2TestCoverage::Basic)? mBasicFrectScalars:
             mDefaultFrectScalars),
@@ -470,7 +470,7 @@
 
 
 Hwc2TestSurfaceDamage::Hwc2TestSurfaceDamage(Hwc2TestCoverage coverage)
-    : Hwc2TestProperty(mSurfaceDamages),
+    : Hwc2TestProperty(mSurfaceDamages, mCompositionSupport),
       mRegionScalars((coverage == Hwc2TestCoverage::Complete)? mCompleteRegionScalars:
             (coverage == Hwc2TestCoverage::Basic)? mBasicRegionScalars:
             mDefaultRegionScalars)
@@ -568,7 +568,7 @@
 
 Hwc2TestTransform::Hwc2TestTransform(Hwc2TestCoverage coverage)
     : Hwc2TestProperty(coverage, mCompleteTransforms, mBasicTransforms,
-            mDefaultTransforms) { }
+            mDefaultTransforms, mCompositionSupport) { }
 
 std::string Hwc2TestTransform::dump() const
 {
@@ -654,3 +654,67 @@
     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> 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
index 9cdf69c..f3c614c 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
@@ -52,6 +52,9 @@
     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;
 };
 
 
@@ -60,12 +63,16 @@
 public:
     Hwc2TestProperty(Hwc2TestCoverage coverage,
             const std::vector<T>& completeList, const std::vector<T>& basicList,
-            const std::vector<T>& defaultList)
+            const std::vector<T>& defaultList,
+            const std::array<bool, 6>& compositionSupport)
         : Hwc2TestProperty((coverage == Hwc2TestCoverage::Complete)? completeList:
-                (coverage == Hwc2TestCoverage::Basic)? basicList : defaultList) { }
+                (coverage == Hwc2TestCoverage::Basic)? basicList : defaultList,
+                compositionSupport) { }
 
-    Hwc2TestProperty(const std::vector<T>& list)
-        : mList(list) { }
+    Hwc2TestProperty(const std::vector<T>& list,
+            const std::array<bool, 6>& compositionSupport)
+        : mList(list),
+          mCompositionSupport(compositionSupport) { }
 
     void reset() override
     {
@@ -89,14 +96,20 @@
         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;
@@ -128,6 +141,8 @@
     Hwc2TestSurfaceDamage* mSurfaceDamage = nullptr;
 
     std::vector<Area> mBufferAreas;
+
+    static const std::array<bool, 6> mCompositionSupport;
 };
 
 
@@ -149,6 +164,8 @@
     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;
 };
 
 
@@ -172,6 +189,8 @@
     hwc2_blend_mode_t mBlendMode;
 
     std::vector<hwc_color_t> mColors;
+
+    static const std::array<bool, 6> mCompositionSupport;
 };
 
 
@@ -185,6 +204,8 @@
     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;
 };
 
 
@@ -198,6 +219,8 @@
     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;
 };
 
 
@@ -218,6 +241,8 @@
     Area mDisplayArea;
 
     std::vector<hwc_rect_t> mDisplayFrames;
+
+    static const std::array<bool, 6> mCompositionSupport;
 };
 
 
@@ -231,6 +256,8 @@
     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;
 };
 
 
@@ -253,6 +280,8 @@
     Area mBufferArea;
 
     std::vector<hwc_frect_t> mSourceCrops;
+
+    static const std::array<bool, 6> mCompositionSupport;
 };
 
 
@@ -277,6 +306,8 @@
     Area mBufferArea = {0, 0};
 
     std::vector<hwc_region_t> mSurfaceDamages;
+
+    static const std::array<bool, 6> mCompositionSupport;
 };
 
 
@@ -290,6 +321,8 @@
     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;
 };