/*
 * 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.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static android.util.RotationUtils.deltaRotation;
import static android.util.RotationUtils.rotateBounds;

import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP;
import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_TOP_OR_LEFT;
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA;
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_BOUNDS;
import static com.android.wm.shell.pip.PipAnimationController.FRACTION_START;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_NONE;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_REMOVE_STACK;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_SAME;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_SNAP_AFTER_RESIZE;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_USER_RESIZE;
import static com.android.wm.shell.pip.PipAnimationController.isInPipDirection;
import static com.android.wm.shell.pip.PipAnimationController.isOutPipDirection;
import static com.android.wm.shell.pip.PipAnimationController.isRemovePipDirection;
import static com.android.wm.shell.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP;
import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP_TO_SPLIT;
import static com.android.wm.shell.transition.Transitions.TRANSIT_REMOVE_PIP;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityTaskManager;
import android.app.PictureInPictureParams;
import android.app.TaskInfo;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.RemoteException;
import android.os.SystemClock;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceControl;
import android.window.TaskOrganizer;
import android.window.TaskSnapshot;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.animation.Interpolators;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.ScreenshotUtils;
import com.android.wm.shell.common.ShellExecutor;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.annotations.ShellMainThread;
import com.android.wm.shell.pip.phone.PipMotionHelper;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.transition.Transitions;

import java.io.PrintWriter;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.IntConsumer;

/**
 * Manages PiP tasks such as resize and offset.
 *
 * This class listens on {@link TaskOrganizer} callbacks for windowing mode change
 * both to and from PiP and issues corresponding animation if applicable.
 * Normally, we apply series of {@link SurfaceControl.Transaction} when the animator is running
 * and files a final {@link WindowContainerTransaction} at the end of the transition.
 *
 * This class is also responsible for general resize/offset PiP operations within SysUI component,
 * see also {@link PipMotionHelper}.
 */
public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        DisplayController.OnDisplaysChangedListener, ShellTaskOrganizer.FocusListener {
    private static final String TAG = PipTaskOrganizer.class.getSimpleName();
    private static final boolean DEBUG = false;
    /**
     * The alpha type is set for swiping to home. But the swiped task may not enter PiP. And if
     * another task enters PiP by non-swipe ways, e.g. call API in foreground or switch to 3-button
     * navigation, then the alpha type is unexpected.
     */
    private static final int ONE_SHOT_ALPHA_ANIMATION_TIMEOUT_MS = 1000;

    /**
     * The fixed start delay in ms when fading out the content overlay from bounds animation.
     * This is to overcome the flicker caused by configuration change when rotating from landscape
     * to portrait PiP in button navigation mode.
     */
    private static final int CONTENT_OVERLAY_FADE_OUT_DELAY_MS = 500;

    private final Context mContext;
    private final SyncTransactionQueue mSyncTransactionQueue;
    private final PipBoundsState mPipBoundsState;
    private final PipBoundsAlgorithm mPipBoundsAlgorithm;
    private final @NonNull PipMenuController mPipMenuController;
    private final PipAnimationController mPipAnimationController;
    private final PipTransitionController mPipTransitionController;
    protected final PipParamsChangedForwarder mPipParamsChangedForwarder;
    private final PipUiEventLogger mPipUiEventLoggerLogger;
    private final int mEnterAnimationDuration;
    private final int mExitAnimationDuration;
    private final int mCrossFadeAnimationDuration;
    private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
    private final Optional<SplitScreenController> mSplitScreenOptional;
    protected final ShellTaskOrganizer mTaskOrganizer;
    protected final ShellExecutor mMainExecutor;

    // These callbacks are called on the update thread
    private final PipAnimationController.PipAnimationCallback mPipAnimationCallback =
            new PipAnimationController.PipAnimationCallback() {
        @Override
        public void onPipAnimationStart(TaskInfo taskInfo,
                PipAnimationController.PipTransitionAnimator animator) {
            final int direction = animator.getTransitionDirection();
            sendOnPipTransitionStarted(direction);
        }

        @Override
        public void onPipAnimationEnd(TaskInfo taskInfo, SurfaceControl.Transaction tx,
                PipAnimationController.PipTransitionAnimator animator) {
            final int direction = animator.getTransitionDirection();
            final int animationType = animator.getAnimationType();
            final Rect destinationBounds = animator.getDestinationBounds();
            if (isInPipDirection(direction) && animator.getContentOverlayLeash() != null) {
                fadeOutAndRemoveOverlay(animator.getContentOverlayLeash(),
                        animator::clearContentOverlay, true /* withStartDelay*/);
            }
            if (mWaitForFixedRotation && animationType == ANIM_TYPE_BOUNDS
                    && direction == TRANSITION_DIRECTION_TO_PIP) {
                // Notify the display to continue the deferred orientation change.
                final WindowContainerTransaction wct = new WindowContainerTransaction();
                wct.scheduleFinishEnterPip(mToken, destinationBounds);
                mTaskOrganizer.applyTransaction(wct);
                // The final task bounds will be applied by onFixedRotationFinished so that all
                // coordinates are in new rotation.
                mSurfaceTransactionHelper.round(tx, mLeash, isInPip());
                mDeferredAnimEndTransaction = tx;
                return;
            }
            final boolean isExitPipDirection = isOutPipDirection(direction)
                    || isRemovePipDirection(direction);
            if (mPipTransitionState.getTransitionState() != PipTransitionState.EXITING_PIP
                    || isExitPipDirection) {
                // Finish resize as long as we're not exiting PIP, or, if we are, only if this is
                // the end of an exit PIP animation.
                // This is necessary in case there was a resize animation ongoing when exit PIP
                // started, in which case the first resize will be skipped to let the exit
                // operation handle the final resize out of PIP mode. See b/185306679.
                finishResize(tx, destinationBounds, direction, animationType);
                sendOnPipTransitionFinished(direction);
            }
        }

        @Override
        public void onPipAnimationCancel(TaskInfo taskInfo,
                PipAnimationController.PipTransitionAnimator animator) {
            final int direction = animator.getTransitionDirection();
            if (isInPipDirection(direction) && animator.getContentOverlayLeash() != null) {
                fadeOutAndRemoveOverlay(animator.getContentOverlayLeash(),
                        animator::clearContentOverlay, true /* withStartDelay */);
            }
            sendOnPipTransitionCancelled(direction);
        }
    };

    private final PipAnimationController.PipTransactionHandler mPipTransactionHandler =
            new PipAnimationController.PipTransactionHandler() {
                @Override
                public boolean handlePipTransaction(SurfaceControl leash,
                        SurfaceControl.Transaction tx, Rect destinationBounds) {
                    if (mPipMenuController.isMenuVisible()) {
                        mPipMenuController.movePipMenu(leash, tx, destinationBounds);
                        return true;
                    }
                    return false;
                }
            };

    private ActivityManager.RunningTaskInfo mTaskInfo;
    // To handle the edge case that onTaskInfoChanged callback is received during the entering
    // PiP transition, where we do not want to intercept the transition but still want to apply the
    // changed RunningTaskInfo when it finishes.
    private ActivityManager.RunningTaskInfo mDeferredTaskInfo;
    private WindowContainerToken mToken;
    private SurfaceControl mLeash;
    private PipTransitionState mPipTransitionState;
    private @PipAnimationController.AnimationType int mOneShotAnimationType = ANIM_TYPE_BOUNDS;
    private long mLastOneShotAlphaAnimationTime;
    private PipSurfaceTransactionHelper.SurfaceControlTransactionFactory
            mSurfaceControlTransactionFactory;
    protected PictureInPictureParams mPictureInPictureParams;
    private IntConsumer mOnDisplayIdChangeCallback;
    /**
     * The end transaction of PiP animation for switching between PiP and fullscreen with
     * orientation change. The transaction should be applied after the display is rotated.
     */
    private SurfaceControl.Transaction mDeferredAnimEndTransaction;
    /** Whether the existing PiP is hidden by alpha. */
    private boolean mHasFadeOut;

    /**
     * If set to {@code true}, the entering animation will be skipped and we will wait for
     * {@link #onFixedRotationFinished(int)} callback to actually enter PiP.
     */
    private boolean mWaitForFixedRotation;

    /**
     * The rotation that the display will apply after expanding PiP to fullscreen. This is only
     * meaningful if {@link #mWaitForFixedRotation} is true.
     */
    private @Surface.Rotation int mNextRotation;

    private @Surface.Rotation int mCurrentRotation;

    /**
     * An optional overlay used to mask content changing between an app in/out of PiP, only set if
     * {@link PipTransitionState#getInSwipePipToHomeTransition()} is true.
     */
    @Nullable
    SurfaceControl mSwipePipToHomeOverlay;

    public PipTaskOrganizer(Context context,
            @NonNull SyncTransactionQueue syncTransactionQueue,
            @NonNull PipTransitionState pipTransitionState,
            @NonNull PipBoundsState pipBoundsState,
            @NonNull PipBoundsAlgorithm boundsHandler,
            @NonNull PipMenuController pipMenuController,
            @NonNull PipAnimationController pipAnimationController,
            @NonNull PipSurfaceTransactionHelper surfaceTransactionHelper,
            @NonNull PipTransitionController pipTransitionController,
            @NonNull PipParamsChangedForwarder pipParamsChangedForwarder,
            Optional<SplitScreenController> splitScreenOptional,
            @NonNull DisplayController displayController,
            @NonNull PipUiEventLogger pipUiEventLogger,
            @NonNull ShellTaskOrganizer shellTaskOrganizer,
            @ShellMainThread ShellExecutor mainExecutor) {
        mContext = context;
        mSyncTransactionQueue = syncTransactionQueue;
        mPipTransitionState = pipTransitionState;
        mPipBoundsState = pipBoundsState;
        mPipBoundsAlgorithm = boundsHandler;
        mPipMenuController = pipMenuController;
        mPipTransitionController = pipTransitionController;
        mPipParamsChangedForwarder = pipParamsChangedForwarder;
        mEnterAnimationDuration = context.getResources()
                .getInteger(R.integer.config_pipEnterAnimationDuration);
        mExitAnimationDuration = context.getResources()
                .getInteger(R.integer.config_pipExitAnimationDuration);
        mCrossFadeAnimationDuration = context.getResources()
                .getInteger(R.integer.config_pipCrossfadeAnimationDuration);
        mSurfaceTransactionHelper = surfaceTransactionHelper;
        mPipAnimationController = pipAnimationController;
        mPipUiEventLoggerLogger = pipUiEventLogger;
        mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
        mSplitScreenOptional = splitScreenOptional;
        mTaskOrganizer = shellTaskOrganizer;
        mMainExecutor = mainExecutor;

        // TODO: Can be removed once wm components are created on the shell-main thread
        mMainExecutor.execute(() -> {
            mTaskOrganizer.addListenerForType(this, TASK_LISTENER_TYPE_PIP);
        });
        mTaskOrganizer.addFocusListener(this);
        mPipTransitionController.setPipOrganizer(this);
        displayController.addDisplayWindowListener(this);
    }

    public PipTransitionController getTransitionController() {
        return mPipTransitionController;
    }

    public Rect getCurrentOrAnimatingBounds() {
        PipAnimationController.PipTransitionAnimator animator =
                mPipAnimationController.getCurrentAnimator();
        if (animator != null && animator.isRunning()) {
            return new Rect(animator.getDestinationBounds());
        }
        return mPipBoundsState.getBounds();
    }

    public boolean isInPip() {
        return mPipTransitionState.isInPip();
    }

    private boolean isLaunchIntoPipTask() {
        return mPictureInPictureParams != null && mPictureInPictureParams.isLaunchIntoPip();
    }

    /**
     * Returns whether the entry animation is waiting to be started.
     */
    public boolean isEntryScheduled() {
        return mPipTransitionState.getTransitionState() == PipTransitionState.ENTRY_SCHEDULED;
    }

    /**
     * Registers a callback when a display change has been detected when we enter PiP.
     */
    public void registerOnDisplayIdChangeCallback(IntConsumer onDisplayIdChangeCallback) {
        mOnDisplayIdChangeCallback = onDisplayIdChangeCallback;
    }

    /**
     * Sets the preferred animation type for one time.
     * This is typically used to set the animation type to
     * {@link PipAnimationController#ANIM_TYPE_ALPHA}.
     */
    public void setOneShotAnimationType(@PipAnimationController.AnimationType int animationType) {
        mOneShotAnimationType = animationType;
        if (animationType == ANIM_TYPE_ALPHA) {
            mLastOneShotAlphaAnimationTime = SystemClock.uptimeMillis();
        }
    }

    /**
     * Callback when Launcher starts swipe-pip-to-home operation.
     * @return {@link Rect} for destination bounds.
     */
    public Rect startSwipePipToHome(ComponentName componentName, ActivityInfo activityInfo,
            PictureInPictureParams pictureInPictureParams) {
        mPipTransitionState.setInSwipePipToHomeTransition(true);
        sendOnPipTransitionStarted(TRANSITION_DIRECTION_TO_PIP);
        setBoundsStateForEntry(componentName, pictureInPictureParams, activityInfo);
        return mPipBoundsAlgorithm.getEntryDestinationBounds();
    }

    /**
     * Callback when launcher finishes swipe-pip-to-home operation.
     * Expect {@link #onTaskAppeared(ActivityManager.RunningTaskInfo, SurfaceControl)} afterwards.
     */
    public void stopSwipePipToHome(int taskId, ComponentName componentName, Rect destinationBounds,
            SurfaceControl overlay) {
        // do nothing if there is no startSwipePipToHome being called before
        if (!mPipTransitionState.getInSwipePipToHomeTransition()) {
            return;
        }
        mPipBoundsState.setBounds(destinationBounds);
        mSwipePipToHomeOverlay = overlay;
        if (ENABLE_SHELL_TRANSITIONS && overlay != null) {
            // With Shell transition, the overlay was attached to the remote transition leash, which
            // will be removed when the current transition is finished, so we need to reparent it
            // to the actual Task surface now.
            // PipTransition is responsible to fade it out and cleanup when finishing the enter PIP
            // transition.
            final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
            mTaskOrganizer.reparentChildSurfaceToTask(taskId, overlay, t);
            t.setLayer(overlay, Integer.MAX_VALUE);
            t.apply();
        }
    }

    public ActivityManager.RunningTaskInfo getTaskInfo() {
        return mTaskInfo;
    }

    public SurfaceControl getSurfaceControl() {
        return mLeash;
    }

    private void setBoundsStateForEntry(ComponentName componentName,
            PictureInPictureParams params, ActivityInfo activityInfo) {
        mPipBoundsState.setBoundsStateForEntry(componentName, activityInfo, params,
                mPipBoundsAlgorithm);
    }

    /**
     * Expands PiP to the previous bounds, this is done in two phases using
     * {@link WindowContainerTransaction}
     * - setActivityWindowingMode to either fullscreen or split-secondary at beginning of the
     *   transaction. without changing the windowing mode of the Task itself. This makes sure the
     *   activity render it's final configuration while the Task is still in PiP.
     * - setWindowingMode to undefined at the end of transition
     * @param animationDurationMs duration in millisecond for the exiting PiP transition
     * @param requestEnterSplit whether the enterSplit button is pressed on PiP or not.
     *                             Indicate the user wishes to directly put PiP into split screen
     *                             mode.
     */
    public void exitPip(int animationDurationMs, boolean requestEnterSplit) {
        if (!mPipTransitionState.isInPip()
                || mPipTransitionState.getTransitionState() == PipTransitionState.EXITING_PIP
                || mToken == null) {
            ProtoLog.wtf(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: Not allowed to exitPip in current state"
                            + " mState=%d mToken=%s", TAG, mPipTransitionState.getTransitionState(),
                    mToken);
            return;
        }

        final WindowContainerTransaction wct = new WindowContainerTransaction();
        if (isLaunchIntoPipTask()) {
            exitLaunchIntoPipTask(wct);
            return;
        }

        if (ENABLE_SHELL_TRANSITIONS) {
            if (requestEnterSplit && mSplitScreenOptional.isPresent()) {
                mSplitScreenOptional.get().prepareEnterSplitScreen(wct, mTaskInfo,
                        isPipTopLeft()
                                ? SPLIT_POSITION_TOP_OR_LEFT : SPLIT_POSITION_BOTTOM_OR_RIGHT);
                mPipTransitionController.startExitTransition(
                        TRANSIT_EXIT_PIP_TO_SPLIT, wct, null /* destinationBounds */);
                return;
            }
        }

        final Rect destinationBounds = getExitDestinationBounds();
        final int direction = syncWithSplitScreenBounds(destinationBounds, requestEnterSplit)
                ? TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN
                : TRANSITION_DIRECTION_LEAVE_PIP;

        if (Transitions.ENABLE_SHELL_TRANSITIONS && direction == TRANSITION_DIRECTION_LEAVE_PIP) {
            // When exit to fullscreen with Shell transition enabled, we update the Task windowing
            // mode directly so that it can also trigger display rotation and visibility update in
            // the same transition if there will be any.
            wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
            // We can inherit the parent bounds as it is going to be fullscreen. The
            // destinationBounds calculated above will be incorrect if this is with rotation.
            wct.setBounds(mToken, null);
        } else {
            final SurfaceControl.Transaction tx =
                    mSurfaceControlTransactionFactory.getTransaction();
            mSurfaceTransactionHelper.scale(tx, mLeash, destinationBounds,
                    mPipBoundsState.getBounds());
            tx.setWindowCrop(mLeash, destinationBounds.width(), destinationBounds.height());
            // We set to fullscreen here for now, but later it will be set to UNDEFINED for
            // the proper windowing mode to take place. See #applyWindowingModeChangeOnExit.
            wct.setActivityWindowingMode(mToken, WINDOWING_MODE_FULLSCREEN);
            wct.setBounds(mToken, destinationBounds);
            wct.setBoundsChangeTransaction(mToken, tx);
        }

        // Cancel the existing animator if there is any.
        // TODO(b/232439933): this is disabled temporarily to unblock b/234502692.
        // cancelCurrentAnimator();

        // Set the exiting state first so if there is fixed rotation later, the running animation
        // won't be interrupted by alpha animation for existing PiP.
        mPipTransitionState.setTransitionState(PipTransitionState.EXITING_PIP);

        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
            mPipTransitionController.startExitTransition(TRANSIT_EXIT_PIP, wct, destinationBounds);
            return;
        }
        mSyncTransactionQueue.queue(wct);
        mSyncTransactionQueue.runInSync(t -> {
            // Make sure to grab the latest source hint rect as it could have been
            // updated right after applying the windowing mode change.
            final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
                    mPictureInPictureParams, destinationBounds);
            final PipAnimationController.PipTransitionAnimator<?> animator =
                    animateResizePip(mPipBoundsState.getBounds(), destinationBounds, sourceHintRect,
                            direction, animationDurationMs, 0 /* startingAngle */);
            if (animator != null) {
                // Even though the animation was started above, re-apply the transaction for the
                // first frame using the SurfaceControl.Transaction supplied by the
                // SyncTransactionQueue. This is necessary because the initial surface transform
                // may not be applied until the next frame if a different Transaction than the one
                // supplied is used, resulting in 1 frame not being cropped to the source rect
                // hint during expansion that causes a visible jank/flash. See b/184166183.
                animator.applySurfaceControlTransaction(mLeash, t, FRACTION_START);
            }
        });
    }

    /** Returns the bounds to restore to when exiting PIP mode. */
    public Rect getExitDestinationBounds() {
        return mPipBoundsState.getDisplayBounds();
    }

    private void exitLaunchIntoPipTask(WindowContainerTransaction wct) {
        wct.startTask(mTaskInfo.launchIntoPipHostTaskId, null /* ActivityOptions */);
        mTaskOrganizer.applyTransaction(wct);

        // Remove the PiP with fade-out animation right after the host Task is brought to front.
        removePip();
    }

    private void applyWindowingModeChangeOnExit(WindowContainerTransaction wct, int direction) {
        // Reset the final windowing mode.
        wct.setWindowingMode(mToken, getOutPipWindowingMode());
        // Simply reset the activity mode set prior to the animation running.
        wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
    }

    /**
     * Removes PiP immediately.
     */
    public void removePip() {
        if (!mPipTransitionState.isInPip() || mToken == null) {
            ProtoLog.wtf(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: Not allowed to removePip in current state"
                            + " mState=%d mToken=%s", TAG, mPipTransitionState.getTransitionState(),
                    mToken);
            return;
        }

        // removePipImmediately is expected when the following animation finishes.
        ValueAnimator animator = mPipAnimationController
                .getAnimator(mTaskInfo, mLeash, mPipBoundsState.getBounds(),
                        1f /* alphaStart */, 0f /* alphaEnd */)
                .setTransitionDirection(TRANSITION_DIRECTION_REMOVE_STACK)
                .setPipTransactionHandler(mPipTransactionHandler)
                .setPipAnimationCallback(mPipAnimationCallback);
        animator.setDuration(mExitAnimationDuration);
        animator.setInterpolator(Interpolators.ALPHA_OUT);
        animator.start();
        mPipTransitionState.setTransitionState(PipTransitionState.EXITING_PIP);
    }

    private void removePipImmediately() {
        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
            final WindowContainerTransaction wct = new WindowContainerTransaction();
            wct.setBounds(mToken, null);
            wct.setWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
            wct.reorder(mToken, false);
            mPipTransitionController.startExitTransition(TRANSIT_REMOVE_PIP, wct,
                    null /* destinationBounds */);
            return;
        }

        try {
            // Reset the task bounds first to ensure the activity configuration is reset as well
            final WindowContainerTransaction wct = new WindowContainerTransaction();
            wct.setBounds(mToken, null);
            mTaskOrganizer.applyTransaction(wct);

            ActivityTaskManager.getService().removeRootTasksInWindowingModes(
                    new int[]{ WINDOWING_MODE_PINNED });
        } catch (RemoteException e) {
            ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: Failed to remove PiP, %s",
                    TAG, e);
        }
    }

    @Override
    public void onTaskAppeared(ActivityManager.RunningTaskInfo info, SurfaceControl leash) {
        Objects.requireNonNull(info, "Requires RunningTaskInfo");
        mTaskInfo = info;
        mToken = mTaskInfo.token;
        mPipTransitionState.setTransitionState(PipTransitionState.TASK_APPEARED);
        mLeash = leash;
        mPictureInPictureParams = mTaskInfo.pictureInPictureParams;
        setBoundsStateForEntry(mTaskInfo.topActivity, mPictureInPictureParams,
                mTaskInfo.topActivityInfo);
        if (mPictureInPictureParams != null) {
            mPipParamsChangedForwarder.notifyActionsChanged(mPictureInPictureParams.getActions(),
                    mPictureInPictureParams.getCloseAction());
            mPipParamsChangedForwarder.notifyTitleChanged(
                    mPictureInPictureParams.getTitle());
            mPipParamsChangedForwarder.notifySubtitleChanged(
                    mPictureInPictureParams.getSubtitle());
        }

        mPipUiEventLoggerLogger.setTaskInfo(mTaskInfo);
        mPipUiEventLoggerLogger.log(PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_ENTER);

        // If the displayId of the task is different than what PipBoundsHandler has, then update
        // it. This is possible if we entered PiP on an external display.
        if (info.displayId != mPipBoundsState.getDisplayId()
                && mOnDisplayIdChangeCallback != null) {
            mOnDisplayIdChangeCallback.accept(info.displayId);
        }

        if (mPipTransitionState.getInSwipePipToHomeTransition()) {
            if (!mWaitForFixedRotation) {
                onEndOfSwipePipToHomeTransition();
            } else {
                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                        "%s: Defer onTaskAppeared-SwipePipToHome until end of fixed rotation.",
                        TAG);
            }
            return;
        }

        if (mOneShotAnimationType == ANIM_TYPE_ALPHA
                && SystemClock.uptimeMillis() - mLastOneShotAlphaAnimationTime
                > ONE_SHOT_ALPHA_ANIMATION_TIMEOUT_MS) {
            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: Alpha animation is expired. Use bounds animation.", TAG);
            mOneShotAnimationType = ANIM_TYPE_BOUNDS;
        }

        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
            // For Shell transition, we will animate the window in PipTransition#startAnimation
            // instead of #onTaskAppeared.
            return;
        }

        if (mWaitForFixedRotation) {
            onTaskAppearedWithFixedRotation();
            return;
        }

        final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
        Objects.requireNonNull(destinationBounds, "Missing destination bounds");
        final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();

        if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
            mPipMenuController.attach(mLeash);
            final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
                    info.pictureInPictureParams, currentBounds);
            scheduleAnimateResizePip(currentBounds, destinationBounds, 0 /* startingAngle */,
                    sourceHintRect, TRANSITION_DIRECTION_TO_PIP, mEnterAnimationDuration,
                    null /* updateBoundsCallback */);
            mPipTransitionState.setTransitionState(PipTransitionState.ENTERING_PIP);
        } else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
            enterPipWithAlphaAnimation(destinationBounds, mEnterAnimationDuration);
            mOneShotAnimationType = ANIM_TYPE_BOUNDS;
        } else {
            throw new RuntimeException("Unrecognized animation type: " + mOneShotAnimationType);
        }
    }

    private void onTaskAppearedWithFixedRotation() {
        if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: Defer entering PiP alpha animation, fixed rotation is ongoing", TAG);
            // If deferred, hside the surface till fixed rotation is completed.
            final SurfaceControl.Transaction tx =
                    mSurfaceControlTransactionFactory.getTransaction();
            tx.setAlpha(mLeash, 0f);
            tx.show(mLeash);
            tx.apply();
            mOneShotAnimationType = ANIM_TYPE_BOUNDS;
            return;
        }
        final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
        final Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
                mPictureInPictureParams, currentBounds);
        final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
        animateResizePip(currentBounds, destinationBounds, sourceHintRect,
                TRANSITION_DIRECTION_TO_PIP, mEnterAnimationDuration, 0 /* startingAngle */);
        mPipTransitionState.setTransitionState(PipTransitionState.ENTERING_PIP);
    }

    /**
     * Called when the display rotation handling is skipped (e.g. when rotation happens while in
     * the middle of an entry transition).
     */
    public void onDisplayRotationSkipped() {
        if (isEntryScheduled()) {
            // The PIP animation is scheduled to start with the previous orientation's bounds,
            // re-calculate the entry bounds and restart the alpha animation.
            final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
            enterPipWithAlphaAnimation(destinationBounds, mEnterAnimationDuration);
        }
    }

    @VisibleForTesting
    void enterPipWithAlphaAnimation(Rect destinationBounds, long durationMs) {
        // If we are fading the PIP in, then we should move the pip to the final location as
        // soon as possible, but set the alpha immediately since the transaction can take a
        // while to process
        final SurfaceControl.Transaction tx =
                mSurfaceControlTransactionFactory.getTransaction();
        tx.setAlpha(mLeash, 0f);
        tx.apply();

        // When entering PiP this transaction will be applied within WindowContainerTransaction and
        // ensure that the PiP has rounded corners.
        final SurfaceControl.Transaction boundsChangeTx =
                mSurfaceControlTransactionFactory.getTransaction();
        mSurfaceTransactionHelper
                .crop(boundsChangeTx, mLeash, destinationBounds)
                .round(boundsChangeTx, mLeash, true /* applyCornerRadius */);

        mPipTransitionState.setTransitionState(PipTransitionState.ENTRY_SCHEDULED);
        applyEnterPipSyncTransaction(destinationBounds, () -> {
            mPipAnimationController
                    .getAnimator(mTaskInfo, mLeash, destinationBounds, 0f, 1f)
                    .setTransitionDirection(TRANSITION_DIRECTION_TO_PIP)
                    .setPipAnimationCallback(mPipAnimationCallback)
                    .setPipTransactionHandler(mPipTransactionHandler)
                    .setDuration(durationMs)
                    .start();
            // mState is set right after the animation is kicked off to block any resize
            // requests such as offsetPip that may have been called prior to the transition.
            mPipTransitionState.setTransitionState(PipTransitionState.ENTERING_PIP);
        }, boundsChangeTx);
    }

    private void onEndOfSwipePipToHomeTransition() {
        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
            return;
        }

        final Rect destinationBounds = mPipBoundsState.getBounds();
        final SurfaceControl swipeToHomeOverlay = mSwipePipToHomeOverlay;
        final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
        mSurfaceTransactionHelper
                .resetScale(tx, mLeash, destinationBounds)
                .crop(tx, mLeash, destinationBounds)
                .round(tx, mLeash, isInPip());
        // The animation is finished in the Launcher and here we directly apply the final touch.
        applyEnterPipSyncTransaction(destinationBounds, () -> {
            // Ensure menu's settled in its final bounds first.
            finishResizeForMenu(destinationBounds);
            sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);

            // Remove the swipe to home overlay
            if (swipeToHomeOverlay != null) {
                fadeOutAndRemoveOverlay(swipeToHomeOverlay,
                        null /* callback */, false /* withStartDelay */);
            }
        }, tx);
        mPipTransitionState.setInSwipePipToHomeTransition(false);
        mSwipePipToHomeOverlay = null;
    }

    private void applyEnterPipSyncTransaction(Rect destinationBounds, Runnable runnable,
            @Nullable SurfaceControl.Transaction boundsChangeTransaction) {
        // PiP menu is attached late in the process here to avoid any artifacts on the leash
        // caused by addShellRoot when in gesture navigation mode.
        mPipMenuController.attach(mLeash);
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
        wct.setBounds(mToken, destinationBounds);
        if (boundsChangeTransaction != null) {
            wct.setBoundsChangeTransaction(mToken, boundsChangeTransaction);
        }
        mSyncTransactionQueue.queue(wct);
        if (runnable != null) {
            mSyncTransactionQueue.runInSync(t -> runnable.run());
        }
    }

    private void sendOnPipTransitionStarted(
            @PipAnimationController.TransitionDirection int direction) {
        if (direction == TRANSITION_DIRECTION_TO_PIP) {
            mPipTransitionState.setTransitionState(PipTransitionState.ENTERING_PIP);
        }
        mPipTransitionController.sendOnPipTransitionStarted(direction);
    }

    @VisibleForTesting
    void sendOnPipTransitionFinished(
            @PipAnimationController.TransitionDirection int direction) {
        if (direction == TRANSITION_DIRECTION_TO_PIP) {
            mPipTransitionState.setTransitionState(PipTransitionState.ENTERED_PIP);
        }
        mPipTransitionController.sendOnPipTransitionFinished(direction);
        // Apply the deferred RunningTaskInfo if applicable after all proper callbacks are sent.
        if (direction == TRANSITION_DIRECTION_TO_PIP && mDeferredTaskInfo != null) {
            onTaskInfoChanged(mDeferredTaskInfo);
            mDeferredTaskInfo = null;
        }
    }

    private void sendOnPipTransitionCancelled(
            @PipAnimationController.TransitionDirection int direction) {
        mPipTransitionController.sendOnPipTransitionCancelled(direction);
    }

    /**
     * Note that dismissing PiP is now originated from SystemUI, see {@link #exitPip(int, boolean)}.
     * Meanwhile this callback is invoked whenever the task is removed. For instance:
     *   - as a result of removeRootTasksInWindowingModes from WM
     *   - activity itself is died
     * Nevertheless, we simply update the internal state here as all the heavy lifting should
     * have been done in WM.
     */
    @Override
    public void onTaskVanished(ActivityManager.RunningTaskInfo info) {
        if (mPipTransitionState.getTransitionState() == PipTransitionState.UNDEFINED) {
            return;
        }
        if (Transitions.ENABLE_SHELL_TRANSITIONS
                && mPipTransitionState.getTransitionState() == PipTransitionState.EXITING_PIP) {
            // With Shell transition, we do the cleanup in PipTransition after exiting PIP.
            return;
        }
        final WindowContainerToken token = info.token;
        Objects.requireNonNull(token, "Requires valid WindowContainerToken");
        if (token.asBinder() != mToken.asBinder()) {
            ProtoLog.wtf(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: Unrecognized token: %s", TAG, token);
            return;
        }

        cancelCurrentAnimator();
        onExitPipFinished(info);

        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
            mPipTransitionController.forceFinishTransition();
        }
    }

    @Override
    public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
        Objects.requireNonNull(mToken, "onTaskInfoChanged requires valid existing mToken");
        if (mPipTransitionState.getTransitionState() != PipTransitionState.ENTERED_PIP
                && mPipTransitionState.getTransitionState() != PipTransitionState.EXITING_PIP) {
            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: Defer onTaskInfoChange in current state: %d", TAG,
                    mPipTransitionState.getTransitionState());
            // Defer applying PiP parameters if the task is entering PiP to avoid disturbing
            // the animation.
            mDeferredTaskInfo = info;
            return;
        }
        mPipBoundsState.setLastPipComponentName(info.topActivity);
        mPipBoundsState.setOverrideMinSize(
                mPipBoundsAlgorithm.getMinimalSize(info.topActivityInfo));
        final PictureInPictureParams newParams = info.pictureInPictureParams;

        // mPictureInPictureParams is only null if there is no PiP
        if (newParams == null || mPictureInPictureParams == null) {
            return;
        }
        applyNewPictureInPictureParams(newParams);
        mPictureInPictureParams = newParams;
    }

    @Override
    public void onFocusTaskChanged(ActivityManager.RunningTaskInfo taskInfo) {
        mPipMenuController.onFocusTaskChanged(taskInfo);
    }

    @Override
    public boolean supportCompatUI() {
        // PIP doesn't support compat.
        return false;
    }

    @Override
    public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
        b.setParent(findTaskSurface(taskId));
    }

    @Override
    public void reparentChildSurfaceToTask(int taskId, SurfaceControl sc,
            SurfaceControl.Transaction t) {
        t.reparent(sc, findTaskSurface(taskId));
    }

    private SurfaceControl findTaskSurface(int taskId) {
        if (mTaskInfo == null || mLeash == null || mTaskInfo.taskId != taskId) {
            throw new IllegalArgumentException("There is no surface for taskId=" + taskId);
        }
        return mLeash;
    }

    @Override
    public void onFixedRotationStarted(int displayId, int newRotation) {
        mNextRotation = newRotation;
        mWaitForFixedRotation = true;

        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
            // The fixed rotation will also be included in the transition info. However, if it is
            // not a PIP transition (such as open another app to different orientation),
            // PIP transition handler may not be aware of the fixed rotation start.
            // Notify the PIP transition handler so that it can fade out the PIP window early for
            // fixed transition of other windows.
            mPipTransitionController.onFixedRotationStarted();
            return;
        }

        if (mPipTransitionState.isInPip()) {
            // Fade out the existing PiP to avoid jump cut during seamless rotation.
            fadeExistingPip(false /* show */);
        }
    }

    @Override
    public void onFixedRotationFinished(int displayId) {
        if (!mWaitForFixedRotation) {
            return;
        }
        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
            clearWaitForFixedRotation();
            return;
        }
        if (mPipTransitionState.getTransitionState() == PipTransitionState.TASK_APPEARED) {
            if (mPipTransitionState.getInSwipePipToHomeTransition()) {
                onEndOfSwipePipToHomeTransition();
            } else {
                // Schedule a regular animation to ensure all the callbacks are still being sent.
                enterPipWithAlphaAnimation(mPipBoundsAlgorithm.getEntryDestinationBounds(),
                        mEnterAnimationDuration);
            }
        } else if (mPipTransitionState.getTransitionState() == PipTransitionState.ENTERED_PIP
                && mHasFadeOut) {
            fadeExistingPip(true /* show */);
        } else if (mPipTransitionState.getTransitionState() == PipTransitionState.ENTERING_PIP
                && mDeferredAnimEndTransaction != null) {
            final PipAnimationController.PipTransitionAnimator<?> animator =
                    mPipAnimationController.getCurrentAnimator();
            final Rect destinationBounds = animator.getDestinationBounds();
            mPipBoundsState.setBounds(destinationBounds);
            applyEnterPipSyncTransaction(destinationBounds, () -> {
                finishResizeForMenu(destinationBounds);
                sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
            }, mDeferredAnimEndTransaction);
        }
        clearWaitForFixedRotation();
    }

    /** Called when exiting PIP transition is finished to do the state cleanup. */
    void onExitPipFinished(TaskInfo info) {
        clearWaitForFixedRotation();
        if (mSwipePipToHomeOverlay != null) {
            removeContentOverlay(mSwipePipToHomeOverlay, null /* callback */);
            mSwipePipToHomeOverlay = null;
        }
        resetShadowRadius();
        mPipTransitionState.setInSwipePipToHomeTransition(false);
        mPictureInPictureParams = null;
        mPipTransitionState.setTransitionState(PipTransitionState.UNDEFINED);
        // Re-set the PIP bounds to none.
        mPipBoundsState.setBounds(new Rect());
        mPipUiEventLoggerLogger.setTaskInfo(null);
        mMainExecutor.executeDelayed(() -> mPipMenuController.detach(), 0);
        mLeash = null;

        if (info.displayId != Display.DEFAULT_DISPLAY && mOnDisplayIdChangeCallback != null) {
            mOnDisplayIdChangeCallback.accept(Display.DEFAULT_DISPLAY);
        }
    }

    private void fadeExistingPip(boolean show) {
        if (mLeash == null || !mLeash.isValid()) {
            ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: Invalid leash on fadeExistingPip: %s", TAG, mLeash);
            return;
        }
        final float alphaStart = show ? 0 : 1;
        final float alphaEnd = show ? 1 : 0;
        mPipAnimationController
                .getAnimator(mTaskInfo, mLeash, mPipBoundsState.getBounds(), alphaStart, alphaEnd)
                .setTransitionDirection(TRANSITION_DIRECTION_SAME)
                .setPipTransactionHandler(mPipTransactionHandler)
                .setDuration(show ? mEnterAnimationDuration : mExitAnimationDuration)
                .start();
        mHasFadeOut = !show;
    }

    private void clearWaitForFixedRotation() {
        mWaitForFixedRotation = false;
        mDeferredAnimEndTransaction = null;
    }

    /** Explicitly set the visibility of PiP window. */
    public void setPipVisibility(boolean visible) {
        if (!isInPip()) {
            return;
        }
        if (mLeash == null || !mLeash.isValid()) {
            ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: Invalid leash on setPipVisibility: %s", TAG, mLeash);
            return;
        }
        final SurfaceControl.Transaction tx =
                mSurfaceControlTransactionFactory.getTransaction();
        mSurfaceTransactionHelper.alpha(tx, mLeash, visible ? 1f : 0f);
        tx.apply();
    }

    @Override
    public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
        mCurrentRotation = newConfig.windowConfiguration.getRotation();
    }

    /**
     * Called when display size or font size of settings changed
     */
    public void onDensityOrFontScaleChanged(Context context) {
        mSurfaceTransactionHelper.onDensityOrFontScaleChanged(context);
    }

    /**
     * TODO(b/152809058): consolidate the display info handling logic in SysUI
     *
     * @param destinationBoundsOut the current destination bounds will be populated to this param
     */
    @SuppressWarnings("unchecked")
    public void onMovementBoundsChanged(Rect destinationBoundsOut, boolean fromRotation,
            boolean fromImeAdjustment, boolean fromShelfAdjustment,
            WindowContainerTransaction wct) {
        // note that this can be called when swipe-to-home or fixed-rotation is happening.
        // Skip this entirely if that's the case.
        final boolean waitForFixedRotationOnEnteringPip = mWaitForFixedRotation
                && (mPipTransitionState.getTransitionState() != PipTransitionState.ENTERED_PIP);
        if ((mPipTransitionState.getInSwipePipToHomeTransition()
                || waitForFixedRotationOnEnteringPip) && fromRotation) {
            if (DEBUG) {
                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                        "%s: Skip onMovementBoundsChanged on rotation change"
                                + " InSwipePipToHomeTransition=%b"
                                + " mWaitForFixedRotation=%b"
                                + " getTransitionState=%d", TAG,
                        mPipTransitionState.getInSwipePipToHomeTransition(), mWaitForFixedRotation,
                        mPipTransitionState.getTransitionState());
            }
            return;
        }
        final PipAnimationController.PipTransitionAnimator animator =
                mPipAnimationController.getCurrentAnimator();
        if (animator == null || !animator.isRunning()
                || animator.getTransitionDirection() != TRANSITION_DIRECTION_TO_PIP) {
            final boolean rotatingPip = mPipTransitionState.isInPip() && fromRotation;
            if (rotatingPip && Transitions.ENABLE_SHELL_TRANSITIONS) {
                // The animation and surface update will be handled by the shell transition handler.
                mPipBoundsState.setBounds(destinationBoundsOut);
            } else if (rotatingPip && mWaitForFixedRotation && mHasFadeOut) {
                // The position will be used by fade-in animation when the fixed rotation is done.
                mPipBoundsState.setBounds(destinationBoundsOut);
            } else if (rotatingPip) {
                // Update bounds state to final destination first. It's important to do this
                // before finishing & cancelling the transition animation so that the MotionHelper
                // bounds are synchronized to the destination bounds when the animation ends.
                mPipBoundsState.setBounds(destinationBoundsOut);
                // If we are rotating while there is a current animation, immediately cancel the
                // animation (remove the listeners so we don't trigger the normal finish resize
                // call that should only happen on the update thread)
                int direction = TRANSITION_DIRECTION_NONE;
                if (animator != null) {
                    direction = animator.getTransitionDirection();
                    PipAnimationController.quietCancel(animator);
                    // Do notify the listeners that this was canceled
                    sendOnPipTransitionCancelled(direction);
                    sendOnPipTransitionFinished(direction);
                }

                // Create a reset surface transaction for the new bounds and update the window
                // container transaction
                final SurfaceControl.Transaction tx = createFinishResizeSurfaceTransaction(
                        destinationBoundsOut);
                prepareFinishResizeTransaction(destinationBoundsOut, direction, tx, wct);
            } else  {
                // There could be an animation on-going. If there is one on-going, last-reported
                // bounds isn't yet updated. We'll use the animator's bounds instead.
                if (animator != null && animator.isRunning()) {
                    if (!animator.getDestinationBounds().isEmpty()) {
                        destinationBoundsOut.set(animator.getDestinationBounds());
                    }
                } else {
                    if (!mPipBoundsState.getBounds().isEmpty()) {
                        destinationBoundsOut.set(mPipBoundsState.getBounds());
                    }
                }
            }
            return;
        }

        final Rect currentDestinationBounds = animator.getDestinationBounds();
        destinationBoundsOut.set(currentDestinationBounds);
        if (!fromImeAdjustment && !fromShelfAdjustment
                && mPipBoundsState.getDisplayBounds().contains(currentDestinationBounds)) {
            // no need to update the destination bounds, bail early
            return;
        }

        final Rect newDestinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
        if (newDestinationBounds.equals(currentDestinationBounds)) return;
        if (animator.getAnimationType() == ANIM_TYPE_BOUNDS) {
            if (mWaitForFixedRotation) {
                // The new destination bounds are in next rotation (DisplayLayout has been rotated
                // in computeRotatedBounds). The animation runs in previous rotation so the end
                // bounds need to be transformed.
                final Rect displayBounds = mPipBoundsState.getDisplayBounds();
                final Rect rotatedEndBounds = new Rect(newDestinationBounds);
                rotateBounds(rotatedEndBounds, displayBounds, mNextRotation, mCurrentRotation);
                animator.updateEndValue(rotatedEndBounds);
            } else {
                animator.updateEndValue(newDestinationBounds);
            }
        }
        animator.setDestinationBounds(newDestinationBounds);
        destinationBoundsOut.set(newDestinationBounds);
    }

    /**
     * Handles all changes to the PictureInPictureParams.
     */
    protected void applyNewPictureInPictureParams(@NonNull PictureInPictureParams params) {
        if (mDeferredTaskInfo != null || PipUtils.aspectRatioChanged(params.getAspectRatioFloat(),
                mPictureInPictureParams.getAspectRatioFloat())) {
            mPipParamsChangedForwarder.notifyAspectRatioChanged(params.getAspectRatioFloat());
        }
        if (mDeferredTaskInfo != null
                || PipUtils.remoteActionsChanged(params.getActions(),
                mPictureInPictureParams.getActions())
                || !PipUtils.remoteActionsMatch(params.getCloseAction(),
                mPictureInPictureParams.getCloseAction())) {
            mPipParamsChangedForwarder.notifyActionsChanged(params.getActions(),
                    params.getCloseAction());
        }
    }

    /**
     * Animates resizing of the pinned stack given the duration.
     */
    public void scheduleAnimateResizePip(Rect toBounds, int duration,
            Consumer<Rect> updateBoundsCallback) {
        scheduleAnimateResizePip(toBounds, duration, TRANSITION_DIRECTION_NONE,
                updateBoundsCallback);
    }

    /**
     * Animates resizing of the pinned stack given the duration.
     */
    public void scheduleAnimateResizePip(Rect toBounds, int duration,
            @PipAnimationController.TransitionDirection int direction,
            Consumer<Rect> updateBoundsCallback) {
        if (mWaitForFixedRotation) {
            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: skip scheduleAnimateResizePip, entering pip deferred", TAG);
            return;
        }
        scheduleAnimateResizePip(mPipBoundsState.getBounds(), toBounds, 0 /* startingAngle */,
                null /* sourceHintRect */, direction, duration, updateBoundsCallback);
    }

    /**
     * Animates resizing of the pinned stack given the duration and start bounds.
     * This is used when the starting bounds is not the current PiP bounds.
     */
    public void scheduleAnimateResizePip(Rect fromBounds, Rect toBounds, int duration,
            float startingAngle, Consumer<Rect> updateBoundsCallback) {
        if (mWaitForFixedRotation) {
            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: skip scheduleAnimateResizePip, entering pip deferred", TAG);
            return;
        }
        scheduleAnimateResizePip(fromBounds, toBounds, startingAngle, null /* sourceHintRect */,
                TRANSITION_DIRECTION_SNAP_AFTER_RESIZE, duration, updateBoundsCallback);
    }

    /**
     * Animates resizing of the pinned stack given the duration and start bounds.
     * This always animates the angle to zero from the starting angle.
     */
    private @Nullable PipAnimationController.PipTransitionAnimator<?> scheduleAnimateResizePip(
            Rect currentBounds, Rect destinationBounds, float startingAngle, Rect sourceHintRect,
            @PipAnimationController.TransitionDirection int direction, int durationMs,
            Consumer<Rect> updateBoundsCallback) {
        if (!mPipTransitionState.isInPip()) {
            // TODO: tend to use shouldBlockResizeRequest here as well but need to consider
            // the fact that when in exitPip, scheduleAnimateResizePip is executed in the window
            // container transaction callback and we want to set the mState immediately.
            return null;
        }

        final PipAnimationController.PipTransitionAnimator<?> animator = animateResizePip(
                currentBounds, destinationBounds, sourceHintRect, direction, durationMs,
                startingAngle);
        if (updateBoundsCallback != null) {
            updateBoundsCallback.accept(destinationBounds);
        }
        return animator;
    }

    /**
     * Directly perform manipulation/resize on the leash. This will not perform any
     * {@link WindowContainerTransaction} until {@link #scheduleFinishResizePip} is called.
     */
    public void scheduleResizePip(Rect toBounds, Consumer<Rect> updateBoundsCallback) {
        // Could happen when exitPip
        if (mToken == null || mLeash == null) {
            ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: Abort animation, invalid leash", TAG);
            return;
        }
        mPipBoundsState.setBounds(toBounds);
        final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
        mSurfaceTransactionHelper
                .crop(tx, mLeash, toBounds)
                .round(tx, mLeash, mPipTransitionState.isInPip());
        if (mPipMenuController.isMenuVisible()) {
            mPipMenuController.resizePipMenu(mLeash, tx, toBounds);
        } else {
            tx.apply();
        }
        if (updateBoundsCallback != null) {
            updateBoundsCallback.accept(toBounds);
        }
    }

    /**
     * Directly perform manipulation/resize on the leash, along with rotation. This will not perform
     * any {@link WindowContainerTransaction} until {@link #scheduleFinishResizePip} is called.
     */
    public void scheduleUserResizePip(Rect startBounds, Rect toBounds,
            Consumer<Rect> updateBoundsCallback) {
        scheduleUserResizePip(startBounds, toBounds, 0 /* degrees */, updateBoundsCallback);
    }

    /**
     * Directly perform a scaled matrix transformation on the leash. This will not perform any
     * {@link WindowContainerTransaction} until {@link #scheduleFinishResizePip} is called.
     */
    public void scheduleUserResizePip(Rect startBounds, Rect toBounds, float degrees,
            Consumer<Rect> updateBoundsCallback) {
        // Could happen when exitPip
        if (mToken == null || mLeash == null) {
            ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: Abort animation, invalid leash", TAG);
            return;
        }

        if (startBounds.isEmpty() || toBounds.isEmpty()) {
            ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: Attempted to user resize PIP to or from empty bounds, aborting.", TAG);
            return;
        }

        final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
        mSurfaceTransactionHelper
                .scale(tx, mLeash, startBounds, toBounds, degrees)
                .round(tx, mLeash, startBounds, toBounds);
        if (mPipMenuController.isMenuVisible()) {
            mPipMenuController.movePipMenu(mLeash, tx, toBounds);
        } else {
            tx.apply();
        }
        if (updateBoundsCallback != null) {
            updateBoundsCallback.accept(toBounds);
        }
    }

    /**
     * Finish an intermediate resize operation. This is expected to be called after
     * {@link #scheduleResizePip}.
     */
    public void scheduleFinishResizePip(Rect destinationBounds) {
        scheduleFinishResizePip(destinationBounds, null /* updateBoundsCallback */);
    }

    /**
     * Same as {@link #scheduleFinishResizePip} but with a callback.
     */
    public void scheduleFinishResizePip(Rect destinationBounds,
            Consumer<Rect> updateBoundsCallback) {
        scheduleFinishResizePip(destinationBounds, TRANSITION_DIRECTION_NONE, updateBoundsCallback);
    }

    /**
     * Finish an intermediate resize operation. This is expected to be called after
     * {@link #scheduleResizePip}.
     *
     * @param destinationBounds the final bounds of the PIP after resizing
     * @param direction the transition direction
     * @param updateBoundsCallback a callback to invoke after finishing the resize
     */
    public void scheduleFinishResizePip(Rect destinationBounds,
            @PipAnimationController.TransitionDirection int direction,
            Consumer<Rect> updateBoundsCallback) {
        if (mPipTransitionState.shouldBlockResizeRequest()) {
            return;
        }

        finishResize(createFinishResizeSurfaceTransaction(destinationBounds), destinationBounds,
                direction, -1);
        if (updateBoundsCallback != null) {
            updateBoundsCallback.accept(destinationBounds);
        }
    }

    private SurfaceControl.Transaction createFinishResizeSurfaceTransaction(
            Rect destinationBounds) {
        final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
        mSurfaceTransactionHelper
                .crop(tx, mLeash, destinationBounds)
                .resetScale(tx, mLeash, destinationBounds)
                .round(tx, mLeash, mPipTransitionState.isInPip());
        return tx;
    }

    /**
     * Offset the PiP window by a given offset on Y-axis, triggered also from screen rotation.
     */
    public void scheduleOffsetPip(Rect originalBounds, int offset, int duration,
            Consumer<Rect> updateBoundsCallback) {
        if (mPipTransitionState.shouldBlockResizeRequest()
                || mPipTransitionState.getInSwipePipToHomeTransition()) {
            return;
        }
        if (mWaitForFixedRotation) {
            ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: skip scheduleOffsetPip, entering pip deferred", TAG);
            return;
        }
        offsetPip(originalBounds, 0 /* xOffset */, offset, duration);
        Rect toBounds = new Rect(originalBounds);
        toBounds.offset(0, offset);
        if (updateBoundsCallback != null) {
            updateBoundsCallback.accept(toBounds);
        }
    }

    private void offsetPip(Rect originalBounds, int xOffset, int yOffset, int durationMs) {
        if (mTaskInfo == null) {
            ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, "%s: mTaskInfo is not set",
                    TAG);
            return;
        }
        final Rect destinationBounds = new Rect(originalBounds);
        destinationBounds.offset(xOffset, yOffset);
        animateResizePip(originalBounds, destinationBounds, null /* sourceHintRect */,
                TRANSITION_DIRECTION_SAME, durationMs, 0);
    }

    private void finishResize(SurfaceControl.Transaction tx, Rect destinationBounds,
            @PipAnimationController.TransitionDirection int direction,
            @PipAnimationController.AnimationType int type) {
        final Rect preResizeBounds = new Rect(mPipBoundsState.getBounds());
        final boolean isPipTopLeft = isPipTopLeft();
        mPipBoundsState.setBounds(destinationBounds);
        if (direction == TRANSITION_DIRECTION_REMOVE_STACK) {
            removePipImmediately();
            return;
        } else if (isInPipDirection(direction) && type == ANIM_TYPE_ALPHA) {
            // TODO: Synchronize this correctly in #applyEnterPipSyncTransaction
            finishResizeForMenu(destinationBounds);
            return;
        }

        WindowContainerTransaction wct = new WindowContainerTransaction();
        prepareFinishResizeTransaction(destinationBounds, direction, tx, wct);

        // Only corner drag, pinch or expand/un-expand resizing may lead to animating the finish
        // resize operation.
        final boolean mayAnimateFinishResize = direction == TRANSITION_DIRECTION_USER_RESIZE
                || direction == TRANSITION_DIRECTION_SNAP_AFTER_RESIZE
                || direction == TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND;
        // Animate with a cross-fade if enabled and seamless resize is disables by the app.
        final boolean animateCrossFadeResize = mayAnimateFinishResize
                && mPictureInPictureParams != null
                && !mPictureInPictureParams.isSeamlessResizeEnabled();
        if (animateCrossFadeResize) {
            // Take a snapshot of the PIP task and show it. We'll fade it out after the wct
            // transaction is applied and the activity is laid out again.
            preResizeBounds.offsetTo(0, 0);
            final Rect snapshotDest = new Rect(0, 0, destinationBounds.width(),
                    destinationBounds.height());
            // Note: Put this at layer=MAX_VALUE-2 since the input consumer for PIP is placed at
            //       MAX_VALUE-1
            final SurfaceControl snapshotSurface = ScreenshotUtils.takeScreenshot(
                    mSurfaceControlTransactionFactory.getTransaction(), mLeash, preResizeBounds,
                    Integer.MAX_VALUE - 2);
            if (snapshotSurface != null) {
                mSyncTransactionQueue.queue(wct);
                mSyncTransactionQueue.runInSync(t -> {
                    // Scale the snapshot from its pre-resize bounds to the post-resize bounds.
                    mSurfaceTransactionHelper.scale(t, snapshotSurface, preResizeBounds,
                            snapshotDest);

                    // Start animation to fade out the snapshot.
                    fadeOutAndRemoveOverlay(snapshotSurface,
                            null /* callback */, false /* withStartDelay */);
                });
            } else {
                applyFinishBoundsResize(wct, direction, isPipTopLeft);
            }
        } else {
            applyFinishBoundsResize(wct, direction, isPipTopLeft);
        }

        finishResizeForMenu(destinationBounds);
    }

    /** Moves the PiP menu to the destination bounds. */
    public void finishResizeForMenu(Rect destinationBounds) {
        if (!isInPip()) {
            return;
        }
        mPipMenuController.movePipMenu(null, null, destinationBounds);
        mPipMenuController.updateMenuBounds(destinationBounds);
    }

    private void prepareFinishResizeTransaction(Rect destinationBounds,
            @PipAnimationController.TransitionDirection int direction,
            SurfaceControl.Transaction tx,
            WindowContainerTransaction wct) {
        final Rect taskBounds;
        if (isInPipDirection(direction)) {
            // If we are animating from fullscreen using a bounds animation, then reset the
            // activity windowing mode set by WM, and set the task bounds to the final bounds
            taskBounds = destinationBounds;
            wct.setActivityWindowingMode(mToken, WINDOWING_MODE_UNDEFINED);
        } else if (isOutPipDirection(direction)) {
            // If we are animating to fullscreen or split screen, then we need to reset the
            // override bounds on the task to ensure that the task "matches" the parent's bounds.
            taskBounds = null;
            applyWindowingModeChangeOnExit(wct, direction);
        } else {
            // Just a resize in PIP
            taskBounds = destinationBounds;
        }
        mSurfaceTransactionHelper.round(tx, mLeash, isInPip());

        wct.setBounds(mToken, taskBounds);
        wct.setBoundsChangeTransaction(mToken, tx);
    }

    /**
     * Applies the window container transaction to finish a bounds resize.
     *
     * Called by {@link #finishResize(SurfaceControl.Transaction, Rect, int, int)}} once it has
     * finished preparing the transaction. It allows subclasses to modify the transaction before
     * applying it.
     */
    public void applyFinishBoundsResize(@NonNull WindowContainerTransaction wct,
            @PipAnimationController.TransitionDirection int direction, boolean wasPipTopLeft) {
        if (direction == TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN) {
            mSplitScreenOptional.ifPresent(splitScreenController ->
                    splitScreenController.enterSplitScreen(mTaskInfo.taskId, wasPipTopLeft, wct));
        } else {
            mTaskOrganizer.applyTransaction(wct);
        }
    }

    private boolean isPipTopLeft() {
        if (!mSplitScreenOptional.isPresent()) {
            return false;
        }
        final Rect topLeft = new Rect();
        final Rect bottomRight = new Rect();
        mSplitScreenOptional.get().getStageBounds(topLeft, bottomRight);

        return topLeft.contains(mPipBoundsState.getBounds());
    }

    /**
     * The windowing mode to restore to when resizing out of PIP direction. Defaults to undefined
     * and can be overridden to restore to an alternate windowing mode.
     */
    public int getOutPipWindowingMode() {
        // By default, simply reset the windowing mode to undefined.
        return WINDOWING_MODE_UNDEFINED;
    }

    private @Nullable PipAnimationController.PipTransitionAnimator<?> animateResizePip(
            Rect currentBounds, Rect destinationBounds, Rect sourceHintRect,
            @PipAnimationController.TransitionDirection int direction, int durationMs,
            float startingAngle) {
        // Could happen when exitPip
        if (mToken == null || mLeash == null) {
            ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: Abort animation, invalid leash", TAG);
            return null;
        }
        if (isInPipDirection(direction)
                && !isSourceRectHintValidForEnterPip(sourceHintRect, destinationBounds)) {
            // The given source rect hint is too small for enter PiP animation, reset it to null.
            sourceHintRect = null;
        }
        final int rotationDelta = mWaitForFixedRotation
                ? deltaRotation(mCurrentRotation, mNextRotation)
                : Surface.ROTATION_0;
        if (rotationDelta != Surface.ROTATION_0) {
            sourceHintRect = computeRotatedBounds(rotationDelta, direction, destinationBounds,
                    sourceHintRect);
        }
        Rect baseBounds = direction == TRANSITION_DIRECTION_SNAP_AFTER_RESIZE
                ? mPipBoundsState.getBounds() : currentBounds;
        final boolean existingAnimatorRunning = mPipAnimationController.getCurrentAnimator() != null
                && mPipAnimationController.getCurrentAnimator().isRunning();
        final PipAnimationController.PipTransitionAnimator<?> animator = mPipAnimationController
                .getAnimator(mTaskInfo, mLeash, baseBounds, currentBounds, destinationBounds,
                        sourceHintRect, direction, startingAngle, rotationDelta);
        animator.setTransitionDirection(direction)
                .setPipTransactionHandler(mPipTransactionHandler)
                .setDuration(durationMs);
        if (!existingAnimatorRunning) {
            animator.setPipAnimationCallback(mPipAnimationCallback);
        }
        if (isInPipDirection(direction)) {
            // Similar to auto-enter-pip transition, we use content overlay when there is no
            // source rect hint to enter PiP use bounds animation.
            if (sourceHintRect == null) {
                animator.setColorContentOverlay(mContext);
            } else {
                final TaskSnapshot snapshot = PipUtils.getTaskSnapshot(
                        mTaskInfo.launchIntoPipHostTaskId, false /* isLowResolution */);
                if (snapshot != null) {
                    // use the task snapshot during the animation, this is for
                    // launch-into-pip aka. content-pip use case.
                    animator.setSnapshotContentOverlay(snapshot, sourceHintRect);
                }
            }
            // The destination bounds are used for the end rect of animation and the final bounds
            // after animation finishes. So after the animation is started, the destination bounds
            // can be updated to new rotation (computeRotatedBounds has changed the DisplayLayout
            // without affecting the animation.
            if (rotationDelta != Surface.ROTATION_0) {
                animator.setDestinationBounds(mPipBoundsAlgorithm.getEntryDestinationBounds());
            }
        }
        animator.start();
        return animator;
    }

    /** Computes destination bounds in old rotation and returns source hint rect if available. */
    private @Nullable Rect computeRotatedBounds(int rotationDelta, int direction,
            Rect outDestinationBounds, Rect sourceHintRect) {
        if (direction == TRANSITION_DIRECTION_TO_PIP) {
            mPipBoundsState.getDisplayLayout().rotateTo(mContext.getResources(), mNextRotation);
            final Rect displayBounds = mPipBoundsState.getDisplayBounds();
            outDestinationBounds.set(mPipBoundsAlgorithm.getEntryDestinationBounds());
            // Transform the destination bounds to current display coordinates.
            rotateBounds(outDestinationBounds, displayBounds, mNextRotation, mCurrentRotation);
            // When entering PiP (from button navigation mode), adjust the source rect hint by
            // display cutout if applicable.
            if (sourceHintRect != null && mTaskInfo.displayCutoutInsets != null) {
                if (rotationDelta == Surface.ROTATION_270) {
                    sourceHintRect.offset(mTaskInfo.displayCutoutInsets.left,
                            mTaskInfo.displayCutoutInsets.top);
                }
            }
        } else if (direction == TRANSITION_DIRECTION_LEAVE_PIP) {
            final Rect rotatedDestinationBounds = new Rect(outDestinationBounds);
            rotateBounds(rotatedDestinationBounds, mPipBoundsState.getDisplayBounds(),
                    rotationDelta);
            return PipBoundsAlgorithm.getValidSourceHintRect(mPictureInPictureParams,
                    rotatedDestinationBounds);
        }
        return sourceHintRect;
    }

    /**
     * This is a situation in which the source rect hint on at least one axis is smaller
     * than the destination bounds, which represents a problem because we would have to scale
     * up that axis to fit the bounds. So instead, just fallback to the non-source hint
     * animation in this case.
     *
     * @return {@code false} if the given source is too small to use for the entering animation.
     */
    private boolean isSourceRectHintValidForEnterPip(Rect sourceRectHint, Rect destinationBounds) {
        return sourceRectHint != null
                && sourceRectHint.width() > destinationBounds.width()
                && sourceRectHint.height() > destinationBounds.height();
    }

    /**
     * Sync with {@link SplitScreenController} on destination bounds if PiP is going to
     * split screen.
     *
     * @param destinationBoundsOut contain the updated destination bounds if applicable
     * @return {@code true} if destinationBounds is altered for split screen
     */
    private boolean syncWithSplitScreenBounds(Rect destinationBoundsOut, boolean enterSplit) {
        if (!enterSplit || !mSplitScreenOptional.isPresent()) {
            return false;
        }
        final Rect topLeft = new Rect();
        final Rect bottomRight = new Rect();
        mSplitScreenOptional.get().getStageBounds(topLeft, bottomRight);
        final boolean isPipTopLeft = isPipTopLeft();
        destinationBoundsOut.set(isPipTopLeft ? topLeft : bottomRight);
        return true;
    }

    /**
     * Fades out and removes an overlay surface.
     */
    void fadeOutAndRemoveOverlay(SurfaceControl surface, Runnable callback,
            boolean withStartDelay) {
        if (surface == null || !surface.isValid()) {
            return;
        }

        final ValueAnimator animator = ValueAnimator.ofFloat(1.0f, 0.0f);
        animator.setDuration(mCrossFadeAnimationDuration);
        animator.addUpdateListener(animation -> {
            if (mPipTransitionState.getTransitionState() == PipTransitionState.UNDEFINED) {
                // Could happen if onTaskVanished happens during the animation since we may have
                // set a start delay on this animation.
                ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                        "%s: Task vanished, skip fadeOutAndRemoveOverlay", TAG);
                PipAnimationController.quietCancel(animation);
            } else if (surface.isValid()) {
                final float alpha = (float) animation.getAnimatedValue();
                final SurfaceControl.Transaction transaction =
                        mSurfaceControlTransactionFactory.getTransaction();
                transaction.setAlpha(surface, alpha);
                transaction.apply();
            }
        });
        animator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                removeContentOverlay(surface, callback);
            }
        });
        animator.setStartDelay(withStartDelay ? CONTENT_OVERLAY_FADE_OUT_DELAY_MS : 0);
        animator.start();
    }

    private void removeContentOverlay(SurfaceControl surface, Runnable callback) {
        if (mPipTransitionState.getTransitionState() == PipTransitionState.UNDEFINED) {
            // Avoid double removal, which is fatal.
            return;
        }
        if (surface == null || !surface.isValid()) {
            ProtoLog.w(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                    "%s: trying to remove invalid content overlay (%s)", TAG, surface);
            return;
        }
        final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
        tx.remove(surface);
        tx.apply();
        if (callback != null) callback.run();
    }

    private void resetShadowRadius() {
        if (mPipTransitionState.getTransitionState() == PipTransitionState.UNDEFINED) {
            // mLeash is undefined when in PipTransitionState.UNDEFINED
            return;
        }
        final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
        tx.setShadowRadius(mLeash, 0f);
        tx.apply();
    }

    private void cancelCurrentAnimator() {
        final PipAnimationController.PipTransitionAnimator<?> animator =
                mPipAnimationController.getCurrentAnimator();
        if (animator != null) {
            if (animator.getContentOverlayLeash() != null) {
                removeContentOverlay(animator.getContentOverlayLeash(),
                        animator::clearContentOverlay);
            }
            PipAnimationController.quietCancel(animator);
        }
    }

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

    /**
     * Dumps internal states.
     */
    @Override
    public void dump(PrintWriter pw, String prefix) {
        final String innerPrefix = prefix + "  ";
        pw.println(prefix + TAG);
        pw.println(innerPrefix + "mTaskInfo=" + mTaskInfo);
        pw.println(innerPrefix + "mToken=" + mToken
                + " binder=" + (mToken != null ? mToken.asBinder() : null));
        pw.println(innerPrefix + "mLeash=" + mLeash);
        pw.println(innerPrefix + "mState=" + mPipTransitionState.getTransitionState());
        pw.println(innerPrefix + "mOneShotAnimationType=" + mOneShotAnimationType);
        pw.println(innerPrefix + "mPictureInPictureParams=" + mPictureInPictureParams);
    }

    @Override
    public String toString() {
        return TAG + ":" + taskListenerTypeToString(TASK_LISTENER_TYPE_PIP);
    }
}
