1 /* 2 * Copyright (C) 2008 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 17 package android.view.animation.cts; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertSame; 23 import static org.junit.Assert.assertTrue; 24 25 import android.Manifest; 26 import android.app.Activity; 27 import android.app.Instrumentation; 28 import android.content.res.XmlResourceParser; 29 import android.platform.test.annotations.AppModeSdkSandbox; 30 import android.util.AttributeSet; 31 import android.util.Xml; 32 import android.view.View; 33 import android.view.animation.AccelerateInterpolator; 34 import android.view.animation.AlphaAnimation; 35 import android.view.animation.Animation; 36 import android.view.animation.AnimationSet; 37 import android.view.animation.ScaleAnimation; 38 import android.view.animation.Transformation; 39 import android.view.animation.TranslateAnimation; 40 import android.view.cts.R; 41 42 import androidx.test.InstrumentationRegistry; 43 import androidx.test.filters.MediumTest; 44 import androidx.test.rule.ActivityTestRule; 45 import androidx.test.runner.AndroidJUnit4; 46 47 import com.android.compatibility.common.util.AdoptShellPermissionsRule; 48 49 import org.junit.Before; 50 import org.junit.Rule; 51 import org.junit.Test; 52 import org.junit.runner.RunWith; 53 54 import java.util.List; 55 56 @MediumTest 57 @RunWith(AndroidJUnit4.class) 58 @AppModeSdkSandbox(reason = "Allow test in the SDK sandbox (does not prevent other modes).") 59 public class AnimationSetTest { 60 private static final float DELTA = 0.001f; 61 private static final long SHORT_CHILD_DURATION = 400; 62 private static final long MEDIUM_CHILD_DURATION = 800; 63 private static final long LONG_CHILD_DURATION = 1200; 64 /** 65 * initial size for initialize(int width, int height, int parentWidth, int parentHeight) 66 */ 67 private static final int INITIAL_SIZE = 100; 68 private static final long ANIMATIONSET_DURATION = 1000; 69 70 private Instrumentation mInstrumentation; 71 private Activity mActivity; 72 73 @Rule(order = 0) 74 public AdoptShellPermissionsRule mAdoptShellPermissionsRule = new AdoptShellPermissionsRule( 75 androidx.test.platform.app.InstrumentationRegistry 76 .getInstrumentation().getUiAutomation(), 77 Manifest.permission.START_ACTIVITIES_FROM_SDK_SANDBOX); 78 79 @Rule(order = 1) 80 public ActivityTestRule<AnimationTestCtsActivity> mActivityRule = 81 new ActivityTestRule<>(AnimationTestCtsActivity.class); 82 83 @Before setup()84 public void setup() { 85 mInstrumentation = InstrumentationRegistry.getInstrumentation(); 86 mActivity = mActivityRule.getActivity(); 87 } 88 89 @Test testConstructor()90 public void testConstructor() { 91 new AnimationSet(true); 92 93 final XmlResourceParser parser = mActivity.getResources().getAnimation( 94 R.anim.anim_set); 95 final AttributeSet attr = Xml.asAttributeSet(parser); 96 assertNotNull(attr); 97 // Test with real AttributeSet 98 new AnimationSet(mActivity, attr); 99 } 100 101 @Test testInitialize()102 public void testInitialize() { 103 final AnimationSet animationSet = createAnimationSet(); 104 animationSet.setDuration(ANIMATIONSET_DURATION); 105 // Before initialize, the durations are original. 106 List<Animation> children = animationSet.getAnimations(); 107 assertEquals(SHORT_CHILD_DURATION, children.get(0).getDuration()); 108 assertEquals(MEDIUM_CHILD_DURATION, children.get(1).getDuration()); 109 assertEquals(LONG_CHILD_DURATION, children.get(2).getDuration()); 110 111 // After initialize, AnimationSet override the child values. 112 assertFalse(animationSet.isInitialized()); 113 animationSet.initialize(INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE); 114 assertTrue(animationSet.isInitialized()); 115 children = animationSet.getAnimations(); 116 assertEquals(ANIMATIONSET_DURATION, children.get(0).getDuration()); 117 assertEquals(ANIMATIONSET_DURATION, children.get(1).getDuration()); 118 assertEquals(ANIMATIONSET_DURATION, children.get(2).getDuration()); 119 } 120 createAnimationSet()121 private AnimationSet createAnimationSet() { 122 AnimationSet animationSet = new AnimationSet(true); 123 124 Animation animation1 = new AlphaAnimation(0.0f, 1.0f); 125 animation1.setDuration(SHORT_CHILD_DURATION); 126 animationSet.addAnimation(animation1); 127 128 Animation animation2 = new ScaleAnimation(1.0f, 2.0f, 1.0f, 3.0f); 129 animation2.setDuration(MEDIUM_CHILD_DURATION); 130 animationSet.addAnimation(animation2); 131 132 Animation animation3 = new TranslateAnimation(0.0f, 50.0f, 0.0f, 5.0f); 133 animation3.setDuration(LONG_CHILD_DURATION); 134 animationSet.addAnimation(animation3); 135 136 return animationSet; 137 } 138 139 @Test testSetFillAfter()140 public void testSetFillAfter() { 141 final AnimationSet animationSet = createAnimationSet(); 142 assertFalse(animationSet.getFillAfter()); 143 144 List<Animation> children = animationSet.getAnimations(); 145 children.get(0).setFillAfter(true); 146 children.get(1).setFillAfter(false); 147 148 animationSet.setFillAfter(true); 149 animationSet.initialize(INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE); 150 assertTrue(animationSet.getFillAfter()); 151 children = animationSet.getAnimations(); 152 for (int i = 0; i < children.size(); i++) { 153 assertTrue(children.get(i).getFillAfter()); 154 } 155 } 156 157 @Test testSetFillBefore()158 public void testSetFillBefore() { 159 final AnimationSet animationSet = createAnimationSet(); 160 assertTrue(animationSet.getFillBefore()); 161 162 List<Animation> children = animationSet.getAnimations(); 163 children.get(0).setFillBefore(true); 164 children.get(1).setFillBefore(false); 165 166 animationSet.setFillBefore(false); 167 animationSet.initialize(INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE); 168 assertFalse(animationSet.getFillBefore()); 169 children = animationSet.getAnimations(); 170 for (int i = 0; i < children.size(); i++) { 171 assertFalse(children.get(i).getFillBefore()); 172 } 173 } 174 175 @Test testAccessDuration()176 public void testAccessDuration() { 177 final AnimationSet animationSet = createAnimationSet(); 178 assertEquals(LONG_CHILD_DURATION, animationSet.getDuration()); 179 180 assertTrue(animationSet.getDuration() > ANIMATIONSET_DURATION); 181 animationSet.setDuration(ANIMATIONSET_DURATION); 182 animationSet.initialize(INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE); 183 assertEquals(ANIMATIONSET_DURATION, animationSet.getDuration()); 184 final List<Animation> children = animationSet.getAnimations(); 185 for (int i = 0; i < children.size(); i++) { 186 assertEquals(ANIMATIONSET_DURATION, children.get(i).getDuration()); 187 } 188 } 189 190 @Test testRestrictDuration()191 public void testRestrictDuration() { 192 final AnimationSet animationSet = new AnimationSet(false); 193 Animation child = null; 194 final long[] originChildDuration = { 1000, 1000, 500 }; 195 final long[] originChildStartOffset = { 2000, 1000, 0 }; 196 final int[] originChildRepeatCount = { 0, 0, 4 }; 197 final long[] originChildDurationHint = new long[3]; 198 for (int i = 0; i < 3; i++) { 199 child = new AlphaAnimation(0.0f, 1.0f); 200 child.setDuration(originChildDuration[i]); 201 child.setStartOffset(originChildStartOffset[i]); 202 child.setRepeatCount(originChildRepeatCount[i]); 203 originChildDurationHint[i] = child.computeDurationHint(); 204 animationSet.addAnimation(child); 205 } 206 final long restrictDuration = 1500; 207 animationSet.restrictDuration(restrictDuration); 208 final List<Animation> children = animationSet.getAnimations(); 209 210 assertTrue(originChildStartOffset[0] > restrictDuration); 211 assertEquals(0, children.get(0).getDuration()); 212 assertEquals(restrictDuration, children.get(0).getStartOffset()); 213 214 assertTrue(originChildStartOffset[1] < restrictDuration); 215 assertTrue(originChildDurationHint[1] > restrictDuration); 216 assertTrue(children.get(1).computeDurationHint() <= restrictDuration); 217 218 assertTrue(originChildDurationHint[2] > restrictDuration); 219 assertTrue(children.get(2).computeDurationHint() <= restrictDuration); 220 assertTrue(originChildRepeatCount[2] > children.get(2).getRepeatCount()); 221 } 222 223 @Test testComputeDurationHint()224 public void testComputeDurationHint() { 225 final AnimationSet animationSet = createAnimationSet(); 226 final List<Animation> children = animationSet.getAnimations(); 227 long expectedDuration = 0; 228 for (int i = 0; i < children.size(); i++) { 229 expectedDuration = Math.max(expectedDuration, children.get(i).computeDurationHint()); 230 } 231 assertEquals(expectedDuration, animationSet.computeDurationHint()); 232 } 233 234 @Test testScaleCurrentDuration()235 public void testScaleCurrentDuration() { 236 final AnimationSet animationSet = createAnimationSet(); 237 List<Animation> children = animationSet.getAnimations(); 238 final long[] originDurations = new long[children.size()]; 239 for (int i = 0; i < children.size(); i++) { 240 originDurations[i] = children.get(i).getDuration(); 241 } 242 243 final float scaleFactor = 2.0f; 244 animationSet.scaleCurrentDuration(scaleFactor); 245 children = animationSet.getAnimations(); 246 for (int i = 0; i < children.size(); i++) { 247 assertEquals((long) (originDurations[i] * scaleFactor), children.get(i).getDuration()); 248 } 249 } 250 251 @Test testAccessRepeatMode()252 public void testAccessRepeatMode() { 253 final AnimationSet animationSet = createAnimationSet(); 254 animationSet.setRepeatMode(Animation.RESTART); 255 animationSet.initialize(INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE); 256 assertEquals(Animation.RESTART, animationSet.getRepeatMode()); 257 List<Animation> children = animationSet.getAnimations(); 258 for (int i = 0; i < children.size(); i++) { 259 assertEquals(Animation.RESTART, children.get(i).getRepeatMode()); 260 } 261 262 animationSet.setRepeatMode(Animation.REVERSE); 263 animationSet.initialize(INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE); 264 assertEquals(Animation.REVERSE, animationSet.getRepeatMode()); 265 children = animationSet.getAnimations(); 266 for (int i = 0; i < children.size(); i++) { 267 assertEquals(Animation.REVERSE, children.get(i).getRepeatMode()); 268 } 269 } 270 271 @Test testAccessStartOffset()272 public void testAccessStartOffset() { 273 final AnimationSet animationSet = createAnimationSet(); 274 assertEquals(0, animationSet.getStartOffset()); 275 List<Animation> children = animationSet.getAnimations(); 276 final long[] originStartOffset = new long[children.size()]; 277 for (int i = 0; i < children.size(); i++) { 278 originStartOffset[i] = children.get(i).getStartOffset(); 279 } 280 281 animationSet.setStartOffset(100); 282 animationSet.initialize(INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE); 283 assertEquals(100, animationSet.getStartOffset()); 284 children = animationSet.getAnimations(); 285 for (int i = 0; i < children.size(); i++) { 286 assertEquals(originStartOffset[i] + animationSet.getStartOffset(), 287 children.get(i).getStartOffset()); 288 } 289 290 assertTrue(animationSet.isInitialized()); 291 animationSet.reset(); 292 assertFalse(animationSet.isInitialized()); 293 children = animationSet.getAnimations(); 294 for (int i = 0; i < children.size(); i++) { 295 assertEquals(originStartOffset[i], children.get(i).getStartOffset()); 296 } 297 } 298 299 @Test testAccessStartTime()300 public void testAccessStartTime() { 301 final AnimationSet animationSet = createAnimationSet(); 302 final long[] originChildStartTime = {1000, 2000, 3000}; 303 List<Animation> children = animationSet.getAnimations(); 304 for (int i = 0; i < children.size(); i++) { 305 children.get(i).setStartTime(originChildStartTime[i]); 306 } 307 308 // Get earliest start time of children animations 309 assertEquals(1000, animationSet.getStartTime()); 310 311 final long startTime = 200; 312 animationSet.setStartTime(startTime); 313 assertEquals(startTime, animationSet.getStartTime()); 314 315 children = animationSet.getAnimations(); 316 for (int i = 0; i < children.size(); i++) { 317 assertEquals(startTime, children.get(i).getStartTime()); 318 } 319 } 320 321 @Test testGetTransformation()322 public void testGetTransformation() throws Throwable { 323 final View animWindowParent = mActivity.findViewById(R.id.anim_window_parent); 324 final View animWindow = mActivity.findViewById(R.id.anim_window); 325 final AnimationSet animationSet = createAnimationSet(); 326 animationSet.setDuration(2000); 327 animationSet.initialize(animWindow.getWidth(), animWindow.getHeight(), 328 animWindowParent.getWidth(), animWindowParent.getHeight()); 329 330 AnimationTestUtils.assertRunAnimation(mInstrumentation, mActivityRule, animWindow, 331 animationSet); 332 final long startTime = animationSet.getStartTime(); 333 334 assertGetTransformation(animationSet, startTime, true); 335 assertGetTransformation(animationSet, startTime + 100, true); 336 assertGetTransformation(animationSet, startTime + animationSet.getDuration(), false); 337 } 338 assertGetTransformation(final AnimationSet animationSet, final long currentTime, final boolean result)339 private void assertGetTransformation(final AnimationSet animationSet, 340 final long currentTime, final boolean result) { 341 final Transformation transformation = new Transformation(); 342 final Transformation expectedTransformation = new Transformation(); 343 final Transformation tempTransformation = new Transformation(); 344 345 assertEquals(result, animationSet.getTransformation(currentTime, transformation)); 346 final List<Animation> children = animationSet.getAnimations(); 347 for (int i = children.size() - 1; i >= 0; i--) { 348 tempTransformation.clear(); 349 children.get(i).getTransformation(currentTime, tempTransformation); 350 expectedTransformation.compose(tempTransformation); 351 } 352 assertTransformationEquals(expectedTransformation, transformation); 353 } 354 assertTransformationEquals(final Transformation expected, final Transformation actual)355 private void assertTransformationEquals(final Transformation expected, 356 final Transformation actual) { 357 assertEquals(expected.getAlpha(), actual.getAlpha(), DELTA); 358 final float[] expectedValues = new float[9]; 359 final float[] actualValues = new float[9]; 360 expected.getMatrix().getValues(expectedValues); 361 actual.getMatrix().getValues(actualValues); 362 for (int i = 0; i < expectedValues.length; i++) { 363 assertEquals(expectedValues[i], actualValues[i], DELTA); 364 } 365 } 366 367 @Test testAccessAnimations()368 public void testAccessAnimations() { 369 final AnimationSet animationSet = new AnimationSet(true); 370 final Animation animation1 = new AlphaAnimation(0.0f, 1.0f); 371 animationSet.addAnimation(animation1); 372 final Animation animation2 = new AlphaAnimation(0.5f, 1.0f); 373 animationSet.addAnimation(animation2); 374 final Animation animation3 = new AlphaAnimation(1.0f, 0.5f); 375 animationSet.addAnimation(animation3); 376 377 final List<Animation> children = animationSet.getAnimations(); 378 assertEquals(3, children.size()); 379 assertSame(animation1, children.get(0)); 380 assertSame(animation2, children.get(1)); 381 assertSame(animation3, children.get(2)); 382 } 383 384 @Test testWillChangeTransformationMatrix()385 public void testWillChangeTransformationMatrix() { 386 final AnimationSet animationSet = new AnimationSet(true); 387 assertFalse(animationSet.willChangeTransformationMatrix()); 388 389 // Add first animation, this is an alpha animation and will not change 390 // the transformation matrix. 391 animationSet.addAnimation(new AlphaAnimation(0.0f, 1.0f)); 392 assertFalse(animationSet.willChangeTransformationMatrix()); 393 assertFalse(animationSet.willChangeBounds()); 394 395 // Add second animation, this is an scale animation and will change 396 // the transformation matrix. 397 animationSet.addAnimation(new ScaleAnimation(1.0f, 2.0f, 1.0f, 2.0f)); 398 assertTrue(animationSet.willChangeTransformationMatrix()); 399 assertTrue(animationSet.willChangeBounds()); 400 } 401 402 @Test testClone()403 public void testClone() throws CloneNotSupportedException { 404 final MyAnimationSet animationSet = new MyAnimationSet(false); 405 final Animation alpha = new AlphaAnimation(0.0f, 1.0f); 406 alpha.setInterpolator(new AccelerateInterpolator()); 407 alpha.initialize(INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE); 408 final Animation scale = new ScaleAnimation(1.0f, 2.0f, 1.0f, 3.0f); 409 scale.initialize(INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE); 410 animationSet.addAnimation(alpha); 411 animationSet.addAnimation(scale); 412 final long startTime = 0; 413 animationSet.setStartTime(startTime); 414 animationSet.setDuration(ANIMATIONSET_DURATION); 415 animationSet.initialize(INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE); 416 417 final AnimationSet clone = animationSet.clone(); 418 clone.initialize(INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE, INITIAL_SIZE); 419 final List<Animation> children = animationSet.getAnimations(); 420 final List<Animation> cloneChildren = clone.getAnimations(); 421 assertEquals(children.size(), cloneChildren.size()); 422 final Transformation expectedTransformation = new Transformation(); 423 final Transformation transformation = new Transformation(); 424 for (int i = 0; i < children.size(); i++) { 425 children.get(i).getTransformation(startTime, expectedTransformation); 426 cloneChildren.get(i).getTransformation(startTime, transformation); 427 assertTransformationEquals(expectedTransformation, transformation); 428 429 children.get(i).getTransformation(startTime + ANIMATIONSET_DURATION / 2, 430 expectedTransformation); 431 cloneChildren.get(i).getTransformation(startTime + ANIMATIONSET_DURATION /2, 432 transformation); 433 assertTransformationEquals(expectedTransformation, transformation); 434 435 children.get(i).getTransformation(startTime + ANIMATIONSET_DURATION, 436 expectedTransformation); 437 cloneChildren.get(i).getTransformation(startTime + ANIMATIONSET_DURATION, 438 transformation); 439 assertTransformationEquals(expectedTransformation, transformation); 440 } 441 } 442 443 private static class MyAnimationSet extends AnimationSet { 444 MyAnimationSet(boolean shareInterpolator)445 public MyAnimationSet(boolean shareInterpolator) { 446 super(shareInterpolator); 447 } 448 449 @Override clone()450 protected AnimationSet clone() throws CloneNotSupportedException { 451 return super.clone(); 452 } 453 } 454 } 455