diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index 9f68d627622cc..56e404c8f4093 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -7786,42 +7786,40 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A /** Gets the horizontal centered container bounds for size compatibility mode. */ void getContainerBounds(Rect outAppBounds, Rect outBounds, int rotation, int orientation, boolean orientationRequested, boolean canChangeOrientation) { + getFrameByOrientation(outBounds, orientation); if (mIsFloating) { - getFrameByOrientation(outBounds, orientation); outAppBounds.set(outBounds); return; } - if (canChangeOrientation) { - getBoundsByRotation(outBounds, rotation); - if (orientationRequested) { - getFrameByOrientation(outAppBounds, orientation); - } else { - outAppBounds.set(outBounds); - } - } else { - if (orientationRequested) { - getFrameByOrientation(outBounds, orientation); - if ((outBounds.width() > outBounds.height()) != (mWidth > mHeight)) { - // The orientation is mismatched but the display cannot rotate. The bounds - // will fit to the short side of display. - if (orientation == ORIENTATION_LANDSCAPE) { - outBounds.bottom = (int) ((float) mWidth * mWidth / mHeight); - outBounds.right = mWidth; - } else { - outBounds.bottom = mHeight; - outBounds.right = (int) ((float) mHeight * mHeight / mWidth); - } - outBounds.offset( - getHorizontalCenterOffset(mWidth, outBounds.width()), 0 /* dy */); - } - } else { - outBounds.set(0, 0, mWidth, mHeight); - } - outAppBounds.set(outBounds); - } + getBoundsByRotation(outAppBounds, rotation); + final int dW = outAppBounds.width(); + final int dH = outAppBounds.height(); + final boolean isOrientationMismatched = + ((outBounds.width() > outBounds.height()) != (dW > dH)); - if (rotation != ROTATION_UNDEFINED) { + if (isOrientationMismatched && !canChangeOrientation && orientationRequested) { + // The orientation is mismatched but the display cannot rotate. The bounds will fit + // to the short side of container. + if (orientation == ORIENTATION_LANDSCAPE) { + outBounds.bottom = (int) ((float) dW * dW / dH); + outBounds.right = dW; + } else { + outBounds.bottom = dH; + outBounds.right = (int) ((float) dH * dH / dW); + } + outBounds.offset(getHorizontalCenterOffset(mWidth, outBounds.width()), 0 /* dy */); + } + outAppBounds.set(outBounds); + + if (isOrientationMismatched) { + // One side of container is smaller than the requested size, then it will be scaled + // and the final position will be calculated according to the parent container and + // scale, so the original size shouldn't be shrunk by insets. + final Rect insets = mNonDecorInsets[rotation]; + outBounds.offset(insets.left, insets.top); + outAppBounds.offset(insets.left, insets.top); + } else if (rotation != ROTATION_UNDEFINED) { // Ensure the app bounds won't overlap with insets. Task.intersectWithInsetsIfFits(outAppBounds, outBounds, mNonDecorInsets[rotation]); } 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 6c648a8948217..468b2c35ffc2e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -35,7 +35,9 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.doCallRealMethod; import android.app.ActivityManager; import android.app.ActivityManagerInternal; @@ -216,22 +218,50 @@ public class SizeCompatTests extends WindowTestsBase { final Rect origBounds = new Rect(mActivity.getBounds()); final Rect currentBounds = mActivity.getWindowConfiguration().getBounds(); + final DisplayContent display = mActivity.mDisplayContent; // Change the size of current display. - resizeDisplay(mStack.mDisplayContent, 1000, 2000); - + resizeDisplay(display, 1000, 2000); + // The bounds should be [100, 0 - 1100, 2500]. assertEquals(origBounds.width(), currentBounds.width()); assertEquals(origBounds.height(), currentBounds.height()); assertScaled(); + // 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); + // The position of configuration bounds should be the same as compat bounds. assertEquals(mActivity.getBounds().left, currentBounds.left); assertEquals(mActivity.getBounds().top, currentBounds.top); // Change display size to a different orientation - resizeDisplay(mStack.mDisplayContent, 2000, 1000); + resizeDisplay(display, 2000, 1000); + // The bounds should be [800, 0 - 1800, 2500]. assertEquals(origBounds.width(), currentBounds.width()); assertEquals(origBounds.height(), currentBounds.height()); + assertEquals(Configuration.ORIENTATION_LANDSCAPE, display.getConfiguration().orientation); + assertEquals(Configuration.ORIENTATION_PORTRAIT, mActivity.getConfiguration().orientation); + + // The previous resize operation doesn't consider the rotation change after size changed. + // These setups apply the requested orientation to rotation as real case that the top fixed + // portrait activity will determine the display rotation. + final DisplayRotation displayRotation = display.getDisplayRotation(); + doCallRealMethod().when(displayRotation).updateRotationUnchecked(anyBoolean()); + // Skip unrelated layout procedures. + mAtm.deferWindowLayout(); + display.reconfigureDisplayLocked(); + displayRotation.updateOrientation(display.getOrientation(), true /* forceUpdate */); + display.sendNewConfiguration(); + + assertEquals(Configuration.ORIENTATION_PORTRAIT, display.getConfiguration().orientation); + assertEquals(Configuration.ORIENTATION_PORTRAIT, mActivity.getConfiguration().orientation); + // 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); + assertScaled(); } @Test