SF: adapt region sampling to display orientation

Pass in the orientation flags of SF to RenderEngine when conducting the
sampling composition. This resulted mis-sampled areas, especially when
the region was outside of the clip of the 0-degree rotated display.

Bug: 132394665
Test: manual verification with 90, 270, 0 rotations
Test: new tests in libsurfaceflinger_unittest#RegionSamplingTest.*
Change-Id: I2869ef191572dbcc9170df8d3ed17414ab053ca4
diff --git a/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp b/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp
index 51d6d7e..160f041 100644
--- a/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp
@@ -17,6 +17,8 @@
 #undef LOG_TAG
 #define LOG_TAG "RegionSamplingTest"
 
+#include <ui/Transform.h>
+
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 #include <array>
@@ -33,18 +35,21 @@
     static int constexpr kWidth = 98;
     static int constexpr kStride = 100;
     static int constexpr kHeight = 29;
+    static int constexpr kOrientation = ui::Transform::ROT_0;
     std::array<uint32_t, kHeight * kStride> buffer;
     Rect const whole_area{0, 0, kWidth, kHeight};
 };
 
 TEST_F(RegionSamplingTest, calculate_mean_white) {
     std::fill(buffer.begin(), buffer.end(), kWhite);
-    EXPECT_THAT(sampleArea(buffer.data(), kStride, whole_area), testing::FloatEq(1.0f));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, whole_area),
+                testing::FloatEq(1.0f));
 }
 
 TEST_F(RegionSamplingTest, calculate_mean_black) {
     std::fill(buffer.begin(), buffer.end(), kBlack);
-    EXPECT_THAT(sampleArea(buffer.data(), kStride, whole_area), testing::FloatEq(0.0f));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, whole_area),
+                testing::FloatEq(0.0f));
 }
 
 TEST_F(RegionSamplingTest, calculate_mean_partial_region) {
@@ -54,7 +59,8 @@
                                  whole_area.top + halfway_down};
     std::fill(buffer.begin(), buffer.begin() + half, 0);
     std::fill(buffer.begin() + half, buffer.end(), kWhite);
-    EXPECT_THAT(sampleArea(buffer.data(), kStride, partial_region), testing::FloatEq(0.0f));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, partial_region),
+                testing::FloatEq(0.0f));
 }
 
 TEST_F(RegionSamplingTest, calculate_mean_mixed_values) {
@@ -63,15 +69,71 @@
         n++;
         return pixel;
     });
-    EXPECT_THAT(sampleArea(buffer.data(), kStride, whole_area), testing::FloatNear(0.083f, 0.01f));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, whole_area),
+                testing::FloatNear(0.083f, 0.01f));
 }
 
 TEST_F(RegionSamplingTest, bimodal_tiebreaker) {
     std::generate(buffer.begin(), buffer.end(),
                   [n = 0]() mutable { return (n++ % 2) ? kBlack : kWhite; });
     // presently there's no tiebreaking strategy in place, accept either of the means
-    EXPECT_THAT(sampleArea(buffer.data(), kStride, whole_area),
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, whole_area),
                 testing::AnyOf(testing::FloatEq(1.0), testing::FloatEq(0.0f)));
 }
 
+TEST_F(RegionSamplingTest, bounds_checking) {
+    std::generate(buffer.begin(), buffer.end(),
+                  [n = 0]() mutable { return (n++ > (kStride * kHeight >> 1)) ? kBlack : kWhite; });
+
+    Rect invalid_region{0, 0, 4, kHeight + 1};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, invalid_region),
+                testing::Eq(0.0));
+
+    invalid_region = Rect{0, 0, -4, kHeight};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, invalid_region),
+                testing::Eq(0.0));
+
+    invalid_region = Rect{3, 0, 2, 0};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, invalid_region),
+                testing::Eq(0.0));
+
+    invalid_region = Rect{0, 3, 0, 2};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, kOrientation, invalid_region),
+                testing::Eq(0.0));
+}
+
+// workaround for b/133849373
+TEST_F(RegionSamplingTest, orientation_90) {
+    std::generate(buffer.begin(), buffer.end(),
+                  [n = 0]() mutable { return (n++ > (kStride * kHeight >> 1)) ? kBlack : kWhite; });
+
+    Rect tl_region{0, 0, 4, 4};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_0,
+                           tl_region),
+                testing::Eq(1.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_180,
+                           tl_region),
+                testing::Eq(1.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_90,
+                           tl_region),
+                testing::Eq(0.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_270,
+                           tl_region),
+                testing::Eq(0.0));
+
+    Rect br_region{kWidth - 4, kHeight - 4, kWidth, kHeight};
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_0,
+                           br_region),
+                testing::Eq(0.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_180,
+                           br_region),
+                testing::Eq(0.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_90,
+                           br_region),
+                testing::Eq(1.0));
+    EXPECT_THAT(sampleArea(buffer.data(), kWidth, kHeight, kStride, ui::Transform::ROT_270,
+                           br_region),
+                testing::Eq(1.0));
+}
+
 } // namespace android