1 package android.animation; 2 3 import com.android.frameworks.coretests.R; 4 5 import android.test.ActivityInstrumentationTestCase2; 6 import android.test.UiThreadTest; 7 import android.test.suitebuilder.annotation.SmallTest; 8 import android.view.View; 9 10 import java.util.ArrayList; 11 12 public class AnimatorSetActivityTest extends ActivityInstrumentationTestCase2<AnimatorSetActivity> { 13 14 private static final long POLL_INTERVAL = 100; // ms 15 private AnimatorSetActivity mActivity; 16 private ObjectAnimator a1,a2,a3; 17 private ValueAnimator a4,a5; 18 19 public AnimatorSetActivityTest() { 20 super(AnimatorSetActivity.class); 21 } 22 23 static class MyListener implements Animator.AnimatorListener { 24 boolean startIsCalled = false; 25 boolean endIsCalled = false; 26 boolean cancelIsCalled = false; 27 28 @Override 29 public void onAnimationStart(Animator animation) { 30 startIsCalled = true; 31 } 32 33 @Override 34 public void onAnimationEnd(Animator animation) { 35 endIsCalled = true; 36 } 37 38 @Override 39 public void onAnimationCancel(Animator animation) { 40 cancelIsCalled = true; 41 } 42 43 @Override 44 public void onAnimationRepeat(Animator animation) { 45 46 } 47 } 48 49 @Override 50 public void setUp() throws Exception { 51 super.setUp(); 52 mActivity = getActivity(); 53 54 View square1 = mActivity.findViewById(R.id.square1); 55 View square2 = mActivity.findViewById(R.id.square2); 56 View square3 = mActivity.findViewById(R.id.square3); 57 a1 = ObjectAnimator.ofFloat(square1, View.TRANSLATION_X, 0f, 500f, 0f).setDuration(250); 58 a2 = ObjectAnimator.ofFloat(square2, View.ALPHA, 1f, 0f).setDuration(350); 59 a3 = ObjectAnimator.ofFloat(square3, View.ROTATION, 0, 90).setDuration(450); 60 a4 = ValueAnimator.ofInt(100, 200).setDuration(450); 61 a5 = ValueAnimator.ofFloat(10f, 5f).setDuration(850); 62 } 63 64 @Override 65 public void tearDown() throws Exception { 66 mActivity = null; 67 a1 = null; 68 a2 = null; 69 a3 = null; 70 a4 = null; 71 a5 = null; 72 super.tearDown(); 73 } 74 75 @SmallTest 76 public void testGetChildAnimations() { 77 AnimatorSet s1 = new AnimatorSet(); 78 s1.playTogether(a1, a2, a3); 79 ArrayList<Animator> children = s1.getChildAnimations(); 80 assertEquals(3, children.size()); 81 assertTrue(children.contains(a1)); 82 assertTrue(children.contains(a2)); 83 assertTrue(children.contains(a3)); 84 85 AnimatorSet s2 = new AnimatorSet(); 86 s2.playSequentially(a1, a2, a3); 87 children = s2.getChildAnimations(); 88 assertEquals(3, children.size()); 89 assertTrue(children.contains(a1)); 90 assertTrue(children.contains(a2)); 91 assertTrue(children.contains(a3)); 92 93 AnimatorSet s3 = new AnimatorSet(); 94 s3.play(a1).before(a2).after(s1).with(s2).after(a3); 95 ArrayList<Animator> s3Children = s3.getChildAnimations(); 96 assertNotNull(s3Children); 97 assertEquals(5, s3Children.size()); 98 assertTrue(s3Children.contains(a1)); 99 assertTrue(s3Children.contains(a2)); 100 assertTrue(s3Children.contains(a3)); 101 assertTrue(s3Children.contains(s1)); 102 assertTrue(s3Children.contains(s2)); 103 104 AnimatorSet s4 = new AnimatorSet(); 105 s4.playSequentially(s3Children); 106 ArrayList<Animator> s4Children = s4.getChildAnimations(); 107 assertNotNull(s4Children); 108 assertEquals(s3Children.size(), s4Children.size()); 109 for (int i = 0; i < s3Children.size(); i++) { 110 Animator child = s3Children.get(i); 111 assertTrue(s4Children.contains(child)); 112 } 113 } 114 115 @SmallTest 116 public void testTotalDuration() { 117 ArrayList<Animator> list = getAnimatorList(); 118 119 // Run animations sequentially and test the total duration against sum of durations. 120 AnimatorSet s1 = new AnimatorSet(); 121 s1.playSequentially(list); 122 long totalDuration = 0; 123 for (int i = 0; i < list.size(); i++) { 124 Animator anim = list.get(i); 125 anim.setStartDelay(0); 126 totalDuration += list.get(i).getDuration(); 127 } 128 assertEquals(totalDuration, s1.getTotalDuration()); 129 130 // Add delay to set, and test total duration 131 s1.setStartDelay(200); 132 assertEquals(totalDuration + 200, s1.getTotalDuration()); 133 134 a1.setStartDelay(100); 135 assertEquals(totalDuration + 200 + 100, s1.getTotalDuration()); 136 137 // Run animations simultaneously, test the total duration against the longest duration 138 AnimatorSet s2 = new AnimatorSet(); 139 s2.playTogether(list); 140 long maxDuration = 0; 141 for (int i = 0; i < list.size(); i++) { 142 long duration = list.get(i).getDuration(); 143 list.get(i).setStartDelay(100); 144 maxDuration = maxDuration > (duration + 100) ? maxDuration : (duration + 100); 145 } 146 assertEquals(maxDuration, s2.getTotalDuration()); 147 148 // Form a cycle in the AnimatorSet and test the total duration 149 AnimatorSet s3 = new AnimatorSet(); 150 s3.play(a1).before(a2).after(a3); 151 s3.play(a1).after(a2).with(a4); 152 assertEquals(AnimatorSet.DURATION_INFINITE, s3.getTotalDuration()); 153 154 // Put all the animators in a cycle 155 AnimatorSet s4 = new AnimatorSet(); 156 s4.play(a1).after(a2); 157 s4.play(a2).after(a1); 158 assertEquals(AnimatorSet.DURATION_INFINITE, s4.getTotalDuration()); 159 160 // No cycle in the set, run a2, a1, a3 in sequence, and a2, a4, a5 together 161 AnimatorSet s5 = new AnimatorSet(); 162 s5.play(a1).after(a2).before(a3); 163 s5.play(a2).with(a4).with(a5); 164 long duration = a1.getDuration() + a1.getStartDelay() + a2.getDuration() + a2 165 .getStartDelay() + a3.getDuration() + a3.getStartDelay(); 166 long a4Duration = a4.getDuration() + a4.getStartDelay(); 167 long a5Duration = a5.getDuration() + a5.getStartDelay(); 168 duration = Math.max(duration, a4Duration); 169 duration = Math.max(duration, a5Duration); 170 assertEquals(duration, s5.getTotalDuration()); 171 172 // Change one animator to repeat infinitely and test the total time 173 a3.setRepeatCount(ValueAnimator.INFINITE); 174 assertEquals(AnimatorSet.DURATION_INFINITE, s5.getTotalDuration()); 175 176 } 177 178 @SmallTest 179 public void testGetDuration() { 180 AnimatorSet s = new AnimatorSet(); 181 assertTrue(s.getDuration() < 0); 182 s.play(a1).before(a2).before(a3).after(a4).after(a5); 183 assertTrue(s.getDuration() < 0); 184 185 long duration = 200; 186 s.setDuration(duration); 187 assertEquals(duration, s.getDuration()); 188 189 } 190 191 @SmallTest 192 @UiThreadTest 193 public void testSetDuration() { 194 AnimatorSet s = getSequentialSet(); 195 assertTrue(s.getDuration() < 0); 196 197 long duration = 300; 198 s.setDuration(duration); 199 assertEquals(duration, s.getDuration()); 200 201 s.start(); 202 assertEquals(duration, s.getDuration()); 203 assertEquals(duration, a1.getDuration()); 204 assertEquals(duration, a2.getDuration()); 205 assertEquals(duration, a3.getDuration()); 206 assertEquals(duration, a4.getDuration()); 207 assertEquals(duration, a5.getDuration()); 208 } 209 210 @SmallTest 211 public void testAddListener() throws InterruptedException { 212 // Verify that the listener is added to the list of listeners in the AnimatorSet 213 // and that newly added listener gets callback for lifecycle events of the animator 214 final AnimatorSet s = new AnimatorSet(); 215 s.play(a1).before(a2).before(a3).after(a4).after(a5); 216 final MyListener listener = new MyListener(); 217 if (s.getListeners() != null) { 218 assertFalse(s.getListeners().contains(listener)); 219 } 220 s.addListener(listener); 221 assertTrue(s.getListeners().contains(listener)); 222 223 assertFalse(listener.startIsCalled); 224 assertFalse(listener.endIsCalled); 225 226 try { 227 runTestOnUiThread(new Runnable() { 228 @Override 229 public void run() { 230 s.start(); 231 assertTrue(listener.startIsCalled); 232 assertFalse(listener.endIsCalled); 233 } 234 }); 235 } catch (Throwable throwable) { 236 throwable.printStackTrace(); 237 } 238 239 Thread.sleep(s.getTotalDuration() + 200); 240 assertTrue(listener.startIsCalled); 241 assertTrue(listener.endIsCalled); 242 } 243 244 @SmallTest 245 public void testRemoveListener() throws Throwable { 246 final AnimatorSet s = new AnimatorSet(); 247 s.playTogether(a1, a2, a3, a4); 248 MyListener listener = new MyListener(); 249 s.addListener(listener); 250 runTestOnUiThread(new Runnable() { 251 @Override 252 public void run() { 253 s.start(); 254 } 255 }); 256 257 Thread.sleep(s.getTotalDuration() + 100); 258 assertTrue(listener.startIsCalled); 259 assertTrue(listener.endIsCalled); 260 261 s.removeListener(listener); 262 if (s.getListeners() != null) { 263 assertFalse(s.getListeners().contains(listener)); 264 } 265 listener.startIsCalled = false; 266 listener.endIsCalled = false; 267 268 runTestOnUiThread(new Runnable() { 269 @Override 270 public void run() { 271 s.start(); 272 } 273 }); 274 Thread.sleep(s.getTotalDuration() + 100); 275 assertFalse(listener.startIsCalled); 276 assertFalse(listener.endIsCalled); 277 } 278 279 @SmallTest 280 public void testEnd() throws Throwable { 281 // End animator set 282 final AnimatorSet s = new AnimatorSet(); 283 s.play(a1).before(a2).after(a3).with(a4); 284 final MyListener listener = new MyListener(); 285 s.addListener(listener); 286 assertFalse(listener.endIsCalled); 287 runTestOnUiThread(new Runnable() { 288 @Override 289 public void run() { 290 s.start(); 291 assertTrue(s.isStarted()); 292 assertTrue(listener.startIsCalled); 293 assertFalse(listener.endIsCalled); 294 } 295 }); 296 297 Thread.sleep(a2.getTotalDuration()); 298 299 runTestOnUiThread(new Runnable() { 300 @Override 301 public void run() { 302 s.end(); 303 assertTrue(listener.startIsCalled); 304 assertTrue(listener.endIsCalled); 305 assertFalse(s.isRunning()); 306 assertFalse(s.isStarted()); 307 308 assertFalse(a1.isStarted()); 309 assertFalse(a2.isStarted()); 310 assertFalse(a3.isStarted()); 311 assertFalse(a4.isStarted()); 312 } 313 }); 314 315 } 316 317 @SmallTest 318 public void testStart() throws Throwable { 319 final AnimatorSet s = new AnimatorSet(); 320 ArrayList<Animator> animators = getAnimatorList(); 321 322 s.playSequentially(animators); 323 final MyListener l = new MyListener(); 324 s.addListener(l); 325 326 ArrayList<MyListener> listeners = new ArrayList<>(animators.size()); 327 for (int i = 0; i < animators.size(); i++) { 328 MyListener listener = new MyListener(); 329 listeners.add(listener); 330 animators.get(i).addListener(listener); 331 } 332 333 // Check the state before calling start() 334 assertFalse(l.startIsCalled); 335 assertFalse(l.endIsCalled); 336 for (int i = 0; i < listeners.size(); i++) { 337 assertFalse(l.startIsCalled); 338 assertFalse(l.endIsCalled); 339 } 340 341 runTestOnUiThread(new Runnable() { 342 @Override 343 public void run() { 344 s.start(); 345 assertTrue(l.startIsCalled); 346 } 347 }); 348 349 long timeout = s.getTotalDuration() * 2; 350 long wait = 0; 351 352 while (wait < timeout) { 353 if (l.endIsCalled) { 354 break; 355 } 356 Thread.sleep(200); 357 wait += 200; 358 } 359 360 // Now the set should finished 361 assertTrue(l.startIsCalled); 362 assertTrue(l.endIsCalled); 363 for (int i = 0; i < listeners.size(); i++) { 364 assertTrue(listeners.get(i).startIsCalled); 365 assertTrue(listeners.get(i).endIsCalled); 366 } 367 } 368 369 @SmallTest 370 public void testCancel() throws Throwable { 371 // Check whether cancel would trigger onAnimationCanceled and cancel all the unfinished 372 // animations 373 final AnimatorSet s = new AnimatorSet(); 374 final ArrayList<Animator> animators = getAnimatorList(); 375 376 s.playTogether(animators); 377 final MyListener l = new MyListener(); 378 s.addListener(l); 379 380 final ArrayList<MyListener> listeners = new ArrayList<>(5); 381 for (int i = 0; i < animators.size(); i++) { 382 MyListener listener = new MyListener(); 383 listeners.add(listener); 384 animators.get(i).addListener(listener); 385 } 386 387 // Check the state before calling start() 388 assertFalse(l.startIsCalled); 389 assertFalse(l.cancelIsCalled); 390 assertFalse(l.endIsCalled); 391 for (int i = 0; i < listeners.size(); i++) { 392 assertFalse(l.startIsCalled); 393 assertFalse(l.cancelIsCalled); 394 assertFalse(l.endIsCalled); 395 } 396 397 runTestOnUiThread(new Runnable() { 398 @Override 399 public void run() { 400 s.start(); 401 } 402 }); 403 404 Thread.sleep(a1.getTotalDuration()); 405 runTestOnUiThread(new Runnable() { 406 @Override 407 public void run() { 408 assertTrue(s.isStarted()); 409 ArrayList<Integer> runningAnimIds = new ArrayList<Integer>(); 410 for (int i = 0; i < animators.size(); i++) { 411 if (animators.get(i).isStarted()) { 412 runningAnimIds.add(i); 413 } 414 } 415 s.cancel(); 416 assertTrue(l.startIsCalled); 417 assertTrue(l.cancelIsCalled); 418 assertTrue(l.endIsCalled); 419 420 for (int i = 0; i < listeners.size(); i++) { 421 assertTrue(listeners.get(i).startIsCalled); 422 if (runningAnimIds.contains(i)) { 423 assertTrue(listeners.get(i).cancelIsCalled); 424 } 425 assertTrue(listeners.get(i).endIsCalled); 426 } 427 } 428 }); 429 430 } 431 432 @SmallTest 433 public void testIsRunning() throws Throwable { 434 final AnimatorSet s = new AnimatorSet(); 435 final long startDelay = 500; 436 s.play(a1).before(a2).after(a3).with(a4); 437 s.play(a3).after(a5); 438 s.setStartDelay(startDelay); 439 MyListener listener = new MyListener(); 440 s.addListener(listener); 441 runTestOnUiThread(new Runnable() { 442 @Override 443 public void run() { 444 s.start(); 445 } 446 }); 447 448 while (!listener.endIsCalled) { 449 boolean passedStartDelay = a1.isStarted() || a2.isStarted() || a3.isStarted() || 450 a4.isStarted() || a5.isStarted(); 451 assertEquals(passedStartDelay, s.isRunning()); 452 Thread.sleep(50); 453 } 454 assertFalse(s.isRunning()); 455 } 456 457 @SmallTest 458 public void testPauseAndResume() throws Throwable { 459 final AnimatorSet set = getSequentialSet(); 460 runTestOnUiThread(new Runnable() { 461 @Override 462 public void run() { 463 // Calling pause before start should have no effect, per documentation 464 set.pause(); 465 set.start(); 466 assertFalse(set.isPaused()); 467 } 468 }); 469 470 while (!a2.isStarted()) { 471 Thread.sleep(50); 472 } 473 runTestOnUiThread(new Runnable() { 474 @Override 475 public void run() { 476 assertFalse(set.isPaused()); 477 set.pause(); 478 assertTrue(set.isPaused()); 479 set.resume(); 480 assertFalse(set.isPaused()); 481 } 482 }); 483 } 484 485 @SmallTest 486 public void testClone() throws Throwable { 487 // Set up an AnimatorSet and two clones, add one listener to each. When the clones animate, 488 // listeners of both the clone and the animator being cloned should receive animation 489 // lifecycle events. 490 final AnimatorSet s1 = getSequentialSet(); 491 492 // Record animators that called their listeners for the corresponding event. 493 final ArrayList<Animator> startedAnimators = new ArrayList<>(); 494 final ArrayList<Animator> canceledAnimators = new ArrayList<>(); 495 final ArrayList<Animator> endedAnimators = new ArrayList<>(); 496 497 final MyListener l1 = new MyListener() { 498 @Override 499 public void onAnimationStart(Animator anim) { 500 super.onAnimationStart(anim); 501 startedAnimators.add(anim); 502 } 503 504 @Override 505 public void onAnimationCancel(Animator anim) { 506 super.onAnimationCancel(anim); 507 canceledAnimators.add(anim); 508 } 509 510 @Override 511 public void onAnimationEnd(Animator anim) { 512 super.onAnimationEnd(anim); 513 endedAnimators.add(anim); 514 } 515 516 }; 517 s1.addListener(l1); 518 519 // Start the animation, and make the first clone during its run and the second clone once 520 // it ends. 521 runTestOnUiThread(new Runnable() { 522 @Override 523 public void run() { 524 assertFalse(l1.startIsCalled); 525 assertFalse(l1.endIsCalled); 526 527 s1.start(); 528 } 529 }); 530 531 // Make the first clone, during the animation's run. 532 assertTrue(s1.isStarted()); 533 final AnimatorSet s2 = s1.clone(); 534 final MyListener l2 = new MyListener(); 535 s2.addListener(l2); 536 537 Thread.sleep(POLL_INTERVAL); 538 runTestOnUiThread(new Runnable() { 539 @Override 540 public void run() { 541 s1.end(); 542 } 543 }); 544 545 Thread.sleep(POLL_INTERVAL); 546 runTestOnUiThread(new Runnable() { 547 @Override 548 public void run() { 549 assertTrue(l1.startIsCalled); 550 assertTrue(l1.endIsCalled); 551 } 552 }); 553 Thread.sleep(POLL_INTERVAL); 554 555 // Make the second clone now. 556 final AnimatorSet s3 = s1.clone(); 557 final MyListener l3 = new MyListener(); 558 s3.addListener(l3); 559 560 runTestOnUiThread(new Runnable() { 561 @Override 562 public void run() { 563 // Checking the fields before animations start. 564 assertFalse(l2.startIsCalled); 565 assertFalse(l2.cancelIsCalled); 566 assertFalse(l2.endIsCalled); 567 assertFalse(l3.startIsCalled); 568 assertFalse(l3.cancelIsCalled); 569 assertFalse(l3.endIsCalled); 570 571 s2.start(); 572 s3.start(); 573 } 574 }); 575 576 Thread.sleep(POLL_INTERVAL); 577 runTestOnUiThread(new Runnable() { 578 @Override 579 public void run() { 580 // Make sure the listeners receive the callbacks 581 // At this time only onAnimationStart() should be called. 582 assertTrue(l2.startIsCalled); 583 assertTrue(l3.startIsCalled); 584 assertFalse(l2.endIsCalled); 585 assertFalse(l3.endIsCalled); 586 assertFalse(l2.cancelIsCalled); 587 assertFalse(l3.cancelIsCalled); 588 589 s2.end(); 590 s3.cancel(); 591 } 592 }); 593 Thread.sleep(POLL_INTERVAL); 594 runTestOnUiThread(new Runnable() { 595 @Override 596 public void run() { 597 // Check that the new listeners for the new animations gets called for the events. 598 assertTrue(l2.startIsCalled); 599 assertFalse(l2.cancelIsCalled); 600 assertTrue(l2.endIsCalled); 601 assertTrue(l3.startIsCalled); 602 assertTrue(l3.cancelIsCalled); 603 assertTrue(l3.endIsCalled); 604 605 // Check that the listener on the animation that was being clone receive the 606 // animation lifecycle events for the clones. 607 assertTrue(onlyContains(startedAnimators, s1, s2, s3)); 608 assertTrue(onlyContains(canceledAnimators, s3)); 609 assertTrue(onlyContains(endedAnimators, s1, s2, s3)); 610 } 611 }); 612 613 } 614 615 /** 616 * Check that the animator list contains exactly the given animators and nothing else. 617 */ 618 private boolean onlyContains(ArrayList<Animator> animators, AnimatorSet... sets) { 619 if (sets.length != animators.size()) { 620 return false; 621 } 622 623 for (int i = 0; i < sets.length; i++) { 624 AnimatorSet set = sets[i]; 625 if (!animators.contains(set)) { 626 return false; 627 } 628 } 629 return true; 630 631 } 632 633 // Create an AnimatorSet with all the animators running sequentially 634 private AnimatorSet getSequentialSet() { 635 AnimatorSet set = new AnimatorSet(); 636 set.playSequentially(a1, a2, a3, a4, a5); 637 return set; 638 } 639 640 private ArrayList<Animator> getAnimatorList() { 641 ArrayList<Animator> list = new ArrayList<>(); 642 list.add(a1); 643 list.add(a2); 644 list.add(a3); 645 list.add(a4); 646 list.add(a5); 647 return list; 648 } 649 650 } 651