Fixed issue with drag resize state when animating pinned stack.

When animating the pinned stack, we set drag resizing on the top
most task in the stack. This has a couple of issues.
- Only the top most task is put in drag sizing mode and all other
task in the stack will not be in resizing mode.
- The top most task of the stack can change during the animation,
so we fail to clear the drag resize flag on the previous top task.

We now track drag sizing at the stack level and have the stack
drag resizing state affect its tasks drag resizing states.

Also added concept of continuing a bounds animation if the same
target called BoundsAnimationController.animateBounds before the
current animation is done. We don't send onAnimationEnd() for the
current animation that is been cancelled and don't send
onAnimationStarted() for the animation that will be replacing it.

Bug: 25672053
Change-Id: I64e89ed09d81e4802dacebc5818dfa1deb0d588f
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationController.java b/services/core/java/com/android/server/wm/BoundsAnimationController.java
index 1bfdcce..0678ca2 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationController.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationController.java
@@ -22,7 +22,6 @@
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
 import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.animation.ValueAnimator;
 import android.graphics.Rect;
 import android.util.ArrayMap;
@@ -41,8 +40,9 @@
  */
 public class BoundsAnimationController {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "BoundsAnimationController" : TAG_WM;
+    private static final int DEBUG_ANIMATION_SLOW_DOWN_FACTOR = 1;
 
-    // Only acccessed on UI thread.
+    // Only accessed on UI thread.
     private ArrayMap<AnimateBoundsUser, BoundsAnimator> mRunningAnimations = new ArrayMap<>();
 
     private final class BoundsAnimator extends ValueAnimator
@@ -52,14 +52,22 @@
         private final Rect mTo;
         private final Rect mTmpRect;
         private final boolean mMoveToFullScreen;
+        // True if this this animation was cancelled and will be replaced the another animation from
+        // the same {@link #AnimateBoundsUser} target.
+        private boolean mWillReplace;
+        // True to true if this animation replaced a previous animation of the same
+        // {@link #AnimateBoundsUser} target.
+        private final boolean mReplacement;
 
-        BoundsAnimator(AnimateBoundsUser target, Rect from, Rect to, boolean moveToFullScreen) {
+        BoundsAnimator(AnimateBoundsUser target, Rect from, Rect to,
+                boolean moveToFullScreen, boolean replacement) {
             super();
             mTarget = target;
             mFrom = from;
             mTo = to;
             mTmpRect = new Rect();
             mMoveToFullScreen = moveToFullScreen;
+            mReplacement = replacement;
             addUpdateListener(this);
             addListener(this);
         }
@@ -68,10 +76,10 @@
         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);
-            mTmpRect.top = (int) (mFrom.top * remains + mTo.top * value);
-            mTmpRect.right = (int) (mFrom.right * remains + mTo.right * value);
-            mTmpRect.bottom = (int) (mFrom.bottom * remains + mTo.bottom * 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_ANIM) Slog.d(TAG, "animateUpdate: mTarget=" + mTarget + ", mBounds="
                     + mTmpRect + ", from=" + mFrom + ", mTo=" + mTo + ", value=" + value
                     + ", remains=" + remains);
@@ -85,13 +93,15 @@
 
         @Override
         public void onAnimationStart(Animator animation) {
-
+            if (!mReplacement) {
+                mTarget.onAnimationStart();
+            }
         }
 
         @Override
         public void onAnimationEnd(Animator animation) {
             finishAnimation();
-            if (mMoveToFullScreen) {
+            if (mMoveToFullScreen && !mWillReplace) {
                 mTarget.moveToFullscreen();
             }
         }
@@ -101,8 +111,16 @@
             finishAnimation();
         }
 
+        @Override
+        public void cancel() {
+            mWillReplace = true;
+            super.cancel();
+        }
+
         private void finishAnimation() {
-            mTarget.finishBoundsAnimation();
+            if (!mWillReplace) {
+                mTarget.onAnimationEnd();
+            }
             removeListener(this);
             removeUpdateListener(this);
             mRunningAnimations.remove(mTarget);
@@ -126,11 +144,13 @@
          */
         boolean setSize(Rect bounds);
 
+        void onAnimationStart();
+
         /**
-         * Callback for the target to inform it that the animation is finished, so it can do some
+         * Callback for the target to inform it that the animation has ended, so it can do some
          * necessary cleanup.
          */
-        void finishBoundsAnimation();
+        void onAnimationEnd();
 
         void moveToFullscreen();
 
@@ -146,13 +166,15 @@
         }
 
         final BoundsAnimator existing = mRunningAnimations.get(target);
-        if (existing != null) {
+        final boolean replacing = existing != null;
+        if (replacing) {
             existing.cancel();
         }
-        BoundsAnimator animator = new BoundsAnimator(target, from, to, moveToFullscreen);
+        final BoundsAnimator animator =
+                new BoundsAnimator(target, from, to, moveToFullscreen, replacing);
         mRunningAnimations.put(target, animator);
         animator.setFloatValues(0f, 1f);
-        animator.setDuration(DEFAULT_APP_TRANSITION_DURATION);
+        animator.setDuration(DEFAULT_APP_TRANSITION_DURATION * DEBUG_ANIMATION_SLOW_DOWN_FACTOR);
         animator.setInterpolator(new LinearInterpolator());
         animator.start();
     }