Undo rotation by physical orientation in WindowInfo transforms
Some devices have a their display panels installed in a different
orientation than the expected default orientation. This can be
configured through the build prop
ro.surface_flinger.primary_display_orientation, or through other means.
Input, framework, and other services are not concerned with the display
panel orientation. In this CL, we rotate the transforms sent in
WindowInfo by the inverse of the physical orientation, making the window
transforms relative to WM's ROTATION_0 instead of the display panel
orientation.
Bug: 179274888
Bug: 195617582
Bug: 195586068
Test: manual with device that has a non-standard display panel
installation
Test: atest com.android.launcher3.ui.TaplTestsLauncher3
Change-Id: I727b22c004014355f337da2b753b61c5946667d0
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index d27b51b..b76ffc4 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2181,11 +2181,11 @@
}
const ui::Transform layerTransform = getInputTransform();
- // Transform that takes window coordinates to unrotated display coordinates
+ // Transform that takes window coordinates to non-rotated display coordinates
ui::Transform t = displayTransform * layerTransform;
int32_t xSurfaceInset = info.surfaceInset;
int32_t ySurfaceInset = info.surfaceInset;
- // Bring screenBounds into unrotated space
+ // Bring screenBounds into non-unrotated space
Rect screenBounds = displayTransform.transform(Rect{mScreenBounds});
const float xScale = t.getScaleX();
@@ -2279,17 +2279,34 @@
info.id = sequence;
info.displayId = getLayerStack().id;
- // Transform that maps from LayerStack space to display space, e.g. rotated to unrotated.
+ // Transform that maps from LayerStack space to display space, e.g. rotated to non-rotated.
// Used when InputFlinger operates in display space.
ui::Transform displayTransform;
if (display) {
- displayTransform = display->getTransform();
- // getOrientation() without masking can contain more-significant bits (eg. ROT_INVALID).
- constexpr uint32_t kAllRotationsMask =
- ui::Transform::ROT_90 | ui::Transform::ROT_180 | ui::Transform::ROT_270;
- info.displayOrientation = displayTransform.getOrientation() & kAllRotationsMask;
- info.displayWidth = display->getWidth();
- info.displayHeight = display->getHeight();
+ // The physical orientation is set when the orientation of the display panel is different
+ // than the default orientation of the device. Other services like InputFlinger do not know
+ // about this, so we do not need to expose the physical orientation of the panel outside of
+ // SurfaceFlinger.
+ const ui::Rotation inversePhysicalOrientation =
+ ui::ROTATION_0 - display->getPhysicalOrientation();
+ auto width = display->getWidth();
+ auto height = display->getHeight();
+ if (inversePhysicalOrientation == ui::ROTATION_90 ||
+ inversePhysicalOrientation == ui::ROTATION_270) {
+ std::swap(width, height);
+ }
+ const ui::Transform undoPhysicalOrientation(ui::Transform::toRotationFlags(
+ inversePhysicalOrientation),
+ width, height);
+ displayTransform = undoPhysicalOrientation * display->getTransform();
+
+ // Send the inverse of the display orientation so that input can transform points back to
+ // the rotated display space.
+ const ui::Rotation inverseOrientation = ui::ROTATION_0 - display->getOrientation();
+ info.displayOrientation = ui::Transform::toRotationFlags(inverseOrientation);
+
+ info.displayWidth = width;
+ info.displayHeight = height;
}
fillInputFrameInfo(info, displayTransform);