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

Commit a2ac34a2 authored by Shivam Agrawal's avatar Shivam Agrawal Committed by Automerger Merge Worker
Browse files

Merge "Unify Aspect Ratio Logic in ActivityRecord" into sc-dev am: 0e7ef13b

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14907845

Change-Id: Ife9ac51e3382779923fd022d4e6429532b1a25f3
parents 0e8894bf 0e7ef13b
Loading
Loading
Loading
Loading
+73 −51
Original line number Diff line number Diff line
@@ -677,8 +677,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    private boolean mInSizeCompatModeForBounds = false;

    // Whether the aspect ratio restrictions applied to the activity bounds in applyAspectRatio().
    // TODO(b/182268157): Aspect ratio can also be applie in resolveFixedOrientationConfiguration
    // but that isn't reflected in this boolean.
    private boolean mIsAspectRatioApplied = false;

    // Bounds populated in resolveFixedOrientationConfiguration when this activity is letterboxed
@@ -7266,41 +7264,48 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }

        final Rect parentBounds = newParentConfig.windowConfiguration.getBounds();
        final int parentWidth = parentBounds.width();
        final int parentHeight = parentBounds.height();
        float aspect = Math.max(parentWidth, parentHeight)
                / (float) Math.min(parentWidth, parentHeight);
        final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
        final Rect containingBounds = new Rect();
        final Rect containingAppBounds = new Rect();
        // Need to shrink the containing bounds into a square because the parent orientation does
        // not match the activity requested orientation.
        if (forcedOrientation == ORIENTATION_LANDSCAPE) {
            // Shrink height to match width. Position height within app bounds.
            final int bottom = Math.min(parentAppBounds.top + parentBounds.width(),
                    parentAppBounds.bottom);
            containingBounds.set(parentBounds.left, parentAppBounds.top, parentBounds.right,
                    bottom);
            containingAppBounds.set(parentAppBounds.left, parentAppBounds.top,
                    parentAppBounds.right, bottom);
        } else {
            // Shrink width to match height. Position width within app bounds.
            final int right = Math.min(parentAppBounds.left + parentBounds.height(),
                    parentAppBounds.right);
            containingBounds.set(parentAppBounds.left, parentBounds.top, right,
                    parentBounds.bottom);
            containingAppBounds.set(parentAppBounds.left, parentAppBounds.top, right,
                    parentAppBounds.bottom);
        }

        Rect mTmpFullBounds = new Rect(resolvedBounds);
        resolvedBounds.set(containingBounds);

        // Override from config_fixedOrientationLetterboxAspectRatio or via ADB with
        // set-fixed-orientation-letterbox-aspect-ratio.
        final float letterboxAspectRatioOverride =
                mWmService.mLetterboxConfiguration.getFixedOrientationLetterboxAspectRatio();
        aspect = letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO
                ? letterboxAspectRatioOverride : aspect;

        // Adjust the fixed orientation letterbox bounds to fit the app request aspect ratio in
        // order to use the extra available space.
        final float maxAspectRatio = info.getMaxAspectRatio();
        final float minAspectRatio = info.getMinAspectRatio();
        if (aspect > maxAspectRatio && maxAspectRatio != 0) {
            aspect = maxAspectRatio;
        } else if (aspect < minAspectRatio) {
            aspect = minAspectRatio;
        }

        // Store the current bounds to be able to revert to size compat mode values below if needed.
        Rect mTmpFullBounds = new Rect(resolvedBounds);
        final float desiredAspectRatio =
                letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO
                        ? letterboxAspectRatioOverride : computeAspectRatio(parentBounds);
        // Apply aspect ratio to resolved bounds
        mIsAspectRatioApplied = applyAspectRatio(resolvedBounds, containingAppBounds,
                containingBounds, desiredAspectRatio, true);

        // Vertically center if orientation is landscape. Bounds will later be horizontally centered
        // in {@link updateResolvedBoundsHorizontalPosition()} regardless of orientation.
        if (forcedOrientation == ORIENTATION_LANDSCAPE) {
            final int height = (int) Math.rint(parentWidth / aspect);
            final int top = parentBounds.centerY() - height / 2;
            resolvedBounds.set(parentBounds.left, top, parentBounds.right, top + height);
        } else {
            final int width = (int) Math.rint(parentHeight / aspect);
            final Rect parentAppBounds = newParentConfig.windowConfiguration.getAppBounds();
            final int left = width <= parentAppBounds.width()
                    // Avoid overlapping with the horizontal decor area when possible.
                    ? parentAppBounds.left : parentBounds.centerX() - width / 2;
            resolvedBounds.set(left, parentBounds.top, left + width, parentBounds.bottom);
            final int offsetY = parentBounds.centerY() - resolvedBounds.centerY();
            resolvedBounds.offset(0, offsetY);
        }

        if (mCompatDisplayInsets != null) {
@@ -7342,8 +7347,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        // then they should be aligned later in #updateResolvedBoundsHorizontalPosition().
        if (!mTmpBounds.isEmpty()) {
            resolvedBounds.set(mTmpBounds);
            // Exclude the horizontal decor area.
            resolvedBounds.left = parentAppBounds.left;
        }
        if (!resolvedBounds.isEmpty() && !resolvedBounds.equals(parentBounds)) {
            // Compute the configuration based on the resolved bounds. If aspect ratio doesn't
@@ -7404,13 +7407,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            mIsAspectRatioApplied =
                    applyAspectRatio(resolvedBounds, containingAppBounds, containingBounds);
        }
        // If the bounds are restricted by fixed aspect ratio, the resolved bounds should be put in
        // the container app bounds. Otherwise the entire container bounds are available.
        final boolean fillContainer = resolvedBounds.equals(containingBounds);
        if (!fillContainer) {
            // The horizontal position should not cover insets.
            resolvedBounds.left = containingAppBounds.left;
        }

        // Use resolvedBounds to compute other override configurations such as appBounds. The bounds
        // are calculated in compat container space. The actual position on screen will be applied
@@ -7477,6 +7473,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        // Align to top of parent (bounds) - this is a UX choice and exclude the horizontal decor
        // if needed. Horizontal position is adjusted in updateResolvedBoundsHorizontalPosition.
        // Above coordinates are in "@" space, now place "*" and "#" to screen space.
        final boolean fillContainer = resolvedBounds.equals(containingBounds);
        final int screenPosX = fillContainer ? containerBounds.left : containerAppBounds.left;
        final int screenPosY = containerBounds.top;
        if (screenPosX != 0 || screenPosY != 0) {
@@ -7713,6 +7710,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        return true;
    }

    private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds,
            Rect containingBounds) {
        return applyAspectRatio(outBounds, containingAppBounds, containingBounds,
                0 /* desiredAspectRatio */, false /* fixedOrientationLetterboxed */);
    }

    /**
     * Applies aspect ratio restrictions to outBounds. If no restrictions, then no change is
     * made to outBounds.
@@ -7721,17 +7724,19 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
     */
    // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
    private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds,
            Rect containingBounds) {
            Rect containingBounds, float desiredAspectRatio, boolean fixedOrientationLetterboxed) {
        final float maxAspectRatio = info.getMaxAspectRatio();
        final Task rootTask = getRootTask();
        final float minAspectRatio = info.getMinAspectRatio();

        if (task == null || rootTask == null
                || (inMultiWindowMode() && !shouldCreateCompatDisplayInsets())
                || (maxAspectRatio == 0 && minAspectRatio == 0)
                || (inMultiWindowMode() && !shouldCreateCompatDisplayInsets()
                    && !fixedOrientationLetterboxed)
                || (maxAspectRatio < 1 && minAspectRatio < 1 && desiredAspectRatio < 1)
                || isInVrUiMode(getConfiguration())) {
            // We don't enforce aspect ratio if the activity task is in multiwindow unless it
            // is in size-compat mode. We also don't set it if we are in VR mode.
            // We don't enforce aspect ratio if the activity task is in multiwindow unless it is in
            // size-compat mode or is letterboxed from fixed orientation. We also don't set it if we
            // are in VR mode.
            return false;
        }

@@ -7739,20 +7744,30 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        final int containingAppHeight = containingAppBounds.height();
        final float containingRatio = computeAspectRatio(containingAppBounds);

        if (desiredAspectRatio < 1) {
            desiredAspectRatio = containingRatio;
        }

        if (maxAspectRatio >= 1 && desiredAspectRatio > maxAspectRatio) {
            desiredAspectRatio = maxAspectRatio;
        } else if (minAspectRatio >= 1 && desiredAspectRatio < minAspectRatio) {
            desiredAspectRatio = minAspectRatio;
        }

        int activityWidth = containingAppWidth;
        int activityHeight = containingAppHeight;

        if (containingRatio > maxAspectRatio && maxAspectRatio != 0) {
        if (containingRatio > desiredAspectRatio) {
            if (containingAppWidth < containingAppHeight) {
                // Width is the shorter side, so we use that to figure-out what the max. height
                // should be given the aspect ratio.
                activityHeight = (int) ((activityWidth * maxAspectRatio) + 0.5f);
                activityHeight = (int) ((activityWidth * desiredAspectRatio) + 0.5f);
            } else {
                // Height is the shorter side, so we use that to figure-out what the max. width
                // should be given the aspect ratio.
                activityWidth = (int) ((activityHeight * maxAspectRatio) + 0.5f);
                activityWidth = (int) ((activityHeight * desiredAspectRatio) + 0.5f);
            }
        } else if (containingRatio < minAspectRatio) {
        } else if (containingRatio < desiredAspectRatio) {
            boolean adjustWidth;
            switch (getRequestedConfigurationOrientation()) {
                case ORIENTATION_LANDSCAPE:
@@ -7780,9 +7795,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                    break;
            }
            if (adjustWidth) {
                activityWidth = (int) ((activityHeight / minAspectRatio) + 0.5f);
                activityWidth = (int) ((activityHeight / desiredAspectRatio) + 0.5f);
            } else {
                activityHeight = (int) ((activityWidth / minAspectRatio) + 0.5f);
                activityHeight = (int) ((activityWidth / desiredAspectRatio) + 0.5f);
            }
        }

@@ -7806,6 +7821,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
        outBounds.set(containingBounds.left, containingBounds.top, right, bottom);

        // If the bounds are restricted by fixed aspect ratio, then out bounds should be put in the
        // container app bounds. Otherwise the entire container bounds are available.
        if (!outBounds.equals(containingBounds)) {
            // The horizontal position should not cover insets.
            outBounds.left = containingAppBounds.left;
        }

        return true;
    }

+3 −2
Original line number Diff line number Diff line
@@ -401,6 +401,7 @@ public class SizeCompatTests extends WindowTestsBase {
        assertFitted();

        final Rect currentBounds = mActivity.getWindowConfiguration().getBounds();
        final Rect currentAppBounds = mActivity.getWindowConfiguration().getAppBounds();
        final Rect originalBounds = new Rect(mActivity.getWindowConfiguration().getBounds());

        final int notchHeight = 100;
@@ -428,8 +429,8 @@ public class SizeCompatTests extends WindowTestsBase {
        // Because the display cannot rotate, the portrait activity will fit the short side of
        // display with keeping portrait bounds [200, 0 - 700, 1000] in center.
        assertEquals(newDisplayBounds.height(), currentBounds.height());
        assertEquals(currentBounds.height() * newDisplayBounds.height() / newDisplayBounds.width(),
                currentBounds.width());
        assertEquals(currentAppBounds.height() * newDisplayBounds.height()
                / newDisplayBounds.width(), currentAppBounds.width());
        assertFitted();
        // The appBounds should be [200, 100 - 700, 1000].
        final Rect appBounds = mActivity.getWindowConfiguration().getAppBounds();