Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ea12f9a7 authored by Mariia Sandrikova's avatar Mariia Sandrikova
Browse files

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
parent 91079f44
Loading
Loading
Loading
Loading
+6 −8
Original line number Diff line number Diff line
@@ -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,
+20 −9
Original line number Diff line number Diff line
@@ -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);
                }
+73 −0
Original line number Diff line number Diff line
@@ -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.
+2 −1
Original line number Diff line number Diff line
@@ -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;