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