1be19e030a14c8e398e8af97fa898ea80187704dfChet Haase/*
2be19e030a14c8e398e8af97fa898ea80187704dfChet Haase * Copyright (C) 2013 The Android Open Source Project
3be19e030a14c8e398e8af97fa898ea80187704dfChet Haase *
4be19e030a14c8e398e8af97fa898ea80187704dfChet Haase * Licensed under the Apache License, Version 2.0 (the "License");
5be19e030a14c8e398e8af97fa898ea80187704dfChet Haase * you may not use this file except in compliance with the License.
6be19e030a14c8e398e8af97fa898ea80187704dfChet Haase * You may obtain a copy of the License at
7be19e030a14c8e398e8af97fa898ea80187704dfChet Haase *
8be19e030a14c8e398e8af97fa898ea80187704dfChet Haase *      http://www.apache.org/licenses/LICENSE-2.0
9be19e030a14c8e398e8af97fa898ea80187704dfChet Haase *
10be19e030a14c8e398e8af97fa898ea80187704dfChet Haase * Unless required by applicable law or agreed to in writing, software
11be19e030a14c8e398e8af97fa898ea80187704dfChet Haase * distributed under the License is distributed on an "AS IS" BASIS,
12be19e030a14c8e398e8af97fa898ea80187704dfChet Haase * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13be19e030a14c8e398e8af97fa898ea80187704dfChet Haase * See the License for the specific language governing permissions and
14be19e030a14c8e398e8af97fa898ea80187704dfChet Haase * limitations under the License.
15be19e030a14c8e398e8af97fa898ea80187704dfChet Haase */
16be19e030a14c8e398e8af97fa898ea80187704dfChet Haasepackage android.animation;
17be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
18be19e030a14c8e398e8af97fa898ea80187704dfChet Haaseimport android.os.Handler;
19be19e030a14c8e398e8af97fa898ea80187704dfChet Haaseimport android.test.ActivityInstrumentationTestCase2;
20be19e030a14c8e398e8af97fa898ea80187704dfChet Haaseimport android.test.suitebuilder.annotation.SmallTest;
21be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
22be19e030a14c8e398e8af97fa898ea80187704dfChet Haaseimport java.util.HashMap;
23be19e030a14c8e398e8af97fa898ea80187704dfChet Haaseimport java.util.concurrent.TimeUnit;
24be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
25be19e030a14c8e398e8af97fa898ea80187704dfChet Haasepublic class AutoCancelTest extends ActivityInstrumentationTestCase2<BasicAnimatorActivity> {
26be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
27be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    boolean mAnimX1Canceled = false;
28be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    boolean mAnimXY1Canceled = false;
29be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    boolean mAnimX2Canceled = false;
30be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    boolean mAnimXY2Canceled = false;
31be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
32be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    private static final long START_DELAY = 100;
33be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    private static final long DELAYED_START_DURATION = 200;
34be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    private static final long FUTURE_TIMEOUT = 1000;
35be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
36be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    HashMap<Animator, Boolean> mCanceledMap = new HashMap<Animator, Boolean>();
37be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
38be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    public AutoCancelTest() {
39be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        super(BasicAnimatorActivity.class);
40be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    }
41be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
42be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    ObjectAnimator setupAnimator(long startDelay, String... properties) {
43be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        ObjectAnimator returnVal;
44be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        if (properties.length == 1) {
45be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            returnVal = ObjectAnimator.ofFloat(this, properties[0], 0, 1);
46be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        } else {
47be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            PropertyValuesHolder[] pvhArray = new PropertyValuesHolder[properties.length];
48be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            for (int i = 0; i < properties.length; i++) {
49be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                pvhArray[i] = PropertyValuesHolder.ofFloat(properties[i], 0, 1);
50be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            }
51be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            returnVal = ObjectAnimator.ofPropertyValuesHolder(this, pvhArray);
52be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        }
53be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        returnVal.setAutoCancel(true);
54be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        returnVal.setStartDelay(startDelay);
55be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        returnVal.addListener(mCanceledListener);
56be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        return returnVal;
57be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    }
58be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
59be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    private void setupAnimators(long startDelay, boolean startLater, final FutureWaiter future)
60be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    throws Exception {
61be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        // Animators to be auto-canceled
62be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        final ObjectAnimator animX1 = setupAnimator(startDelay, "x");
63be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        final ObjectAnimator animY1 = setupAnimator(startDelay, "y");
64be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        final ObjectAnimator animXY1 = setupAnimator(startDelay, "x", "y");
65be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        final ObjectAnimator animXZ1 = setupAnimator(startDelay, "x", "z");
66be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
67be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        animX1.start();
68be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        animY1.start();
69be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        animXY1.start();
70be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        animXZ1.start();
71be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
72be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        final ObjectAnimator animX2 = setupAnimator(0, "x");
73be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        animX2.addListener(new AnimatorListenerAdapter() {
74be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            @Override
75be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            public void onAnimationStart(Animator animation) {
76be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                // We expect only animX1 to be canceled at this point
77be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                if (mCanceledMap.get(animX1) == null ||
78be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                        mCanceledMap.get(animX1) != true ||
79be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                        mCanceledMap.get(animY1) != null ||
80be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                        mCanceledMap.get(animXY1) != null ||
81be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                        mCanceledMap.get(animXZ1) != null) {
82be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                    future.set(false);
83be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                }
84be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            }
85be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        });
86be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
87be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        final ObjectAnimator animXY2 = setupAnimator(0, "x", "y");
88be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        animXY2.addListener(new AnimatorListenerAdapter() {
89be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            @Override
90be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            public void onAnimationStart(Animator animation) {
91be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                // We expect only animXY1 to be canceled at this point
92be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                if (mCanceledMap.get(animXY1) == null ||
93be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                        mCanceledMap.get(animXY1) != true ||
94be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                        mCanceledMap.get(animY1) != null ||
95be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                        mCanceledMap.get(animXZ1) != null) {
96be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                    future.set(false);
97be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                }
98be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
99be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            }
100be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
101be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            @Override
102be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            public void onAnimationEnd(Animator animation) {
103be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                // Release future if not done already via failures during start
104be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                future.release();
105be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            }
106be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        });
107be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
108be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        if (startLater) {
109be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            Handler handler = new Handler();
110be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            handler.postDelayed(new Runnable() {
111be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                @Override
112be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                public void run() {
113be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                    animX2.start();
114be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                    animXY2.start();
115be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                }
116be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            }, DELAYED_START_DURATION);
117be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        } else {
118be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            animX2.start();
119be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            animXY2.start();
120be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        }
121be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    }
122be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
123be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    @SmallTest
124be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    public void testAutoCancel() throws Exception {
125be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        final FutureWaiter future = new FutureWaiter();
126be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        getActivity().runOnUiThread(new Runnable() {
127be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            @Override
128be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            public void run() {
129be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                try {
130be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                    setupAnimators(0, false, future);
131be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                } catch (Exception e) {
132be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                    future.setException(e);
133be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                }
134be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            }
135be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        });
136be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        assertTrue(future.get(FUTURE_TIMEOUT, TimeUnit.MILLISECONDS));
137be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    }
138be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
139be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    @SmallTest
140be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    public void testAutoCancelDelayed() throws Exception {
141be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        final FutureWaiter future = new FutureWaiter();
142be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        getActivity().runOnUiThread(new Runnable() {
143be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            @Override
144be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            public void run() {
145be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                try {
146be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                    setupAnimators(START_DELAY, false, future);
147be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                } catch (Exception e) {
148be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                    future.setException(e);
149be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                }
150be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            }
151be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        });
152be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        assertTrue(future.get(FUTURE_TIMEOUT, TimeUnit.MILLISECONDS));
153be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    }
154be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
155be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    @SmallTest
156be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    public void testAutoCancelTestLater() throws Exception {
157be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        final FutureWaiter future = new FutureWaiter();
158be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        getActivity().runOnUiThread(new Runnable() {
159be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            @Override
160be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            public void run() {
161be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                try {
162be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                    setupAnimators(0, true, future);
163be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                } catch (Exception e) {
164be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                    future.setException(e);
165be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                }
166be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            }
167be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        });
168be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        assertTrue(future.get(FUTURE_TIMEOUT, TimeUnit.MILLISECONDS));
169be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    }
170be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
171be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    @SmallTest
172be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    public void testAutoCancelDelayedTestLater() throws Exception {
173be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        final FutureWaiter future = new FutureWaiter();
174be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        getActivity().runOnUiThread(new Runnable() {
175be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            @Override
176be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            public void run() {
177be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                try {
178be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                    setupAnimators(START_DELAY, true, future);
179be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                } catch (Exception e) {
180be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                    future.setException(e);
181be19e030a14c8e398e8af97fa898ea80187704dfChet Haase                }
182be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            }
183be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        });
184be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        assertTrue(future.get(FUTURE_TIMEOUT, TimeUnit.MILLISECONDS));
185be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    }
186be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
187be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    private AnimatorListenerAdapter mCanceledListener = new AnimatorListenerAdapter() {
188be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        @Override
189be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        public void onAnimationCancel(Animator animation) {
190be19e030a14c8e398e8af97fa898ea80187704dfChet Haase            mCanceledMap.put(animation, true);
191be19e030a14c8e398e8af97fa898ea80187704dfChet Haase        }
192be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    };
193be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
194be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    public void setX(float x) {}
195be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
196be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    public void setY(float y) {}
197be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
198be19e030a14c8e398e8af97fa898ea80187704dfChet Haase    public void setZ(float z) {}
199be19e030a14c8e398e8af97fa898ea80187704dfChet Haase}
200be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
201be19e030a14c8e398e8af97fa898ea80187704dfChet Haase
202