1cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler/*
2cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler * Copyright (C) 2016 The Android Open Source Project
3cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler *
4cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler * Licensed under the Apache License, Version 2.0 (the "License");
5cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler * you may not use this file except in compliance with the License.
6cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler * You may obtain a copy of the License at
7cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler *
8cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler *      http://www.apache.org/licenses/LICENSE-2.0
9cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler *
10cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler * Unless required by applicable law or agreed to in writing, software
11cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler * distributed under the License is distributed on an "AS IS" BASIS,
12cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler * See the License for the specific language governing permissions and
14cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler * limitations under the License
15cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler */
16cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
17cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantlerpackage android.transition;
18cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
19cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantlerimport android.animation.AnimatorSetActivity;
20cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantlerimport android.app.Activity;
21cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantlerimport android.test.ActivityInstrumentationTestCase2;
22cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantlerimport android.test.suitebuilder.annotation.SmallTest;
23cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantlerimport android.view.Gravity;
24cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantlerimport android.view.View;
25cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantlerimport android.view.ViewGroup;
26cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantlerimport android.view.ViewTreeObserver;
27cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
28cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantlerimport com.android.frameworks.coretests.R;
29cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
30cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantlerimport java.util.concurrent.CountDownLatch;
31cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantlerimport java.util.concurrent.TimeUnit;
32cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
33cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
34cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantlerpublic class SlideTransitionTest extends ActivityInstrumentationTestCase2<AnimatorSetActivity> {
35cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
36cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler    Activity mActivity;
37cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
38cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler    public SlideTransitionTest() {
39cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        super(AnimatorSetActivity.class);
40cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler    }
41cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
42cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler    @Override
43cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler    protected void setUp() throws Exception {
44cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        mActivity = getActivity();
45cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler    }
46cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
47cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler    @SmallTest
48cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler    public void testShortSlide() throws Throwable {
49cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        final float slideFraction = 0.5f;
50cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        final View square1 = mActivity.findViewById(R.id.square1);
51cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        final View sceneRoot = mActivity.findViewById(R.id.container);
52cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        final SlideTranslationValueRatchet ratchet = new SlideTranslationValueRatchet(square1);
53cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        square1.getViewTreeObserver().addOnPreDrawListener(ratchet);
54cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
55cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        final Slide slideOut = new Slide(Gravity.BOTTOM);
56cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        final float finalOffsetOut = sceneRoot.getHeight() * slideFraction;
57cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        slideOut.setSlideFraction(slideFraction);
58cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        TransitionLatch latch = setVisibilityInTransition(slideOut, R.id.square1, View.INVISIBLE);
59cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        assertTrue(latch.startLatch.await(200, TimeUnit.MILLISECONDS));
60cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        assertEquals(0f, square1.getTranslationY(), 0.1f);
61cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        assertEquals(View.VISIBLE, square1.getVisibility());
62cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        Thread.sleep(100);
63cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        assertFalse(square1.getTranslationY() < 0.1
64cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler                || square1.getTranslationY() > finalOffsetOut - 0.1);
65cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        assertTrue(latch.endLatch.await(400, TimeUnit.MILLISECONDS));
66cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        // Give this 20% slop in case some frames get dropped.
67cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        assertTrue(finalOffsetOut * 0.8 < ratchet.maxY);
68cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        assertTrue(finalOffsetOut + 0.1 > ratchet.maxY);
69cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        assertEquals(View.INVISIBLE, square1.getVisibility());
70cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
71cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        ratchet.reset();
72cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        final Slide slideIn = new Slide(Gravity.BOTTOM);
73cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        final float initialOffsetIn = sceneRoot.getHeight() * slideFraction;
74cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        slideIn.setSlideFraction(slideFraction);
75cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        latch = setVisibilityInTransition(slideIn, R.id.square1, View.VISIBLE);
76cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        assertTrue(latch.startLatch.await(200, TimeUnit.MILLISECONDS));
77cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        assertEquals(initialOffsetIn, square1.getTranslationY(), 0.1f);
78cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        assertEquals(View.VISIBLE, square1.getVisibility());
79cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        Thread.sleep(100);
80cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        assertFalse(square1.getTranslationY() < 0.1
81cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler                || square1.getTranslationY() > initialOffsetIn - 0.1);
82cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        assertTrue(latch.endLatch.await(400, TimeUnit.MILLISECONDS));
83cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        assertEquals(0f, ratchet.minY, 0.1);
84cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        assertEquals(0f, square1.getTranslationY(), 0.1);
85cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        assertEquals(View.VISIBLE, square1.getVisibility());
86cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
87cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        square1.getViewTreeObserver().removeOnPreDrawListener(ratchet);
88cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler    }
89cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
90cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler    public TransitionLatch setVisibilityInTransition(final Transition transition, int viewId,
91cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            final int visibility) throws Throwable {
92cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        final ViewGroup sceneRoot = (ViewGroup) mActivity.findViewById(R.id.container);
93cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        final View view = sceneRoot.findViewById(viewId);
94cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        TransitionLatch latch = new TransitionLatch();
95cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        transition.addListener(latch);
96cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        runTestOnUiThread(new Runnable() {
97cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            @Override
98cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            public void run() {
99cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler                TransitionManager.beginDelayedTransition(sceneRoot, transition);
100cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler                view.setVisibility(visibility);
101cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            }
102cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        });
103cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        return latch;
104cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler    }
105cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
106cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler    public static class TransitionLatch implements Transition.TransitionListener {
107cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        public CountDownLatch startLatch = new CountDownLatch(1);
108cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        public CountDownLatch endLatch = new CountDownLatch(1);
109cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        public CountDownLatch cancelLatch = new CountDownLatch(1);
110cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        public CountDownLatch pauseLatch = new CountDownLatch(1);
111cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        public CountDownLatch resumeLatch = new CountDownLatch(1);
112cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
113cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        @Override
114cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        public void onTransitionStart(Transition transition) {
115cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            startLatch.countDown();
116cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        }
117cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
118cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        @Override
119cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        public void onTransitionEnd(Transition transition) {
120cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            endLatch.countDown();
121cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            transition.removeListener(this);
122cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        }
123cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
124cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        @Override
125cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        public void onTransitionCancel(Transition transition) {
126cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            cancelLatch.countDown();
127cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        }
128cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
129cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        @Override
130cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        public void onTransitionPause(Transition transition) {
131cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            pauseLatch.countDown();
132cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        }
133cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
134cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        @Override
135cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        public void onTransitionResume(Transition transition) {
136cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            resumeLatch.countDown();
137cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        }
138cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler    }
139cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
140cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler    private static class SlideTranslationValueRatchet
141cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            implements ViewTreeObserver.OnPreDrawListener {
142cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
143cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        private final View mView;
144cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        private boolean mInitialized;
145cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        public float minX = Float.NaN;
146cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        public float minY = Float.NaN;
147cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        public float maxX = Float.NaN;
148cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        public float maxY = Float.NaN;
149cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
150cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        public SlideTranslationValueRatchet(View view) {
151cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            mView = view;
152cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        }
153cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
154cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        public void reset() {
155cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            minX = minY = maxX = maxY = Float.NaN;
156cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            mInitialized = false;
157cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        }
158cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler
159cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        @Override
160cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        public boolean onPreDraw() {
161cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            if (!mInitialized) {
162cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler                minX = maxX = mView.getTranslationX();
163cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler                minY = maxY = mView.getTranslationY();
164cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler                mInitialized = true;
165cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            } else {
166cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler                minX = Math.min(minX, mView.getTranslationX());
167cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler                minY = Math.min(minY, mView.getTranslationY());
168cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler                maxX = Math.max(maxX, mView.getTranslationX());
169cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler                maxY = Math.max(maxY, mView.getTranslationY());
170cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            }
171cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler            return true;
172cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler        }
173cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler    }
174cfa15bd1d532830954a5f9717c05e3fe19bc512aTony Mantler}
175