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

Commit 7cb2114c authored by Johannes Gallmann's avatar Johannes Gallmann Committed by Android (Google) Code Review
Browse files

Merge "Play cross-activity back animation without letterboxes" into main

parents 5e899586 ff6b4983
Loading
Loading
Loading
Loading
+27 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.TestApi;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
@@ -111,6 +112,8 @@ public final class BackNavigationInfo implements Parcelable {
    @Nullable
    private final CustomAnimationInfo mCustomAnimationInfo;

    private final int mLetterboxColor;

    /**
     * Create a new {@link BackNavigationInfo} instance.
     *
@@ -124,13 +127,15 @@ public final class BackNavigationInfo implements Parcelable {
            @Nullable IOnBackInvokedCallback onBackInvokedCallback,
            boolean isPrepareRemoteAnimation,
            boolean isAnimationCallback,
            @Nullable CustomAnimationInfo customAnimationInfo) {
            @Nullable CustomAnimationInfo customAnimationInfo,
            int letterboxColor) {
        mType = type;
        mOnBackNavigationDone = onBackNavigationDone;
        mOnBackInvokedCallback = onBackInvokedCallback;
        mPrepareRemoteAnimation = isPrepareRemoteAnimation;
        mAnimationCallback = isAnimationCallback;
        mCustomAnimationInfo = customAnimationInfo;
        mLetterboxColor = letterboxColor;
    }

    private BackNavigationInfo(@NonNull Parcel in) {
@@ -140,6 +145,7 @@ public final class BackNavigationInfo implements Parcelable {
        mPrepareRemoteAnimation = in.readBoolean();
        mAnimationCallback = in.readBoolean();
        mCustomAnimationInfo = in.readTypedObject(CustomAnimationInfo.CREATOR);
        mLetterboxColor = in.readInt();
    }

    /** @hide */
@@ -151,6 +157,7 @@ public final class BackNavigationInfo implements Parcelable {
        dest.writeBoolean(mPrepareRemoteAnimation);
        dest.writeBoolean(mAnimationCallback);
        dest.writeTypedObject(mCustomAnimationInfo, flags);
        dest.writeInt(mLetterboxColor);
    }

    /**
@@ -192,6 +199,13 @@ public final class BackNavigationInfo implements Parcelable {
        return mAnimationCallback;
    }

    /**
     * @return Letterbox color
     * @hide
     */
    public int getLetterboxColor() {
        return mLetterboxColor;
    }
    /**
     * Callback to be called when the back preview is finished in order to notify the server that
     * it can clean up the resources created for the animation.
@@ -387,6 +401,8 @@ public final class BackNavigationInfo implements Parcelable {
        private CustomAnimationInfo mCustomAnimationInfo;
        private boolean mAnimationCallback = false;

        private int mLetterboxColor = Color.TRANSPARENT;

        /**
         * @see BackNavigationInfo#getType()
         */
@@ -453,6 +469,14 @@ public final class BackNavigationInfo implements Parcelable {
            return this;
        }

        /**
         * @param color Non-transparent if there contain letterbox color.
         */
        public Builder setLetterboxColor(int color) {
            mLetterboxColor = color;
            return this;
        }

        /**
         * Builds and returns an instance of {@link BackNavigationInfo}
         */
@@ -461,7 +485,8 @@ public final class BackNavigationInfo implements Parcelable {
                    mOnBackInvokedCallback,
                    mPrepareRemoteAnimation,
                    mAnimationCallback,
                    mCustomAnimationInfo);
                    mCustomAnimationInfo,
                    mLetterboxColor);
        }
    }
}
+99 −10
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.content.Context
import android.content.res.Configuration
import android.graphics.Color
import android.graphics.Matrix
import android.graphics.PointF
import android.graphics.Rect
@@ -35,6 +36,7 @@ import android.view.animation.DecelerateInterpolator
import android.view.animation.Interpolator
import android.window.BackEvent
import android.window.BackMotionEvent
import android.window.BackNavigationInfo
import android.window.BackProgressAnimator
import android.window.IOnBackInvokedCallback
import com.android.internal.jank.Cuj
@@ -67,6 +69,7 @@ class CrossActivityBackAnimation @Inject constructor(
    private val currentEnteringRect = RectF()

    private val backAnimRect = Rect()
    private val cropRect = Rect()

    private var cornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context)

@@ -95,6 +98,10 @@ class CrossActivityBackAnimation @Inject constructor(
    private var maxScrimAlpha: Float = 0f

    private var isLetterboxed = false
    private var enteringHasSameLetterbox = false
    private var leftLetterboxLayer: SurfaceControl? = null
    private var rightLetterboxLayer: SurfaceControl? = null
    private var letterboxColor: Int = 0

    override fun onConfigurationChanged(newConfiguration: Configuration) {
        cornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context)
@@ -115,8 +122,12 @@ class CrossActivityBackAnimation @Inject constructor(

        transaction.setAnimationTransaction()
        isLetterboxed = closingTarget!!.taskInfo.appCompatTaskInfo.topActivityBoundsLetterboxed
        if (isLetterboxed) {
            // Include letterbox in back animation
        enteringHasSameLetterbox = isLetterboxed &&
                closingTarget!!.localBounds.equals(enteringTarget!!.localBounds)

        if (isLetterboxed && !enteringHasSameLetterbox) {
            // Play animation with letterboxes, if closing and entering target have mismatching
            // letterboxes
            backAnimRect.set(closingTarget!!.windowConfiguration.bounds)
        } else {
            // otherwise play animation on localBounds only
@@ -144,12 +155,25 @@ class CrossActivityBackAnimation @Inject constructor(
        targetEnteringRect.set(startEnteringRect)
        targetEnteringRect.scaleCentered(MAX_SCALE)

        // Draw background with task background color.
        // Draw background with task background color (or letterbox color).
        val backgroundColor = if (isLetterboxed) {
            letterboxColor
        } else {
            enteringTarget!!.taskInfo.taskDescription!!.backgroundColor
        }
        background.ensureBackground(
            closingTarget!!.windowConfiguration.bounds,
            enteringTarget!!.taskInfo.taskDescription!!.backgroundColor, transaction
            closingTarget!!.windowConfiguration.bounds, backgroundColor, transaction
        )
        ensureScrimLayer()
        if (isLetterboxed && enteringHasSameLetterbox) {
            // crop left and right letterboxes
            cropRect.set(closingTarget!!.localBounds.left, 0, closingTarget!!.localBounds.right,
                    closingTarget!!.windowConfiguration.bounds.height())
            // and add fake letterbox square surfaces instead
            ensureLetterboxes()
        } else {
            cropRect.set(backAnimRect)
        }
        applyTransaction()
    }

@@ -249,18 +273,25 @@ class CrossActivityBackAnimation @Inject constructor(
        }
        finishCallback = null
        removeScrimLayer()
        removeLetterbox()
        isLetterboxed = false
        enteringHasSameLetterbox = false
    }

    private fun applyTransform(leash: SurfaceControl?, rect: RectF, alpha: Float) {
        if (leash == null || !leash.isValid) return
        val scale = rect.width() / backAnimRect.width()
        transformMatrix.reset()
        transformMatrix.setScale(scale, scale)
        val scalePivotX = if (isLetterboxed && enteringHasSameLetterbox) {
            closingTarget!!.localBounds.left.toFloat()
        } else {
            0f
        }
        transformMatrix.setScale(scale, scale, scalePivotX, 0f)
        transformMatrix.postTranslate(rect.left, rect.top)
        transaction.setAlpha(leash, alpha)
            .setMatrix(leash, transformMatrix, tmpFloat9)
            .setCrop(leash, backAnimRect)
            .setCrop(leash, cropRect)
            .setCornerRadius(leash, cornerRadius)
    }

@@ -297,15 +328,73 @@ class CrossActivityBackAnimation @Inject constructor(
    }

    private fun removeScrimLayer() {
        scrimLayer?.let {
        if (removeLayer(scrimLayer)) applyTransaction()
        scrimLayer = null
    }

    /**
     * Adds two "fake" letterbox square surfaces to the left and right of the localBounds of the
     * closing target
     */
    private fun ensureLetterboxes() {
        closingTarget?.let { t ->
            if (t.localBounds.left != 0 && leftLetterboxLayer == null) {
                val bounds = Rect(0, t.windowConfiguration.bounds.top, t.localBounds.left,
                        t.windowConfiguration.bounds.bottom)
                leftLetterboxLayer = ensureLetterbox(bounds)
            }
            if (t.localBounds.right != t.windowConfiguration.bounds.right &&
                    rightLetterboxLayer == null) {
                val bounds = Rect(t.localBounds.right, t.windowConfiguration.bounds.top,
                        t.windowConfiguration.bounds.right, t.windowConfiguration.bounds.bottom)
                rightLetterboxLayer = ensureLetterbox(bounds)
            }
        }
    }

    private fun ensureLetterbox(bounds: Rect): SurfaceControl {
        val letterboxBuilder = SurfaceControl.Builder()
                .setName("Cross-Activity back animation letterbox")
                .setCallsite("CrossActivityBackAnimation")
                .setColorLayer()
                .setOpaque(true)
                .setHidden(false)

        rootTaskDisplayAreaOrganizer.attachToDisplayArea(Display.DEFAULT_DISPLAY, letterboxBuilder)
        val layer = letterboxBuilder.build()
        val colorComponents = floatArrayOf(Color.red(letterboxColor) / 255f,
                Color.green(letterboxColor) / 255f, Color.blue(letterboxColor) / 255f)
        transaction
                .setColor(layer, colorComponents)
                .setCrop(layer, bounds)
                .setRelativeLayer(layer, closingTarget!!.leash, 1)
                .show(layer)
        return layer
    }

    private fun removeLetterbox() {
        if (removeLayer(leftLetterboxLayer) || removeLayer(rightLetterboxLayer)) applyTransaction()
        leftLetterboxLayer = null
        rightLetterboxLayer = null
    }

    private fun removeLayer(layer: SurfaceControl?): Boolean {
        layer?.let {
            if (it.isValid) {
                transaction.remove(it)
                applyTransaction()
                return true
            }
        }
        scrimLayer = null
        return false
    }

    override fun prepareNextAnimation(
            animationInfo: BackNavigationInfo.CustomAnimationInfo?,
            letterboxColor: Int
    ): Boolean {
        this.letterboxColor = letterboxColor
        return false
    }

    private inner class Callback : IOnBackInvokedCallback.Default() {
        override fun onBackStarted(backMotionEvent: BackMotionEvent) {
+2 −1
Original line number Diff line number Diff line
@@ -271,7 +271,8 @@ public class CustomizeActivityAnimation extends ShellBackAnimation {

    /** Load customize animation before animation start. */
    @Override
    public boolean prepareNextAnimation(BackNavigationInfo.CustomAnimationInfo animationInfo) {
    public boolean prepareNextAnimation(BackNavigationInfo.CustomAnimationInfo animationInfo,
            int letterboxColor) {
        if (animationInfo == null) {
            return false;
        }
+3 −2
Original line number Diff line number Diff line
@@ -42,11 +42,12 @@ public abstract class ShellBackAnimation {
    public abstract BackAnimationRunner getRunner();

    /**
     * Prepare the next animation with customized animation.
     * Prepare the next animation.
     *
     * @return true if this type of back animation should override the default.
     */
    public boolean prepareNextAnimation(BackNavigationInfo.CustomAnimationInfo animationInfo) {
    public boolean prepareNextAnimation(BackNavigationInfo.CustomAnimationInfo animationInfo,
            int letterboxColor) {
        return false;
    }

+4 −1
Original line number Diff line number Diff line
@@ -154,11 +154,14 @@ public class ShellBackAnimationRegistry {
        if (type == BackNavigationInfo.TYPE_CROSS_ACTIVITY && mAnimationDefinition.contains(type)) {
            if (mCustomizeActivityAnimation != null
                    && mCustomizeActivityAnimation.prepareNextAnimation(
                            backNavigationInfo.getCustomAnimationInfo())) {
                            backNavigationInfo.getCustomAnimationInfo(), 0)) {
                mAnimationDefinition.get(type).resetWaitingAnimation();
                mAnimationDefinition.set(
                        BackNavigationInfo.TYPE_CROSS_ACTIVITY,
                        mCustomizeActivityAnimation.getRunner());
            } else if (mDefaultCrossActivityAnimation != null) {
                mDefaultCrossActivityAnimation.prepareNextAnimation(null,
                        backNavigationInfo.getLetterboxColor());
            }
        }
        BackAnimationRunner runner = mAnimationDefinition.get(type);
Loading