From ccf766b921ee0fdfc64cb1cbf8896f5558cc741f Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Tue, 14 Mar 2023 16:19:37 +0000 Subject: [PATCH] Set app space position to app configuration The frames in ClientWindowFrames for client use app coordinate space, and InsetsState also apply app's scale. So the position of the bounds in Configuration should be consistent with them. So the sandbox calculation such as "displayFrame.left - bounds.left" can be consistent. Previously it may be "appSpace - screenSpace". In general, ActivityRecord#getBounds() is used for window layout in server side so it is in screen space. While record.getWindowConfiguration.getBounds() is used to report to app so it is in app space. Fix: 270401710 Test: SizeCompatTests#testFixedScreenBoundsWhenDisplaySizeChanged SizeCompatTests#testFixedOrientationRotateCutoutDisplay Change-Id: Ife48bd5789db7cb9ba32302b345128cd4419a4b6 --- .../com/android/server/wm/ActivityRecord.java | 16 ++++++++++++++++ .../com/android/server/wm/SizeCompatTests.java | 18 ++++++++++-------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index b946e7e060443..7ada2135212c2 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -8307,6 +8307,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A * requested in the config or via an ADB command. For more context see {@link * LetterboxUiController#getHorizontalPositionMultiplier(Configuration)} and * {@link LetterboxUiController#getVerticalPositionMultiplier(Configuration)} + *

+ * Note that this is the final step that can change the resolved bounds. After this method + * is called, the position of the bounds will be moved to app space as sandboxing if the + * activity has a size compat scale. */ private void updateResolvedBoundsPosition(Configuration newParentConfiguration) { final Configuration resolvedConfig = getResolvedOverrideConfiguration(); @@ -8368,6 +8372,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Since bounds has changed, the configuration needs to be computed accordingly. getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration); + + // The position of configuration bounds were calculated in screen space because that is + // easier to resolve the relative position in parent container. However, if the activity is + // scaled, the position should follow the scale because the configuration will be sent to + // the client which is expected to be in a scaled environment. + if (mSizeCompatScale != 1f) { + final int screenPosX = resolvedBounds.left; + final int screenPosY = resolvedBounds.top; + final int dx = (int) (screenPosX / mSizeCompatScale + 0.5f) - screenPosX; + final int dy = (int) (screenPosY / mSizeCompatScale + 0.5f) - screenPosY; + offsetBounds(resolvedConfig, dx, dy); + } } void recomputeConfiguration() { diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java index d77b6ada268e0..4eb070df0e47b 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -573,11 +573,11 @@ public class SizeCompatTests extends WindowTestsBase { // The scale is 2000/2500=0.8. The horizontal centered offset is (1000-(1000*0.8))/2=100. final float scale = (float) display.mBaseDisplayHeight / currentBounds.height(); final int offsetX = (int) (display.mBaseDisplayWidth - (origBounds.width() * scale)) / 2; - assertEquals(offsetX, currentBounds.left); + final int screenX = mActivity.getBounds().left; + assertEquals(offsetX, screenX); - // The position of configuration bounds should be the same as compat bounds. - assertEquals(mActivity.getBounds().left, currentBounds.left); - assertEquals(mActivity.getBounds().top, currentBounds.top); + // The position of configuration bounds should be in app space. + assertEquals(screenX, (int) (currentBounds.left * scale + 0.5f)); // Activity is sandboxed to the offset size compat bounds. assertActivityMaxBoundsSandboxed(); @@ -607,7 +607,7 @@ public class SizeCompatTests extends WindowTestsBase { // The size should still be in portrait [100, 0 - 1100, 2500] = 1000x2500. assertEquals(origBounds.width(), currentBounds.width()); assertEquals(origBounds.height(), currentBounds.height()); - assertEquals(offsetX, currentBounds.left); + assertEquals(offsetX, mActivity.getBounds().left); assertScaled(); // Activity is sandboxed due to size compat mode. assertActivityMaxBoundsSandboxed(); @@ -770,9 +770,11 @@ public class SizeCompatTests extends WindowTestsBase { assertEquals(origAppBounds.height(), appBounds.height()); // The activity is 1000x1400 and the display is 2500x1000. assertScaled(); - // The position in configuration should be global coordinates. - assertEquals(mActivity.getBounds().left, currentBounds.left); - assertEquals(mActivity.getBounds().top, currentBounds.top); + final float scale = mActivity.getCompatScale(); + // The position in configuration should be in app coordinates. + final Rect screenBounds = mActivity.getBounds(); + assertEquals(screenBounds.left, (int) (currentBounds.left * scale + 0.5f)); + assertEquals(screenBounds.top, (int) (currentBounds.top * scale + 0.5f)); // Activity max bounds are sandboxed due to size compat mode. assertActivityMaxBoundsSandboxed();