diff options
| author | 2025-02-09 22:38:36 -0800 | |
|---|---|---|
| committer | 2025-02-13 15:01:46 +0900 | |
| commit | bf8b16bc6cf96fe58049a3b525c773d97d9b7ace (patch) | |
| tree | 5c2793d93357d12fa19824c1ad68f9c43e075a6e | |
| parent | 7d2ddd33d9715f791ec4fa930a2c2aa3a46120bf (diff) | |
Fix wrong compat override screen sizes
Override is applied when the insets decouple is enabled and the app is a
legacy app. When calculating the screenWidthDp and screenHeightDp, the
display size excluding status bars, navigation bars, and display cutouts
should be used.
The current implementation is calculating the screenWidthDp and
screenHeightDp by excluding the navigation bars and display cutouts from
the display size. This is not consistent with the legacy behavior of the
system.
When the device has a status bar larger than a display cutout, or the
device doesn't have a display cutout, some app may experience layout
issue because of the inconsistency.
Bug: 391063639
Test: WindowProcessControllerTests
Flag: EXEMPT bugfix
Change-Id: I2e3ac42ac341e8eff7a01dd4985451b7e37a4842
| -rw-r--r-- | services/core/java/com/android/server/wm/ConfigurationContainer.java | 12 | ||||
| -rw-r--r-- | services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java | 54 |
2 files changed, 64 insertions, 2 deletions
diff --git a/services/core/java/com/android/server/wm/ConfigurationContainer.java b/services/core/java/com/android/server/wm/ConfigurationContainer.java index 05dcbb7f9af4..aaa18ad6acc9 100644 --- a/services/core/java/com/android/server/wm/ConfigurationContainer.java +++ b/services/core/java/com/android/server/wm/ConfigurationContainer.java @@ -257,10 +257,12 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { // This should be the only place override the configuration for ActivityRecord. Override // the value if not calculated yet. Rect outAppBounds = inOutConfig.windowConfiguration.getAppBounds(); + Rect outConfigBounds = new Rect(outAppBounds); if (outAppBounds == null || outAppBounds.isEmpty()) { inOutConfig.windowConfiguration.setAppBounds( newParentConfiguration.windowConfiguration.getBounds()); outAppBounds = inOutConfig.windowConfiguration.getAppBounds(); + outConfigBounds.set(outAppBounds); if (task != null) { task = task.getCreatedByOrganizerTask(); if (task != null && (task.mOffsetYForInsets != 0 || task.mOffsetXForInsets != 0)) { @@ -279,6 +281,12 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { outAppBounds.inset(decor.mOverrideNonDecorInsets); } } + if (!outConfigBounds.intersect(decor.mOverrideConfigFrame)) { + if (inOutConfig.windowConfiguration.getWindowingMode() + == WINDOWING_MODE_MULTI_WINDOW) { + outAppBounds.inset(decor.mOverrideConfigInsets); + } + } if (task != null && (task.mOffsetYForInsets != 0 || task.mOffsetXForInsets != 0)) { outAppBounds.offset(-task.mOffsetXForInsets, -task.mOffsetYForInsets); } @@ -289,10 +297,10 @@ public abstract class ConfigurationContainer<E extends ConfigurationContainer> { } density *= DisplayMetrics.DENSITY_DEFAULT_SCALE; if (inOutConfig.screenWidthDp == Configuration.SCREEN_WIDTH_DP_UNDEFINED) { - inOutConfig.screenWidthDp = (int) (outAppBounds.width() / density + 0.5f); + inOutConfig.screenWidthDp = (int) (outConfigBounds.width() / density + 0.5f); } if (inOutConfig.screenHeightDp == Configuration.SCREEN_HEIGHT_DP_UNDEFINED) { - inOutConfig.screenHeightDp = (int) (outAppBounds.height() / density + 0.5f); + inOutConfig.screenHeightDp = (int) (outConfigBounds.height() / density + 0.5f); } if (inOutConfig.smallestScreenWidthDp == Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFINED && parentWindowingMode == WINDOWING_MODE_FULLSCREEN) { diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java index 1dfb20a41816..d228970e0371 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java @@ -19,6 +19,7 @@ package com.android.server.wm; import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; import static android.content.pm.ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED; +import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION; import static android.content.res.Configuration.GRAMMATICAL_GENDER_NOT_SPECIFIED; import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; import static android.content.res.Configuration.ORIENTATION_PORTRAIT; @@ -33,9 +34,11 @@ import static com.android.server.wm.ActivityRecord.State.RESUMED; import static com.android.server.wm.ActivityRecord.State.STARTED; import static com.android.server.wm.ActivityRecord.State.STOPPED; import static com.android.server.wm.ActivityRecord.State.STOPPING; +import static com.android.server.wm.ConfigurationContainer.applySizeOverrideIfNeeded; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; @@ -58,6 +61,7 @@ import android.content.res.Configuration; import android.graphics.Rect; import android.os.LocaleList; import android.os.RemoteException; +import android.platform.test.annotations.EnableFlags; import android.platform.test.annotations.Presubmit; import org.junit.Before; @@ -453,6 +457,56 @@ public class WindowProcessControllerTests extends WindowTestsBase { assertEquals(topDisplayArea, mWpc.getTopActivityDisplayArea()); } + @Test + @EnableFlags(com.android.window.flags.Flags.FLAG_INSETS_DECOUPLED_CONFIGURATION) + public void testOverrideConfigurationApplied() { + final DisplayContent displayContent = new TestDisplayContent.Builder(mAtm, 1000, 1500) + .setSystemDecorations(true).setDensityDpi(160).build(); + final DisplayPolicy displayPolicy = displayContent.getDisplayPolicy(); + // Setup the decor insets info. + final DisplayPolicy.DecorInsets.Info decorInsetsInfo = new DisplayPolicy.DecorInsets.Info(); + final Rect emptyRect = new Rect(); + decorInsetsInfo.mNonDecorInsets.set(emptyRect); + decorInsetsInfo.mConfigInsets.set(emptyRect); + decorInsetsInfo.mOverrideConfigInsets.set(new Rect(0, 100, 0, 200)); + decorInsetsInfo.mOverrideNonDecorInsets.set(new Rect(0, 0, 0, 200)); + decorInsetsInfo.mNonDecorFrame.set(new Rect(0, 0, 1000, 1500)); + decorInsetsInfo.mConfigFrame.set(new Rect(0, 0, 1000, 1500)); + decorInsetsInfo.mOverrideConfigFrame.set(new Rect(0, 100, 1000, 1300)); + decorInsetsInfo.mOverrideNonDecorFrame.set(new Rect(0, 0, 1000, 1300)); + doReturn(decorInsetsInfo).when(displayPolicy) + .getDecorInsetsInfo(anyInt(), anyInt(), anyInt()); + + final Configuration newParentConfig = displayContent.getConfiguration(); + final Configuration resolvedConfig = new Configuration(); + + // Mock the app info to not enforce the decoupled configuration to apply the override. + final ApplicationInfo appInfo = mock(ApplicationInfo.class); + doReturn(false).when(appInfo) + .isChangeEnabled(INSETS_DECOUPLED_CONFIGURATION_ENFORCED); + doReturn(false).when(appInfo) + .isChangeEnabled(OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION); + + // No value should be set before override. + assertNull(resolvedConfig.windowConfiguration.getAppBounds()); + applySizeOverrideIfNeeded( + displayContent, + appInfo, + newParentConfig, + resolvedConfig, + false /* optsOutEdgeToEdge */, + false /* hasFixedRotationTransform */, + false /* hasCompatDisplayInsets */, + null /* task */); + + // Assert the override config insets are applied. + // Status bars, and all non-decor insets should be deducted for the config screen size. + assertEquals(1200, resolvedConfig.screenHeightDp); + // Only the non-decor insets should be deducted for the app bounds. + assertNotNull(resolvedConfig.windowConfiguration.getAppBounds()); + assertEquals(1300, resolvedConfig.windowConfiguration.getAppBounds().height()); + } + private TestDisplayContent createTestDisplayContentInContainer() { return new TestDisplayContent.Builder(mAtm, 1000, 1500).build(); } |