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

Commit 19b1ed40 authored by Pablo Gamito's avatar Pablo Gamito Committed by Automerger Merge Worker
Browse files

Merge "Polish activity transition for letterbox" into tm-qpr-dev am: c3a33cde

parents fdca862c c3a33cde
Loading
Loading
Loading
Loading
+47 −3
Original line number Diff line number Diff line
@@ -660,6 +660,9 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A

    boolean mUseTransferredAnimation;

    /** Whether we need to setup the animation to animate only within the letterbox. */
    private boolean mNeedsLetterboxedAnimation;

    /**
     * @see #currentLaunchCanTurnScreenOn()
     */
@@ -1762,8 +1765,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        mLetterboxUiController.layoutLetterbox(winHint);
    }

    boolean hasWallpaperBackgroudForLetterbox() {
        return mLetterboxUiController.hasWallpaperBackgroudForLetterbox();
    boolean hasWallpaperBackgroundForLetterbox() {
        return mLetterboxUiController.hasWallpaperBackgroundForLetterbox();
    }

    void updateLetterboxSurface(WindowState winHint, Transaction t) {
        mLetterboxUiController.updateLetterboxSurface(winHint, t);
    }

    void updateLetterboxSurface(WindowState winHint) {
@@ -5334,6 +5341,18 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        commitVisibility(visible, performLayout, false /* fromTransition */);
    }

    void setNeedsLetterboxedAnimation(boolean needsLetterboxedAnimation) {
        mNeedsLetterboxedAnimation = needsLetterboxedAnimation;
    }

    boolean isNeedsLetterboxedAnimation() {
        return mNeedsLetterboxedAnimation;
    }

    boolean isInLetterboxAnimation() {
        return mNeedsLetterboxedAnimation && isAnimating();
    }

    /**
     * Post process after applying an app transition animation.
     *
@@ -7261,6 +7280,10 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
                .setParent(getAnimationLeashParent())
                .setName(getSurfaceControl() + " - animation-bounds")
                .setCallsite("ActivityRecord.createAnimationBoundsLayer");
        if (mNeedsLetterboxedAnimation) {
            // Needs to be an effect layer to support rounded corners
            builder.setEffectLayer();
        }
        final SurfaceControl boundsLayer = builder.build();
        t.show(boundsLayer);
        return boundsLayer;
@@ -7298,6 +7321,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            mAnimatingActivityRegistry.notifyStarting(this);
        }

        if (mNeedsLetterboxedAnimation) {
            updateLetterboxSurface(findMainWindow(), t);
            mNeedsAnimationBoundsLayer = true;
        }

        // If the animation needs to be cropped then an animation bounds layer is created as a
        // child of the root pinned task or animation layer. The leash is then reparented to this
        // new layer.
@@ -7320,6 +7348,17 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            t.setLayer(leash, 0);
            t.setLayer(mAnimationBoundsLayer, getLastLayer());

            if (mNeedsLetterboxedAnimation) {
                final int cornerRadius = mLetterboxUiController
                        .getRoundedCornersRadius(findMainWindow());

                final Rect letterboxInnerBounds = new Rect();
                getLetterboxInnerBounds(letterboxInnerBounds);

                t.setCornerRadius(mAnimationBoundsLayer, cornerRadius)
                        .setCrop(mAnimationBoundsLayer, letterboxInnerBounds);
            }

            // Reparent leash to animation bounds layer.
            t.reparent(leash, mAnimationBoundsLayer);
        }
@@ -7433,6 +7472,12 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
            mAnimationBoundsLayer = null;
        }

        mNeedsAnimationBoundsLayer = false;
        if (mNeedsLetterboxedAnimation) {
            mNeedsLetterboxedAnimation = false;
            updateLetterboxSurface(findMainWindow(), t);
        }

        if (mAnimatingActivityRegistry != null) {
            mAnimatingActivityRegistry.notifyFinished(this);
        }
@@ -7445,7 +7490,6 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
        Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "AR#onAnimationFinished");
        mTransit = TRANSIT_OLD_UNSET;
        mTransitFlags = 0;
        mNeedsAnimationBoundsLayer = false;

        setAppLayoutChanges(FINISH_LAYOUT_REDO_ANIM | FINISH_LAYOUT_REDO_WALLPAPER,
                "ActivityRecord");
+28 −0
Original line number Diff line number Diff line
@@ -81,9 +81,11 @@ import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Rect;
import android.os.Trace;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Pair;
import android.util.Slog;
import android.view.Display;
import android.view.RemoteAnimationAdapter;
@@ -1028,6 +1030,32 @@ public class AppTransitionController {
            return;
        }

        if (AppTransition.isActivityTransitOld(transit)) {
            final ArrayList<Pair<ActivityRecord, Rect>> closingLetterboxes = new ArrayList();
            for (int i = 0; i < closingApps.size(); ++i) {
                ActivityRecord closingApp = closingApps.valueAt(i);
                if (closingApp.areBoundsLetterboxed()) {
                    final Rect insets = closingApp.getLetterboxInsets();
                    closingLetterboxes.add(new Pair(closingApp, insets));
                }
            }

            for (int i = 0; i < openingApps.size(); ++i) {
                ActivityRecord openingApp = openingApps.valueAt(i);
                if (openingApp.areBoundsLetterboxed()) {
                    final Rect openingInsets = openingApp.getLetterboxInsets();
                    for (Pair<ActivityRecord, Rect> closingLetterbox : closingLetterboxes) {
                        final Rect closingInsets = closingLetterbox.second;
                        if (openingInsets.equals(closingInsets)) {
                            ActivityRecord closingApp = closingLetterbox.first;
                            openingApp.setNeedsLetterboxedAnimation(true);
                            closingApp.setNeedsLetterboxedAnimation(true);
                        }
                    }
                }
            }
        }

        final ArraySet<WindowContainer> openingWcs = getAnimationTargets(
                openingApps, closingApps, true /* visible */);
        final ArraySet<WindowContainer> closingWcs = getAnimationTargets(
+12 −6
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ public class Letterbox {
    private final Supplier<Boolean> mHasWallpaperBackgroundSupplier;
    private final Supplier<Integer> mBlurRadiusSupplier;
    private final Supplier<Float> mDarkScrimAlphaSupplier;
    private final Supplier<SurfaceControl> mParentSurfaceSupplier;

    private final Rect mOuter = new Rect();
    private final Rect mInner = new Rect();
@@ -87,7 +88,8 @@ public class Letterbox {
            Supplier<Integer> blurRadiusSupplier,
            Supplier<Float> darkScrimAlphaSupplier,
            IntConsumer doubleTapCallbackX,
            IntConsumer doubleTapCallbackY) {
            IntConsumer doubleTapCallbackY,
            Supplier<SurfaceControl> parentSurface) {
        mSurfaceControlFactory = surfaceControlFactory;
        mTransactionFactory = transactionFactory;
        mAreCornersRounded = areCornersRounded;
@@ -97,6 +99,7 @@ public class Letterbox {
        mDarkScrimAlphaSupplier = darkScrimAlphaSupplier;
        mDoubleTapCallbackX = doubleTapCallbackX;
        mDoubleTapCallbackY = doubleTapCallbackY;
        mParentSurfaceSupplier = parentSurface;
    }

    /**
@@ -121,7 +124,6 @@ public class Letterbox {
        mFullWindowSurface.layout(outer.left, outer.top, outer.right, outer.bottom, surfaceOrigin);
    }


    /**
     * Gets the insets between the outer and inner rects.
     */
@@ -333,6 +335,7 @@ public class Letterbox {
        private SurfaceControl mSurface;
        private Color mColor;
        private boolean mHasWallpaperBackground;
        private SurfaceControl mParentSurface;

        private final Rect mSurfaceFrameRelative = new Rect();
        private final Rect mLayoutFrameGlobal = new Rect();
@@ -403,10 +406,12 @@ public class Letterbox {
                }

                mColor = mColorSupplier.get();
                mParentSurface = mParentSurfaceSupplier.get();
                t.setColor(mSurface, getRgbColorArray());
                t.setPosition(mSurface, mSurfaceFrameRelative.left, mSurfaceFrameRelative.top);
                t.setWindowCrop(mSurface, mSurfaceFrameRelative.width(),
                        mSurfaceFrameRelative.height());
                t.reparent(mSurface, mParentSurface);

                mHasWallpaperBackground = mHasWallpaperBackgroundSupplier.get();
                updateAlphaAndBlur(t);
@@ -452,12 +457,13 @@ public class Letterbox {

        public boolean needsApplySurfaceChanges() {
            return !mSurfaceFrameRelative.equals(mLayoutFrameRelative)
                    // If mSurfaceFrameRelative is empty then mHasWallpaperBackground and mColor
                    // may never be updated in applySurfaceChanges but this doesn't mean that
                    // update is needed.
                    // If mSurfaceFrameRelative is empty then mHasWallpaperBackground, mColor,
                    // and mParentSurface may never be updated in applySurfaceChanges but this
                    // doesn't mean that update is needed.
                    || !mSurfaceFrameRelative.isEmpty()
                    && (mHasWallpaperBackgroundSupplier.get() != mHasWallpaperBackground
                    || !mColorSupplier.get().equals(mColor));
                    || !mColorSupplier.get().equals(mColor)
                    || mParentSurfaceSupplier.get() != mParentSurface);
        }
    }
}
+5 −5
Original line number Diff line number Diff line
@@ -265,7 +265,7 @@ final class LetterboxConfiguration {
    }

    /**
     * Overrides corners raidus for activities presented in the letterbox mode. If given value < 0,
     * Overrides corners radius for activities presented in the letterbox mode. If given value < 0,
     * both it and a value of {@link
     * com.android.internal.R.integer.config_letterboxActivityCornersRadius} will be ignored and
     * corners of the activity won't be rounded.
@@ -275,7 +275,7 @@ final class LetterboxConfiguration {
    }

    /**
     * Resets corners raidus for activities presented in the letterbox mode to {@link
     * Resets corners radius for activities presented in the letterbox mode to {@link
     * com.android.internal.R.integer.config_letterboxActivityCornersRadius}.
     */
    void resetLetterboxActivityCornersRadius() {
@@ -291,7 +291,7 @@ final class LetterboxConfiguration {
    }

    /**
     * Gets corners raidus for activities presented in the letterbox mode.
     * Gets corners radius for activities presented in the letterbox mode.
     */
    int getLetterboxActivityCornersRadius() {
        return mLetterboxActivityCornersRadius;
@@ -318,7 +318,7 @@ final class LetterboxConfiguration {
    /**
     * Sets color of letterbox background which is used when {@link
     * #getLetterboxBackgroundType()} is {@link #LETTERBOX_BACKGROUND_SOLID_COLOR} or as
     * fallback for other backfround types.
     * fallback for other background types.
     */
    void setLetterboxBackgroundColor(Color color) {
        mLetterboxBackgroundColorOverride = color;
@@ -327,7 +327,7 @@ final class LetterboxConfiguration {
    /**
     * Sets color ID of letterbox background which is used when {@link
     * #getLetterboxBackgroundType()} is {@link #LETTERBOX_BACKGROUND_SOLID_COLOR} or as
     * fallback for other backfround types.
     * fallback for other background types.
     */
    void setLetterboxBackgroundColorResourceId(int colorId) {
        mLetterboxBackgroundColorResourceIdOverride = colorId;
+99 −35
Original line number Diff line number Diff line
@@ -89,7 +89,7 @@ final class LetterboxUiController {

    // Taskbar expanded height. Used to determine whether to crop an app window to display rounded
    // corners above the taskbar.
    private float mExpandedTaskBarHeight;
    private final float mExpandedTaskBarHeight;

    private boolean mShowWallpaperForLetterboxBackground;

@@ -120,7 +120,7 @@ final class LetterboxUiController {
        }
    }

    boolean hasWallpaperBackgroudForLetterbox() {
    boolean hasWallpaperBackgroundForLetterbox() {
        return mShowWallpaperForLetterboxBackground;
    }

@@ -137,6 +137,11 @@ final class LetterboxUiController {
    void getLetterboxInnerBounds(Rect outBounds) {
        if (mLetterbox != null) {
            outBounds.set(mLetterbox.getInnerFrame());
            final WindowState w = mActivityRecord.findMainWindow();
            if (w == null) {
                return;
            }
            adjustBoundsForTaskbar(w, outBounds);
        } else {
            outBounds.setEmpty();
        }
@@ -160,13 +165,17 @@ final class LetterboxUiController {
    }

    void updateLetterboxSurface(WindowState winHint) {
        updateLetterboxSurface(winHint, mActivityRecord.getSyncTransaction());
    }

    void updateLetterboxSurface(WindowState winHint, Transaction t) {
        final WindowState w = mActivityRecord.findMainWindow();
        if (w != winHint && winHint != null && w != null) {
            return;
        }
        layoutLetterbox(winHint);
        if (mLetterbox != null && mLetterbox.needsApplySurfaceChanges()) {
            mLetterbox.applySurfaceChanges(mActivityRecord.getSyncTransaction());
            mLetterbox.applySurfaceChanges(t);
        }
    }

@@ -191,14 +200,22 @@ final class LetterboxUiController {
                        mActivityRecord.mWmService.mTransactionFactory,
                        this::shouldLetterboxHaveRoundedCorners,
                        this::getLetterboxBackgroundColor,
                        this::hasWallpaperBackgroudForLetterbox,
                        this::hasWallpaperBackgroundForLetterbox,
                        this::getLetterboxWallpaperBlurRadius,
                        this::getLetterboxWallpaperDarkScrimAlpha,
                        this::handleHorizontalDoubleTap,
                        this::handleVerticalDoubleTap);
                        this::handleVerticalDoubleTap,
                        this::getLetterboxParentSurface);
                mLetterbox.attachInput(w);
            }

            if (mActivityRecord.isInLetterboxAnimation()) {
                // In this case we attach the letterbox to the task instead of the activity.
                mActivityRecord.getTask().getPosition(mTmpPoint);
            } else {
                mActivityRecord.getPosition(mTmpPoint);
            }

            // Get the bounds of the "space-to-fill". The transformed bounds have the highest
            // priority because the activity is launched in a rotated environment. In multi-window
            // mode, the task-level represents this. In fullscreen-mode, the task container does
@@ -215,6 +232,13 @@ final class LetterboxUiController {
        }
    }

    SurfaceControl getLetterboxParentSurface() {
        if (mActivityRecord.isInLetterboxAnimation()) {
            return mActivityRecord.getTask().getSurfaceControl();
        }
        return mActivityRecord.getSurfaceControl();
    }

    private boolean shouldLetterboxHaveRoundedCorners() {
        // TODO(b/214030873): remove once background is drawn for transparent activities
        // Letterbox shouldn't have rounded corners if the activity is transparent
@@ -436,7 +460,7 @@ final class LetterboxUiController {
                }
                break;
            case LETTERBOX_BACKGROUND_WALLPAPER:
                if (hasWallpaperBackgroudForLetterbox()) {
                if (hasWallpaperBackgroundForLetterbox()) {
                    // Color is used for translucent scrim that dims wallpaper.
                    return Color.valueOf(Color.BLACK);
                }
@@ -459,15 +483,14 @@ final class LetterboxUiController {
    private void updateRoundedCorners(WindowState mainWindow) {
        final SurfaceControl windowSurface = mainWindow.getClientViewRootSurface();
        if (windowSurface != null && windowSurface.isValid()) {
            Transaction transaction = mActivityRecord.getSyncTransaction();

            final InsetsState insetsState = mainWindow.getInsetsState();
            final InsetsSource taskbarInsetsSource =
                    insetsState.peekSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);

            if (!isLetterboxedNotForDisplayCutout(mainWindow)
                    || !mLetterboxConfiguration.isLetterboxActivityCornersRounded()
                    || taskbarInsetsSource == null) {
            final Transaction transaction = mActivityRecord.getSyncTransaction();

            if (!requiresRoundedCorners(mainWindow) || mActivityRecord.isInLetterboxAnimation()) {
                // We don't want corner radius on the window.
                // In the case the ActivityRecord requires a letterboxed animation we never want
                // rounded corners on the window because rounded corners are applied at the
                // animation-bounds surface level and rounded corners on the window would interfere
                // with that leading to unexpected rounded corner positioning during the animation.
                transaction
                        .setWindowCrop(windowSurface, null)
                        .setCornerRadius(windowSurface, 0);
@@ -476,48 +499,89 @@ final class LetterboxUiController {

            Rect cropBounds = null;

            // Rounded corners should be displayed above the taskbar. When taskbar is hidden,
            // an insets frame is equal to a navigation bar which shouldn't affect position of
            // rounded corners since apps are expected to handle navigation bar inset.
            // This condition checks whether the taskbar is visible.
            // Do not crop the taskbar inset if the window is in immersive mode - the user can
            // swipe to show/hide the taskbar as an overlay.
            if (taskbarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight
                    && taskbarInsetsSource.isVisible()) {
            if (hasVisibleTaskbar(mainWindow)) {
                cropBounds = new Rect(mActivityRecord.getBounds());
                // Activity bounds are in screen coordinates while (0,0) for activity's surface
                // control is at the top left corner of an app window so offsetting bounds
                // accordingly.
                cropBounds.offsetTo(0, 0);
                // Rounded cornerners should be displayed above the taskbar.
                cropBounds.bottom =
                        Math.min(cropBounds.bottom, taskbarInsetsSource.getFrame().top);
                if (mActivityRecord.inSizeCompatMode()
                        && mActivityRecord.getSizeCompatScale() < 1.0f) {
                    cropBounds.scale(1.0f / mActivityRecord.getSizeCompatScale());
                }
                // Rounded corners should be displayed above the taskbar.
                adjustBoundsForTaskbarUnchecked(mainWindow, cropBounds);
            }

            transaction
                    .setWindowCrop(windowSurface, cropBounds)
                    .setCornerRadius(windowSurface, getRoundedCorners(insetsState));
                    .setCornerRadius(windowSurface, getRoundedCornersRadius(mainWindow));
        }
    }

    // Returns rounded corners radius based on override in
    private boolean requiresRoundedCorners(WindowState mainWindow) {
        final InsetsSource taskbarInsetsSource = getTaskbarInsetsSource(mainWindow);

        return isLetterboxedNotForDisplayCutout(mainWindow)
                && mLetterboxConfiguration.isLetterboxActivityCornersRounded()
                && taskbarInsetsSource != null;
    }

    // Returns rounded corners radius the letterboxed activity should have based on override in
    // R.integer.config_letterboxActivityCornersRadius or min device bottom corner radii.
    // Device corners can be different on the right and left sides but we use the same radius
    // for all corners for consistency and pick a minimal bottom one for consistency with a
    // taskbar rounded corners.
    private int getRoundedCorners(InsetsState insetsState) {
    int getRoundedCornersRadius(WindowState mainWindow) {
        if (!requiresRoundedCorners(mainWindow)) {
            return 0;
        }

        if (mLetterboxConfiguration.getLetterboxActivityCornersRadius() >= 0) {
            return mLetterboxConfiguration.getLetterboxActivityCornersRadius();
        }

        final InsetsState insetsState = mainWindow.getInsetsState();
        return Math.min(
                getInsetsStateCornerRadius(insetsState, RoundedCorner.POSITION_BOTTOM_LEFT),
                getInsetsStateCornerRadius(insetsState, RoundedCorner.POSITION_BOTTOM_RIGHT));
    }

    /**
     * Returns whether the taskbar is visible. Returns false if the window is in immersive mode,
     * since the user can swipe to show/hide the taskbar as an overlay.
     */
    private boolean hasVisibleTaskbar(WindowState mainWindow) {
        final InsetsSource taskbarInsetsSource = getTaskbarInsetsSource(mainWindow);

        return taskbarInsetsSource != null
                && taskbarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight
                && taskbarInsetsSource.isVisible();
    }

    private InsetsSource getTaskbarInsetsSource(WindowState mainWindow) {
        final InsetsState insetsState = mainWindow.getInsetsState();
        return insetsState.peekSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
    }

    private void adjustBoundsForTaskbar(WindowState mainWindow, Rect bounds) {
        // Rounded corners should be displayed above the taskbar. When taskbar is hidden,
        // an insets frame is equal to a navigation bar which shouldn't affect position of
        // rounded corners since apps are expected to handle navigation bar inset.
        // This condition checks whether the taskbar is visible.
        // Do not crop the taskbar inset if the window is in immersive mode - the user can
        // swipe to show/hide the taskbar as an overlay.
        if (hasVisibleTaskbar(mainWindow)) {
            adjustBoundsForTaskbarUnchecked(mainWindow, bounds);
        }
    }

    private void adjustBoundsForTaskbarUnchecked(WindowState mainWindow, Rect bounds) {
        // Rounded corners should be displayed above the taskbar.
        bounds.bottom =
                Math.min(bounds.bottom, getTaskbarInsetsSource(mainWindow).getFrame().top);
        if (mActivityRecord.inSizeCompatMode()
                && mActivityRecord.getSizeCompatScale() < 1.0f) {
            bounds.scale(1.0f / mActivityRecord.getSizeCompatScale());
        }
    }

    private int getInsetsStateCornerRadius(
                InsetsState insetsState, @RoundedCorner.Position int position) {
        RoundedCorner corner = insetsState.getRoundedCorners().getRoundedCorner(position);
@@ -592,7 +656,7 @@ final class LetterboxUiController {
                + letterboxBackgroundTypeToString(
                        mLetterboxConfiguration.getLetterboxBackgroundType()));
        pw.println(prefix + "  letterboxCornerRadius="
                + getRoundedCorners(mainWin.getInsetsState()));
                + getRoundedCornersRadius(mainWin));
        if (mLetterboxConfiguration.getLetterboxBackgroundType()
                == LETTERBOX_BACKGROUND_WALLPAPER) {
            pw.println(prefix + "  isLetterboxWallpaperBlurSupported="
Loading