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

Commit 0cde3ea0 authored by Yunfan Chen's avatar Yunfan Chen Committed by Android (Google) Code Review
Browse files

Merge "Fix immersive app resizing when repositioning" into main

parents c756c6c1 e95a103c
Loading
Loading
Loading
Loading
+48 −17
Original line number Diff line number Diff line
@@ -315,6 +315,7 @@ import android.content.pm.UserProperties;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
@@ -356,6 +357,7 @@ import android.view.RemoteAnimationTarget;
import android.view.Surface.Rotation;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.WindowInsets;
import android.view.WindowInsets.Type;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
@@ -8560,6 +8562,13 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        if (isFixedOrientationLetterboxAllowed) {
            resolveFixedOrientationConfiguration(newParentConfiguration);
        }
        // If activity in fullscreen mode is letterboxed because of fixed orientation then bounds
        // are already calculated in resolveFixedOrientationConfiguration.
        // Don't apply aspect ratio if app is overridden to fullscreen by device user/manufacturer.
        if (!isLetterboxedForFixedOrientationAndAspectRatio()
                && !mLetterboxUiController.hasFullscreenOverride()) {
            resolveAspectRatioRestriction(newParentConfiguration);
        }
        final CompatDisplayInsets compatDisplayInsets = getCompatDisplayInsets();
        if (compatDisplayInsets != null) {
            resolveSizeCompatModeConfiguration(newParentConfiguration, compatDisplayInsets);
@@ -8572,14 +8581,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            if (!matchParentBounds()) {
                computeConfigByResolveHint(resolvedConfig, newParentConfiguration);
            }
        // If activity in fullscreen mode is letterboxed because of fixed orientation then bounds
        // are already calculated in resolveFixedOrientationConfiguration, or if in size compat
        // mode, it should already be calculated in resolveSizeCompatModeConfiguration.
        // Don't apply aspect ratio if app is overridden to fullscreen by device user/manufacturer.
        }
        if (!isLetterboxedForFixedOrientationAndAspectRatio() && !mInSizeCompatModeForBounds
                && !mLetterboxUiController.hasFullscreenOverride()) {
            resolveAspectRatioRestriction(newParentConfiguration);
        }
        if (isFixedOrientationLetterboxAllowed || compatDisplayInsets != null
@@ -8801,7 +8802,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            return APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_FIXED_ORIENTATION;
        }
        // Letterbox for limited aspect ratio.
        if (mIsAspectRatioApplied) {
        if (isLetterboxedForAspectRatioOnly()) {
            return APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_ASPECT_RATIO;
        }
@@ -8830,13 +8831,27 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        final Rect parentBounds = newParentConfiguration.windowConfiguration.getBounds();
        final float screenResolvedBoundsWidth = screenResolvedBounds.width();
        final float parentAppBoundsWidth = parentAppBounds.width();
        final boolean isImmersiveMode = isImmersiveMode(parentBounds);
        final Insets navBarInsets;
        if (isImmersiveMode) {
            navBarInsets = mDisplayContent.getInsetsStateController()
                    .getRawInsetsState().calculateInsets(
                            parentBounds,
                            WindowInsets.Type.navigationBars(),
                            true /* ignoreVisibility */);
        } else {
            navBarInsets = Insets.NONE;
        }
        // Horizontal position
        int offsetX = 0;
        if (parentBounds.width() != screenResolvedBoundsWidth) {
            if (screenResolvedBoundsWidth <= parentAppBoundsWidth) {
                float positionMultiplier = mLetterboxUiController.getHorizontalPositionMultiplier(
                        newParentConfiguration);
                offsetX = Math.max(0, (int) Math.ceil((parentAppBoundsWidth
                // If in immersive mode, always align to right and overlap right insets (task bar)
                // as they are transient and hidden. This removes awkward right spacing.
                final int appWidth = (int) (parentAppBoundsWidth + navBarInsets.right);
                offsetX = Math.max(0, (int) Math.ceil((appWidth
                        - screenResolvedBoundsWidth) * positionMultiplier)
                        // This is added to make sure that insets added inside
                        // CompatDisplayInsets#getContainerBounds() do not break the alignment
@@ -8856,9 +8871,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                        newParentConfiguration);
                // If in immersive mode, always align to bottom and overlap bottom insets (nav bar,
                // task bar) as they are transient and hidden. This removes awkward bottom spacing.
                final float newHeight = mDisplayContent.getDisplayPolicy().isImmersiveMode()
                        ? parentBoundsHeight : parentAppBoundsHeight;
                offsetY = Math.max(0, (int) Math.ceil((newHeight
                final int appHeight = (int) (parentAppBoundsHeight + navBarInsets.bottom);
                offsetY = Math.max(0, (int) Math.ceil((appHeight
                        - screenResolvedBoundsHeight) * positionMultiplier)
                        // This is added to make sure that insets added inside
                        // CompatDisplayInsets#getContainerBounds() do not break the alignment
@@ -8878,7 +8892,8 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        // If the top is aligned with parentAppBounds add the vertical insets back so that the app
        // content aligns with the status bar
        if (resolvedConfig.windowConfiguration.getAppBounds().top == parentAppBounds.top) {
        if (resolvedConfig.windowConfiguration.getAppBounds().top == parentAppBounds.top
                && !isImmersiveMode) {
            resolvedConfig.windowConfiguration.getBounds().top = parentBounds.top;
            if (mSizeCompatBounds != null) {
                mSizeCompatBounds.top = parentBounds.top;
@@ -8901,6 +8916,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
    }
    boolean isImmersiveMode(@NonNull Rect parentBounds) {
        if (!mResolveConfigHint.mUseOverrideInsetsForConfig) {
            return false;
        }
        final Insets navBarInsets = mDisplayContent.getInsetsStateController()
                .getRawInsetsState().calculateInsets(
                        parentBounds,
                        WindowInsets.Type.navigationBars(),
                        false /* ignoreVisibility */);
        return Insets.NONE.equals(navBarInsets);
    }
    @NonNull Rect getScreenResolvedBounds() {
        final Configuration resolvedConfig = getResolvedOverrideConfiguration();
        final Rect resolvedBounds = resolvedConfig.windowConfiguration.getBounds();
@@ -8943,6 +8970,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        return mLetterboxBoundsForFixedOrientationAndAspectRatio != null;
    }
    boolean isLetterboxedForAspectRatioOnly() {
        return mLetterboxBoundsForAspectRatio != null;
    }
    boolean isAspectRatioApplied() {
        return mIsAspectRatioApplied;
    }
@@ -9235,11 +9266,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        // orientation bounds (stored in resolved bounds) instead of parent bounds since the
        // activity will be displayed within them even if it is in size compat mode. They should be
        // saved here before resolved bounds are overridden below.
        final Rect containerBounds = isLetterboxedForFixedOrientationAndAspectRatio()
        final Rect containerBounds = isAspectRatioApplied()
                ? new Rect(resolvedBounds)
                : newParentConfiguration.windowConfiguration.getBounds();
        final Rect containerAppBounds = isLetterboxedForFixedOrientationAndAspectRatio()
                ? new Rect(getResolvedOverrideConfiguration().windowConfiguration.getAppBounds())
        final Rect containerAppBounds = isAspectRatioApplied()
                ? new Rect(resolvedConfig.windowConfiguration.getAppBounds())
                : newParentConfiguration.windowConfiguration.getAppBounds();
        final int requestedOrientation = getRequestedConfigurationOrientation();
+1 −1
Original line number Diff line number Diff line
@@ -1704,7 +1704,7 @@ final class LetterboxUiController {
        if (mainWin.isLetterboxedForDisplayCutout()) {
            return "DISPLAY_CUTOUT";
        }
        if (mActivityRecord.isAspectRatioApplied()) {
        if (mActivityRecord.isLetterboxedForAspectRatioOnly()) {
            return "ASPECT_RATIO";
        }
        return "UNKNOWN_REASON";
+52 −2
Original line number Diff line number Diff line
@@ -108,6 +108,7 @@ import android.os.Binder;
import android.os.RemoteException;
import android.os.UserHandle;
import android.platform.test.annotations.Presubmit;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;
import android.view.InsetsFrameProvider;
@@ -188,6 +189,7 @@ public class SizeCompatTests extends WindowTestsBase {
    private void setUpApp(DisplayContent display) {
        mTask = new TaskBuilder(mSupervisor).setDisplay(display).setCreateActivity(true).build();
        mActivity = mTask.getTopNonFinishingActivity();
        doReturn(false).when(mActivity).isImmersiveMode(any());
    }

    private void setUpDisplaySizeWithApp(int dw, int dh) {
@@ -396,6 +398,55 @@ public class SizeCompatTests extends WindowTestsBase {
        verify(translucentActivity.mLetterboxUiController).updateInheritedLetterbox();
    }

    // TODO(b/333663877): Enable test after fix
    @Test
    @RequiresFlagsDisabled({Flags.FLAG_INSETS_DECOUPLED_CONFIGURATION})
    public void testRepositionLandscapeImmersiveAppWithDisplayCutout() {
        final int dw = 2100;
        final int dh = 2000;
        final int cutoutHeight = 150;
        final TestDisplayContent display = new TestDisplayContent.Builder(mAtm, dw, dh)
                .setCanRotate(false)
                .setNotch(cutoutHeight)
                .build();
        setUpApp(display);
        display.setIgnoreOrientationRequest(true /* ignoreOrientationRequest */);
        mWm.mLetterboxConfiguration.setLetterboxVerticalPositionMultiplier(0.5f);
        mWm.mLetterboxConfiguration.setIsVerticalReachabilityEnabled(true);

        doReturn(true).when(mActivity).isImmersiveMode(any());
        prepareMinAspectRatio(mActivity, OVERRIDE_MIN_ASPECT_RATIO_LARGE_VALUE,
                SCREEN_ORIENTATION_LANDSCAPE);
        addWindowToActivity(mActivity);
        mActivity.mRootWindowContainer.performSurfacePlacement();

        final Function<ActivityRecord, Rect> innerBoundsOf =
                (ActivityRecord a) -> {
                    final Rect bounds = new Rect();
                    a.mLetterboxUiController.getLetterboxInnerBounds(bounds);
                    return bounds;
                };

        final Consumer<Integer> doubleClick =
                (Integer y) -> {
                    mActivity.mLetterboxUiController.handleVerticalDoubleTap(y);
                    mActivity.mRootWindowContainer.performSurfacePlacement();
                };

        final Rect bounds = mActivity.getBounds();
        assertTrue(bounds.top > cutoutHeight && bounds.bottom < dh);
        assertEquals(dw, bounds.width());

        // Double click bottom.
        doubleClick.accept(dh - 10);
        assertEquals(dh, innerBoundsOf.apply(mActivity).bottom);

        // Double click top.
        doubleClick.accept(10);
        doubleClick.accept(10);
        assertEquals(cutoutHeight, innerBoundsOf.apply(mActivity).top);
    }

    @Test
    public void testResetOpaqueReferenceWhenOpaqueIsDestroyed() {
        mWm.mLetterboxConfiguration.setTranslucentLetterboxingOverrideEnabled(true);
@@ -4034,8 +4085,7 @@ public class SizeCompatTests extends WindowTestsBase {

        // Prepare unresizable landscape activity
        prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
        final DisplayPolicy displayPolicy = mActivity.mDisplayContent.getDisplayPolicy();
        doReturn(immersive).when(displayPolicy).isImmersiveMode();
        doReturn(immersive).when(mActivity).isImmersiveMode(any());

        mActivity.mRootWindowContainer.performSurfacePlacement();