diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index a9b154c869e83..d6076f7012437 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -7737,9 +7737,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // relatively fixed. overrideConfig.colorMode = fullConfig.colorMode; overrideConfig.densityDpi = fullConfig.densityDpi; - // The smallest screen width is the short side of screen bounds. Because the bounds - // and density won't be changed, smallestScreenWidthDp is also fixed. - overrideConfig.smallestScreenWidthDp = fullConfig.smallestScreenWidthDp; if (info.isFixedOrientation()) { // lock rotation too. When in size-compat, onConfigurationChanged will watch for and // apply runtime rotation changes. @@ -7836,7 +7833,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // computed accordingly. if (!matchParentBounds()) { getTaskFragment().computeConfigResourceOverrides(resolvedConfig, - newParentConfiguration); + newParentConfiguration, areBoundsLetterboxed()); } // If activity in fullscreen mode is letterboxed because of fixed orientation then bounds // are already calculated in resolveFixedOrientationConfiguration. @@ -8007,7 +8004,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A } // Since bounds has changed, the configuration needs to be computed accordingly. - getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration); + getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration, + areBoundsLetterboxed()); } void recomputeConfiguration() { @@ -8223,7 +8221,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Calculate app bounds using fixed orientation bounds because they will be needed later // for comparison with size compat app bounds in {@link resolveSizeCompatModeConfiguration}. getTaskFragment().computeConfigResourceOverrides(getResolvedOverrideConfiguration(), - newParentConfig); + newParentConfig, mCompatDisplayInsets, areBoundsLetterboxed()); mLetterboxBoundsForFixedOrientationAndAspectRatio = new Rect(resolvedBounds); } @@ -8251,7 +8249,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // Compute the configuration based on the resolved bounds. If aspect ratio doesn't // restrict, the bounds should be the requested override bounds. getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration, - getFixedRotationTransformDisplayInfo()); + getFixedRotationTransformDisplayInfo(), areBoundsLetterboxed()); } } @@ -8315,7 +8313,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // are calculated in compat container space. The actual position on screen will be applied // later, so the calculation is simpler that doesn't need to involve offset from parent. getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration, - mCompatDisplayInsets); + mCompatDisplayInsets, areBoundsLetterboxed()); // Use current screen layout as source because the size of app is independent to parent. resolvedConfig.screenLayout = TaskFragment.computeScreenLayoutOverride( getConfiguration().screenLayout, resolvedConfig.screenWidthDp, diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index f8a9d4665acca..21c5886f085ba 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -1957,29 +1957,37 @@ class TaskFragment extends WindowContainer { void computeConfigResourceOverrides(@NonNull Configuration inOutConfig, @NonNull Configuration parentConfig) { computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */, - null /* compatInsets */); + null /* compatInsets */, false /* areBoundsLetterboxed */); } void computeConfigResourceOverrides(@NonNull Configuration inOutConfig, - @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo) { + @NonNull Configuration parentConfig, boolean areBoundsLetterboxed) { + computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */, + null /* compatInsets */, areBoundsLetterboxed); + } + + void computeConfigResourceOverrides(@NonNull Configuration inOutConfig, + @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo, + boolean areBoundsLetterboxed) { if (overrideDisplayInfo != null) { // Make sure the screen related configs can be computed by the provided display info. inOutConfig.screenLayout = Configuration.SCREENLAYOUT_UNDEFINED; invalidateAppBoundsConfig(inOutConfig); } computeConfigResourceOverrides(inOutConfig, parentConfig, overrideDisplayInfo, - null /* compatInsets */); + null /* compatInsets */, areBoundsLetterboxed); } void computeConfigResourceOverrides(@NonNull Configuration inOutConfig, @NonNull Configuration parentConfig, - @Nullable ActivityRecord.CompatDisplayInsets compatInsets) { + @Nullable ActivityRecord.CompatDisplayInsets compatInsets, + boolean areBoundsLetterboxed) { if (compatInsets != null) { // Make sure the app bounds can be computed by the compat insets. invalidateAppBoundsConfig(inOutConfig); } computeConfigResourceOverrides(inOutConfig, parentConfig, null /* overrideDisplayInfo */, - compatInsets); + compatInsets, areBoundsLetterboxed); } /** @@ -2006,7 +2014,8 @@ class TaskFragment extends WindowContainer { **/ void computeConfigResourceOverrides(@NonNull Configuration inOutConfig, @NonNull Configuration parentConfig, @Nullable DisplayInfo overrideDisplayInfo, - @Nullable ActivityRecord.CompatDisplayInsets compatInsets) { + @Nullable ActivityRecord.CompatDisplayInsets compatInsets, + boolean areBoundsLetterboxed) { int windowingMode = inOutConfig.windowConfiguration.getWindowingMode(); if (windowingMode == WINDOWING_MODE_UNDEFINED) { windowingMode = parentConfig.windowConfiguration.getWindowingMode(); @@ -2113,6 +2122,7 @@ class TaskFragment extends WindowContainer { : overrideScreenHeightDp; } + // TODO(b/238331848): Consider simplifying logic that computes smallestScreenWidthDp. if (inOutConfig.smallestScreenWidthDp == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED) { // When entering to or exiting from Pip, the PipTaskOrganizer will set the @@ -2128,9 +2138,10 @@ class TaskFragment extends WindowContainer { // task, because they should not be affected by insets. inOutConfig.smallestScreenWidthDp = (int) (0.5f + Math.min(mTmpFullBounds.width(), mTmpFullBounds.height()) / density); - } else if (isEmbedded()) { - // For embedded TFs, the smallest width should be updated. Otherwise, inherit - // from the parent task would result in applications loaded wrong resource. + } else if (isEmbedded() || areBoundsLetterboxed || customContainerPolicy) { + // For embedded TFs and activities that are letteboxed or eligible for size + // compat mode, the smallest width should be updated. Otherwise, inherit from + // the parent task would result in applications loaded wrong resource. inOutConfig.smallestScreenWidthDp = Math.min(inOutConfig.screenWidthDp, inOutConfig.screenHeightDp); } 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 324e244c46f50..f2640d2dc4049 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -1495,6 +1495,79 @@ public class SizeCompatTests extends WindowTestsBase { assertEquals(displayBounds.height() / defaultAspectRatio, activityBounds.width(), 0.5); } + @Test + public void testComputeConfigResourceOverrides_unresizableApp() { + // Set up a display in landscape and ignoring orientation request. + setUpDisplaySizeWithApp(2800, 1400); + mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); + + prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT); + + final Rect activityBounds = new Rect(mActivity.getBounds()); + + int originalScreenWidthDp = mActivity.getConfiguration().screenWidthDp; + int originalScreenHeighthDp = mActivity.getConfiguration().screenHeightDp; + + // App should launch in fixed orientation letterbox. + // Activity bounds should be 700x1400 with the ratio as the display. + assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio()); + assertFitted(); + assertEquals(originalScreenWidthDp, mActivity.getConfiguration().smallestScreenWidthDp); + assertTrue(originalScreenWidthDp < originalScreenHeighthDp); + + // Rotate display to portrait. + rotateDisplay(mActivity.mDisplayContent, ROTATION_90); + + // After we rotate, the activity should go in the size-compat mode and report the same + // configuration values. + assertScaled(); + assertEquals(originalScreenWidthDp, mActivity.getConfiguration().smallestScreenWidthDp); + assertEquals(originalScreenWidthDp, mActivity.getConfiguration().screenWidthDp); + assertEquals(originalScreenHeighthDp, mActivity.getConfiguration().screenHeightDp); + + // Restart activity + mActivity.restartProcessIfVisible(); + + // Now configuration should be updated + assertFitted(); + assertNotEquals(originalScreenWidthDp, mActivity.getConfiguration().screenWidthDp); + assertNotEquals(originalScreenHeighthDp, mActivity.getConfiguration().screenHeightDp); + assertEquals(mActivity.getConfiguration().screenWidthDp, + mActivity.getConfiguration().smallestScreenWidthDp); + } + + @Test + public void testComputeConfigResourceOverrides_resizableFixedOrientationActivity() { + // Set up a display in landscape and ignoring orientation request. + setUpDisplaySizeWithApp(2800, 1400); + mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */); + + // Portrait fixed app without max aspect. + prepareLimitedBounds(mActivity, SCREEN_ORIENTATION_PORTRAIT, false /* isUnresizable */); + + final Rect activityBounds = new Rect(mActivity.getBounds()); + + int originalScreenWidthDp = mActivity.getConfiguration().screenWidthDp; + int originalScreenHeighthDp = mActivity.getConfiguration().screenHeightDp; + + // App should launch in fixed orientation letterbox. + // Activity bounds should be 700x1400 with the ratio as the display. + assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio()); + assertFitted(); + assertEquals(originalScreenWidthDp, mActivity.getConfiguration().smallestScreenWidthDp); + assertTrue(originalScreenWidthDp < originalScreenHeighthDp); + + // Rotate display to portrait. + rotateDisplay(mActivity.mDisplayContent, ROTATION_90); + + // Now configuration should be updated + assertFitted(); + assertNotEquals(originalScreenWidthDp, mActivity.getConfiguration().screenWidthDp); + assertNotEquals(originalScreenHeighthDp, mActivity.getConfiguration().screenHeightDp); + assertEquals(mActivity.getConfiguration().screenWidthDp, + mActivity.getConfiguration().smallestScreenWidthDp); + } + @Test public void testSplitAspectRatioForUnresizablePortraitApps() { // Set up a display in landscape and ignoring orientation request. diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java index 46e21f1ffdbcb..e2fe1b175dc82 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java @@ -691,7 +691,8 @@ public class TaskTests extends WindowTestsBase { final ActivityRecord.CompatDisplayInsets compatInsets = new ActivityRecord.CompatDisplayInsets( display, activity, /* fixedOrientationBounds= */ null); - task.computeConfigResourceOverrides(inOutConfig, parentConfig, compatInsets); + task.computeConfigResourceOverrides( + inOutConfig, parentConfig, compatInsets, /* areBoundsLetterboxed */ true); assertEquals(largerLandscapeBounds, inOutConfig.windowConfiguration.getAppBounds()); final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;