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

Commit b0d976b8 authored by Graciela Putri's avatar Graciela Putri Committed by Android (Google) Code Review
Browse files

Merge "Fix immersive app resizing when repositioning" into 24D1-dev

parents 903e019c 89e06578
Loading
Loading
Loading
Loading
+49 −18
Original line number Diff line number Diff line
@@ -76,7 +76,6 @@ import static android.content.pm.ActivityInfo.FLAG_NO_HISTORY;
import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
import static android.content.pm.ActivityInfo.FLAG_STATE_NOT_NEEDED;
import static android.content.pm.ActivityInfo.FLAG_TURN_SCREEN_ON;
import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION;
import static android.content.pm.ActivityInfo.INSETS_DECOUPLED_CONFIGURATION_ENFORCED;
import static android.content.pm.ActivityInfo.LAUNCH_MULTIPLE;
import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE;
@@ -86,6 +85,7 @@ import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_ALLOWLISTED;
import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
import static android.content.pm.ActivityInfo.OVERRIDE_ENABLE_INSETS_DECOUPLED_CONFIGURATION;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_EXCLUDE_PORTRAIT_FULLSCREEN;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_LARGE;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM;
@@ -311,6 +311,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;
@@ -352,6 +353,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;
@@ -8533,6 +8535,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);
@@ -8545,14 +8554,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
@@ -8764,7 +8765,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;
        }

@@ -8793,13 +8794,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
@@ -8819,9 +8834,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
@@ -8841,7 +8855,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;
@@ -8864,6 +8879,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        }
    }

    boolean isImmersiveMode(@NonNull Rect parentBounds) {
        if (!mResolveConfigHint.mUseOverrideInsetsForStableBounds) {
            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();
@@ -8906,6 +8933,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        return mLetterboxBoundsForFixedOrientationAndAspectRatio != null;
    }

    boolean isLetterboxedForAspectRatioOnly() {
        return mLetterboxBoundsForAspectRatio != null;
    }

    boolean isAspectRatioApplied() {
        return mIsAspectRatioApplied;
    }
@@ -9198,11 +9229,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
@@ -1686,7 +1686,7 @@ final class LetterboxUiController {
        if (mainWin.isLetterboxedForDisplayCutout()) {
            return "DISPLAY_CUTOUT";
        }
        if (mActivityRecord.isAspectRatioApplied()) {
        if (mActivityRecord.isLetterboxedForAspectRatioOnly()) {
            return "ASPECT_RATIO";
        }
        return "UNKNOWN_REASON";
+53 −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;
@@ -123,6 +124,7 @@ import com.android.internal.policy.SystemBarUtils;
import com.android.internal.statusbar.LetterboxDetails;
import com.android.server.statusbar.StatusBarManagerInternal;
import com.android.server.wm.DeviceStateController.DeviceState;
import com.android.window.flags.Flags;

import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
@@ -187,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) {
@@ -395,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);
@@ -3994,8 +4046,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();