Home | History | Annotate | Download | only in cts
      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 static com.android.compatibility.common.util.CtsMockitoUtils.within;
     19 
     20 import static org.junit.Assert.assertEquals;
     21 import static org.junit.Assert.assertFalse;
     22 import static org.junit.Assert.assertNotNull;
     23 import static org.junit.Assert.assertTrue;
     24 import static org.mockito.Mockito.atLeast;
     25 import static org.mockito.Mockito.mock;
     26 import static org.mockito.Mockito.timeout;
     27 import static org.mockito.Mockito.times;
     28 import static org.mockito.Mockito.verify;
     29 
     30 import android.animation.Animator;
     31 import android.animation.Animator.AnimatorListener;
     32 import android.animation.AnimatorListenerAdapter;
     33 import android.animation.ObjectAnimator;
     34 import android.animation.PropertyValuesHolder;
     35 import android.animation.TimeInterpolator;
     36 import android.animation.TypeEvaluator;
     37 import android.animation.ValueAnimator;
     38 import android.animation.ValueAnimator.AnimatorUpdateListener;
     39 import android.graphics.Color;
     40 import android.graphics.PointF;
     41 import android.os.SystemClock;
     42 import android.view.animation.AccelerateInterpolator;
     43 import android.view.animation.LinearInterpolator;
     44 
     45 import androidx.test.InstrumentationRegistry;
     46 import androidx.test.annotation.UiThreadTest;
     47 import androidx.test.filters.LargeTest;
     48 import androidx.test.rule.ActivityTestRule;
     49 import androidx.test.runner.AndroidJUnit4;
     50 
     51 import org.junit.AfterClass;
     52 import org.junit.Before;
     53 import org.junit.BeforeClass;
     54 import org.junit.Rule;
     55 import org.junit.Test;
     56 import org.junit.runner.RunWith;
     57 
     58 import java.util.concurrent.CountDownLatch;
     59 import java.util.concurrent.TimeUnit;
     60 
     61 @LargeTest
     62 @RunWith(AndroidJUnit4.class)
     63 public class ValueAnimatorTest {
     64     private static final float EPSILON = 0.0001f;
     65     private static float sPreviousAnimatorScale = 1.0f;
     66 
     67     private AnimationActivity mActivity;
     68     private ValueAnimator mValueAnimator;
     69     private final long mDuration = 2000;
     70 
     71     @Rule
     72     public ActivityTestRule<AnimationActivity> mActivityRule =
     73             new ActivityTestRule<>(AnimationActivity.class);
     74 
     75     @Before
     76     public void setup() {
     77         InstrumentationRegistry.getInstrumentation().setInTouchMode(false);
     78         mActivity = mActivityRule.getActivity();
     79         mValueAnimator = mActivity.createAnimatorWithDuration(mDuration);
     80     }
     81 
     82     @BeforeClass
     83     public static void beforeClass() {
     84         sPreviousAnimatorScale = ValueAnimator.getDurationScale();
     85         ValueAnimator.setDurationScale(1.0f);
     86     }
     87 
     88     @AfterClass
     89     public static void afterClass() {
     90         ValueAnimator.setDurationScale(sPreviousAnimatorScale);
     91     }
     92 
     93     @Test
     94     public void testDuration() throws Throwable {
     95         ValueAnimator valueAnimatorLocal = mActivity.createAnimatorWithDuration(mDuration);
     96         startAnimation(valueAnimatorLocal);
     97         assertEquals(mDuration, valueAnimatorLocal.getDuration());
     98     }
     99 
    100     @Test
    101     public void testIsRunning() throws Throwable {
    102         assertFalse(mValueAnimator.isRunning());
    103         startAnimation(mValueAnimator);
    104         ValueAnimator valueAnimatorReturned = mActivity.view.bounceYAnimator;
    105         assertTrue(valueAnimatorReturned.isRunning());
    106     }
    107 
    108     @Test
    109     public void testIsStarted() throws Throwable {
    110         assertFalse(mValueAnimator.isRunning());
    111         assertFalse(mValueAnimator.isStarted());
    112         long startDelay = 10000;
    113         mValueAnimator.setStartDelay(startDelay);
    114         startAnimation(mValueAnimator);
    115         assertFalse(mValueAnimator.isRunning());
    116         assertTrue(mValueAnimator.isStarted());
    117     }
    118 
    119     @Test
    120     public void testRepeatMode() throws Throwable {
    121         ValueAnimator mValueAnimator = mActivity.createAnimatorWithRepeatMode(
    122             ValueAnimator.RESTART);
    123         startAnimation(mValueAnimator);
    124         assertEquals(ValueAnimator.RESTART, mValueAnimator.getRepeatMode());
    125     }
    126 
    127     @Test
    128     public void testRepeatCount() throws Throwable {
    129         int repeatCount = 2;
    130         ValueAnimator mValueAnimator = mActivity.createAnimatorWithRepeatCount(repeatCount);
    131         startAnimation(mValueAnimator);
    132         assertEquals(repeatCount, mValueAnimator.getRepeatCount());
    133     }
    134 
    135     @Test
    136     public void testStartDelay() {
    137         long startDelay = 1000;
    138         mValueAnimator.setStartDelay(startDelay);
    139         assertEquals(startDelay, mValueAnimator.getStartDelay());
    140     }
    141 
    142     /**
    143      * Verify that an animator with start delay will have its listener's onAnimationStart(...)
    144      * and onAnimationEnd(...) called at the right time.
    145      */
    146     @Test
    147     public void testListenerCallbackWithStartDelay() throws Throwable {
    148         final ValueAnimator anim = ValueAnimator.ofFloat(0f, 1f);
    149         anim.setStartDelay(300);
    150         anim.setDuration(300);
    151         AnimatorListener listener = mock(AnimatorListenerAdapter.class);
    152         anim.addListener(listener);
    153         mActivityRule.runOnUiThread(() -> {
    154             anim.start();
    155         });
    156 
    157         verify(listener, timeout(450).times(1)).onAnimationStart(anim, false);
    158         verify(listener, timeout(450).times(1)).onAnimationEnd(anim, false);
    159     }
    160 
    161     @Test
    162     public void testGetCurrentPlayTime() throws Throwable {
    163         startAnimation(mValueAnimator);
    164         SystemClock.sleep(100);
    165         long currentPlayTime = mValueAnimator.getCurrentPlayTime();
    166         assertTrue(currentPlayTime  >  0);
    167     }
    168 
    169     @Test
    170     public void testSetCurrentPlayTime() throws Throwable {
    171         final ValueAnimator anim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration);
    172         final ValueAnimator delayedAnim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration);
    173         delayedAnim.setStartDelay(mDuration);
    174         final long proposedCurrentPlayTime = mDuration / 2;
    175         mActivityRule.runOnUiThread(() -> {
    176             anim.setCurrentPlayTime(mDuration / 2);
    177             long currentPlayTime = anim.getCurrentPlayTime();
    178             float currentFraction = anim.getAnimatedFraction();
    179             float currentValue = (Float) anim.getAnimatedValue();
    180             assertEquals(proposedCurrentPlayTime, currentPlayTime);
    181             assertEquals(.5f, currentFraction, EPSILON);
    182             assertEquals(50, currentValue, EPSILON);
    183 
    184             delayedAnim.setCurrentPlayTime(mDuration / 2);
    185             currentPlayTime = delayedAnim.getCurrentPlayTime();
    186             currentFraction = delayedAnim.getAnimatedFraction();
    187             currentValue = (Float) delayedAnim.getAnimatedValue();
    188             assertEquals(proposedCurrentPlayTime, currentPlayTime);
    189             assertEquals(.5f, currentFraction, EPSILON);
    190             assertEquals(50, currentValue, EPSILON);
    191         });
    192         // Now make sure that it's still true a little later, to test that we're
    193         // getting a result based on the seek time, not the wall clock time
    194         SystemClock.sleep(100);
    195         long currentPlayTime = anim.getCurrentPlayTime();
    196         float currentFraction = anim.getAnimatedFraction();
    197         float currentValue = (Float) anim.getAnimatedValue();
    198         assertEquals(proposedCurrentPlayTime, currentPlayTime);
    199         assertEquals(.5f, currentFraction, EPSILON);
    200         assertEquals(50, currentValue, EPSILON);
    201 
    202         currentPlayTime = delayedAnim.getCurrentPlayTime();
    203         currentFraction = delayedAnim.getAnimatedFraction();
    204         currentValue = (Float) delayedAnim.getAnimatedValue();
    205         assertEquals(proposedCurrentPlayTime, currentPlayTime);
    206         assertEquals(.5f, currentFraction, EPSILON);
    207         assertEquals(50, currentValue, EPSILON);
    208 
    209         // Finally, start() the delayed animation and check that the play time was
    210         // not affected by playing during the delay
    211         mActivityRule.runOnUiThread(() -> {
    212             delayedAnim.start();
    213             assertEquals(proposedCurrentPlayTime, delayedAnim.getCurrentPlayTime());
    214             assertEquals(.5f, delayedAnim.getAnimatedFraction(), EPSILON);
    215             assertEquals(50, (float) delayedAnim.getAnimatedValue(), EPSILON);
    216         });
    217 
    218         SystemClock.sleep(100);
    219         currentPlayTime = delayedAnim.getCurrentPlayTime();
    220         currentFraction = delayedAnim.getAnimatedFraction();
    221         currentValue = (Float) delayedAnim.getAnimatedValue();
    222         assertTrue(currentPlayTime > proposedCurrentPlayTime);
    223         assertTrue(currentFraction > 0.5f);
    224         assertTrue(currentValue > 50);
    225 
    226         mActivityRule.runOnUiThread(delayedAnim::cancel);
    227     }
    228 
    229     @Test
    230     public void testPauseListener() throws Throwable {
    231         // Adds two pause listeners to the animator, and remove one after the animator is paused.
    232         Animator.AnimatorPauseListener l1 = mock(Animator.AnimatorPauseListener.class);
    233         Animator.AnimatorPauseListener l2 = mock(Animator.AnimatorPauseListener.class);
    234         ValueAnimator a1 = ValueAnimator.ofFloat(0, 1f);
    235         a1.addPauseListener(l1);
    236         a1.addPauseListener(l2);
    237         mActivityRule.runOnUiThread(() -> {
    238             a1.start();
    239             a1.pause();
    240             verify(l1, times(1)).onAnimationPause(a1);
    241             verify(l2, times(1)).onAnimationPause(a1);
    242             a1.removePauseListener(l2);
    243             a1.resume();
    244         });
    245 
    246         // Check that the pause listener that is removed doesn't have resume called.
    247         verify(l1, times(1)).onAnimationResume(a1);
    248         verify(l2, times(0)).onAnimationResume(a1);
    249     }
    250 
    251     @Test
    252     public void testSetCurrentPlayTimeAfterStart() throws Throwable {
    253         // This test sets current play time right after start() is called on a non-delayed animation
    254         final long duration = 100;
    255         final float seekFraction = 0.2f;
    256         final CountDownLatch frameUpdateLatch = new CountDownLatch(1);
    257 
    258         final AnimatorSetTest.MyListener myListener = new AnimatorSetTest.MyListener();
    259         final ValueAnimator anim  = ValueAnimator.ofFloat(0, 1).setDuration(duration);
    260         anim.setInterpolator(null);
    261         final Animator.AnimatorListener listener = mock(Animator.AnimatorListener.class);
    262         anim.addListener(listener);
    263         anim.addListener(myListener);
    264         mActivityRule.runOnUiThread(() -> {
    265             anim.start();
    266             anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    267                 float fractionOnFirstFrame = -1f;
    268 
    269                 @Override
    270                 public void onAnimationUpdate(ValueAnimator animation) {
    271                     if (fractionOnFirstFrame < 0) {
    272                         // First frame:
    273                         fractionOnFirstFrame = animation.getAnimatedFraction();
    274                         assertEquals(seekFraction, fractionOnFirstFrame, EPSILON);
    275                         frameUpdateLatch.countDown();
    276                     } else {
    277                         assertTrue(animation.getAnimatedFraction() >= fractionOnFirstFrame);
    278                     }
    279                 }
    280             });
    281             long currentPlayTime = (long) (seekFraction * (float) duration);
    282             anim.setCurrentPlayTime(currentPlayTime);
    283         });
    284         assertTrue(frameUpdateLatch.await(100, TimeUnit.MILLISECONDS));
    285         verify(listener, within(200)).onAnimationEnd(anim, false);
    286         // Also make sure the onAnimationEnd(anim) is called.
    287         assertTrue(myListener.mEndIsCalled);
    288     }
    289 
    290     @Test
    291     public void testSetCurrentFraction() throws Throwable {
    292         final ValueAnimator anim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration);
    293         final long proposedCurrentPlayTime = mDuration / 2;
    294         mActivityRule.runOnUiThread(() -> {
    295             anim.setCurrentFraction(.5f);
    296             long currentPlayTime = anim.getCurrentPlayTime();
    297             float currentFraction = anim.getAnimatedFraction();
    298             float currentValue = (Float) anim.getAnimatedValue();
    299             assertEquals(proposedCurrentPlayTime, currentPlayTime);
    300             assertEquals(.5f, currentFraction, EPSILON);
    301             assertEquals(50, currentValue, EPSILON);
    302         });
    303         // Now make sure that it's still true a little later, to test that we're
    304         // getting a result based on the seek time, not the wall clock time
    305         SystemClock.sleep(100);
    306         long currentPlayTime = anim.getCurrentPlayTime();
    307         float currentFraction = anim.getAnimatedFraction();
    308         float currentValue = (Float) anim.getAnimatedValue();
    309         assertEquals(proposedCurrentPlayTime, currentPlayTime);
    310         assertEquals(.5f, currentFraction, EPSILON);
    311         assertEquals(50, currentValue, EPSILON);
    312     }
    313 
    314     @UiThreadTest
    315     @Test
    316     public void testReverseRightAfterStart() {
    317         // Reverse() right after start() should trigger immediate end() at fraction 0.
    318         final ValueAnimator anim = ValueAnimator.ofFloat(0, 100).setDuration(mDuration);
    319         anim.start();
    320         assertTrue(anim.isStarted());
    321         anim.reverse();
    322         assertFalse(anim.isStarted());
    323         assertEquals(0f, anim.getAnimatedFraction(), 0.0f);
    324     }
    325 
    326     @Test
    327     public void testGetFrameDelay() throws Throwable {
    328         final long frameDelay = 10;
    329         mActivityRule.runOnUiThread(() -> mValueAnimator.setFrameDelay(frameDelay));
    330         startAnimation(mValueAnimator);
    331         SystemClock.sleep(100);
    332         mActivityRule.runOnUiThread(() -> {
    333             long actualFrameDelay = mValueAnimator.getFrameDelay();
    334             assertEquals(frameDelay, actualFrameDelay);
    335         });
    336     }
    337 
    338     @Test
    339     public void testUpdateListeners() throws Throwable {
    340         final AnimatorSetTest.MyListener myListener = new AnimatorSetTest.MyListener();
    341         ValueAnimator.AnimatorUpdateListener l1 = mock(ValueAnimator.AnimatorUpdateListener.class);
    342         ValueAnimator.AnimatorUpdateListener l2 = mock(ValueAnimator.AnimatorUpdateListener.class);
    343         ValueAnimator.AnimatorUpdateListener l3 = mock(ValueAnimator.AnimatorUpdateListener.class);
    344         ValueAnimator.AnimatorUpdateListener l4 = mock(ValueAnimator.AnimatorUpdateListener.class);
    345 
    346         AnimatorListenerAdapter listener = mock(AnimatorListenerAdapter.class);
    347 
    348         ValueAnimator a1 = ValueAnimator.ofFloat(0, 1f);
    349         a1.setDuration(50);
    350         a1.addUpdateListener(l1);
    351         a1.addUpdateListener(l2);
    352         a1.removeAllUpdateListeners();
    353 
    354         a1.addUpdateListener(l3);
    355         a1.addUpdateListener(l4);
    356         a1.removeUpdateListener(l3);
    357 
    358         a1.addListener(listener);
    359         a1.addListener(myListener);
    360 
    361         mActivityRule.runOnUiThread(() -> {
    362             a1.start();
    363         });
    364 
    365         // Wait for the anim to finish.
    366         verify(listener, within(200)).onAnimationEnd(a1, false);
    367         // Also make sure the onAnimationEnd(anim) is called.
    368         assertTrue(myListener.mEndIsCalled);
    369 
    370         verify(l1, times(0)).onAnimationUpdate(a1);
    371         verify(l2, times(0)).onAnimationUpdate(a1);
    372         verify(l3, times(0)).onAnimationUpdate(a1);
    373         verify(l4, atLeast(1)).onAnimationUpdate(a1);
    374     }
    375 
    376     @Test
    377     public void testValuesSetterAndGetter() throws Throwable {
    378 
    379         final AnimatorSetTest.MyListener myListener = new AnimatorSetTest.MyListener();
    380         ValueAnimator a2 = ValueAnimator.ofPropertyValuesHolder();
    381         PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("scaleX", 0f, 1f);
    382         PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("scaleY", 1f, 2f);
    383         a2.setValues(p1, p2);
    384         PropertyValuesHolder[] holders = a2.getValues();
    385         assertEquals(2, holders.length);
    386 
    387         // Use the PropertyValueHolders returned from the getter to initialize the animator, in
    388         // order to test the getter.
    389         ValueAnimator a1 = ValueAnimator.ofPropertyValuesHolder(holders);
    390         a1.setDuration(50);
    391         a1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    392             @Override
    393             public void onAnimationUpdate(ValueAnimator animation) {
    394                 float scaleX = (Float) animation.getAnimatedValue("scaleX");
    395                 float scaleY = (Float) animation.getAnimatedValue("scaleY");
    396                 assertTrue(scaleX >= 0f && scaleX <= 1f);
    397                 assertTrue(scaleY >= 1f && scaleY <= 2f);
    398             }
    399         });
    400         AnimatorListenerAdapter l1 = mock(AnimatorListenerAdapter.class);
    401         a1.addListener(l1);
    402         a1.addListener(myListener);
    403 
    404         mActivityRule.runOnUiThread(() -> {
    405             a1.start();
    406         });
    407 
    408         verify(l1, within(200)).onAnimationEnd(a1, false);
    409         // Also make sure the onAnimationEnd(anim) is called.
    410         assertTrue(myListener.mEndIsCalled);
    411     }
    412 
    413     @Test
    414     public void testSetObjectValues() throws Throwable {
    415         TypeEvaluator<PointF> eval = new TypeEvaluator<PointF>() {
    416             PointF tmpValue = new PointF();
    417             @Override
    418             public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
    419                 tmpValue.x = fraction * startValue.x + (1f - fraction) * endValue.x;
    420                 tmpValue.y = fraction * startValue.y + (1f - fraction) * endValue.y;
    421                 return tmpValue;
    422             }
    423         };
    424 
    425         final AnimatorSetTest.MyListener myListener = new AnimatorSetTest.MyListener();
    426         ValueAnimator a1 = new ValueAnimator();
    427         a1.setDuration(50);
    428         a1.setObjectValues(new PointF(0, 0), new PointF(1, 1));
    429         a1.setEvaluator(eval);
    430         a1.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    431             @Override
    432             public void onAnimationUpdate(ValueAnimator animation) {
    433                 PointF point = (PointF) animation.getAnimatedValue();
    434                 assertTrue(point.x >= 0f && point.x <= 1f);
    435                 assertTrue(point.y >= 0f && point.y <= 1f);
    436             }
    437         });
    438         AnimatorListenerAdapter l1 = mock(AnimatorListenerAdapter.class);
    439         a1.addListener(l1);
    440         a1.addListener(myListener);
    441         mActivityRule.runOnUiThread(() -> {
    442             a1.start();
    443         });
    444 
    445         verify(l1, within(200)).onAnimationEnd(a1, false);
    446         // Also make sure the onAnimationEnd(anim) is called.
    447         assertTrue(myListener.mEndIsCalled);
    448     }
    449 
    450     @Test
    451     public void testSetInterpolator() throws Throwable {
    452         AccelerateInterpolator interpolator = new AccelerateInterpolator();
    453         ValueAnimator mValueAnimator = mActivity.createAnimatorWithInterpolator(interpolator);
    454         startAnimation(mValueAnimator);
    455         assertTrue(interpolator.equals(mValueAnimator.getInterpolator()));
    456     }
    457 
    458     @Test
    459     public void testCancel() throws Throwable {
    460         startAnimation(mValueAnimator);
    461         SystemClock.sleep(100);
    462         cancelAnimation(mValueAnimator);
    463         assertFalse(mValueAnimator.isRunning());
    464     }
    465 
    466     @Test
    467     public void testEnd() throws Throwable {
    468         Object object = mActivity.view.newBall;
    469         String property = "y";
    470         float startY = mActivity.mStartY;
    471         float endY = mActivity.mStartY + mActivity.mDeltaY;
    472         ObjectAnimator objAnimator = ObjectAnimator.ofFloat(object, property, startY, endY);
    473         objAnimator.setDuration(mDuration);
    474         objAnimator.setRepeatCount(ValueAnimator.INFINITE);
    475         objAnimator.setInterpolator(new AccelerateInterpolator());
    476         objAnimator.setRepeatMode(ValueAnimator.REVERSE);
    477         startAnimation(objAnimator);
    478         SystemClock.sleep(100);
    479         endAnimation(objAnimator);
    480         float y = mActivity.view.newBall.getY();
    481         assertEquals(y, endY, 0.0f);
    482     }
    483 
    484     @Test
    485     public void testGetAnimatedFraction() throws Throwable {
    486         ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
    487         assertNotNull(animator);
    488         animator.setDuration(200);
    489         animator.addUpdateListener(new AnimatorUpdateListener() {
    490             public float lastFraction = 0;
    491             @Override
    492             public void onAnimationUpdate(ValueAnimator animation) {
    493                 float currentFraction = animation.getAnimatedFraction();
    494                 assertTrue(
    495                         "Last fraction = " + lastFraction + "current fraction = " + currentFraction,
    496                         animation.getAnimatedFraction() >= lastFraction);
    497                 lastFraction = currentFraction;
    498                 assertTrue(currentFraction <= 1f);
    499             }
    500         });
    501         CountDownLatch latch = new CountDownLatch(1);
    502         animator.addListener(new AnimatorListenerAdapter() {
    503             @Override
    504             public void onAnimationEnd(Animator animation) {
    505                 latch.countDown();
    506             }
    507         });
    508         mActivityRule.runOnUiThread(() -> {
    509             animator.start();
    510         });
    511 
    512         latch.await(1000, TimeUnit.MILLISECONDS);
    513 
    514         assertEquals(1.0f, animator.getAnimatedFraction(), EPSILON);
    515     }
    516 
    517     class TestInterpolator implements TimeInterpolator {
    518 
    519         @Override
    520         public float getInterpolation(float input) {
    521             return input * input;
    522         }
    523     }
    524 
    525     @Test
    526     public void testGetAnimatedValue() {
    527         ValueAnimator animator = ValueAnimator.ofFloat(0f, 1f);
    528         assertNotNull(animator);
    529         TimeInterpolator myInterpolator = new TestInterpolator();
    530         animator.setInterpolator(myInterpolator);
    531         int sliceNum = 10;
    532         for (int i = 0; i <= sliceNum; i++) {
    533             float fraction = i / (float) sliceNum;
    534             animator.setCurrentFraction(fraction);
    535             assertEquals(myInterpolator.getInterpolation(fraction),
    536                     (float) animator.getAnimatedValue(), EPSILON);
    537 
    538         }
    539     }
    540 
    541     @Test
    542     public void testGetAnimatedValue_PropertyName() {
    543         PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 100f, -100f);
    544         PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 0f, 1f);
    545         ValueAnimator animator = ValueAnimator.ofPropertyValuesHolder(pvhX, pvhY);
    546         assertNotNull(animator);
    547         TimeInterpolator myInterpolator = new TestInterpolator();
    548         animator.setInterpolator(myInterpolator);
    549         int sliceNum = 10;
    550         for (int i = 0; i <= sliceNum; i++) {
    551             float fraction = i / (float) sliceNum;
    552             animator.setCurrentFraction(fraction);
    553             assertEquals(myInterpolator.getInterpolation(fraction),
    554                     (float) animator.getAnimatedValue("y"), EPSILON);
    555 
    556         }
    557     }
    558 
    559     @Test
    560     public void testOfFloat() throws Throwable {
    561         float start = 0.0f;
    562         float end = 1.0f;
    563         float[] values = {start, end};
    564         final ValueAnimator valueAnimatorLocal = ValueAnimator.ofFloat(values);
    565         valueAnimatorLocal.setDuration(mDuration);
    566         valueAnimatorLocal.setRepeatCount(ValueAnimator.INFINITE);
    567         valueAnimatorLocal.setInterpolator(new AccelerateInterpolator());
    568         valueAnimatorLocal.setRepeatMode(ValueAnimator.RESTART);
    569 
    570         mActivityRule.runOnUiThread(valueAnimatorLocal::start);
    571         SystemClock.sleep(100);
    572         boolean isRunning = valueAnimatorLocal.isRunning();
    573         assertTrue(isRunning);
    574 
    575         Float animatedValue = (Float) valueAnimatorLocal.getAnimatedValue();
    576         assertTrue(animatedValue >= start);
    577         assertTrue(animatedValue <= end);
    578     }
    579 
    580     @Test
    581     public void testOfInt() throws Throwable {
    582         int start = 0;
    583         int end = 10;
    584         int[] values = {start, end};
    585         final ValueAnimator valueAnimatorLocal = ValueAnimator.ofInt(values);
    586         valueAnimatorLocal.setDuration(mDuration);
    587         valueAnimatorLocal.setRepeatCount(ValueAnimator.INFINITE);
    588         valueAnimatorLocal.setInterpolator(new AccelerateInterpolator());
    589         valueAnimatorLocal.setRepeatMode(ValueAnimator.RESTART);
    590 
    591         mActivityRule.runOnUiThread(valueAnimatorLocal::start);
    592         SystemClock.sleep(100);
    593         boolean isRunning = valueAnimatorLocal.isRunning();
    594         assertTrue(isRunning);
    595 
    596         Integer animatedValue = (Integer) valueAnimatorLocal.getAnimatedValue();
    597         assertTrue(animatedValue >= start);
    598         assertTrue(animatedValue <= end);
    599     }
    600 
    601     @Test
    602     public void testOfArgb() throws Throwable {
    603         int start = 0xffff0000;
    604         int end = 0xff0000ff;
    605         int[] values = {start, end};
    606         int startRed = Color.red(start);
    607         int startBlue = Color.blue(start);
    608         int endRed = Color.red(end);
    609         int endBlue = Color.blue(end);
    610         final ValueAnimator valueAnimatorLocal = ValueAnimator.ofArgb(values);
    611         valueAnimatorLocal.setDuration(mDuration);
    612 
    613         final CountDownLatch latch = new CountDownLatch(1);
    614         valueAnimatorLocal.addUpdateListener((ValueAnimator animation) -> {
    615             if (animation.getAnimatedFraction() > .05f) {
    616                 latch.countDown();
    617             }
    618         });
    619 
    620         mActivityRule.runOnUiThread(valueAnimatorLocal::start);
    621         boolean isRunning = valueAnimatorLocal.isRunning();
    622         assertTrue(isRunning);
    623 
    624         assertTrue(latch.await(500, TimeUnit.MILLISECONDS));
    625 
    626         Integer animatedValue = (Integer) valueAnimatorLocal.getAnimatedValue();
    627         int alpha = Color.alpha(animatedValue);
    628         int red = Color.red(animatedValue);
    629         int green = Color.green(animatedValue);
    630         int blue = Color.blue(animatedValue);
    631         assertTrue(red < startRed);
    632         assertTrue(red > endRed);
    633         assertTrue(blue > startBlue);
    634         assertTrue(blue < endBlue);
    635         assertEquals(255, alpha);
    636         assertEquals(0, green);
    637 
    638         mActivityRule.runOnUiThread(valueAnimatorLocal::cancel);
    639     }
    640 
    641     @Test
    642     public void testNoDelayOnSeekAnimation() throws Throwable {
    643         ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
    644         animator.setInterpolator(new LinearInterpolator());
    645         animator.setStartDelay(1000);
    646         animator.setDuration(300);
    647         animator.setCurrentPlayTime(150);
    648         final Animator.AnimatorListener watcher = mock(Animator.AnimatorListener.class);
    649         animator.addListener(watcher);
    650         mActivityRule.runOnUiThread(animator::start);
    651         verify(watcher, times(1)).onAnimationStart(animator, false);
    652         assertTrue(((Float)animator.getAnimatedValue()) >= 0.5f);
    653         assertTrue(animator.getAnimatedFraction() >= 0.5f);
    654         mActivityRule.runOnUiThread(animator::cancel);
    655     }
    656 
    657     @Test
    658     public void testNotifiesAfterEnd() throws Throwable {
    659         final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
    660         animator.addListener(new AnimatorListenerAdapter() {
    661             @Override
    662             public void onAnimationStart(Animator animation) {
    663                 assertTrue(animation.isStarted());
    664                 assertTrue(animation.isRunning());
    665             }
    666 
    667             @Override
    668             public void onAnimationEnd(Animator animation) {
    669                 assertFalse(animation.isRunning());
    670                 assertFalse(animation.isStarted());
    671                 super.onAnimationEnd(animation);
    672             }
    673         });
    674         mActivityRule.runOnUiThread(() -> {
    675             animator.start();
    676             animator.end();
    677         });
    678     }
    679 
    680     @Test
    681     public void testAnimatorsEnabled() throws Throwable {
    682         float currentDurationScale = ValueAnimator.getDurationScale();
    683         try {
    684             testAnimatorsEnabledImpl(true);
    685             testAnimatorsEnabledImpl(false);
    686         } finally {
    687             // restore scale value to avoid messing up future tests
    688             ValueAnimator.setDurationScale(currentDurationScale);
    689         }
    690     }
    691 
    692     private void testAnimatorsEnabledImpl(boolean enabled) throws Throwable {
    693         final CountDownLatch startLatch = new CountDownLatch(1);
    694         final CountDownLatch endLatch = new CountDownLatch(1);
    695         final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
    696         animator.setDuration(1000);
    697         animator.addListener(new AnimatorListenerAdapter() {
    698             @Override
    699             public void onAnimationEnd(Animator animation) {
    700                 endLatch.countDown();
    701             }
    702         });
    703         mActivityRule.runOnUiThread(() -> {
    704             animator.start();
    705             startLatch.countDown();
    706         });
    707 
    708         assertTrue(startLatch.await(200, TimeUnit.MILLISECONDS));
    709 
    710         float durationScale = enabled ? 1 : 0;
    711         ValueAnimator.setDurationScale(durationScale);
    712 
    713         if (enabled) {
    714             assertTrue("Animators not enabled with duration scale 1",
    715                     ValueAnimator.areAnimatorsEnabled());
    716             assertFalse("Animator ended too early when animators enabled = ",
    717                     endLatch.await(100, TimeUnit.MILLISECONDS));
    718         } else {
    719             assertFalse("Animators enabled with duration scale 0",
    720                     ValueAnimator.areAnimatorsEnabled());
    721             assertTrue("Animator did not end when animators enabled = ",
    722                     endLatch.await(100, TimeUnit.MILLISECONDS));
    723         }
    724         mActivityRule.runOnUiThread(() -> {
    725             animator.end();
    726         });
    727     }
    728 
    729     private ValueAnimator getAnimator() {
    730         Object object = mActivity.view.newBall;
    731         String property = "y";
    732         float startY = mActivity.mStartY;
    733         float endY = mActivity.mStartY + mActivity.mDeltaY;
    734         ValueAnimator objAnimator = ObjectAnimator.ofFloat(object, property, startY, endY);
    735         objAnimator.setDuration(mDuration);
    736         objAnimator.setRepeatCount(ValueAnimator.INFINITE);
    737         objAnimator.setInterpolator(new AccelerateInterpolator());
    738         objAnimator.setRepeatMode(ValueAnimator.REVERSE);
    739         return objAnimator;
    740     }
    741 
    742     private void startAnimation(final ValueAnimator animator) throws Throwable {
    743         mActivityRule.runOnUiThread(() -> mActivity.startAnimation(animator));
    744     }
    745 
    746     private void endAnimation(final ValueAnimator animator) throws Throwable {
    747         mActivityRule.runOnUiThread(animator::end);
    748     }
    749 
    750     private void cancelAnimation(final ValueAnimator animator) throws Throwable {
    751         mActivityRule.runOnUiThread(animator::cancel);
    752     }
    753 
    754     private String errorMessage(float[] values) {
    755         StringBuilder message = new StringBuilder();
    756         for (int i = 0; i < values.length; i++) {
    757             message.append(values[i]).append(" ");
    758         }
    759         return message.toString();
    760     }
    761 }
    762