Loading services/core/java/com/android/server/wm/ActivityRecord.java +6 −8 Original line number Diff line number Diff line Loading @@ -7733,9 +7733,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. Loading Loading @@ -7832,7 +7829,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. Loading Loading @@ -8003,7 +8000,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() { Loading Loading @@ -8219,7 +8217,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); } Loading Loading @@ -8247,7 +8245,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()); } } Loading Loading @@ -8311,7 +8309,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, Loading services/core/java/com/android/server/wm/TaskFragment.java +20 −9 Original line number Diff line number Diff line Loading @@ -1957,29 +1957,37 @@ class TaskFragment extends WindowContainer<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); } /** Loading @@ -2006,7 +2014,8 @@ class TaskFragment extends WindowContainer<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(); Loading Loading @@ -2113,6 +2122,7 @@ class TaskFragment extends WindowContainer<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 Loading @@ -2128,9 +2138,10 @@ class TaskFragment extends WindowContainer<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); } Loading services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +73 −0 Original line number Diff line number Diff line Loading @@ -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. Loading services/tests/wmtests/src/com/android/server/wm/TaskTests.java +2 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading
services/core/java/com/android/server/wm/ActivityRecord.java +6 −8 Original line number Diff line number Diff line Loading @@ -7733,9 +7733,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. Loading Loading @@ -7832,7 +7829,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. Loading Loading @@ -8003,7 +8000,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() { Loading Loading @@ -8219,7 +8217,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); } Loading Loading @@ -8247,7 +8245,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()); } } Loading Loading @@ -8311,7 +8309,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, Loading
services/core/java/com/android/server/wm/TaskFragment.java +20 −9 Original line number Diff line number Diff line Loading @@ -1957,29 +1957,37 @@ class TaskFragment extends WindowContainer<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); } /** Loading @@ -2006,7 +2014,8 @@ class TaskFragment extends WindowContainer<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(); Loading Loading @@ -2113,6 +2122,7 @@ class TaskFragment extends WindowContainer<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 Loading @@ -2128,9 +2138,10 @@ class TaskFragment extends WindowContainer<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); } Loading
services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +73 −0 Original line number Diff line number Diff line Loading @@ -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. Loading
services/tests/wmtests/src/com/android/server/wm/TaskTests.java +2 −1 Original line number Diff line number Diff line Loading @@ -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; Loading