test-hwc2: set layer source crop

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: If3079efd7a035d1d182f04c56dc55300cdcedc47
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
index c092f22..b060be9 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp
@@ -425,6 +425,22 @@
         }
     }
 
+    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 setLayerTransform(hwc2_display_t display, hwc2_layer_t layer,
             hwc_transform_t transform, hwc2_error_t* outErr = nullptr)
     {
@@ -903,6 +919,13 @@
             testLayer.getPlaneAlpha(), outErr));
 }
 
+void setSourceCrop(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
+        const Hwc2TestLayer& testLayer, hwc2_error_t* outErr)
+{
+    EXPECT_NO_FATAL_FAILURE(test->setLayerSourceCrop(display, layer,
+            testLayer.getSourceCrop(), outErr));
+}
+
 void setTransform(Hwc2Test* test, hwc2_display_t display, hwc2_layer_t layer,
         const Hwc2TestLayer& testLayer, hwc2_error_t* outErr)
 {
@@ -942,6 +965,13 @@
     return testLayer->advancePlaneAlpha();
 }
 
+bool advanceSourceCrop(Hwc2TestLayer* testLayer)
+{
+    if (testLayer->advanceSourceCrop())
+        return true;
+    return testLayer->advanceBufferArea();
+}
+
 bool advanceTransform(Hwc2TestLayer* testLayer)
 {
     return testLayer->advanceTransform();
@@ -1898,6 +1928,27 @@
     ));
 }
 
+/* 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 transform value of a layer. */
 TEST_F(Hwc2Test, SET_LAYER_TRANSFORM)
 {
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp
index 261fe97..cdf4392 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.cpp
@@ -21,12 +21,17 @@
 Hwc2TestLayer::Hwc2TestLayer(Hwc2TestCoverage coverage, const Area& displayArea,
         uint32_t zOrder)
     : mBlendMode(coverage),
+      mBufferArea(coverage, displayArea),
       mComposition(coverage),
       mDataspace(coverage),
       mDisplayFrame(coverage, displayArea),
       mPlaneAlpha(coverage),
+      mSourceCrop(coverage),
       mTransform(coverage),
-      mZOrder(zOrder) { }
+      mZOrder(zOrder)
+{
+    mBufferArea.setDependent(&mSourceCrop);
+}
 
 std::string Hwc2TestLayer::dump() const
 {
@@ -75,6 +80,11 @@
     return mPlaneAlpha.get();
 }
 
+hwc_frect_t Hwc2TestLayer::getSourceCrop() const
+{
+    return mSourceCrop.get();
+}
+
 hwc_transform_t Hwc2TestLayer::getTransform() const
 {
     return mTransform.get();
@@ -90,6 +100,11 @@
     return mBlendMode.advance();
 }
 
+bool Hwc2TestLayer::advanceBufferArea()
+{
+    return mBufferArea.advance();
+}
+
 bool Hwc2TestLayer::advanceComposition()
 {
     return mComposition.advance();
@@ -110,6 +125,11 @@
     return mPlaneAlpha.advance();
 }
 
+bool Hwc2TestLayer::advanceSourceCrop()
+{
+    return mSourceCrop.advance();
+}
+
 bool Hwc2TestLayer::advanceTransform()
 {
     return mTransform.advance();
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h
index e24ff77..86d40cc 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayer.h
@@ -39,27 +39,32 @@
     android_dataspace_t    getDataspace() const;
     hwc_rect_t             getDisplayFrame() const;
     float                  getPlaneAlpha() const;
+    hwc_frect_t            getSourceCrop() const;
     hwc_transform_t        getTransform() const;
     uint32_t               getZOrder() const;
 
     bool advanceBlendMode();
+    bool advanceBufferArea();
     bool advanceComposition();
     bool advanceDataspace();
     bool advanceDisplayFrame();
     bool advancePlaneAlpha();
+    bool advanceSourceCrop();
     bool advanceTransform();
 
 private:
-    std::array<Hwc2TestContainer*, 6> mProperties = {{
-        &mBlendMode, &mComposition, &mDataspace,  &mDisplayFrame, &mPlaneAlpha,
-        &mTransform
+    std::array<Hwc2TestContainer*, 7> mProperties = {{
+        &mBlendMode, &mComposition, &mDataspace, &mDisplayFrame, &mPlaneAlpha,
+        &mSourceCrop, &mTransform
     }};
 
     Hwc2TestBlendMode mBlendMode;
+    Hwc2TestBufferArea mBufferArea;
     Hwc2TestComposition mComposition;
     Hwc2TestDataspace mDataspace;
     Hwc2TestDisplayFrame mDisplayFrame;
     Hwc2TestPlaneAlpha mPlaneAlpha;
+    Hwc2TestSourceCrop mSourceCrop;
     Hwc2TestTransform mTransform;
 
     uint32_t mZOrder;
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
index e793c11..0073857 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp
@@ -18,6 +18,70 @@
 
 #include "Hwc2TestProperties.h"
 
+Hwc2TestBufferArea::Hwc2TestBufferArea(Hwc2TestCoverage coverage,
+        const Area& displayArea)
+    : Hwc2TestProperty(mBufferAreas),
+      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(Hwc2TestSourceCrop* sourceCrop)
+{
+    mSourceCrop = sourceCrop;
+    updateDependents();
+}
+
+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 (mSourceCrop)
+        mSourceCrop->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) { }
@@ -224,6 +288,70 @@
 };
 
 
+Hwc2TestSourceCrop::Hwc2TestSourceCrop(Hwc2TestCoverage coverage,
+        const Area& bufferArea)
+    : Hwc2TestProperty(mSourceCrops),
+      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},
+};
+
+
 Hwc2TestTransform::Hwc2TestTransform(Hwc2TestCoverage coverage)
     : Hwc2TestProperty(coverage, mCompleteTransforms, mBasicTransforms,
             mDefaultTransforms) { }
diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
index 25c6ad8..9df532e 100644
--- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
+++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.h
@@ -74,9 +74,11 @@
     {
         if (mListIdx + 1 < mList.size()) {
             mListIdx++;
+            updateDependents();
             return true;
         }
         reset();
+        updateDependents();
         return false;
     }
 
@@ -86,11 +88,41 @@
     }
 
 protected:
+    /* If a derived class has dependents, override this function */
+    virtual void updateDependents() { }
+
     const std::vector<T>& mList;
     size_t mListIdx = 0;
 };
 
 
+class Hwc2TestSourceCrop;
+
+class Hwc2TestBufferArea : public Hwc2TestProperty<Area> {
+public:
+    Hwc2TestBufferArea(Hwc2TestCoverage coverage, const Area& displayArea);
+
+    std::string dump() const override;
+
+    void setDependent(Hwc2TestSourceCrop* sourceCrop);
+
+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;
+
+    Hwc2TestSourceCrop* mSourceCrop = nullptr;
+
+    std::vector<Area> mBufferAreas;
+};
+
+
 class Hwc2TestBlendMode : public Hwc2TestProperty<hwc2_blend_mode_t> {
 public:
     Hwc2TestBlendMode(Hwc2TestCoverage coverage);
@@ -163,6 +195,28 @@
 };
 
 
+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;
+};
+
+
 class Hwc2TestTransform : public Hwc2TestProperty<hwc_transform_t> {
 public:
     Hwc2TestTransform(Hwc2TestCoverage coverage);