Home | History | Annotate | Download | only in cts
      1 /*
      2 * Copyright (C) 2014 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.view.animation.cts;
     17 
     18 import static org.junit.Assert.assertEquals;
     19 import static org.junit.Assert.assertFalse;
     20 import static org.junit.Assert.assertNotSame;
     21 import static org.junit.Assert.assertSame;
     22 import static org.junit.Assert.assertTrue;
     23 
     24 import android.animation.Animator;
     25 import android.animation.AnimatorInflater;
     26 import android.animation.AnimatorListenerAdapter;
     27 import android.animation.AnimatorSet;
     28 import android.animation.ObjectAnimator;
     29 import android.animation.StateListAnimator;
     30 import android.app.Instrumentation;
     31 import android.app.UiAutomation;
     32 import android.content.Context;
     33 import android.support.test.InstrumentationRegistry;
     34 import android.support.test.filters.MediumTest;
     35 import android.support.test.rule.ActivityTestRule;
     36 import android.support.test.runner.AndroidJUnit4;
     37 import android.util.Log;
     38 import android.view.Display;
     39 import android.view.Surface;
     40 import android.view.View;
     41 import android.view.WindowManager;
     42 import android.view.cts.R;
     43 
     44 import org.junit.Before;
     45 import org.junit.After;
     46 import org.junit.Rule;
     47 import org.junit.Test;
     48 import org.junit.runner.RunWith;
     49 
     50 import java.util.HashSet;
     51 import java.util.Set;
     52 import java.util.concurrent.CountDownLatch;
     53 import java.util.concurrent.TimeUnit;
     54 
     55 @MediumTest
     56 @RunWith(AndroidJUnit4.class)
     57 public class AnimatorInflaterTest {
     58     private static final String TAG = "AnimatorInflaterTest";
     59 
     60     private Instrumentation mInstrumentation;
     61     private AnimationTestCtsActivity mActivity;
     62     private View mTestView;
     63     private int mUserRotation;
     64 
     65     Set<Integer> identityHashes = new HashSet<>();
     66 
     67     @Rule
     68     public ActivityTestRule<AnimationTestCtsActivity> mActivityRule =
     69             new ActivityTestRule<>(AnimationTestCtsActivity.class);
     70 
     71     @Before
     72     public void setup() {
     73         mInstrumentation = InstrumentationRegistry.getInstrumentation();
     74         mActivity = mActivityRule.getActivity();
     75         mTestView = mActivity.findViewById(R.id.anim_window);
     76         mUserRotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
     77     }
     78 
     79     @After
     80     public void tearDown() {
     81         mInstrumentation.getUiAutomation().setRotation(mUserRotation);
     82     }
     83 
     84     private void assertUnique(Object object) {
     85         assertUnique(object, "");
     86     }
     87 
     88     private void assertUnique(Object object, String msg) {
     89         final int code = System.identityHashCode(object);
     90         assertTrue("object should be unique " + msg + ", obj:" + object, identityHashes.add(code));
     91     }
     92 
     93     @Test
     94     public void testLoadAnimatorWithDifferentInterpolators() throws Throwable {
     95         Animator anim1 = AnimatorInflater .loadAnimator(mActivity, R.anim.changing_test_animator);
     96         if (!rotate()) {
     97             return;//cancel test
     98         }
     99         Animator anim2 = AnimatorInflater .loadAnimator(mActivity, R.anim.changing_test_animator);
    100         assertNotSame(anim1, anim2);
    101         assertNotSame("interpolater is orientation dependent, should change",
    102                 anim1.getInterpolator(), anim2.getInterpolator());
    103     }
    104 
    105     /**
    106      * Tests animators with dimension references.
    107      */
    108     @Test
    109     public void testLoadAnimator() throws Throwable {
    110         // to identify objects
    111         Animator anim1 = AnimatorInflater.loadAnimator(mActivity, R.anim.test_animator);
    112         Animator anim2 = AnimatorInflater.loadAnimator(mActivity, R.anim.test_animator);
    113         assertNotSame("a different animation should be returned", anim1, anim2);
    114         assertSame("interpolator should be shallow cloned", anim1.getInterpolator(),
    115                 anim2.getInterpolator());
    116         for (int i = 0; i < 2; i++) {
    117             float targetX = mActivity.getResources()
    118                     .getDimension(R.dimen.test_animator_target_x);
    119             // y value changes in landscape orientation
    120             float targetY = mActivity.getResources()
    121                     .getDimension(R.dimen.test_animator_target_y);
    122             for (Animator anim : new Animator[]{anim1, anim2}) {
    123                 assertTrue(anim instanceof AnimatorSet);
    124                 assertUnique(anim);
    125                 AnimatorSet set = (AnimatorSet) anim;
    126                 assertEquals("should have 3 sub animations", 3, set.getChildAnimations().size());
    127                 for (Animator subAnim : set.getChildAnimations()) {
    128                     assertUnique(subAnim);
    129                     assertTrue(subAnim instanceof ObjectAnimator);
    130                 }
    131                 final ObjectAnimator child1 = (ObjectAnimator) set.getChildAnimations().get(0);
    132                 final ObjectAnimator child2 = (ObjectAnimator) set.getChildAnimations().get(1);
    133                 final DummyObject dummyObject = new DummyObject();
    134                 mActivityRule.runOnUiThread(() -> {
    135                     for (ObjectAnimator animator : new ObjectAnimator[]{child1, child2}) {
    136                         animator.setTarget(dummyObject);
    137                         animator.setupStartValues();
    138                         animator.start();
    139                         animator.end();
    140                     }
    141                 });
    142                 assertEquals(targetX, dummyObject.x, 0.0f);
    143                 assertEquals(targetY, dummyObject.y, 0.0f);
    144             }
    145             if (i == 0) {
    146                 if (!rotate()) {
    147                     return;//cancel test
    148                 }
    149             }
    150             anim1 = AnimatorInflater.loadAnimator(mActivity, R.anim.test_animator);
    151             anim2 = AnimatorInflater.loadAnimator(mActivity, R.anim.test_animator);
    152 
    153         }
    154     }
    155 
    156     private boolean rotate() throws Throwable {
    157         WindowManager mWindowManager = (WindowManager) mActivity
    158                 .getSystemService(Context.WINDOW_SERVICE);
    159         Display display = mWindowManager.getDefaultDisplay();
    160         int orientation = mActivity.getResources().getConfiguration().orientation;
    161 
    162         Instrumentation.ActivityMonitor monitor = new Instrumentation.ActivityMonitor(
    163                 mActivity.getClass().getName(), null, false);
    164         mInstrumentation.addMonitor(monitor);
    165         int nextRotation = 0;
    166         switch (display.getRotation()) {
    167             case Surface.ROTATION_0:
    168             case Surface.ROTATION_180:
    169                 nextRotation = UiAutomation.ROTATION_FREEZE_90;
    170                 break;
    171             case Surface.ROTATION_90:
    172             case Surface.ROTATION_270:
    173                 nextRotation = UiAutomation.ROTATION_FREEZE_0;
    174                 break;
    175             default:
    176                 Log.e(TAG, "Cannot get rotation, test is canceled");
    177                 return false;
    178         }
    179         boolean rotated = mInstrumentation.getUiAutomation().setRotation(nextRotation);
    180         Thread.sleep(500);
    181         if (!rotated) {
    182             Log.e(TAG, "Rotation failed, test is canceled");
    183         }
    184         mInstrumentation.waitForIdleSync();
    185         if (!mActivity.waitUntilVisible()) {
    186             Log.e(TAG, "Activity failed to complete rotation, canceling test");
    187             return false;
    188         }
    189         if (mActivity.getWindowManager().getDefaultDisplay().getRotation() != nextRotation) {
    190             Log.e(TAG, "New activity orientation does not match. Canceling test");
    191             return false;
    192         }
    193         if (mActivity.getResources().getConfiguration().orientation == orientation) {
    194             Log.e(TAG, "Screen orientation didn't change, test is canceled");
    195             return false;
    196         }
    197         return true;
    198     }
    199 
    200     /**
    201      * Simple state list animator test that checks for cloning
    202      */
    203     @Test
    204     public void testLoadStateListAnimator() {
    205         StateListAnimator sla1 = AnimatorInflater.loadStateListAnimator(mActivity,
    206                 R.anim.test_state_list_animator);
    207         StateListAnimator sla2 = AnimatorInflater.loadStateListAnimator(mActivity,
    208                 R.anim.test_state_list_animator);
    209         assertUnique(sla1);
    210         assertUnique(sla2);
    211     }
    212 
    213     /**
    214      * Tests a state list animator which has an @anim reference that has different xmls per
    215      * orientation
    216      */
    217     @Test
    218     public void testLoadStateListAnimatorWithChangingResetState() throws Throwable {
    219         loadStateListAnimatorWithChangingResetStateTest();
    220         if (!rotate()) {
    221             return;//cancel test
    222         }
    223 
    224         loadStateListAnimatorWithChangingResetStateTest();
    225     }
    226 
    227     private void loadStateListAnimatorWithChangingResetStateTest() throws Throwable {
    228         final StateListAnimator sla = AnimatorInflater.loadStateListAnimator(mActivity,
    229                 R.anim.test_state_list_animator_2);
    230         mActivityRule.runOnUiThread(() -> {
    231             mTestView.setStateListAnimator(sla);
    232             mTestView.jumpDrawablesToCurrentState();
    233         });
    234         float resetValue = mActivity.getResources().getDimension(R.dimen.reset_state_value);
    235         mInstrumentation.waitForIdleSync();
    236         assertEquals(resetValue, mTestView.getX(), 0.0f);
    237         assertEquals(resetValue, mTestView.getY(), 0.0f);
    238         assertEquals(resetValue, mTestView.getZ(), 0.0f);
    239     }
    240 
    241     /**
    242      * Tests a state list animator which has different xml descriptions per orientation.
    243      */
    244     @Test
    245     public void testLoadChangingStateListAnimator() throws Throwable {
    246         loadChangingStateListAnimatorTest();
    247         if (!rotate()) {
    248             return;//cancel test
    249         }
    250         loadChangingStateListAnimatorTest();
    251     }
    252 
    253     private void loadChangingStateListAnimatorTest() throws Throwable {
    254         final StateListAnimator sla = AnimatorInflater.loadStateListAnimator(mActivity,
    255                 R.anim.changing_state_list_animator);
    256         mActivityRule.runOnUiThread(() -> {
    257             mTestView.setStateListAnimator(sla);
    258             mTestView.jumpDrawablesToCurrentState();
    259         });
    260         float targetValue = mActivity.getResources()
    261                 .getDimension(R.dimen.changing_state_list_anim_target_x_value);
    262         mInstrumentation.waitForIdleSync();
    263         assertEquals(targetValue, mTestView.getX(), 0.0f);
    264     }
    265 
    266     /**
    267      * Tests that makes sure that reloaded animator is not affected by previous changes
    268      */
    269     @Test
    270     public void testReloadedAnimatorIsNotModified() throws Throwable {
    271         final Animator anim1 = AnimatorInflater.loadAnimator(mActivity, R.anim.test_animator);
    272         final CountDownLatch mStarted = new CountDownLatch(1);
    273         final AnimatorListenerAdapter listener = new AnimatorListenerAdapter() {
    274             @Override
    275             public void onAnimationEnd(Animator animation) {
    276                 super.onAnimationEnd(animation);
    277             }
    278 
    279             @Override
    280             public void onAnimationStart(Animator animation) {
    281                 super.onAnimationStart(animation);
    282                 mStarted.countDown();
    283             }
    284         };
    285         mActivityRule.runOnUiThread(() -> {
    286             anim1.setTarget(mTestView);
    287             anim1.addListener(listener);
    288             anim1.start();
    289         });
    290         Animator anim2 = AnimatorInflater.loadAnimator(mActivity, R.anim.test_animator);
    291         assertTrue(anim1.isStarted());
    292         assertFalse(anim2.isStarted());
    293         assertFalse("anim2 should not include the listener",
    294                 anim2.getListeners() != null && anim2.getListeners().contains(listener));
    295         assertTrue("animator should start", mStarted.await(10, TimeUnit.SECONDS));
    296         assertFalse(anim2.isRunning());
    297 
    298     }
    299 
    300     class DummyObject {
    301 
    302         float x;
    303         float y;
    304 
    305         public float getX() {
    306             return x;
    307         }
    308 
    309         public void setX(float x) {
    310             this.x = x;
    311         }
    312 
    313         public float getY() {
    314             return y;
    315         }
    316 
    317         public void setY(float y) {
    318             this.y = y;
    319         }
    320     }
    321 }
    322 
    323