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