Adjust smallestScreenWidthDp for letterbox
By definition, smallestScreenWidthDp is the smallest value of both screenWidthDp and screenHeightDp. When a different value is reported in smallestScreenWidthDp, the app can load incorrect layout. Test: atest WmTests:SizeCompatTests Fix: 232406936 Change-Id: Ie0d7767fba03cc07e21e3624d9d8c5b0ea13dff1
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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();
|
||||
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user