1 /*
2  * Copyright (C) 2018 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 android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
20 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
21 import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
22 import static android.view.WindowManager.TRANSIT_OLD_ACTIVITY_OPEN;
23 import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY;
24 import static android.view.WindowManager.TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER;
25 import static android.view.WindowManager.TRANSIT_OLD_NONE;
26 import static android.view.WindowManager.TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE;
27 import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
28 
29 import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast;
30 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
31 import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
32 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
33 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
34 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions;
35 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
36 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
37 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
38 
39 import static junit.framework.Assert.assertFalse;
40 import static junit.framework.Assert.fail;
41 
42 import static org.junit.Assert.assertEquals;
43 import static org.junit.Assert.assertNotNull;
44 import static org.junit.Assert.assertTrue;
45 import static org.mockito.ArgumentMatchers.any;
46 import static org.mockito.ArgumentMatchers.anyBoolean;
47 import static org.mockito.ArgumentMatchers.anyFloat;
48 import static org.mockito.ArgumentMatchers.anyInt;
49 import static org.mockito.ArgumentMatchers.eq;
50 import static org.mockito.Mockito.mock;
51 
52 import android.graphics.Point;
53 import android.graphics.Rect;
54 import android.os.Binder;
55 import android.os.IBinder;
56 import android.os.IInterface;
57 import android.os.RemoteException;
58 import android.platform.test.annotations.Presubmit;
59 import android.view.IRemoteAnimationFinishedCallback;
60 import android.view.IRemoteAnimationRunner;
61 import android.view.RemoteAnimationAdapter;
62 import android.view.RemoteAnimationTarget;
63 import android.view.SurfaceControl;
64 import android.view.SurfaceControl.Transaction;
65 
66 import androidx.test.filters.SmallTest;
67 
68 import com.android.server.testutils.OffsettableClock;
69 import com.android.server.testutils.TestHandler;
70 import com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord;
71 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
72 
73 import org.junit.Before;
74 import org.junit.Test;
75 import org.junit.runner.RunWith;
76 import org.mockito.ArgumentCaptor;
77 import org.mockito.Mock;
78 import org.mockito.MockitoAnnotations;
79 
80 /**
81  * Build/Install/Run:
82  * atest WmTests:RemoteAnimationControllerTest
83  */
84 @SmallTest
85 @Presubmit
86 @RunWith(WindowTestRunner.class)
87 public class RemoteAnimationControllerTest extends WindowTestsBase {
88 
89     @Mock
90     SurfaceControl mMockLeash;
91     @Mock
92     SurfaceControl mMockThumbnailLeash;
93     @Mock
94     Transaction mMockTransaction;
95     @Mock
96     OnAnimationFinishedCallback mFinishedCallback;
97     @Mock
98     OnAnimationFinishedCallback mThumbnailFinishedCallback;
99     @Mock
100     IRemoteAnimationRunner mMockRunner;
101     private RemoteAnimationAdapter mAdapter;
102     private RemoteAnimationController mController;
103     private final OffsettableClock mClock = new OffsettableClock.Stopped();
104     private TestHandler mHandler;
105 
106     @Before
setUp()107     public void setUp() throws Exception {
108         MockitoAnnotations.initMocks(this);
109 
110         when(mMockRunner.asBinder()).thenReturn(new Binder());
111         mAdapter = new RemoteAnimationAdapter(mMockRunner, 100, 50, true /* changeNeedsSnapshot */);
112         mAdapter.setCallingPidUid(123, 456);
113         runWithScissors(mWm.mH, () -> mHandler = new TestHandler(null, mClock), 0);
114         mController = new RemoteAnimationController(mWm, mDisplayContent, mAdapter,
115                 mHandler, false /*isActivityEmbedding*/);
116     }
117 
createAppOverlayWindow()118     private WindowState createAppOverlayWindow() {
119         final WindowState win = createWindow(null /* parent */, TYPE_APPLICATION_OVERLAY,
120                 "testOverlayWindow");
121         win.mActivityRecord = null;
122         win.mHasSurface = true;
123         return win;
124     }
125 
126     @Test
testForwardsShowBackdrop()127     public void testForwardsShowBackdrop() throws Exception {
128         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
129         mDisplayContent.mOpeningApps.add(win.mActivityRecord);
130         final WindowState overlayWin = createAppOverlayWindow();
131         try {
132             final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
133                     win.mActivityRecord,
134                     new Point(50, 100), null, new Rect(50, 100, 150, 150), null,
135                     true /* showBackdrop */).mAdapter;
136             adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
137                     mFinishedCallback);
138             mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
139             mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
140             final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
141                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
142             final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
143                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
144             final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
145                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
146             final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
147                     ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
148             verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_ACTIVITY_OPEN),
149                     appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
150                     finishedCaptor.capture());
151             assertEquals(1, appsCaptor.getValue().length);
152             final RemoteAnimationTarget app = appsCaptor.getValue()[0];
153             assertTrue(app.showBackdrop);
154         } finally {
155             mDisplayContent.mOpeningApps.clear();
156         }
157     }
158 
159     @Test
testRun()160     public void testRun() throws Exception {
161         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
162         mDisplayContent.mOpeningApps.add(win.mActivityRecord);
163         final WindowState overlayWin = createAppOverlayWindow();
164         try {
165             final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
166                     win.mActivityRecord,
167                     new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false).mAdapter;
168             adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
169                     mFinishedCallback);
170             mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
171             mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
172             final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
173                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
174             final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
175                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
176             final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
177                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
178             final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
179                     ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
180             verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_ACTIVITY_OPEN),
181                     appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
182                     finishedCaptor.capture());
183             assertEquals(1, appsCaptor.getValue().length);
184             final RemoteAnimationTarget app = appsCaptor.getValue()[0];
185             assertEquals(new Point(50, 100), app.position);
186             assertEquals(new Rect(50, 100, 150, 150), app.sourceContainerBounds);
187             assertEquals(win.mActivityRecord.getPrefixOrderIndex(), app.prefixOrderIndex);
188             assertEquals(win.mActivityRecord.getTask().mTaskId, app.taskId);
189             assertEquals(mMockLeash, app.leash);
190             assertEquals(false, app.isTranslucent);
191             verify(mMockTransaction).setPosition(mMockLeash, app.position.x, app.position.y);
192             verify(mMockTransaction).setWindowCrop(mMockLeash, 100, 50);
193 
194             finishedCaptor.getValue().onAnimationFinished();
195             verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
196                     eq(adapter));
197             assertEquals(0, nonAppsCaptor.getValue().length);
198         } finally {
199             mDisplayContent.mOpeningApps.clear();
200         }
201     }
202 
203     @Test
testCancel()204     public void testCancel() throws Exception {
205         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
206         final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
207                 win.mActivityRecord,
208                 new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false).mAdapter;
209         adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
210                 mFinishedCallback);
211         mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
212 
213         adapter.onAnimationCancelled(mMockLeash);
214         verify(mMockRunner).onAnimationCancelled();
215     }
216 
217     @Test
testTimeout()218     public void testTimeout() throws Exception {
219         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
220         final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
221                 win.mActivityRecord,
222                 new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false).mAdapter;
223         adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
224                 mFinishedCallback);
225         mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
226 
227         mClock.fastForward(10500);
228         mHandler.timeAdvance();
229 
230         verify(mMockRunner).onAnimationCancelled();
231         verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
232                 eq(adapter));
233     }
234 
235     @Test
testTimeout_scaled()236     public void testTimeout_scaled() throws Exception {
237         try {
238             mWm.setAnimationScale(2, 5.0f);
239             final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION,
240                     "testWin");
241             final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
242                     win.mActivityRecord, new Point(50, 100), null, new Rect(50, 100, 150, 150),
243                     null, false).mAdapter;
244             adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
245                     mFinishedCallback);
246             mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
247 
248             mClock.fastForward(10500);
249             mHandler.timeAdvance();
250 
251             verify(mMockRunner, never()).onAnimationCancelled();
252 
253             mClock.fastForward(52500);
254             mHandler.timeAdvance();
255 
256             verify(mMockRunner).onAnimationCancelled();
257             verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
258                     eq(adapter));
259         } finally {
260             mWm.setAnimationScale(2, 1.0f);
261         }
262     }
263 
264     @Test
testZeroAnimations()265     public void testZeroAnimations() throws Exception {
266         mController.goodToGo(TRANSIT_OLD_NONE);
267         verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any());
268         verify(mMockRunner).onAnimationCancelled();
269     }
270 
271     @Test
testNotReallyStarted()272     public void testNotReallyStarted() throws Exception {
273         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
274         mController.createRemoteAnimationRecord(win.mActivityRecord,
275                 new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false);
276         mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
277         verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any());
278         verify(mMockRunner).onAnimationCancelled();
279     }
280 
281     @Test
testOneNotStarted()282     public void testOneNotStarted() throws Exception {
283         final WindowState win1 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin1");
284         final WindowState win2 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin2");
285         mController.createRemoteAnimationRecord(win1.mActivityRecord,
286                 new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false);
287         final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
288                 win2.mActivityRecord,
289                 new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false).mAdapter;
290         adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
291                 mFinishedCallback);
292         mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
293         mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
294         final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
295                 ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
296         final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
297                 ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
298         final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
299                 ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
300         final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
301                 ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
302         verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_ACTIVITY_OPEN),
303                 appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
304                 finishedCaptor.capture());
305         assertEquals(1, appsCaptor.getValue().length);
306         assertEquals(mMockLeash, appsCaptor.getValue()[0].leash);
307     }
308 
309     @Test
testRemovedBeforeStarted()310     public void testRemovedBeforeStarted() throws Exception {
311         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
312         final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
313                 win.mActivityRecord,
314                 new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false).mAdapter;
315         adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
316                 mFinishedCallback);
317         win.mActivityRecord.removeImmediately();
318         mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
319         verify(mMockRunner, never()).onAnimationStart(anyInt(), any(), any(), any(), any());
320         verify(mMockRunner).onAnimationCancelled();
321         verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
322                 eq(adapter));
323     }
324 
325     @Test
testOpeningTaskWithTopFinishingActivity()326     public void testOpeningTaskWithTopFinishingActivity() {
327         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "win");
328         final Task task = win.getTask();
329         final ActivityRecord topFinishing = new ActivityBuilder(mAtm).setTask(task).build();
330         // Now the task contains:
331         //     - Activity[1] (top, finishing, no window)
332         //     - Activity[0] (has window)
333         topFinishing.finishing = true;
334         spyOn(mDisplayContent.mAppTransition);
335         doReturn(mController).when(mDisplayContent.mAppTransition).getRemoteAnimationController();
336         task.applyAnimationUnchecked(null /* lp */, true /* enter */, TRANSIT_OLD_TASK_OPEN,
337                 false /* isVoiceInteraction */, null /* sources */);
338         mController.goodToGo(TRANSIT_OLD_TASK_OPEN);
339         mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
340         final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
341                 ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
342         try {
343             verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_OPEN),
344                     appsCaptor.capture(), any(), any(), any());
345         } catch (RemoteException ignored) {
346         }
347         assertEquals(1, appsCaptor.getValue().length);
348         assertEquals(RemoteAnimationTarget.MODE_OPENING, appsCaptor.getValue()[0].mode);
349     }
350 
351     @Test
testChangeToSmallerSize()352     public void testChangeToSmallerSize() throws Exception {
353         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
354         mDisplayContent.mChangingContainers.add(win.mActivityRecord);
355         try {
356             final RemoteAnimationRecord record = mController.createRemoteAnimationRecord(
357                     win.mActivityRecord, new Point(50, 100), null, new Rect(50, 100, 150, 150),
358                     new Rect(0, 0, 200, 200), false);
359             assertNotNull(record.mThumbnailAdapter);
360             ((AnimationAdapter) record.mAdapter)
361                     .startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION,
362                             mFinishedCallback);
363             ((AnimationAdapter) record.mThumbnailAdapter).startAnimation(mMockThumbnailLeash,
364                     mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION, mThumbnailFinishedCallback);
365             mController.goodToGo(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE);
366             mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
367             final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
368                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
369             final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
370                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
371             final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
372                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
373             final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
374                     ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
375             verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE),
376                     appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
377                     finishedCaptor.capture());
378             assertEquals(1, appsCaptor.getValue().length);
379             final RemoteAnimationTarget app = appsCaptor.getValue()[0];
380             assertEquals(RemoteAnimationTarget.MODE_CHANGING, app.mode);
381             assertEquals(new Point(50, 100), app.position);
382             assertEquals(new Rect(50, 100, 150, 150), app.sourceContainerBounds);
383             assertEquals(new Rect(0, 0, 200, 200), app.startBounds);
384             assertEquals(mMockLeash, app.leash);
385             assertEquals(mMockThumbnailLeash, app.startLeash);
386             assertEquals(false, app.isTranslucent);
387             verify(mMockTransaction).setPosition(
388                     mMockLeash, app.startBounds.left, app.startBounds.top);
389             verify(mMockTransaction).setWindowCrop(
390                     mMockLeash, app.startBounds.width(), app.startBounds.height());
391             verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
392             verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, app.startBounds.width(),
393                     app.startBounds.height());
394 
395             finishedCaptor.getValue().onAnimationFinished();
396             verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),
397                     eq(record.mAdapter));
398             verify(mThumbnailFinishedCallback).onAnimationFinished(
399                     eq(ANIMATION_TYPE_WINDOW_ANIMATION), eq(record.mThumbnailAdapter));
400         } finally {
401             mDisplayContent.mChangingContainers.clear();
402         }
403     }
404 
405     @Test
testChangeTolargerSize()406     public void testChangeTolargerSize() throws Exception {
407         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
408         mDisplayContent.mChangingContainers.add(win.mActivityRecord);
409         try {
410             final RemoteAnimationRecord record = mController.createRemoteAnimationRecord(
411                     win.mActivityRecord, new Point(0, 0), null, new Rect(0, 0, 200, 200),
412                     new Rect(50, 100, 150, 150), false);
413             assertNotNull(record.mThumbnailAdapter);
414             ((AnimationAdapter) record.mAdapter)
415                     .startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION,
416                             mFinishedCallback);
417             ((AnimationAdapter) record.mThumbnailAdapter).startAnimation(mMockThumbnailLeash,
418                     mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION, mThumbnailFinishedCallback);
419             mController.goodToGo(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE);
420             mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
421             final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
422                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
423             final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
424                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
425             final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
426                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
427             final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
428                     ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
429             verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE),
430                     appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
431                     finishedCaptor.capture());
432             assertEquals(1, appsCaptor.getValue().length);
433             final RemoteAnimationTarget app = appsCaptor.getValue()[0];
434             assertEquals(RemoteAnimationTarget.MODE_CHANGING, app.mode);
435             assertEquals(new Point(0, 0), app.position);
436             assertEquals(new Rect(0, 0, 200, 200), app.sourceContainerBounds);
437             assertEquals(new Rect(50, 100, 150, 150), app.startBounds);
438             assertEquals(mMockLeash, app.leash);
439             assertEquals(mMockThumbnailLeash, app.startLeash);
440             assertEquals(false, app.isTranslucent);
441             verify(mMockTransaction).setPosition(
442                     mMockLeash, app.startBounds.left, app.startBounds.top);
443             verify(mMockTransaction).setWindowCrop(
444                     mMockLeash, app.startBounds.width(), app.startBounds.height());
445             verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
446             verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, app.startBounds.width(),
447                     app.startBounds.height());
448 
449             finishedCaptor.getValue().onAnimationFinished();
450             verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),
451                     eq(record.mAdapter));
452             verify(mThumbnailFinishedCallback).onAnimationFinished(
453                     eq(ANIMATION_TYPE_WINDOW_ANIMATION), eq(record.mThumbnailAdapter));
454         } finally {
455             mDisplayContent.mChangingContainers.clear();
456         }
457     }
458 
459     @Test
testChangeToDifferentPosition()460     public void testChangeToDifferentPosition() throws Exception {
461         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
462         mDisplayContent.mChangingContainers.add(win.mActivityRecord);
463         try {
464             final RemoteAnimationRecord record = mController.createRemoteAnimationRecord(
465                     win.mActivityRecord, new Point(100, 100), null, new Rect(150, 150, 400, 400),
466                     new Rect(50, 100, 150, 150), false);
467             assertNotNull(record.mThumbnailAdapter);
468             ((AnimationAdapter) record.mAdapter)
469                     .startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION,
470                             mFinishedCallback);
471             ((AnimationAdapter) record.mThumbnailAdapter).startAnimation(mMockThumbnailLeash,
472                     mMockTransaction, ANIMATION_TYPE_WINDOW_ANIMATION, mThumbnailFinishedCallback);
473             mController.goodToGo(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE);
474             mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
475             final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
476                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
477             final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
478                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
479             final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
480                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
481             final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
482                     ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
483             verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_CHANGE_WINDOWING_MODE),
484                     appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
485                     finishedCaptor.capture());
486             assertEquals(1, appsCaptor.getValue().length);
487             final RemoteAnimationTarget app = appsCaptor.getValue()[0];
488             assertEquals(RemoteAnimationTarget.MODE_CHANGING, app.mode);
489             assertEquals(new Point(100, 100), app.position);
490             assertEquals(new Rect(150, 150, 400, 400), app.sourceContainerBounds);
491             assertEquals(new Rect(50, 100, 150, 150), app.startBounds);
492             assertEquals(mMockLeash, app.leash);
493             assertEquals(mMockThumbnailLeash, app.startLeash);
494             assertEquals(false, app.isTranslucent);
495             verify(mMockTransaction).setPosition(
496                     mMockLeash, app.position.x + app.startBounds.left - app.screenSpaceBounds.left,
497                     app.position.y + app.startBounds.top - app.screenSpaceBounds.top);
498             verify(mMockTransaction).setWindowCrop(
499                     mMockLeash, app.startBounds.width(), app.startBounds.height());
500             verify(mMockTransaction).setPosition(mMockThumbnailLeash, 0, 0);
501             verify(mMockTransaction).setWindowCrop(mMockThumbnailLeash, app.startBounds.width(),
502                     app.startBounds.height());
503 
504             finishedCaptor.getValue().onAnimationFinished();
505             verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_WINDOW_ANIMATION),
506                     eq(record.mAdapter));
507             verify(mThumbnailFinishedCallback).onAnimationFinished(
508                     eq(ANIMATION_TYPE_WINDOW_ANIMATION), eq(record.mThumbnailAdapter));
509         } finally {
510             mDisplayContent.mChangingContainers.clear();
511         }
512     }
513 
514     @Test
testWallpaperIncluded_expectTarget()515     public void testWallpaperIncluded_expectTarget() throws Exception {
516         final WindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, mock(IBinder.class),
517                 true, mDisplayContent, true /* ownerCanManageAppTokens */);
518         spyOn(mDisplayContent.mWallpaperController);
519         doReturn(true).when(mDisplayContent.mWallpaperController).isWallpaperVisible();
520         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
521         mDisplayContent.mOpeningApps.add(win.mActivityRecord);
522         try {
523             final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
524                     win.mActivityRecord,
525                     new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false).mAdapter;
526             adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
527                     mFinishedCallback);
528             mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
529             mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
530             final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
531                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
532             final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
533                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
534             final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
535                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
536             final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
537                     ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
538             verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_ACTIVITY_OPEN),
539                     appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
540                     finishedCaptor.capture());
541             assertEquals(1, wallpapersCaptor.getValue().length);
542         } finally {
543             mDisplayContent.mOpeningApps.clear();
544         }
545     }
546 
547     @Test
testWallpaperAnimatorCanceled_expectAnimationKeepsRunning()548     public void testWallpaperAnimatorCanceled_expectAnimationKeepsRunning() throws Exception {
549         final WindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, mock(IBinder.class),
550                 true, mDisplayContent, true /* ownerCanManageAppTokens */);
551         spyOn(mDisplayContent.mWallpaperController);
552         doReturn(true).when(mDisplayContent.mWallpaperController).isWallpaperVisible();
553         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
554         mDisplayContent.mOpeningApps.add(win.mActivityRecord);
555         try {
556             final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
557                     win.mActivityRecord,
558                     new Point(50, 100), null, new Rect(50, 100, 150, 150), null, false).mAdapter;
559             adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
560                     mFinishedCallback);
561             mController.goodToGo(TRANSIT_OLD_ACTIVITY_OPEN);
562             mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
563             final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
564                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
565             final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
566                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
567             final ArgumentCaptor<RemoteAnimationTarget[]> nonAPpsCaptor =
568                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
569             final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
570                     ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
571             verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_ACTIVITY_OPEN),
572                     appsCaptor.capture(), wallpapersCaptor.capture(), nonAPpsCaptor.capture(),
573                     finishedCaptor.capture());
574             assertEquals(1, wallpapersCaptor.getValue().length);
575 
576             // Cancel the wallpaper window animator and ensure the runner is not canceled
577             wallpaperWindowToken.cancelAnimation();
578             verify(mMockRunner, never()).onAnimationCancelled();
579         } finally {
580             mDisplayContent.mOpeningApps.clear();
581         }
582     }
583 
584     @Test
testNonAppIncluded_keygaurdGoingAway()585     public void testNonAppIncluded_keygaurdGoingAway() throws Exception {
586         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
587         mDisplayContent.mOpeningApps.add(win.mActivityRecord);
588         // Add overlay window hidden by the keyguard.
589         final WindowState overlayWin = createAppOverlayWindow();
590         overlayWin.hide(false /* doAnimation */, false /* requestAnim */);
591         try {
592             final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
593                     win.mActivityRecord, new Point(50, 100), null,
594                     new Rect(50, 100, 150, 150), null, false).mAdapter;
595             adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
596                     mFinishedCallback);
597             mController.goodToGo(TRANSIT_OLD_KEYGUARD_GOING_AWAY);
598             mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
599             final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
600                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
601             final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
602                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
603             final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
604                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
605             final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
606                     ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
607             verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_KEYGUARD_GOING_AWAY),
608                     appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
609                     finishedCaptor.capture());
610             assertEquals(1, appsCaptor.getValue().length);
611             final RemoteAnimationTarget app = appsCaptor.getValue()[0];
612             assertEquals(new Point(50, 100), app.position);
613             assertEquals(new Rect(50, 100, 150, 150), app.sourceContainerBounds);
614             assertEquals(win.mActivityRecord.getPrefixOrderIndex(), app.prefixOrderIndex);
615             assertEquals(win.mActivityRecord.getTask().mTaskId, app.taskId);
616             assertEquals(mMockLeash, app.leash);
617             assertEquals(false, app.isTranslucent);
618             verify(mMockTransaction).setPosition(mMockLeash, app.position.x, app.position.y);
619             verify(mMockTransaction).setWindowCrop(mMockLeash, 100, 50);
620 
621             finishedCaptor.getValue().onAnimationFinished();
622             verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
623                     eq(adapter));
624             assertEquals(1, nonAppsCaptor.getValue().length);
625         } finally {
626             mDisplayContent.mOpeningApps.clear();
627         }
628     }
629 
630     @Test
testNonAppIncluded_keygaurdGoingAwayToWallpaper()631     public void testNonAppIncluded_keygaurdGoingAwayToWallpaper() throws Exception {
632         final WindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm, mock(IBinder.class),
633                 true, mDisplayContent, true /* ownerCanManageAppTokens */);
634         spyOn(mDisplayContent.mWallpaperController);
635         doReturn(true).when(mDisplayContent.mWallpaperController).isWallpaperVisible();
636         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
637         mDisplayContent.mOpeningApps.add(win.mActivityRecord);
638         // Add overlay window hidden by the keyguard.
639         final WindowState overlayWin = createAppOverlayWindow();
640         overlayWin.hide(false /* doAnimation */, false /* requestAnim */);
641         try {
642             final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
643                     win.mActivityRecord, new Point(50, 100), null,
644                     new Rect(50, 100, 150, 150), null, false).mAdapter;
645             adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
646                     mFinishedCallback);
647             mController.goodToGo(TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER);
648             mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
649             final ArgumentCaptor<RemoteAnimationTarget[]> appsCaptor =
650                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
651             final ArgumentCaptor<RemoteAnimationTarget[]> wallpapersCaptor =
652                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
653             final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
654                     ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
655             final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
656                     ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
657             verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_KEYGUARD_GOING_AWAY_ON_WALLPAPER),
658                     appsCaptor.capture(), wallpapersCaptor.capture(), nonAppsCaptor.capture(),
659                     finishedCaptor.capture());
660             assertEquals(1, wallpapersCaptor.getValue().length);
661             assertEquals(1, nonAppsCaptor.getValue().length);
662         } finally {
663             mDisplayContent.mOpeningApps.clear();
664         }
665     }
666 
667     @Test
testNonAppTarget_sendNavBar()668     public void testNonAppTarget_sendNavBar() throws Exception {
669         final int transit = TRANSIT_OLD_TASK_OPEN;
670         final AnimationAdapter adapter = setupForNonAppTargetNavBar(transit, true);
671 
672         final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
673                 ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
674         final ArgumentCaptor<IRemoteAnimationFinishedCallback> finishedCaptor =
675                 ArgumentCaptor.forClass(IRemoteAnimationFinishedCallback.class);
676         verify(mMockRunner).onAnimationStart(eq(transit), any(), any(),
677                 nonAppsCaptor.capture(), finishedCaptor.capture());
678         boolean containNavTarget = false;
679         for (int i = 0; i < nonAppsCaptor.getValue().length; i++) {
680             if (nonAppsCaptor.getValue()[0].windowType == TYPE_NAVIGATION_BAR) {
681                 containNavTarget = true;
682                 break;
683             }
684         }
685         assertTrue(containNavTarget);
686         assertEquals(1, mController.mPendingNonAppAnimations.size());
687         final NonAppWindowAnimationAdapter nonAppAdapter =
688                 mController.mPendingNonAppAnimations.get(0);
689         spyOn(nonAppAdapter.getLeashFinishedCallback());
690 
691         finishedCaptor.getValue().onAnimationFinished();
692         verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_APP_TRANSITION),
693                 eq(adapter));
694         verify(nonAppAdapter.getLeashFinishedCallback())
695                 .onAnimationFinished(nonAppAdapter.getLastAnimationType(), nonAppAdapter);
696     }
697 
698     @Test
testNonAppTarget_notSendNavBar_notAttachToApp()699     public void testNonAppTarget_notSendNavBar_notAttachToApp() throws Exception {
700         final int transit = TRANSIT_OLD_TASK_OPEN;
701         setupForNonAppTargetNavBar(transit, false);
702 
703         final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
704                 ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
705         verify(mMockRunner).onAnimationStart(eq(transit),
706                 any(), any(), nonAppsCaptor.capture(), any());
707         for (int i = 0; i < nonAppsCaptor.getValue().length; i++) {
708             if (nonAppsCaptor.getValue()[0].windowType == TYPE_NAVIGATION_BAR) {
709                 fail("Non-app animation target must not contain navbar");
710             }
711         }
712     }
713 
714     @Test
testNonAppTarget_notSendNavBar_controlledByFadeRotation()715     public void testNonAppTarget_notSendNavBar_controlledByFadeRotation() throws Exception {
716         final AsyncRotationController mockController =
717                 mock(AsyncRotationController.class);
718         doReturn(mockController).when(mDisplayContent).getAsyncRotationController();
719         final int transit = TRANSIT_OLD_TASK_OPEN;
720         setupForNonAppTargetNavBar(transit, true);
721 
722         final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
723                 ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
724         verify(mMockRunner).onAnimationStart(eq(transit),
725                 any(), any(), nonAppsCaptor.capture(), any());
726         for (int i = 0; i < nonAppsCaptor.getValue().length; i++) {
727             if (nonAppsCaptor.getValue()[0].windowType == TYPE_NAVIGATION_BAR) {
728                 fail("Non-app animation target must not contain navbar");
729             }
730         }
731     }
732 
733     @Test
testNonAppTarget_notSendNavBar_controlledByRecents()734     public void testNonAppTarget_notSendNavBar_controlledByRecents() throws Exception {
735         final RecentsAnimationController mockController =
736                 mock(RecentsAnimationController.class);
737         doReturn(mockController).when(mWm).getRecentsAnimationController();
738         final int transit = TRANSIT_OLD_TASK_OPEN;
739         setupForNonAppTargetNavBar(transit, true);
740 
741         final ArgumentCaptor<RemoteAnimationTarget[]> nonAppsCaptor =
742                 ArgumentCaptor.forClass(RemoteAnimationTarget[].class);
743         verify(mMockRunner).onAnimationStart(eq(transit),
744                 any(), any(), nonAppsCaptor.capture(), any());
745         for (int i = 0; i < nonAppsCaptor.getValue().length; i++) {
746             if (nonAppsCaptor.getValue()[0].windowType == TYPE_NAVIGATION_BAR) {
747                 fail("Non-app animation target must not contain navbar");
748             }
749         }
750     }
751 
752     @SetupWindows(addWindows = W_INPUT_METHOD)
753     @Test
testLaunchRemoteAnimationWithoutImeBehind()754     public void testLaunchRemoteAnimationWithoutImeBehind() {
755         final WindowState win1 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin1");
756         final WindowState win2 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin2");
757 
758         // Simulating win1 has shown IME and being IME layering/input target
759         mDisplayContent.setImeLayeringTarget(win1);
760         mDisplayContent.setImeInputTarget(win1);
761         mImeWindow.mWinAnimator.mSurfaceController = mock(WindowSurfaceController.class);
762         mImeWindow.mWinAnimator.hide(mDisplayContent.getPendingTransaction(), "test");
763         spyOn(mDisplayContent);
764         doReturn(true).when(mImeWindow.mWinAnimator.mSurfaceController).hasSurface();
765         doReturn(true).when(mImeWindow.mWinAnimator.mSurfaceController)
766                 .prepareToShowInTransaction(any(), anyFloat());
767         makeWindowVisibleAndDrawn(mImeWindow);
768         assertTrue(mImeWindow.isOnScreen());
769         assertFalse(mImeWindow.isParentWindowHidden());
770 
771         try {
772             // Simulating now win1 is being covered by the lockscreen which has no surface,
773             // and then launching an activity win2 with the remote animation
774             win1.mHasSurface = false;
775             win1.mActivityRecord.setVisibility(false);
776             mDisplayContent.mOpeningApps.add(win2.mActivityRecord);
777             final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
778                     win2.mActivityRecord, new Point(50, 100), null,
779                     new Rect(50, 100, 150, 150), null, false).mAdapter;
780             adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
781                     mFinishedCallback);
782 
783             mDisplayContent.applySurfaceChangesTransaction();
784             mController.goodToGo(TRANSIT_OLD_TASK_OPEN);
785             mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
786 
787             verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_OPEN),
788                     any(), any(), any(), any());
789             // Verify the IME window won't apply surface change transaction with forAllImeWindows
790             verify(mDisplayContent, never()).forAllImeWindows(any(), eq(true));
791         } catch (Exception e) {
792             // no-op
793         } finally {
794             mDisplayContent.mOpeningApps.clear();
795         }
796     }
797 
setupForNonAppTargetNavBar(int transit, boolean shouldAttachNavBar)798     private AnimationAdapter setupForNonAppTargetNavBar(int transit, boolean shouldAttachNavBar) {
799         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
800         mDisplayContent.mOpeningApps.add(win.mActivityRecord);
801         final WindowState navBar = createWindow(null, TYPE_NAVIGATION_BAR, "NavigationBar");
802         mDisplayContent.getDisplayPolicy().addWindowLw(navBar, navBar.mAttrs);
803         final DisplayPolicy policy = mDisplayContent.getDisplayPolicy();
804         spyOn(policy);
805         doReturn(shouldAttachNavBar).when(policy).shouldAttachNavBarToAppDuringTransition();
806 
807         final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
808                 win.mActivityRecord, new Point(50, 100), null,
809                 new Rect(50, 100, 150, 150), null, false).mAdapter;
810         adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
811                 mFinishedCallback);
812         mController.goodToGo(transit);
813         mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
814         return adapter;
815     }
816 
verifyNoMoreInteractionsExceptAsBinder(IInterface binder)817     private static void verifyNoMoreInteractionsExceptAsBinder(IInterface binder) {
818         verify(binder, atLeast(0)).asBinder();
819         verifyNoMoreInteractions(binder);
820     }
821 }
822