Set better defaults for layer stack and oriented display space
When the device is not logically rotated and there is a 90 degree or 270
degree physical installation, then the content rectangle and bounds of
the layer stack space and the oriented display space must be consistent with
the framebuffer space and un-oriented display space. That is, if the
framebuffer space and un-oriented display space are in portrait, then the
layer stack space and the oriented display space should be in landscape
without any cropping effects.
Prior to this patch, devices with a rotated physical install orientation
would have its boot animation cropped due to the mismatch in the logical
display space and physical display space
Bug: 203165976
Test: boot animation is not cropped
Change-Id: I965b6c0578e982fe1b2a4dbdb18c24b5922388a9
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();