From 29f24a134c8c1bf6ddd2cf810e62c58f047fd3c8 Mon Sep 17 00:00:00 2001 From: Chris Li Date: Thu, 18 Feb 2021 14:01:51 -0800 Subject: [PATCH] DisplayContent rotateBounds not keeping same physical position for 180 Rotation_90 + rotation_90 is different from the result of rotation_180 with the current implementation. Should also take care of rotation_180. Fix: 180751251 Bug: 173124775 Test: atest WmTests:DisplayContentTests Test: atest WMShellUnitTests:DisplayLayoutTest Test: atest FrameworksCoreTests:RotationUtilsTest Change-Id: Ia1c87409b4c4cc412c3fd89e58d08b6ae2069fd0 --- core/java/android/util/RotationUtils.java | 55 ++++++++++++++ .../src/android/util/RotationUtilsTest.java | 61 +++++++++++++++ .../wm/shell/common/DisplayLayout.java | 38 +--------- .../LegacySplitDisplayLayout.java | 3 +- .../wm/shell/pip/PipAnimationController.java | 4 +- .../wm/shell/common/DisplayLayoutTest.java | 18 ++--- .../shell/pip/PipAnimationControllerTest.java | 4 +- .../com/android/server/wm/DisplayContent.java | 76 +++---------------- .../com/android/server/wm/DisplayPolicy.java | 16 +++- .../android/server/wm/DisplayRotation.java | 3 +- .../server/wm/ScreenRotationAnimation.java | 8 +- .../core/java/com/android/server/wm/Task.java | 4 +- .../server/wm/DisplayContentTests.java | 32 ++++++++ 13 files changed, 194 insertions(+), 128 deletions(-) create mode 100644 core/tests/coretests/src/android/util/RotationUtilsTest.java diff --git a/core/java/android/util/RotationUtils.java b/core/java/android/util/RotationUtils.java index 698cb77947cfe..0ac2c9c25ad1c 100644 --- a/core/java/android/util/RotationUtils.java +++ b/core/java/android/util/RotationUtils.java @@ -24,6 +24,7 @@ import static android.view.Surface.ROTATION_90; import android.annotation.Dimension; import android.graphics.Insets; import android.graphics.Matrix; +import android.graphics.Rect; import android.view.Surface.Rotation; /** @@ -72,6 +73,60 @@ public class RotationUtils { return rotated; } + /** + * Rotates bounds as if parentBounds and bounds are a group. The group is rotated from + * oldRotation to newRotation. This assumes that parentBounds is at 0,0 and remains at 0,0 after + * rotation. The bounds will be at the same physical position in parentBounds. + * + * Only 'inOutBounds' is mutated. + */ + public static void rotateBounds(Rect inOutBounds, Rect parentBounds, @Rotation int oldRotation, + @Rotation int newRotation) { + rotateBounds(inOutBounds, parentBounds, deltaRotation(oldRotation, newRotation)); + } + + /** + * Rotates bounds as if parentBounds and bounds are a group. The group is rotated by `delta` + * 90-degree counter-clockwise increments. This assumes that parentBounds is at 0,0 and + * remains at 0,0 after rotation. The bounds will be at the same physical position in + * parentBounds. + * + * Only 'inOutBounds' is mutated. + */ + public static void rotateBounds(Rect inOutBounds, Rect parentBounds, @Rotation int rotation) { + final int origLeft = inOutBounds.left; + final int origTop = inOutBounds.top; + switch (rotation) { + case ROTATION_0: + return; + case ROTATION_90: + inOutBounds.left = inOutBounds.top; + inOutBounds.top = parentBounds.right - inOutBounds.right; + inOutBounds.right = inOutBounds.bottom; + inOutBounds.bottom = parentBounds.right - origLeft; + return; + case ROTATION_180: + inOutBounds.left = parentBounds.right - inOutBounds.right; + inOutBounds.right = parentBounds.right - origLeft; + inOutBounds.top = parentBounds.bottom - inOutBounds.bottom; + inOutBounds.bottom = parentBounds.bottom - origTop; + return; + case ROTATION_270: + inOutBounds.left = parentBounds.bottom - inOutBounds.bottom; + inOutBounds.bottom = inOutBounds.right; + inOutBounds.right = parentBounds.bottom - inOutBounds.top; + inOutBounds.top = origLeft; + } + } + + /** @return the rotation needed to rotate from oldRotation to newRotation. */ + @Rotation + public static int deltaRotation(int oldRotation, int newRotation) { + int delta = newRotation - oldRotation; + if (delta < 0) delta += 4; + return delta; + } + /** * Sets a matrix such that given a rotation, it transforms physical display * coordinates to that rotation's logical coordinates. diff --git a/core/tests/coretests/src/android/util/RotationUtilsTest.java b/core/tests/coretests/src/android/util/RotationUtilsTest.java new file mode 100644 index 0000000000000..5dbe03e8b42bd --- /dev/null +++ b/core/tests/coretests/src/android/util/RotationUtilsTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.util; + +import static android.util.RotationUtils.rotateBounds; +import static android.view.Surface.ROTATION_180; +import static android.view.Surface.ROTATION_270; +import static android.view.Surface.ROTATION_90; + +import static org.junit.Assert.assertEquals; + +import android.graphics.Rect; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Tests for {@link RotationUtils}. + * + * Build/Install/Run: + * atest FrameworksCoreTests:RotationUtilsTest + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class RotationUtilsTest { + + @Test + public void testRotateBounds() { + Rect testParent = new Rect(0, 0, 1000, 600); + Rect testInner = new Rect(40, 20, 120, 80); + + Rect testResult = new Rect(testInner); + rotateBounds(testResult, testParent, ROTATION_90); + assertEquals(new Rect(20, 880, 80, 960), testResult); + + testResult.set(testInner); + rotateBounds(testResult, testParent, ROTATION_180); + assertEquals(new Rect(880, 520, 960, 580), testResult); + + testResult.set(testInner); + rotateBounds(testResult, testParent, ROTATION_270); + assertEquals(new Rect(520, 40, 580, 120), testResult); + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java index 58a4baf396141..4564af438f320 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java @@ -22,6 +22,8 @@ import static android.content.res.Configuration.UI_MODE_TYPE_CAR; import static android.content.res.Configuration.UI_MODE_TYPE_MASK; import static android.os.Process.SYSTEM_UID; import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS; +import static android.util.RotationUtils.rotateBounds; +import static android.util.RotationUtils.rotateInsets; import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_270; @@ -37,7 +39,6 @@ import android.graphics.Rect; import android.os.SystemProperties; import android.provider.Settings; import android.util.DisplayMetrics; -import android.util.RotationUtils; import android.util.Size; import android.view.Display; import android.view.DisplayCutout; @@ -240,38 +241,6 @@ public class DisplayLayout { return navigationBarPosition(res, mWidth, mHeight, mRotation); } - /** - * Rotates bounds as if parentBounds and bounds are a group. The group is rotated by `delta` - * 90-degree counter-clockwise increments. This assumes that parentBounds is at 0,0 and - * remains at 0,0 after rotation. - * - * Only 'bounds' is mutated. - */ - public static void rotateBounds(Rect inOutBounds, Rect parentBounds, int delta) { - int rdelta = ((delta % 4) + 4) % 4; - int origLeft = inOutBounds.left; - switch (rdelta) { - case 0: - return; - case 1: - inOutBounds.left = inOutBounds.top; - inOutBounds.top = parentBounds.right - inOutBounds.right; - inOutBounds.right = inOutBounds.bottom; - inOutBounds.bottom = parentBounds.right - origLeft; - return; - case 2: - inOutBounds.left = parentBounds.right - inOutBounds.right; - inOutBounds.right = parentBounds.right - origLeft; - return; - case 3: - inOutBounds.left = parentBounds.bottom - inOutBounds.bottom; - inOutBounds.bottom = inOutBounds.right; - inOutBounds.right = parentBounds.bottom - inOutBounds.top; - inOutBounds.top = origLeft; - return; - } - } - /** * Calculates the stable insets if we already have the non-decor insets. */ @@ -359,8 +328,7 @@ public class DisplayLayout { if (rotation == ROTATION_0) { return computeSafeInsets(cutout, displayWidth, displayHeight); } - final Insets waterfallInsets = - RotationUtils.rotateInsets(cutout.getWaterfallInsets(), rotation); + final Insets waterfallInsets = rotateInsets(cutout.getWaterfallInsets(), rotation); final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270); Rect[] cutoutRects = cutout.getBoundingRectsAll(); final Rect[] newBounds = new Rect[cutoutRects.length]; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java index 477ec339f1db8..40244fbb45037 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/legacysplitscreen/LegacySplitDisplayLayout.java @@ -18,6 +18,7 @@ package com.android.wm.shell.legacysplitscreen; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; +import static android.util.RotationUtils.rotateBounds; import static android.view.WindowManager.DOCKED_BOTTOM; import static android.view.WindowManager.DOCKED_INVALID; import static android.view.WindowManager.DOCKED_LEFT; @@ -244,7 +245,7 @@ public class LegacySplitDisplayLayout { DividerSnapAlgorithm snap = initSnapAlgorithmForRotation(context, tmpDL, dividerSize); tmpRect.set(bounds); - DisplayLayout.rotateBounds(tmpRect, displayRect, rotation - dl.rotation()); + rotateBounds(tmpRect, displayRect, dl.rotation(), rotation); rotatedDisplayRect.set(0, 0, tmpDL.width(), tmpDL.height()); final int dockSide = getPrimarySplitSide(tmpRect, rotatedDisplayRect, tmpDL.getOrientation()); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java index 5ffa9885a1437..66560d339c5a6 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java @@ -16,6 +16,7 @@ package com.android.wm.shell.pip; +import static android.util.RotationUtils.rotateBounds; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; @@ -33,7 +34,6 @@ import android.view.SurfaceControl; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.SfVsyncFrameCallbackProvider; import com.android.wm.shell.animation.Interpolators; -import com.android.wm.shell.common.DisplayLayout; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -448,7 +448,7 @@ public class PipAnimationController { // Rotate the end bounds according to the rotation delta because the display will // be rotated to the same orientation. rotatedEndRect = new Rect(endValue); - DisplayLayout.rotateBounds(rotatedEndRect, endValue, rotationDelta); + rotateBounds(rotatedEndRect, endValue, rotationDelta); } else { rotatedEndRect = null; } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java index 2b5b77e49e3ab..88e754c587925 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java @@ -38,6 +38,12 @@ import com.android.internal.R; import org.junit.Test; +/** + * Tests for {@link DisplayLayout}. + * + * Build/Install/Run: + * atest WMShellUnitTests:DisplayLayoutTest + */ @SmallTest public class DisplayLayoutTest { @@ -70,18 +76,6 @@ public class DisplayLayoutTest { @Test public void testRotate() { // Basic rotate utility - Rect testParent = new Rect(0, 0, 1000, 600); - Rect testInner = new Rect(40, 20, 120, 80); - Rect testResult = new Rect(testInner); - DisplayLayout.rotateBounds(testResult, testParent, 1); - assertEquals(new Rect(20, 880, 80, 960), testResult); - testResult.set(testInner); - DisplayLayout.rotateBounds(testResult, testParent, 2); - assertEquals(new Rect(880, 20, 960, 80), testResult); - testResult.set(testInner); - DisplayLayout.rotateBounds(testResult, testParent, 3); - assertEquals(new Rect(520, 40, 580, 120), testResult); - Resources res = createResources(40, 50, false, 30, 40); DisplayInfo info = createDisplayInfo(1000, 1500, 60, ROTATION_0); DisplayLayout dl = new DisplayLayout(info, res, true, true); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java index 3147dab1a0f82..63b94139dd9c8 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/pip/PipAnimationControllerTest.java @@ -16,6 +16,7 @@ package com.android.wm.shell.pip; +import static android.util.RotationUtils.rotateBounds; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_90; @@ -37,7 +38,6 @@ import android.view.SurfaceControl; import androidx.test.filters.SmallTest; import com.android.wm.shell.ShellTestCase; -import com.android.wm.shell.common.DisplayLayout; import org.junit.Before; import org.junit.Test; @@ -141,7 +141,7 @@ public class PipAnimationControllerTest extends ShellTestCase { // Apply fraction 1 to compute the end value. animator.applySurfaceControlTransaction(mLeash, new DummySurfaceControlTx(), 1); final Rect rotatedEndBounds = new Rect(endBounds); - DisplayLayout.rotateBounds(rotatedEndBounds, endBounds, ROTATION_90); + rotateBounds(rotatedEndBounds, endBounds, ROTATION_90); assertEquals("Expect 90 degree rotated bounds", rotatedEndBounds, animator.mCurrentValue); } diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 0143e70f53ca3..4bc49d833e539 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -36,6 +36,7 @@ import static android.content.res.Configuration.ORIENTATION_UNDEFINED; import static android.os.Build.VERSION_CODES.N; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; import static android.util.DisplayMetrics.DENSITY_DEFAULT; +import static android.util.RotationUtils.deltaRotation; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; import static android.view.Display.FLAG_PRIVATE; @@ -47,7 +48,6 @@ import static android.view.InsetsState.ITYPE_LEFT_GESTURES; import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_RIGHT_GESTURES; import static android.view.Surface.ROTATION_0; -import static android.view.Surface.ROTATION_180; import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; import static android.view.View.GONE; @@ -158,10 +158,8 @@ import android.content.res.CompatibilityInfo; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Insets; -import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; -import android.graphics.RectF; import android.graphics.Region; import android.graphics.Region.Op; import android.hardware.HardwareBuffer; @@ -206,6 +204,7 @@ import android.view.MagnificationSpec; import android.view.RemoteAnimationDefinition; import android.view.RoundedCorners; import android.view.Surface; +import android.view.Surface.Rotation; import android.view.SurfaceControl; import android.view.SurfaceControl.Transaction; import android.view.SurfaceSession; @@ -449,8 +448,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp /** Save allocating when calculating rects */ private final Rect mTmpRect = new Rect(); private final Rect mTmpRect2 = new Rect(); - private final RectF mTmpRectF = new RectF(); - private final Matrix mTmpMatrix = new Matrix(); private final Region mTmpRegion = new Region(); /** Used for handing back size of display */ @@ -1289,7 +1286,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return mInsetsPolicy; } - @Surface.Rotation + @Rotation int getRotation() { return mDisplayRotation.getRotation(); } @@ -1479,7 +1476,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * Returns a valid rotation if the activity can use different orientation than the display. * Otherwise {@link #ROTATION_UNDEFINED}. */ - @Surface.Rotation + @Rotation int rotationForActivityInDifferentOrientation(@NonNull ActivityRecord r) { if (!WindowManagerService.ENABLE_FIXED_ROTATION_TRANSFORM) { return ROTATION_UNDEFINED; @@ -1614,7 +1611,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp * Sets the provided record to {@link #mFixedRotationLaunchingApp} if possible to apply fixed * rotation transform to it and indicate that the display may be rotated after it is launched. */ - void setFixedRotationLaunchingApp(@NonNull ActivityRecord r, @Surface.Rotation int rotation) { + void setFixedRotationLaunchingApp(@NonNull ActivityRecord r, @Rotation int rotation) { final WindowToken prevRotatedLaunchingApp = mFixedRotationLaunchingApp; if (prevRotatedLaunchingApp == r && r.getWindowConfiguration().getRotation() == rotation) { @@ -2951,27 +2948,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp forAllRootTasks(Task::prepareFreezingTaskBounds); } - void rotateBounds(int oldRotation, int newRotation, Rect bounds) { - getBounds(mTmpRect, newRotation); - rotateBounds(mTmpRect, oldRotation, newRotation, bounds); - } - - void rotateBounds(Rect parentBounds, int oldRotation, int newRotation, Rect bounds) { - // Compute a transform matrix to undo the coordinate space transformation, - // and present the window at the same physical position it previously occupied. - final int deltaRotation = deltaRotation(newRotation, oldRotation); - createRotationMatrix( - deltaRotation, parentBounds.width(), parentBounds.height(), mTmpMatrix); - - mTmpRectF.set(bounds); - mTmpMatrix.mapRect(mTmpRectF); - mTmpRectF.round(bounds); - } - - static int deltaRotation(int oldRotation, int newRotation) { - int delta = newRotation - oldRotation; - if (delta < 0) delta += 4; - return delta; + void rotateBounds(@Rotation int oldRotation, @Rotation int newRotation, Rect inOutBounds) { + // Get display bounds on oldRotation as parent bounds for the rotation. + getBounds(mTmpRect, oldRotation); + RotationUtils.rotateBounds(inOutBounds, mTmpRect, oldRotation, newRotation); } public void setRotationAnimation(ScreenRotationAnimation screenRotationAnimation) { @@ -2985,35 +2965,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp return mScreenRotationAnimation; } - private static void createRotationMatrix(int rotation, float displayWidth, float displayHeight, - Matrix outMatrix) { - // For rotations without Z-ordering we don't need the target rectangle's position. - createRotationMatrix(rotation, 0 /* rectLeft */, 0 /* rectTop */, displayWidth, - displayHeight, outMatrix); - } - - static void createRotationMatrix(int rotation, float rectLeft, float rectTop, - float displayWidth, float displayHeight, Matrix outMatrix) { - switch (rotation) { - case ROTATION_0: - outMatrix.reset(); - break; - case ROTATION_270: - outMatrix.setRotate(270, 0, 0); - outMatrix.postTranslate(0, displayHeight); - outMatrix.postTranslate(rectTop, 0); - break; - case ROTATION_180: - outMatrix.reset(); - break; - case ROTATION_90: - outMatrix.setRotate(90, 0, 0); - outMatrix.postTranslate(displayWidth, 0); - outMatrix.postTranslate(-rectTop, rectLeft); - break; - } - } - @Override public void dumpDebug(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel) { @@ -4289,17 +4240,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp out.set(left, top, left + width, top + height); } - private void getBounds(Rect out, int orientation) { + private void getBounds(Rect out, @Rotation int rotation) { getBounds(out); // Rotate the Rect if needed. final int currentRotation = mDisplayInfo.rotation; - final int rotationDelta = deltaRotation(currentRotation, orientation); + final int rotationDelta = deltaRotation(currentRotation, rotation); if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) { - createRotationMatrix(rotationDelta, mBaseDisplayWidth, mBaseDisplayHeight, mTmpMatrix); - mTmpRectF.set(out); - mTmpMatrix.mapRect(mTmpRectF); - mTmpRectF.round(out); + out.set(0, 0, out.height(), out.width()); } } diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java index 5460e36a5f1b4..f64f04cc08296 100644 --- a/services/core/java/com/android/server/wm/DisplayPolicy.java +++ b/services/core/java/com/android/server/wm/DisplayPolicy.java @@ -24,6 +24,8 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMAR import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; import static android.content.res.Configuration.UI_MODE_TYPE_CAR; import static android.content.res.Configuration.UI_MODE_TYPE_MASK; +import static android.util.RotationUtils.deltaRotation; +import static android.util.RotationUtils.rotateBounds; import static android.view.Display.TYPE_INTERNAL; import static android.view.InsetsState.ITYPE_BOTTOM_MANDATORY_GESTURES; import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT; @@ -1046,11 +1048,17 @@ public class DisplayPolicy { return; } - // Get displayFrames bounds - sTmpDisplayFrameBounds.set(0, 0, displayFrames.mDisplayWidth, displayFrames.mDisplayHeight); + // Get displayFrames bounds as it is on WindowState's rotation. + final int deltaRotation = deltaRotation(windowRotation, displayFrames.mRotation); + if (deltaRotation == Surface.ROTATION_90 || deltaRotation == Surface.ROTATION_270) { + sTmpDisplayFrameBounds.set( + 0, 0, displayFrames.mDisplayHeight, displayFrames.mDisplayWidth); + } else { + sTmpDisplayFrameBounds.set( + 0, 0, displayFrames.mDisplayWidth, displayFrames.mDisplayHeight); + } // Rotate the WindowState's bounds based on the displayFrames rotation - mDisplayContent.rotateBounds(sTmpDisplayFrameBounds, windowRotation, - displayFrames.mRotation, outBounds); + rotateBounds(outBounds, sTmpDisplayFrameBounds, deltaRotation); } /** diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java index d5ded97ee0b90..63cb38a593491 100644 --- a/services/core/java/com/android/server/wm/DisplayRotation.java +++ b/services/core/java/com/android/server/wm/DisplayRotation.java @@ -17,6 +17,7 @@ package com.android.server.wm; import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; +import static android.util.RotationUtils.deltaRotation; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT; import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE; @@ -475,7 +476,7 @@ public class DisplayRotation { "Display id=%d rotation changed to %d from %d, lastOrientation=%d", displayId, rotation, oldRotation, lastOrientation); - if (DisplayContent.deltaRotation(rotation, oldRotation) != 2) { + if (deltaRotation(oldRotation, rotation) != Surface.ROTATION_180) { mDisplayContent.mWaitingForConfig = true; } diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java index 533c82e599c9f..95a4f69edd575 100644 --- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java +++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java @@ -17,6 +17,7 @@ package com.android.server.wm; import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; +import static android.util.RotationUtils.deltaRotation; import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; @@ -174,7 +175,7 @@ class ScreenRotationAnimation { // apply rotation animation because there should be a top app shown as rotated. So the // specified original rotation customizes the direction of animation to have better look // when restoring the rotated app to the same rotation as current display. - final int delta = DisplayContent.deltaRotation(originalRotation, realOriginalRotation); + final int delta = deltaRotation(originalRotation, realOriginalRotation); final boolean flipped = delta == Surface.ROTATION_90 || delta == Surface.ROTATION_270; mOriginalWidth = flipped ? originalHeight : originalWidth; mOriginalHeight = flipped ? originalWidth : originalHeight; @@ -330,7 +331,7 @@ class ScreenRotationAnimation { // Compute the transformation matrix that must be applied // to the snapshot to make it stay in the same original position // with the current screen rotation. - int delta = DisplayContent.deltaRotation(rotation, Surface.ROTATION_0); + int delta = deltaRotation(rotation, Surface.ROTATION_0); RotationAnimationUtils.createRotationMatrix(delta, mWidth, mHeight, mSnapshotInitialMatrix); setRotationTransform(t, mSnapshotInitialMatrix); @@ -352,8 +353,7 @@ class ScreenRotationAnimation { mStarted = true; // Figure out how the screen has moved from the original rotation. - int delta = DisplayContent.deltaRotation(mCurRotation, mOriginalRotation); - + int delta = deltaRotation(mCurRotation, mOriginalRotation); final boolean customAnim; if (exitAnim != 0 && enterAnim != 0) { diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index d60b6e0ef81db..7238fd6fa7475 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -2361,9 +2361,7 @@ class Task extends WindowContainer { final int newRotation = getWindowConfiguration().getRotation(); final boolean rotationChanged = prevRotation != newRotation; if (rotationChanged) { - mDisplayContent.rotateBounds( - newParentConfig.windowConfiguration.getBounds(), prevRotation, newRotation, - newBounds); + mDisplayContent.rotateBounds(prevRotation, newRotation, newBounds); setBounds(newBounds); } } diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java index dc702e6bc5728..c216bfa90571f 100644 --- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java @@ -33,6 +33,7 @@ import static android.view.InsetsState.ITYPE_NAVIGATION_BAR; import static android.view.InsetsState.ITYPE_STATUS_BAR; import static android.view.Surface.ROTATION_0; import static android.view.Surface.ROTATION_180; +import static android.view.Surface.ROTATION_270; import static android.view.Surface.ROTATION_90; import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE; import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW; @@ -1845,6 +1846,37 @@ public class DisplayContentTests extends WindowTestsBase { verify(t).show(mDisplayContent.mImeScreenshot); } + @Test + public void testRotateBounds_keepSamePhysicalPosition() { + final DisplayContent dc = + new TestDisplayContent.Builder(mAtm, 1000, 2000).build(); + final Rect initBounds = new Rect(0, 0, 700, 1500); + final Rect rotateBounds = new Rect(initBounds); + + // Rotate from 0 to 0 + dc.rotateBounds(ROTATION_0, ROTATION_0, rotateBounds); + + assertEquals(new Rect(0, 0, 700, 1500), rotateBounds); + + // Rotate from 0 to 90 + rotateBounds.set(initBounds); + dc.rotateBounds(ROTATION_0, ROTATION_90, rotateBounds); + + assertEquals(new Rect(0, 300, 1500, 1000), rotateBounds); + + // Rotate from 0 to 180 + rotateBounds.set(initBounds); + dc.rotateBounds(ROTATION_0, ROTATION_180, rotateBounds); + + assertEquals(new Rect(300, 500, 1000, 2000), rotateBounds); + + // Rotate from 0 to 270 + rotateBounds.set(initBounds); + dc.rotateBounds(ROTATION_0, ROTATION_270, rotateBounds); + + assertEquals(new Rect(500, 0, 2000, 700), rotateBounds); + } + private boolean isOptionsPanelAtRight(int displayId) { return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT; }