OSDN Git Service

998c72a9e9c8a6d4093140b28fdd9ac570c401f3
[android-x86/frameworks-base.git] / core / tests / coretests / src / android / animation / ValueAnimatorTests.java
1 /*
2 * Copyright (C) 2015 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 package android.animation;
17
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;
26
27 import java.util.ArrayList;
28
29 import static android.test.MoreAsserts.assertNotEqual;
30
31 public class ValueAnimatorTests extends ActivityInstrumentationTestCase2<BasicAnimatorActivity> {
32     private static final long WAIT_TIME_OUT = 5000;
33     private ValueAnimator a1;
34     private ValueAnimator a2;
35
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
39
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;
44
45     private final static long DEFAULT_FRAME_INTERVAL = 5; //ms
46     private final static long COMMIT_DELAY = 3; //ms
47
48     public ValueAnimatorTests() {
49         super(BasicAnimatorActivity.class);
50     }
51
52     @Override
53     public void setUp() throws Exception {
54         super.setUp();
55         a1 = ValueAnimator.ofFloat(A1_START_VALUE, A1_END_VALUE).setDuration(300);
56         a2 = ValueAnimator.ofInt(A2_START_VALUE, A2_END_VALUE).setDuration(500);
57     }
58
59     @Override
60     public void tearDown() throws Exception {
61         a1 = null;
62         a2 = null;
63         super.tearDown();
64     }
65
66     @SmallTest
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);
73
74         final MyUpdateListener listener = new MyUpdateListener();
75         a.addUpdateListener(listener);
76         final long[] startTime = new long[1];
77
78         runTestOnUiThread(new Runnable() {
79             @Override
80             public void run() {
81                 // Test the time between isRunning() and isStarted()
82                 assertFalse(a.isStarted());
83                 assertFalse(a.isRunning());
84                 a.start();
85                 startTime[0] = SystemClock.uptimeMillis();
86                 assertTrue(a.isStarted());
87                 assertFalse(a.isRunning());
88             }
89         });
90
91         Thread.sleep(a.getTotalDuration());
92         runTestOnUiThread(new Runnable() {
93             @Override
94             public void run() {
95                 assertTrue(listener.wasRunning);
96                 assertTrue(listener.firstRunningFrameTime - startTime[0] >= delay);
97             }
98         });
99
100         Thread.sleep(a.getTotalDuration());
101         runTestOnUiThread(new Runnable() {
102             @Override
103             public void run() {
104                 assertFalse(a.isStarted());
105             }
106         });
107     }
108
109     @SmallTest
110     public void testListenerCallbacks() throws Throwable {
111         final MyListener l1 = new MyListener();
112         final MyListener l2 = new MyListener();
113         a1.addListener(l1);
114         a2.addListener(l2);
115         a2.setStartDelay(400);
116
117         assertFalse(l1.startCalled);
118         assertFalse(l1.cancelCalled);
119         assertFalse(l1.endCalled);
120         assertFalse(l2.startCalled);
121         assertFalse(l2.cancelCalled);
122         assertFalse(l2.endCalled);
123
124         runTestOnUiThread(new Runnable() {
125             @Override
126             public void run() {
127                 a1.start();
128                 a2.start();
129             }
130         });
131
132         long wait = 0;
133         Thread.sleep(POLL_INTERVAL);
134         wait += POLL_INTERVAL;
135
136         runTestOnUiThread(new Runnable() {
137             @Override
138             public void run() {
139                 assertFalse(l1.cancelCalled);
140                 a1.cancel();
141                 assertTrue(l1.cancelCalled);
142                 assertTrue(l1.endCalled);
143             }
144         });
145
146         while (wait < a2.getStartDelay()) {
147             runTestOnUiThread(new Runnable() {
148                 @Override
149                 public void run() {
150                     // Make sure a2's start listener isn't called during start delay.
151                     assertTrue(l1.startCalled);
152                     assertFalse(l2.startCalled);
153                 }
154             });
155             Thread.sleep(POLL_INTERVAL);
156             wait += POLL_INTERVAL;
157         }
158
159         long delay = Math.max(a1.getTotalDuration(), a2.getTotalDuration()) + TOLERANCE;
160         Thread.sleep(delay);
161
162         runTestOnUiThread(new Runnable() {
163             @Override
164             public void run() {
165                 // a1 is canceled.
166                 assertTrue(l1.startCalled);
167                 assertTrue(l1.cancelCalled);
168                 assertTrue(l1.endCalled);
169
170                 // a2 is supposed to finish normally
171                 assertTrue(l2.startCalled);
172                 assertFalse(l2.cancelCalled);
173                 assertTrue(l2.endCalled);
174             }
175         });
176     }
177
178     @SmallTest
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];
187
188         runTestOnUiThread(new Runnable() {
189             @Override
190             public void run() {
191                 a1.start();
192                 a2.start();
193                 startTime[0] = SystemClock.uptimeMillis();
194                 assertTrue(a1.isStarted());
195                 assertTrue(a2.isStarted());
196             }
197         });
198         long delayMs = 0;
199         while (delayMs < startDelay) {
200             Thread.sleep(POLL_INTERVAL);
201             delayMs += POLL_INTERVAL;
202             runTestOnUiThread(new Runnable() {
203                 @Override
204                 public void run() {
205                     if (SystemClock.uptimeMillis() - startTime[0] < startDelay) {
206                         assertFalse(a1.isRunning());
207                     }
208                 }
209             });
210         }
211
212         Thread.sleep(startDelay);
213         runTestOnUiThread(new Runnable() {
214             @Override
215             public void run() {
216                 assertTrue(a1.isRunning());
217                 assertTrue(a2.isRunning());
218             }
219         });
220
221         long delay = Math.max(a1.getTotalDuration(), a2.getTotalDuration()) * 2;
222         Thread.sleep(delay);
223         runTestOnUiThread(new Runnable() {
224             @Override
225             public void run() {
226                 assertFalse(a1.isStarted());
227                 assertFalse(a1.isRunning());
228                 assertFalse(a2.isStarted());
229                 assertFalse(a2.isRunning());
230             }
231         });
232     }
233
234     @SmallTest
235     public void testPause() throws Throwable {
236         runTestOnUiThread(new Runnable() {
237             @Override
238             public void run() {
239                 assertFalse(a1.isPaused());
240                 assertFalse(a2.isPaused());
241
242                 a1.start();
243                 a2.start();
244
245                 assertFalse(a1.isPaused());
246                 assertFalse(a2.isPaused());
247                 assertTrue(a1.isStarted());
248                 assertTrue(a2.isStarted());
249             }
250         });
251
252         Thread.sleep(POLL_INTERVAL);
253         runTestOnUiThread(new Runnable() {
254             @Override
255             public void run() {
256                 assertTrue(a1.isRunning());
257                 assertTrue(a2.isRunning());
258                 a1.pause();
259                 assertTrue(a1.isPaused());
260                 assertFalse(a2.isPaused());
261                 assertTrue(a1.isRunning());
262             }
263         });
264
265         Thread.sleep(a2.getTotalDuration());
266         runTestOnUiThread(new Runnable() {
267             @Override
268             public void run() {
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());
275
276                 a1.resume();
277             }
278         });
279
280         Thread.sleep(POLL_INTERVAL);
281         runTestOnUiThread(new Runnable() {
282             @Override
283             public void run() {
284                 assertTrue(a1.isRunning());
285                 assertTrue(a1.isStarted());
286                 assertFalse(a1.isPaused());
287             }
288         });
289
290         Thread.sleep(a1.getTotalDuration());
291         runTestOnUiThread(new Runnable() {
292             @Override
293             public void run() {
294                 // a1 should finish by now.
295                 assertFalse(a1.isRunning());
296                 assertFalse(a1.isStarted());
297                 assertFalse(a1.isPaused());
298             }
299         });
300
301     }
302
303     @SmallTest
304     public void testPauseListener() throws Throwable {
305         MyPauseListener l1 = new MyPauseListener();
306         MyPauseListener l2 = new MyPauseListener();
307         a1.addPauseListener(l1);
308         a2.addPauseListener(l2);
309
310         assertFalse(l1.pauseCalled);
311         assertFalse(l1.resumeCalled);
312         assertFalse(l2.pauseCalled);
313         assertFalse(l2.resumeCalled);
314
315         runTestOnUiThread(new Runnable() {
316             @Override
317             public void run() {
318                 a1.start();
319                 a2.start();
320             }
321         });
322
323         Thread.sleep(a1.getTotalDuration() / 2);
324         a1.pause();
325
326         Thread.sleep(a2.getTotalDuration());
327
328         // Only a1's pause listener should be called.
329         assertTrue(l1.pauseCalled);
330         assertFalse(l1.resumeCalled);
331         a1.resume();
332
333         Thread.sleep(a1.getTotalDuration());
334
335         assertTrue(l1.pauseCalled);
336         assertTrue(l1.resumeCalled);
337         assertFalse(l2.pauseCalled);
338         assertFalse(l2.resumeCalled);
339     }
340
341     @SmallTest
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);
350
351         final long[] lastUpdate = new long[1];
352
353         runTestOnUiThread(new Runnable() {
354             @Override
355             public void run() {
356                 a1.start();
357             }
358         });
359
360         Thread.sleep(totalDuration / 2);
361
362         runTestOnUiThread(new Runnable() {
363             @Override
364             public void run() {
365                 assertTrue(l1.firstRunningFrameTime > 0);
366                 assertTrue(l1.lastUpdateTime > l1.firstRunningFrameTime);
367                 lastUpdate[0] = l1.lastUpdateTime;
368                 a1.pause();
369             }
370         });
371
372         Thread.sleep(totalDuration);
373
374         runTestOnUiThread(new Runnable() {
375             @Override
376             public void run() {
377                 // There should be no update after pause()
378                 assertEquals(lastUpdate[0], l1.lastUpdateTime);
379                 a1.resume();
380             }
381         });
382
383         do {
384             Thread.sleep(POLL_INTERVAL);
385             runTestOnUiThread(new Runnable() {
386                 @Override
387                 public void run() {
388                     assertTrue(l1.lastUpdateTime > lastUpdate[0]);
389                     lastUpdate[0] = l1.lastUpdateTime;
390                 }
391             });
392         } while (!a1.isStarted());
393
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);
398     }
399
400     @SmallTest
401     public void testEnd() throws Throwable {
402         final MyListener l1 = new MyListener();
403         final MyListener l2 = new MyListener();
404         a1.addListener(l1);
405         a2.addListener(l2);
406         a1.addListener(new MyListener() {
407             @Override
408             public void onAnimationEnd(Animator anim) {
409                 anim.cancel();
410             }
411         });
412         a2.addListener(new MyListener() {
413             @Override
414             public void onAnimationCancel(Animator anim) {
415                 anim.end();
416             }
417         });
418
419         runTestOnUiThread(new Runnable() {
420             @Override
421             public void run() {
422                 assertFalse(l1.cancelCalled);
423                 assertFalse(l1.endCalled);
424                 assertFalse(l2.cancelCalled);
425                 assertFalse(l2.endCalled);
426                 a1.start();
427                 a2.start();
428             }
429         });
430         Thread.sleep(POLL_INTERVAL);
431         runTestOnUiThread(new Runnable() {
432             @Override
433             public void run() {
434                 a1.end();
435                 a2.cancel();
436             }
437         });
438         Thread.sleep(POLL_INTERVAL);
439         runTestOnUiThread(new Runnable() {
440             @Override
441             public void run() {
442                 // Calling cancel from onAnimationEnd will be ignored.
443                 assertFalse(l1.cancelCalled);
444                 assertTrue(l1.endCalled);
445                 assertTrue(l2.cancelCalled);
446                 assertTrue(l2.endCalled);
447
448                 float value1 = (Float) a1.getAnimatedValue();
449                 int value2 = (Integer) a2.getAnimatedValue();
450                 assertEquals(A1_END_VALUE, value1);
451                 assertEquals(A2_END_VALUE, value2);
452             }
453         });
454
455     }
456
457     @SmallTest
458     public void testEndValue() throws Throwable {
459         final MyListener l1 = new MyListener();
460         a1.addListener(l1);
461
462         final MyListener l2 = new MyListener();
463         a2.addListener(l2);
464
465         runTestOnUiThread(new Runnable() {
466             @Override
467             public void run() {
468                 a1.start();
469                 a2.start();
470             }
471         });
472
473         Thread.sleep(POLL_INTERVAL);
474         runTestOnUiThread(new Runnable() {
475             @Override
476             public void run() {
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());
482
483                 // Force a2 to end.
484                 a2.end();
485             }
486         });
487
488         Thread.sleep(a1.getTotalDuration());
489
490         runTestOnUiThread(new Runnable() {
491             @Override
492             public void run() {
493                 assertFalse(l1.cancelCalled);
494                 assertTrue(l1.endCalled);
495                 assertFalse(l2.cancelCalled);
496                 assertTrue(l2.endCalled);
497
498                 // By now a1 should have finished normally and a2 has skipped to the end, check
499                 // their end values.
500                 assertEquals(A1_END_VALUE, ((Float) (a1.getAnimatedValue())).floatValue());
501                 assertEquals(A2_END_VALUE, ((Integer) (a2.getAnimatedValue())).intValue());
502             }
503         });
504     }
505
506     @SmallTest
507     public void testUpdateListener() throws InterruptedException {
508
509         final MyFrameCallbackProvider provider = new MyFrameCallbackProvider();
510         long sleep = 0;
511         while (provider.mHandler == null) {
512             Thread.sleep(POLL_INTERVAL);
513             sleep += POLL_INTERVAL;
514             if (sleep > WAIT_TIME_OUT) {
515                 break;
516             }
517         }
518         // Either the looper has started, or timed out
519         assertNotNull(provider.mHandler);
520
521         final MyListener listener = new MyListener();
522         final MyUpdateListener l1 = new MyUpdateListener() {
523             @Override
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);
530                 } else {
531                     // First frame:
532                     assertTrue(listener.startCalled);
533                     assertTrue(listener.startTime > 0);
534                     assertTrue(currentTime - listener.startTime < frameDelay * 2);
535                 }
536                 super.onAnimationUpdate(animation);
537             }
538         };
539         a1.addUpdateListener(l1);
540         a1.addListener(listener);
541         a1.setStartDelay(100);
542
543         provider.mHandler.post(new Runnable() {
544             @Override
545             public void run() {
546                 AnimationHandler.getInstance().setProvider(provider);
547                 a1.start();
548             }
549         });
550         Thread.sleep(POLL_INTERVAL);
551         assertTrue(a1.isStarted());
552         Thread.sleep(a1.getTotalDuration() + TOLERANCE);
553         // Finished by now.
554         assertFalse(a1.isStarted());
555         assertTrue(listener.endTime > 0);
556
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());
560     }
561
562
563     @SmallTest
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() {
570             @Override
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.
575                 a0.cancel();
576                 a1.end();
577                 a3.end();
578                 a4.cancel();
579             }
580         };
581         a2.addListener(listener);
582
583         runTestOnUiThread(new Runnable() {
584             @Override
585             public void run() {
586                 a0.start();
587                 a1.start();
588                 a2.start();
589                 a3.start();
590                 a4.start();
591             }
592         });
593         runTestOnUiThread(new Runnable() {
594             @Override
595             public void run() {
596                 assertTrue(a0.isStarted());
597                 assertTrue(a1.isStarted());
598                 assertTrue(a2.isStarted());
599                 assertTrue(a3.isStarted());
600                 assertTrue(a4.isStarted());
601             }
602         });
603         Thread.sleep(POLL_INTERVAL);
604         runTestOnUiThread(new Runnable() {
605             @Override
606             public void run() {
607                 // End the animator that should be in the middle of the list.
608                 a2.end();
609             }
610         });
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());
618     }
619
620     @SmallTest
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;
628
629         // Extend duration so we have plenty of latitude to manipulate the animations when they
630         // are running.
631         a1.setDuration(1000);
632         a2.setDuration(1000);
633         a1.addListener(l1);
634         a2.addListener(l2);
635         a1.addUpdateListener(updateListener1);
636         a2.addUpdateListener(updateListener2);
637         TimeInterpolator interpolator = new LinearInterpolator();
638         a1.setInterpolator(interpolator);
639         a2.setInterpolator(interpolator);
640
641         runTestOnUiThread(new Runnable() {
642             @Override
643             public void run() {
644                 assertFalse(a1.isStarted());
645                 assertFalse(a1.isRunning());
646                 assertFalse(a2.isStarted());
647                 assertFalse(a2.isRunning());
648
649                 // Test isRunning() and isStarted() before and after seek
650                 a1.setCurrentFraction(a1StartFraction);
651                 a2.setCurrentFraction(a2StartFraction);
652
653                 assertFalse(a1.isStarted());
654                 assertFalse(a1.isRunning());
655                 assertFalse(a2.isStarted());
656                 assertFalse(a2.isRunning());
657             }
658         });
659         Thread.sleep(POLL_INTERVAL);
660
661         // Start animation and seek during the animation.
662         runTestOnUiThread(new Runnable() {
663             @Override
664             public void run() {
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());
671
672                 a1.start();
673                 a2.start();
674             }
675         });
676
677         Thread.sleep(POLL_INTERVAL);
678         final float halfwayFraction = 0.5f;
679         runTestOnUiThread(new Runnable() {
680             @Override
681             public void run() {
682                 assertTrue(l1.startCalled);
683                 assertTrue(l2.startCalled);
684                 assertFalse(l1.endCalled);
685                 assertFalse(l2.endCalled);
686
687                 // Check whether the animations start from the seeking fraction
688                 assertTrue(updateListener1.startFraction >= a1StartFraction);
689                 assertTrue(updateListener2.startFraction >= a2StartFraction);
690
691                 assertTrue(a1.isStarted());
692                 assertTrue(a1.isRunning());
693                 assertTrue(a2.isStarted());
694                 assertTrue(a2.isRunning());
695
696                 a1.setCurrentFraction(halfwayFraction);
697                 a2.setCurrentFraction(halfwayFraction);
698             }
699         });
700
701         Thread.sleep(POLL_INTERVAL);
702
703         // Check that seeking during running doesn't change animation's internal state
704         runTestOnUiThread(new Runnable() {
705             @Override
706             public void run() {
707                 assertTrue(l1.startCalled);
708                 assertTrue(l2.startCalled);
709                 assertFalse(l1.endCalled);
710                 assertFalse(l2.endCalled);
711
712                 assertTrue(a1.isStarted());
713                 assertTrue(a1.isRunning());
714                 assertTrue(a2.isStarted());
715                 assertTrue(a2.isRunning());
716             }
717         });
718
719         // Wait until the animators finish successfully.
720         long wait = Math.max(a1.getTotalDuration(), a2.getTotalDuration());
721         Thread.sleep(wait);
722
723         runTestOnUiThread(new Runnable() {
724             @Override
725             public void run() {
726                 // Verify that the animators have finished.
727                 assertTrue(l1.endCalled);
728                 assertTrue(l2.endCalled);
729
730                 assertFalse(a1.isStarted());
731                 assertFalse(a2.isStarted());
732                 assertFalse(a1.isRunning());
733                 assertFalse(a2.isRunning());
734             }
735         });
736
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() {
741             @Override
742             public void run() {
743                 a1.start();
744             }
745         });
746
747         Thread.sleep(POLL_INTERVAL);
748         runTestOnUiThread(new Runnable() {
749             @Override
750             public void run() {
751                 assertTrue(updateListener1.wasRunning);
752                 assertTrue(updateListener1.startFraction >= 0);
753                 assertTrue(updateListener1.startFraction < halfwayFraction);
754                 a1.end();
755             }
756         });
757
758     }
759
760     @SmallTest
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();
765         a1.addListener(l1);
766         a2.addListener(l2);
767         runTestOnUiThread(new Runnable() {
768             @Override
769             public void run() {
770                 assertFalse(l1.startCalled);
771                 assertFalse(l2.startCalled);
772                 assertEquals(0f, a1.getAnimatedFraction());
773                 assertEquals(0f, a2.getAnimatedFraction());
774                 a1.start();
775                 a2.start();
776             }
777         });
778         Thread.sleep(POLL_INTERVAL);
779         runTestOnUiThread(new Runnable() {
780             @Override
781             public void run() {
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);
789             }
790         });
791         Thread.sleep(POLL_INTERVAL);
792         runTestOnUiThread(new Runnable() {
793             @Override
794             public void run() {
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());
799             }
800         });
801
802         Thread.sleep(a1.getTotalDuration());
803         runTestOnUiThread(new Runnable() {
804             @Override
805             public void run() {
806                 // By now a1 should finish also.
807                 assertTrue(l1.endCalled);
808                 assertEquals(1f, a1.getAnimatedFraction());
809             }
810         });
811     }
812
813     @SmallTest
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.
819
820         a1.setStartDelay(20);
821
822         // First start a1's first run.
823         final MyListener normalEndingListener = new MyListener();
824         a1.addListener(normalEndingListener);
825         runTestOnUiThread(new Runnable() {
826             @Override
827             public void run() {
828                 assertFalse(a1.isStarted());
829                 assertFalse(normalEndingListener.startCalled);
830                 assertFalse(normalEndingListener.endCalled);
831                 // Start normally
832                 a1.start();
833             }
834         });
835
836         Thread.sleep(a1.getTotalDuration() + POLL_INTERVAL);
837
838         // a1 should have finished by now.
839         runTestOnUiThread(new Runnable() {
840             @Override
841             public void run() {
842                 // Call end() on both a1 and a2 without calling start()
843                 final MyListener l1 = new MyListener();
844                 a1.addListener(l1);
845                 final MyListener l2 = new MyListener();
846                 a2.addListener(l2);
847
848                 assertFalse(a1.isStarted());
849                 assertFalse(l1.startCalled);
850                 assertFalse(l1.endCalled);
851                 assertFalse(a2.isStarted());
852                 assertFalse(l2.startCalled);
853                 assertFalse(l1.endCalled);
854
855                 a1.end();
856                 a2.end();
857
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);
863
864                 assertTrue(l2.startCalled);
865                 assertTrue(l2.endCalled);
866                 assertFalse(a2.isStarted());
867                 assertTrue(l2.endTime >= l1.startTime);
868             }
869         });
870     }
871
872     @SmallTest
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.
876         a1.setDuration(0);
877         a2.setDuration(0);
878
879         // Set a fraction on an animation with 0-duration
880         final ValueAnimator a3 = ValueAnimator.ofInt(0, 100);
881         a3.setDuration(0);
882         a3.setCurrentFraction(1.0f);
883         assertEquals(1.0f, a3.getAnimatedFraction());
884
885         final MyListener l1 = new MyListener();
886         final MyListener l2 = new MyListener();
887         final MyListener l3 = new MyListener();
888         a1.addListener(l1);
889         a2.addListener(l2);
890         a3.addListener(l3);
891         runTestOnUiThread(new Runnable() {
892             @Override
893             public void run() {
894                 assertFalse(l1.startCalled);
895                 assertFalse(l2.startCalled);
896                 assertFalse(l3.startCalled);
897                 assertFalse(l1.endCalled);
898                 assertFalse(l2.endCalled);
899                 assertFalse(l3.endCalled);
900                 a1.start();
901                 a2.reverse();
902                 a3.start();
903             }
904         });
905         Thread.sleep(POLL_INTERVAL);
906         runTestOnUiThread(new Runnable() {
907             @Override
908             public void run() {
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());
922             }
923         });
924     }
925
926     @SmallTest
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);
931
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();
936         a1.addListener(l1);
937         a2.addListener(l2);
938
939         runTestOnUiThread(new Runnable() {
940             @Override
941             public void run() {
942                 assertFalse(l1.startCalled);
943                 assertFalse(l2.startCalled);
944                 assertFalse(l1.endCalled);
945                 assertFalse(l2.endCalled);
946
947                 a1.start();
948                 a2.start();
949             }
950         });
951         Thread.sleep(POLL_INTERVAL);
952
953         runTestOnUiThread(new Runnable() {
954             @Override
955             public void run() {
956                 assertTrue(l1.startCalled);
957                 assertTrue(l2.startCalled);
958                 assertTrue(l1.endCalled);
959                 assertTrue(l2.endCalled);
960             }
961         });
962
963         // Restore duration scale
964         ValueAnimator.setDurationScale(scale);
965     }
966
967     @SmallTest
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);
971         a1.setDuration(400);
972         a2.setDuration(600);
973         a3.setDuration(400);
974         final MyListener l1 = new MyListener();
975         final MyListener l2 = new MyListener();
976         final MyListener l3 = new MyListener();
977         a1.addListener(l1);
978         a2.addListener(l2);
979         a3.addListener(l3);
980
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() {
984             @Override
985             public void run() {
986                 assertFalse(l1.startCalled);
987                 assertFalse(l2.startCalled);
988                 assertFalse(l3.startCalled);
989                 assertFalse(l1.endCalled);
990                 assertFalse(l2.endCalled);
991                 assertFalse(l3.endCalled);
992                 a1.reverse();
993                 a2.reverse();
994                 a3.reverse();
995             }
996         });
997         Thread.sleep(POLL_INTERVAL);
998         runTestOnUiThread(new Runnable() {
999             @Override
1000             public void run() {
1001                 assertTrue(l1.startCalled);
1002                 assertTrue(l2.startCalled);
1003                 assertTrue(l3.startCalled);
1004
1005                 a1.setCurrentFraction(0f);
1006                 a2.setCurrentFraction(1f);
1007                 a3.end();
1008
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());
1012             }
1013         });
1014         Thread.sleep(POLL_INTERVAL);
1015
1016         // By now, a2 should have finished due to the seeking. It wouldn't have finished otherwise.
1017         runTestOnUiThread(new Runnable() {
1018             @Override
1019             public void run() {
1020                 // Check that both animations have started, and a2 has finished.
1021                 assertFalse(l1.endCalled);
1022                 assertTrue(l2.endCalled);
1023                 assertTrue(l3.endCalled);
1024             }
1025         });
1026         Thread.sleep(a1.getTotalDuration());
1027
1028         runTestOnUiThread(new Runnable() {
1029             @Override
1030             public void run() {
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());
1036             }
1037         });
1038     }
1039
1040     class MyUpdateListener implements ValueAnimator.AnimatorUpdateListener {
1041         boolean wasRunning = false;
1042         long firstRunningFrameTime = -1;
1043         long lastUpdateTime = -1;
1044         float startFraction = 0;
1045
1046         @Override
1047         public void onAnimationUpdate(ValueAnimator animation) {
1048             lastUpdateTime = SystemClock.uptimeMillis();
1049             if (animation.isRunning() && !wasRunning) {
1050                 // Delay has passed
1051                 firstRunningFrameTime = lastUpdateTime;
1052                 startFraction = animation.getAnimatedFraction();
1053                 wasRunning = animation.isRunning();
1054             }
1055         }
1056
1057         void reset() {
1058             wasRunning = false;
1059             firstRunningFrameTime = -1;
1060             lastUpdateTime = -1;
1061             startFraction = 0;
1062         }
1063     }
1064
1065     class MyListener implements Animator.AnimatorListener {
1066         boolean startCalled = false;
1067         boolean cancelCalled = false;
1068         boolean endCalled = false;
1069         long startTime = -1;
1070         long endTime = -1;
1071
1072         @Override
1073         public void onAnimationStart(Animator animation) {
1074             startCalled = true;
1075             startTime = SystemClock.uptimeMillis();
1076         }
1077
1078         @Override
1079         public void onAnimationEnd(Animator animation) {
1080             endCalled = true;
1081             endTime = SystemClock.uptimeMillis();
1082         }
1083
1084         @Override
1085         public void onAnimationCancel(Animator animation) {
1086             cancelCalled = true;
1087         }
1088
1089         @Override
1090         public void onAnimationRepeat(Animator animation) {
1091
1092         }
1093     }
1094
1095     class MyPauseListener implements Animator.AnimatorPauseListener {
1096         boolean pauseCalled = false;
1097         boolean resumeCalled = false;
1098
1099         @Override
1100         public void onAnimationPause(Animator animation) {
1101             pauseCalled = true;
1102         }
1103
1104         @Override
1105         public void onAnimationResume(Animator animation) {
1106             resumeCalled = true;
1107         }
1108     }
1109
1110     class MyFrameCallbackProvider implements AnimationHandler.AnimationFrameCallbackProvider {
1111
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<>();
1116
1117         final LooperThread mThread = new LooperThread();
1118
1119         public MyFrameCallbackProvider() {
1120             mThread.start();
1121         }
1122
1123         @Override
1124         public void postFrameCallback(Choreographer.FrameCallback callback) {
1125             mHandler.sendEmptyMessageDelayed(MSG_FRAME, mFrameDelay);
1126             if (!mFrameCallbacks.contains(callback)) {
1127                 mFrameCallbacks.add(callback);
1128             }
1129         }
1130
1131         @Override
1132         public void postCommitCallback(Runnable runnable) {
1133             // Run the runnable after a commit delay
1134             mHandler.postDelayed(runnable, COMMIT_DELAY);
1135         }
1136
1137         @Override
1138         public long getFrameTime() {
1139             return SystemClock.uptimeMillis();
1140         }
1141
1142         @Override
1143         public long getFrameDelay() {
1144             return mFrameDelay;
1145         }
1146
1147         @Override
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);
1153             }
1154         }
1155
1156         class LooperThread extends Thread {
1157             public void run() {
1158                 Looper.prepare();
1159                 mHandler = new Handler() {
1160                     public void handleMessage(Message msg) {
1161                         // Handle message here.
1162                         switch (msg.what) {
1163                             case MSG_FRAME:
1164                                 for (int i = 0; i < mFrameCallbacks.size(); i++) {
1165                                     mFrameCallbacks.get(i).doFrame(SystemClock.uptimeMillis());
1166                                 }
1167                                 break;
1168                             default:
1169                                 break;
1170                         }
1171                     }
1172                 };
1173                 Looper.loop();
1174             }
1175         }
1176     }
1177 }