diff options
3 files changed, 108 insertions, 10 deletions
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java index c712167c4cd1..f671b1d1bddd 100644 --- a/services/core/java/com/android/server/wm/ActivityRecord.java +++ b/services/core/java/com/android/server/wm/ActivityRecord.java @@ -7934,6 +7934,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. @@ -8047,8 +8049,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 @@ -8436,7 +8454,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); } @@ -9107,6 +9125,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 @@ -9115,12 +9145,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; } diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index be541ae0ba20..6641a42c5644 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -2124,7 +2124,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 { @@ -2213,6 +2213,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 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 e9080ab78fbc..a8e91980014e 100644 --- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java @@ -1617,6 +1617,79 @@ public class SizeCompatTests extends WindowTestsBase { } @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. int screenWidth = 1600; |