/*
 * Copyright (C) 2016 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.server.wm;

import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;

import android.animation.AnimationHandler;
import android.animation.AnimationHandler.AnimationFrameCallbackProvider;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.content.Context;
import android.graphics.Rect;
import android.os.Handler;
import android.os.IBinder;
import android.os.Debug;
import android.util.ArrayMap;
import android.util.Slog;
import android.view.Choreographer;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.view.WindowManagerInternal;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;

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

/**
 * Enables animating bounds of objects.
 *
 * In multi-window world bounds of both stack and tasks can change. When we need these bounds to
 * change smoothly and not require the app to relaunch (e.g. because it handles resizes and
 * relaunching it would cause poorer experience), these class provides a way to directly animate
 * the bounds of the resized object.
 *
 * The object that is resized needs to implement {@link BoundsAnimationTarget} interface.
 *
 * NOTE: All calls to methods in this class should be done on the Animation thread
 */
public class BoundsAnimationController {
    private static final boolean DEBUG_LOCAL = false;
    private static final boolean DEBUG = DEBUG_LOCAL || DEBUG_ANIM;
    private static final String TAG = TAG_WITH_CLASS_NAME || DEBUG_LOCAL
            ? "BoundsAnimationController" : TAG_WM;
    private static final int DEBUG_ANIMATION_SLOW_DOWN_FACTOR = 1;

    private static final int DEFAULT_TRANSITION_DURATION = 425;

    @Retention(RetentionPolicy.SOURCE)
    @IntDef({NO_PIP_MODE_CHANGED_CALLBACKS, SCHEDULE_PIP_MODE_CHANGED_ON_START,
        SCHEDULE_PIP_MODE_CHANGED_ON_END})
    public @interface SchedulePipModeChangedState {}
    /** Do not schedule any PiP mode changed callbacks as a part of this animation. */
    public static final int NO_PIP_MODE_CHANGED_CALLBACKS = 0;
    /** Schedule a PiP mode changed callback when this animation starts. */
    public static final int SCHEDULE_PIP_MODE_CHANGED_ON_START = 1;
    /** Schedule a PiP mode changed callback when this animation ends. */
    public static final int SCHEDULE_PIP_MODE_CHANGED_ON_END = 2;

    // Only accessed on UI thread.
    private ArrayMap<BoundsAnimationTarget, BoundsAnimator> mRunningAnimations = new ArrayMap<>();

    private final class AppTransitionNotifier
            extends WindowManagerInternal.AppTransitionListener implements Runnable {

        public void onAppTransitionCancelledLocked() {
            if (DEBUG) Slog.d(TAG, "onAppTransitionCancelledLocked:"
                    + " mFinishAnimationAfterTransition=" + mFinishAnimationAfterTransition);
            animationFinished();
        }
        public void onAppTransitionFinishedLocked(IBinder token) {
            if (DEBUG) Slog.d(TAG, "onAppTransitionFinishedLocked:"
                    + " mFinishAnimationAfterTransition=" + mFinishAnimationAfterTransition);
            animationFinished();
        }
        private void animationFinished() {
            if (mFinishAnimationAfterTransition) {
                mHandler.removeCallbacks(this);
                // This might end up calling into activity manager which will be bad since we have
                // the window manager lock held at this point. Post a message to take care of the
                // processing so we don't deadlock.
                mHandler.post(this);
            }
        }

        @Override
        public void run() {
            for (int i = 0; i < mRunningAnimations.size(); i++) {
                final BoundsAnimator b = mRunningAnimations.valueAt(i);
                b.onAnimationEnd(null);
            }
        }
    }

    private final Handler mHandler;
    private final AppTransition mAppTransition;
    private final AppTransitionNotifier mAppTransitionNotifier = new AppTransitionNotifier();
    private final Interpolator mFastOutSlowInInterpolator;
    private boolean mFinishAnimationAfterTransition = false;
    private final AnimationHandler mAnimationHandler;

    private static final int WAIT_FOR_DRAW_TIMEOUT_MS = 3000;

    BoundsAnimationController(Context context, AppTransition transition, Handler handler,
            AnimationHandler animationHandler) {
        mHandler = handler;
        mAppTransition = transition;
        mAppTransition.registerListenerLocked(mAppTransitionNotifier);
        mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
                com.android.internal.R.interpolator.fast_out_slow_in);
        mAnimationHandler = animationHandler;
    }

    @VisibleForTesting
    final class BoundsAnimator extends ValueAnimator
            implements ValueAnimator.AnimatorUpdateListener, ValueAnimator.AnimatorListener {

        private final BoundsAnimationTarget mTarget;
        private final Rect mFrom = new Rect();
        private final Rect mTo = new Rect();
        private final Rect mTmpRect = new Rect();
        private final Rect mTmpTaskBounds = new Rect();

        // True if this this animation was canceled and will be replaced the another animation from
        // the same {@link #BoundsAnimationTarget} target.
        private boolean mSkipFinalResize;
        // True if this animation replaced a previous animation of the same
        // {@link #BoundsAnimationTarget} target.
        private final boolean mSkipAnimationStart;
        // True if this animation was canceled by the user, not as a part of a replacing animation
        private boolean mSkipAnimationEnd;

        // True if the animation target is animating from the fullscreen. Only one of
        // {@link mMoveToFullscreen} or {@link mMoveFromFullscreen} can be true at any time in the
        // animation.
        private boolean mMoveFromFullscreen;
        // True if the animation target should be moved to the fullscreen stack at the end of this
        // animation. Only one of {@link mMoveToFullscreen} or {@link mMoveFromFullscreen} can be
        // true at any time in the animation.
        private boolean mMoveToFullscreen;

        // Whether to schedule PiP mode changes on animation start/end
        private @SchedulePipModeChangedState int mSchedulePipModeChangedState;

        // Depending on whether we are animating from
        // a smaller to a larger size
        private final int mFrozenTaskWidth;
        private final int mFrozenTaskHeight;

        // Timeout callback to ensure we continue the animation if waiting for resuming or app
        // windows drawn fails
        private final Runnable mResumeRunnable = () -> resume();

        BoundsAnimator(BoundsAnimationTarget target, Rect from, Rect to,
                @SchedulePipModeChangedState int schedulePipModeChangedState,
                boolean moveFromFullscreen, boolean moveToFullscreen,
                boolean replacingExistingAnimation) {
            super();
            mTarget = target;
            mFrom.set(from);
            mTo.set(to);
            mSkipAnimationStart = replacingExistingAnimation;
            mSchedulePipModeChangedState = schedulePipModeChangedState;
            mMoveFromFullscreen = moveFromFullscreen;
            mMoveToFullscreen = moveToFullscreen;
            addUpdateListener(this);
            addListener(this);

            // If we are animating from smaller to larger, we want to change the task bounds
            // to their final size immediately so we can use scaling to make the window
            // larger. Likewise if we are going from bigger to smaller, we want to wait until
            // the end so we don't have to upscale from the smaller finished size.
            if (animatingToLargerSize()) {
                mFrozenTaskWidth = mTo.width();
                mFrozenTaskHeight = mTo.height();
            } else {
                mFrozenTaskWidth = mFrom.width();
                mFrozenTaskHeight = mFrom.height();
            }
        }

        @Override
        public void onAnimationStart(Animator animation) {
            if (DEBUG) Slog.d(TAG, "onAnimationStart: mTarget=" + mTarget
                    + " mSkipAnimationStart=" + mSkipAnimationStart
                    + " mSchedulePipModeChangedState=" + mSchedulePipModeChangedState);
            mFinishAnimationAfterTransition = false;
            mTmpRect.set(mFrom.left, mFrom.top, mFrom.left + mFrozenTaskWidth,
                    mFrom.top + mFrozenTaskHeight);

            // Boost the thread priority of the animation thread while the bounds animation is
            // running
            updateBooster();

            // Ensure that we have prepared the target for animation before
            // we trigger any size changes, so it can swap surfaces
            // in to appropriate modes, or do as it wishes otherwise.
            if (!mSkipAnimationStart) {
                mTarget.onAnimationStart(mSchedulePipModeChangedState ==
                        SCHEDULE_PIP_MODE_CHANGED_ON_START);

                // When starting an animation from fullscreen, pause here and wait for the
                // windows-drawn signal before we start the rest of the transition down into PiP.
                if (mMoveFromFullscreen) {
                    pause();
                }
            }

            // Immediately update the task bounds if they have to become larger, but preserve
            // the starting position so we don't jump at the beginning of the animation.
            if (animatingToLargerSize()) {
                mTarget.setPinnedStackSize(mFrom, mTmpRect);

                // We pause the animation until the app has drawn at the new size.
                // The target will notify us via BoundsAnimationController#resume.
                // We do this here and pause the animation, rather than just defer starting it
                // so we can enter the animating state and have WindowStateAnimator apply the
                // correct logic to make this resize seamless.
                if (mMoveToFullscreen) {
                    pause();
                }
            }
        }

        @Override
        public void pause() {
            if (DEBUG) Slog.d(TAG, "pause: waiting for windows drawn");
            super.pause();
            mHandler.postDelayed(mResumeRunnable, WAIT_FOR_DRAW_TIMEOUT_MS);
        }

        @Override
        public void resume() {
            if (DEBUG) Slog.d(TAG, "resume:");
            mHandler.removeCallbacks(mResumeRunnable);
            super.resume();
        }

        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            final float value = (Float) animation.getAnimatedValue();
            final float remains = 1 - value;
            mTmpRect.left = (int) (mFrom.left * remains + mTo.left * value + 0.5f);
            mTmpRect.top = (int) (mFrom.top * remains + mTo.top * value + 0.5f);
            mTmpRect.right = (int) (mFrom.right * remains + mTo.right * value + 0.5f);
            mTmpRect.bottom = (int) (mFrom.bottom * remains + mTo.bottom * value + 0.5f);
            if (DEBUG) Slog.d(TAG, "animateUpdate: mTarget=" + mTarget + " mBounds="
                    + mTmpRect + " from=" + mFrom + " mTo=" + mTo + " value=" + value
                    + " remains=" + remains);

            mTmpTaskBounds.set(mTmpRect.left, mTmpRect.top,
                    mTmpRect.left + mFrozenTaskWidth, mTmpRect.top + mFrozenTaskHeight);

            if (!mTarget.setPinnedStackSize(mTmpRect, mTmpTaskBounds)) {
                // Whoops, the target doesn't feel like animating anymore. Let's immediately finish
                // any further animation.
                if (DEBUG) Slog.d(TAG, "animateUpdate: cancelled");

                // If we have already scheduled a PiP mode changed at the start of the animation,
                // then we need to clean up and schedule one at the end, since we have canceled the
                // animation to the final state.
                if (mSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START) {
                    mSchedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
                }

                // Since we are cancelling immediately without a replacement animation, send the
                // animation end to maintain callback parity, but also skip any further resizes
                cancelAndCallAnimationEnd();
            }
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            if (DEBUG) Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget
                    + " mSkipFinalResize=" + mSkipFinalResize
                    + " mFinishAnimationAfterTransition=" + mFinishAnimationAfterTransition
                    + " mAppTransitionIsRunning=" + mAppTransition.isRunning()
                    + " callers=" + Debug.getCallers(2));

            // There could be another animation running. For example in the
            // move to fullscreen case, recents will also be closing while the
            // previous task will be taking its place in the fullscreen stack.
            // we have to ensure this is completed before we finish the animation
            // and take our place in the fullscreen stack.
            if (mAppTransition.isRunning() && !mFinishAnimationAfterTransition) {
                mFinishAnimationAfterTransition = true;
                return;
            }

            if (!mSkipAnimationEnd) {
                // If this animation has already scheduled the picture-in-picture mode on start, and
                // we are not skipping the final resize due to being canceled, then move the PiP to
                // fullscreen once the animation ends
                if (DEBUG) Slog.d(TAG, "onAnimationEnd: mTarget=" + mTarget
                        + " moveToFullscreen=" + mMoveToFullscreen);
                mTarget.onAnimationEnd(mSchedulePipModeChangedState ==
                        SCHEDULE_PIP_MODE_CHANGED_ON_END, !mSkipFinalResize ? mTo : null,
                                mMoveToFullscreen);
            }

            // Clean up this animation
            removeListener(this);
            removeUpdateListener(this);
            mRunningAnimations.remove(mTarget);

            // Reset the thread priority of the animation thread after the bounds animation is done
            updateBooster();
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            // Always skip the final resize when the animation is canceled
            mSkipFinalResize = true;
            mMoveToFullscreen = false;
        }

        private void cancelAndCallAnimationEnd() {
            if (DEBUG) Slog.d(TAG, "cancelAndCallAnimationEnd: mTarget=" + mTarget);
            mSkipAnimationEnd = false;
            super.cancel();
        }

        @Override
        public void cancel() {
            if (DEBUG) Slog.d(TAG, "cancel: mTarget=" + mTarget);
            mSkipAnimationEnd = true;
            super.cancel();
        }

        /**
         * @return true if the animation target is the same as the input bounds.
         */
        boolean isAnimatingTo(Rect bounds) {
            return mTo.equals(bounds);
        }

        /**
         * @return true if we are animating to a larger surface size
         */
        @VisibleForTesting
        boolean animatingToLargerSize() {
            // TODO: Fix this check for aspect ratio changes
            return (mFrom.width() * mFrom.height() <= mTo.width() * mTo.height());
        }

        @Override
        public void onAnimationRepeat(Animator animation) {
            // Do nothing
        }

        @Override
        public AnimationHandler getAnimationHandler() {
            if (mAnimationHandler != null) {
                return mAnimationHandler;
            }
            return super.getAnimationHandler();
        }
    }

    public void animateBounds(final BoundsAnimationTarget target, Rect from, Rect to,
            int animationDuration, @SchedulePipModeChangedState int schedulePipModeChangedState,
            boolean moveFromFullscreen, boolean moveToFullscreen) {
        animateBoundsImpl(target, from, to, animationDuration, schedulePipModeChangedState,
                moveFromFullscreen, moveToFullscreen);
    }

    @VisibleForTesting
    BoundsAnimator animateBoundsImpl(final BoundsAnimationTarget target, Rect from, Rect to,
            int animationDuration, @SchedulePipModeChangedState int schedulePipModeChangedState,
            boolean moveFromFullscreen, boolean moveToFullscreen) {
        final BoundsAnimator existing = mRunningAnimations.get(target);
        final boolean replacing = existing != null;

        if (DEBUG) Slog.d(TAG, "animateBounds: target=" + target + " from=" + from + " to=" + to
                + " schedulePipModeChangedState=" + schedulePipModeChangedState
                + " replacing=" + replacing);

        if (replacing) {
            if (existing.isAnimatingTo(to)) {
                // Just let the current animation complete if it has the same destination as the
                // one we are trying to start.
                if (DEBUG) Slog.d(TAG, "animateBounds: same destination as existing=" + existing
                        + " ignoring...");

                return existing;
            }

            // Update the PiP callback states if we are replacing the animation
            if (existing.mSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START) {
                if (schedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START) {
                    if (DEBUG) Slog.d(TAG, "animateBounds: still animating to fullscreen, keep"
                            + " existing deferred state");
                } else {
                    if (DEBUG) Slog.d(TAG, "animateBounds: fullscreen animation canceled, callback"
                            + " on start already processed, schedule deferred update on end");
                    schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
                }
            } else if (existing.mSchedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_END) {
                if (schedulePipModeChangedState == SCHEDULE_PIP_MODE_CHANGED_ON_START) {
                    if (DEBUG) Slog.d(TAG, "animateBounds: non-fullscreen animation canceled,"
                            + " callback on start will be processed");
                } else {
                    if (DEBUG) Slog.d(TAG, "animateBounds: still animating from fullscreen, keep"
                            + " existing deferred state");
                    schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_END;
                }
            }

            // Since we are replacing, we skip both animation start and end callbacks
            existing.cancel();
        }
        final BoundsAnimator animator = new BoundsAnimator(target, from, to,
                schedulePipModeChangedState, moveFromFullscreen, moveToFullscreen, replacing);
        mRunningAnimations.put(target, animator);
        animator.setFloatValues(0f, 1f);
        animator.setDuration((animationDuration != -1 ? animationDuration
                : DEFAULT_TRANSITION_DURATION) * DEBUG_ANIMATION_SLOW_DOWN_FACTOR);
        animator.setInterpolator(mFastOutSlowInInterpolator);
        animator.start();
        return animator;
    }

    public Handler getHandler() {
        return mHandler;
    }

    public void onAllWindowsDrawn() {
        if (DEBUG) Slog.d(TAG, "onAllWindowsDrawn:");
        mHandler.post(this::resume);
    }

    private void resume() {
        for (int i = 0; i < mRunningAnimations.size(); i++) {
            final BoundsAnimator b = mRunningAnimations.valueAt(i);
            b.resume();
        }
    }

    private void updateBooster() {
        WindowManagerService.sThreadPriorityBooster.setBoundsAnimationRunning(
                !mRunningAnimations.isEmpty());
    }
}
