blob: b908d92673193201a840f7c5c5cafbe3b77b2605 [file] [log] [blame]
Doris Liube5a8ac2015-08-14 15:11:29 -07001/*
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*/
16package android.animation;
17
Doris Liu2822a422015-08-26 16:30:20 -070018import android.os.Handler;
19import android.os.Looper;
20import android.os.Message;
Doris Liube5a8ac2015-08-14 15:11:29 -070021import android.os.SystemClock;
22import android.test.ActivityInstrumentationTestCase2;
23import android.test.suitebuilder.annotation.SmallTest;
Doris Liu2822a422015-08-26 16:30:20 -070024import android.view.Choreographer;
25import android.view.animation.LinearInterpolator;
26
27import java.util.ArrayList;
Doris Liube5a8ac2015-08-14 15:11:29 -070028
Doris Liu435d2f72015-08-20 10:57:49 -070029import static android.test.MoreAsserts.assertNotEqual;
30
Doris Liube5a8ac2015-08-14 15:11:29 -070031public class ValueAnimatorTests extends ActivityInstrumentationTestCase2<BasicAnimatorActivity> {
Doris Liu2822a422015-08-26 16:30:20 -070032 private static final long WAIT_TIME_OUT = 5000;
Doris Liube5a8ac2015-08-14 15:11:29 -070033 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
Doris Liu435d2f72015-08-20 10:57:49 -070040 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
Doris Liu2822a422015-08-26 16:30:20 -070045 private final static long DEFAULT_FRAME_INTERVAL = 5; //ms
46 private final static long COMMIT_DELAY = 3; //ms
47
Doris Liube5a8ac2015-08-14 15:11:29 -070048 public ValueAnimatorTests() {
49 super(BasicAnimatorActivity.class);
50 }
51
52 @Override
53 public void setUp() throws Exception {
54 super.setUp();
Doris Liu435d2f72015-08-20 10:57:49 -070055 a1 = ValueAnimator.ofFloat(A1_START_VALUE, A1_END_VALUE).setDuration(300);
56 a2 = ValueAnimator.ofInt(A2_START_VALUE, A2_END_VALUE).setDuration(500);
Doris Liube5a8ac2015-08-14 15:11:29 -070057 }
58
59 @Override
60 public void tearDown() throws Exception {
Doris Liube5a8ac2015-08-14 15:11:29 -070061 a1 = null;
62 a2 = null;
Doris Liu2822a422015-08-26 16:30:20 -070063 super.tearDown();
Doris Liube5a8ac2015-08-14 15:11:29 -070064 }
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);
George Mounta06b3f12016-03-02 08:06:32 -0800331 runTestOnUiThread(new Runnable() {
332 @Override
333 public void run() {
334 a1.resume();
335 }
336 });
Doris Liube5a8ac2015-08-14 15:11:29 -0700337
338 Thread.sleep(a1.getTotalDuration());
339
340 assertTrue(l1.pauseCalled);
341 assertTrue(l1.resumeCalled);
342 assertFalse(l2.pauseCalled);
343 assertFalse(l2.resumeCalled);
344 }
345
346 @SmallTest
347 public void testResume() throws Throwable {
348 final MyUpdateListener l1 = new MyUpdateListener();
349 final long totalDuration = a1.getTotalDuration();
350 a1.addUpdateListener(l1);
351 // Set a longer duration on a1 for this test
352 a1.setDuration(1000);
353 assertTrue(l1.firstRunningFrameTime < 0);
354 assertTrue(l1.lastUpdateTime < 0);
355
356 final long[] lastUpdate = new long[1];
357
358 runTestOnUiThread(new Runnable() {
359 @Override
360 public void run() {
361 a1.start();
362 }
363 });
364
365 Thread.sleep(totalDuration / 2);
366
367 runTestOnUiThread(new Runnable() {
368 @Override
369 public void run() {
370 assertTrue(l1.firstRunningFrameTime > 0);
371 assertTrue(l1.lastUpdateTime > l1.firstRunningFrameTime);
372 lastUpdate[0] = l1.lastUpdateTime;
373 a1.pause();
374 }
375 });
376
377 Thread.sleep(totalDuration);
378
379 runTestOnUiThread(new Runnable() {
380 @Override
381 public void run() {
382 // There should be no update after pause()
383 assertEquals(lastUpdate[0], l1.lastUpdateTime);
384 a1.resume();
385 }
386 });
387
388 do {
389 Thread.sleep(POLL_INTERVAL);
390 runTestOnUiThread(new Runnable() {
391 @Override
392 public void run() {
393 assertTrue(l1.lastUpdateTime > lastUpdate[0]);
394 lastUpdate[0] = l1.lastUpdateTime;
395 }
396 });
397 } while (!a1.isStarted());
398
399 // Time between pause and resume: totalDuration
400 long entireSpan = totalDuration * 2;
401 long frameDelta = l1.lastUpdateTime - l1.firstRunningFrameTime;
402 assertTrue(Math.abs(entireSpan - frameDelta) < TOLERANCE);
403 }
404
Doris Liu435d2f72015-08-20 10:57:49 -0700405 @SmallTest
Doris Liu169cc4c2015-08-27 15:51:10 -0700406 public void testEnd() throws Throwable {
407 final MyListener l1 = new MyListener();
408 final MyListener l2 = new MyListener();
409 a1.addListener(l1);
410 a2.addListener(l2);
411 a1.addListener(new MyListener() {
412 @Override
413 public void onAnimationEnd(Animator anim) {
414 anim.cancel();
415 }
416 });
417 a2.addListener(new MyListener() {
418 @Override
419 public void onAnimationCancel(Animator anim) {
420 anim.end();
421 }
422 });
423
424 runTestOnUiThread(new Runnable() {
425 @Override
426 public void run() {
427 assertFalse(l1.cancelCalled);
428 assertFalse(l1.endCalled);
429 assertFalse(l2.cancelCalled);
430 assertFalse(l2.endCalled);
431 a1.start();
432 a2.start();
433 }
434 });
435 Thread.sleep(POLL_INTERVAL);
436 runTestOnUiThread(new Runnable() {
437 @Override
438 public void run() {
439 a1.end();
440 a2.cancel();
441 }
442 });
443 Thread.sleep(POLL_INTERVAL);
444 runTestOnUiThread(new Runnable() {
445 @Override
446 public void run() {
447 // Calling cancel from onAnimationEnd will be ignored.
448 assertFalse(l1.cancelCalled);
449 assertTrue(l1.endCalled);
450 assertTrue(l2.cancelCalled);
451 assertTrue(l2.endCalled);
452
453 float value1 = (Float) a1.getAnimatedValue();
454 int value2 = (Integer) a2.getAnimatedValue();
455 assertEquals(A1_END_VALUE, value1);
456 assertEquals(A2_END_VALUE, value2);
457 }
458 });
459
460 }
461
462 @SmallTest
Doris Liu435d2f72015-08-20 10:57:49 -0700463 public void testEndValue() throws Throwable {
464 final MyListener l1 = new MyListener();
465 a1.addListener(l1);
466
467 final MyListener l2 = new MyListener();
468 a2.addListener(l2);
469
470 runTestOnUiThread(new Runnable() {
471 @Override
472 public void run() {
473 a1.start();
474 a2.start();
475 }
476 });
477
478 Thread.sleep(POLL_INTERVAL);
479 runTestOnUiThread(new Runnable() {
480 @Override
481 public void run() {
482 // Animation has started but not finished, check animated values against end values
483 assertFalse(l1.endCalled);
484 assertFalse(l2.endCalled);
485 assertNotEqual(A1_END_VALUE, a1.getAnimatedValue());
486 assertNotEqual(A1_END_VALUE, a2.getAnimatedValue());
487
488 // Force a2 to end.
489 a2.end();
490 }
491 });
492
493 Thread.sleep(a1.getTotalDuration());
494
495 runTestOnUiThread(new Runnable() {
496 @Override
497 public void run() {
498 assertFalse(l1.cancelCalled);
499 assertTrue(l1.endCalled);
500 assertFalse(l2.cancelCalled);
501 assertTrue(l2.endCalled);
502
503 // By now a1 should have finished normally and a2 has skipped to the end, check
504 // their end values.
505 assertEquals(A1_END_VALUE, ((Float) (a1.getAnimatedValue())).floatValue());
506 assertEquals(A2_END_VALUE, ((Integer) (a2.getAnimatedValue())).intValue());
507 }
508 });
509 }
510
Doris Liu2822a422015-08-26 16:30:20 -0700511 @SmallTest
512 public void testUpdateListener() throws InterruptedException {
513
514 final MyFrameCallbackProvider provider = new MyFrameCallbackProvider();
515 long sleep = 0;
516 while (provider.mHandler == null) {
517 Thread.sleep(POLL_INTERVAL);
518 sleep += POLL_INTERVAL;
519 if (sleep > WAIT_TIME_OUT) {
520 break;
521 }
522 }
523 // Either the looper has started, or timed out
524 assertNotNull(provider.mHandler);
525
526 final MyListener listener = new MyListener();
527 final MyUpdateListener l1 = new MyUpdateListener() {
528 @Override
529 public void onAnimationUpdate(ValueAnimator animation) {
530 long currentTime = SystemClock.uptimeMillis();
531 long frameDelay = provider.getFrameDelay();
532 if (lastUpdateTime > 0) {
533 // Error tolerance here is one frame.
534 assertTrue((currentTime - lastUpdateTime) < frameDelay * 2);
535 } else {
536 // First frame:
537 assertTrue(listener.startCalled);
538 assertTrue(listener.startTime > 0);
539 assertTrue(currentTime - listener.startTime < frameDelay * 2);
540 }
541 super.onAnimationUpdate(animation);
542 }
543 };
544 a1.addUpdateListener(l1);
545 a1.addListener(listener);
546 a1.setStartDelay(100);
547
548 provider.mHandler.post(new Runnable() {
549 @Override
550 public void run() {
551 AnimationHandler.getInstance().setProvider(provider);
552 a1.start();
553 }
554 });
555 Thread.sleep(POLL_INTERVAL);
556 assertTrue(a1.isStarted());
557 Thread.sleep(a1.getTotalDuration() + TOLERANCE);
558 // Finished by now.
559 assertFalse(a1.isStarted());
560 assertTrue(listener.endTime > 0);
561
562 // Check the time difference between last frame and end time.
563 assertTrue(listener.endTime >= l1.lastUpdateTime);
564 assertTrue(listener.endTime - l1.lastUpdateTime < 2 * provider.getFrameDelay());
565 }
566
567
568 @SmallTest
569 public void testConcurrentModification() throws Throwable {
570 // Attempt to modify list of animations as the list is being iterated
571 final ValueAnimator a0 = ValueAnimator.ofInt(100, 200).setDuration(500);
572 final ValueAnimator a3 = ValueAnimator.ofFloat(0, 1).setDuration(500);
573 final ValueAnimator a4 = ValueAnimator.ofInt(200, 300).setDuration(500);
574 final MyListener listener = new MyListener() {
575 @Override
576 public void onAnimationEnd(Animator anim) {
577 super.onAnimationEnd(anim);
578 // AnimationHandler should be iterating the list at the moment, end/cancel all
579 // the other animations. No ConcurrentModificationException should happen.
580 a0.cancel();
581 a1.end();
582 a3.end();
583 a4.cancel();
584 }
585 };
586 a2.addListener(listener);
587
588 runTestOnUiThread(new Runnable() {
589 @Override
590 public void run() {
591 a0.start();
592 a1.start();
593 a2.start();
594 a3.start();
595 a4.start();
596 }
597 });
598 runTestOnUiThread(new Runnable() {
599 @Override
600 public void run() {
601 assertTrue(a0.isStarted());
602 assertTrue(a1.isStarted());
603 assertTrue(a2.isStarted());
604 assertTrue(a3.isStarted());
605 assertTrue(a4.isStarted());
606 }
607 });
608 Thread.sleep(POLL_INTERVAL);
609 runTestOnUiThread(new Runnable() {
610 @Override
611 public void run() {
612 // End the animator that should be in the middle of the list.
613 a2.end();
614 }
615 });
616 Thread.sleep(POLL_INTERVAL);
617 assertTrue(listener.endCalled);
618 assertFalse(a0.isStarted());
619 assertFalse(a1.isStarted());
620 assertFalse(a2.isStarted());
621 assertFalse(a3.isStarted());
622 assertFalse(a4.isStarted());
623 }
624
625 @SmallTest
Doris Liu68dcb302015-10-06 10:32:09 -0700626 public void testSeek() throws Throwable {
Doris Liu2822a422015-08-26 16:30:20 -0700627 final MyListener l1 = new MyListener();
628 final MyListener l2 = new MyListener();
629 final MyUpdateListener updateListener1 = new MyUpdateListener();
630 final MyUpdateListener updateListener2 = new MyUpdateListener();
631 final float a1StartFraction = 0.2f;
632 final float a2StartFraction = 0.3f;
633
634 // Extend duration so we have plenty of latitude to manipulate the animations when they
635 // are running.
636 a1.setDuration(1000);
637 a2.setDuration(1000);
638 a1.addListener(l1);
639 a2.addListener(l2);
640 a1.addUpdateListener(updateListener1);
641 a2.addUpdateListener(updateListener2);
642 TimeInterpolator interpolator = new LinearInterpolator();
643 a1.setInterpolator(interpolator);
644 a2.setInterpolator(interpolator);
645
646 runTestOnUiThread(new Runnable() {
647 @Override
648 public void run() {
649 assertFalse(a1.isStarted());
650 assertFalse(a1.isRunning());
651 assertFalse(a2.isStarted());
652 assertFalse(a2.isRunning());
653
654 // Test isRunning() and isStarted() before and after seek
655 a1.setCurrentFraction(a1StartFraction);
656 a2.setCurrentFraction(a2StartFraction);
657
658 assertFalse(a1.isStarted());
659 assertFalse(a1.isRunning());
660 assertFalse(a2.isStarted());
661 assertFalse(a2.isRunning());
662 }
663 });
664 Thread.sleep(POLL_INTERVAL);
665
666 // Start animation and seek during the animation.
667 runTestOnUiThread(new Runnable() {
668 @Override
669 public void run() {
670 assertFalse(a1.isStarted());
671 assertFalse(a1.isRunning());
672 assertFalse(a2.isStarted());
673 assertFalse(a2.isRunning());
674 assertEquals(a1StartFraction, a1.getAnimatedFraction());
675 assertEquals(a2StartFraction, a2.getAnimatedFraction());
676
677 a1.start();
678 a2.start();
679 }
680 });
681
682 Thread.sleep(POLL_INTERVAL);
683 final float halfwayFraction = 0.5f;
684 runTestOnUiThread(new Runnable() {
685 @Override
686 public void run() {
687 assertTrue(l1.startCalled);
688 assertTrue(l2.startCalled);
689 assertFalse(l1.endCalled);
690 assertFalse(l2.endCalled);
691
692 // Check whether the animations start from the seeking fraction
693 assertTrue(updateListener1.startFraction >= a1StartFraction);
694 assertTrue(updateListener2.startFraction >= a2StartFraction);
695
696 assertTrue(a1.isStarted());
697 assertTrue(a1.isRunning());
698 assertTrue(a2.isStarted());
699 assertTrue(a2.isRunning());
700
701 a1.setCurrentFraction(halfwayFraction);
702 a2.setCurrentFraction(halfwayFraction);
703 }
704 });
705
706 Thread.sleep(POLL_INTERVAL);
707
708 // Check that seeking during running doesn't change animation's internal state
709 runTestOnUiThread(new Runnable() {
710 @Override
711 public void run() {
712 assertTrue(l1.startCalled);
713 assertTrue(l2.startCalled);
714 assertFalse(l1.endCalled);
715 assertFalse(l2.endCalled);
716
717 assertTrue(a1.isStarted());
718 assertTrue(a1.isRunning());
719 assertTrue(a2.isStarted());
720 assertTrue(a2.isRunning());
721 }
722 });
723
724 // Wait until the animators finish successfully.
725 long wait = Math.max(a1.getTotalDuration(), a2.getTotalDuration());
726 Thread.sleep(wait);
727
728 runTestOnUiThread(new Runnable() {
729 @Override
730 public void run() {
731 // Verify that the animators have finished.
732 assertTrue(l1.endCalled);
733 assertTrue(l2.endCalled);
734
735 assertFalse(a1.isStarted());
736 assertFalse(a2.isStarted());
737 assertFalse(a1.isRunning());
738 assertFalse(a2.isRunning());
739 }
740 });
741
742 // Re-start animator a1 after it ends normally, and check that seek value from last run
743 // does not affect the new run.
744 updateListener1.reset();
745 runTestOnUiThread(new Runnable() {
746 @Override
747 public void run() {
748 a1.start();
749 }
750 });
751
752 Thread.sleep(POLL_INTERVAL);
753 runTestOnUiThread(new Runnable() {
754 @Override
755 public void run() {
756 assertTrue(updateListener1.wasRunning);
757 assertTrue(updateListener1.startFraction >= 0);
758 assertTrue(updateListener1.startFraction < halfwayFraction);
759 a1.end();
760 }
761 });
762
763 }
764
Doris Liu68dcb302015-10-06 10:32:09 -0700765 @SmallTest
766 public void testSeekWhileRunning() throws Throwable {
767 // Seek one animator to the beginning and the other one to the end when they are running.
768 final MyListener l1 = new MyListener();
769 final MyListener l2 = new MyListener();
770 a1.addListener(l1);
771 a2.addListener(l2);
772 runTestOnUiThread(new Runnable() {
773 @Override
774 public void run() {
775 assertFalse(l1.startCalled);
776 assertFalse(l2.startCalled);
777 assertEquals(0f, a1.getAnimatedFraction());
778 assertEquals(0f, a2.getAnimatedFraction());
779 a1.start();
780 a2.start();
781 }
782 });
783 Thread.sleep(POLL_INTERVAL);
784 runTestOnUiThread(new Runnable() {
785 @Override
786 public void run() {
787 assertFalse(l1.endCalled);
788 assertFalse(l2.endCalled);
789 assertTrue(a1.isRunning());
790 assertTrue(a2.isRunning());
791 // During the run, seek one to the beginning, the other to the end
792 a1.setCurrentFraction(0f);
793 a2.setCurrentFraction(1f);
794 }
795 });
796 Thread.sleep(POLL_INTERVAL);
797 runTestOnUiThread(new Runnable() {
798 @Override
799 public void run() {
800 // Check that a2 has finished due to the seeking, but a1 hasn't finished.
801 assertFalse(l1.endCalled);
802 assertTrue(l2.endCalled);
803 assertEquals(1f, a2.getAnimatedFraction());
804 }
805 });
806
807 Thread.sleep(a1.getTotalDuration());
808 runTestOnUiThread(new Runnable() {
809 @Override
810 public void run() {
811 // By now a1 should finish also.
812 assertTrue(l1.endCalled);
813 assertEquals(1f, a1.getAnimatedFraction());
814 }
815 });
816 }
817
818 @SmallTest
Doris Liu81963e32015-11-09 14:41:07 -0800819 public void testEndBeforeStart() throws Throwable {
820 // This test calls two animators that are not yet started. One animator has completed a
821 // previous run but hasn't started since then, the other one has never run. When end() is
822 // called on these two animators, we expected their animation listeners to receive both
823 // onAnimationStarted(Animator) and onAnimationEnded(Animator) callbacks, in that sequence.
824
825 a1.setStartDelay(20);
826
827 // First start a1's first run.
828 final MyListener normalEndingListener = new MyListener();
829 a1.addListener(normalEndingListener);
830 runTestOnUiThread(new Runnable() {
831 @Override
832 public void run() {
833 assertFalse(a1.isStarted());
834 assertFalse(normalEndingListener.startCalled);
835 assertFalse(normalEndingListener.endCalled);
836 // Start normally
837 a1.start();
838 }
839 });
840
841 Thread.sleep(a1.getTotalDuration() + POLL_INTERVAL);
842
843 // a1 should have finished by now.
844 runTestOnUiThread(new Runnable() {
845 @Override
846 public void run() {
847 // Call end() on both a1 and a2 without calling start()
848 final MyListener l1 = new MyListener();
849 a1.addListener(l1);
850 final MyListener l2 = new MyListener();
851 a2.addListener(l2);
852
853 assertFalse(a1.isStarted());
854 assertFalse(l1.startCalled);
855 assertFalse(l1.endCalled);
856 assertFalse(a2.isStarted());
857 assertFalse(l2.startCalled);
858 assertFalse(l1.endCalled);
859
860 a1.end();
861 a2.end();
862
863 // Check that both animators' listeners have received the animation callbacks.
864 assertTrue(l1.startCalled);
865 assertTrue(l1.endCalled);
866 assertFalse(a1.isStarted());
867 assertTrue(l1.endTime >= l1.startTime);
868
869 assertTrue(l2.startCalled);
870 assertTrue(l2.endCalled);
871 assertFalse(a2.isStarted());
872 assertTrue(l2.endTime >= l1.startTime);
873 }
874 });
875 }
876
877 @SmallTest
Doris Liu68dcb302015-10-06 10:32:09 -0700878 public void testZeroDuration() throws Throwable {
879 // Run two animators with zero duration, with one running forward and the other one
880 // backward. Check that the animations start and finish with the correct end fractions.
881 a1.setDuration(0);
882 a2.setDuration(0);
883
884 // Set a fraction on an animation with 0-duration
885 final ValueAnimator a3 = ValueAnimator.ofInt(0, 100);
886 a3.setDuration(0);
887 a3.setCurrentFraction(1.0f);
888 assertEquals(1.0f, a3.getAnimatedFraction());
889
890 final MyListener l1 = new MyListener();
891 final MyListener l2 = new MyListener();
892 final MyListener l3 = new MyListener();
893 a1.addListener(l1);
894 a2.addListener(l2);
895 a3.addListener(l3);
896 runTestOnUiThread(new Runnable() {
897 @Override
898 public void run() {
899 assertFalse(l1.startCalled);
900 assertFalse(l2.startCalled);
901 assertFalse(l3.startCalled);
902 assertFalse(l1.endCalled);
903 assertFalse(l2.endCalled);
904 assertFalse(l3.endCalled);
905 a1.start();
906 a2.reverse();
907 a3.start();
Doris Liu40428c82016-02-25 18:37:06 -0800908 // Check that the animators' values are immediately set to end value in the case of
909 // 0-duration.
910 assertEquals(A1_END_VALUE, a1.getAnimatedValue());
911 assertEquals(A2_START_VALUE, a2.getAnimatedValue());
Doris Liu68dcb302015-10-06 10:32:09 -0700912 }
913 });
914 Thread.sleep(POLL_INTERVAL);
915 runTestOnUiThread(new Runnable() {
916 @Override
917 public void run() {
918 // Check that the animators have started and finished with the right values.
919 assertTrue(l1.startCalled);
920 assertTrue(l2.startCalled);
921 assertTrue(l3.startCalled);
922 assertTrue(l1.endCalled);
923 assertTrue(l2.endCalled);
924 assertTrue(l3.endCalled);
925 assertEquals(1.0f, a1.getAnimatedFraction());
926 assertEquals(0f, a2.getAnimatedFraction());
927 assertEquals(1f, a3.getAnimatedFraction());
928 assertEquals(A1_END_VALUE, a1.getAnimatedValue());
929 assertEquals(A2_START_VALUE, a2.getAnimatedValue());
930 assertEquals(100, a3.getAnimatedValue());
931 }
932 });
933 }
934
935 @SmallTest
Doris Liua0942e22015-10-12 17:25:08 -0700936 public void testZeroScale() throws Throwable {
937 // Test whether animations would end properly when the scale is forced to be zero
938 float scale = ValueAnimator.getDurationScale();
939 ValueAnimator.setDurationScale(0f);
940
941 // Run two animators, one of which has a start delay, after setting the duration scale to 0
942 a1.setStartDelay(200);
943 final MyListener l1 = new MyListener();
944 final MyListener l2 = new MyListener();
945 a1.addListener(l1);
946 a2.addListener(l2);
947
948 runTestOnUiThread(new Runnable() {
949 @Override
950 public void run() {
951 assertFalse(l1.startCalled);
952 assertFalse(l2.startCalled);
953 assertFalse(l1.endCalled);
954 assertFalse(l2.endCalled);
955
956 a1.start();
957 a2.start();
Doris Liu40428c82016-02-25 18:37:06 -0800958
959 // In the case of 0 duration scale applied to a non-0 duration, check that the
960 // value is immediately set to the start value.
961 assertEquals(A2_START_VALUE, a2.getAnimatedValue());
Doris Liua0942e22015-10-12 17:25:08 -0700962 }
963 });
964 Thread.sleep(POLL_INTERVAL);
965
966 runTestOnUiThread(new Runnable() {
967 @Override
968 public void run() {
969 assertTrue(l1.startCalled);
970 assertTrue(l2.startCalled);
971 assertTrue(l1.endCalled);
972 assertTrue(l2.endCalled);
Doris Liu40428c82016-02-25 18:37:06 -0800973 assertEquals(A1_END_VALUE, a1.getAnimatedValue());
974 assertEquals(A2_END_VALUE, a2.getAnimatedValue());
Doris Liua0942e22015-10-12 17:25:08 -0700975 }
976 });
977
978 // Restore duration scale
979 ValueAnimator.setDurationScale(scale);
980 }
981
982 @SmallTest
Doris Liu68dcb302015-10-06 10:32:09 -0700983 public void testReverse() throws Throwable {
984 // Prolong animators duration so that we can do multiple checks during their run
985 final ValueAnimator a3 = ValueAnimator.ofInt(0, 100);
986 a1.setDuration(400);
987 a2.setDuration(600);
988 a3.setDuration(400);
989 final MyListener l1 = new MyListener();
990 final MyListener l2 = new MyListener();
991 final MyListener l3 = new MyListener();
992 a1.addListener(l1);
993 a2.addListener(l2);
994 a3.addListener(l3);
995
996 // Reverse three animators, seek one to the beginning and another to the end, and force
997 // to end the third one during reversing.
998 runTestOnUiThread(new Runnable() {
999 @Override
1000 public void run() {
1001 assertFalse(l1.startCalled);
1002 assertFalse(l2.startCalled);
1003 assertFalse(l3.startCalled);
1004 assertFalse(l1.endCalled);
1005 assertFalse(l2.endCalled);
1006 assertFalse(l3.endCalled);
1007 a1.reverse();
1008 a2.reverse();
1009 a3.reverse();
1010 }
1011 });
1012 Thread.sleep(POLL_INTERVAL);
1013 runTestOnUiThread(new Runnable() {
1014 @Override
1015 public void run() {
1016 assertTrue(l1.startCalled);
1017 assertTrue(l2.startCalled);
1018 assertTrue(l3.startCalled);
1019
1020 a1.setCurrentFraction(0f);
1021 a2.setCurrentFraction(1f);
1022 a3.end();
1023
1024 // Check that the fraction has been set, and the getter returns the correct values.
1025 assertEquals(1f, a1.getAnimatedFraction());
1026 assertEquals(0f, a2.getAnimatedFraction());
1027 }
1028 });
1029 Thread.sleep(POLL_INTERVAL);
1030
1031 // By now, a2 should have finished due to the seeking. It wouldn't have finished otherwise.
1032 runTestOnUiThread(new Runnable() {
1033 @Override
1034 public void run() {
1035 // Check that both animations have started, and a2 has finished.
1036 assertFalse(l1.endCalled);
1037 assertTrue(l2.endCalled);
1038 assertTrue(l3.endCalled);
1039 }
1040 });
1041 Thread.sleep(a1.getTotalDuration());
1042
1043 runTestOnUiThread(new Runnable() {
1044 @Override
1045 public void run() {
1046 // Verify that a1 has finished as well.
1047 assertTrue(l1.endCalled);
1048 assertEquals(0f, a1.getAnimatedFraction());
1049 assertEquals(0f, a2.getAnimatedFraction());
1050 assertEquals(0f, a3.getAnimatedFraction());
1051 }
1052 });
1053 }
1054
Doris Liube5a8ac2015-08-14 15:11:29 -07001055 class MyUpdateListener implements ValueAnimator.AnimatorUpdateListener {
1056 boolean wasRunning = false;
1057 long firstRunningFrameTime = -1;
1058 long lastUpdateTime = -1;
Doris Liu2822a422015-08-26 16:30:20 -07001059 float startFraction = 0;
Doris Liube5a8ac2015-08-14 15:11:29 -07001060
1061 @Override
1062 public void onAnimationUpdate(ValueAnimator animation) {
1063 lastUpdateTime = SystemClock.uptimeMillis();
1064 if (animation.isRunning() && !wasRunning) {
1065 // Delay has passed
1066 firstRunningFrameTime = lastUpdateTime;
Doris Liu2822a422015-08-26 16:30:20 -07001067 startFraction = animation.getAnimatedFraction();
Doris Liube5a8ac2015-08-14 15:11:29 -07001068 wasRunning = animation.isRunning();
1069 }
1070 }
Doris Liu2822a422015-08-26 16:30:20 -07001071
1072 void reset() {
1073 wasRunning = false;
1074 firstRunningFrameTime = -1;
1075 lastUpdateTime = -1;
1076 startFraction = 0;
1077 }
Doris Liube5a8ac2015-08-14 15:11:29 -07001078 }
1079
1080 class MyListener implements Animator.AnimatorListener {
1081 boolean startCalled = false;
1082 boolean cancelCalled = false;
1083 boolean endCalled = false;
Doris Liu2822a422015-08-26 16:30:20 -07001084 long startTime = -1;
1085 long endTime = -1;
Doris Liube5a8ac2015-08-14 15:11:29 -07001086
1087 @Override
1088 public void onAnimationStart(Animator animation) {
1089 startCalled = true;
Doris Liu2822a422015-08-26 16:30:20 -07001090 startTime = SystemClock.uptimeMillis();
Doris Liube5a8ac2015-08-14 15:11:29 -07001091 }
1092
1093 @Override
1094 public void onAnimationEnd(Animator animation) {
1095 endCalled = true;
Doris Liu2822a422015-08-26 16:30:20 -07001096 endTime = SystemClock.uptimeMillis();
Doris Liube5a8ac2015-08-14 15:11:29 -07001097 }
1098
1099 @Override
1100 public void onAnimationCancel(Animator animation) {
1101 cancelCalled = true;
1102 }
1103
1104 @Override
1105 public void onAnimationRepeat(Animator animation) {
1106
1107 }
1108 }
1109
1110 class MyPauseListener implements Animator.AnimatorPauseListener {
1111 boolean pauseCalled = false;
1112 boolean resumeCalled = false;
1113
1114 @Override
1115 public void onAnimationPause(Animator animation) {
1116 pauseCalled = true;
1117 }
1118
1119 @Override
1120 public void onAnimationResume(Animator animation) {
1121 resumeCalled = true;
1122 }
1123 }
Doris Liu2822a422015-08-26 16:30:20 -07001124
1125 class MyFrameCallbackProvider implements AnimationHandler.AnimationFrameCallbackProvider {
1126
1127 Handler mHandler = null;
1128 private final static int MSG_FRAME = 0;
1129 private long mFrameDelay = DEFAULT_FRAME_INTERVAL;
1130 private ArrayList<Choreographer.FrameCallback> mFrameCallbacks = new ArrayList<>();
1131
1132 final LooperThread mThread = new LooperThread();
1133
1134 public MyFrameCallbackProvider() {
1135 mThread.start();
1136 }
1137
1138 @Override
1139 public void postFrameCallback(Choreographer.FrameCallback callback) {
1140 mHandler.sendEmptyMessageDelayed(MSG_FRAME, mFrameDelay);
1141 if (!mFrameCallbacks.contains(callback)) {
1142 mFrameCallbacks.add(callback);
1143 }
1144 }
1145
1146 @Override
1147 public void postCommitCallback(Runnable runnable) {
1148 // Run the runnable after a commit delay
1149 mHandler.postDelayed(runnable, COMMIT_DELAY);
1150 }
1151
1152 @Override
1153 public long getFrameTime() {
1154 return SystemClock.uptimeMillis();
1155 }
1156
1157 @Override
1158 public long getFrameDelay() {
1159 return mFrameDelay;
1160 }
1161
1162 @Override
1163 public void setFrameDelay(long delay) {
1164 mFrameDelay = delay;
1165 if (mFrameCallbacks.size() != 0) {
1166 mHandler.removeMessages(MSG_FRAME);
1167 mHandler.sendEmptyMessageDelayed(MSG_FRAME, mFrameDelay);
1168 }
1169 }
1170
1171 class LooperThread extends Thread {
1172 public void run() {
1173 Looper.prepare();
1174 mHandler = new Handler() {
1175 public void handleMessage(Message msg) {
1176 // Handle message here.
1177 switch (msg.what) {
1178 case MSG_FRAME:
1179 for (int i = 0; i < mFrameCallbacks.size(); i++) {
1180 mFrameCallbacks.get(i).doFrame(SystemClock.uptimeMillis());
1181 }
1182 break;
1183 default:
1184 break;
1185 }
1186 }
1187 };
1188 Looper.loop();
1189 }
1190 }
1191 }
Doris Liube5a8ac2015-08-14 15:11:29 -07001192}