Merge "Shrink default launch bounds on small display" into tm-qpr-dev
diff --git a/services/core/java/com/android/server/wm/LaunchParamsUtil.java b/services/core/java/com/android/server/wm/LaunchParamsUtil.java
index 91469a0..09a17e1 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 @@
 
     private static final int DISPLAY_EDGE_OFFSET_DP = 27;
 
+    private static final Rect TMP_STABLE_BOUNDS = new Rect();
+
     private LaunchParamsUtil() {}
 
     /**
@@ -130,18 +132,42 @@
         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 f51a173..14a2d03 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 @@
             // 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 @@
                                                 @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 dce9f66..1188f49 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 @@
     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;
@@ -1346,6 +1351,20 @@
     }
 
     @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(
                 WINDOWING_MODE_FREEFORM);
@@ -1535,16 +1554,15 @@
         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 @@
 
         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 @@
         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 @@
     }
 
     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;
     }