PageRenderTime 47ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/core/tests/coretests/src/android/animation/ValueAnimatorTests.java

https://github.com/android/platform_frameworks_base
Java | 1213 lines | 982 code | 147 blank | 84 comment | 18 complexity | c99e8dee4c731546a0eb917a73b1e368 MD5 | raw file
Possible License(s): Apache-2.0
  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. import static android.test.MoreAsserts.assertNotEqual;
  18. import static junit.framework.Assert.assertEquals;
  19. import static junit.framework.Assert.assertFalse;
  20. import static junit.framework.Assert.assertNotNull;
  21. import static junit.framework.Assert.assertTrue;
  22. import android.os.Handler;
  23. import android.os.Looper;
  24. import android.os.Message;
  25. import android.os.SystemClock;
  26. import android.view.Choreographer;
  27. import android.view.animation.LinearInterpolator;
  28. import androidx.test.filters.MediumTest;
  29. import androidx.test.rule.ActivityTestRule;
  30. import androidx.test.runner.AndroidJUnit4;
  31. import org.junit.After;
  32. import org.junit.Before;
  33. import org.junit.Test;
  34. import org.junit.runner.RunWith;
  35. import java.util.ArrayList;
  36. @RunWith(AndroidJUnit4.class)
  37. @MediumTest
  38. public class ValueAnimatorTests {
  39. private static final long WAIT_TIME_OUT = 5000;
  40. private ValueAnimator a1;
  41. private ValueAnimator a2;
  42. // Tolerance of error in calculations related to duration, frame time, etc. due to frame delay.
  43. private final static long TOLERANCE = 100; // ms
  44. private final static long POLL_INTERVAL = 100; // ms
  45. private final static float A1_START_VALUE = 0f;
  46. private final static float A1_END_VALUE = 1f;
  47. private final static int A2_START_VALUE = 100;
  48. private final static int A2_END_VALUE = 200;
  49. private final static long DEFAULT_FRAME_INTERVAL = 5; //ms
  50. private final static long COMMIT_DELAY = 3; //ms
  51. private ActivityTestRule<BasicAnimatorActivity> mActivityRule =
  52. new ActivityTestRule<>(BasicAnimatorActivity.class);
  53. @Before
  54. public void setUp() throws Exception {
  55. a1 = ValueAnimator.ofFloat(A1_START_VALUE, A1_END_VALUE).setDuration(300);
  56. a2 = ValueAnimator.ofInt(A2_START_VALUE, A2_END_VALUE).setDuration(500);
  57. }
  58. @After
  59. public void tearDown() throws Exception {
  60. a1 = null;
  61. a2 = null;
  62. }
  63. @Test
  64. public void testStartDelay() throws Throwable {
  65. final ValueAnimator a = ValueAnimator.ofFloat(5f, 20f);
  66. assertEquals(a.getStartDelay(), 0);
  67. final long delay = 200;
  68. a.setStartDelay(delay);
  69. assertEquals(a.getStartDelay(), delay);
  70. final MyUpdateListener listener = new MyUpdateListener();
  71. a.addUpdateListener(listener);
  72. final long[] startTime = new long[1];
  73. mActivityRule.runOnUiThread(new Runnable() {
  74. @Override
  75. public void run() {
  76. // Test the time between isRunning() and isStarted()
  77. assertFalse(a.isStarted());
  78. assertFalse(a.isRunning());
  79. a.start();
  80. startTime[0] = SystemClock.uptimeMillis();
  81. assertTrue(a.isStarted());
  82. assertFalse(a.isRunning());
  83. }
  84. });
  85. Thread.sleep(a.getTotalDuration());
  86. mActivityRule.runOnUiThread(new Runnable() {
  87. @Override
  88. public void run() {
  89. assertTrue(listener.wasRunning);
  90. assertTrue(listener.firstRunningFrameTime - startTime[0] >= delay);
  91. }
  92. });
  93. Thread.sleep(a.getTotalDuration());
  94. mActivityRule.runOnUiThread(new Runnable() {
  95. @Override
  96. public void run() {
  97. assertFalse(a.isStarted());
  98. }
  99. });
  100. }
  101. @Test
  102. public void testListenerCallbacks() throws Throwable {
  103. final MyListener l1 = new MyListener();
  104. final MyListener l2 = new MyListener();
  105. a1.addListener(l1);
  106. a2.addListener(l2);
  107. a2.setStartDelay(400);
  108. assertFalse(l1.startCalled);
  109. assertFalse(l1.cancelCalled);
  110. assertFalse(l1.endCalled);
  111. assertFalse(l2.startCalled);
  112. assertFalse(l2.cancelCalled);
  113. assertFalse(l2.endCalled);
  114. mActivityRule.runOnUiThread(new Runnable() {
  115. @Override
  116. public void run() {
  117. a1.start();
  118. a2.start();
  119. }
  120. });
  121. long wait = 0;
  122. Thread.sleep(POLL_INTERVAL);
  123. wait += POLL_INTERVAL;
  124. mActivityRule.runOnUiThread(new Runnable() {
  125. @Override
  126. public void run() {
  127. assertFalse(l1.cancelCalled);
  128. a1.cancel();
  129. assertTrue(l1.cancelCalled);
  130. assertTrue(l1.endCalled);
  131. }
  132. });
  133. while (wait < a2.getStartDelay()) {
  134. mActivityRule.runOnUiThread(new Runnable() {
  135. @Override
  136. public void run() {
  137. // Make sure a2's start listener isn't called during start delay.
  138. assertTrue(l1.startCalled);
  139. assertFalse(l2.startCalled);
  140. }
  141. });
  142. Thread.sleep(POLL_INTERVAL);
  143. wait += POLL_INTERVAL;
  144. }
  145. long delay = Math.max(a1.getTotalDuration(), a2.getTotalDuration()) + TOLERANCE;
  146. Thread.sleep(delay);
  147. mActivityRule.runOnUiThread(new Runnable() {
  148. @Override
  149. public void run() {
  150. // a1 is canceled.
  151. assertTrue(l1.startCalled);
  152. assertTrue(l1.cancelCalled);
  153. assertTrue(l1.endCalled);
  154. // a2 is supposed to finish normally
  155. assertTrue(l2.startCalled);
  156. assertFalse(l2.cancelCalled);
  157. assertTrue(l2.endCalled);
  158. }
  159. });
  160. }
  161. @Test
  162. public void testIsStarted() throws Throwable {
  163. assertFalse(a1.isStarted());
  164. assertFalse(a2.isStarted());
  165. assertFalse(a1.isRunning());
  166. assertFalse(a2.isRunning());
  167. final long startDelay = 150;
  168. a1.setStartDelay(startDelay);
  169. final long[] startTime = new long[1];
  170. mActivityRule.runOnUiThread(new Runnable() {
  171. @Override
  172. public void run() {
  173. a1.start();
  174. a2.start();
  175. startTime[0] = SystemClock.uptimeMillis();
  176. assertTrue(a1.isStarted());
  177. assertTrue(a2.isStarted());
  178. }
  179. });
  180. long delayMs = 0;
  181. while (delayMs < startDelay) {
  182. Thread.sleep(POLL_INTERVAL);
  183. delayMs += POLL_INTERVAL;
  184. mActivityRule.runOnUiThread(new Runnable() {
  185. @Override
  186. public void run() {
  187. if (SystemClock.uptimeMillis() - startTime[0] < startDelay) {
  188. assertFalse(a1.isRunning());
  189. }
  190. }
  191. });
  192. }
  193. Thread.sleep(startDelay);
  194. mActivityRule.runOnUiThread(new Runnable() {
  195. @Override
  196. public void run() {
  197. assertTrue(a1.isRunning());
  198. assertTrue(a2.isRunning());
  199. }
  200. });
  201. long delay = Math.max(a1.getTotalDuration(), a2.getTotalDuration()) * 2;
  202. Thread.sleep(delay);
  203. mActivityRule.runOnUiThread(new Runnable() {
  204. @Override
  205. public void run() {
  206. assertFalse(a1.isStarted());
  207. assertFalse(a1.isRunning());
  208. assertFalse(a2.isStarted());
  209. assertFalse(a2.isRunning());
  210. }
  211. });
  212. }
  213. @Test
  214. public void testPause() throws Throwable {
  215. mActivityRule.runOnUiThread(new Runnable() {
  216. @Override
  217. public void run() {
  218. assertFalse(a1.isPaused());
  219. assertFalse(a2.isPaused());
  220. a1.start();
  221. a2.start();
  222. assertFalse(a1.isPaused());
  223. assertFalse(a2.isPaused());
  224. assertTrue(a1.isStarted());
  225. assertTrue(a2.isStarted());
  226. }
  227. });
  228. Thread.sleep(POLL_INTERVAL);
  229. mActivityRule.runOnUiThread(new Runnable() {
  230. @Override
  231. public void run() {
  232. assertTrue(a1.isRunning());
  233. assertTrue(a2.isRunning());
  234. a1.pause();
  235. assertTrue(a1.isPaused());
  236. assertFalse(a2.isPaused());
  237. assertTrue(a1.isRunning());
  238. }
  239. });
  240. Thread.sleep(a2.getTotalDuration());
  241. mActivityRule.runOnUiThread(new Runnable() {
  242. @Override
  243. public void run() {
  244. // By this time, a2 should have finished, and a1 is still paused
  245. assertFalse(a2.isStarted());
  246. assertFalse(a2.isRunning());
  247. assertTrue(a1.isStarted());
  248. assertTrue(a1.isRunning());
  249. assertTrue(a1.isPaused());
  250. a1.resume();
  251. }
  252. });
  253. Thread.sleep(POLL_INTERVAL);
  254. mActivityRule.runOnUiThread(new Runnable() {
  255. @Override
  256. public void run() {
  257. assertTrue(a1.isRunning());
  258. assertTrue(a1.isStarted());
  259. assertFalse(a1.isPaused());
  260. }
  261. });
  262. Thread.sleep(a1.getTotalDuration());
  263. mActivityRule.runOnUiThread(new Runnable() {
  264. @Override
  265. public void run() {
  266. // a1 should finish by now.
  267. assertFalse(a1.isRunning());
  268. assertFalse(a1.isStarted());
  269. assertFalse(a1.isPaused());
  270. }
  271. });
  272. }
  273. @Test
  274. public void testPauseListener() throws Throwable {
  275. MyPauseListener l1 = new MyPauseListener();
  276. MyPauseListener l2 = new MyPauseListener();
  277. a1.addPauseListener(l1);
  278. a2.addPauseListener(l2);
  279. assertFalse(l1.pauseCalled);
  280. assertFalse(l1.resumeCalled);
  281. assertFalse(l2.pauseCalled);
  282. assertFalse(l2.resumeCalled);
  283. mActivityRule.runOnUiThread(new Runnable() {
  284. @Override
  285. public void run() {
  286. a1.start();
  287. a2.start();
  288. }
  289. });
  290. Thread.sleep(a1.getTotalDuration() / 2);
  291. a1.pause();
  292. Thread.sleep(a2.getTotalDuration());
  293. // Only a1's pause listener should be called.
  294. assertTrue(l1.pauseCalled);
  295. assertFalse(l1.resumeCalled);
  296. mActivityRule.runOnUiThread(new Runnable() {
  297. @Override
  298. public void run() {
  299. a1.resume();
  300. }
  301. });
  302. Thread.sleep(a1.getTotalDuration());
  303. assertTrue(l1.pauseCalled);
  304. assertTrue(l1.resumeCalled);
  305. assertFalse(l2.pauseCalled);
  306. assertFalse(l2.resumeCalled);
  307. }
  308. @Test
  309. public void testResume() throws Throwable {
  310. final MyUpdateListener l1 = new MyUpdateListener();
  311. final long totalDuration = a1.getTotalDuration();
  312. a1.addUpdateListener(l1);
  313. // Set a longer duration on a1 for this test
  314. a1.setDuration(1000);
  315. assertTrue(l1.firstRunningFrameTime < 0);
  316. assertTrue(l1.lastUpdateTime < 0);
  317. final long[] lastUpdate = new long[1];
  318. mActivityRule.runOnUiThread(new Runnable() {
  319. @Override
  320. public void run() {
  321. a1.start();
  322. }
  323. });
  324. Thread.sleep(totalDuration / 2);
  325. mActivityRule.runOnUiThread(new Runnable() {
  326. @Override
  327. public void run() {
  328. assertTrue(l1.firstRunningFrameTime > 0);
  329. assertTrue(l1.lastUpdateTime > l1.firstRunningFrameTime);
  330. lastUpdate[0] = l1.lastUpdateTime;
  331. a1.pause();
  332. }
  333. });
  334. Thread.sleep(totalDuration);
  335. mActivityRule.runOnUiThread(new Runnable() {
  336. @Override
  337. public void run() {
  338. // There should be no update after pause()
  339. assertEquals(lastUpdate[0], l1.lastUpdateTime);
  340. a1.resume();
  341. }
  342. });
  343. do {
  344. Thread.sleep(POLL_INTERVAL);
  345. mActivityRule.runOnUiThread(new Runnable() {
  346. @Override
  347. public void run() {
  348. assertTrue(l1.lastUpdateTime > lastUpdate[0]);
  349. lastUpdate[0] = l1.lastUpdateTime;
  350. }
  351. });
  352. } while (!a1.isStarted());
  353. // Time between pause and resume: totalDuration
  354. long entireSpan = totalDuration * 2;
  355. long frameDelta = l1.lastUpdateTime - l1.firstRunningFrameTime;
  356. assertTrue(Math.abs(entireSpan - frameDelta) < TOLERANCE);
  357. }
  358. @Test
  359. public void testEnd() throws Throwable {
  360. final MyListener l1 = new MyListener();
  361. final MyListener l2 = new MyListener();
  362. a1.addListener(l1);
  363. a2.addListener(l2);
  364. a1.addListener(new MyListener() {
  365. @Override
  366. public void onAnimationEnd(Animator anim) {
  367. anim.cancel();
  368. }
  369. });
  370. a2.addListener(new MyListener() {
  371. @Override
  372. public void onAnimationCancel(Animator anim) {
  373. anim.end();
  374. }
  375. });
  376. mActivityRule.runOnUiThread(new Runnable() {
  377. @Override
  378. public void run() {
  379. assertFalse(l1.cancelCalled);
  380. assertFalse(l1.endCalled);
  381. assertFalse(l2.cancelCalled);
  382. assertFalse(l2.endCalled);
  383. a1.start();
  384. a2.start();
  385. }
  386. });
  387. Thread.sleep(POLL_INTERVAL);
  388. mActivityRule.runOnUiThread(new Runnable() {
  389. @Override
  390. public void run() {
  391. a1.end();
  392. a2.cancel();
  393. }
  394. });
  395. Thread.sleep(POLL_INTERVAL);
  396. mActivityRule.runOnUiThread(new Runnable() {
  397. @Override
  398. public void run() {
  399. // Calling cancel from onAnimationEnd will be ignored.
  400. assertFalse(l1.cancelCalled);
  401. assertTrue(l1.endCalled);
  402. assertTrue(l2.cancelCalled);
  403. assertTrue(l2.endCalled);
  404. float value1 = (Float) a1.getAnimatedValue();
  405. int value2 = (Integer) a2.getAnimatedValue();
  406. assertEquals(A1_END_VALUE, value1);
  407. assertEquals(A2_END_VALUE, value2);
  408. }
  409. });
  410. }
  411. @Test
  412. public void testEndValue() throws Throwable {
  413. final MyListener l1 = new MyListener();
  414. a1.addListener(l1);
  415. final MyListener l2 = new MyListener();
  416. a2.addListener(l2);
  417. mActivityRule.runOnUiThread(new Runnable() {
  418. @Override
  419. public void run() {
  420. a1.start();
  421. a2.start();
  422. }
  423. });
  424. Thread.sleep(POLL_INTERVAL);
  425. mActivityRule.runOnUiThread(new Runnable() {
  426. @Override
  427. public void run() {
  428. // Animation has started but not finished, check animated values against end values
  429. assertFalse(l1.endCalled);
  430. assertFalse(l2.endCalled);
  431. assertNotEqual(A1_END_VALUE, a1.getAnimatedValue());
  432. assertNotEqual(A1_END_VALUE, a2.getAnimatedValue());
  433. // Force a2 to end.
  434. a2.end();
  435. }
  436. });
  437. Thread.sleep(a1.getTotalDuration());
  438. mActivityRule.runOnUiThread(new Runnable() {
  439. @Override
  440. public void run() {
  441. assertFalse(l1.cancelCalled);
  442. assertTrue(l1.endCalled);
  443. assertFalse(l2.cancelCalled);
  444. assertTrue(l2.endCalled);
  445. // By now a1 should have finished normally and a2 has skipped to the end, check
  446. // their end values.
  447. assertEquals(A1_END_VALUE, ((Float) (a1.getAnimatedValue())).floatValue());
  448. assertEquals(A2_END_VALUE, ((Integer) (a2.getAnimatedValue())).intValue());
  449. }
  450. });
  451. }
  452. @Test
  453. public void testUpdateListener() throws InterruptedException {
  454. final MyFrameCallbackProvider provider = new MyFrameCallbackProvider();
  455. long sleep = 0;
  456. while (provider.mHandler == null) {
  457. Thread.sleep(POLL_INTERVAL);
  458. sleep += POLL_INTERVAL;
  459. if (sleep > WAIT_TIME_OUT) {
  460. break;
  461. }
  462. }
  463. // Either the looper has started, or timed out
  464. assertNotNull(provider.mHandler);
  465. final MyListener listener = new MyListener();
  466. final MyUpdateListener l1 = new MyUpdateListener() {
  467. @Override
  468. public void onAnimationUpdate(ValueAnimator animation) {
  469. long currentTime = SystemClock.uptimeMillis();
  470. long frameDelay = provider.getFrameDelay();
  471. if (lastUpdateTime > 0) {
  472. // Error tolerance here is 3 frame.
  473. assertTrue((currentTime - lastUpdateTime) < frameDelay * 4);
  474. } else {
  475. // First frame:
  476. assertTrue(listener.startCalled);
  477. assertTrue(listener.startTime > 0);
  478. assertTrue(currentTime - listener.startTime < frameDelay * 4);
  479. }
  480. super.onAnimationUpdate(animation);
  481. }
  482. };
  483. a1.addUpdateListener(l1);
  484. a1.addListener(listener);
  485. a1.setStartDelay(100);
  486. provider.mHandler.post(new Runnable() {
  487. @Override
  488. public void run() {
  489. AnimationHandler.getInstance().setProvider(provider);
  490. a1.start();
  491. }
  492. });
  493. Thread.sleep(POLL_INTERVAL);
  494. assertTrue(a1.isStarted());
  495. Thread.sleep(a1.getTotalDuration() + TOLERANCE);
  496. // Finished by now.
  497. if (provider.mAssertionError != null) {
  498. throw provider.mAssertionError;
  499. }
  500. assertFalse(a1.isStarted());
  501. assertTrue(listener.endTime > 0);
  502. // Check the time difference between last frame and end time.
  503. assertTrue(listener.endTime >= l1.lastUpdateTime);
  504. assertTrue(listener.endTime - l1.lastUpdateTime < 2 * provider.getFrameDelay());
  505. }
  506. @Test
  507. public void testConcurrentModification() throws Throwable {
  508. // Attempt to modify list of animations as the list is being iterated
  509. final ValueAnimator a0 = ValueAnimator.ofInt(100, 200).setDuration(500);
  510. final ValueAnimator a3 = ValueAnimator.ofFloat(0, 1).setDuration(500);
  511. final ValueAnimator a4 = ValueAnimator.ofInt(200, 300).setDuration(500);
  512. final MyListener listener = new MyListener() {
  513. @Override
  514. public void onAnimationEnd(Animator anim) {
  515. super.onAnimationEnd(anim);
  516. // AnimationHandler should be iterating the list at the moment, end/cancel all
  517. // the other animations. No ConcurrentModificationException should happen.
  518. a0.cancel();
  519. a1.end();
  520. a3.end();
  521. a4.cancel();
  522. }
  523. };
  524. a2.addListener(listener);
  525. mActivityRule.runOnUiThread(new Runnable() {
  526. @Override
  527. public void run() {
  528. a0.start();
  529. a1.start();
  530. a2.start();
  531. a3.start();
  532. a4.start();
  533. }
  534. });
  535. mActivityRule.runOnUiThread(new Runnable() {
  536. @Override
  537. public void run() {
  538. assertTrue(a0.isStarted());
  539. assertTrue(a1.isStarted());
  540. assertTrue(a2.isStarted());
  541. assertTrue(a3.isStarted());
  542. assertTrue(a4.isStarted());
  543. }
  544. });
  545. Thread.sleep(POLL_INTERVAL);
  546. mActivityRule.runOnUiThread(new Runnable() {
  547. @Override
  548. public void run() {
  549. // End the animator that should be in the middle of the list.
  550. a2.end();
  551. }
  552. });
  553. Thread.sleep(POLL_INTERVAL);
  554. assertTrue(listener.endCalled);
  555. assertFalse(a0.isStarted());
  556. assertFalse(a1.isStarted());
  557. assertFalse(a2.isStarted());
  558. assertFalse(a3.isStarted());
  559. assertFalse(a4.isStarted());
  560. }
  561. @Test
  562. public void testSeek() throws Throwable {
  563. final MyListener l1 = new MyListener();
  564. final MyListener l2 = new MyListener();
  565. final MyUpdateListener updateListener1 = new MyUpdateListener();
  566. final MyUpdateListener updateListener2 = new MyUpdateListener();
  567. final float a1StartFraction = 0.2f;
  568. final float a2StartFraction = 0.3f;
  569. // Extend duration so we have plenty of latitude to manipulate the animations when they
  570. // are running.
  571. a1.setDuration(1000);
  572. a2.setDuration(1000);
  573. a1.addListener(l1);
  574. a2.addListener(l2);
  575. a1.addUpdateListener(updateListener1);
  576. a2.addUpdateListener(updateListener2);
  577. TimeInterpolator interpolator = new LinearInterpolator();
  578. a1.setInterpolator(interpolator);
  579. a2.setInterpolator(interpolator);
  580. mActivityRule.runOnUiThread(new Runnable() {
  581. @Override
  582. public void run() {
  583. assertFalse(a1.isStarted());
  584. assertFalse(a1.isRunning());
  585. assertFalse(a2.isStarted());
  586. assertFalse(a2.isRunning());
  587. // Test isRunning() and isStarted() before and after seek
  588. a1.setCurrentFraction(a1StartFraction);
  589. a2.setCurrentFraction(a2StartFraction);
  590. assertFalse(a1.isStarted());
  591. assertFalse(a1.isRunning());
  592. assertFalse(a2.isStarted());
  593. assertFalse(a2.isRunning());
  594. }
  595. });
  596. Thread.sleep(POLL_INTERVAL);
  597. // Start animation and seek during the animation.
  598. mActivityRule.runOnUiThread(new Runnable() {
  599. @Override
  600. public void run() {
  601. assertFalse(a1.isStarted());
  602. assertFalse(a1.isRunning());
  603. assertFalse(a2.isStarted());
  604. assertFalse(a2.isRunning());
  605. assertEquals(a1StartFraction, a1.getAnimatedFraction());
  606. assertEquals(a2StartFraction, a2.getAnimatedFraction());
  607. a1.start();
  608. a2.start();
  609. }
  610. });
  611. Thread.sleep(POLL_INTERVAL);
  612. final float halfwayFraction = 0.5f;
  613. mActivityRule.runOnUiThread(new Runnable() {
  614. @Override
  615. public void run() {
  616. assertTrue(l1.startCalled);
  617. assertTrue(l2.startCalled);
  618. assertFalse(l1.endCalled);
  619. assertFalse(l2.endCalled);
  620. // Check whether the animations start from the seeking fraction
  621. assertTrue(updateListener1.startFraction >= a1StartFraction);
  622. assertTrue(updateListener2.startFraction >= a2StartFraction);
  623. assertTrue(a1.isStarted());
  624. assertTrue(a1.isRunning());
  625. assertTrue(a2.isStarted());
  626. assertTrue(a2.isRunning());
  627. a1.setCurrentFraction(halfwayFraction);
  628. a2.setCurrentFraction(halfwayFraction);
  629. }
  630. });
  631. Thread.sleep(POLL_INTERVAL);
  632. // Check that seeking during running doesn't change animation's internal state
  633. mActivityRule.runOnUiThread(new Runnable() {
  634. @Override
  635. public void run() {
  636. assertTrue(l1.startCalled);
  637. assertTrue(l2.startCalled);
  638. assertFalse(l1.endCalled);
  639. assertFalse(l2.endCalled);
  640. assertTrue(a1.isStarted());
  641. assertTrue(a1.isRunning());
  642. assertTrue(a2.isStarted());
  643. assertTrue(a2.isRunning());
  644. }
  645. });
  646. // Wait until the animators finish successfully.
  647. long wait = Math.max(a1.getTotalDuration(), a2.getTotalDuration());
  648. Thread.sleep(wait);
  649. mActivityRule.runOnUiThread(new Runnable() {
  650. @Override
  651. public void run() {
  652. // Verify that the animators have finished.
  653. assertTrue(l1.endCalled);
  654. assertTrue(l2.endCalled);
  655. assertFalse(a1.isStarted());
  656. assertFalse(a2.isStarted());
  657. assertFalse(a1.isRunning());
  658. assertFalse(a2.isRunning());
  659. }
  660. });
  661. // Re-start animator a1 after it ends normally, and check that seek value from last run
  662. // does not affect the new run.
  663. updateListener1.reset();
  664. mActivityRule.runOnUiThread(new Runnable() {
  665. @Override
  666. public void run() {
  667. a1.start();
  668. }
  669. });
  670. Thread.sleep(POLL_INTERVAL);
  671. mActivityRule.runOnUiThread(new Runnable() {
  672. @Override
  673. public void run() {
  674. assertTrue(updateListener1.wasRunning);
  675. assertTrue(updateListener1.startFraction >= 0);
  676. assertTrue(updateListener1.startFraction < halfwayFraction);
  677. a1.end();
  678. }
  679. });
  680. }
  681. @Test
  682. public void testSeekWhileRunning() throws Throwable {
  683. // Seek one animator to the beginning and the other one to the end when they are running.
  684. final MyListener l1 = new MyListener();
  685. final MyListener l2 = new MyListener();
  686. a1.addListener(l1);
  687. a2.addListener(l2);
  688. mActivityRule.runOnUiThread(new Runnable() {
  689. @Override
  690. public void run() {
  691. assertFalse(l1.startCalled);
  692. assertFalse(l2.startCalled);
  693. assertEquals(0f, a1.getAnimatedFraction());
  694. assertEquals(0f, a2.getAnimatedFraction());
  695. a1.start();
  696. a2.start();
  697. }
  698. });
  699. Thread.sleep(POLL_INTERVAL);
  700. mActivityRule.runOnUiThread(new Runnable() {
  701. @Override
  702. public void run() {
  703. assertFalse(l1.endCalled);
  704. assertFalse(l2.endCalled);
  705. assertTrue(a1.isRunning());
  706. assertTrue(a2.isRunning());
  707. // During the run, seek one to the beginning, the other to the end
  708. a1.setCurrentFraction(0f);
  709. a2.setCurrentFraction(1f);
  710. }
  711. });
  712. Thread.sleep(POLL_INTERVAL);
  713. mActivityRule.runOnUiThread(new Runnable() {
  714. @Override
  715. public void run() {
  716. // Check that a2 has finished due to the seeking, but a1 hasn't finished.
  717. assertFalse(l1.endCalled);
  718. assertTrue(l2.endCalled);
  719. assertEquals(1f, a2.getAnimatedFraction());
  720. }
  721. });
  722. Thread.sleep(a1.getTotalDuration());
  723. mActivityRule.runOnUiThread(new Runnable() {
  724. @Override
  725. public void run() {
  726. // By now a1 should finish also.
  727. assertTrue(l1.endCalled);
  728. assertEquals(1f, a1.getAnimatedFraction());
  729. }
  730. });
  731. }
  732. @Test
  733. public void testEndBeforeStart() throws Throwable {
  734. // This test calls two animators that are not yet started. One animator has completed a
  735. // previous run but hasn't started since then, the other one has never run. When end() is
  736. // called on these two animators, we expected their animation listeners to receive both
  737. // onAnimationStarted(Animator) and onAnimationEnded(Animator) callbacks, in that sequence.
  738. a1.setStartDelay(20);
  739. // First start a1's first run.
  740. final MyListener normalEndingListener = new MyListener();
  741. a1.addListener(normalEndingListener);
  742. mActivityRule.runOnUiThread(new Runnable() {
  743. @Override
  744. public void run() {
  745. assertFalse(a1.isStarted());
  746. assertFalse(normalEndingListener.startCalled);
  747. assertFalse(normalEndingListener.endCalled);
  748. // Start normally
  749. a1.start();
  750. }
  751. });
  752. Thread.sleep(a1.getTotalDuration() + POLL_INTERVAL);
  753. // a1 should have finished by now.
  754. mActivityRule.runOnUiThread(new Runnable() {
  755. @Override
  756. public void run() {
  757. // Call end() on both a1 and a2 without calling start()
  758. final MyListener l1 = new MyListener();
  759. a1.addListener(l1);
  760. final MyListener l2 = new MyListener();
  761. a2.addListener(l2);
  762. assertFalse(a1.isStarted());
  763. assertFalse(l1.startCalled);
  764. assertFalse(l1.endCalled);
  765. assertFalse(a2.isStarted());
  766. assertFalse(l2.startCalled);
  767. assertFalse(l1.endCalled);
  768. a1.end();
  769. a2.end();
  770. // Check that both animators' listeners have received the animation callbacks.
  771. assertTrue(l1.startCalled);
  772. assertTrue(l1.endCalled);
  773. assertFalse(a1.isStarted());
  774. assertTrue(l1.endTime >= l1.startTime);
  775. assertTrue(l2.startCalled);
  776. assertTrue(l2.endCalled);
  777. assertFalse(a2.isStarted());
  778. assertTrue(l2.endTime >= l1.startTime);
  779. }
  780. });
  781. }
  782. @Test
  783. public void testZeroDuration() throws Throwable {
  784. // Run two animators with zero duration, with one running forward and the other one
  785. // backward. Check that the animations start and finish with the correct end fractions.
  786. a1.setDuration(0);
  787. a2.setDuration(0);
  788. // Set a fraction on an animation with 0-duration
  789. final ValueAnimator a3 = ValueAnimator.ofInt(0, 100);
  790. a3.setDuration(0);
  791. a3.setCurrentFraction(1.0f);
  792. assertEquals(1.0f, a3.getAnimatedFraction());
  793. final MyListener l1 = new MyListener();
  794. final MyListener l2 = new MyListener();
  795. final MyListener l3 = new MyListener();
  796. a1.addListener(l1);
  797. a2.addListener(l2);
  798. a3.addListener(l3);
  799. mActivityRule.runOnUiThread(new Runnable() {
  800. @Override
  801. public void run() {
  802. assertFalse(l1.startCalled);
  803. assertFalse(l2.startCalled);
  804. assertFalse(l3.startCalled);
  805. assertFalse(l1.endCalled);
  806. assertFalse(l2.endCalled);
  807. assertFalse(l3.endCalled);
  808. a1.start();
  809. a2.reverse();
  810. a3.start();
  811. // Check that the animators' values are immediately set to end value in the case of
  812. // 0-duration.
  813. assertEquals(A1_END_VALUE, a1.getAnimatedValue());
  814. assertEquals(A2_START_VALUE, a2.getAnimatedValue());
  815. }
  816. });
  817. Thread.sleep(POLL_INTERVAL);
  818. mActivityRule.runOnUiThread(new Runnable() {
  819. @Override
  820. public void run() {
  821. // Check that the animators have started and finished with the right values.
  822. assertTrue(l1.startCalled);
  823. assertTrue(l2.startCalled);
  824. assertTrue(l3.startCalled);
  825. assertTrue(l1.endCalled);
  826. assertTrue(l2.endCalled);
  827. assertTrue(l3.endCalled);
  828. assertEquals(1.0f, a1.getAnimatedFraction());
  829. assertEquals(0f, a2.getAnimatedFraction());
  830. assertEquals(1f, a3.getAnimatedFraction());
  831. assertEquals(A1_END_VALUE, a1.getAnimatedValue());
  832. assertEquals(A2_START_VALUE, a2.getAnimatedValue());
  833. assertEquals(100, a3.getAnimatedValue());
  834. }
  835. });
  836. }
  837. @Test
  838. public void testZeroScale() throws Throwable {
  839. // Test whether animations would end properly when the scale is forced to be zero
  840. float scale = ValueAnimator.getDurationScale();
  841. ValueAnimator.setDurationScale(0f);
  842. // Run two animators, one of which has a start delay, after setting the duration scale to 0
  843. a1.setStartDelay(200);
  844. final MyListener l1 = new MyListener();
  845. final MyListener l2 = new MyListener();
  846. a1.addListener(l1);
  847. a2.addListener(l2);
  848. mActivityRule.runOnUiThread(new Runnable() {
  849. @Override
  850. public void run() {
  851. assertFalse(l1.startCalled);
  852. assertFalse(l2.startCalled);
  853. assertFalse(l1.endCalled);
  854. assertFalse(l2.endCalled);
  855. a1.start();
  856. a2.start();
  857. // In the case of 0 duration scale applied to a non-0 duration, check that the
  858. // value is immediately set to the start value.
  859. assertEquals(A2_START_VALUE, a2.getAnimatedValue());
  860. }
  861. });
  862. Thread.sleep(POLL_INTERVAL);
  863. mActivityRule.runOnUiThread(new Runnable() {
  864. @Override
  865. public void run() {
  866. assertTrue(l1.startCalled);
  867. assertTrue(l2.startCalled);
  868. assertTrue(l1.endCalled);
  869. assertTrue(l2.endCalled);
  870. assertEquals(A1_END_VALUE, a1.getAnimatedValue());
  871. assertEquals(A2_END_VALUE, a2.getAnimatedValue());
  872. }
  873. });
  874. // Restore duration scale
  875. ValueAnimator.setDurationScale(scale);
  876. }
  877. @Test
  878. public void testReverse() throws Throwable {
  879. // Prolong animators duration so that we can do multiple checks during their run
  880. final ValueAnimator a3 = ValueAnimator.ofInt(0, 100);
  881. a1.setDuration(400);
  882. a2.setDuration(600);
  883. a3.setDuration(400);
  884. final MyListener l1 = new MyListener();
  885. final MyListener l2 = new MyListener();
  886. final MyListener l3 = new MyListener();
  887. a1.addListener(l1);
  888. a2.addListener(l2);
  889. a3.addListener(l3);
  890. // Reverse three animators, seek one to the beginning and another to the end, and force
  891. // to end the third one during reversing.
  892. mActivityRule.runOnUiThread(new Runnable() {
  893. @Override
  894. public void run() {
  895. assertFalse(l1.startCalled);
  896. assertFalse(l2.startCalled);
  897. assertFalse(l3.startCalled);
  898. assertFalse(l1.endCalled);
  899. assertFalse(l2.endCalled);
  900. assertFalse(l3.endCalled);
  901. a1.reverse();
  902. a2.reverse();
  903. a3.reverse();
  904. }
  905. });
  906. Thread.sleep(POLL_INTERVAL);
  907. mActivityRule.runOnUiThread(new Runnable() {
  908. @Override
  909. public void run() {
  910. assertTrue(l1.startCalled);
  911. assertTrue(l2.startCalled);
  912. assertTrue(l3.startCalled);
  913. a1.setCurrentFraction(0f);
  914. a2.setCurrentFraction(1f);
  915. a3.end();
  916. // Check that the fraction has been set, and the getter returns the correct values.
  917. assertEquals(1f, a1.getAnimatedFraction());
  918. assertEquals(0f, a2.getAnimatedFraction());
  919. }
  920. });
  921. Thread.sleep(POLL_INTERVAL);
  922. // By now, a2 should have finished due to the seeking. It wouldn't have finished otherwise.
  923. mActivityRule.runOnUiThread(new Runnable() {
  924. @Override
  925. public void run() {
  926. // Check that both animations have started, and a2 has finished.
  927. assertFalse(l1.endCalled);
  928. assertTrue(l2.endCalled);
  929. assertTrue(l3.endCalled);
  930. }
  931. });
  932. Thread.sleep(a1.getTotalDuration());
  933. mActivityRule.runOnUiThread(new Runnable() {
  934. @Override
  935. public void run() {
  936. // Verify that a1 has finished as well.
  937. assertTrue(l1.endCalled);
  938. assertEquals(0f, a1.getAnimatedFraction());
  939. assertEquals(0f, a2.getAnimatedFraction());
  940. assertEquals(0f, a3.getAnimatedFraction());
  941. }
  942. });
  943. }
  944. class MyUpdateListener implements ValueAnimator.AnimatorUpdateListener {
  945. boolean wasRunning = false;
  946. long firstRunningFrameTime = -1;
  947. long lastUpdateTime = -1;
  948. float startFraction = 0;
  949. @Override
  950. public void onAnimationUpdate(ValueAnimator animation) {
  951. lastUpdateTime = SystemClock.uptimeMillis();
  952. if (animation.isRunning() && !wasRunning) {
  953. // Delay has passed
  954. firstRunningFrameTime = lastUpdateTime;
  955. startFraction = animation.getAnimatedFraction();
  956. wasRunning = animation.isRunning();
  957. }
  958. }
  959. void reset() {
  960. wasRunning = false;
  961. firstRunningFrameTime = -1;
  962. lastUpdateTime = -1;
  963. startFraction = 0;
  964. }
  965. }
  966. class MyListener implements Animator.AnimatorListener {
  967. boolean startCalled = false;
  968. boolean cancelCalled = false;
  969. boolean endCalled = false;
  970. long startTime = -1;
  971. long endTime = -1;
  972. @Override
  973. public void onAnimationStart(Animator animation) {
  974. startCalled = true;
  975. startTime = SystemClock.uptimeMillis();
  976. }
  977. @Override
  978. public void onAnimationEnd(Animator animation) {
  979. endCalled = true;
  980. endTime = SystemClock.uptimeMillis();
  981. }
  982. @Override
  983. public void onAnimationCancel(Animator animation) {
  984. cancelCalled = true;
  985. }
  986. @Override
  987. public void onAnimationRepeat(Animator animation) {
  988. }
  989. }
  990. class MyPauseListener implements Animator.AnimatorPauseListener {
  991. boolean pauseCalled = false;
  992. boolean resumeCalled = false;
  993. @Override
  994. public void onAnimationPause(Animator animation) {
  995. pauseCalled = true;
  996. }
  997. @Override
  998. public void onAnimationResume(Animator animation) {
  999. resumeCalled = true;
  1000. }
  1001. }
  1002. class MyFrameCallbackProvider implements AnimationHandler.AnimationFrameCallbackProvider {
  1003. Handler mHandler = null;
  1004. private final static int MSG_FRAME = 0;
  1005. private long mFrameDelay = DEFAULT_FRAME_INTERVAL;
  1006. private ArrayList<Choreographer.FrameCallback> mFrameCallbacks = new ArrayList<>();
  1007. volatile AssertionError mAssertionError = null;
  1008. final LooperThread mThread = new LooperThread();
  1009. public MyFrameCallbackProvider() {
  1010. mThread.start();
  1011. }
  1012. @Override
  1013. public void postFrameCallback(Choreographer.FrameCallback callback) {
  1014. mHandler.sendEmptyMessageDelayed(MSG_FRAME, mFrameDelay);
  1015. if (!mFrameCallbacks.contains(callback)) {
  1016. mFrameCallbacks.add(callback);
  1017. }
  1018. }
  1019. @Override
  1020. public void postCommitCallback(Runnable runnable) {
  1021. // Run the runnable after a commit delay
  1022. mHandler.postDelayed(runnable, COMMIT_DELAY);
  1023. }
  1024. @Override
  1025. public long getFrameTime() {
  1026. return SystemClock.uptimeMillis();
  1027. }
  1028. @Override
  1029. public long getFrameDelay() {
  1030. return mFrameDelay;
  1031. }
  1032. @Override
  1033. public void setFrameDelay(long delay) {
  1034. mFrameDelay = delay;
  1035. if (mFrameCallbacks.size() != 0) {
  1036. mHandler.removeMessages(MSG_FRAME);
  1037. mHandler.sendEmptyMessageDelayed(MSG_FRAME, mFrameDelay);
  1038. }
  1039. }
  1040. class LooperThread extends Thread {
  1041. public void run() {
  1042. Looper.prepare();
  1043. mHandler = new Handler() {
  1044. public void handleMessage(Message msg) {
  1045. try {
  1046. // Handle message here.
  1047. switch (msg.what) {
  1048. case MSG_FRAME:
  1049. for (int i = 0; i < mFrameCallbacks.size(); i++) {
  1050. mFrameCallbacks.get(i).doFrame(SystemClock.uptimeMillis());
  1051. }
  1052. break;
  1053. default:
  1054. break;
  1055. }
  1056. } catch (AssertionError e) {
  1057. mAssertionError = e;
  1058. Looper.myLooper().quit();
  1059. }
  1060. }
  1061. };
  1062. Looper.loop();
  1063. }
  1064. }
  1065. }
  1066. }