From 1f931a590ba8a22fc8adc7de4c21d55bfca9aacc Mon Sep 17 00:00:00 2001 From: Riddle Hsu Date: Wed, 22 Apr 2020 21:15:38 +0800 Subject: [PATCH] Respect parent bounds if it can contain the override bounds The parent configuration may have been transformed (fixed rotation), in that case the override bounds should be able to fit in the given parent bounds. Besides, the rotation of task display area is different than the override bounds. So parent app bounds should be still chosen as the container area. Fixes: 154699350 Test: atest AspectRatioTests#testMinAspectLandscapeActivity TaskRecordTests#testComputeConfigResourceOverrides Change-Id: Iaf5c1f838d2c51c6c0175b5e6e947e6690ed9cf3 --- .../core/java/com/android/server/wm/Task.java | 48 ++++++++++--------- .../android/server/wm/TaskRecordTests.java | 15 ++++-- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java index 5bf49a6aa0927..93c6b6e7b83c4 100644 --- a/services/core/java/com/android/server/wm/Task.java +++ b/services/core/java/com/android/server/wm/Task.java @@ -2285,16 +2285,18 @@ class Task extends WindowContainer { } density *= DisplayMetrics.DENSITY_DEFAULT_SCALE; - // If bounds have been overridden at this level, restrict config resources to these bounds - // rather than the parent because the overridden bounds can be larger than the parent. - boolean hasOverrideBounds = false; + // The bounds may have been overridden at this level. If the parent cannot cover these + // bounds, the configuration is still computed according to the override bounds. + final boolean insideParentBounds; + final Rect parentBounds = parentConfig.windowConfiguration.getBounds(); final Rect resolvedBounds = inOutConfig.windowConfiguration.getBounds(); if (resolvedBounds == null || resolvedBounds.isEmpty()) { - mTmpFullBounds.set(parentConfig.windowConfiguration.getBounds()); + mTmpFullBounds.set(parentBounds); + insideParentBounds = true; } else { mTmpFullBounds.set(resolvedBounds); - hasOverrideBounds = true; + insideParentBounds = parentBounds.contains(resolvedBounds); } Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds(); @@ -2303,30 +2305,30 @@ class Task extends WindowContainer { outAppBounds = inOutConfig.windowConfiguration.getAppBounds(); } // Non-null compatibility insets means the activity prefers to keep its original size, so - // the out bounds doesn't need to be restricted by the parent. - final boolean insideParentBounds = compatInsets == null; - if (insideParentBounds && windowingMode != WINDOWING_MODE_FREEFORM) { - Rect parentAppBounds; - if (hasOverrideBounds) { - // Since we overrode the bounds, restrict appBounds to display non-decor rather - // than parent. Otherwise, it won't match the overridden bounds. - final TaskDisplayArea displayArea = getDisplayArea(); - parentAppBounds = displayArea != null - ? displayArea.getConfiguration().windowConfiguration.getAppBounds() : null; + // the out bounds doesn't need to be restricted by the parent or current display. + final boolean customContainerPolicy = compatInsets != null; + if (!customContainerPolicy && windowingMode != WINDOWING_MODE_FREEFORM) { + final Rect containingAppBounds; + if (insideParentBounds) { + containingAppBounds = parentConfig.windowConfiguration.getAppBounds(); } else { - parentAppBounds = parentConfig.windowConfiguration.getAppBounds(); + // Restrict appBounds to display non-decor rather than parent because the override + // bounds are beyond the parent. Otherwise, it won't match the overridden bounds. + final TaskDisplayArea displayArea = getDisplayArea(); + containingAppBounds = displayArea != null + ? displayArea.getWindowConfiguration().getAppBounds() : null; } - if (parentAppBounds != null && !parentAppBounds.isEmpty()) { - outAppBounds.intersect(parentAppBounds); + if (containingAppBounds != null && !containingAppBounds.isEmpty()) { + outAppBounds.intersect(containingAppBounds); } } if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED || inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) { - if (insideParentBounds && WindowConfiguration.isFloating(windowingMode)) { + if (!customContainerPolicy && WindowConfiguration.isFloating(windowingMode)) { mTmpNonDecorBounds.set(mTmpFullBounds); mTmpStableBounds.set(mTmpFullBounds); - } else if (insideParentBounds + } else if (!customContainerPolicy && (overrideDisplayInfo != null || getDisplayContent() != null)) { final DisplayInfo di = overrideDisplayInfo != null ? overrideDisplayInfo @@ -2344,7 +2346,7 @@ class Task extends WindowContainer { if (rotation == ROTATION_UNDEFINED) { rotation = parentConfig.windowConfiguration.getRotation(); } - if (rotation != ROTATION_UNDEFINED && compatInsets != null) { + if (rotation != ROTATION_UNDEFINED && customContainerPolicy) { mTmpNonDecorBounds.set(mTmpFullBounds); mTmpStableBounds.set(mTmpFullBounds); compatInsets.getBoundsByRotation(mTmpBounds, rotation); @@ -2362,13 +2364,13 @@ class Task extends WindowContainer { if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) { final int overrideScreenWidthDp = (int) (mTmpStableBounds.width() / density); - inOutConfig.screenWidthDp = (insideParentBounds && !hasOverrideBounds) + inOutConfig.screenWidthDp = (insideParentBounds && !customContainerPolicy) ? Math.min(overrideScreenWidthDp, parentConfig.screenWidthDp) : overrideScreenWidthDp; } if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) { final int overrideScreenHeightDp = (int) (mTmpStableBounds.height() / density); - inOutConfig.screenHeightDp = (insideParentBounds && !hasOverrideBounds) + inOutConfig.screenHeightDp = (insideParentBounds && !customContainerPolicy) ? Math.min(overrideScreenHeightDp, parentConfig.screenHeightDp) : overrideScreenHeightDp; } diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java index dcc2ff1311a5d..60875de5a68be 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskRecordTests.java @@ -372,7 +372,9 @@ public class TaskRecordTests extends ActivityTestsBase { final int longSide = 1200; final int shortSide = 600; final Rect parentBounds = new Rect(0, 0, 250, 500); + final Rect parentAppBounds = new Rect(0, 0, 250, 480); parentConfig.windowConfiguration.setBounds(parentBounds); + parentConfig.windowConfiguration.setAppBounds(parentAppBounds); parentConfig.densityDpi = 400; parentConfig.screenHeightDp = (parentBounds.bottom * 160) / parentConfig.densityDpi; // 200 parentConfig.screenWidthDp = (parentBounds.right * 160) / parentConfig.densityDpi; // 100 @@ -383,21 +385,25 @@ public class TaskRecordTests extends ActivityTestsBase { assertEquals(parentConfig.screenHeightDp, inOutConfig.screenHeightDp); assertEquals(parentConfig.screenWidthDp, inOutConfig.screenWidthDp); + assertEquals(parentAppBounds, inOutConfig.windowConfiguration.getAppBounds()); assertEquals(Configuration.ORIENTATION_PORTRAIT, inOutConfig.orientation); // If bounds are overridden, config properties should be made to match. Surface hierarchy // will crop for policy. inOutConfig.setToDefaults(); - inOutConfig.windowConfiguration.getBounds().set(0, 0, shortSide, longSide); - // By default, the parent bounds should limit the existing input bounds. + final Rect largerPortraitBounds = new Rect(0, 0, shortSide, longSide); + inOutConfig.windowConfiguration.setBounds(largerPortraitBounds); task.computeConfigResourceOverrides(inOutConfig, parentConfig); - + // The override bounds are beyond the parent, the out appBounds should not be intersected + // by parent appBounds. + assertEquals(largerPortraitBounds, inOutConfig.windowConfiguration.getAppBounds()); assertEquals(longSide, inOutConfig.screenHeightDp * parentConfig.densityDpi / 160); assertEquals(shortSide, inOutConfig.screenWidthDp * parentConfig.densityDpi / 160); inOutConfig.setToDefaults(); // Landscape bounds. - inOutConfig.windowConfiguration.getBounds().set(0, 0, longSide, shortSide); + final Rect largerLandscapeBounds = new Rect(0, 0, longSide, shortSide); + inOutConfig.windowConfiguration.setBounds(largerLandscapeBounds); // Setup the display with a top stable inset. The later assertion will ensure the inset is // excluded from screenHeightDp. @@ -415,6 +421,7 @@ public class TaskRecordTests extends ActivityTestsBase { new ActivityRecord.CompatDisplayInsets(display, task); task.computeConfigResourceOverrides(inOutConfig, parentConfig, compatIntsets); + assertEquals(largerLandscapeBounds, inOutConfig.windowConfiguration.getAppBounds()); assertEquals((shortSide - statusBarHeight) * DENSITY_DEFAULT / parentConfig.densityDpi, inOutConfig.screenHeightDp); assertEquals(longSide * DENSITY_DEFAULT / parentConfig.densityDpi,