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

Commit 0e7ef13b authored by Shivam Agrawal's avatar Shivam Agrawal Committed by Android (Google) Code Review
Browse files

Merge "Unify Aspect Ratio Logic in ActivityRecord" into sc-dev

parents 9592b727 efb54c7b
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();