Merge "ViewPropertyAnimator cancels prior animations"
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index cc00f94..27e7db1 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -143,10 +143,36 @@
     private static class PropertyBundle {
         int mPropertyMask;
         ArrayList<NameValuesHolder> mNameValuesHolder;
+
         PropertyBundle(int propertyMask, ArrayList<NameValuesHolder> nameValuesHolder) {
             mPropertyMask = propertyMask;
             mNameValuesHolder = nameValuesHolder;
         }
+
+        /**
+         * Removes the given property from being animated as a part of this
+         * PropertyBundle. If the property was a part of this bundle, it returns
+         * true to indicate that it was, in fact, canceled. This is an indication
+         * to the caller that a cancellation actually occurred.
+         *
+         * @param propertyConstant The property whose cancellation is requested.
+         * @return true if the given property is a part of this bundle and if it
+         * has therefore been canceled.
+         */
+        boolean cancel(int propertyConstant) {
+            if ((mPropertyMask & propertyConstant) != 0 && mNameValuesHolder != null) {
+                int count = mNameValuesHolder.size();
+                for (int i = 0; i < count; ++i) {
+                    NameValuesHolder nameValuesHolder = mNameValuesHolder.get(i);
+                    if (nameValuesHolder.mNameConstant == propertyConstant) {
+                        mNameValuesHolder.remove(i);
+                        mPropertyMask &= ~propertyConstant;
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
     }
 
     /**
@@ -508,24 +534,6 @@
             NameValuesHolder nameValuesHolder = nameValueList.get(i);
             propertyMask |= nameValuesHolder.mNameConstant;
         }
-        // First, cancel any running animation on the same property set
-        if (mAnimatorMap.size() > 0) {
-            Animator animatorToCancel = null;
-            Set<Animator> animatorSet = mAnimatorMap.keySet();
-            for (Animator runningAnim : animatorSet) {
-                PropertyBundle bundle = mAnimatorMap.get(runningAnim);
-                if (bundle.mPropertyMask == propertyMask) {
-                    // There can be only one such duplicate, because that animation would
-                    // have caused previous ones to cancel prior to starting. So break when we
-                    // find one.
-                    animatorToCancel = runningAnim;
-                    break;
-                }
-            }
-            if (animatorToCancel != null) {
-                animatorToCancel.cancel();
-            }
-        }
         mAnimatorMap.put(animator, new PropertyBundle(propertyMask, nameValueList));
         animator.addUpdateListener(mAnimatorEventListener);
         animator.addListener(mAnimatorEventListener);
@@ -578,6 +586,29 @@
      * @param byValue The amount by which the property will change
      */
     private void animatePropertyBy(int constantName, float fromValue, float byValue) {
+        // First, cancel any existing animations on this property
+        if (mAnimatorMap.size() > 0) {
+            Animator animatorToCancel = null;
+            Set<Animator> animatorSet = mAnimatorMap.keySet();
+            for (Animator runningAnim : animatorSet) {
+                PropertyBundle bundle = mAnimatorMap.get(runningAnim);
+                if (bundle.cancel(constantName)) {
+                    // property was canceled - cancel the animation if it's now empty
+                    // Note that it's safe to break out here because every new animation
+                    // on a property will cancel a previous animation on that property, so
+                    // there can only ever be one such animation running.
+                    if (bundle.mPropertyMask == NONE) {
+                        // the animation is not longer changing animthing - cancel it
+                        animatorToCancel = runningAnim;
+                        break;
+                    }
+                }
+            }
+            if (animatorToCancel != null) {
+                animatorToCancel.cancel();
+            }
+        }
+
         float startValue = getValue(constantName);
         NameValuesHolder nameValuePair = new NameValuesHolder(constantName, startValue, byValue);
         mPendingAnimations.add(nameValuePair);