1 /* 2 * Copyright (C) 2016 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.transition; 18 19 import android.animation.Animator; 20 import android.animation.AnimatorSetActivity; 21 import android.app.Activity; 22 import android.graphics.Bitmap; 23 import android.graphics.drawable.BitmapDrawable; 24 import android.test.ActivityInstrumentationTestCase2; 25 import android.test.suitebuilder.annotation.SmallTest; 26 import android.transition.Transition.TransitionListener; 27 import android.view.View; 28 import android.view.ViewGroup; 29 import android.widget.FrameLayout; 30 import android.widget.ImageView; 31 32 import com.android.frameworks.coretests.R; 33 34 import java.util.concurrent.CountDownLatch; 35 import java.util.concurrent.TimeUnit; 36 37 public class FadeTransitionTest extends ActivityInstrumentationTestCase2<AnimatorSetActivity> { 38 Activity mActivity; 39 public FadeTransitionTest() { 40 super(AnimatorSetActivity.class); 41 } 42 43 @Override 44 protected void setUp() throws Exception { 45 mActivity = getActivity(); 46 } 47 48 @SmallTest 49 public void testFadeOutAndIn() throws Throwable { 50 View square1 = mActivity.findViewById(R.id.square1); 51 Fade fadeOut = new Fade(Fade.MODE_OUT); 52 TransitionLatch latch = setVisibilityInTransition(fadeOut, R.id.square1, View.INVISIBLE); 53 assertTrue(latch.startLatch.await(400, TimeUnit.MILLISECONDS)); 54 assertEquals(View.VISIBLE, square1.getVisibility()); 55 waitForAnimation(); 56 assertFalse(square1.getTransitionAlpha() == 0 || square1.getTransitionAlpha() == 1); 57 assertTrue(latch.endLatch.await(800, TimeUnit.MILLISECONDS)); 58 assertEquals(1.0f, square1.getTransitionAlpha()); 59 assertEquals(View.INVISIBLE, square1.getVisibility()); 60 61 Fade fadeIn = new Fade(Fade.MODE_IN); 62 latch = setVisibilityInTransition(fadeIn, R.id.square1, View.VISIBLE); 63 assertTrue(latch.startLatch.await(400, TimeUnit.MILLISECONDS)); 64 assertEquals(View.VISIBLE, square1.getVisibility()); 65 waitForAnimation(); 66 final float transitionAlpha = square1.getTransitionAlpha(); 67 assertTrue("expecting transitionAlpha to be between 0 and 1. Was " + transitionAlpha, 68 transitionAlpha > 0 && transitionAlpha < 1); 69 assertTrue(latch.endLatch.await(800, TimeUnit.MILLISECONDS)); 70 assertEquals(1.0f, square1.getTransitionAlpha()); 71 assertEquals(View.VISIBLE, square1.getVisibility()); 72 } 73 74 @SmallTest 75 public void testFadeOutInterrupt() throws Throwable { 76 View square1 = mActivity.findViewById(R.id.square1); 77 Fade fadeOut = new Fade(Fade.MODE_OUT); 78 FadeValueCheck fadeOutValueCheck = new FadeValueCheck(square1); 79 fadeOut.addListener(fadeOutValueCheck); 80 TransitionLatch outLatch = setVisibilityInTransition(fadeOut, R.id.square1, View.INVISIBLE); 81 assertTrue(outLatch.startLatch.await(400, TimeUnit.MILLISECONDS)); 82 waitForAnimation(); 83 84 Fade fadeIn = new Fade(Fade.MODE_IN); 85 FadeValueCheck fadeInValueCheck = new FadeValueCheck(square1); 86 fadeIn.addListener(fadeInValueCheck); 87 TransitionLatch inLatch = setVisibilityInTransition(fadeIn, R.id.square1, View.VISIBLE); 88 assertTrue(inLatch.startLatch.await(400, TimeUnit.MILLISECONDS)); 89 90 assertEquals(fadeOutValueCheck.pauseTransitionAlpha, fadeInValueCheck.startTransitionAlpha); 91 assertTrue("expecting transitionAlpha to be between 0 and 1. Was " + 92 fadeOutValueCheck.pauseTransitionAlpha, 93 fadeOutValueCheck.pauseTransitionAlpha > 0 && 94 fadeOutValueCheck.pauseTransitionAlpha < 1); 95 96 assertTrue(inLatch.endLatch.await(800, TimeUnit.MILLISECONDS)); 97 assertEquals(1.0f, square1.getTransitionAlpha()); 98 assertEquals(View.VISIBLE, square1.getVisibility()); 99 } 100 101 @SmallTest 102 public void testFadeInInterrupt() throws Throwable { 103 final View square1 = mActivity.findViewById(R.id.square1); 104 runTestOnUiThread(new Runnable() { 105 @Override 106 public void run() { 107 square1.setVisibility(View.INVISIBLE); 108 } 109 }); 110 Fade fadeIn = new Fade(Fade.MODE_IN); 111 FadeValueCheck fadeInValueCheck = new FadeValueCheck(square1); 112 fadeIn.addListener(fadeInValueCheck); 113 TransitionLatch inLatch = setVisibilityInTransition(fadeIn, R.id.square1, View.VISIBLE); 114 assertTrue(inLatch.startLatch.await(400, TimeUnit.MILLISECONDS)); 115 waitForAnimation(); 116 117 Fade fadeOut = new Fade(Fade.MODE_OUT); 118 FadeValueCheck fadeOutValueCheck = new FadeValueCheck(square1); 119 fadeOut.addListener(fadeOutValueCheck); 120 TransitionLatch outLatch = setVisibilityInTransition(fadeOut, R.id.square1, View.INVISIBLE); 121 assertTrue(outLatch.startLatch.await(400, TimeUnit.MILLISECONDS)); 122 123 assertEquals(fadeInValueCheck.pauseTransitionAlpha, fadeOutValueCheck.startTransitionAlpha); 124 assertTrue("expecting transitionAlpha to be between 0 and 1. Was " + 125 fadeInValueCheck.pauseTransitionAlpha, 126 fadeInValueCheck.pauseTransitionAlpha > 0 && 127 fadeInValueCheck.pauseTransitionAlpha < 1); 128 129 assertTrue(outLatch.endLatch.await(800, TimeUnit.MILLISECONDS)); 130 assertEquals(1.0f, square1.getTransitionAlpha()); 131 assertEquals(View.INVISIBLE, square1.getVisibility()); 132 } 133 134 @SmallTest 135 public void testSnapshotView() throws Throwable { 136 final View square1 = mActivity.findViewById(R.id.square1); 137 138 final CountDownLatch disappearCalled = new CountDownLatch(1); 139 final Fade fadeOut = new Fade(Fade.MODE_OUT) { 140 @Override 141 public Animator onDisappear(ViewGroup sceneRoot, View view, 142 TransitionValues startValues, 143 TransitionValues endValues) { 144 assertNotSame(square1, view); 145 assertTrue(view instanceof ImageView); 146 ImageView imageView = (ImageView) view; 147 BitmapDrawable background = (BitmapDrawable) imageView.getDrawable(); 148 Bitmap bitmap = background.getBitmap(); 149 assertEquals(Bitmap.Config.HARDWARE, bitmap.getConfig()); 150 Bitmap copy = bitmap.copy(Bitmap.Config.ARGB_8888, false); 151 assertEquals(0xFFFF0000, copy.getPixel(1, 1)); 152 disappearCalled.countDown(); 153 return super.onDisappear(sceneRoot, view, startValues, endValues); 154 } 155 }; 156 157 runTestOnUiThread(new Runnable() { 158 @Override 159 public void run() { 160 ViewGroup container = mActivity.findViewById(R.id.container); 161 TransitionManager.beginDelayedTransition(container, fadeOut); 162 container.removeView(square1); 163 FrameLayout parent = new FrameLayout(mActivity); 164 parent.addView(square1); 165 } 166 }); 167 168 assertTrue(disappearCalled.await(1, TimeUnit.SECONDS)); 169 } 170 171 public TransitionLatch setVisibilityInTransition(final Transition transition, int viewId, 172 final int visibility) throws Throwable { 173 final ViewGroup sceneRoot = (ViewGroup) mActivity.findViewById(R.id.container); 174 final View view = sceneRoot.findViewById(viewId); 175 TransitionLatch latch = new TransitionLatch(); 176 transition.addListener(latch); 177 runTestOnUiThread(new Runnable() { 178 @Override 179 public void run() { 180 TransitionManager.beginDelayedTransition(sceneRoot, transition); 181 view.setVisibility(visibility); 182 } 183 }); 184 return latch; 185 } 186 187 /** 188 * Waits for two animation frames to ensure animation values change. 189 */ 190 private void waitForAnimation() throws InterruptedException { 191 final CountDownLatch latch = new CountDownLatch(2); 192 mActivity.getWindow().getDecorView().postOnAnimation(new Runnable() { 193 @Override 194 public void run() { 195 latch.countDown(); 196 if (latch.getCount() > 0) { 197 mActivity.getWindow().getDecorView().postOnAnimation(this); 198 } 199 } 200 }); 201 assertTrue(latch.await(1, TimeUnit.SECONDS)); 202 } 203 204 public static class TransitionLatch implements TransitionListener { 205 public CountDownLatch startLatch = new CountDownLatch(1); 206 public CountDownLatch endLatch = new CountDownLatch(1); 207 public CountDownLatch cancelLatch = new CountDownLatch(1); 208 public CountDownLatch pauseLatch = new CountDownLatch(1); 209 public CountDownLatch resumeLatch = new CountDownLatch(1); 210 211 @Override 212 public void onTransitionStart(Transition transition) { 213 startLatch.countDown(); 214 } 215 216 @Override 217 public void onTransitionEnd(Transition transition) { 218 endLatch.countDown(); 219 transition.removeListener(this); 220 } 221 222 @Override 223 public void onTransitionCancel(Transition transition) { 224 cancelLatch.countDown(); 225 } 226 227 @Override 228 public void onTransitionPause(Transition transition) { 229 pauseLatch.countDown(); 230 } 231 232 @Override 233 public void onTransitionResume(Transition transition) { 234 resumeLatch.countDown(); 235 } 236 } 237 238 private static class FadeValueCheck extends TransitionListenerAdapter { 239 public float startTransitionAlpha; 240 public float pauseTransitionAlpha; 241 private final View mView; 242 243 public FadeValueCheck(View view) { 244 mView = view; 245 } 246 @Override 247 public void onTransitionStart(Transition transition) { 248 startTransitionAlpha = mView.getTransitionAlpha(); 249 } 250 251 @Override 252 public void onTransitionPause(Transition transition) { 253 pauseTransitionAlpha = mView.getTransitionAlpha(); 254 } 255 } 256 } 257