Home | History | Annotate | Download | only in animation
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package android.animation;
     18 
     19 import android.content.res.ConfigurationBoundResourceCache;
     20 import android.os.Looper;
     21 import android.os.Trace;
     22 import android.util.AndroidRuntimeException;
     23 import android.view.Choreographer;
     24 import android.view.animation.AccelerateDecelerateInterpolator;
     25 import android.view.animation.AnimationUtils;
     26 import android.view.animation.LinearInterpolator;
     27 
     28 import java.util.ArrayList;
     29 import java.util.HashMap;
     30 
     31 /**
     32  * This class provides a simple timing engine for running animations
     33  * which calculate animated values and set them on target objects.
     34  *
     35  * <p>There is a single timing pulse that all animations use. It runs in a
     36  * custom handler to ensure that property changes happen on the UI thread.</p>
     37  *
     38  * <p>By default, ValueAnimator uses non-linear time interpolation, via the
     39  * {@link AccelerateDecelerateInterpolator} class, which accelerates into and decelerates
     40  * out of an animation. This behavior can be changed by calling
     41  * {@link ValueAnimator#setInterpolator(TimeInterpolator)}.</p>
     42  *
     43  * <div class="special reference">
     44  * <h3>Developer Guides</h3>
     45  * <p>For more information about animating with {@code ValueAnimator}, read the
     46  * <a href="{@docRoot}guide/topics/graphics/prop-animation.html#value-animator">Property
     47  * Animation</a> developer guide.</p>
     48  * </div>
     49  */
     50 @SuppressWarnings("unchecked")
     51 public class ValueAnimator extends Animator {
     52 
     53     /**
     54      * Internal constants
     55      */
     56     private static float sDurationScale = 1.0f;
     57 
     58     /**
     59      * Values used with internal variable mPlayingState to indicate the current state of an
     60      * animation.
     61      */
     62     static final int STOPPED    = 0; // Not yet playing
     63     static final int RUNNING    = 1; // Playing normally
     64     static final int SEEKED     = 2; // Seeked to some time value
     65 
     66     /**
     67      * Internal variables
     68      * NOTE: This object implements the clone() method, making a deep copy of any referenced
     69      * objects. As other non-trivial fields are added to this class, make sure to add logic
     70      * to clone() to make deep copies of them.
     71      */
     72 
     73     // The first time that the animation's animateFrame() method is called. This time is used to
     74     // determine elapsed time (and therefore the elapsed fraction) in subsequent calls
     75     // to animateFrame()
     76     long mStartTime;
     77 
     78     /**
     79      * Set when setCurrentPlayTime() is called. If negative, animation is not currently seeked
     80      * to a value.
     81      */
     82     float mSeekFraction = -1;
     83 
     84     /**
     85      * Set on the next frame after pause() is called, used to calculate a new startTime
     86      * or delayStartTime which allows the animator to continue from the point at which
     87      * it was paused. If negative, has not yet been set.
     88      */
     89     private long mPauseTime;
     90 
     91     /**
     92      * Set when an animator is resumed. This triggers logic in the next frame which
     93      * actually resumes the animator.
     94      */
     95     private boolean mResumed = false;
     96 
     97 
     98     // The static sAnimationHandler processes the internal timing loop on which all animations
     99     // are based
    100     /**
    101      * @hide
    102      */
    103     protected static ThreadLocal<AnimationHandler> sAnimationHandler =
    104             new ThreadLocal<AnimationHandler>();
    105 
    106     // The time interpolator to be used if none is set on the animation
    107     private static final TimeInterpolator sDefaultInterpolator =
    108             new AccelerateDecelerateInterpolator();
    109 
    110     /**
    111      * Used to indicate whether the animation is currently playing in reverse. This causes the
    112      * elapsed fraction to be inverted to calculate the appropriate values.
    113      */
    114     private boolean mPlayingBackwards = false;
    115 
    116     /**
    117      * Flag to indicate whether this animator is playing in reverse mode, specifically
    118      * by being started or interrupted by a call to reverse(). This flag is different than
    119      * mPlayingBackwards, which indicates merely whether the current iteration of the
    120      * animator is playing in reverse. It is used in corner cases to determine proper end
    121      * behavior.
    122      */
    123     private boolean mReversing;
    124 
    125     /**
    126      * This variable tracks the current iteration that is playing. When mCurrentIteration exceeds the
    127      * repeatCount (if repeatCount!=INFINITE), the animation ends
    128      */
    129     private int mCurrentIteration = 0;
    130 
    131     /**
    132      * Tracks current elapsed/eased fraction, for querying in getAnimatedFraction().
    133      */
    134     private float mCurrentFraction = 0f;
    135 
    136     /**
    137      * Tracks whether a startDelay'd animation has begun playing through the startDelay.
    138      */
    139     private boolean mStartedDelay = false;
    140 
    141     /**
    142      * Tracks the time at which the animation began playing through its startDelay. This is
    143      * different from the mStartTime variable, which is used to track when the animation became
    144      * active (which is when the startDelay expired and the animation was added to the active
    145      * animations list).
    146      */
    147     private long mDelayStartTime;
    148 
    149     /**
    150      * Flag that represents the current state of the animation. Used to figure out when to start
    151      * an animation (if state == STOPPED). Also used to end an animation that
    152      * has been cancel()'d or end()'d since the last animation frame. Possible values are
    153      * STOPPED, RUNNING, SEEKED.
    154      */
    155     int mPlayingState = STOPPED;
    156 
    157     /**
    158      * Additional playing state to indicate whether an animator has been start()'d. There is
    159      * some lag between a call to start() and the first animation frame. We should still note
    160      * that the animation has been started, even if it's first animation frame has not yet
    161      * happened, and reflect that state in isRunning().
    162      * Note that delayed animations are different: they are not started until their first
    163      * animation frame, which occurs after their delay elapses.
    164      */
    165     private boolean mRunning = false;
    166 
    167     /**
    168      * Additional playing state to indicate whether an animator has been start()'d, whether or
    169      * not there is a nonzero startDelay.
    170      */
    171     private boolean mStarted = false;
    172 
    173     /**
    174      * Tracks whether we've notified listeners of the onAnimationStart() event. This can be
    175      * complex to keep track of since we notify listeners at different times depending on
    176      * startDelay and whether start() was called before end().
    177      */
    178     private boolean mStartListenersCalled = false;
    179 
    180     /**
    181      * Flag that denotes whether the animation is set up and ready to go. Used to
    182      * set up animation that has not yet been started.
    183      */
    184     boolean mInitialized = false;
    185 
    186     //
    187     // Backing variables
    188     //
    189 
    190     // How long the animation should last in ms
    191     private long mDuration = (long)(300 * sDurationScale);
    192     private long mUnscaledDuration = 300;
    193 
    194     // The amount of time in ms to delay starting the animation after start() is called
    195     private long mStartDelay = 0;
    196     private long mUnscaledStartDelay = 0;
    197 
    198     // The number of times the animation will repeat. The default is 0, which means the animation
    199     // will play only once
    200     private int mRepeatCount = 0;
    201 
    202     /**
    203      * The type of repetition that will occur when repeatMode is nonzero. RESTART means the
    204      * animation will start from the beginning on every new cycle. REVERSE means the animation
    205      * will reverse directions on each iteration.
    206      */
    207     private int mRepeatMode = RESTART;
    208 
    209     /**
    210      * The time interpolator to be used. The elapsed fraction of the animation will be passed
    211      * through this interpolator to calculate the interpolated fraction, which is then used to
    212      * calculate the animated values.
    213      */
    214     private TimeInterpolator mInterpolator = sDefaultInterpolator;
    215 
    216     /**
    217      * The set of listeners to be sent events through the life of an animation.
    218      */
    219     ArrayList<AnimatorUpdateListener> mUpdateListeners = null;
    220 
    221     /**
    222      * The property/value sets being animated.
    223      */
    224     PropertyValuesHolder[] mValues;
    225 
    226     /**
    227      * A hashmap of the PropertyValuesHolder objects. This map is used to lookup animated values
    228      * by property name during calls to getAnimatedValue(String).
    229      */
    230     HashMap<String, PropertyValuesHolder> mValuesMap;
    231 
    232     /**
    233      * Public constants
    234      */
    235 
    236     /**
    237      * When the animation reaches the end and <code>repeatCount</code> is INFINITE
    238      * or a positive value, the animation restarts from the beginning.
    239      */
    240     public static final int RESTART = 1;
    241     /**
    242      * When the animation reaches the end and <code>repeatCount</code> is INFINITE
    243      * or a positive value, the animation reverses direction on every iteration.
    244      */
    245     public static final int REVERSE = 2;
    246     /**
    247      * This value used used with the {@link #setRepeatCount(int)} property to repeat
    248      * the animation indefinitely.
    249      */
    250     public static final int INFINITE = -1;
    251 
    252 
    253     /**
    254      * @hide
    255      */
    256     public static void setDurationScale(float durationScale) {
    257         sDurationScale = durationScale;
    258     }
    259 
    260     /**
    261      * @hide
    262      */
    263     public static float getDurationScale() {
    264         return sDurationScale;
    265     }
    266 
    267     /**
    268      * Creates a new ValueAnimator object. This default constructor is primarily for
    269      * use internally; the factory methods which take parameters are more generally
    270      * useful.
    271      */
    272     public ValueAnimator() {
    273     }
    274 
    275     /**
    276      * Constructs and returns a ValueAnimator that animates between int values. A single
    277      * value implies that that value is the one being animated to. However, this is not typically
    278      * useful in a ValueAnimator object because there is no way for the object to determine the
    279      * starting value for the animation (unlike ObjectAnimator, which can derive that value
    280      * from the target object and property being animated). Therefore, there should typically
    281      * be two or more values.
    282      *
    283      * @param values A set of values that the animation will animate between over time.
    284      * @return A ValueAnimator object that is set up to animate between the given values.
    285      */
    286     public static ValueAnimator ofInt(int... values) {
    287         ValueAnimator anim = new ValueAnimator();
    288         anim.setIntValues(values);
    289         return anim;
    290     }
    291 
    292     /**
    293      * Constructs and returns a ValueAnimator that animates between color values. A single
    294      * value implies that that value is the one being animated to. However, this is not typically
    295      * useful in a ValueAnimator object because there is no way for the object to determine the
    296      * starting value for the animation (unlike ObjectAnimator, which can derive that value
    297      * from the target object and property being animated). Therefore, there should typically
    298      * be two or more values.
    299      *
    300      * @param values A set of values that the animation will animate between over time.
    301      * @return A ValueAnimator object that is set up to animate between the given values.
    302      */
    303     public static ValueAnimator ofArgb(int... values) {
    304         ValueAnimator anim = new ValueAnimator();
    305         anim.setIntValues(values);
    306         anim.setEvaluator(ArgbEvaluator.getInstance());
    307         return anim;
    308     }
    309 
    310     /**
    311      * Constructs and returns a ValueAnimator that animates between float values. A single
    312      * value implies that that value is the one being animated to. However, this is not typically
    313      * useful in a ValueAnimator object because there is no way for the object to determine the
    314      * starting value for the animation (unlike ObjectAnimator, which can derive that value
    315      * from the target object and property being animated). Therefore, there should typically
    316      * be two or more values.
    317      *
    318      * @param values A set of values that the animation will animate between over time.
    319      * @return A ValueAnimator object that is set up to animate between the given values.
    320      */
    321     public static ValueAnimator ofFloat(float... values) {
    322         ValueAnimator anim = new ValueAnimator();
    323         anim.setFloatValues(values);
    324         return anim;
    325     }
    326 
    327     /**
    328      * Constructs and returns a ValueAnimator that animates between the values
    329      * specified in the PropertyValuesHolder objects.
    330      *
    331      * @param values A set of PropertyValuesHolder objects whose values will be animated
    332      * between over time.
    333      * @return A ValueAnimator object that is set up to animate between the given values.
    334      */
    335     public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values) {
    336         ValueAnimator anim = new ValueAnimator();
    337         anim.setValues(values);
    338         return anim;
    339     }
    340     /**
    341      * Constructs and returns a ValueAnimator that animates between Object values. A single
    342      * value implies that that value is the one being animated to. However, this is not typically
    343      * useful in a ValueAnimator object because there is no way for the object to determine the
    344      * starting value for the animation (unlike ObjectAnimator, which can derive that value
    345      * from the target object and property being animated). Therefore, there should typically
    346      * be two or more values.
    347      *
    348      * <p>Since ValueAnimator does not know how to animate between arbitrary Objects, this
    349      * factory method also takes a TypeEvaluator object that the ValueAnimator will use
    350      * to perform that interpolation.
    351      *
    352      * @param evaluator A TypeEvaluator that will be called on each animation frame to
    353      * provide the ncessry interpolation between the Object values to derive the animated
    354      * value.
    355      * @param values A set of values that the animation will animate between over time.
    356      * @return A ValueAnimator object that is set up to animate between the given values.
    357      */
    358     public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) {
    359         ValueAnimator anim = new ValueAnimator();
    360         anim.setObjectValues(values);
    361         anim.setEvaluator(evaluator);
    362         return anim;
    363     }
    364 
    365     /**
    366      * Sets int values that will be animated between. A single
    367      * value implies that that value is the one being animated to. However, this is not typically
    368      * useful in a ValueAnimator object because there is no way for the object to determine the
    369      * starting value for the animation (unlike ObjectAnimator, which can derive that value
    370      * from the target object and property being animated). Therefore, there should typically
    371      * be two or more values.
    372      *
    373      * <p>If there are already multiple sets of values defined for this ValueAnimator via more
    374      * than one PropertyValuesHolder object, this method will set the values for the first
    375      * of those objects.</p>
    376      *
    377      * @param values A set of values that the animation will animate between over time.
    378      */
    379     public void setIntValues(int... values) {
    380         if (values == null || values.length == 0) {
    381             return;
    382         }
    383         if (mValues == null || mValues.length == 0) {
    384             setValues(PropertyValuesHolder.ofInt("", values));
    385         } else {
    386             PropertyValuesHolder valuesHolder = mValues[0];
    387             valuesHolder.setIntValues(values);
    388         }
    389         // New property/values/target should cause re-initialization prior to starting
    390         mInitialized = false;
    391     }
    392 
    393     /**
    394      * Sets float values that will be animated between. A single
    395      * value implies that that value is the one being animated to. However, this is not typically
    396      * useful in a ValueAnimator object because there is no way for the object to determine the
    397      * starting value for the animation (unlike ObjectAnimator, which can derive that value
    398      * from the target object and property being animated). Therefore, there should typically
    399      * be two or more values.
    400      *
    401      * <p>If there are already multiple sets of values defined for this ValueAnimator via more
    402      * than one PropertyValuesHolder object, this method will set the values for the first
    403      * of those objects.</p>
    404      *
    405      * @param values A set of values that the animation will animate between over time.
    406      */
    407     public void setFloatValues(float... values) {
    408         if (values == null || values.length == 0) {
    409             return;
    410         }
    411         if (mValues == null || mValues.length == 0) {
    412             setValues(PropertyValuesHolder.ofFloat("", values));
    413         } else {
    414             PropertyValuesHolder valuesHolder = mValues[0];
    415             valuesHolder.setFloatValues(values);
    416         }
    417         // New property/values/target should cause re-initialization prior to starting
    418         mInitialized = false;
    419     }
    420 
    421     /**
    422      * Sets the values to animate between for this animation. A single
    423      * value implies that that value is the one being animated to. However, this is not typically
    424      * useful in a ValueAnimator object because there is no way for the object to determine the
    425      * starting value for the animation (unlike ObjectAnimator, which can derive that value
    426      * from the target object and property being animated). Therefore, there should typically
    427      * be two or more values.
    428      *
    429      * <p>If there are already multiple sets of values defined for this ValueAnimator via more
    430      * than one PropertyValuesHolder object, this method will set the values for the first
    431      * of those objects.</p>
    432      *
    433      * <p>There should be a TypeEvaluator set on the ValueAnimator that knows how to interpolate
    434      * between these value objects. ValueAnimator only knows how to interpolate between the
    435      * primitive types specified in the other setValues() methods.</p>
    436      *
    437      * @param values The set of values to animate between.
    438      */
    439     public void setObjectValues(Object... values) {
    440         if (values == null || values.length == 0) {
    441             return;
    442         }
    443         if (mValues == null || mValues.length == 0) {
    444             setValues(PropertyValuesHolder.ofObject("", null, values));
    445         } else {
    446             PropertyValuesHolder valuesHolder = mValues[0];
    447             valuesHolder.setObjectValues(values);
    448         }
    449         // New property/values/target should cause re-initialization prior to starting
    450         mInitialized = false;
    451     }
    452 
    453     /**
    454      * Sets the values, per property, being animated between. This function is called internally
    455      * by the constructors of ValueAnimator that take a list of values. But a ValueAnimator can
    456      * be constructed without values and this method can be called to set the values manually
    457      * instead.
    458      *
    459      * @param values The set of values, per property, being animated between.
    460      */
    461     public void setValues(PropertyValuesHolder... values) {
    462         int numValues = values.length;
    463         mValues = values;
    464         mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
    465         for (int i = 0; i < numValues; ++i) {
    466             PropertyValuesHolder valuesHolder = values[i];
    467             mValuesMap.put(valuesHolder.getPropertyName(), valuesHolder);
    468         }
    469         // New property/values/target should cause re-initialization prior to starting
    470         mInitialized = false;
    471     }
    472 
    473     /**
    474      * Returns the values that this ValueAnimator animates between. These values are stored in
    475      * PropertyValuesHolder objects, even if the ValueAnimator was created with a simple list
    476      * of value objects instead.
    477      *
    478      * @return PropertyValuesHolder[] An array of PropertyValuesHolder objects which hold the
    479      * values, per property, that define the animation.
    480      */
    481     public PropertyValuesHolder[] getValues() {
    482         return mValues;
    483     }
    484 
    485     /**
    486      * This function is called immediately before processing the first animation
    487      * frame of an animation. If there is a nonzero <code>startDelay</code>, the
    488      * function is called after that delay ends.
    489      * It takes care of the final initialization steps for the
    490      * animation.
    491      *
    492      *  <p>Overrides of this method should call the superclass method to ensure
    493      *  that internal mechanisms for the animation are set up correctly.</p>
    494      */
    495     void initAnimation() {
    496         if (!mInitialized) {
    497             int numValues = mValues.length;
    498             for (int i = 0; i < numValues; ++i) {
    499                 mValues[i].init();
    500             }
    501             mInitialized = true;
    502         }
    503     }
    504 
    505 
    506     /**
    507      * Sets the length of the animation. The default duration is 300 milliseconds.
    508      *
    509      * @param duration The length of the animation, in milliseconds. This value cannot
    510      * be negative.
    511      * @return ValueAnimator The object called with setDuration(). This return
    512      * value makes it easier to compose statements together that construct and then set the
    513      * duration, as in <code>ValueAnimator.ofInt(0, 10).setDuration(500).start()</code>.
    514      */
    515     public ValueAnimator setDuration(long duration) {
    516         if (duration < 0) {
    517             throw new IllegalArgumentException("Animators cannot have negative duration: " +
    518                     duration);
    519         }
    520         mUnscaledDuration = duration;
    521         updateScaledDuration();
    522         return this;
    523     }
    524 
    525     private void updateScaledDuration() {
    526         mDuration = (long)(mUnscaledDuration * sDurationScale);
    527     }
    528 
    529     /**
    530      * Gets the length of the animation. The default duration is 300 milliseconds.
    531      *
    532      * @return The length of the animation, in milliseconds.
    533      */
    534     public long getDuration() {
    535         return mUnscaledDuration;
    536     }
    537 
    538     /**
    539      * Sets the position of the animation to the specified point in time. This time should
    540      * be between 0 and the total duration of the animation, including any repetition. If
    541      * the animation has not yet been started, then it will not advance forward after it is
    542      * set to this time; it will simply set the time to this value and perform any appropriate
    543      * actions based on that time. If the animation is already running, then setCurrentPlayTime()
    544      * will set the current playing time to this value and continue playing from that point.
    545      *
    546      * @param playTime The time, in milliseconds, to which the animation is advanced or rewound.
    547      */
    548     public void setCurrentPlayTime(long playTime) {
    549         float fraction = mUnscaledDuration > 0 ? (float) playTime / mUnscaledDuration : 1;
    550         setCurrentFraction(fraction);
    551     }
    552 
    553     /**
    554      * Sets the position of the animation to the specified fraction. This fraction should
    555      * be between 0 and the total fraction of the animation, including any repetition. That is,
    556      * a fraction of 0 will position the animation at the beginning, a value of 1 at the end,
    557      * and a value of 2 at the end of a reversing animator that repeats once. If
    558      * the animation has not yet been started, then it will not advance forward after it is
    559      * set to this fraction; it will simply set the fraction to this value and perform any
    560      * appropriate actions based on that fraction. If the animation is already running, then
    561      * setCurrentFraction() will set the current fraction to this value and continue
    562      * playing from that point. {@link Animator.AnimatorListener} events are not called
    563      * due to changing the fraction; those events are only processed while the animation
    564      * is running.
    565      *
    566      * @param fraction The fraction to which the animation is advanced or rewound. Values
    567      * outside the range of 0 to the maximum fraction for the animator will be clamped to
    568      * the correct range.
    569      */
    570     public void setCurrentFraction(float fraction) {
    571         initAnimation();
    572         if (fraction < 0) {
    573             fraction = 0;
    574         }
    575         int iteration = (int) fraction;
    576         if (fraction == 1) {
    577             iteration -= 1;
    578         } else if (fraction > 1) {
    579             if (iteration < (mRepeatCount + 1) || mRepeatCount == INFINITE) {
    580                 if (mRepeatMode == REVERSE) {
    581                     mPlayingBackwards = (iteration % 2) != 0;
    582                 }
    583                 fraction = fraction % 1f;
    584             } else {
    585                 fraction = 1;
    586                 iteration -= 1;
    587             }
    588         } else {
    589             mPlayingBackwards = mReversing;
    590         }
    591         mCurrentIteration = iteration;
    592         long seekTime = (long) (mDuration * fraction);
    593         long currentTime = AnimationUtils.currentAnimationTimeMillis();
    594         mStartTime = currentTime - seekTime;
    595         if (mPlayingState != RUNNING) {
    596             mSeekFraction = fraction;
    597             mPlayingState = SEEKED;
    598         }
    599         if (mPlayingBackwards) {
    600             fraction = 1f - fraction;
    601         }
    602         animateValue(fraction);
    603     }
    604 
    605     /**
    606      * Gets the current position of the animation in time, which is equal to the current
    607      * time minus the time that the animation started. An animation that is not yet started will
    608      * return a value of zero.
    609      *
    610      * @return The current position in time of the animation.
    611      */
    612     public long getCurrentPlayTime() {
    613         if (!mInitialized || mPlayingState == STOPPED) {
    614             return 0;
    615         }
    616         return AnimationUtils.currentAnimationTimeMillis() - mStartTime;
    617     }
    618 
    619     /**
    620      * This custom, static handler handles the timing pulse that is shared by
    621      * all active animations. This approach ensures that the setting of animation
    622      * values will happen on the UI thread and that all animations will share
    623      * the same times for calculating their values, which makes synchronizing
    624      * animations possible.
    625      *
    626      * The handler uses the Choreographer for executing periodic callbacks.
    627      *
    628      * @hide
    629      */
    630     @SuppressWarnings("unchecked")
    631     protected static class AnimationHandler implements Runnable {
    632         // The per-thread list of all active animations
    633         /** @hide */
    634         protected final ArrayList<ValueAnimator> mAnimations = new ArrayList<ValueAnimator>();
    635 
    636         // Used in doAnimationFrame() to avoid concurrent modifications of mAnimations
    637         private final ArrayList<ValueAnimator> mTmpAnimations = new ArrayList<ValueAnimator>();
    638 
    639         // The per-thread set of animations to be started on the next animation frame
    640         /** @hide */
    641         protected final ArrayList<ValueAnimator> mPendingAnimations = new ArrayList<ValueAnimator>();
    642 
    643         /**
    644          * Internal per-thread collections used to avoid set collisions as animations start and end
    645          * while being processed.
    646          * @hide
    647          */
    648         protected final ArrayList<ValueAnimator> mDelayedAnims = new ArrayList<ValueAnimator>();
    649         private final ArrayList<ValueAnimator> mEndingAnims = new ArrayList<ValueAnimator>();
    650         private final ArrayList<ValueAnimator> mReadyAnims = new ArrayList<ValueAnimator>();
    651 
    652         private final Choreographer mChoreographer;
    653         private boolean mAnimationScheduled;
    654 
    655         private AnimationHandler() {
    656             mChoreographer = Choreographer.getInstance();
    657         }
    658 
    659         /**
    660          * Start animating on the next frame.
    661          */
    662         public void start() {
    663             scheduleAnimation();
    664         }
    665 
    666         private void doAnimationFrame(long frameTime) {
    667             // mPendingAnimations holds any animations that have requested to be started
    668             // We're going to clear mPendingAnimations, but starting animation may
    669             // cause more to be added to the pending list (for example, if one animation
    670             // starting triggers another starting). So we loop until mPendingAnimations
    671             // is empty.
    672             while (mPendingAnimations.size() > 0) {
    673                 ArrayList<ValueAnimator> pendingCopy =
    674                         (ArrayList<ValueAnimator>) mPendingAnimations.clone();
    675                 mPendingAnimations.clear();
    676                 int count = pendingCopy.size();
    677                 for (int i = 0; i < count; ++i) {
    678                     ValueAnimator anim = pendingCopy.get(i);
    679                     // If the animation has a startDelay, place it on the delayed list
    680                     if (anim.mStartDelay == 0) {
    681                         anim.startAnimation(this);
    682                     } else {
    683                         mDelayedAnims.add(anim);
    684                     }
    685                 }
    686             }
    687             // Next, process animations currently sitting on the delayed queue, adding
    688             // them to the active animations if they are ready
    689             int numDelayedAnims = mDelayedAnims.size();
    690             for (int i = 0; i < numDelayedAnims; ++i) {
    691                 ValueAnimator anim = mDelayedAnims.get(i);
    692                 if (anim.delayedAnimationFrame(frameTime)) {
    693                     mReadyAnims.add(anim);
    694                 }
    695             }
    696             int numReadyAnims = mReadyAnims.size();
    697             if (numReadyAnims > 0) {
    698                 for (int i = 0; i < numReadyAnims; ++i) {
    699                     ValueAnimator anim = mReadyAnims.get(i);
    700                     anim.startAnimation(this);
    701                     anim.mRunning = true;
    702                     mDelayedAnims.remove(anim);
    703                 }
    704                 mReadyAnims.clear();
    705             }
    706 
    707             // Now process all active animations. The return value from animationFrame()
    708             // tells the handler whether it should now be ended
    709             int numAnims = mAnimations.size();
    710             for (int i = 0; i < numAnims; ++i) {
    711                 mTmpAnimations.add(mAnimations.get(i));
    712             }
    713             for (int i = 0; i < numAnims; ++i) {
    714                 ValueAnimator anim = mTmpAnimations.get(i);
    715                 if (mAnimations.contains(anim) && anim.doAnimationFrame(frameTime)) {
    716                     mEndingAnims.add(anim);
    717                 }
    718             }
    719             mTmpAnimations.clear();
    720             if (mEndingAnims.size() > 0) {
    721                 for (int i = 0; i < mEndingAnims.size(); ++i) {
    722                     mEndingAnims.get(i).endAnimation(this);
    723                 }
    724                 mEndingAnims.clear();
    725             }
    726 
    727             // If there are still active or delayed animations, schedule a future call to
    728             // onAnimate to process the next frame of the animations.
    729             if (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty()) {
    730                 scheduleAnimation();
    731             }
    732         }
    733 
    734         // Called by the Choreographer.
    735         @Override
    736         public void run() {
    737             mAnimationScheduled = false;
    738             doAnimationFrame(mChoreographer.getFrameTime());
    739         }
    740 
    741         private void scheduleAnimation() {
    742             if (!mAnimationScheduled) {
    743                 mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, this, null);
    744                 mAnimationScheduled = true;
    745             }
    746         }
    747     }
    748 
    749     /**
    750      * The amount of time, in milliseconds, to delay starting the animation after
    751      * {@link #start()} is called.
    752      *
    753      * @return the number of milliseconds to delay running the animation
    754      */
    755     public long getStartDelay() {
    756         return mUnscaledStartDelay;
    757     }
    758 
    759     /**
    760      * The amount of time, in milliseconds, to delay starting the animation after
    761      * {@link #start()} is called.
    762 
    763      * @param startDelay The amount of the delay, in milliseconds
    764      */
    765     public void setStartDelay(long startDelay) {
    766         this.mStartDelay = (long)(startDelay * sDurationScale);
    767         mUnscaledStartDelay = startDelay;
    768     }
    769 
    770     /**
    771      * The amount of time, in milliseconds, between each frame of the animation. This is a
    772      * requested time that the animation will attempt to honor, but the actual delay between
    773      * frames may be different, depending on system load and capabilities. This is a static
    774      * function because the same delay will be applied to all animations, since they are all
    775      * run off of a single timing loop.
    776      *
    777      * The frame delay may be ignored when the animation system uses an external timing
    778      * source, such as the display refresh rate (vsync), to govern animations.
    779      *
    780      * @return the requested time between frames, in milliseconds
    781      */
    782     public static long getFrameDelay() {
    783         return Choreographer.getFrameDelay();
    784     }
    785 
    786     /**
    787      * The amount of time, in milliseconds, between each frame of the animation. This is a
    788      * requested time that the animation will attempt to honor, but the actual delay between
    789      * frames may be different, depending on system load and capabilities. This is a static
    790      * function because the same delay will be applied to all animations, since they are all
    791      * run off of a single timing loop.
    792      *
    793      * The frame delay may be ignored when the animation system uses an external timing
    794      * source, such as the display refresh rate (vsync), to govern animations.
    795      *
    796      * @param frameDelay the requested time between frames, in milliseconds
    797      */
    798     public static void setFrameDelay(long frameDelay) {
    799         Choreographer.setFrameDelay(frameDelay);
    800     }
    801 
    802     /**
    803      * The most recent value calculated by this <code>ValueAnimator</code> when there is just one
    804      * property being animated. This value is only sensible while the animation is running. The main
    805      * purpose for this read-only property is to retrieve the value from the <code>ValueAnimator</code>
    806      * during a call to {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which
    807      * is called during each animation frame, immediately after the value is calculated.
    808      *
    809      * @return animatedValue The value most recently calculated by this <code>ValueAnimator</code> for
    810      * the single property being animated. If there are several properties being animated
    811      * (specified by several PropertyValuesHolder objects in the constructor), this function
    812      * returns the animated value for the first of those objects.
    813      */
    814     public Object getAnimatedValue() {
    815         if (mValues != null && mValues.length > 0) {
    816             return mValues[0].getAnimatedValue();
    817         }
    818         // Shouldn't get here; should always have values unless ValueAnimator was set up wrong
    819         return null;
    820     }
    821 
    822     /**
    823      * The most recent value calculated by this <code>ValueAnimator</code> for <code>propertyName</code>.
    824      * The main purpose for this read-only property is to retrieve the value from the
    825      * <code>ValueAnimator</code> during a call to
    826      * {@link AnimatorUpdateListener#onAnimationUpdate(ValueAnimator)}, which
    827      * is called during each animation frame, immediately after the value is calculated.
    828      *
    829      * @return animatedValue The value most recently calculated for the named property
    830      * by this <code>ValueAnimator</code>.
    831      */
    832     public Object getAnimatedValue(String propertyName) {
    833         PropertyValuesHolder valuesHolder = mValuesMap.get(propertyName);
    834         if (valuesHolder != null) {
    835             return valuesHolder.getAnimatedValue();
    836         } else {
    837             // At least avoid crashing if called with bogus propertyName
    838             return null;
    839         }
    840     }
    841 
    842     /**
    843      * Sets how many times the animation should be repeated. If the repeat
    844      * count is 0, the animation is never repeated. If the repeat count is
    845      * greater than 0 or {@link #INFINITE}, the repeat mode will be taken
    846      * into account. The repeat count is 0 by default.
    847      *
    848      * @param value the number of times the animation should be repeated
    849      */
    850     public void setRepeatCount(int value) {
    851         mRepeatCount = value;
    852     }
    853     /**
    854      * Defines how many times the animation should repeat. The default value
    855      * is 0.
    856      *
    857      * @return the number of times the animation should repeat, or {@link #INFINITE}
    858      */
    859     public int getRepeatCount() {
    860         return mRepeatCount;
    861     }
    862 
    863     /**
    864      * Defines what this animation should do when it reaches the end. This
    865      * setting is applied only when the repeat count is either greater than
    866      * 0 or {@link #INFINITE}. Defaults to {@link #RESTART}.
    867      *
    868      * @param value {@link #RESTART} or {@link #REVERSE}
    869      */
    870     public void setRepeatMode(int value) {
    871         mRepeatMode = value;
    872     }
    873 
    874     /**
    875      * Defines what this animation should do when it reaches the end.
    876      *
    877      * @return either one of {@link #REVERSE} or {@link #RESTART}
    878      */
    879     public int getRepeatMode() {
    880         return mRepeatMode;
    881     }
    882 
    883     /**
    884      * Adds a listener to the set of listeners that are sent update events through the life of
    885      * an animation. This method is called on all listeners for every frame of the animation,
    886      * after the values for the animation have been calculated.
    887      *
    888      * @param listener the listener to be added to the current set of listeners for this animation.
    889      */
    890     public void addUpdateListener(AnimatorUpdateListener listener) {
    891         if (mUpdateListeners == null) {
    892             mUpdateListeners = new ArrayList<AnimatorUpdateListener>();
    893         }
    894         mUpdateListeners.add(listener);
    895     }
    896 
    897     /**
    898      * Removes all listeners from the set listening to frame updates for this animation.
    899      */
    900     public void removeAllUpdateListeners() {
    901         if (mUpdateListeners == null) {
    902             return;
    903         }
    904         mUpdateListeners.clear();
    905         mUpdateListeners = null;
    906     }
    907 
    908     /**
    909      * Removes a listener from the set listening to frame updates for this animation.
    910      *
    911      * @param listener the listener to be removed from the current set of update listeners
    912      * for this animation.
    913      */
    914     public void removeUpdateListener(AnimatorUpdateListener listener) {
    915         if (mUpdateListeners == null) {
    916             return;
    917         }
    918         mUpdateListeners.remove(listener);
    919         if (mUpdateListeners.size() == 0) {
    920             mUpdateListeners = null;
    921         }
    922     }
    923 
    924 
    925     /**
    926      * The time interpolator used in calculating the elapsed fraction of this animation. The
    927      * interpolator determines whether the animation runs with linear or non-linear motion,
    928      * such as acceleration and deceleration. The default value is
    929      * {@link android.view.animation.AccelerateDecelerateInterpolator}
    930      *
    931      * @param value the interpolator to be used by this animation. A value of <code>null</code>
    932      * will result in linear interpolation.
    933      */
    934     @Override
    935     public void setInterpolator(TimeInterpolator value) {
    936         if (value != null) {
    937             mInterpolator = value;
    938         } else {
    939             mInterpolator = new LinearInterpolator();
    940         }
    941     }
    942 
    943     /**
    944      * Returns the timing interpolator that this ValueAnimator uses.
    945      *
    946      * @return The timing interpolator for this ValueAnimator.
    947      */
    948     @Override
    949     public TimeInterpolator getInterpolator() {
    950         return mInterpolator;
    951     }
    952 
    953     /**
    954      * The type evaluator to be used when calculating the animated values of this animation.
    955      * The system will automatically assign a float or int evaluator based on the type
    956      * of <code>startValue</code> and <code>endValue</code> in the constructor. But if these values
    957      * are not one of these primitive types, or if different evaluation is desired (such as is
    958      * necessary with int values that represent colors), a custom evaluator needs to be assigned.
    959      * For example, when running an animation on color values, the {@link ArgbEvaluator}
    960      * should be used to get correct RGB color interpolation.
    961      *
    962      * <p>If this ValueAnimator has only one set of values being animated between, this evaluator
    963      * will be used for that set. If there are several sets of values being animated, which is
    964      * the case if PropertyValuesHolder objects were set on the ValueAnimator, then the evaluator
    965      * is assigned just to the first PropertyValuesHolder object.</p>
    966      *
    967      * @param value the evaluator to be used this animation
    968      */
    969     public void setEvaluator(TypeEvaluator value) {
    970         if (value != null && mValues != null && mValues.length > 0) {
    971             mValues[0].setEvaluator(value);
    972         }
    973     }
    974 
    975     private void notifyStartListeners() {
    976         if (mListeners != null && !mStartListenersCalled) {
    977             ArrayList<AnimatorListener> tmpListeners =
    978                     (ArrayList<AnimatorListener>) mListeners.clone();
    979             int numListeners = tmpListeners.size();
    980             for (int i = 0; i < numListeners; ++i) {
    981                 tmpListeners.get(i).onAnimationStart(this);
    982             }
    983         }
    984         mStartListenersCalled = true;
    985     }
    986 
    987     /**
    988      * Start the animation playing. This version of start() takes a boolean flag that indicates
    989      * whether the animation should play in reverse. The flag is usually false, but may be set
    990      * to true if called from the reverse() method.
    991      *
    992      * <p>The animation started by calling this method will be run on the thread that called
    993      * this method. This thread should have a Looper on it (a runtime exception will be thrown if
    994      * this is not the case). Also, if the animation will animate
    995      * properties of objects in the view hierarchy, then the calling thread should be the UI
    996      * thread for that view hierarchy.</p>
    997      *
    998      * @param playBackwards Whether the ValueAnimator should start playing in reverse.
    999      */
   1000     private void start(boolean playBackwards) {
   1001         if (Looper.myLooper() == null) {
   1002             throw new AndroidRuntimeException("Animators may only be run on Looper threads");
   1003         }
   1004         mReversing = playBackwards;
   1005         mPlayingBackwards = playBackwards;
   1006         if (playBackwards && mSeekFraction != -1) {
   1007             if (mSeekFraction == 0 && mCurrentIteration == 0) {
   1008                 // special case: reversing from seek-to-0 should act as if not seeked at all
   1009                 mSeekFraction = 0;
   1010             } else if (mRepeatCount == INFINITE) {
   1011                 mSeekFraction = 1 - (mSeekFraction % 1);
   1012             } else {
   1013                 mSeekFraction = 1 + mRepeatCount - (mCurrentIteration + mSeekFraction);
   1014             }
   1015             mCurrentIteration = (int) mSeekFraction;
   1016             mSeekFraction = mSeekFraction % 1;
   1017         }
   1018         if (mCurrentIteration > 0 && mRepeatMode == REVERSE &&
   1019                 (mCurrentIteration < (mRepeatCount + 1) || mRepeatCount == INFINITE)) {
   1020             // if we were seeked to some other iteration in a reversing animator,
   1021             // figure out the correct direction to start playing based on the iteration
   1022             if (playBackwards) {
   1023                 mPlayingBackwards = (mCurrentIteration % 2) == 0;
   1024             } else {
   1025                 mPlayingBackwards = (mCurrentIteration % 2) != 0;
   1026             }
   1027         }
   1028         int prevPlayingState = mPlayingState;
   1029         mPlayingState = STOPPED;
   1030         mStarted = true;
   1031         mStartedDelay = false;
   1032         mPaused = false;
   1033         updateScaledDuration(); // in case the scale factor has changed since creation time
   1034         AnimationHandler animationHandler = getOrCreateAnimationHandler();
   1035         animationHandler.mPendingAnimations.add(this);
   1036         if (mStartDelay == 0) {
   1037             // This sets the initial value of the animation, prior to actually starting it running
   1038             if (prevPlayingState != SEEKED) {
   1039                 setCurrentPlayTime(0);
   1040             }
   1041             mPlayingState = STOPPED;
   1042             mRunning = true;
   1043             notifyStartListeners();
   1044         }
   1045         animationHandler.start();
   1046     }
   1047 
   1048     @Override
   1049     public void start() {
   1050         start(false);
   1051     }
   1052 
   1053     @Override
   1054     public void cancel() {
   1055         // Only cancel if the animation is actually running or has been started and is about
   1056         // to run
   1057         AnimationHandler handler = getOrCreateAnimationHandler();
   1058         if (mPlayingState != STOPPED
   1059                 || handler.mPendingAnimations.contains(this)
   1060                 || handler.mDelayedAnims.contains(this)) {
   1061             // Only notify listeners if the animator has actually started
   1062             if ((mStarted || mRunning) && mListeners != null) {
   1063                 if (!mRunning) {
   1064                     // If it's not yet running, then start listeners weren't called. Call them now.
   1065                     notifyStartListeners();
   1066                 }
   1067                 ArrayList<AnimatorListener> tmpListeners =
   1068                         (ArrayList<AnimatorListener>) mListeners.clone();
   1069                 for (AnimatorListener listener : tmpListeners) {
   1070                     listener.onAnimationCancel(this);
   1071                 }
   1072             }
   1073             endAnimation(handler);
   1074         }
   1075     }
   1076 
   1077     @Override
   1078     public void end() {
   1079         AnimationHandler handler = getOrCreateAnimationHandler();
   1080         if (!handler.mAnimations.contains(this) && !handler.mPendingAnimations.contains(this)) {
   1081             // Special case if the animation has not yet started; get it ready for ending
   1082             mStartedDelay = false;
   1083             startAnimation(handler);
   1084             mStarted = true;
   1085         } else if (!mInitialized) {
   1086             initAnimation();
   1087         }
   1088         animateValue(mPlayingBackwards ? 0f : 1f);
   1089         endAnimation(handler);
   1090     }
   1091 
   1092     @Override
   1093     public void resume() {
   1094         if (mPaused) {
   1095             mResumed = true;
   1096         }
   1097         super.resume();
   1098     }
   1099 
   1100     @Override
   1101     public void pause() {
   1102         boolean previouslyPaused = mPaused;
   1103         super.pause();
   1104         if (!previouslyPaused && mPaused) {
   1105             mPauseTime = -1;
   1106             mResumed = false;
   1107         }
   1108     }
   1109 
   1110     @Override
   1111     public boolean isRunning() {
   1112         return (mPlayingState == RUNNING || mRunning);
   1113     }
   1114 
   1115     @Override
   1116     public boolean isStarted() {
   1117         return mStarted;
   1118     }
   1119 
   1120     /**
   1121      * Plays the ValueAnimator in reverse. If the animation is already running,
   1122      * it will stop itself and play backwards from the point reached when reverse was called.
   1123      * If the animation is not currently running, then it will start from the end and
   1124      * play backwards. This behavior is only set for the current animation; future playing
   1125      * of the animation will use the default behavior of playing forward.
   1126      */
   1127     @Override
   1128     public void reverse() {
   1129         mPlayingBackwards = !mPlayingBackwards;
   1130         if (mPlayingState == RUNNING) {
   1131             long currentTime = AnimationUtils.currentAnimationTimeMillis();
   1132             long currentPlayTime = currentTime - mStartTime;
   1133             long timeLeft = mDuration - currentPlayTime;
   1134             mStartTime = currentTime - timeLeft;
   1135             mReversing = !mReversing;
   1136         } else if (mStarted) {
   1137             end();
   1138         } else {
   1139             start(true);
   1140         }
   1141     }
   1142 
   1143     /**
   1144      * @hide
   1145      */
   1146     @Override
   1147     public boolean canReverse() {
   1148         return true;
   1149     }
   1150 
   1151     /**
   1152      * Called internally to end an animation by removing it from the animations list. Must be
   1153      * called on the UI thread.
   1154      * @hide
   1155      */
   1156     protected void endAnimation(AnimationHandler handler) {
   1157         handler.mAnimations.remove(this);
   1158         handler.mPendingAnimations.remove(this);
   1159         handler.mDelayedAnims.remove(this);
   1160         mPlayingState = STOPPED;
   1161         mPaused = false;
   1162         if ((mStarted || mRunning) && mListeners != null) {
   1163             if (!mRunning) {
   1164                 // If it's not yet running, then start listeners weren't called. Call them now.
   1165                 notifyStartListeners();
   1166              }
   1167             ArrayList<AnimatorListener> tmpListeners =
   1168                     (ArrayList<AnimatorListener>) mListeners.clone();
   1169             int numListeners = tmpListeners.size();
   1170             for (int i = 0; i < numListeners; ++i) {
   1171                 tmpListeners.get(i).onAnimationEnd(this);
   1172             }
   1173         }
   1174         mRunning = false;
   1175         mStarted = false;
   1176         mStartListenersCalled = false;
   1177         mPlayingBackwards = false;
   1178         mReversing = false;
   1179         mCurrentIteration = 0;
   1180         if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
   1181             Trace.asyncTraceEnd(Trace.TRACE_TAG_VIEW, getNameForTrace(),
   1182                     System.identityHashCode(this));
   1183         }
   1184     }
   1185 
   1186     /**
   1187      * Called internally to start an animation by adding it to the active animations list. Must be
   1188      * called on the UI thread.
   1189      */
   1190     private void startAnimation(AnimationHandler handler) {
   1191         if (Trace.isTagEnabled(Trace.TRACE_TAG_VIEW)) {
   1192             Trace.asyncTraceBegin(Trace.TRACE_TAG_VIEW, getNameForTrace(),
   1193                     System.identityHashCode(this));
   1194         }
   1195         initAnimation();
   1196         handler.mAnimations.add(this);
   1197         if (mStartDelay > 0 && mListeners != null) {
   1198             // Listeners were already notified in start() if startDelay is 0; this is
   1199             // just for delayed animations
   1200             notifyStartListeners();
   1201         }
   1202     }
   1203 
   1204     /**
   1205      * Returns the name of this animator for debugging purposes.
   1206      */
   1207     String getNameForTrace() {
   1208         return "animator";
   1209     }
   1210 
   1211 
   1212     /**
   1213      * Internal function called to process an animation frame on an animation that is currently
   1214      * sleeping through its <code>startDelay</code> phase. The return value indicates whether it
   1215      * should be woken up and put on the active animations queue.
   1216      *
   1217      * @param currentTime The current animation time, used to calculate whether the animation
   1218      * has exceeded its <code>startDelay</code> and should be started.
   1219      * @return True if the animation's <code>startDelay</code> has been exceeded and the animation
   1220      * should be added to the set of active animations.
   1221      */
   1222     private boolean delayedAnimationFrame(long currentTime) {
   1223         if (!mStartedDelay) {
   1224             mStartedDelay = true;
   1225             mDelayStartTime = currentTime;
   1226         }
   1227         if (mPaused) {
   1228             if (mPauseTime < 0) {
   1229                 mPauseTime = currentTime;
   1230             }
   1231             return false;
   1232         } else if (mResumed) {
   1233             mResumed = false;
   1234             if (mPauseTime > 0) {
   1235                 // Offset by the duration that the animation was paused
   1236                 mDelayStartTime += (currentTime - mPauseTime);
   1237             }
   1238         }
   1239         long deltaTime = currentTime - mDelayStartTime;
   1240         if (deltaTime > mStartDelay) {
   1241             // startDelay ended - start the anim and record the
   1242             // mStartTime appropriately
   1243             mStartTime = currentTime - (deltaTime - mStartDelay);
   1244             mPlayingState = RUNNING;
   1245             return true;
   1246         }
   1247         return false;
   1248     }
   1249 
   1250     /**
   1251      * This internal function processes a single animation frame for a given animation. The
   1252      * currentTime parameter is the timing pulse sent by the handler, used to calculate the
   1253      * elapsed duration, and therefore
   1254      * the elapsed fraction, of the animation. The return value indicates whether the animation
   1255      * should be ended (which happens when the elapsed time of the animation exceeds the
   1256      * animation's duration, including the repeatCount).
   1257      *
   1258      * @param currentTime The current time, as tracked by the static timing handler
   1259      * @return true if the animation's duration, including any repetitions due to
   1260      * <code>repeatCount</code>, has been exceeded and the animation should be ended.
   1261      */
   1262     boolean animationFrame(long currentTime) {
   1263         boolean done = false;
   1264         switch (mPlayingState) {
   1265         case RUNNING:
   1266         case SEEKED:
   1267             float fraction = mDuration > 0 ? (float)(currentTime - mStartTime) / mDuration : 1f;
   1268             if (mDuration == 0 && mRepeatCount != INFINITE) {
   1269                 // Skip to the end
   1270                 mCurrentIteration = mRepeatCount;
   1271                 if (!mReversing) {
   1272                     mPlayingBackwards = false;
   1273                 }
   1274             }
   1275             if (fraction >= 1f) {
   1276                 if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) {
   1277                     // Time to repeat
   1278                     if (mListeners != null) {
   1279                         int numListeners = mListeners.size();
   1280                         for (int i = 0; i < numListeners; ++i) {
   1281                             mListeners.get(i).onAnimationRepeat(this);
   1282                         }
   1283                     }
   1284                     if (mRepeatMode == REVERSE) {
   1285                         mPlayingBackwards = !mPlayingBackwards;
   1286                     }
   1287                     mCurrentIteration += (int) fraction;
   1288                     fraction = fraction % 1f;
   1289                     mStartTime += mDuration;
   1290                 } else {
   1291                     done = true;
   1292                     fraction = Math.min(fraction, 1.0f);
   1293                 }
   1294             }
   1295             if (mPlayingBackwards) {
   1296                 fraction = 1f - fraction;
   1297             }
   1298             animateValue(fraction);
   1299             break;
   1300         }
   1301 
   1302         return done;
   1303     }
   1304 
   1305     /**
   1306      * Processes a frame of the animation, adjusting the start time if needed.
   1307      *
   1308      * @param frameTime The frame time.
   1309      * @return true if the animation has ended.
   1310      */
   1311     final boolean doAnimationFrame(long frameTime) {
   1312         if (mPlayingState == STOPPED) {
   1313             mPlayingState = RUNNING;
   1314             if (mSeekFraction < 0) {
   1315                 mStartTime = frameTime;
   1316             } else {
   1317                 long seekTime = (long) (mDuration * mSeekFraction);
   1318                 mStartTime = frameTime - seekTime;
   1319                 mSeekFraction = -1;
   1320             }
   1321         }
   1322         if (mPaused) {
   1323             if (mPauseTime < 0) {
   1324                 mPauseTime = frameTime;
   1325             }
   1326             return false;
   1327         } else if (mResumed) {
   1328             mResumed = false;
   1329             if (mPauseTime > 0) {
   1330                 // Offset by the duration that the animation was paused
   1331                 mStartTime += (frameTime - mPauseTime);
   1332             }
   1333         }
   1334         // The frame time might be before the start time during the first frame of
   1335         // an animation.  The "current time" must always be on or after the start
   1336         // time to avoid animating frames at negative time intervals.  In practice, this
   1337         // is very rare and only happens when seeking backwards.
   1338         final long currentTime = Math.max(frameTime, mStartTime);
   1339         return animationFrame(currentTime);
   1340     }
   1341 
   1342     /**
   1343      * Returns the current animation fraction, which is the elapsed/interpolated fraction used in
   1344      * the most recent frame update on the animation.
   1345      *
   1346      * @return Elapsed/interpolated fraction of the animation.
   1347      */
   1348     public float getAnimatedFraction() {
   1349         return mCurrentFraction;
   1350     }
   1351 
   1352     /**
   1353      * This method is called with the elapsed fraction of the animation during every
   1354      * animation frame. This function turns the elapsed fraction into an interpolated fraction
   1355      * and then into an animated value (from the evaluator. The function is called mostly during
   1356      * animation updates, but it is also called when the <code>end()</code>
   1357      * function is called, to set the final value on the property.
   1358      *
   1359      * <p>Overrides of this method must call the superclass to perform the calculation
   1360      * of the animated value.</p>
   1361      *
   1362      * @param fraction The elapsed fraction of the animation.
   1363      */
   1364     void animateValue(float fraction) {
   1365         fraction = mInterpolator.getInterpolation(fraction);
   1366         mCurrentFraction = fraction;
   1367         int numValues = mValues.length;
   1368         for (int i = 0; i < numValues; ++i) {
   1369             mValues[i].calculateValue(fraction);
   1370         }
   1371         if (mUpdateListeners != null) {
   1372             int numListeners = mUpdateListeners.size();
   1373             for (int i = 0; i < numListeners; ++i) {
   1374                 mUpdateListeners.get(i).onAnimationUpdate(this);
   1375             }
   1376         }
   1377     }
   1378 
   1379     @Override
   1380     public ValueAnimator clone() {
   1381         final ValueAnimator anim = (ValueAnimator) super.clone();
   1382         if (mUpdateListeners != null) {
   1383             anim.mUpdateListeners = new ArrayList<AnimatorUpdateListener>(mUpdateListeners);
   1384         }
   1385         anim.mSeekFraction = -1;
   1386         anim.mPlayingBackwards = false;
   1387         anim.mReversing = false;
   1388         anim.mCurrentIteration = 0;
   1389         anim.mInitialized = false;
   1390         anim.mPlayingState = STOPPED;
   1391         anim.mStartedDelay = false;
   1392         PropertyValuesHolder[] oldValues = mValues;
   1393         if (oldValues != null) {
   1394             int numValues = oldValues.length;
   1395             anim.mValues = new PropertyValuesHolder[numValues];
   1396             anim.mValuesMap = new HashMap<String, PropertyValuesHolder>(numValues);
   1397             for (int i = 0; i < numValues; ++i) {
   1398                 PropertyValuesHolder newValuesHolder = oldValues[i].clone();
   1399                 anim.mValues[i] = newValuesHolder;
   1400                 anim.mValuesMap.put(newValuesHolder.getPropertyName(), newValuesHolder);
   1401             }
   1402         }
   1403         return anim;
   1404     }
   1405 
   1406     /**
   1407      * Implementors of this interface can add themselves as update listeners
   1408      * to an <code>ValueAnimator</code> instance to receive callbacks on every animation
   1409      * frame, after the current frame's values have been calculated for that
   1410      * <code>ValueAnimator</code>.
   1411      */
   1412     public static interface AnimatorUpdateListener {
   1413         /**
   1414          * <p>Notifies the occurrence of another frame of the animation.</p>
   1415          *
   1416          * @param animation The animation which was repeated.
   1417          */
   1418         void onAnimationUpdate(ValueAnimator animation);
   1419 
   1420     }
   1421 
   1422     /**
   1423      * Return the number of animations currently running.
   1424      *
   1425      * Used by StrictMode internally to annotate violations.
   1426      * May be called on arbitrary threads!
   1427      *
   1428      * @hide
   1429      */
   1430     public static int getCurrentAnimationsCount() {
   1431         AnimationHandler handler = sAnimationHandler.get();
   1432         return handler != null ? handler.mAnimations.size() : 0;
   1433     }
   1434 
   1435     /**
   1436      * Clear all animations on this thread, without canceling or ending them.
   1437      * This should be used with caution.
   1438      *
   1439      * @hide
   1440      */
   1441     public static void clearAllAnimations() {
   1442         AnimationHandler handler = sAnimationHandler.get();
   1443         if (handler != null) {
   1444             handler.mAnimations.clear();
   1445             handler.mPendingAnimations.clear();
   1446             handler.mDelayedAnims.clear();
   1447         }
   1448     }
   1449 
   1450     private static AnimationHandler getOrCreateAnimationHandler() {
   1451         AnimationHandler handler = sAnimationHandler.get();
   1452         if (handler == null) {
   1453             handler = new AnimationHandler();
   1454             sAnimationHandler.set(handler);
   1455         }
   1456         return handler;
   1457     }
   1458 
   1459     @Override
   1460     public String toString() {
   1461         String returnVal = "ValueAnimator@" + Integer.toHexString(hashCode());
   1462         if (mValues != null) {
   1463             for (int i = 0; i < mValues.length; ++i) {
   1464                 returnVal += "\n    " + mValues[i].toString();
   1465             }
   1466         }
   1467         return returnVal;
   1468     }
   1469 
   1470     /**
   1471      * <p>Whether or not the ValueAnimator is allowed to run asynchronously off of
   1472      * the UI thread. This is a hint that informs the ValueAnimator that it is
   1473      * OK to run the animation off-thread, however ValueAnimator may decide
   1474      * that it must run the animation on the UI thread anyway. For example if there
   1475      * is an {@link AnimatorUpdateListener} the animation will run on the UI thread,
   1476      * regardless of the value of this hint.</p>
   1477      *
   1478      * <p>Regardless of whether or not the animation runs asynchronously, all
   1479      * listener callbacks will be called on the UI thread.</p>
   1480      *
   1481      * <p>To be able to use this hint the following must be true:</p>
   1482      * <ol>
   1483      * <li>{@link #getAnimatedFraction()} is not needed (it will return undefined values).</li>
   1484      * <li>The animator is immutable while {@link #isStarted()} is true. Requests
   1485      *    to change values, duration, delay, etc... may be ignored.</li>
   1486      * <li>Lifecycle callback events may be asynchronous. Events such as
   1487      *    {@link Animator.AnimatorListener#onAnimationEnd(Animator)} or
   1488      *    {@link Animator.AnimatorListener#onAnimationRepeat(Animator)} may end up delayed
   1489      *    as they must be posted back to the UI thread, and any actions performed
   1490      *    by those callbacks (such as starting new animations) will not happen
   1491      *    in the same frame.</li>
   1492      * <li>State change requests ({@link #cancel()}, {@link #end()}, {@link #reverse()}, etc...)
   1493      *    may be asynchronous. It is guaranteed that all state changes that are
   1494      *    performed on the UI thread in the same frame will be applied as a single
   1495      *    atomic update, however that frame may be the current frame,
   1496      *    the next frame, or some future frame. This will also impact the observed
   1497      *    state of the Animator. For example, {@link #isStarted()} may still return true
   1498      *    after a call to {@link #end()}. Using the lifecycle callbacks is preferred over
   1499      *    queries to {@link #isStarted()}, {@link #isRunning()}, and {@link #isPaused()}
   1500      *    for this reason.</li>
   1501      * </ol>
   1502      * @hide
   1503      */
   1504     @Override
   1505     public void setAllowRunningAsynchronously(boolean mayRunAsync) {
   1506         // It is up to subclasses to support this, if they can.
   1507     }
   1508 }
   1509