ASLD: ASLD's XML reversible flag can turn off the reverse behavior now.

Previously, the android:reversible flag behaves like a suggestion.
Now it is used to enforce no reverse when set to false. In this way, user can
safely setup one direction animation only.
When set to true, but AVD can't reverse , then it will show a warning.

At the same time, update the tests to show different cases, including
AnimationDrawable.

b/18413484

Change-Id: I5552c49dcbd76b0724b4d5593bce8388b27bd905
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
index 6d23634..f58a765 100644
--- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -199,6 +199,8 @@
             return false;
         }
 
+        boolean hasReversibleFlag = state.transitionHasReversibleFlag(fromId, toId);
+
         // This may fail if we're already on the transition, but that's okay!
         selectDrawable(transitionIndex);
 
@@ -206,10 +208,14 @@
         final Drawable d = getCurrent();
         if (d instanceof AnimationDrawable) {
             final boolean reversed = state.isTransitionReversed(fromId, toId);
-            transition = new AnimationDrawableTransition((AnimationDrawable) d, reversed);
+
+            transition = new AnimationDrawableTransition((AnimationDrawable) d,
+                    reversed, hasReversibleFlag);
         } else if (d instanceof AnimatedVectorDrawable) {
             final boolean reversed = state.isTransitionReversed(fromId, toId);
-            transition = new AnimatedVectorDrawableTransition((AnimatedVectorDrawable) d, reversed);
+
+            transition = new AnimatedVectorDrawableTransition((AnimatedVectorDrawable) d,
+                    reversed, hasReversibleFlag);
         } else if (d instanceof Animatable) {
             transition = new AnimatableTransition((Animatable) d);
         } else {
@@ -260,7 +266,12 @@
     private static class AnimationDrawableTransition  extends Transition {
         private final ObjectAnimator mAnim;
 
-        public AnimationDrawableTransition(AnimationDrawable ad, boolean reversed) {
+        // Even AnimationDrawable is always reversible technically, but
+        // we should obey the XML's android:reversible flag.
+        private final boolean mHasReversibleFlag;
+
+        public AnimationDrawableTransition(AnimationDrawable ad,
+                boolean reversed, boolean hasReversibleFlag) {
             final int frameCount = ad.getNumberOfFrames();
             final int fromFrame = reversed ? frameCount - 1 : 0;
             final int toFrame = reversed ? 0 : frameCount - 1;
@@ -269,13 +280,13 @@
             anim.setAutoCancel(true);
             anim.setDuration(interp.getTotalDuration());
             anim.setInterpolator(interp);
-
+            mHasReversibleFlag = hasReversibleFlag;
             mAnim = anim;
         }
 
         @Override
         public boolean canReverse() {
-            return true;
+            return mHasReversibleFlag;
         }
 
         @Override
@@ -296,16 +307,28 @@
 
     private static class AnimatedVectorDrawableTransition  extends Transition {
         private final AnimatedVectorDrawable mAvd;
+
+        // mReversed is indicating the current transition's direction.
         private final boolean mReversed;
 
-        public AnimatedVectorDrawableTransition(AnimatedVectorDrawable avd, boolean reversed) {
+        // mHasReversibleFlag is indicating whether the whole transition has
+        // reversible flag set to true.
+        // If mHasReversibleFlag is false, then mReversed is always false.
+        private final boolean mHasReversibleFlag;
+
+        public AnimatedVectorDrawableTransition(AnimatedVectorDrawable avd,
+                boolean reversed, boolean hasReversibleFlag) {
             mAvd = avd;
             mReversed = reversed;
+            mHasReversibleFlag = hasReversibleFlag;
         }
 
         @Override
         public boolean canReverse() {
-            return mAvd.canReverse();
+            // When the transition's XML says it is not reversible, then we obey
+            // it, even if the AVD itself is reversible.
+            // This will help the single direction transition.
+            return mAvd.canReverse() && mHasReversibleFlag;
         }
 
         @Override
@@ -322,7 +345,8 @@
             if (canReverse()) {
                 mAvd.reverse();
             } else {
-                Log.w(LOGTAG, "Reverse() is called on a drawable can't reverse");
+                Log.w(LOGTAG, "Can't reverse, either the reversible is set to false,"
+                        + " or the AnimatedVectorDrawable can't reverse");
             }
         }
 
@@ -520,8 +544,12 @@
     }
 
     static class AnimatedStateListState extends StateListState {
-        private static final int REVERSE_SHIFT = 32;
-        private static final int REVERSE_MASK = 0x1;
+        // REVERSED_BIT is indicating the current transition's direction.
+        private static final long REVERSED_BIT = 0x100000000l;
+
+        // REVERSIBLE_FLAG_BIT is indicating whether the whole transition has
+        // reversible flag set to true.
+        private static final long REVERSIBLE_FLAG_BIT = 0x200000000l;
 
         int[] mAnimThemeAttrs;
 
@@ -545,11 +573,15 @@
         int addTransition(int fromId, int toId, @NonNull Drawable anim, boolean reversible) {
             final int pos = super.addChild(anim);
             final long keyFromTo = generateTransitionKey(fromId, toId);
-            mTransitions.append(keyFromTo, pos);
+            long reversibleBit = 0;
+            if (reversible) {
+                reversibleBit = REVERSIBLE_FLAG_BIT;
+            }
+            mTransitions.append(keyFromTo, pos | reversibleBit);
 
             if (reversible) {
                 final long keyToFrom = generateTransitionKey(toId, fromId);
-                mTransitions.append(keyToFrom, pos | (1L << REVERSE_SHIFT));
+                mTransitions.append(keyToFrom, pos | REVERSED_BIT | reversibleBit);
             }
 
             return addChild(anim);
@@ -581,7 +613,12 @@
 
         boolean isTransitionReversed(int fromId, int toId) {
             final long keyFromTo = generateTransitionKey(fromId, toId);
-            return (mTransitions.get(keyFromTo, -1) >> REVERSE_SHIFT & REVERSE_MASK) == 1;
+            return (mTransitions.get(keyFromTo, -1) & REVERSED_BIT) != 0;
+        }
+
+        boolean transitionHasReversibleFlag(int fromId, int toId) {
+            final long keyFromTo = generateTransitionKey(fromId, toId);
+            return (mTransitions.get(keyFromTo, -1) & REVERSIBLE_FLAG_BIT) != 0;
         }
 
         @Override
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index d0edeba..e9c8c2a 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -462,19 +462,22 @@
     /**
      * Reverses ongoing animations or starts pending animations in reverse.
      * <p>
-     * NOTE: Only works of all animations are ValueAnimators.
+     * NOTE: Only works if all animations support reverse. Otherwise, this will
+     * do nothing.
      * @hide
      */
     public void reverse() {
+        // Only reverse when all the animators can be reverse. Otherwise, partially
+        // reverse is confusing.
+        if (!canReverse()) {
+            Log.w(LOGTAG, "AnimatedVectorDrawable can't reverse()");
+            return;
+        }
         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()) {
-                animator.reverse();
-            } else {
-                Log.w(LOGTAG, "AnimatedVectorDrawable can't reverse()");
-            }
+            animator.reverse();
         }
     }
 
diff --git a/tests/VectorDrawableTest/res/anim/animation_grouping_1_01.xml b/tests/VectorDrawableTest/res/anim/animation_grouping_1_01.xml
index 8d82d05..8ab79a5 100644
--- a/tests/VectorDrawableTest/res/anim/animation_grouping_1_01.xml
+++ b/tests/VectorDrawableTest/res/anim/animation_grouping_1_01.xml
@@ -15,12 +15,8 @@
      limitations under the License.
 -->
 
-<set xmlns:android="http://schemas.android.com/apk/res/android" >
-
-    <objectAnimator
-        android:duration="3300"
-        android:propertyName="rotation"
-        android:valueFrom="0"
-        android:valueTo="360"
-        android:repeatCount="-1" />
-</set>
\ No newline at end of file
+<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:duration="3300"
+    android:propertyName="rotation"
+    android:valueFrom="0"
+    android:valueTo="450" />
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_drawable04.xml b/tests/VectorDrawableTest/res/drawable/state_animation_drawable04.xml
new file mode 100644
index 0000000..a0a801c
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_drawable04.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_drawable_vector"
+        android:reversible="true">
+    </transition>
+</animated-selector>
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_drawable04_false.xml b/tests/VectorDrawableTest/res/drawable/state_animation_drawable04_false.xml
new file mode 100644
index 0000000..3cf8e48
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_drawable04_false.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:state_checked="false"
+        android:drawable="@drawable/vector_drawable_favorite" />
+    <transition android:fromId="@+id/off" android:toId="@+id/on"
+        android:drawable="@drawable/animation_drawable_vector"
+        android:reversible="false">
+    </transition>
+</animated-selector>
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml
index 18d7755..768fe39 100644
--- a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01.xml
@@ -17,7 +17,7 @@
 <animated-selector xmlns:android="http://schemas.android.com/apk/res/android">
     <item android:id="@+id/on" android:state_checked="true"
         android:drawable="@drawable/vector_drawable12" />
-    <item android:id="@+id/off"
+    <item android:id="@+id/off" android:state_checked="false"
         android:drawable="@drawable/vector_drawable12" />
     <transition android:fromId="@+id/off" android:toId="@+id/on" android:reversible="true">
         <animated-vector android:drawable="@drawable/vector_drawable12">
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01_false.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01_false.xml
new file mode 100644
index 0000000..96d378c
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable01_false.xml
@@ -0,0 +1,47 @@
+<!--
+ 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_drawable12" />
+    <item android:id="@+id/off" android:state_checked="false"
+        android:drawable="@drawable/vector_drawable12" />
+    <transition android:fromId="@+id/off" android:toId="@+id/on" android:reversible="false">
+        <animated-vector android:drawable="@drawable/vector_drawable12">
+            <target
+                android:name="pie1"
+                android:animation="@anim/trim_path_animation01" />
+            <target
+                android:name="v"
+                android:animation="@anim/trim_path_animation02" />
+            <target
+                android:name="v"
+                android:animation="@anim/trim_path_animation05" />
+            <target
+                android:name="rotationGroup"
+                android:animation="@anim/trim_path_animation03" />
+            <target
+                android:name="rotationGroup3"
+                android:animation="@anim/trim_path_animation03" />
+            <target
+                android:name="rotationGroupBlue"
+                android:animation="@anim/trim_path_animation03" />
+            <target
+                android:name="rotationGroup"
+                android:animation="@anim/trim_path_animation04" />
+        </animated-vector>
+    </transition>
+</animated-selector>
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02_false.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02_false.xml
new file mode 100644
index 0000000..b722da1
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable02_false.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:state_checked="false"
+        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="false">
+    </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
index 65cf25b..e24dd1f 100644
--- a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03.xml
@@ -17,7 +17,7 @@
 <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"
+    <item android:id="@+id/off" android:state_checked="false"
         android:drawable="@drawable/vector_drawable_favorite" />
     <transition android:fromId="@+id/off" android:toId="@+id/on"
         android:drawable="@drawable/animation_vector_drawable_favorite"
diff --git a/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03_false.xml b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03_false.xml
new file mode 100644
index 0000000..e788bc2
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/state_animation_vector_drawable03_false.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:state_checked="false"
+        android:drawable="@drawable/vector_drawable_favorite" />
+    <transition android:fromId="@+id/off" android:toId="@+id/on"
+        android:drawable="@drawable/animation_vector_drawable_favorite"
+        android:reversible="false">
+    </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 566cc4b..5386555 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/AnimatedStateVectorDrawableTest.java
@@ -27,9 +27,16 @@
     private static final String LOGCAT = "AnimatedStateVectorDrawableTest";
 
     protected int[] icon = {
+            // These shows pairs of ASLD , the left side set the reversible to true.
+            // the right side set to false.
             R.drawable.state_animation_vector_drawable01,
+            R.drawable.state_animation_vector_drawable01_false,
             R.drawable.state_animation_vector_drawable02,
+            R.drawable.state_animation_vector_drawable02_false,
             R.drawable.state_animation_vector_drawable03,
+            R.drawable.state_animation_vector_drawable03_false,
+            R.drawable.state_animation_drawable04,
+            R.drawable.state_animation_drawable04_false,
     };
 
     @Override
@@ -39,7 +46,7 @@
         ScrollView scrollView = new ScrollView(this);
         GridLayout container = new GridLayout(this);
         scrollView.addView(container);
-        container.setColumnCount(5);
+        container.setColumnCount(2);
 
         for (int i = 0; i < icon.length; i++) {
             CheckBox button = new CheckBox(this);