1 /* 2 * Copyright (C) 2017 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 com.android.server.wm; 18 19 import static org.junit.Assert.assertEquals; 20 import static org.junit.Assert.assertFalse; 21 import static org.junit.Assert.assertNotNull; 22 import static org.junit.Assert.assertNull; 23 import static org.junit.Assert.assertTrue; 24 import static org.mockito.ArgumentMatchers.eq; 25 import static org.mockito.Mockito.any; 26 import static org.mockito.Mockito.never; 27 import static org.mockito.Mockito.verify; 28 import static org.mockito.Mockito.verifyZeroInteractions; 29 30 import android.platform.test.annotations.Presubmit; 31 import android.support.test.filters.FlakyTest; 32 import android.support.test.filters.SmallTest; 33 import android.support.test.runner.AndroidJUnit4; 34 import android.view.SurfaceControl; 35 import android.view.SurfaceControl.Builder; 36 import android.view.SurfaceControl.Transaction; 37 import android.view.SurfaceSession; 38 39 import com.android.server.wm.SurfaceAnimator.Animatable; 40 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; 41 42 import org.junit.Before; 43 import org.junit.Test; 44 import org.junit.runner.RunWith; 45 import org.mockito.ArgumentCaptor; 46 import org.mockito.Mock; 47 import org.mockito.MockitoAnnotations; 48 49 import java.util.ArrayList; 50 51 /** 52 * Test class for {@link SurfaceAnimatorTest}. 53 * 54 * atest FrameworksServicesTests:com.android.server.wm.SurfaceAnimatorTest 55 */ 56 @SmallTest 57 @Presubmit 58 @RunWith(AndroidJUnit4.class) 59 public class SurfaceAnimatorTest extends WindowTestsBase { 60 61 @Mock AnimationAdapter mSpec; 62 @Mock AnimationAdapter mSpec2; 63 @Mock Transaction mTransaction; 64 65 private SurfaceSession mSession = new SurfaceSession(); 66 private MyAnimatable mAnimatable; 67 private MyAnimatable mAnimatable2; 68 private DeferFinishAnimatable mDeferFinishAnimatable; 69 70 @Before 71 public void setUp() throws Exception { 72 super.setUp(); 73 MockitoAnnotations.initMocks(this); 74 mAnimatable = new MyAnimatable(); 75 mAnimatable2 = new MyAnimatable(); 76 mDeferFinishAnimatable = new DeferFinishAnimatable(); 77 } 78 79 @Test 80 public void testRunAnimation() throws Exception { 81 mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */); 82 final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass( 83 OnAnimationFinishedCallback.class); 84 assertAnimating(mAnimatable); 85 verify(mTransaction).reparent(eq(mAnimatable.mSurface), eq(mAnimatable.mLeash.getHandle())); 86 verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture()); 87 88 callbackCaptor.getValue().onAnimationFinished(mSpec); 89 assertNotAnimating(mAnimatable); 90 assertTrue(mAnimatable.mFinishedCallbackCalled); 91 verify(mTransaction).destroy(eq(mAnimatable.mLeash)); 92 // TODO: Verify reparenting once we use mPendingTransaction to reparent it back 93 } 94 95 @Test 96 public void testOverrideAnimation() throws Exception { 97 mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */); 98 final SurfaceControl firstLeash = mAnimatable.mLeash; 99 mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec2, true /* hidden */); 100 101 verify(mTransaction).destroy(eq(firstLeash)); 102 assertFalse(mAnimatable.mFinishedCallbackCalled); 103 104 final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass( 105 OnAnimationFinishedCallback.class); 106 assertAnimating(mAnimatable); 107 verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture()); 108 109 // First animation was finished, but this shouldn't cancel the second animation 110 callbackCaptor.getValue().onAnimationFinished(mSpec); 111 assertTrue(mAnimatable.mSurfaceAnimator.isAnimating()); 112 113 // Second animation was finished 114 verify(mSpec2).startAnimation(any(), any(), callbackCaptor.capture()); 115 callbackCaptor.getValue().onAnimationFinished(mSpec2); 116 assertNotAnimating(mAnimatable); 117 assertTrue(mAnimatable.mFinishedCallbackCalled); 118 } 119 120 @Test 121 public void testCancelAnimation() throws Exception { 122 mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */); 123 assertAnimating(mAnimatable); 124 mAnimatable.mSurfaceAnimator.cancelAnimation(); 125 assertNotAnimating(mAnimatable); 126 verify(mSpec).onAnimationCancelled(any()); 127 assertTrue(mAnimatable.mFinishedCallbackCalled); 128 verify(mTransaction).destroy(eq(mAnimatable.mLeash)); 129 } 130 131 @Test 132 public void testDelayingAnimationStart() throws Exception { 133 mAnimatable.mSurfaceAnimator.startDelayingAnimationStart(); 134 mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */); 135 verifyZeroInteractions(mSpec); 136 assertAnimating(mAnimatable); 137 assertTrue(mAnimatable.mSurfaceAnimator.isAnimationStartDelayed()); 138 mAnimatable.mSurfaceAnimator.endDelayingAnimationStart(); 139 verify(mSpec).startAnimation(any(), any(), any()); 140 } 141 142 @Test 143 public void testDelayingAnimationStartAndCancelled() throws Exception { 144 mAnimatable.mSurfaceAnimator.startDelayingAnimationStart(); 145 mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */); 146 mAnimatable.mSurfaceAnimator.cancelAnimation(); 147 verifyZeroInteractions(mSpec); 148 assertNotAnimating(mAnimatable); 149 assertTrue(mAnimatable.mFinishedCallbackCalled); 150 verify(mTransaction).destroy(eq(mAnimatable.mLeash)); 151 } 152 153 @Test 154 public void testTransferAnimation() throws Exception { 155 mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, true /* hidden */); 156 157 final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass( 158 OnAnimationFinishedCallback.class); 159 verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture()); 160 final SurfaceControl leash = mAnimatable.mLeash; 161 162 mAnimatable2.mSurfaceAnimator.transferAnimation(mAnimatable.mSurfaceAnimator); 163 assertNotAnimating(mAnimatable); 164 assertAnimating(mAnimatable2); 165 assertEquals(leash, mAnimatable2.mSurfaceAnimator.mLeash); 166 verify(mTransaction, never()).destroy(eq(leash)); 167 callbackCaptor.getValue().onAnimationFinished(mSpec); 168 assertNotAnimating(mAnimatable2); 169 assertTrue(mAnimatable2.mFinishedCallbackCalled); 170 verify(mTransaction).destroy(eq(leash)); 171 } 172 173 @Test 174 @FlakyTest(detail = "Promote once confirmed non-flaky") 175 public void testDeferFinish() throws Exception { 176 177 // Start animation 178 mDeferFinishAnimatable.mSurfaceAnimator.startAnimation(mTransaction, mSpec, 179 true /* hidden */); 180 final ArgumentCaptor<OnAnimationFinishedCallback> callbackCaptor = ArgumentCaptor.forClass( 181 OnAnimationFinishedCallback.class); 182 assertAnimating(mDeferFinishAnimatable); 183 verify(mSpec).startAnimation(any(), any(), callbackCaptor.capture()); 184 185 // Finish the animation but then make sure we are deferring. 186 callbackCaptor.getValue().onAnimationFinished(mSpec); 187 assertAnimating(mDeferFinishAnimatable); 188 189 // Now end defer finishing. 190 mDeferFinishAnimatable.endDeferFinishCallback.run(); 191 assertNotAnimating(mAnimatable2); 192 assertTrue(mDeferFinishAnimatable.mFinishedCallbackCalled); 193 verify(mTransaction).destroy(eq(mDeferFinishAnimatable.mLeash)); 194 } 195 196 private void assertAnimating(MyAnimatable animatable) { 197 assertTrue(animatable.mSurfaceAnimator.isAnimating()); 198 assertNotNull(animatable.mSurfaceAnimator.getAnimation()); 199 } 200 201 private void assertNotAnimating(MyAnimatable animatable) { 202 assertFalse(animatable.mSurfaceAnimator.isAnimating()); 203 assertNull(animatable.mSurfaceAnimator.getAnimation()); 204 } 205 206 private class MyAnimatable implements Animatable { 207 208 final SurfaceControl mParent; 209 final SurfaceControl mSurface; 210 final SurfaceAnimator mSurfaceAnimator; 211 SurfaceControl mLeash; 212 boolean mFinishedCallbackCalled; 213 214 MyAnimatable() { 215 mParent = sWm.makeSurfaceBuilder(mSession) 216 .setName("test surface parent") 217 .setSize(3000, 3000) 218 .build(); 219 mSurface = sWm.makeSurfaceBuilder(mSession) 220 .setName("test surface") 221 .setSize(1, 1) 222 .build(); 223 mFinishedCallbackCalled = false; 224 mLeash = null; 225 mSurfaceAnimator = new SurfaceAnimator(this, mFinishedCallback, sWm); 226 } 227 228 @Override 229 public Transaction getPendingTransaction() { 230 return mTransaction; 231 } 232 233 @Override 234 public void commitPendingTransaction() { 235 } 236 237 @Override 238 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) { 239 } 240 241 @Override 242 public void onAnimationLeashDestroyed(Transaction t) { 243 } 244 245 @Override 246 public Builder makeAnimationLeash() { 247 return new SurfaceControl.Builder(mSession) { 248 249 @Override 250 public SurfaceControl build() { 251 mLeash = super.build(); 252 return mLeash; 253 } 254 }.setParent(mParent); 255 } 256 257 @Override 258 public SurfaceControl getAnimationLeashParent() { 259 return mParent; 260 } 261 262 @Override 263 public SurfaceControl getSurfaceControl() { 264 return mSurface; 265 } 266 267 @Override 268 public SurfaceControl getParentSurfaceControl() { 269 return mParent; 270 } 271 272 @Override 273 public int getSurfaceWidth() { 274 return 1; 275 } 276 277 @Override 278 public int getSurfaceHeight() { 279 return 1; 280 } 281 282 private final Runnable mFinishedCallback = () -> mFinishedCallbackCalled = true; 283 } 284 285 private class DeferFinishAnimatable extends MyAnimatable { 286 287 Runnable endDeferFinishCallback; 288 289 @Override 290 public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) { 291 this.endDeferFinishCallback = endDeferFinishCallback; 292 return true; 293 } 294 } 295 } 296