2 * Copyright (C) 2015 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package android.animation;
18 import android.os.Handler;
19 import android.os.Looper;
20 import android.os.Message;
21 import android.os.SystemClock;
22 import android.test.ActivityInstrumentationTestCase2;
23 import android.test.suitebuilder.annotation.SmallTest;
24 import android.view.Choreographer;
25 import android.view.animation.LinearInterpolator;
27 import java.util.ArrayList;
29 import static android.test.MoreAsserts.assertNotEqual;
31 public class ValueAnimatorTests extends ActivityInstrumentationTestCase2<BasicAnimatorActivity> {
32 private static final long WAIT_TIME_OUT = 5000;
33 private ValueAnimator a1;
34 private ValueAnimator a2;
36 // Tolerance of error in calculations related to duration, frame time, etc. due to frame delay.
37 private final static long TOLERANCE = 100; // ms
38 private final static long POLL_INTERVAL = 100; // ms
40 private final static float A1_START_VALUE = 0f;
41 private final static float A1_END_VALUE = 1f;
42 private final static int A2_START_VALUE = 100;
43 private final static int A2_END_VALUE = 200;
45 private final static long DEFAULT_FRAME_INTERVAL = 5; //ms
46 private final static long COMMIT_DELAY = 3; //ms
48 public ValueAnimatorTests() {
49 super(BasicAnimatorActivity.class);
53 public void setUp() throws Exception {
55 a1 = ValueAnimator.ofFloat(A1_START_VALUE, A1_END_VALUE).setDuration(300);
56 a2 = ValueAnimator.ofInt(A2_START_VALUE, A2_END_VALUE).setDuration(500);
60 public void tearDown() throws Exception {
67 public void testStartDelay() throws Throwable {
68 final ValueAnimator a = ValueAnimator.ofFloat(5f, 20f);
69 assertEquals(a.getStartDelay(), 0);
70 final long delay = 200;
71 a.setStartDelay(delay);
72 assertEquals(a.getStartDelay(), delay);
74 final MyUpdateListener listener = new MyUpdateListener();
75 a.addUpdateListener(listener);
76 final long[] startTime = new long[1];
78 runTestOnUiThread(new Runnable() {
81 // Test the time between isRunning() and isStarted()
82 assertFalse(a.isStarted());
83 assertFalse(a.isRunning());
85 startTime[0] = SystemClock.uptimeMillis();
86 assertTrue(a.isStarted());
87 assertFalse(a.isRunning());
91 Thread.sleep(a.getTotalDuration());
92 runTestOnUiThread(new Runnable() {
95 assertTrue(listener.wasRunning);
96 assertTrue(listener.firstRunningFrameTime - startTime[0] >= delay);
100 Thread.sleep(a.getTotalDuration());
101 runTestOnUiThread(new Runnable() {
104 assertFalse(a.isStarted());
110 public void testListenerCallbacks() throws Throwable {
111 final MyListener l1 = new MyListener();
112 final MyListener l2 = new MyListener();
115 a2.setStartDelay(400);
117 assertFalse(l1.startCalled);
118 assertFalse(l1.cancelCalled);
119 assertFalse(l1.endCalled);
120 assertFalse(l2.startCalled);
121 assertFalse(l2.cancelCalled);
122 assertFalse(l2.endCalled);
124 runTestOnUiThread(new Runnable() {
133 Thread.sleep(POLL_INTERVAL);
134 wait += POLL_INTERVAL;
136 runTestOnUiThread(new Runnable() {
139 assertFalse(l1.cancelCalled);
141 assertTrue(l1.cancelCalled);
142 assertTrue(l1.endCalled);
146 while (wait < a2.getStartDelay()) {
147 runTestOnUiThread(new Runnable() {
150 // Make sure a2's start listener isn't called during start delay.
151 assertTrue(l1.startCalled);
152 assertFalse(l2.startCalled);
155 Thread.sleep(POLL_INTERVAL);
156 wait += POLL_INTERVAL;
159 long delay = Math.max(a1.getTotalDuration(), a2.getTotalDuration()) + TOLERANCE;
162 runTestOnUiThread(new Runnable() {
166 assertTrue(l1.startCalled);
167 assertTrue(l1.cancelCalled);
168 assertTrue(l1.endCalled);
170 // a2 is supposed to finish normally
171 assertTrue(l2.startCalled);
172 assertFalse(l2.cancelCalled);
173 assertTrue(l2.endCalled);
179 public void testIsStarted() throws Throwable {
180 assertFalse(a1.isStarted());
181 assertFalse(a2.isStarted());
182 assertFalse(a1.isRunning());
183 assertFalse(a2.isRunning());
184 final long startDelay = 150;
185 a1.setStartDelay(startDelay);
186 final long[] startTime = new long[1];
188 runTestOnUiThread(new Runnable() {
193 startTime[0] = SystemClock.uptimeMillis();
194 assertTrue(a1.isStarted());
195 assertTrue(a2.isStarted());
199 while (delayMs < startDelay) {
200 Thread.sleep(POLL_INTERVAL);
201 delayMs += POLL_INTERVAL;
202 runTestOnUiThread(new Runnable() {
205 if (SystemClock.uptimeMillis() - startTime[0] < startDelay) {
206 assertFalse(a1.isRunning());
212 Thread.sleep(startDelay);
213 runTestOnUiThread(new Runnable() {
216 assertTrue(a1.isRunning());
217 assertTrue(a2.isRunning());
221 long delay = Math.max(a1.getTotalDuration(), a2.getTotalDuration()) * 2;
223 runTestOnUiThread(new Runnable() {
226 assertFalse(a1.isStarted());
227 assertFalse(a1.isRunning());
228 assertFalse(a2.isStarted());
229 assertFalse(a2.isRunning());
235 public void testPause() throws Throwable {
236 runTestOnUiThread(new Runnable() {
239 assertFalse(a1.isPaused());
240 assertFalse(a2.isPaused());
245 assertFalse(a1.isPaused());
246 assertFalse(a2.isPaused());
247 assertTrue(a1.isStarted());
248 assertTrue(a2.isStarted());
252 Thread.sleep(POLL_INTERVAL);
253 runTestOnUiThread(new Runnable() {
256 assertTrue(a1.isRunning());
257 assertTrue(a2.isRunning());
259 assertTrue(a1.isPaused());
260 assertFalse(a2.isPaused());
261 assertTrue(a1.isRunning());
265 Thread.sleep(a2.getTotalDuration());
266 runTestOnUiThread(new Runnable() {
269 // By this time, a2 should have finished, and a1 is still paused
270 assertFalse(a2.isStarted());
271 assertFalse(a2.isRunning());
272 assertTrue(a1.isStarted());
273 assertTrue(a1.isRunning());
274 assertTrue(a1.isPaused());
280 Thread.sleep(POLL_INTERVAL);
281 runTestOnUiThread(new Runnable() {
284 assertTrue(a1.isRunning());
285 assertTrue(a1.isStarted());
286 assertFalse(a1.isPaused());
290 Thread.sleep(a1.getTotalDuration());
291 runTestOnUiThread(new Runnable() {
294 // a1 should finish by now.
295 assertFalse(a1.isRunning());
296 assertFalse(a1.isStarted());
297 assertFalse(a1.isPaused());
304 public void testPauseListener() throws Throwable {
305 MyPauseListener l1 = new MyPauseListener();
306 MyPauseListener l2 = new MyPauseListener();
307 a1.addPauseListener(l1);
308 a2.addPauseListener(l2);
310 assertFalse(l1.pauseCalled);
311 assertFalse(l1.resumeCalled);
312 assertFalse(l2.pauseCalled);
313 assertFalse(l2.resumeCalled);
315 runTestOnUiThread(new Runnable() {
323 Thread.sleep(a1.getTotalDuration() / 2);
326 Thread.sleep(a2.getTotalDuration());
328 // Only a1's pause listener should be called.
329 assertTrue(l1.pauseCalled);
330 assertFalse(l1.resumeCalled);
333 Thread.sleep(a1.getTotalDuration());
335 assertTrue(l1.pauseCalled);
336 assertTrue(l1.resumeCalled);
337 assertFalse(l2.pauseCalled);
338 assertFalse(l2.resumeCalled);
342 public void testResume() throws Throwable {
343 final MyUpdateListener l1 = new MyUpdateListener();
344 final long totalDuration = a1.getTotalDuration();
345 a1.addUpdateListener(l1);
346 // Set a longer duration on a1 for this test
347 a1.setDuration(1000);
348 assertTrue(l1.firstRunningFrameTime < 0);
349 assertTrue(l1.lastUpdateTime < 0);
351 final long[] lastUpdate = new long[1];
353 runTestOnUiThread(new Runnable() {
360 Thread.sleep(totalDuration / 2);
362 runTestOnUiThread(new Runnable() {
365 assertTrue(l1.firstRunningFrameTime > 0);
366 assertTrue(l1.lastUpdateTime > l1.firstRunningFrameTime);
367 lastUpdate[0] = l1.lastUpdateTime;
372 Thread.sleep(totalDuration);
374 runTestOnUiThread(new Runnable() {
377 // There should be no update after pause()
378 assertEquals(lastUpdate[0], l1.lastUpdateTime);
384 Thread.sleep(POLL_INTERVAL);
385 runTestOnUiThread(new Runnable() {
388 assertTrue(l1.lastUpdateTime > lastUpdate[0]);
389 lastUpdate[0] = l1.lastUpdateTime;
392 } while (!a1.isStarted());
394 // Time between pause and resume: totalDuration
395 long entireSpan = totalDuration * 2;
396 long frameDelta = l1.lastUpdateTime - l1.firstRunningFrameTime;
397 assertTrue(Math.abs(entireSpan - frameDelta) < TOLERANCE);
401 public void testEnd() throws Throwable {
402 final MyListener l1 = new MyListener();
403 final MyListener l2 = new MyListener();
406 a1.addListener(new MyListener() {
408 public void onAnimationEnd(Animator anim) {
412 a2.addListener(new MyListener() {
414 public void onAnimationCancel(Animator anim) {
419 runTestOnUiThread(new Runnable() {
422 assertFalse(l1.cancelCalled);
423 assertFalse(l1.endCalled);
424 assertFalse(l2.cancelCalled);
425 assertFalse(l2.endCalled);
430 Thread.sleep(POLL_INTERVAL);
431 runTestOnUiThread(new Runnable() {
438 Thread.sleep(POLL_INTERVAL);
439 runTestOnUiThread(new Runnable() {
442 // Calling cancel from onAnimationEnd will be ignored.
443 assertFalse(l1.cancelCalled);
444 assertTrue(l1.endCalled);
445 assertTrue(l2.cancelCalled);
446 assertTrue(l2.endCalled);
448 float value1 = (Float) a1.getAnimatedValue();
449 int value2 = (Integer) a2.getAnimatedValue();
450 assertEquals(A1_END_VALUE, value1);
451 assertEquals(A2_END_VALUE, value2);
458 public void testEndValue() throws Throwable {
459 final MyListener l1 = new MyListener();
462 final MyListener l2 = new MyListener();
465 runTestOnUiThread(new Runnable() {
473 Thread.sleep(POLL_INTERVAL);
474 runTestOnUiThread(new Runnable() {
477 // Animation has started but not finished, check animated values against end values
478 assertFalse(l1.endCalled);
479 assertFalse(l2.endCalled);
480 assertNotEqual(A1_END_VALUE, a1.getAnimatedValue());
481 assertNotEqual(A1_END_VALUE, a2.getAnimatedValue());
488 Thread.sleep(a1.getTotalDuration());
490 runTestOnUiThread(new Runnable() {
493 assertFalse(l1.cancelCalled);
494 assertTrue(l1.endCalled);
495 assertFalse(l2.cancelCalled);
496 assertTrue(l2.endCalled);
498 // By now a1 should have finished normally and a2 has skipped to the end, check
500 assertEquals(A1_END_VALUE, ((Float) (a1.getAnimatedValue())).floatValue());
501 assertEquals(A2_END_VALUE, ((Integer) (a2.getAnimatedValue())).intValue());
507 public void testUpdateListener() throws InterruptedException {
509 final MyFrameCallbackProvider provider = new MyFrameCallbackProvider();
511 while (provider.mHandler == null) {
512 Thread.sleep(POLL_INTERVAL);
513 sleep += POLL_INTERVAL;
514 if (sleep > WAIT_TIME_OUT) {
518 // Either the looper has started, or timed out
519 assertNotNull(provider.mHandler);
521 final MyListener listener = new MyListener();
522 final MyUpdateListener l1 = new MyUpdateListener() {
524 public void onAnimationUpdate(ValueAnimator animation) {
525 long currentTime = SystemClock.uptimeMillis();
526 long frameDelay = provider.getFrameDelay();
527 if (lastUpdateTime > 0) {
528 // Error tolerance here is one frame.
529 assertTrue((currentTime - lastUpdateTime) < frameDelay * 2);
532 assertTrue(listener.startCalled);
533 assertTrue(listener.startTime > 0);
534 assertTrue(currentTime - listener.startTime < frameDelay * 2);
536 super.onAnimationUpdate(animation);
539 a1.addUpdateListener(l1);
540 a1.addListener(listener);
541 a1.setStartDelay(100);
543 provider.mHandler.post(new Runnable() {
546 AnimationHandler.getInstance().setProvider(provider);
550 Thread.sleep(POLL_INTERVAL);
551 assertTrue(a1.isStarted());
552 Thread.sleep(a1.getTotalDuration() + TOLERANCE);
554 assertFalse(a1.isStarted());
555 assertTrue(listener.endTime > 0);
557 // Check the time difference between last frame and end time.
558 assertTrue(listener.endTime >= l1.lastUpdateTime);
559 assertTrue(listener.endTime - l1.lastUpdateTime < 2 * provider.getFrameDelay());
564 public void testConcurrentModification() throws Throwable {
565 // Attempt to modify list of animations as the list is being iterated
566 final ValueAnimator a0 = ValueAnimator.ofInt(100, 200).setDuration(500);
567 final ValueAnimator a3 = ValueAnimator.ofFloat(0, 1).setDuration(500);
568 final ValueAnimator a4 = ValueAnimator.ofInt(200, 300).setDuration(500);
569 final MyListener listener = new MyListener() {
571 public void onAnimationEnd(Animator anim) {
572 super.onAnimationEnd(anim);
573 // AnimationHandler should be iterating the list at the moment, end/cancel all
574 // the other animations. No ConcurrentModificationException should happen.
581 a2.addListener(listener);
583 runTestOnUiThread(new Runnable() {
593 runTestOnUiThread(new Runnable() {
596 assertTrue(a0.isStarted());
597 assertTrue(a1.isStarted());
598 assertTrue(a2.isStarted());
599 assertTrue(a3.isStarted());
600 assertTrue(a4.isStarted());
603 Thread.sleep(POLL_INTERVAL);
604 runTestOnUiThread(new Runnable() {
607 // End the animator that should be in the middle of the list.
611 Thread.sleep(POLL_INTERVAL);
612 assertTrue(listener.endCalled);
613 assertFalse(a0.isStarted());
614 assertFalse(a1.isStarted());
615 assertFalse(a2.isStarted());
616 assertFalse(a3.isStarted());
617 assertFalse(a4.isStarted());
621 public void testSeek() throws Throwable {
622 final MyListener l1 = new MyListener();
623 final MyListener l2 = new MyListener();
624 final MyUpdateListener updateListener1 = new MyUpdateListener();
625 final MyUpdateListener updateListener2 = new MyUpdateListener();
626 final float a1StartFraction = 0.2f;
627 final float a2StartFraction = 0.3f;
629 // Extend duration so we have plenty of latitude to manipulate the animations when they
631 a1.setDuration(1000);
632 a2.setDuration(1000);
635 a1.addUpdateListener(updateListener1);
636 a2.addUpdateListener(updateListener2);
637 TimeInterpolator interpolator = new LinearInterpolator();
638 a1.setInterpolator(interpolator);
639 a2.setInterpolator(interpolator);
641 runTestOnUiThread(new Runnable() {
644 assertFalse(a1.isStarted());
645 assertFalse(a1.isRunning());
646 assertFalse(a2.isStarted());
647 assertFalse(a2.isRunning());
649 // Test isRunning() and isStarted() before and after seek
650 a1.setCurrentFraction(a1StartFraction);
651 a2.setCurrentFraction(a2StartFraction);
653 assertFalse(a1.isStarted());
654 assertFalse(a1.isRunning());
655 assertFalse(a2.isStarted());
656 assertFalse(a2.isRunning());
659 Thread.sleep(POLL_INTERVAL);
661 // Start animation and seek during the animation.
662 runTestOnUiThread(new Runnable() {
665 assertFalse(a1.isStarted());
666 assertFalse(a1.isRunning());
667 assertFalse(a2.isStarted());
668 assertFalse(a2.isRunning());
669 assertEquals(a1StartFraction, a1.getAnimatedFraction());
670 assertEquals(a2StartFraction, a2.getAnimatedFraction());
677 Thread.sleep(POLL_INTERVAL);
678 final float halfwayFraction = 0.5f;
679 runTestOnUiThread(new Runnable() {
682 assertTrue(l1.startCalled);
683 assertTrue(l2.startCalled);
684 assertFalse(l1.endCalled);
685 assertFalse(l2.endCalled);
687 // Check whether the animations start from the seeking fraction
688 assertTrue(updateListener1.startFraction >= a1StartFraction);
689 assertTrue(updateListener2.startFraction >= a2StartFraction);
691 assertTrue(a1.isStarted());
692 assertTrue(a1.isRunning());
693 assertTrue(a2.isStarted());
694 assertTrue(a2.isRunning());
696 a1.setCurrentFraction(halfwayFraction);
697 a2.setCurrentFraction(halfwayFraction);
701 Thread.sleep(POLL_INTERVAL);
703 // Check that seeking during running doesn't change animation's internal state
704 runTestOnUiThread(new Runnable() {
707 assertTrue(l1.startCalled);
708 assertTrue(l2.startCalled);
709 assertFalse(l1.endCalled);
710 assertFalse(l2.endCalled);
712 assertTrue(a1.isStarted());
713 assertTrue(a1.isRunning());
714 assertTrue(a2.isStarted());
715 assertTrue(a2.isRunning());
719 // Wait until the animators finish successfully.
720 long wait = Math.max(a1.getTotalDuration(), a2.getTotalDuration());
723 runTestOnUiThread(new Runnable() {
726 // Verify that the animators have finished.
727 assertTrue(l1.endCalled);
728 assertTrue(l2.endCalled);
730 assertFalse(a1.isStarted());
731 assertFalse(a2.isStarted());
732 assertFalse(a1.isRunning());
733 assertFalse(a2.isRunning());
737 // Re-start animator a1 after it ends normally, and check that seek value from last run
738 // does not affect the new run.
739 updateListener1.reset();
740 runTestOnUiThread(new Runnable() {
747 Thread.sleep(POLL_INTERVAL);
748 runTestOnUiThread(new Runnable() {
751 assertTrue(updateListener1.wasRunning);
752 assertTrue(updateListener1.startFraction >= 0);
753 assertTrue(updateListener1.startFraction < halfwayFraction);
761 public void testSeekWhileRunning() throws Throwable {
762 // Seek one animator to the beginning and the other one to the end when they are running.
763 final MyListener l1 = new MyListener();
764 final MyListener l2 = new MyListener();
767 runTestOnUiThread(new Runnable() {
770 assertFalse(l1.startCalled);
771 assertFalse(l2.startCalled);
772 assertEquals(0f, a1.getAnimatedFraction());
773 assertEquals(0f, a2.getAnimatedFraction());
778 Thread.sleep(POLL_INTERVAL);
779 runTestOnUiThread(new Runnable() {
782 assertFalse(l1.endCalled);
783 assertFalse(l2.endCalled);
784 assertTrue(a1.isRunning());
785 assertTrue(a2.isRunning());
786 // During the run, seek one to the beginning, the other to the end
787 a1.setCurrentFraction(0f);
788 a2.setCurrentFraction(1f);
791 Thread.sleep(POLL_INTERVAL);
792 runTestOnUiThread(new Runnable() {
795 // Check that a2 has finished due to the seeking, but a1 hasn't finished.
796 assertFalse(l1.endCalled);
797 assertTrue(l2.endCalled);
798 assertEquals(1f, a2.getAnimatedFraction());
802 Thread.sleep(a1.getTotalDuration());
803 runTestOnUiThread(new Runnable() {
806 // By now a1 should finish also.
807 assertTrue(l1.endCalled);
808 assertEquals(1f, a1.getAnimatedFraction());
814 public void testEndBeforeStart() throws Throwable {
815 // This test calls two animators that are not yet started. One animator has completed a
816 // previous run but hasn't started since then, the other one has never run. When end() is
817 // called on these two animators, we expected their animation listeners to receive both
818 // onAnimationStarted(Animator) and onAnimationEnded(Animator) callbacks, in that sequence.
820 a1.setStartDelay(20);
822 // First start a1's first run.
823 final MyListener normalEndingListener = new MyListener();
824 a1.addListener(normalEndingListener);
825 runTestOnUiThread(new Runnable() {
828 assertFalse(a1.isStarted());
829 assertFalse(normalEndingListener.startCalled);
830 assertFalse(normalEndingListener.endCalled);
836 Thread.sleep(a1.getTotalDuration() + POLL_INTERVAL);
838 // a1 should have finished by now.
839 runTestOnUiThread(new Runnable() {
842 // Call end() on both a1 and a2 without calling start()
843 final MyListener l1 = new MyListener();
845 final MyListener l2 = new MyListener();
848 assertFalse(a1.isStarted());
849 assertFalse(l1.startCalled);
850 assertFalse(l1.endCalled);
851 assertFalse(a2.isStarted());
852 assertFalse(l2.startCalled);
853 assertFalse(l1.endCalled);
858 // Check that both animators' listeners have received the animation callbacks.
859 assertTrue(l1.startCalled);
860 assertTrue(l1.endCalled);
861 assertFalse(a1.isStarted());
862 assertTrue(l1.endTime >= l1.startTime);
864 assertTrue(l2.startCalled);
865 assertTrue(l2.endCalled);
866 assertFalse(a2.isStarted());
867 assertTrue(l2.endTime >= l1.startTime);
873 public void testZeroDuration() throws Throwable {
874 // Run two animators with zero duration, with one running forward and the other one
875 // backward. Check that the animations start and finish with the correct end fractions.
879 // Set a fraction on an animation with 0-duration
880 final ValueAnimator a3 = ValueAnimator.ofInt(0, 100);
882 a3.setCurrentFraction(1.0f);
883 assertEquals(1.0f, a3.getAnimatedFraction());
885 final MyListener l1 = new MyListener();
886 final MyListener l2 = new MyListener();
887 final MyListener l3 = new MyListener();
891 runTestOnUiThread(new Runnable() {
894 assertFalse(l1.startCalled);
895 assertFalse(l2.startCalled);
896 assertFalse(l3.startCalled);
897 assertFalse(l1.endCalled);
898 assertFalse(l2.endCalled);
899 assertFalse(l3.endCalled);
905 Thread.sleep(POLL_INTERVAL);
906 runTestOnUiThread(new Runnable() {
909 // Check that the animators have started and finished with the right values.
910 assertTrue(l1.startCalled);
911 assertTrue(l2.startCalled);
912 assertTrue(l3.startCalled);
913 assertTrue(l1.endCalled);
914 assertTrue(l2.endCalled);
915 assertTrue(l3.endCalled);
916 assertEquals(1.0f, a1.getAnimatedFraction());
917 assertEquals(0f, a2.getAnimatedFraction());
918 assertEquals(1f, a3.getAnimatedFraction());
919 assertEquals(A1_END_VALUE, a1.getAnimatedValue());
920 assertEquals(A2_START_VALUE, a2.getAnimatedValue());
921 assertEquals(100, a3.getAnimatedValue());
927 public void testZeroScale() throws Throwable {
928 // Test whether animations would end properly when the scale is forced to be zero
929 float scale = ValueAnimator.getDurationScale();
930 ValueAnimator.setDurationScale(0f);
932 // Run two animators, one of which has a start delay, after setting the duration scale to 0
933 a1.setStartDelay(200);
934 final MyListener l1 = new MyListener();
935 final MyListener l2 = new MyListener();
939 runTestOnUiThread(new Runnable() {
942 assertFalse(l1.startCalled);
943 assertFalse(l2.startCalled);
944 assertFalse(l1.endCalled);
945 assertFalse(l2.endCalled);
951 Thread.sleep(POLL_INTERVAL);
953 runTestOnUiThread(new Runnable() {
956 assertTrue(l1.startCalled);
957 assertTrue(l2.startCalled);
958 assertTrue(l1.endCalled);
959 assertTrue(l2.endCalled);
963 // Restore duration scale
964 ValueAnimator.setDurationScale(scale);
968 public void testReverse() throws Throwable {
969 // Prolong animators duration so that we can do multiple checks during their run
970 final ValueAnimator a3 = ValueAnimator.ofInt(0, 100);
974 final MyListener l1 = new MyListener();
975 final MyListener l2 = new MyListener();
976 final MyListener l3 = new MyListener();
981 // Reverse three animators, seek one to the beginning and another to the end, and force
982 // to end the third one during reversing.
983 runTestOnUiThread(new Runnable() {
986 assertFalse(l1.startCalled);
987 assertFalse(l2.startCalled);
988 assertFalse(l3.startCalled);
989 assertFalse(l1.endCalled);
990 assertFalse(l2.endCalled);
991 assertFalse(l3.endCalled);
997 Thread.sleep(POLL_INTERVAL);
998 runTestOnUiThread(new Runnable() {
1001 assertTrue(l1.startCalled);
1002 assertTrue(l2.startCalled);
1003 assertTrue(l3.startCalled);
1005 a1.setCurrentFraction(0f);
1006 a2.setCurrentFraction(1f);
1009 // Check that the fraction has been set, and the getter returns the correct values.
1010 assertEquals(1f, a1.getAnimatedFraction());
1011 assertEquals(0f, a2.getAnimatedFraction());
1014 Thread.sleep(POLL_INTERVAL);
1016 // By now, a2 should have finished due to the seeking. It wouldn't have finished otherwise.
1017 runTestOnUiThread(new Runnable() {
1020 // Check that both animations have started, and a2 has finished.
1021 assertFalse(l1.endCalled);
1022 assertTrue(l2.endCalled);
1023 assertTrue(l3.endCalled);
1026 Thread.sleep(a1.getTotalDuration());
1028 runTestOnUiThread(new Runnable() {
1031 // Verify that a1 has finished as well.
1032 assertTrue(l1.endCalled);
1033 assertEquals(0f, a1.getAnimatedFraction());
1034 assertEquals(0f, a2.getAnimatedFraction());
1035 assertEquals(0f, a3.getAnimatedFraction());
1040 class MyUpdateListener implements ValueAnimator.AnimatorUpdateListener {
1041 boolean wasRunning = false;
1042 long firstRunningFrameTime = -1;
1043 long lastUpdateTime = -1;
1044 float startFraction = 0;
1047 public void onAnimationUpdate(ValueAnimator animation) {
1048 lastUpdateTime = SystemClock.uptimeMillis();
1049 if (animation.isRunning() && !wasRunning) {
1051 firstRunningFrameTime = lastUpdateTime;
1052 startFraction = animation.getAnimatedFraction();
1053 wasRunning = animation.isRunning();
1059 firstRunningFrameTime = -1;
1060 lastUpdateTime = -1;
1065 class MyListener implements Animator.AnimatorListener {
1066 boolean startCalled = false;
1067 boolean cancelCalled = false;
1068 boolean endCalled = false;
1069 long startTime = -1;
1073 public void onAnimationStart(Animator animation) {
1075 startTime = SystemClock.uptimeMillis();
1079 public void onAnimationEnd(Animator animation) {
1081 endTime = SystemClock.uptimeMillis();
1085 public void onAnimationCancel(Animator animation) {
1086 cancelCalled = true;
1090 public void onAnimationRepeat(Animator animation) {
1095 class MyPauseListener implements Animator.AnimatorPauseListener {
1096 boolean pauseCalled = false;
1097 boolean resumeCalled = false;
1100 public void onAnimationPause(Animator animation) {
1105 public void onAnimationResume(Animator animation) {
1106 resumeCalled = true;
1110 class MyFrameCallbackProvider implements AnimationHandler.AnimationFrameCallbackProvider {
1112 Handler mHandler = null;
1113 private final static int MSG_FRAME = 0;
1114 private long mFrameDelay = DEFAULT_FRAME_INTERVAL;
1115 private ArrayList<Choreographer.FrameCallback> mFrameCallbacks = new ArrayList<>();
1117 final LooperThread mThread = new LooperThread();
1119 public MyFrameCallbackProvider() {
1124 public void postFrameCallback(Choreographer.FrameCallback callback) {
1125 mHandler.sendEmptyMessageDelayed(MSG_FRAME, mFrameDelay);
1126 if (!mFrameCallbacks.contains(callback)) {
1127 mFrameCallbacks.add(callback);
1132 public void postCommitCallback(Runnable runnable) {
1133 // Run the runnable after a commit delay
1134 mHandler.postDelayed(runnable, COMMIT_DELAY);
1138 public long getFrameTime() {
1139 return SystemClock.uptimeMillis();
1143 public long getFrameDelay() {
1148 public void setFrameDelay(long delay) {
1149 mFrameDelay = delay;
1150 if (mFrameCallbacks.size() != 0) {
1151 mHandler.removeMessages(MSG_FRAME);
1152 mHandler.sendEmptyMessageDelayed(MSG_FRAME, mFrameDelay);
1156 class LooperThread extends Thread {
1159 mHandler = new Handler() {
1160 public void handleMessage(Message msg) {
1161 // Handle message here.
1164 for (int i = 0; i < mFrameCallbacks.size(); i++) {
1165 mFrameCallbacks.get(i).doFrame(SystemClock.uptimeMillis());