diff --git a/services/core/java/com/android/server/wm/LaunchParamsUtil.java b/services/core/java/com/android/server/wm/LaunchParamsUtil.java index 91469a065eeca..09a17e166f46e 100644 --- a/services/core/java/com/android/server/wm/LaunchParamsUtil.java +++ b/services/core/java/com/android/server/wm/LaunchParamsUtil.java @@ -46,6 +46,8 @@ class LaunchParamsUtil { private static final int DISPLAY_EDGE_OFFSET_DP = 27; + private static final Rect TMP_STABLE_BOUNDS = new Rect(); + private LaunchParamsUtil() {} /** @@ -130,18 +132,42 @@ class LaunchParamsUtil { return new Size(adjWidth, adjHeight); } - static void adjustBoundsToFitInDisplayArea(@NonNull Rect stableBounds, int layoutDirection, + static void adjustBoundsToFitInDisplayArea(@NonNull TaskDisplayArea displayArea, + int layoutDirection, @NonNull ActivityInfo.WindowLayout layout, @NonNull Rect inOutBounds) { + // Give a small margin between the window bounds and the display bounds. + final Rect stableBounds = TMP_STABLE_BOUNDS; + displayArea.getStableRect(stableBounds); + final float density = (float) displayArea.getConfiguration().densityDpi / DENSITY_DEFAULT; + final int displayEdgeOffset = (int) (DISPLAY_EDGE_OFFSET_DP * density + 0.5f); + stableBounds.inset(displayEdgeOffset, displayEdgeOffset); + if (stableBounds.width() < inOutBounds.width() || stableBounds.height() < inOutBounds.height()) { - // There is no way for us to fit the bounds in the displayArea without changing width - // or height. Just move the start to align with the displayArea. - final int left = layoutDirection == View.LAYOUT_DIRECTION_RTL - ? stableBounds.right - inOutBounds.right + inOutBounds.left - : stableBounds.left; - inOutBounds.offsetTo(left, stableBounds.top); - return; + final float heightShrinkRatio = stableBounds.width() / (float) inOutBounds.width(); + final float widthShrinkRatio = + stableBounds.height() / (float) inOutBounds.height(); + final float shrinkRatio = Math.min(heightShrinkRatio, widthShrinkRatio); + // Minimum layout requirements. + final int layoutMinWidth = (layout == null) ? -1 : layout.minWidth; + final int layoutMinHeight = (layout == null) ? -1 : layout.minHeight; + int adjustedWidth = Math.max(layoutMinWidth, (int) (inOutBounds.width() * shrinkRatio)); + int adjustedHeight = Math.max(layoutMinHeight, + (int) (inOutBounds.height() * shrinkRatio)); + if (stableBounds.width() < adjustedWidth + || stableBounds.height() < adjustedHeight) { + // There is no way for us to fit the bounds in the displayArea without breaking min + // size constraints. Set the min size to make visible as much content as possible. + final int left = layoutDirection == View.LAYOUT_DIRECTION_RTL + ? stableBounds.right - adjustedWidth + : stableBounds.left; + inOutBounds.set(left, stableBounds.top, left + adjustedWidth, + stableBounds.top + adjustedHeight); + return; + } + inOutBounds.set(inOutBounds.left, inOutBounds.top, + inOutBounds.left + adjustedWidth, inOutBounds.top + adjustedHeight); } final int dx; diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java index f51a173924cb6..14a2d0383019e 100644 --- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java +++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java @@ -768,9 +768,10 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { // to the center of suggested bounds (or the displayArea if no suggested bounds). The // default size might be too big to center to source activity bounds in displayArea, so // we may need to move it back to the displayArea. + adjustBoundsToFitInDisplayArea(displayArea, layout, mTmpBounds); + inOutBounds.setEmpty(); LaunchParamsUtil.centerBounds(displayArea, mTmpBounds.width(), mTmpBounds.height(), inOutBounds); - adjustBoundsToFitInDisplayArea(displayArea, layout, inOutBounds); if (DEBUG) appendLog("freeform-size-mismatch=" + inOutBounds); } @@ -821,8 +822,7 @@ class TaskLaunchParamsModifier implements LaunchParamsModifier { @NonNull Rect inOutBounds) { final int layoutDirection = mSupervisor.mRootWindowContainer.getConfiguration() .getLayoutDirection(); - displayArea.getStableRect(mTmpStableBounds); - LaunchParamsUtil.adjustBoundsToFitInDisplayArea(mTmpStableBounds, layoutDirection, layout, + LaunchParamsUtil.adjustBoundsToFitInDisplayArea(displayArea, layoutDirection, layout, inOutBounds); } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java index dce9f66356535..1188f49ae60e9 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskLaunchParamsModifierTests.java @@ -85,6 +85,11 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { private static final Rect DISPLAY_STABLE_BOUNDS = new Rect(/* left */ 100, /* top */ 200, /* right */ 1620, /* bottom */ 680); + private static final Rect SMALL_DISPLAY_BOUNDS = new Rect(/* left */ 0, /* top */ 0, + /* right */ 1000, /* bottom */ 500); + private static final Rect SMALL_DISPLAY_STABLE_BOUNDS = new Rect(/* left */ 100, + /* top */ 50, /* right */ 900, /* bottom */ 450); + private ActivityRecord mActivity; private TaskLaunchParamsModifier mTarget; @@ -1345,6 +1350,20 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { DISPLAY_STABLE_BOUNDS.bottom - mResult.mBounds.bottom, /* delta */ 1); } + @Test + public void testDefaultFreeformSizeShrinksOnSmallDisplay() { + final TestDisplayContent freeformDisplay = createNewDisplayContent( + WINDOWING_MODE_FREEFORM, SMALL_DISPLAY_BOUNDS, SMALL_DISPLAY_STABLE_BOUNDS); + + final ActivityOptions options = ActivityOptions.makeBasic(); + options.setLaunchDisplayId(freeformDisplay.mDisplayId); + + assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setOptions(options) + .calculate()); + + assertEquals(new Rect(414, 77, 587, 423), mResult.mBounds); + } + @Test public void testDefaultFreeformSizeRespectsMinAspectRatio() { final TestDisplayContent freeformDisplay = createNewDisplayContent( @@ -1535,16 +1554,15 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { options.setLaunchDisplayId(freeformDisplay.mDisplayId); mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM; - mCurrent.mBounds.set(100, 300, 1820, 1380); + mCurrent.mBounds.set(0, 0, 3000, 2000); mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP; assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setOptions(options).calculate()); - assertTrue("Result bounds should start from app bounds's origin, but it's " - + mResult.mBounds, - mResult.mBounds.left == 100 && mResult.mBounds.top == 200); + // Must shrink to fit the display while reserving aspect ratio. + assertEquals(new Rect(127, 227, 766, 653), mResult.mBounds); } @Test @@ -1560,18 +1578,19 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { final ActivityOptions options = ActivityOptions.makeBasic(); options.setLaunchDisplayId(freeformDisplay.mDisplayId); + final ActivityInfo.WindowLayout layout = new WindowLayoutBuilder() + .setMinWidth(500).setMinHeight(500).build(); mCurrent.mWindowingMode = WINDOWING_MODE_FREEFORM; - mCurrent.mBounds.set(100, 300, 1820, 1380); + mCurrent.mBounds.set(0, 0, 2000, 3000); mActivity.info.applicationInfo.targetSdkVersion = Build.VERSION_CODES.LOLLIPOP; assertEquals(RESULT_CONTINUE, - new CalculateRequestBuilder().setOptions(options).calculate()); + new CalculateRequestBuilder().setOptions(options).setLayout(layout).calculate()); - assertTrue("Result bounds should start from top-right corner of app bounds, but " - + "it's " + mResult.mBounds, - mResult.mBounds.left == -100 && mResult.mBounds.top == 200); + // Must shrink to fit the display while reserving aspect ratio. + assertEquals(new Rect(1093, 227, 1593, 727), mResult.mBounds); } @Test @@ -1746,7 +1765,7 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { assertEquals(RESULT_CONTINUE, new CalculateRequestBuilder().setOptions(options).calculate()); - assertEquals(new Rect(100, 200, 400, 500), mResult.mBounds); + assertEquals(new Rect(127, 227, 427, 527), mResult.mBounds); } @Test @@ -1799,13 +1818,18 @@ public class TaskLaunchParamsModifierTests extends WindowTestsBase { } private TestDisplayContent createNewDisplayContent(int windowingMode) { + return createNewDisplayContent(windowingMode, DISPLAY_BOUNDS, DISPLAY_STABLE_BOUNDS); + } + + private TestDisplayContent createNewDisplayContent(int windowingMode, Rect displayBounds, + Rect displayStableBounds) { final TestDisplayContent display = addNewDisplayContentAt(DisplayContent.POSITION_TOP); display.getDefaultTaskDisplayArea().setWindowingMode(windowingMode); - display.setBounds(DISPLAY_BOUNDS); + display.setBounds(displayBounds); display.getConfiguration().densityDpi = DENSITY_DEFAULT; display.getConfiguration().orientation = ORIENTATION_LANDSCAPE; configInsetsState(display.getInsetsStateController().getRawInsetsState(), display, - DISPLAY_STABLE_BOUNDS); + displayStableBounds); return display; }