am 6f5df881: Merge "Add more reverse support to AnimatedVD" into lmp-dev

* commit '6f5df88108b7fb6b9a59ac36f448bd23b5397ef1':
  Add more reverse support to AnimatedVD
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index 129e52c..95f83ac 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -356,6 +356,22 @@
     public void setTarget(Object target) {
     }
 
+    // Hide reverse() and canReverse() for now since reverse() only work for simple
+    // cases, like we don't support sequential, neither startDelay.
+    // TODO: make reverse() works for all the Animators.
+    /**
+     * @hide
+     */
+    public boolean canReverse() {
+        return false;
+    }
+
+    /**
+     * @hide
+     */
+    public void reverse() {
+    }
+
     /**
      * <p>An animation listener receives notifications from an animation.
      * Notifications indicate animation related events, such as the end or the
diff --git a/core/java/android/animation/AnimatorSet.java b/core/java/android/animation/AnimatorSet.java
index 018a2d6..9156eeb 100644
--- a/core/java/android/animation/AnimatorSet.java
+++ b/core/java/android/animation/AnimatorSet.java
@@ -124,7 +124,7 @@
     // was set on this AnimatorSet, so it should not be passed down to the children.
     private TimeInterpolator mInterpolator = null;
 
-
+    private boolean mReversible = true;
     /**
      * Sets up this AnimatorSet to play all of the supplied animations at the same time.
      * This is equivalent to calling {@link #play(Animator)} with the first animator in the
@@ -177,6 +177,7 @@
             if (items.length == 1) {
                 play(items[0]);
             } else {
+                mReversible = false;
                 for (int i = 0; i < items.length - 1; ++i) {
                     play(items[i]).before(items[i+1]);
                 }
@@ -196,6 +197,7 @@
             if (items.size() == 1) {
                 play(items.get(0));
             } else {
+                mReversible = false;
                 for (int i = 0; i < items.size() - 1; ++i) {
                     play(items.get(i)).before(items.get(i+1));
                 }
@@ -407,6 +409,9 @@
      */
     @Override
     public void setStartDelay(long startDelay) {
+        if (mStartDelay > 0) {
+            mReversible = false;
+        }
         mStartDelay = startDelay;
     }
 
@@ -512,7 +517,7 @@
                 node.animation.setInterpolator(mInterpolator);
             }
         }
-            // First, sort the nodes (if necessary). This will ensure that sortedNodes
+        // First, sort the nodes (if necessary). This will ensure that sortedNodes
         // contains the animation nodes in the correct order.
         sortNodes();
 
@@ -626,6 +631,7 @@
         anim.mNodeMap = new HashMap<Animator, Node>();
         anim.mNodes = new ArrayList<Node>();
         anim.mSortedNodes = new ArrayList<Node>();
+        anim.mReversible = mReversible;
 
         // Walk through the old nodes list, cloning each node and adding it to the new nodemap.
         // One problem is that the old node dependencies point to nodes in the old AnimatorSet.
@@ -908,6 +914,35 @@
     }
 
     /**
+     * @hide
+     */
+    @Override
+    public boolean canReverse() {
+        if (!mReversible)  {
+            return false;
+        }
+        // Loop to make sure all the Nodes can reverse.
+        for (Node node : mNodes) {
+            if (!node.animation.canReverse() || node.animation.getStartDelay() > 0) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public void reverse() {
+        if (canReverse()) {
+            for (Node node : mNodes) {
+                node.animation.reverse();
+            }
+        }
+    }
+
+    /**
      * Dependency holds information about the node that some other node is
      * dependent upon and the nature of that dependency.
      *
@@ -1124,6 +1159,7 @@
          * {@link AnimatorSet#play(Animator)} method ends.
          */
         public Builder before(Animator anim) {
+            mReversible = false;
             Node node = mNodeMap.get(anim);
             if (node == null) {
                 node = new Node(anim);
@@ -1144,6 +1180,7 @@
          * {@link AnimatorSet#play(Animator)} method to play.
          */
         public Builder after(Animator anim) {
+            mReversible = false;
             Node node = mNodeMap.get(anim);
             if (node == null) {
                 node = new Node(anim);
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 5338dd0..e3380a9 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -1038,6 +1038,7 @@
      * play backwards. This behavior is only set for the current animation; future playing
      * of the animation will use the default behavior of playing forward.
      */
+    @Override
     public void reverse() {
         mPlayingBackwards = !mPlayingBackwards;
         if (mPlayingState == RUNNING) {
@@ -1053,6 +1054,14 @@
     }
 
     /**
+     * @hide
+     */
+    @Override
+    public boolean canReverse() {
+        return true;
+    }
+
+    /**
      * Called internally to end an animation by removing it from the animations list. Must be
      * called on the UI thread.
      */
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
index 485b38a..d5aa5f8 100644
--- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -26,6 +26,7 @@
 import android.content.res.Resources.Theme;
 import android.content.res.TypedArray;
 import android.util.AttributeSet;
+import android.util.Log;
 import android.util.LongSparseLongArray;
 import android.util.SparseIntArray;
 import android.util.StateSet;
@@ -62,6 +63,8 @@
  * @attr ref android.R.styleable#DrawableStates_state_pressed
  */
 public class AnimatedStateListDrawable extends StateListDrawable {
+    private static final String LOGTAG = AnimatedStateListDrawable.class.getSimpleName();
+
     private static final String ELEMENT_TRANSITION = "transition";
     private static final String ELEMENT_ITEM = "item";
 
@@ -302,13 +305,13 @@
 
         @Override
         public boolean canReverse() {
-            return true;
+            return mAvd.canReverse();
         }
 
         @Override
         public void start() {
             if (mReversed) {
-                mAvd.reverse();
+                reverse();
             } else {
                 mAvd.start();
             }
@@ -316,7 +319,11 @@
 
         @Override
         public void reverse() {
-            mAvd.reverse();
+            if (canReverse()) {
+                mAvd.reverse();
+            } else {
+                Log.w(LOGTAG, "Reverse() is called on a drawable can't reverse");
+            }
         }
 
         @Override
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index 071d8ba4..11c2571 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -337,15 +337,33 @@
      * Reverses ongoing animations or starts pending animations in reverse.
      * <p>
      * NOTE: Only works of all animations are ValueAnimators.
+     * @hide
      */
-    void reverse() {
+    public void reverse() {
         final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
         final int size = animators.size();
         for (int i = 0; i < size; i++) {
             final Animator animator = animators.get(i);
-            if (animator instanceof ValueAnimator) {
-                ((ValueAnimator) animator).reverse();
+            if (animator.canReverse()) {
+                animator.reverse();
+            } else {
+                Log.w(LOGTAG, "AnimatedVectorDrawable can't reverse()");
             }
         }
     }
+
+    /**
+     * @hide
+     */
+    public boolean canReverse() {
+        final ArrayList<Animator> animators = mAnimatedVectorState.mAnimators;
+        final int size = animators.size();
+        for (int i = 0; i < size; i++) {
+            final Animator animator = animators.get(i);
+            if (!animator.canReverse()) {
+                return false;
+            }
+        }
+        return true;
+    }
 }
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml
similarity index 98%
rename from tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable.xml
rename to tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml
index 30fb1b8..18d7755 100644
--- a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable.xml
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml
@@ -19,7 +19,7 @@
         android:drawable="@drawable/vector_drawable12" />
     <item android:id="@+id/off"
         android:drawable="@drawable/vector_drawable12" />
-    <transition android:fromId="@+id/off" android:toId="@+id/on">
+    <transition android:fromId="@+id/off" android:toId="@+id/on" android:reversible="true">
         <animated-vector android:drawable="@drawable/vector_drawable12">
             <target
                 android:name="pie1"
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02.xml
new file mode 100644
index 0000000..6a67b02
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/on" android:state_checked="true"
+        android:drawable="@drawable/vector_drawable_grouping_1" />
+    <item android:id="@+id/off"
+        android:drawable="@drawable/vector_drawable_grouping_1" />
+    <transition android:fromId="@+id/off" android:toId="@+id/on"
+        android:drawable="@drawable/animation_vector_drawable_grouping_1"
+        android:reversible="true">
+    </transition>
+</animated-selector>
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml
new file mode 100644
index 0000000..65cf25b
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml
@@ -0,0 +1,26 @@
+<!--
+ Copyright (C) 2014 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.
+-->
+
+<animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/on" android:state_checked="true"
+        android:drawable="@drawable/vector_drawable_favorite" />
+    <item android:id="@+id/off"
+        android:drawable="@drawable/vector_drawable_favorite" />
+    <transition android:fromId="@+id/off" android:toId="@+id/on"
+        android:drawable="@drawable/animation_vector_drawable_favorite"
+        android:reversible="true">
+    </transition>
+</animated-selector>
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java
index 0ae0136..566cc4b 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java
@@ -27,7 +27,9 @@
     private static final String LOGCAT = "AnimatedStateVectorDrawableTest";
 
     protected int[] icon = {
-            R.drawable.state_animation_vector_drawable
+            R.drawable.state_animation_vector_drawable01,
+            R.drawable.state_animation_vector_drawable02,
+            R.drawable.state_animation_vector_drawable03,
     };
 
     @Override
@@ -37,7 +39,7 @@
         ScrollView scrollView = new ScrollView(this);
         GridLayout container = new GridLayout(this);
         scrollView.addView(container);
-        container.setColumnCount(1);
+        container.setColumnCount(5);
 
         for (int i = 0; i < icon.length; i++) {
             CheckBox button = new CheckBox(this);