1 /* 2 * Copyright (C) 2012 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.cts; 17 18 import android.animation.Animator; 19 import android.animation.AnimatorListenerAdapter; 20 import android.animation.ObjectAnimator; 21 import android.animation.ValueAnimator; 22 import android.test.ActivityInstrumentationTestCase2; 23 import android.view.animation.AccelerateInterpolator; 24 import android.view.animation.LinearInterpolator; 25 26 import java.util.concurrent.CountDownLatch; 27 import java.util.concurrent.TimeUnit; 28 29 public class ValueAnimatorTest extends 30 ActivityInstrumentationTestCase2<AnimationActivity> { 31 private AnimationActivity mActivity; 32 private ValueAnimator mValueAnimator; 33 private long mDuration = 2000; 34 ValueAnimatorTest()35 public ValueAnimatorTest() { 36 super(AnimationActivity.class); 37 } 38 39 @Override setUp()40 protected void setUp() throws Exception { 41 super.setUp(); 42 setActivityInitialTouchMode(false); 43 mActivity = getActivity(); 44 mValueAnimator = mActivity.createAnimatorWithDuration(mDuration); 45 } 46 testDuration()47 public void testDuration() throws Throwable { 48 final long duration = 2000; 49 ValueAnimator valueAnimatorLocal = mActivity.createAnimatorWithDuration(duration); 50 startAnimation(valueAnimatorLocal); 51 assertEquals(duration, valueAnimatorLocal.getDuration()); 52 } 53 testIsRunning()54 public void testIsRunning() throws Throwable { 55 assertFalse(mValueAnimator.isRunning()); 56 startAnimation(mValueAnimator); 57 ValueAnimator valueAnimatorReturned = mActivity.view.bounceYAnimator; 58 assertTrue(valueAnimatorReturned.isRunning()); 59 } 60 testIsStarted()61 public void testIsStarted() throws Throwable { 62 assertFalse(mValueAnimator.isRunning()); 63 assertFalse(mValueAnimator.isStarted()); 64 long startDelay = 10000; 65 mValueAnimator.setStartDelay(startDelay); 66 startAnimation(mValueAnimator); 67 assertFalse(mValueAnimator.isRunning()); 68 assertTrue(mValueAnimator.isStarted()); 69 } 70 testRepeatMode()71 public void testRepeatMode() throws Throwable { 72 ValueAnimator mValueAnimator = mActivity.createAnimatorWithRepeatMode( 73 ValueAnimator.RESTART); 74 startAnimation(mValueAnimator); 75 assertEquals(ValueAnimator.RESTART, mValueAnimator.getRepeatMode()); 76 } 77 testRepeatCount()78 public void testRepeatCount() throws Throwable { 79 int repeatCount = 2; 80 ValueAnimator mValueAnimator = mActivity.createAnimatorWithRepeatCount(repeatCount); 81 startAnimation(mValueAnimator); 82 assertEquals(repeatCount, mValueAnimator.getRepeatCount()); 83 } 84 testStartDelay()85 public void testStartDelay() { 86 long startDelay = 1000; 87 mValueAnimator.setStartDelay(startDelay); 88 assertEquals(startDelay, mValueAnimator.getStartDelay()); 89 } 90 testGetCurrentPlayTime()91 public void testGetCurrentPlayTime() throws Throwable { 92 startAnimation(mValueAnimator); 93 Thread.sleep(100); 94 long currentPlayTime = mValueAnimator.getCurrentPlayTime(); 95 assertTrue(currentPlayTime > 0); 96 } 97 98 /** 99 * Test for equality within some epsilon. This accounts for minor differences 100 * due to floating-point accuracy. 101 */ assertRoughlyEqual(float expected, float actual)102 private void assertRoughlyEqual(float expected, float actual) { 103 final float epsilon = .001f; 104 assertTrue(actual > (expected - epsilon) && actual < (expected + epsilon)); 105 } 106 testSetCurrentPlayTime()107 public void testSetCurrentPlayTime() throws Throwable { 108 final ValueAnimator anim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration); 109 final ValueAnimator delayedAnim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration); 110 delayedAnim.setStartDelay(mDuration); 111 final long proposedCurrentPlayTime = mDuration / 2; 112 runTestOnUiThread(new Runnable() { 113 @Override 114 public void run() { 115 anim.setCurrentPlayTime(mDuration / 2); 116 long currentPlayTime = anim.getCurrentPlayTime(); 117 float currentFraction = anim.getAnimatedFraction(); 118 float currentValue = (Float) anim.getAnimatedValue(); 119 assertEquals(proposedCurrentPlayTime, currentPlayTime); 120 assertRoughlyEqual(.5f, currentFraction); 121 assertRoughlyEqual(50, currentValue); 122 123 delayedAnim.setCurrentPlayTime(mDuration / 2); 124 currentPlayTime = delayedAnim.getCurrentPlayTime(); 125 currentFraction = delayedAnim.getAnimatedFraction(); 126 currentValue = (Float) delayedAnim.getAnimatedValue(); 127 assertEquals(proposedCurrentPlayTime, currentPlayTime); 128 assertRoughlyEqual(.5f, currentFraction); 129 assertRoughlyEqual(50, currentValue); 130 } 131 }); 132 // Now make sure that it's still true a little later, to test that we're 133 // getting a result based on the seek time, not the wall clock time 134 Thread.sleep(100); 135 long currentPlayTime = anim.getCurrentPlayTime(); 136 float currentFraction = anim.getAnimatedFraction(); 137 float currentValue = (Float) anim.getAnimatedValue(); 138 assertEquals(proposedCurrentPlayTime, currentPlayTime); 139 assertRoughlyEqual(.5f, currentFraction); 140 assertRoughlyEqual(50, currentValue); 141 142 currentPlayTime = delayedAnim.getCurrentPlayTime(); 143 currentFraction = delayedAnim.getAnimatedFraction(); 144 currentValue = (Float) delayedAnim.getAnimatedValue(); 145 assertEquals(proposedCurrentPlayTime, currentPlayTime); 146 assertRoughlyEqual(.5f, currentFraction); 147 assertRoughlyEqual(50, currentValue); 148 149 // Finally, start() the delayed animation and check that the play time was 150 // not affected by playing during the delay 151 runTestOnUiThread(new Runnable() { 152 @Override 153 public void run() { 154 delayedAnim.start(); 155 long currentPlayTime = delayedAnim.getCurrentPlayTime(); 156 float currentFraction = delayedAnim.getAnimatedFraction(); 157 float currentValue = (Float) delayedAnim.getAnimatedValue(); 158 assertEquals(proposedCurrentPlayTime, currentPlayTime); 159 assertRoughlyEqual(.5f, currentFraction); 160 assertRoughlyEqual(50, currentValue); 161 } 162 }); 163 164 Thread.sleep(100); 165 currentPlayTime = delayedAnim.getCurrentPlayTime(); 166 currentFraction = delayedAnim.getAnimatedFraction(); 167 currentValue = (Float) delayedAnim.getAnimatedValue(); 168 assertEquals(proposedCurrentPlayTime, currentPlayTime); 169 assertRoughlyEqual(.5f, currentFraction); 170 assertRoughlyEqual(50, currentValue); 171 172 runTestOnUiThread(new Runnable() { 173 @Override 174 public void run() { 175 delayedAnim.cancel(); 176 } 177 }); 178 } 179 testSetCurrentPlayTimeAfterStart()180 public void testSetCurrentPlayTimeAfterStart() throws Throwable { 181 // This test sets current play time right after start() is called on a non-delayed animation 182 final long duration = 100; 183 final float seekFraction = 0.2f; 184 final CountDownLatch frameUpdateLatch = new CountDownLatch(1); 185 final CountDownLatch endLatch = new CountDownLatch(1); 186 187 final ValueAnimator anim = ValueAnimator.ofFloat(0, 1).setDuration(duration); 188 anim.setInterpolator(null); 189 anim.addListener(new AnimatorListenerAdapter() { 190 @Override 191 public void onAnimationEnd(Animator animation) { 192 super.onAnimationEnd(animation); 193 endLatch.countDown(); 194 } 195 }); 196 runTestOnUiThread(new Runnable() { 197 @Override 198 public void run() { 199 anim.start(); 200 anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 201 float fractionOnFirstFrame = -1f; 202 @Override 203 public void onAnimationUpdate(ValueAnimator animation) { 204 if (fractionOnFirstFrame < 0) { 205 // First frame: 206 fractionOnFirstFrame = animation.getAnimatedFraction(); 207 assertRoughlyEqual(seekFraction, fractionOnFirstFrame); 208 frameUpdateLatch.countDown(); 209 } else { 210 assertTrue(animation.getAnimatedFraction() >= fractionOnFirstFrame); 211 } 212 } 213 }); 214 long currentPlayTime = (long) (seekFraction * (float) duration); 215 anim.setCurrentPlayTime(currentPlayTime); 216 } 217 }); 218 assertTrue(frameUpdateLatch.await(100, TimeUnit.MILLISECONDS)); 219 assertTrue(endLatch.await(200, TimeUnit.MILLISECONDS)); 220 } 221 testSetCurrentFraction()222 public void testSetCurrentFraction() throws Throwable { 223 final ValueAnimator anim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration); 224 final long proposedCurrentPlayTime = mDuration / 2; 225 runTestOnUiThread(new Runnable() { 226 @Override 227 public void run() { 228 anim.setCurrentFraction(.5f); 229 long currentPlayTime = anim.getCurrentPlayTime(); 230 float currentFraction = anim.getAnimatedFraction(); 231 float currentValue = (Float) anim.getAnimatedValue(); 232 assertEquals(proposedCurrentPlayTime, currentPlayTime); 233 assertRoughlyEqual(.5f, currentFraction); 234 assertRoughlyEqual(50, currentValue); 235 } 236 }); 237 // Now make sure that it's still true a little later, to test that we're 238 // getting a result based on the seek time, not the wall clock time 239 Thread.sleep(100); 240 long currentPlayTime = anim.getCurrentPlayTime(); 241 float currentFraction = anim.getAnimatedFraction(); 242 float currentValue = (Float) anim.getAnimatedValue(); 243 assertEquals(proposedCurrentPlayTime, currentPlayTime); 244 assertRoughlyEqual(.5f, currentFraction); 245 assertRoughlyEqual(50, currentValue); 246 } 247 testReverseRightAfterStart()248 public void testReverseRightAfterStart() throws Throwable { 249 runTestOnUiThread(new Runnable() { 250 @Override 251 public void run() { 252 // Reverse() right after start() should trigger immediate end() at fraction 0. 253 final ValueAnimator anim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration); 254 anim.start(); 255 assertTrue(anim.isStarted()); 256 anim.reverse(); 257 assertFalse(anim.isStarted()); 258 assertEquals(0f, anim.getAnimatedFraction()); 259 } 260 }); 261 } 262 testGetFrameDelay()263 public void testGetFrameDelay() throws Throwable { 264 final long frameDelay = 10; 265 runTestOnUiThread(new Runnable() { 266 @Override 267 public void run() { 268 mValueAnimator.setFrameDelay(frameDelay); 269 } 270 }); 271 startAnimation(mValueAnimator); 272 Thread.sleep(100); 273 runTestOnUiThread(new Runnable() { 274 @Override 275 public void run() { 276 long actualFrameDelay = mValueAnimator.getFrameDelay(); 277 assertEquals(frameDelay, actualFrameDelay); 278 } 279 }); 280 } 281 testSetInterpolator()282 public void testSetInterpolator() throws Throwable { 283 AccelerateInterpolator interpolator = new AccelerateInterpolator(); 284 ValueAnimator mValueAnimator = mActivity.createAnimatorWithInterpolator(interpolator); 285 startAnimation(mValueAnimator); 286 assertTrue(interpolator.equals(mValueAnimator.getInterpolator())); 287 } 288 testCancel()289 public void testCancel() throws Throwable { 290 startAnimation(mValueAnimator); 291 Thread.sleep(100); 292 cancelAnimation(mValueAnimator); 293 assertFalse(mValueAnimator.isRunning()); 294 } 295 testEnd()296 public void testEnd() throws Throwable { 297 Object object = mActivity.view.newBall; 298 String property = "y"; 299 float startY = mActivity.mStartY; 300 float endY = mActivity.mStartY + mActivity.mDeltaY; 301 ObjectAnimator objAnimator = ObjectAnimator.ofFloat(object, property, startY, endY); 302 objAnimator.setDuration(mDuration); 303 objAnimator.setRepeatCount(ValueAnimator.INFINITE); 304 objAnimator.setInterpolator(new AccelerateInterpolator()); 305 objAnimator.setRepeatMode(ValueAnimator.REVERSE); 306 startAnimation(objAnimator); 307 Thread.sleep(100); 308 endAnimation(objAnimator); 309 float y = mActivity.view.newBall.getY(); 310 assertEquals(y, endY); 311 } 312 testGetAnimatedFraction()313 public void testGetAnimatedFraction() throws Throwable { 314 ValueAnimator objAnimator = getAnimator(); 315 startAnimation(objAnimator); 316 assertNotNull(objAnimator); 317 float[] fractions = getValue(objAnimator, 10, "getAnimatedFraction()", 200l, null); 318 for(int j = 0; j < 9; j++){ 319 assertTrue(fractions[j] >= 0.0); 320 assertTrue(fractions[j] <= 1.0); 321 assertTrue(errorMessage(fractions), fractions[j + 1] >= fractions[j]); 322 } 323 } 324 testGetAnimatedValue()325 public void testGetAnimatedValue() throws Throwable { 326 ValueAnimator objAnimator = getAnimator(); 327 startAnimation(objAnimator); 328 assertNotNull(objAnimator); 329 float[] animatedValues = getValue(objAnimator, 10, "getAnimatedValue()", 200l, null); 330 331 for(int j = 0; j < 9; j++){ 332 assertTrue(errorMessage(animatedValues), animatedValues[j + 1] >= animatedValues[j]); 333 } 334 } testGetAnimatedValue_PropertyName()335 public void testGetAnimatedValue_PropertyName() throws Throwable { 336 String property = "y"; 337 338 ValueAnimator objAnimator = getAnimator(); 339 startAnimation(objAnimator); 340 assertNotNull(objAnimator); 341 float[] animatedValues = getValue(objAnimator, 10, "getAnimatedValue(property)", 200l, 342 property); 343 for(int j = 0; j < 9; j++){ 344 assertTrue(errorMessage(animatedValues), animatedValues[j + 1] >= animatedValues[j]); 345 } 346 } 347 testOfFloat()348 public void testOfFloat() throws Throwable { 349 float start = 0.0f; 350 float end = 1.0f; 351 float[] values = {start, end}; 352 final ValueAnimator valueAnimatorLocal = ValueAnimator.ofFloat(values); 353 valueAnimatorLocal.setDuration(mDuration); 354 valueAnimatorLocal.setRepeatCount(ValueAnimator.INFINITE); 355 valueAnimatorLocal.setInterpolator(new AccelerateInterpolator()); 356 valueAnimatorLocal.setRepeatMode(ValueAnimator.RESTART); 357 358 this.runTestOnUiThread(new Runnable(){ 359 public void run() { 360 valueAnimatorLocal.start(); 361 } 362 }); 363 Thread.sleep(100); 364 boolean isRunning = valueAnimatorLocal.isRunning(); 365 assertTrue(isRunning); 366 367 Float animatedValue = (Float) valueAnimatorLocal.getAnimatedValue(); 368 assertTrue(animatedValue >= start); 369 assertTrue(animatedValue <= end); 370 } 371 testOfInt()372 public void testOfInt() throws Throwable { 373 int start = 0; 374 int end = 10; 375 int[] values = {start, end}; 376 final ValueAnimator valueAnimatorLocal = ValueAnimator.ofInt(values); 377 valueAnimatorLocal.setDuration(mDuration); 378 valueAnimatorLocal.setRepeatCount(ValueAnimator.INFINITE); 379 valueAnimatorLocal.setInterpolator(new AccelerateInterpolator()); 380 valueAnimatorLocal.setRepeatMode(ValueAnimator.RESTART); 381 382 this.runTestOnUiThread(new Runnable(){ 383 public void run() { 384 valueAnimatorLocal.start(); 385 } 386 }); 387 Thread.sleep(100); 388 boolean isRunning = valueAnimatorLocal.isRunning(); 389 assertTrue(isRunning); 390 391 Integer animatedValue = (Integer) valueAnimatorLocal.getAnimatedValue(); 392 assertTrue(animatedValue >= start); 393 assertTrue(animatedValue <= end); 394 } 395 testNoDelayOnSeekAnimation()396 public void testNoDelayOnSeekAnimation() throws Throwable { 397 ValueAnimator animator = ValueAnimator.ofFloat(0, 1); 398 animator.setInterpolator(new LinearInterpolator()); 399 animator.setStartDelay(1000); 400 animator.setDuration(300); 401 animator.setCurrentPlayTime(150); 402 EventWatcher watcher = new EventWatcher(); 403 animator.addListener(watcher); 404 runTestOnUiThread(new Runnable() { 405 @Override 406 public void run() { 407 animator.start(); 408 } 409 }); 410 assertTrue(watcher.start.await(0, TimeUnit.MILLISECONDS)); 411 assertTrue(((Float)animator.getAnimatedValue()) >= 0.5f); 412 assertTrue(animator.getAnimatedFraction() >= 0.5f); 413 runTestOnUiThread(new Runnable() { 414 @Override 415 public void run() { 416 animator.cancel(); 417 } 418 }); 419 } 420 getAnimator()421 private ValueAnimator getAnimator() { 422 Object object = mActivity.view.newBall; 423 String property = "y"; 424 float startY = mActivity.mStartY; 425 float endY = mActivity.mStartY + mActivity.mDeltaY; 426 ValueAnimator objAnimator = ObjectAnimator.ofFloat(object, property, startY, endY); 427 objAnimator.setDuration(mDuration); 428 objAnimator.setRepeatCount(ValueAnimator.INFINITE); 429 objAnimator.setInterpolator(new AccelerateInterpolator()); 430 objAnimator.setRepeatMode(ValueAnimator.REVERSE); 431 return objAnimator; 432 } 433 getValue(ValueAnimator animator, int n, String methodName, long sleepTime, String property)434 private float[] getValue(ValueAnimator animator, int n, String methodName, 435 long sleepTime, String property) throws InterruptedException { 436 float[] values = new float[n]; 437 for(int i = 0; i < n; i++){ 438 Thread.sleep(sleepTime); 439 float value = 0.0f; 440 if(methodName.equals("getAnimatedFraction()")) { 441 value = animator.getAnimatedFraction(); 442 }else if(methodName.equals("getAnimatedValue()")) { 443 value = ((Float)animator.getAnimatedValue()).floatValue(); 444 }else if(methodName.equals("getAnimatedValue(property)")) { 445 value = ((Float)animator.getAnimatedValue(property)).floatValue(); 446 } 447 values[i] = value; 448 } 449 return values; 450 } 451 startAnimation(final ValueAnimator animator)452 private void startAnimation(final ValueAnimator animator) throws Throwable { 453 this.runTestOnUiThread(new Runnable() { 454 public void run() { 455 mActivity.startAnimation(animator); 456 } 457 }); 458 } 459 endAnimation(final ValueAnimator animator)460 private void endAnimation(final ValueAnimator animator) throws Throwable { 461 this.runTestOnUiThread(new Runnable() { 462 public void run() { 463 animator.end(); 464 } 465 }); 466 } 467 cancelAnimation(final ValueAnimator animator)468 private void cancelAnimation(final ValueAnimator animator) throws Throwable { 469 this.runTestOnUiThread(new Runnable() { 470 public void run() { 471 animator.cancel(); 472 } 473 }); 474 } 475 errorMessage(float[] values)476 private String errorMessage(float[] values) { 477 StringBuilder message = new StringBuilder(); 478 for (int i = 0; i < values.length; i++) { 479 message.append(values[i]).append(" "); 480 } 481 return message.toString(); 482 } 483 484 class EventWatcher implements Animator.AnimatorListener { 485 public CountDownLatch start = new CountDownLatch(1); 486 public CountDownLatch end = new CountDownLatch(1); 487 public CountDownLatch cancel = new CountDownLatch(1); 488 public CountDownLatch repeat = new CountDownLatch(1); 489 onAnimationCancel(Animator animation)490 public void onAnimationCancel(Animator animation) { 491 cancel.countDown(); 492 } 493 onAnimationEnd(Animator animation)494 public void onAnimationEnd(Animator animation) { 495 end.countDown(); 496 } 497 onAnimationRepeat(Animator animation)498 public void onAnimationRepeat(Animator animation) { 499 repeat.countDown(); 500 } 501 onAnimationStart(Animator animation)502 public void onAnimationStart(Animator animation) { 503 start.countDown(); 504 } 505 } 506 } 507