/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.wm.shell.pip;

import static android.util.RotationUtils.rotateBounds;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;

import android.animation.AnimationHandler;
import android.animation.Animator;
import android.animation.RectEvaluator;
import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.app.TaskInfo;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.Rect;
import android.view.Choreographer;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceSession;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.wm.shell.animation.Interpolators;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.Objects;

/**
 * Controller class of PiP animations (both from and to PiP mode).
 */
public class PipAnimationController {
    static final float FRACTION_START = 0f;
    private static final float FRACTION_END = 1f;

    public static final int ANIM_TYPE_BOUNDS = 0;
    public static final int ANIM_TYPE_ALPHA = 1;

    @IntDef(prefix = { "ANIM_TYPE_" }, value = {
            ANIM_TYPE_BOUNDS,
            ANIM_TYPE_ALPHA
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface AnimationType {}

    public static final int TRANSITION_DIRECTION_NONE = 0;
    public static final int TRANSITION_DIRECTION_SAME = 1;
    public static final int TRANSITION_DIRECTION_TO_PIP = 2;
    public static final int TRANSITION_DIRECTION_LEAVE_PIP = 3;
    public static final int TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN = 4;
    public static final int TRANSITION_DIRECTION_REMOVE_STACK = 5;
    public static final int TRANSITION_DIRECTION_SNAP_AFTER_RESIZE = 6;
    public static final int TRANSITION_DIRECTION_USER_RESIZE = 7;
    public static final int TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND = 8;

    @IntDef(prefix = { "TRANSITION_DIRECTION_" }, value = {
            TRANSITION_DIRECTION_NONE,
            TRANSITION_DIRECTION_SAME,
            TRANSITION_DIRECTION_TO_PIP,
            TRANSITION_DIRECTION_LEAVE_PIP,
            TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN,
            TRANSITION_DIRECTION_REMOVE_STACK,
            TRANSITION_DIRECTION_SNAP_AFTER_RESIZE,
            TRANSITION_DIRECTION_USER_RESIZE,
            TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface TransitionDirection {}

    public static boolean isInPipDirection(@TransitionDirection int direction) {
        return direction == TRANSITION_DIRECTION_TO_PIP;
    }

    public static boolean isOutPipDirection(@TransitionDirection int direction) {
        return direction == TRANSITION_DIRECTION_LEAVE_PIP
                || direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN;
    }

    /** Whether the given direction represents removing PIP. */
    public static boolean isRemovePipDirection(@TransitionDirection int direction) {
        return direction == TRANSITION_DIRECTION_REMOVE_STACK;
    }

    private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;

    private final ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal =
            ThreadLocal.withInitial(() -> {
                AnimationHandler handler = new AnimationHandler();
                handler.setProvider(new SfVsyncFrameCallbackProvider());
                return handler;
            });

    private PipTransitionAnimator mCurrentAnimator;

    public PipAnimationController(PipSurfaceTransactionHelper helper) {
        mSurfaceTransactionHelper = helper;
    }

    @SuppressWarnings("unchecked")
    @VisibleForTesting
    public PipTransitionAnimator getAnimator(TaskInfo taskInfo, SurfaceControl leash,
            Rect destinationBounds, float alphaStart, float alphaEnd) {
        if (mCurrentAnimator == null) {
            mCurrentAnimator = setupPipTransitionAnimator(
                    PipTransitionAnimator.ofAlpha(taskInfo, leash, destinationBounds, alphaStart,
                            alphaEnd));
        } else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA
                && Objects.equals(destinationBounds, mCurrentAnimator.getDestinationBounds())
                && mCurrentAnimator.isRunning()) {
            mCurrentAnimator.updateEndValue(alphaEnd);
        } else {
            mCurrentAnimator.cancel();
            mCurrentAnimator = setupPipTransitionAnimator(
                    PipTransitionAnimator.ofAlpha(taskInfo, leash, destinationBounds, alphaStart,
                            alphaEnd));
        }
        return mCurrentAnimator;
    }

    @SuppressWarnings("unchecked")
    /**
     * Construct and return an animator that animates from the {@param startBounds} to the
     * {@param endBounds} with the given {@param direction}. If {@param direction} is type
     * {@link ANIM_TYPE_BOUNDS}, then {@param sourceHintRect} will be used to animate
     * in a better, more smooth manner. If the original bound was rotated and a reset needs to
     * happen, pass in {@param startingAngle}.
     *
     * In the case where one wants to start animation during an intermediate animation (for example,
     * if the user is currently doing a pinch-resize, and upon letting go now PiP needs to animate
     * to the correct snap fraction region), then provide the base bounds, which is current PiP
     * leash bounds before transformation/any animation. This is so when we try to construct
     * the different transformation matrices for the animation, we are constructing this based off
     * the PiP original bounds, rather than the {@param startBounds}, which is post-transformed.
     *
     * If non-zero {@param rotationDelta} is given, it means that the display will be rotated by
     * leaving PiP to fullscreen, and the {@param endBounds} is the fullscreen bounds before the
     * rotation change.
     */
    @VisibleForTesting
    public PipTransitionAnimator getAnimator(TaskInfo taskInfo, SurfaceControl leash,
            Rect baseBounds, Rect startBounds, Rect endBounds, Rect sourceHintRect,
            @PipAnimationController.TransitionDirection int direction, float startingAngle,
            @Surface.Rotation int rotationDelta) {
        if (mCurrentAnimator == null) {
            mCurrentAnimator = setupPipTransitionAnimator(
                    PipTransitionAnimator.ofBounds(taskInfo, leash, startBounds, startBounds,
                            endBounds, sourceHintRect, direction, 0 /* startingAngle */,
                            rotationDelta));
        } else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA
                && mCurrentAnimator.isRunning()) {
            // If we are still animating the fade into pip, then just move the surface and ensure
            // we update with the new destination bounds, but don't interrupt the existing animation
            // with a new bounds
            mCurrentAnimator.setDestinationBounds(endBounds);
        } else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_BOUNDS
                && mCurrentAnimator.isRunning()) {
            mCurrentAnimator.setDestinationBounds(endBounds);
            // construct new Rect instances in case they are recycled
            mCurrentAnimator.updateEndValue(new Rect(endBounds));
        } else {
            mCurrentAnimator.cancel();
            mCurrentAnimator = setupPipTransitionAnimator(
                    PipTransitionAnimator.ofBounds(taskInfo, leash, baseBounds, startBounds,
                            endBounds, sourceHintRect, direction, startingAngle, rotationDelta));
        }
        return mCurrentAnimator;
    }

    PipTransitionAnimator getCurrentAnimator() {
        return mCurrentAnimator;
    }

    private PipTransitionAnimator setupPipTransitionAnimator(PipTransitionAnimator animator) {
        animator.setSurfaceTransactionHelper(mSurfaceTransactionHelper);
        animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
        animator.setFloatValues(FRACTION_START, FRACTION_END);
        animator.setAnimationHandler(mSfAnimationHandlerThreadLocal.get());
        return animator;
    }

    /**
     * Additional callback interface for PiP animation
     */
    public static class PipAnimationCallback {
        /**
         * Called when PiP animation is started.
         */
        public void onPipAnimationStart(TaskInfo taskInfo, PipTransitionAnimator animator) {}

        /**
         * Called when PiP animation is ended.
         */
        public void onPipAnimationEnd(TaskInfo taskInfo, SurfaceControl.Transaction tx,
                PipTransitionAnimator animator) {}

        /**
         * Called when PiP animation is cancelled.
         */
        public void onPipAnimationCancel(TaskInfo taskInfo, PipTransitionAnimator animator) {}
    }

    /**
     * A handler class that could register itself to apply the transaction instead of the
     * animation controller doing it. For example, the menu controller can be one such handler.
     */
    public static class PipTransactionHandler {

        /**
         * Called when the animation controller is about to apply a transaction. Allow a registered
         * handler to apply the transaction instead.
         *
         * @return true if handled by the handler, false otherwise.
         */
        public boolean handlePipTransaction(SurfaceControl leash, SurfaceControl.Transaction tx,
                Rect destinationBounds) {
            return false;
        }
    }

    /**
     * Animator for PiP transition animation which supports both alpha and bounds animation.
     * @param <T> Type of property to animate, either alpha (float) or bounds (Rect)
     */
    public abstract static class PipTransitionAnimator<T> extends ValueAnimator implements
            ValueAnimator.AnimatorUpdateListener,
            ValueAnimator.AnimatorListener {
        private final TaskInfo mTaskInfo;
        private final SurfaceControl mLeash;
        private final @AnimationType int mAnimationType;
        private final Rect mDestinationBounds = new Rect();

        private T mBaseValue;
        protected T mCurrentValue;
        protected T mStartValue;
        private T mEndValue;
        private float mStartingAngle;
        private PipAnimationCallback mPipAnimationCallback;
        private PipTransactionHandler mPipTransactionHandler;
        private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
                mSurfaceControlTransactionFactory;
        private PipSurfaceTransactionHelper mSurfaceTransactionHelper;
        private @TransitionDirection int mTransitionDirection;
        protected SurfaceControl mContentOverlay;

        private PipTransitionAnimator(TaskInfo taskInfo, SurfaceControl leash,
                @AnimationType int animationType, Rect destinationBounds, T baseValue, T startValue,
                T endValue, float startingAngle) {
            mTaskInfo = taskInfo;
            mLeash = leash;
            mAnimationType = animationType;
            mDestinationBounds.set(destinationBounds);
            mBaseValue = baseValue;
            mStartValue = startValue;
            mEndValue = endValue;
            mStartingAngle = startingAngle;
            addListener(this);
            addUpdateListener(this);
            mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
            mTransitionDirection = TRANSITION_DIRECTION_NONE;
        }

        @Override
        public void onAnimationStart(Animator animation) {
            mCurrentValue = mStartValue;
            onStartTransaction(mLeash, newSurfaceControlTransaction());
            if (mPipAnimationCallback != null) {
                mPipAnimationCallback.onPipAnimationStart(mTaskInfo, this);
            }
        }

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            applySurfaceControlTransaction(mLeash, newSurfaceControlTransaction(),
                    animation.getAnimatedFraction());
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            mCurrentValue = mEndValue;
            final SurfaceControl.Transaction tx = newSurfaceControlTransaction();
            onEndTransaction(mLeash, tx, mTransitionDirection);
            if (mPipAnimationCallback != null) {
                mPipAnimationCallback.onPipAnimationEnd(mTaskInfo, tx, this);
            }
            mTransitionDirection = TRANSITION_DIRECTION_NONE;
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            if (mPipAnimationCallback != null) {
                mPipAnimationCallback.onPipAnimationCancel(mTaskInfo, this);
            }
            mTransitionDirection = TRANSITION_DIRECTION_NONE;
        }

        @Override public void onAnimationRepeat(Animator animation) {}

        @VisibleForTesting
        @AnimationType public int getAnimationType() {
            return mAnimationType;
        }

        @VisibleForTesting
        public PipTransitionAnimator<T> setPipAnimationCallback(PipAnimationCallback callback) {
            mPipAnimationCallback = callback;
            return this;
        }

        PipTransitionAnimator<T> setPipTransactionHandler(PipTransactionHandler handler) {
            mPipTransactionHandler = handler;
            return this;
        }

        boolean handlePipTransaction(SurfaceControl leash, SurfaceControl.Transaction tx,
                Rect destinationBounds) {
            if (mPipTransactionHandler != null) {
                return mPipTransactionHandler.handlePipTransaction(leash, tx, destinationBounds);
            }
            return false;
        }

        SurfaceControl getContentOverlay() {
            return mContentOverlay;
        }

        PipTransitionAnimator<T> setUseContentOverlay(Context context) {
            final SurfaceControl.Transaction tx = newSurfaceControlTransaction();
            if (mContentOverlay != null) {
                // remove existing content overlay if there is any.
                tx.remove(mContentOverlay);
                tx.apply();
            }
            mContentOverlay = new SurfaceControl.Builder(new SurfaceSession())
                    .setCallsite("PipAnimation")
                    .setName("PipContentOverlay")
                    .setColorLayer()
                    .build();
            tx.show(mContentOverlay);
            tx.setLayer(mContentOverlay, Integer.MAX_VALUE);
            tx.setColor(mContentOverlay, getContentOverlayColor(context));
            tx.setAlpha(mContentOverlay, 0f);
            tx.reparent(mContentOverlay, mLeash);
            tx.apply();
            return this;
        }

        private float[] getContentOverlayColor(Context context) {
            final TypedArray ta = context.obtainStyledAttributes(new int[] {
                    android.R.attr.colorBackground });
            try {
                int colorAccent = ta.getColor(0, 0);
                return new float[] {
                        Color.red(colorAccent) / 255f,
                        Color.green(colorAccent) / 255f,
                        Color.blue(colorAccent) / 255f };
            } finally {
                ta.recycle();
            }
        }

        /**
         * Clears the {@link #mContentOverlay}, this should be done after the content overlay is
         * faded out, such as in {@link PipTaskOrganizer#fadeOutAndRemoveOverlay}
         */
        void clearContentOverlay() {
            mContentOverlay = null;
        }

        @VisibleForTesting
        @TransitionDirection public int getTransitionDirection() {
            return mTransitionDirection;
        }

        @VisibleForTesting
        public PipTransitionAnimator<T> setTransitionDirection(@TransitionDirection int direction) {
            if (direction != TRANSITION_DIRECTION_SAME) {
                mTransitionDirection = direction;
            }
            return this;
        }

        T getStartValue() {
            return mStartValue;
        }

        T getBaseValue() {
            return mBaseValue;
        }

        @VisibleForTesting
        public T getEndValue() {
            return mEndValue;
        }

        Rect getDestinationBounds() {
            return mDestinationBounds;
        }

        void setDestinationBounds(Rect destinationBounds) {
            mDestinationBounds.set(destinationBounds);
            if (mAnimationType == ANIM_TYPE_ALPHA) {
                onStartTransaction(mLeash, newSurfaceControlTransaction());
            }
        }

        void setCurrentValue(T value) {
            mCurrentValue = value;
        }

        boolean shouldApplyCornerRadius() {
            return !isOutPipDirection(mTransitionDirection);
        }

        boolean inScaleTransition() {
            if (mAnimationType != ANIM_TYPE_BOUNDS) return false;
            final int direction = getTransitionDirection();
            return !isInPipDirection(direction) && !isOutPipDirection(direction);
        }

        /**
         * Updates the {@link #mEndValue}.
         *
         * NOTE: Do not forget to call {@link #setDestinationBounds(Rect)} for bounds animation.
         * This is typically used when we receive a shelf height adjustment during the bounds
         * animation. In which case we can update the end bounds and keep the existing animation
         * running instead of cancelling it.
         */
        public void updateEndValue(T endValue) {
            mEndValue = endValue;
        }

        /**
         * @return {@link SurfaceControl.Transaction} instance with vsync-id.
         */
        protected SurfaceControl.Transaction newSurfaceControlTransaction() {
            final SurfaceControl.Transaction tx =
                    mSurfaceControlTransactionFactory.getTransaction();
            tx.setFrameTimelineVsync(Choreographer.getSfInstance().getVsyncId());
            return tx;
        }

        @VisibleForTesting
        public void setSurfaceControlTransactionFactory(
                PipSurfaceTransactionHelper.SurfaceControlTransactionFactory factory) {
            mSurfaceControlTransactionFactory = factory;
        }

        PipSurfaceTransactionHelper getSurfaceTransactionHelper() {
            return mSurfaceTransactionHelper;
        }

        void setSurfaceTransactionHelper(PipSurfaceTransactionHelper helper) {
            mSurfaceTransactionHelper = helper;
        }

        void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {}

        void onEndTransaction(SurfaceControl leash, SurfaceControl.Transaction tx,
                @TransitionDirection int transitionDirection) {}

        abstract void applySurfaceControlTransaction(SurfaceControl leash,
                SurfaceControl.Transaction tx, float fraction);

        static PipTransitionAnimator<Float> ofAlpha(TaskInfo taskInfo, SurfaceControl leash,
                Rect destinationBounds, float startValue, float endValue) {
            return new PipTransitionAnimator<Float>(taskInfo, leash, ANIM_TYPE_ALPHA,
                    destinationBounds, startValue, startValue, endValue, 0) {
                @Override
                void applySurfaceControlTransaction(SurfaceControl leash,
                        SurfaceControl.Transaction tx, float fraction) {
                    final float alpha = getStartValue() * (1 - fraction) + getEndValue() * fraction;
                    setCurrentValue(alpha);
                    getSurfaceTransactionHelper().alpha(tx, leash, alpha)
                            .round(tx, leash, shouldApplyCornerRadius());
                    tx.apply();
                }

                @Override
                void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
                    if (getTransitionDirection() == TRANSITION_DIRECTION_REMOVE_STACK) {
                        // while removing the pip stack, no extra work needs to be done here.
                        return;
                    }
                    getSurfaceTransactionHelper()
                            .resetScale(tx, leash, getDestinationBounds())
                            .crop(tx, leash, getDestinationBounds())
                            .round(tx, leash, shouldApplyCornerRadius());
                    tx.show(leash);
                    tx.apply();
                }

                @Override
                public void updateEndValue(Float endValue) {
                    super.updateEndValue(endValue);
                    mStartValue = mCurrentValue;
                }
            };
        }

        static PipTransitionAnimator<Rect> ofBounds(TaskInfo taskInfo, SurfaceControl leash,
                Rect baseValue, Rect startValue, Rect endValue, Rect sourceHintRect,
                @PipAnimationController.TransitionDirection int direction, float startingAngle,
                @Surface.Rotation int rotationDelta) {
            final boolean isOutPipDirection = isOutPipDirection(direction);

            // Just for simplicity we'll interpolate between the source rect hint insets and empty
            // insets to calculate the window crop
            final Rect initialSourceValue;
            if (isOutPipDirection) {
                initialSourceValue = new Rect(endValue);
            } else {
                initialSourceValue = new Rect(baseValue);
            }

            final Rect rotatedEndRect;
            final Rect lastEndRect;
            final Rect initialContainerRect;
            if (rotationDelta == ROTATION_90 || rotationDelta == ROTATION_270) {
                lastEndRect = new Rect(endValue);
                rotatedEndRect = new Rect(endValue);
                // Rotate the end bounds according to the rotation delta because the display will
                // be rotated to the same orientation.
                rotateBounds(rotatedEndRect, initialSourceValue, rotationDelta);
                // Use the rect that has the same orientation as the hint rect.
                initialContainerRect = isOutPipDirection ? rotatedEndRect : initialSourceValue;
            } else {
                rotatedEndRect = lastEndRect = null;
                initialContainerRect = initialSourceValue;
            }

            final Rect sourceHintRectInsets;
            if (sourceHintRect == null) {
                sourceHintRectInsets = null;
            } else {
                sourceHintRectInsets = new Rect(sourceHintRect.left - initialContainerRect.left,
                        sourceHintRect.top - initialContainerRect.top,
                        initialContainerRect.right - sourceHintRect.right,
                        initialContainerRect.bottom - sourceHintRect.bottom);
            }
            final Rect zeroInsets = new Rect(0, 0, 0, 0);

            // construct new Rect instances in case they are recycled
            return new PipTransitionAnimator<Rect>(taskInfo, leash, ANIM_TYPE_BOUNDS,
                    endValue, new Rect(baseValue), new Rect(startValue), new Rect(endValue),
                    startingAngle) {
                private final RectEvaluator mRectEvaluator = new RectEvaluator(new Rect());
                private final RectEvaluator mInsetsEvaluator = new RectEvaluator(new Rect());

                @Override
                void applySurfaceControlTransaction(SurfaceControl leash,
                        SurfaceControl.Transaction tx, float fraction) {
                    final Rect base = getBaseValue();
                    final Rect start = getStartValue();
                    final Rect end = getEndValue();
                    if (mContentOverlay != null) {
                        tx.setAlpha(mContentOverlay, fraction < 0.5f ? 0 : (fraction - 0.5f) * 2);
                    }
                    if (rotatedEndRect != null) {
                        // Animate the bounds in a different orientation. It only happens when
                        // switching between PiP and fullscreen.
                        applyRotation(tx, leash, fraction, start, end);
                        return;
                    }
                    Rect bounds = mRectEvaluator.evaluate(fraction, start, end);
                    float angle = (1.0f - fraction) * startingAngle;
                    setCurrentValue(bounds);
                    if (inScaleTransition() || sourceHintRect == null) {
                        if (isOutPipDirection) {
                            getSurfaceTransactionHelper().scale(tx, leash, end, bounds);
                        } else {
                            getSurfaceTransactionHelper().scale(tx, leash, base, bounds, angle)
                                    .round(tx, leash, base, bounds);
                        }
                    } else {
                        final Rect insets = computeInsets(fraction);
                        getSurfaceTransactionHelper().scaleAndCrop(tx, leash,
                                initialSourceValue, bounds, insets);
                        if (shouldApplyCornerRadius()) {
                            final Rect destinationBounds = new Rect(bounds);
                            destinationBounds.inset(insets);
                            getSurfaceTransactionHelper().round(tx, leash,
                                    initialContainerRect, destinationBounds);
                        }
                    }
                    if (!handlePipTransaction(leash, tx, bounds)) {
                        tx.apply();
                    }
                }

                private void applyRotation(SurfaceControl.Transaction tx, SurfaceControl leash,
                        float fraction, Rect start, Rect end) {
                    if (!end.equals(lastEndRect)) {
                        // If the end bounds are changed during animating (e.g. shelf height), the
                        // rotated end bounds also need to be updated.
                        rotatedEndRect.set(endValue);
                        rotateBounds(rotatedEndRect, initialSourceValue, rotationDelta);
                        lastEndRect.set(end);
                    }
                    final Rect bounds = mRectEvaluator.evaluate(fraction, start, rotatedEndRect);
                    setCurrentValue(bounds);
                    final Rect insets = computeInsets(fraction);
                    final float degree, x, y;
                    if (rotationDelta == ROTATION_90) {
                        degree = 90 * fraction;
                        x = fraction * (end.right - start.left) + start.left;
                        y = fraction * (end.top - start.top) + start.top;
                    } else {
                        degree = -90 * fraction;
                        x = fraction * (end.left - start.left) + start.left;
                        y = fraction * (end.bottom - start.top) + start.top;
                    }
                    getSurfaceTransactionHelper()
                            .rotateAndScaleWithCrop(tx, leash, initialContainerRect, bounds,
                                    insets, degree, x, y, isOutPipDirection,
                                    rotationDelta == ROTATION_270 /* clockwise */)
                            .round(tx, leash, initialContainerRect, bounds);
                    tx.apply();
                }

                private Rect computeInsets(float fraction) {
                    if (sourceHintRectInsets == null) {
                        return zeroInsets;
                    }
                    final Rect startRect = isOutPipDirection ? sourceHintRectInsets : zeroInsets;
                    final Rect endRect = isOutPipDirection ? zeroInsets : sourceHintRectInsets;
                    return mInsetsEvaluator.evaluate(fraction, startRect, endRect);
                }

                @Override
                void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
                    getSurfaceTransactionHelper()
                            .alpha(tx, leash, 1f)
                            .round(tx, leash, shouldApplyCornerRadius());
                    // TODO(b/178632364): this is a work around for the black background when
                    // entering PiP in buttion navigation mode.
                    if (isInPipDirection(direction)) {
                        tx.setWindowCrop(leash, getStartValue());
                    }
                    tx.show(leash);
                    tx.apply();
                }

                @Override
                void onEndTransaction(SurfaceControl leash, SurfaceControl.Transaction tx,
                        int transitionDirection) {
                    // NOTE: intentionally does not apply the transaction here.
                    // this end transaction should get executed synchronously with the final
                    // WindowContainerTransaction in task organizer
                    final Rect destBounds = getDestinationBounds();
                    getSurfaceTransactionHelper().resetScale(tx, leash, destBounds);
                    if (isOutPipDirection(transitionDirection)) {
                        // Exit pip, clear scale, position and crop.
                        tx.setMatrix(leash, 1, 0, 0, 1);
                        tx.setPosition(leash, 0, 0);
                        tx.setWindowCrop(leash, 0, 0);
                    } else {
                        getSurfaceTransactionHelper().crop(tx, leash, destBounds);
                    }
                }

                @Override
                public void updateEndValue(Rect endValue) {
                    super.updateEndValue(endValue);
                    if (mStartValue != null && mCurrentValue != null) {
                        mStartValue.set(mCurrentValue);
                    }
                }
            };
        }
    }
}
