1 /* 2 * Copyright (C) 2015 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 package android.transition.cts; 17 18 import com.android.cts.transition.R; 19 20 import android.animation.Animator; 21 import android.animation.ObjectAnimator; 22 import android.os.SystemClock; 23 import android.test.ActivityInstrumentationTestCase2; 24 import android.transition.Scene; 25 import android.transition.TransitionManager; 26 import android.transition.TransitionValues; 27 import android.transition.Visibility; 28 import android.view.Choreographer; 29 import android.view.Choreographer.FrameCallback; 30 import android.view.View; 31 import android.view.ViewGroup; 32 import android.widget.FrameLayout; 33 34 import java.util.ArrayList; 35 36 public class BaseTransitionTest extends ActivityInstrumentationTestCase2<TransitionActivity> { 37 protected TransitionActivity mActivity; 38 protected FrameLayout mSceneRoot; 39 public float mAnimatedValue; 40 protected ArrayList<View> mTargets = new ArrayList<>(); 41 protected TestTransition mTransition; 42 BaseTransitionTest()43 public BaseTransitionTest() { 44 super(TransitionActivity.class); 45 } 46 47 @Override setUp()48 protected void setUp() throws Exception { 49 super.setUp(); 50 setActivityInitialTouchMode(false); 51 mActivity = getActivity(); 52 mSceneRoot = (FrameLayout) mActivity.findViewById(R.id.container); 53 mTargets.clear(); 54 mTransition = new TestTransition(); 55 } 56 waitForStart()57 protected void waitForStart() throws InterruptedException { 58 waitForStart(mTransition.listener); 59 } 60 waitForStart(SimpleTransitionListener listener)61 protected static void waitForStart(SimpleTransitionListener listener) throws InterruptedException { 62 long endTime = SystemClock.uptimeMillis() + 50; 63 synchronized (listener) { 64 while (!listener.started) { 65 long now = SystemClock.uptimeMillis(); 66 long waitTime = endTime - now; 67 if (waitTime <= 0) { 68 throw new InterruptedException(); 69 } 70 listener.wait(waitTime); 71 } 72 } 73 } 74 waitForEnd(long waitMillis)75 protected void waitForEnd(long waitMillis) throws InterruptedException { 76 waitForEnd(mTransition.listener, waitMillis); 77 } 78 waitForEnd(SimpleTransitionListener listener, long waitMillis)79 protected static void waitForEnd(SimpleTransitionListener listener, long waitMillis) 80 throws InterruptedException { 81 long endTime = SystemClock.uptimeMillis() + waitMillis; 82 synchronized (listener) { 83 while (!listener.ended) { 84 long now = SystemClock.uptimeMillis(); 85 long waitTime = endTime - now; 86 if (waitTime <= 0) { 87 throw new InterruptedException(); 88 } 89 listener.wait(waitTime); 90 } 91 } 92 } 93 startTransition(final int layoutId)94 protected void startTransition(final int layoutId) throws Throwable { 95 runTestOnUiThread(new Runnable() { 96 @Override 97 public void run() { 98 Scene scene = Scene.getSceneForLayout(mSceneRoot, layoutId, mActivity); 99 TransitionManager.go(scene, mTransition); 100 } 101 }); 102 waitForStart(); 103 } 104 endTransition()105 protected void endTransition() throws Throwable { 106 runTestOnUiThread(new Runnable() { 107 @Override 108 public void run() { 109 TransitionManager.endTransitions(mSceneRoot); 110 } 111 }); 112 } 113 enterScene(final int layoutId)114 protected void enterScene(final int layoutId) throws Throwable { 115 runTestOnUiThread(new Runnable() { 116 @Override 117 public void run() { 118 Scene scene = Scene.getSceneForLayout(mSceneRoot, layoutId, mActivity); 119 scene.enter(); 120 } 121 }); 122 getInstrumentation().waitForIdleSync(); 123 } 124 125 // Waits at least one frame and it could be more. The animated values should have changed 126 // from the previously recorded values by the end of this method. waitForAnimationFrame()127 protected void waitForAnimationFrame() throws Throwable { 128 final boolean[] tripped = new boolean[] { false }; 129 runTestOnUiThread(new Runnable() { 130 @Override 131 public void run() { 132 Choreographer.getInstance().postFrameCallbackDelayed(new FrameCallback() { 133 @Override 134 public void doFrame(long frameTimeNanos) { 135 synchronized (tripped) { 136 tripped[0] = true; 137 tripped.notifyAll(); 138 } 139 } 140 }, 16); // make sure it is the next animation frame. 141 } 142 }); 143 synchronized (tripped) { 144 long endTime = SystemClock.uptimeMillis() + 60; 145 while (!tripped[0]) { 146 long waitTime = endTime - SystemClock.uptimeMillis(); 147 if (waitTime <= 0) { 148 throw new InterruptedException(); 149 } 150 tripped.wait(waitTime); 151 } 152 } 153 } 154 155 public class TestTransition extends Visibility { 156 public final SimpleTransitionListener listener = new SimpleTransitionListener(); 157 TestTransition()158 public TestTransition() { 159 addListener(listener); 160 setDuration(100); 161 } 162 163 @Override onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues)164 public Animator onAppear(ViewGroup sceneRoot, View view, TransitionValues startValues, 165 TransitionValues endValues) { 166 mTargets.add(endValues.view); 167 return ObjectAnimator.ofFloat(BaseTransitionTest.this, "mAnimatedValue", 0, 1); 168 } 169 170 @Override onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, TransitionValues endValues)171 public Animator onDisappear(ViewGroup sceneRoot, View view, TransitionValues startValues, 172 TransitionValues endValues) { 173 mTargets.add(startValues.view); 174 return ObjectAnimator.ofFloat(BaseTransitionTest.this, "mAnimatedValue", 1, 0); 175 } 176 } 177 } 178