1/*
2 * Copyright (C) 2013 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 */
16package android.animation;
17
18import android.os.Handler;
19import android.test.ActivityInstrumentationTestCase2;
20import android.test.suitebuilder.annotation.SmallTest;
21
22import java.util.HashMap;
23import java.util.concurrent.TimeUnit;
24
25public class AutoCancelTest extends ActivityInstrumentationTestCase2<BasicAnimatorActivity> {
26
27    boolean mAnimX1Canceled = false;
28    boolean mAnimXY1Canceled = false;
29    boolean mAnimX2Canceled = false;
30    boolean mAnimXY2Canceled = false;
31
32    private static final long START_DELAY = 100;
33    private static final long DELAYED_START_DURATION = 200;
34    private static final long FUTURE_TIMEOUT = 1000;
35
36    HashMap<Animator, Boolean> mCanceledMap = new HashMap<Animator, Boolean>();
37
38    public AutoCancelTest() {
39        super(BasicAnimatorActivity.class);
40    }
41
42    ObjectAnimator setupAnimator(long startDelay, String... properties) {
43        ObjectAnimator returnVal;
44        if (properties.length == 1) {
45            returnVal = ObjectAnimator.ofFloat(this, properties[0], 0, 1);
46        } else {
47            PropertyValuesHolder[] pvhArray = new PropertyValuesHolder[properties.length];
48            for (int i = 0; i < properties.length; i++) {
49                pvhArray[i] = PropertyValuesHolder.ofFloat(properties[i], 0, 1);
50            }
51            returnVal = ObjectAnimator.ofPropertyValuesHolder(this, pvhArray);
52        }
53        returnVal.setAutoCancel(true);
54        returnVal.setStartDelay(startDelay);
55        returnVal.addListener(mCanceledListener);
56        return returnVal;
57    }
58
59    private void setupAnimators(long startDelay, boolean startLater, final FutureWaiter future)
60    throws Exception {
61        // Animators to be auto-canceled
62        final ObjectAnimator animX1 = setupAnimator(startDelay, "x");
63        final ObjectAnimator animY1 = setupAnimator(startDelay, "y");
64        final ObjectAnimator animXY1 = setupAnimator(startDelay, "x", "y");
65        final ObjectAnimator animXZ1 = setupAnimator(startDelay, "x", "z");
66
67        animX1.start();
68        animY1.start();
69        animXY1.start();
70        animXZ1.start();
71
72        final ObjectAnimator animX2 = setupAnimator(0, "x");
73        animX2.addListener(new AnimatorListenerAdapter() {
74            @Override
75            public void onAnimationStart(Animator animation) {
76                // We expect only animX1 to be canceled at this point
77                if (mCanceledMap.get(animX1) == null ||
78                        mCanceledMap.get(animX1) != true ||
79                        mCanceledMap.get(animY1) != null ||
80                        mCanceledMap.get(animXY1) != null ||
81                        mCanceledMap.get(animXZ1) != null) {
82                    future.set(false);
83                }
84            }
85        });
86
87        final ObjectAnimator animXY2 = setupAnimator(0, "x", "y");
88        animXY2.addListener(new AnimatorListenerAdapter() {
89            @Override
90            public void onAnimationStart(Animator animation) {
91                // We expect only animXY1 to be canceled at this point
92                if (mCanceledMap.get(animXY1) == null ||
93                        mCanceledMap.get(animXY1) != true ||
94                        mCanceledMap.get(animY1) != null ||
95                        mCanceledMap.get(animXZ1) != null) {
96                    future.set(false);
97                }
98
99            }
100
101            @Override
102            public void onAnimationEnd(Animator animation) {
103                // Release future if not done already via failures during start
104                future.release();
105            }
106        });
107
108        if (startLater) {
109            Handler handler = new Handler();
110            handler.postDelayed(new Runnable() {
111                @Override
112                public void run() {
113                    animX2.start();
114                    animXY2.start();
115                }
116            }, DELAYED_START_DURATION);
117        } else {
118            animX2.start();
119            animXY2.start();
120        }
121    }
122
123    @SmallTest
124    public void testAutoCancel() throws Exception {
125        final FutureWaiter future = new FutureWaiter();
126        getActivity().runOnUiThread(new Runnable() {
127            @Override
128            public void run() {
129                try {
130                    setupAnimators(0, false, future);
131                } catch (Exception e) {
132                    future.setException(e);
133                }
134            }
135        });
136        assertTrue(future.get(FUTURE_TIMEOUT, TimeUnit.MILLISECONDS));
137    }
138
139    @SmallTest
140    public void testAutoCancelDelayed() throws Exception {
141        final FutureWaiter future = new FutureWaiter();
142        getActivity().runOnUiThread(new Runnable() {
143            @Override
144            public void run() {
145                try {
146                    setupAnimators(START_DELAY, false, future);
147                } catch (Exception e) {
148                    future.setException(e);
149                }
150            }
151        });
152        assertTrue(future.get(FUTURE_TIMEOUT, TimeUnit.MILLISECONDS));
153    }
154
155    @SmallTest
156    public void testAutoCancelTestLater() throws Exception {
157        final FutureWaiter future = new FutureWaiter();
158        getActivity().runOnUiThread(new Runnable() {
159            @Override
160            public void run() {
161                try {
162                    setupAnimators(0, true, future);
163                } catch (Exception e) {
164                    future.setException(e);
165                }
166            }
167        });
168        assertTrue(future.get(FUTURE_TIMEOUT, TimeUnit.MILLISECONDS));
169    }
170
171    @SmallTest
172    public void testAutoCancelDelayedTestLater() throws Exception {
173        final FutureWaiter future = new FutureWaiter();
174        getActivity().runOnUiThread(new Runnable() {
175            @Override
176            public void run() {
177                try {
178                    setupAnimators(START_DELAY, true, future);
179                } catch (Exception e) {
180                    future.setException(e);
181                }
182            }
183        });
184        assertTrue(future.get(FUTURE_TIMEOUT, TimeUnit.MILLISECONDS));
185    }
186
187    private AnimatorListenerAdapter mCanceledListener = new AnimatorListenerAdapter() {
188        @Override
189        public void onAnimationCancel(Animator animation) {
190            mCanceledMap.put(animation, true);
191        }
192    };
193
194    public void setX(float x) {}
195
196    public void setY(float y) {}
197
198    public void setZ(float z) {}
199}
200
201
202