Merge "Set better defaults for layer stack and oriented display space" into tm-dev
diff --git a/libs/ui/include/ui/Size.h b/libs/ui/include/ui/Size.h
index ecc192d..bdcbd56 100644
--- a/libs/ui/include/ui/Size.h
+++ b/libs/ui/include/ui/Size.h
@@ -23,6 +23,8 @@
 #include <type_traits>
 #include <utility>
 
+#include <ui/Rotation.h>
+
 namespace android::ui {
 
 // A simple value type representing a two-dimensional size.
@@ -61,6 +63,16 @@
         set(Size(w, h));
     }
 
+    // Applies a rotation onto the size
+    void rotate(Rotation rotation) {
+        if (rotation == ROTATION_90 || rotation == ROTATION_270) {
+            transpose();
+        }
+    }
+
+    // Swaps the width and height, emulating a 90 degree rotation.
+    void transpose() { std::swap(width, height); }
+
     // Sets the value to kInvalidSize
     void makeInvalid();
 
diff --git a/libs/ui/tests/Size_test.cpp b/libs/ui/tests/Size_test.cpp
index acef47f..0a236e6 100644
--- a/libs/ui/tests/Size_test.cpp
+++ b/libs/ui/tests/Size_test.cpp
@@ -61,6 +61,38 @@
     EXPECT_FALSE(Size(1, 1) < Size(1, 1));
 }
 
+TEST(SizeTest, Transpose) {
+    Size s(123, 456);
+    s.transpose();
+    EXPECT_EQ(s, Size(456, 123));
+}
+
+TEST(SizeTest, Rotate) {
+    {
+        Size s(123, 456);
+        s.rotate(Rotation::Rotation0);
+        EXPECT_EQ(s, Size(123, 456));
+    }
+
+    {
+        Size s(123, 456);
+        s.rotate(Rotation::Rotation90);
+        EXPECT_EQ(s, Size(456, 123));
+    }
+
+    {
+        Size s(123, 456);
+        s.rotate(Rotation::Rotation180);
+        EXPECT_EQ(s, Size(123, 456));
+    }
+
+    {
+        Size s(123, 456);
+        s.rotate(Rotation::Rotation270);
+        EXPECT_EQ(s, Size(456, 123));
+    }
+}
+
 TEST(SizeTest, ValidAndEmpty) {
     {
         Size s;
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 3651c8b..65e7a7f 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -299,26 +299,24 @@
         sPrimaryDisplayRotationFlags = ui::Transform::toRotationFlags(orientation);
     }
 
-    if (!orientedDisplaySpaceRect.isValid()) {
-        // The destination frame can be invalid if it has never been set,
-        // in that case we assume the whole display size.
-        orientedDisplaySpaceRect =
-                getCompositionDisplay()->getState().displaySpace.getBoundsAsRect();
-    }
-
-    if (layerStackSpaceRect.isEmpty()) {
-        // The layerStackSpaceRect can be invalid if it has never been set, in that case
-        // we assume the whole framebuffer size.
-        layerStackSpaceRect =
-                getCompositionDisplay()->getState().framebufferSpace.getBoundsAsRect();
-        if (orientation == ui::ROTATION_90 || orientation == ui::ROTATION_270) {
-            std::swap(layerStackSpaceRect.right, layerStackSpaceRect.bottom);
-        }
-    }
-
     // We need to take care of display rotation for globalTransform for case if the panel is not
     // installed aligned with device orientation.
     const auto transformOrientation = orientation + mPhysicalOrientation;
+
+    const auto& state = getCompositionDisplay()->getState();
+
+    // If the layer stack and destination frames have never been set, then configure them to be the
+    // same as the physical device, taking into account the total transform.
+    if (!orientedDisplaySpaceRect.isValid()) {
+        ui::Size bounds = state.displaySpace.getBounds();
+        bounds.rotate(transformOrientation);
+        orientedDisplaySpaceRect = Rect(bounds);
+    }
+    if (layerStackSpaceRect.isEmpty()) {
+        ui::Size bounds = state.framebufferSpace.getBounds();
+        bounds.rotate(transformOrientation);
+        layerStackSpaceRect = Rect(bounds);
+    }
     getCompositionDisplay()->setProjection(transformOrientation, layerStackSpaceRect,
                                            orientedDisplaySpaceRect);
 }
diff --git a/services/surfaceflinger/tests/unittests/DisplayDevice_SetProjectionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayDevice_SetProjectionTest.cpp
index 3d24ecb..5734d34 100644
--- a/services/surfaceflinger/tests/unittests/DisplayDevice_SetProjectionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayDevice_SetProjectionTest.cpp
@@ -21,6 +21,7 @@
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
+#include <ui/Rotation.h>
 
 namespace android {
 namespace {
@@ -53,6 +54,11 @@
 
     ui::Size swapWH(const ui::Size size) const { return ui::Size(size.height, size.width); }
 
+    void setDefaultProjection() {
+        // INVALID_RECT pulls from the physical display dimensions.
+        mDisplayDevice->setProjection(ui::ROTATION_0, Rect::INVALID_RECT, Rect::INVALID_RECT);
+    }
+
     void setProjectionForRotation0() {
         // A logical rotation of 0 uses the SurfaceFlinger display size
         mDisplayDevice->setProjection(ui::ROTATION_0, Rect(mFlingerDisplaySize),
@@ -79,6 +85,30 @@
                                       Rect(swapWH(mFlingerDisplaySize)));
     }
 
+    void expectDefaultState() {
+        const auto& compositionState = mDisplayDevice->getCompositionDisplay()->getState();
+        EXPECT_EQ(ui::Transform(ui::Transform::toRotationFlags(mPhysicalOrientation),
+                                mHardwareDisplaySize.width, mHardwareDisplaySize.height),
+                  compositionState.transform);
+        EXPECT_EQ(mPhysicalOrientation, compositionState.displaySpace.getOrientation());
+        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.displaySpace.getContent());
+        EXPECT_EQ(mHardwareDisplaySize, compositionState.displaySpace.getBounds());
+        EXPECT_EQ(Rect(mHardwareDisplaySize), compositionState.framebufferSpace.getContent());
+        EXPECT_EQ(mHardwareDisplaySize, compositionState.framebufferSpace.getBounds());
+
+        const ui::Size expectedLogicalSize = (mPhysicalOrientation == ui::ROTATION_270 ||
+                                              mPhysicalOrientation == ui::ROTATION_90)
+                ? swapWH(mHardwareDisplaySize)
+                : mHardwareDisplaySize;
+
+        EXPECT_EQ(Rect(expectedLogicalSize), compositionState.orientedDisplaySpace.getContent());
+        EXPECT_EQ(expectedLogicalSize, compositionState.orientedDisplaySpace.getBounds());
+        EXPECT_EQ(Rect(expectedLogicalSize), compositionState.layerStackSpace.getContent());
+        EXPECT_EQ(expectedLogicalSize, compositionState.layerStackSpace.getBounds());
+
+        EXPECT_EQ(false, compositionState.needsFiltering);
+    }
+
     void expectStateForHardwareTransform0() {
         const auto& compositionState = mDisplayDevice->getCompositionDisplay()->getState();
         EXPECT_EQ(ui::Transform(TRANSFORM_FLAGS_ROT_0, mHardwareDisplaySize.width,
@@ -147,6 +177,11 @@
                                            ui::ROTATION_0) {}
 };
 
+TEST_F(DisplayDeviceSetProjectionTest_Installed0, checkDefaultProjection) {
+    setDefaultProjection();
+    expectDefaultState();
+}
+
 TEST_F(DisplayDeviceSetProjectionTest_Installed0, checkWith0OutputRotation) {
     setProjectionForRotation0();
     expectStateForHardwareTransform0();
@@ -174,6 +209,11 @@
                                            ui::ROTATION_90) {}
 };
 
+TEST_F(DisplayDeviceSetProjectionTest_Installed90, checkDefaultProjection) {
+    setDefaultProjection();
+    expectDefaultState();
+}
+
 TEST_F(DisplayDeviceSetProjectionTest_Installed90, checkWith0OutputRotation) {
     setProjectionForRotation0();
     expectStateForHardwareTransform90();
@@ -201,6 +241,11 @@
                                            ui::ROTATION_180) {}
 };
 
+TEST_F(DisplayDeviceSetProjectionTest_Installed180, checkDefaultProjection) {
+    setDefaultProjection();
+    expectDefaultState();
+}
+
 TEST_F(DisplayDeviceSetProjectionTest_Installed180, checkWith0OutputRotation) {
     setProjectionForRotation0();
     expectStateForHardwareTransform180();
@@ -228,6 +273,11 @@
                                            ui::ROTATION_270) {}
 };
 
+TEST_F(DisplayDeviceSetProjectionTest_Installed270, checkDefaultProjection) {
+    setDefaultProjection();
+    expectDefaultState();
+}
+
 TEST_F(DisplayDeviceSetProjectionTest_Installed270, checkWith0OutputRotation) {
     setProjectionForRotation0();
     expectStateForHardwareTransform270();