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