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