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

Commit 56854d40 authored by Graciela Wissen Putri's avatar Graciela Wissen Putri
Browse files

Use resolved bounds in CompatDisplayInsets if letterboxed for aspect ratio

Activity can stay in size compat mode even when restarted if it is
letterboxed for aspect ratio but not letterboxed for fixed orientation.
This is because resolveAspectRatioRestriction is only called if
compatDisplayInsets is null since we assume aspect ratio is already
resolved in resolveFixedOrientationConfiguration if app is eligible for
size compat mode. With close to square displays, landscape app can have
orientation respected with insets (portrait display, landscape
orientation with 3BN mode enabled) but still letterboxed for aspect
ratio if user chooses aspect ratio or manufacturer overrides app's
aspect ratio.

CompatDisplayInsets should use resolved override bounds if activity is
letterboxed for fixed orientation or aspect ratio so size compat
calculations displays within these bounds and not task bounds.

Fix: 327210346
Test: atest SizeCompatTests
Change-Id: I47ca4412a89e0c672c0118658c33d29e15f30c95
parent 7548f9fa
Loading
Loading
Loading
Loading
+31 −17
Original line number Diff line number Diff line
@@ -813,6 +813,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    @Nullable
    private Rect mLetterboxBoundsForFixedOrientationAndAspectRatio;

    // Bounds populated in resolveAspectRatioRestriction when this activity is letterboxed for
    // aspect ratio. If not null, they are used as parent container in
    // resolveSizeCompatModeConfiguration and in a constructor of CompatDisplayInsets.
    @Nullable
    private Rect mLetterboxBoundsForAspectRatio;

    // Whether the activity is eligible to be letterboxed for fixed orientation with respect to its
    // requested orientation, even when it's letterbox for another reason (e.g., size compat mode)
    // and therefore #isLetterboxedForFixedOrientationAndAspectRatio returns false.
@@ -8402,10 +8408,14 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                    fullConfig.windowConfiguration.getRotation());
        }

        final Rect letterboxedContainerBounds =
                mLetterboxBoundsForFixedOrientationAndAspectRatio != null
                ? mLetterboxBoundsForFixedOrientationAndAspectRatio
                : mLetterboxBoundsForAspectRatio;

        // The role of CompatDisplayInsets is like the override bounds.
        mCompatDisplayInsets =
                new CompatDisplayInsets(
                        mDisplayContent, this, mLetterboxBoundsForFixedOrientationAndAspectRatio);
                new CompatDisplayInsets(mDisplayContent, this, letterboxedContainerBounds);
    }

    private void clearSizeCompatModeAttributes() {
@@ -8477,6 +8487,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        mIsAspectRatioApplied = false;
        mIsEligibleForFixedOrientationLetterbox = false;
        mLetterboxBoundsForFixedOrientationAndAspectRatio = null;
        mLetterboxBoundsForAspectRatio = null;

        // Can't use resolvedConfig.windowConfiguration.getWindowingMode() because it can be
        // different from windowing mode of the task (PiP) during transition from fullscreen to PiP
@@ -8511,9 +8522,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                getTaskFragment().computeConfigResourceOverrides(resolvedConfig,
                        newParentConfiguration);
            }
        }
        // If activity in fullscreen mode is letterboxed because of fixed orientation then bounds
        // are already calculated in resolveFixedOrientationConfiguration.
        } else if (!isLetterboxedForFixedOrientationAndAspectRatio()) {
        // are already calculated in resolveFixedOrientationConfiguration, or if in size compat
        // mode, it should already be calculated in resolveSizeCompatModeConfiguration
        if (!isLetterboxedForFixedOrientationAndAspectRatio() && !mInSizeCompatModeForBounds) {
            resolveAspectRatioRestriction(newParentConfiguration);
        }

@@ -8920,7 +8933,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
        final CompatDisplayInsets compatDisplayInsets = getCompatDisplayInsets();

        if (compatDisplayInsets != null && !compatDisplayInsets.mIsInFixedOrientationLetterbox) {
        if (compatDisplayInsets != null
                && !compatDisplayInsets.mIsInFixedOrientationOrAspectRatioLetterbox) {
            // App prefers to keep its original size.
            // If the size compat is from previous fixed orientation letterboxing, we may want to
            // have fixed orientation letterbox again, otherwise it will show the size compat
@@ -9052,6 +9066,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            // restrict, the bounds should be the requested override bounds.
            getTaskFragment().computeConfigResourceOverrides(resolvedConfig, newParentConfiguration,
                    getFixedRotationTransformDisplayInfo());
            mLetterboxBoundsForAspectRatio = new Rect(resolvedBounds);
        }
    }

@@ -10620,10 +10635,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        /** Whether the {@link Task} windowingMode represents a floating window*/
        final boolean mIsFloating;
        /**
         * Whether is letterboxed because of fixed orientation when the unresizable activity is
         * first shown.
         * Whether is letterboxed because of fixed orientation or aspect ratio when the
         * unresizable activity is first shown.
         */
        final boolean mIsInFixedOrientationLetterbox;
        final boolean mIsInFixedOrientationOrAspectRatioLetterbox;
        /**
         * The nonDecorInsets for each rotation. Includes the navigation bar and cutout insets. It
         * is used to compute the appBounds.
@@ -10638,7 +10653,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

        /** Constructs the environment to simulate the bounds behavior of the given container. */
        CompatDisplayInsets(DisplayContent display, ActivityRecord container,
                @Nullable Rect fixedOrientationBounds) {
                @Nullable Rect letterboxedContainerBounds) {
            mOriginalRotation = display.getRotation();
            mIsFloating = container.getWindowConfiguration().tasksAreFloating();
            mOriginalRequestedOrientation = container.getRequestedConfigurationOrientation();
@@ -10653,22 +10668,21 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                    mNonDecorInsets[rotation] = emptyRect;
                    mStableInsets[rotation] = emptyRect;
                }
                mIsInFixedOrientationLetterbox = false;
                mIsInFixedOrientationOrAspectRatioLetterbox = false;
                return;
            }

            final Task task = container.getTask();

            mIsInFixedOrientationLetterbox = fixedOrientationBounds != null;

            mIsInFixedOrientationOrAspectRatioLetterbox = letterboxedContainerBounds != null;
            // Store the bounds of the Task for the non-resizable activity to use in size compat
            // mode so that the activity will not be resized regardless the windowing mode it is
            // currently in.
            // When an activity needs to be letterboxed because of fixed orientation, use fixed
            // orientation bounds instead of task bounds since the activity will be displayed
            // within these even if it is in size compat mode.
            final Rect filledContainerBounds = mIsInFixedOrientationLetterbox
                    ? fixedOrientationBounds
            // When an activity needs to be letterboxed because of fixed orientation or aspect
            // ratio, use resolved bounds instead of task bounds since the activity will be
            // displayed within these even if it is in size compat mode.
            final Rect filledContainerBounds = mIsInFixedOrientationOrAspectRatioLetterbox
                    ? letterboxedContainerBounds
                    : task != null ? task.getBounds() : display.getBounds();
            final int filledContainerRotation = task != null
                    ? task.getConfiguration().windowConfiguration.getRotation()
+33 −2
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_16_9;
import static android.content.pm.PackageManager.USER_MIN_ASPECT_RATIO_3_2;
@@ -1910,7 +1911,6 @@ public class SizeCompatTests extends WindowTestsBase {
        assertThat(mActivity.inSizeCompatMode()).isTrue();
        assertActivityMaxBoundsSandboxed();


        final int scale = dh / dw;

        // App bounds should be dh / scale x dw / scale
@@ -4100,6 +4100,37 @@ public class SizeCompatTests extends WindowTestsBase {
        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
    }

    @Test
    public void testFixedAspectRatioAppInPortraitCloseToSquareDisplay_notInSizeCompat() {
        setUpDisplaySizeWithApp(2200, 2280);
        mActivity.mDisplayContent.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        final DisplayContent display = mActivity.mDisplayContent;
        // Simulate taskbar, final app bounds are (0, 0, 2200, 2130) - landscape
        final WindowState navbar = createWindow(null, TYPE_NAVIGATION_BAR, mDisplayContent,
                "navbar");
        final Binder owner = new Binder();
        navbar.mAttrs.providedInsets = new InsetsFrameProvider[] {
                new InsetsFrameProvider(owner, 0, WindowInsets.Type.navigationBars())
                        .setInsetsSize(Insets.of(0, 0, 0, 150))
        };
        display.getDisplayPolicy().addWindowLw(navbar, navbar.mAttrs);
        assertTrue(navbar.providesDisplayDecorInsets()
                && display.getDisplayPolicy().updateDecorInsetsInfo());
        display.sendNewConfiguration();

        prepareMinAspectRatio(mActivity, OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
                SCREEN_ORIENTATION_LANDSCAPE);
        // To force config to update again but with the same landscape orientation.
        mActivity.setRequestedOrientation(SCREEN_ORIENTATION_SENSOR_LANDSCAPE);

        assertTrue(mActivity.shouldCreateCompatDisplayInsets());
        assertNotNull(mActivity.getCompatDisplayInsets());
        // Activity is not letterboxed for fixed orientation because orientation is respected
        // with insets, and should not be in size compat mode
        assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
        assertFalse(mActivity.inSizeCompatMode());
    }

    @Test
    public void testApplyAspectRatio_activityAlignWithParentAppVertical() {
        // The display's app bounds will be (0, 100, 1000, 2350)
+1 −1
Original line number Diff line number Diff line
@@ -799,7 +799,7 @@ public class TaskTests extends WindowTestsBase {
        final ActivityRecord activity = new ActivityBuilder(mAtm).setTask(task).build();
        final ActivityRecord.CompatDisplayInsets compatInsets =
                new ActivityRecord.CompatDisplayInsets(
                        display, activity, /* fixedOrientationBounds= */ null);
                        display, activity, /* letterboxedContainerBounds */ null);
        task.computeConfigResourceOverrides(inOutConfig, parentConfig, compatInsets);

        assertEquals(largerLandscapeBounds, inOutConfig.windowConfiguration.getAppBounds());