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