Loading services/core/java/com/android/server/wm/ActivityRecord.java +33 −9 Original line number Diff line number Diff line Loading @@ -7938,6 +7938,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // 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; // TODO(b/264276741): Check whether the runtime orietnation request is fixed rather than // the manifest orientation which may be obsolete. if (info.isFixedOrientation()) { // lock rotation too. When in size-compat, onConfigurationChanged will watch for and // apply runtime rotation changes. Loading Loading @@ -8051,8 +8053,24 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A updateResolvedBoundsPosition(newParentConfiguration); } if (mVisibleRequested) { updateCompatDisplayInsets(); boolean isIgnoreOrientationRequest = mDisplayContent != null && mDisplayContent.getIgnoreOrientationRequest(); if (mCompatDisplayInsets == null // for size compat mode set in updateCompatDisplayInsets // Fixed orientation letterboxing is possible on both large screen devices // with ignoreOrientationRequest enabled and on phones in split screen even with // ignoreOrientationRequest disabled. && (mLetterboxBoundsForFixedOrientationAndAspectRatio != null // Limiting check for aspect ratio letterboxing to devices with enabled // ignoreOrientationRequest. This avoids affecting phones where apps may // not expect the change of smallestScreenWidthDp after rotation which is // possible with this logic. Not having smallestScreenWidthDp completely // accurate on phones shouldn't make the big difference and is expected // to be already well-tested by apps. || (isIgnoreOrientationRequest && mIsAspectRatioApplied))) { // TODO(b/264034555): Use mDisplayContent to calculate smallestScreenWidthDp from all // rotations and only re-calculate if parent bounds have non-orientation size change. resolvedConfig.smallestScreenWidthDp = Math.min(resolvedConfig.screenWidthDp, resolvedConfig.screenHeightDp); } // Assign configuration sequence number into hierarchy because there is a different way than Loading Loading @@ -8440,7 +8458,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); mLetterboxBoundsForFixedOrientationAndAspectRatio = new Rect(resolvedBounds); } Loading Loading @@ -9119,6 +9137,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mLastReportedDisplayId = newDisplayId; } // Calling from here rather than from onConfigurationChanged because it's possible that // onConfigurationChanged was called before mVisibleRequested became true and // mCompatDisplayInsets may not be called again when mVisibleRequested changes. And we // don't want to save mCompatDisplayInsets in onConfigurationChanged without visibility // check to avoid remembering obsolete configuration which can lead to unnecessary // size-compat mode. if (mVisibleRequested) { // Calling from here rather than resolveOverrideConfiguration to ensure that this is // called after full config is updated in ConfigurationContainer#onConfigurationChanged. updateCompatDisplayInsets(); } // Short circuit: if the two full configurations are equal (the common case), then there is // nothing to do. We test the full configuration instead of the global and merged override // configurations because there are cases (like moving a task to the root pinned task) where Loading @@ -9127,12 +9157,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (getConfiguration().equals(mTmpConfig) && !forceNewConfig && !displayChanged) { ProtoLog.v(WM_DEBUG_CONFIGURATION, "Configuration & display " + "unchanged in %s", this); // It's possible that resolveOverrideConfiguration was called before mVisibleRequested // became true and mCompatDisplayInsets may not have been created so ensure // that mCompatDisplayInsets is created here. if (mVisibleRequested) { updateCompatDisplayInsets(); } return true; } Loading services/core/java/com/android/server/wm/TaskFragment.java +2 −1 Original line number Diff line number Diff line Loading @@ -2138,7 +2138,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { final Rect parentBounds = parentConfig.windowConfiguration.getBounds(); final Rect resolvedBounds = inOutConfig.windowConfiguration.getBounds(); if (resolvedBounds == null || resolvedBounds.isEmpty()) { if (resolvedBounds.isEmpty()) { mTmpFullBounds.set(parentBounds); insideParentBounds = true; } else { Loading Loading @@ -2227,6 +2227,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 services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +73 −0 Original line number Diff line number Diff line Loading @@ -1616,6 +1616,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 Loading
services/core/java/com/android/server/wm/ActivityRecord.java +33 −9 Original line number Diff line number Diff line Loading @@ -7938,6 +7938,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A // 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; // TODO(b/264276741): Check whether the runtime orietnation request is fixed rather than // the manifest orientation which may be obsolete. if (info.isFixedOrientation()) { // lock rotation too. When in size-compat, onConfigurationChanged will watch for and // apply runtime rotation changes. Loading Loading @@ -8051,8 +8053,24 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A updateResolvedBoundsPosition(newParentConfiguration); } if (mVisibleRequested) { updateCompatDisplayInsets(); boolean isIgnoreOrientationRequest = mDisplayContent != null && mDisplayContent.getIgnoreOrientationRequest(); if (mCompatDisplayInsets == null // for size compat mode set in updateCompatDisplayInsets // Fixed orientation letterboxing is possible on both large screen devices // with ignoreOrientationRequest enabled and on phones in split screen even with // ignoreOrientationRequest disabled. && (mLetterboxBoundsForFixedOrientationAndAspectRatio != null // Limiting check for aspect ratio letterboxing to devices with enabled // ignoreOrientationRequest. This avoids affecting phones where apps may // not expect the change of smallestScreenWidthDp after rotation which is // possible with this logic. Not having smallestScreenWidthDp completely // accurate on phones shouldn't make the big difference and is expected // to be already well-tested by apps. || (isIgnoreOrientationRequest && mIsAspectRatioApplied))) { // TODO(b/264034555): Use mDisplayContent to calculate smallestScreenWidthDp from all // rotations and only re-calculate if parent bounds have non-orientation size change. resolvedConfig.smallestScreenWidthDp = Math.min(resolvedConfig.screenWidthDp, resolvedConfig.screenHeightDp); } // Assign configuration sequence number into hierarchy because there is a different way than Loading Loading @@ -8440,7 +8458,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); mLetterboxBoundsForFixedOrientationAndAspectRatio = new Rect(resolvedBounds); } Loading Loading @@ -9119,6 +9137,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A mLastReportedDisplayId = newDisplayId; } // Calling from here rather than from onConfigurationChanged because it's possible that // onConfigurationChanged was called before mVisibleRequested became true and // mCompatDisplayInsets may not be called again when mVisibleRequested changes. And we // don't want to save mCompatDisplayInsets in onConfigurationChanged without visibility // check to avoid remembering obsolete configuration which can lead to unnecessary // size-compat mode. if (mVisibleRequested) { // Calling from here rather than resolveOverrideConfiguration to ensure that this is // called after full config is updated in ConfigurationContainer#onConfigurationChanged. updateCompatDisplayInsets(); } // Short circuit: if the two full configurations are equal (the common case), then there is // nothing to do. We test the full configuration instead of the global and merged override // configurations because there are cases (like moving a task to the root pinned task) where Loading @@ -9127,12 +9157,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A if (getConfiguration().equals(mTmpConfig) && !forceNewConfig && !displayChanged) { ProtoLog.v(WM_DEBUG_CONFIGURATION, "Configuration & display " + "unchanged in %s", this); // It's possible that resolveOverrideConfiguration was called before mVisibleRequested // became true and mCompatDisplayInsets may not have been created so ensure // that mCompatDisplayInsets is created here. if (mVisibleRequested) { updateCompatDisplayInsets(); } return true; } Loading
services/core/java/com/android/server/wm/TaskFragment.java +2 −1 Original line number Diff line number Diff line Loading @@ -2138,7 +2138,7 @@ class TaskFragment extends WindowContainer<WindowContainer> { final Rect parentBounds = parentConfig.windowConfiguration.getBounds(); final Rect resolvedBounds = inOutConfig.windowConfiguration.getBounds(); if (resolvedBounds == null || resolvedBounds.isEmpty()) { if (resolvedBounds.isEmpty()) { mTmpFullBounds.set(parentBounds); insideParentBounds = true; } else { Loading Loading @@ -2227,6 +2227,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
services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +73 −0 Original line number Diff line number Diff line Loading @@ -1616,6 +1616,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