blob: 8e85e7b96d1f07b63f39f6c76dd90d43acb085f5 [file] [log] [blame]
Winson Chungda876c92018-04-05 18:31:06 -07001/*
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
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070014 * limitations under the License.
Winson Chungda876c92018-04-05 18:31:06 -070015 */
16
17package com.android.server.wm;
18
19import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
20import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
21import static android.view.Display.DEFAULT_DISPLAY;
Vadim Caen2a9ccc92020-01-29 12:21:41 +010022import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
lumark54284462019-03-05 20:44:27 +080023import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
Vadim Caen2a9ccc92020-01-29 12:21:41 +010024import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
Brett Chabota26eda92018-07-23 13:08:30 -070025
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090026import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast;
lumark54284462019-03-05 20:44:27 +080027import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
Winson Chung7a545ae2019-07-16 14:52:13 -070028import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
Winson Chungd5852192019-09-06 17:20:28 -070029import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
lumark54284462019-03-05 20:44:27 +080030import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Winson Chungd5852192019-09-06 17:20:28 -070031import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
Tadashi G. Takaokabf0d57b2018-11-19 16:09:58 +090032import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
33import static com.android.dx.mockito.inline.extended.ExtendedMockito.verifyNoMoreInteractions;
34import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
Winson Chung7906b3e2018-05-10 10:32:39 -070035import static com.android.server.wm.RecentsAnimationController.REORDER_KEEP_IN_PLACE;
36import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_ORIGINAL_POSITION;
Winson Chungd5852192019-09-06 17:20:28 -070037import static com.android.server.wm.RecentsAnimationController.REORDER_MOVE_TO_TOP;
Issei Suzuki8b995df2020-01-08 12:23:04 +010038import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
Brett Chabota26eda92018-07-23 13:08:30 -070039
lumark54284462019-03-05 20:44:27 +080040import static org.junit.Assert.assertEquals;
Winson Chung732446a2018-09-19 13:15:17 -070041import static org.junit.Assert.assertFalse;
lumark54284462019-03-05 20:44:27 +080042import static org.junit.Assert.assertNotNull;
Winson Chung7a545ae2019-07-16 14:52:13 -070043import static org.junit.Assert.assertNull;
Winson Chung732446a2018-09-19 13:15:17 -070044import static org.junit.Assert.assertTrue;
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070045import static org.junit.Assert.fail;
lumarkf6f34942019-04-29 16:56:50 +080046import static org.mockito.ArgumentMatchers.any;
lumark54284462019-03-05 20:44:27 +080047import static org.mockito.ArgumentMatchers.anyBoolean;
Winson Chung7a545ae2019-07-16 14:52:13 -070048import static org.mockito.ArgumentMatchers.anyInt;
Winson Chungda876c92018-04-05 18:31:06 -070049import static org.mockito.ArgumentMatchers.eq;
Riddle Hsu6393ad12020-03-02 23:56:32 +080050import static org.mockito.Mockito.clearInvocations;
Winson Chungd5852192019-09-06 17:20:28 -070051import static org.mockito.Mockito.mock;
52import static org.mockito.Mockito.never;
Winson Chungda876c92018-04-05 18:31:06 -070053
Tracy Zhou8089ffa2019-07-30 17:30:43 -070054import android.app.ActivityManager.TaskSnapshot;
Vadim Caena0fa9662020-01-27 15:00:01 +010055import android.content.pm.ActivityInfo;
56import android.content.res.Configuration;
Winson Chungda876c92018-04-05 18:31:06 -070057import android.os.Binder;
Winson Chungd5852192019-09-06 17:20:28 -070058import android.os.IBinder;
Winson Chungda876c92018-04-05 18:31:06 -070059import android.os.IInterface;
60import android.platform.test.annotations.Presubmit;
Winson Chung732446a2018-09-19 13:15:17 -070061import android.util.SparseBooleanArray;
Winson Chungda876c92018-04-05 18:31:06 -070062import android.view.IRecentsAnimationRunner;
63import android.view.SurfaceControl;
Brett Chabota26eda92018-07-23 13:08:30 -070064
65import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -070066
Winson Chungda876c92018-04-05 18:31:06 -070067import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
Brett Chabota26eda92018-07-23 13:08:30 -070068
Vadim Caen2a9ccc92020-01-29 12:21:41 +010069import com.google.common.truth.Truth;
70
Winson Chungda876c92018-04-05 18:31:06 -070071import org.junit.Before;
72import org.junit.Test;
Riddle Hsu73f53572019-09-23 23:13:01 +080073import org.junit.runner.RunWith;
Winson Chungda876c92018-04-05 18:31:06 -070074import org.mockito.Mock;
75import org.mockito.MockitoAnnotations;
76
Vadim Caen2a9ccc92020-01-29 12:21:41 +010077import java.util.ArrayList;
78
Winson Chungda876c92018-04-05 18:31:06 -070079/**
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070080 * Build/Install/Run:
Riddle Hsu73f53572019-09-23 23:13:01 +080081 * atest WmTests:RecentsAnimationControllerTest
Winson Chungda876c92018-04-05 18:31:06 -070082 */
83@SmallTest
84@Presubmit
Riddle Hsu73f53572019-09-23 23:13:01 +080085@RunWith(WindowTestRunner.class)
Winson Chungda876c92018-04-05 18:31:06 -070086public class RecentsAnimationControllerTest extends WindowTestsBase {
87
88 @Mock SurfaceControl mMockLeash;
89 @Mock SurfaceControl.Transaction mMockTransaction;
90 @Mock OnAnimationFinishedCallback mFinishedCallback;
91 @Mock IRecentsAnimationRunner mMockRunner;
92 @Mock RecentsAnimationController.RecentsAnimationCallbacks mAnimationCallbacks;
Tracy Zhou8089ffa2019-07-30 17:30:43 -070093 @Mock TaskSnapshot mMockTaskSnapshot;
Winson Chungda876c92018-04-05 18:31:06 -070094 private RecentsAnimationController mController;
Riddle Hsu6393ad12020-03-02 23:56:32 +080095 private DisplayContent mDefaultDisplay;
96 private ActivityStack mRootHomeTask;
Winson Chungda876c92018-04-05 18:31:06 -070097
98 @Before
99 public void setUp() throws Exception {
Winson Chungda876c92018-04-05 18:31:06 -0700100 MockitoAnnotations.initMocks(this);
Riddle Hsu72d6dc32020-03-25 22:58:00 +0800101 doNothing().when(mWm.mRoot).performSurfacePlacement();
Winson Chungda876c92018-04-05 18:31:06 -0700102 when(mMockRunner.asBinder()).thenReturn(new Binder());
Riddle Hsu6393ad12020-03-02 23:56:32 +0800103 mDefaultDisplay = mWm.mRoot.getDefaultDisplay();
Winson Chungd5852192019-09-06 17:20:28 -0700104 mController = spy(new RecentsAnimationController(mWm, mMockRunner, mAnimationCallbacks,
105 DEFAULT_DISPLAY));
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700106 mRootHomeTask = mDefaultDisplay.getDefaultTaskDisplayArea().getRootHomeTask();
Riddle Hsu6393ad12020-03-02 23:56:32 +0800107 assertNotNull(mRootHomeTask);
Winson Chungda876c92018-04-05 18:31:06 -0700108 }
109
110 @Test
111 public void testRemovedBeforeStarted_expectCanceled() throws Exception {
Riddle Hsu6393ad12020-03-02 23:56:32 +0800112 final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
Winson Chungda876c92018-04-05 18:31:06 -0700113 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700114 AnimationAdapter adapter = mController.addAnimation(activity.getTask(),
Winson Chungda876c92018-04-05 18:31:06 -0700115 false /* isRecentTaskInvisible */);
Issei Suzuki8b995df2020-01-08 12:23:04 +0100116 adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_RECENTS,
117 mFinishedCallback);
Winson Chungda876c92018-04-05 18:31:06 -0700118
119 // Remove the app window so that the animation target can not be created
Garfield Tane8d84ab2019-10-11 09:49:40 -0700120 activity.removeImmediately();
Winson Chungda876c92018-04-05 18:31:06 -0700121 mController.startAnimation();
122
123 // Verify that the finish callback to reparent the leash is called
Issei Suzuki8b995df2020-01-08 12:23:04 +0100124 verify(mFinishedCallback).onAnimationFinished(eq(ANIMATION_TYPE_RECENTS), eq(adapter));
Winson Chungda876c92018-04-05 18:31:06 -0700125 // Verify the animation canceled callback to the app was made
Tracy Zhou8089ffa2019-07-30 17:30:43 -0700126 verify(mMockRunner).onAnimationCanceled(null /* taskSnapshot */);
Winson Chungda876c92018-04-05 18:31:06 -0700127 verifyNoMoreInteractionsExceptAsBinder(mMockRunner);
128 }
129
Winson Chung7906b3e2018-05-10 10:32:39 -0700130 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700131 public void testCancelAfterRemove_expectIgnored() {
Riddle Hsu6393ad12020-03-02 23:56:32 +0800132 final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
Winson Chung7906b3e2018-05-10 10:32:39 -0700133 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700134 AnimationAdapter adapter = mController.addAnimation(activity.getTask(),
Winson Chung7906b3e2018-05-10 10:32:39 -0700135 false /* isRecentTaskInvisible */);
Issei Suzuki8b995df2020-01-08 12:23:04 +0100136 adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_RECENTS,
137 mFinishedCallback);
Winson Chung7906b3e2018-05-10 10:32:39 -0700138
139 // Remove the app window so that the animation target can not be created
Garfield Tane8d84ab2019-10-11 09:49:40 -0700140 activity.removeImmediately();
Winson Chung7906b3e2018-05-10 10:32:39 -0700141 mController.startAnimation();
142 mController.cleanupAnimation(REORDER_KEEP_IN_PLACE);
143 try {
144 mController.cancelAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION, "test");
145 } catch (Exception e) {
146 fail("Unexpected failure when canceling animation after finishing it");
147 }
148 }
149
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700150 @Test
151 public void testIncludedApps_expectTargetAndVisible() {
152 mWm.setRecentsAnimationController(mController);
Riddle Hsu6393ad12020-03-02 23:56:32 +0800153 final ActivityRecord homeActivity = createHomeActivity();
154 final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
Winson Chung732446a2018-09-19 13:15:17 -0700155 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
Riddle Hsu6393ad12020-03-02 23:56:32 +0800156 final ActivityRecord hiddenActivity = createActivityRecord(mDefaultDisplay,
Winson Chung732446a2018-09-19 13:15:17 -0700157 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
Issei Suzukif2f6c912019-11-08 11:24:18 +0100158 hiddenActivity.setVisible(false);
Riddle Hsu6393ad12020-03-02 23:56:32 +0800159 mDefaultDisplay.getConfiguration().windowConfiguration.setRotation(
160 mDefaultDisplay.getRotation());
Riddle Hsu70a920c2020-05-05 17:20:32 +0800161 initializeRecentsAnimationController(mController, homeActivity);
Winson Chung732446a2018-09-19 13:15:17 -0700162
163 // Ensure that we are animating the target activity as well
Garfield Tane8d84ab2019-10-11 09:49:40 -0700164 assertTrue(mController.isAnimatingTask(homeActivity.getTask()));
165 assertTrue(mController.isAnimatingTask(activity.getTask()));
166 assertFalse(mController.isAnimatingTask(hiddenActivity.getTask()));
Winson Chung732446a2018-09-19 13:15:17 -0700167 }
168
lumark54284462019-03-05 20:44:27 +0800169 @Test
Winson Chungd5852192019-09-06 17:20:28 -0700170 public void testWallpaperIncluded_expectTarget() throws Exception {
171 mWm.setRecentsAnimationController(mController);
Riddle Hsu6393ad12020-03-02 23:56:32 +0800172 final ActivityRecord homeActivity = createHomeActivity();
173 final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
Winson Chungd5852192019-09-06 17:20:28 -0700174 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
Riddle Hsu6393ad12020-03-02 23:56:32 +0800175 final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
176 activity.addWindow(win1);
Winson Chungd5852192019-09-06 17:20:28 -0700177 final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
Riddle Hsu6393ad12020-03-02 23:56:32 +0800178 mock(IBinder.class), true, mDefaultDisplay, true /* ownerCanManageAppTokens */);
179 spyOn(mDefaultDisplay.mWallpaperController);
180 doReturn(true).when(mDefaultDisplay.mWallpaperController).isWallpaperVisible();
Winson Chungd5852192019-09-06 17:20:28 -0700181
Riddle Hsu6393ad12020-03-02 23:56:32 +0800182 mDefaultDisplay.getConfiguration().windowConfiguration.setRotation(
183 mDefaultDisplay.getRotation());
Riddle Hsu70a920c2020-05-05 17:20:32 +0800184 initializeRecentsAnimationController(mController, homeActivity);
Winson Chungd5852192019-09-06 17:20:28 -0700185 mController.startAnimation();
186
187 // Ensure that we are animating the app and wallpaper target
Riddle Hsu6393ad12020-03-02 23:56:32 +0800188 assertTrue(mController.isAnimatingTask(activity.getTask()));
Winson Chungd5852192019-09-06 17:20:28 -0700189 assertTrue(mController.isAnimatingWallpaper(wallpaperWindowToken));
190 }
191
192 @Test
193 public void testWallpaperAnimatorCanceled_expectAnimationKeepsRunning() throws Exception {
194 mWm.setRecentsAnimationController(mController);
Riddle Hsu6393ad12020-03-02 23:56:32 +0800195 final ActivityRecord homeActivity = createHomeActivity();
196 final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
Winson Chungd5852192019-09-06 17:20:28 -0700197 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700198 final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
199 activity.addWindow(win1);
Winson Chungd5852192019-09-06 17:20:28 -0700200 final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
Riddle Hsu6393ad12020-03-02 23:56:32 +0800201 mock(IBinder.class), true, mDefaultDisplay, true /* ownerCanManageAppTokens */);
202 spyOn(mDefaultDisplay.mWallpaperController);
203 doReturn(true).when(mDefaultDisplay.mWallpaperController).isWallpaperVisible();
Winson Chungd5852192019-09-06 17:20:28 -0700204
Riddle Hsu6393ad12020-03-02 23:56:32 +0800205 mDefaultDisplay.getConfiguration().windowConfiguration.setRotation(
206 mDefaultDisplay.getRotation());
Riddle Hsu70a920c2020-05-05 17:20:32 +0800207 initializeRecentsAnimationController(mController, homeActivity);
Winson Chungd5852192019-09-06 17:20:28 -0700208 mController.startAnimation();
209
210 // Cancel the animation and ensure the controller is still running
211 wallpaperWindowToken.cancelAnimation();
Garfield Tane8d84ab2019-10-11 09:49:40 -0700212 assertTrue(mController.isAnimatingTask(activity.getTask()));
Winson Chungd5852192019-09-06 17:20:28 -0700213 assertFalse(mController.isAnimatingWallpaper(wallpaperWindowToken));
214 verify(mMockRunner, never()).onAnimationCanceled(null /* taskSnapshot */);
215 }
216
217 @Test
218 public void testFinish_expectTargetAndWallpaperAdaptersRemoved() {
219 mWm.setRecentsAnimationController(mController);
Riddle Hsu6393ad12020-03-02 23:56:32 +0800220 final ActivityRecord homeActivity = createHomeActivity();
Garfield Tane8d84ab2019-10-11 09:49:40 -0700221 final WindowState hwin1 = createWindow(null, TYPE_BASE_APPLICATION, homeActivity, "hwin1");
222 homeActivity.addWindow(hwin1);
Riddle Hsu6393ad12020-03-02 23:56:32 +0800223 final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
Winson Chungd5852192019-09-06 17:20:28 -0700224 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700225 final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
226 activity.addWindow(win1);
Winson Chungd5852192019-09-06 17:20:28 -0700227 final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
Riddle Hsu6393ad12020-03-02 23:56:32 +0800228 mock(IBinder.class), true, mDefaultDisplay, true /* ownerCanManageAppTokens */);
229 spyOn(mDefaultDisplay.mWallpaperController);
230 doReturn(true).when(mDefaultDisplay.mWallpaperController).isWallpaperVisible();
Winson Chungd5852192019-09-06 17:20:28 -0700231
232 // Start and finish the animation
Riddle Hsu70a920c2020-05-05 17:20:32 +0800233 initializeRecentsAnimationController(mController, homeActivity);
Winson Chungd5852192019-09-06 17:20:28 -0700234 mController.startAnimation();
Riddle Hsu6393ad12020-03-02 23:56:32 +0800235
236 assertTrue(mController.isAnimatingTask(homeActivity.getTask()));
237 assertTrue(mController.isAnimatingTask(activity.getTask()));
238
Winson Chungd5852192019-09-06 17:20:28 -0700239 // Reset at this point since we may remove adapters that couldn't be created
Riddle Hsu6393ad12020-03-02 23:56:32 +0800240 clearInvocations(mController);
Winson Chungd5852192019-09-06 17:20:28 -0700241 mController.cleanupAnimation(REORDER_MOVE_TO_TOP);
242
243 // Ensure that we remove the task (home & app) and wallpaper adapters
244 verify(mController, times(2)).removeAnimation(any());
245 verify(mController, times(1)).removeWallpaperAnimation(any());
246 }
247
248 @Test
Winson Chung7a545ae2019-07-16 14:52:13 -0700249 public void testDeferCancelAnimation() throws Exception {
lumark54284462019-03-05 20:44:27 +0800250 mWm.setRecentsAnimationController(mController);
Riddle Hsu6393ad12020-03-02 23:56:32 +0800251 final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
lumark54284462019-03-05 20:44:27 +0800252 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700253 final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
254 activity.addWindow(win1);
255 assertEquals(activity.getTask().getTopVisibleActivity(), activity);
256 assertEquals(activity.findMainWindow(), win1);
lumark54284462019-03-05 20:44:27 +0800257
Garfield Tane8d84ab2019-10-11 09:49:40 -0700258 mController.addAnimation(activity.getTask(), false /* isRecentTaskInvisible */);
259 assertTrue(mController.isAnimatingTask(activity.getTask()));
lumark54284462019-03-05 20:44:27 +0800260
Winson Chung7a545ae2019-07-16 14:52:13 -0700261 mController.setDeferredCancel(true /* deferred */, false /* screenshot */);
262 mController.cancelAnimationWithScreenshot(false /* screenshot */);
Tracy Zhou8089ffa2019-07-30 17:30:43 -0700263 verify(mMockRunner).onAnimationCanceled(null /* taskSnapshot */);
Winson Chung7a545ae2019-07-16 14:52:13 -0700264 assertNull(mController.mRecentScreenshotAnimator);
265
266 // Simulate the app transition finishing
267 mController.mAppTransitionListener.onAppTransitionStartingLocked(0, 0, 0, 0);
Wale Ogunwalea441b922019-06-27 19:21:44 -0700268 verify(mAnimationCallbacks).onAnimationFinished(REORDER_KEEP_IN_PLACE, false);
Winson Chung7a545ae2019-07-16 14:52:13 -0700269 }
270
271 @Test
272 public void testDeferCancelAnimationWithScreenShot() throws Exception {
273 mWm.setRecentsAnimationController(mController);
Riddle Hsu6393ad12020-03-02 23:56:32 +0800274 final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
Winson Chung7a545ae2019-07-16 14:52:13 -0700275 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700276 final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
277 activity.addWindow(win1);
278 assertEquals(activity.getTask().getTopVisibleActivity(), activity);
279 assertEquals(activity.findMainWindow(), win1);
Winson Chung7a545ae2019-07-16 14:52:13 -0700280
Garfield Tane8d84ab2019-10-11 09:49:40 -0700281 mController.addAnimation(activity.getTask(), false /* isRecentTaskInvisible */);
282 assertTrue(mController.isAnimatingTask(activity.getTask()));
Winson Chung7a545ae2019-07-16 14:52:13 -0700283
Tracy Zhou8089ffa2019-07-30 17:30:43 -0700284 spyOn(mWm.mTaskSnapshotController);
285 doNothing().when(mWm.mTaskSnapshotController).notifyAppVisibilityChanged(any(),
286 anyBoolean());
287 doReturn(mMockTaskSnapshot).when(mWm.mTaskSnapshotController).getSnapshot(anyInt(),
Peter Kalauskas4dc04602020-02-12 18:49:03 -0800288 anyInt(), eq(false) /* restoreFromDisk */, eq(false) /* isLowResolution */);
Winson Chung7a545ae2019-07-16 14:52:13 -0700289 mController.setDeferredCancel(true /* deferred */, true /* screenshot */);
290 mController.cancelAnimationWithScreenshot(true /* screenshot */);
Tracy Zhou8089ffa2019-07-30 17:30:43 -0700291 verify(mMockRunner).onAnimationCanceled(mMockTaskSnapshot /* taskSnapshot */);
lumark54284462019-03-05 20:44:27 +0800292 assertNotNull(mController.mRecentScreenshotAnimator);
293 assertTrue(mController.mRecentScreenshotAnimator.isAnimating());
294
295 // Assume IRecentsAnimationController#cleanupScreenshot called to finish screenshot
296 // animation.
lumarkf6f34942019-04-29 16:56:50 +0800297 spyOn(mController.mRecentScreenshotAnimator.mAnimatable);
lumark54284462019-03-05 20:44:27 +0800298 mController.mRecentScreenshotAnimator.cancelAnimation();
lumarkf6f34942019-04-29 16:56:50 +0800299 verify(mController.mRecentScreenshotAnimator.mAnimatable).onAnimationLeashLost(any());
Wale Ogunwalea441b922019-06-27 19:21:44 -0700300 verify(mAnimationCallbacks).onAnimationFinished(REORDER_KEEP_IN_PLACE, false);
lumark54284462019-03-05 20:44:27 +0800301 }
302
lumarkb5a78b32019-04-25 20:31:30 +0800303 @Test
304 public void testShouldAnimateWhenNoCancelWithDeferredScreenshot() {
305 mWm.setRecentsAnimationController(mController);
Riddle Hsu6393ad12020-03-02 23:56:32 +0800306 final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
lumarkb5a78b32019-04-25 20:31:30 +0800307 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700308 final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, activity, "win1");
309 activity.addWindow(win1);
310 assertEquals(activity.getTask().getTopVisibleActivity(), activity);
311 assertEquals(activity.findMainWindow(), win1);
lumarkb5a78b32019-04-25 20:31:30 +0800312
Garfield Tane8d84ab2019-10-11 09:49:40 -0700313 mController.addAnimation(activity.getTask(), false /* isRecentTaskInvisible */);
314 assertTrue(mController.isAnimatingTask(activity.getTask()));
lumarkb5a78b32019-04-25 20:31:30 +0800315
Garfield Tane8d84ab2019-10-11 09:49:40 -0700316 // Assume activity transition should animate when no
Hongwei Wang85cf41f2020-01-15 15:14:47 -0800317 // IRecentsAnimationController#setDeferCancelUntilNextTransition called.
Winson Chung7a545ae2019-07-16 14:52:13 -0700318 assertFalse(mController.shouldDeferCancelWithScreenshot());
Evan Rosky50ea8c12020-04-02 20:49:05 -0700319 assertTrue(activity.shouldAnimate());
lumarkb5a78b32019-04-25 20:31:30 +0800320 }
321
Vadim Caena0fa9662020-01-27 15:00:01 +0100322 @Test
323 public void testRecentViewInFixedPortraitWhenTopAppInLandscape() {
Vadim Caena0fa9662020-01-27 15:00:01 +0100324 mWm.setRecentsAnimationController(mController);
325
Riddle Hsu6393ad12020-03-02 23:56:32 +0800326 final ActivityRecord homeActivity = createHomeActivity();
327 homeActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
Vadim Caena0fa9662020-01-27 15:00:01 +0100328
Riddle Hsu6393ad12020-03-02 23:56:32 +0800329 final ActivityRecord landActivity = createActivityRecord(mDefaultDisplay,
Vadim Caena0fa9662020-01-27 15:00:01 +0100330 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
331 landActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
332 final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, landActivity, "win1");
333 landActivity.addWindow(win1);
334
335 assertEquals(landActivity.getTask().getTopVisibleActivity(), landActivity);
336 assertEquals(landActivity.findMainWindow(), win1);
337
338 // Ensure that the display is in Landscape
339 landActivity.onDescendantOrientationChanged(landActivity.token, landActivity);
340 assertEquals(Configuration.ORIENTATION_LANDSCAPE,
Riddle Hsu6393ad12020-03-02 23:56:32 +0800341 mDefaultDisplay.getConfiguration().orientation);
Vadim Caena0fa9662020-01-27 15:00:01 +0100342
Riddle Hsu70a920c2020-05-05 17:20:32 +0800343 initializeRecentsAnimationController(mController, homeActivity);
Vadim Caena0fa9662020-01-27 15:00:01 +0100344
Riddle Hsu08bc4ed2020-05-26 18:32:18 +0800345 assertTrue(mDefaultDisplay.isFixedRotationLaunchingApp(homeActivity));
Riddle Hsucbc5d272020-04-24 23:26:46 +0800346
Vadim Caena0fa9662020-01-27 15:00:01 +0100347 // Check that the home app is in portrait
348 assertEquals(Configuration.ORIENTATION_PORTRAIT,
Riddle Hsu6393ad12020-03-02 23:56:32 +0800349 homeActivity.getConfiguration().orientation);
Riddle Hsucbc5d272020-04-24 23:26:46 +0800350
Riddle Hsue291c7d2020-06-10 22:58:20 +0800351 // Home activity won't become top (return to landActivity), so the top rotated record should
352 // be cleared.
Riddle Hsucbc5d272020-04-24 23:26:46 +0800353 mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
Riddle Hsue291c7d2020-06-10 22:58:20 +0800354 assertFalse(mDefaultDisplay.isFixedRotationLaunchingApp(homeActivity));
Riddle Hsu08bc4ed2020-05-26 18:32:18 +0800355 assertFalse(mDefaultDisplay.hasTopFixedRotationLaunchingApp());
Riddle Hsue291c7d2020-06-10 22:58:20 +0800356 // The transform should keep until the transition is done, so the restored configuration
357 // won't be sent to activity and cause unnecessary configuration change.
358 assertTrue(homeActivity.hasFixedRotationTransform());
359
360 // In real case the transition will be executed from RecentsAnimation#finishAnimation.
361 mDefaultDisplay.mFixedRotationTransitionListener.onAppTransitionFinishedLocked(
362 homeActivity.token);
363 assertFalse(homeActivity.hasFixedRotationTransform());
Vadim Caena0fa9662020-01-27 15:00:01 +0100364 }
365
Vadim Caen2a9ccc92020-01-29 12:21:41 +0100366 @Test
Riddle Hsu70a920c2020-05-05 17:20:32 +0800367 public void testClearFixedRotationLaunchingAppAfterCleanupAnimation() {
368 final ActivityRecord homeActivity = createHomeActivity();
369 homeActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
370 final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
371 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
372 // Assume an activity is launching to different rotation.
373 mDefaultDisplay.setFixedRotationLaunchingApp(activity,
374 (mDefaultDisplay.getRotation() + 1) % 4);
375
376 assertTrue(activity.hasFixedRotationTransform());
Riddle Hsu08bc4ed2020-05-26 18:32:18 +0800377 assertTrue(mDefaultDisplay.isFixedRotationLaunchingApp(activity));
Riddle Hsu70a920c2020-05-05 17:20:32 +0800378
379 // Before the transition is done, the recents animation is triggered.
380 initializeRecentsAnimationController(mController, homeActivity);
381 assertFalse(homeActivity.hasFixedRotationTransform());
382
383 // Simulate giving up the swipe up gesture to keep the original activity as top.
384 mController.cleanupAnimation(REORDER_MOVE_TO_ORIGINAL_POSITION);
385 // The rotation transform should be cleared after updating orientation with display.
386 assertFalse(activity.hasFixedRotationTransform());
Riddle Hsu08bc4ed2020-05-26 18:32:18 +0800387 assertFalse(mDefaultDisplay.hasTopFixedRotationLaunchingApp());
Riddle Hsu70a920c2020-05-05 17:20:32 +0800388 }
389
390 @Test
Vadim Caen2a9ccc92020-01-29 12:21:41 +0100391 public void testWallpaperHasFixedRotationApplied() {
Vadim Caen2a9ccc92020-01-29 12:21:41 +0100392 mWm.setRecentsAnimationController(mController);
393
Riddle Hsu6393ad12020-03-02 23:56:32 +0800394 // Create a portrait home activity, a wallpaper and a landscape activity displayed on top.
395 final ActivityRecord homeActivity = createHomeActivity();
Vadim Caen2a9ccc92020-01-29 12:21:41 +0100396 homeActivity.setOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
397
398 final WindowState homeWindow = createWindow(null, TYPE_BASE_APPLICATION, homeActivity,
399 "homeWindow");
400 homeActivity.addWindow(homeWindow);
401 homeWindow.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
402
403 // Landscape application
Riddle Hsu6393ad12020-03-02 23:56:32 +0800404 final ActivityRecord activity = createActivityRecord(mDefaultDisplay,
Vadim Caen2a9ccc92020-01-29 12:21:41 +0100405 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
406 final WindowState applicationWindow = createWindow(null, TYPE_BASE_APPLICATION, activity,
407 "applicationWindow");
408 activity.addWindow(applicationWindow);
409 activity.setOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
410
411 // Wallpaper
412 final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
Riddle Hsu6393ad12020-03-02 23:56:32 +0800413 mock(IBinder.class), true, mDefaultDisplay, true /* ownerCanManageAppTokens */);
Vadim Caen2a9ccc92020-01-29 12:21:41 +0100414 final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, wallpaperWindowToken,
415 "wallpaperWindow");
416
417 // Make sure the landscape activity is on top and the display is in landscape
418 activity.moveFocusableActivityToTop("test");
Riddle Hsu6393ad12020-03-02 23:56:32 +0800419 mDefaultDisplay.getConfiguration().windowConfiguration.setRotation(
420 mDefaultDisplay.getRotation());
Vadim Caen2a9ccc92020-01-29 12:21:41 +0100421
Riddle Hsu6393ad12020-03-02 23:56:32 +0800422 spyOn(mDefaultDisplay.mWallpaperController);
423 doReturn(true).when(mDefaultDisplay.mWallpaperController).isWallpaperVisible();
Vadim Caen2a9ccc92020-01-29 12:21:41 +0100424
425 // Start the recents animation
Riddle Hsu70a920c2020-05-05 17:20:32 +0800426 initializeRecentsAnimationController(mController, homeActivity);
Vadim Caen2a9ccc92020-01-29 12:21:41 +0100427
Riddle Hsu6393ad12020-03-02 23:56:32 +0800428 mDefaultDisplay.mWallpaperController.adjustWallpaperWindows();
Vadim Caen2a9ccc92020-01-29 12:21:41 +0100429
430 // Check preconditions
431 ArrayList<WallpaperWindowToken> wallpapers = new ArrayList<>(1);
Riddle Hsu6393ad12020-03-02 23:56:32 +0800432 mDefaultDisplay.forAllWallpaperWindows(wallpapers::add);
Vadim Caen2a9ccc92020-01-29 12:21:41 +0100433
434 Truth.assertThat(wallpapers).hasSize(1);
435 Truth.assertThat(wallpapers.get(0).getTopChild()).isEqualTo(wallpaperWindow);
436
437 // Actual check
438 assertEquals(Configuration.ORIENTATION_PORTRAIT,
439 wallpapers.get(0).getConfiguration().orientation);
Riddle Hsu6393ad12020-03-02 23:56:32 +0800440
Riddle Hsucbc5d272020-04-24 23:26:46 +0800441 mController.cleanupAnimation(REORDER_MOVE_TO_TOP);
442 // The transform state should keep because we expect to listen the signal from the
443 // transition executed by moving the task to front.
444 assertTrue(homeActivity.hasFixedRotationTransform());
Riddle Hsu08bc4ed2020-05-26 18:32:18 +0800445 assertTrue(mDefaultDisplay.isFixedRotationLaunchingApp(homeActivity));
Riddle Hsucbc5d272020-04-24 23:26:46 +0800446
447 mDefaultDisplay.mFixedRotationTransitionListener.onAppTransitionFinishedLocked(
448 homeActivity.token);
Riddle Hsu6393ad12020-03-02 23:56:32 +0800449 // Wallpaper's transform state should be cleared with home.
Riddle Hsucbc5d272020-04-24 23:26:46 +0800450 assertFalse(homeActivity.hasFixedRotationTransform());
Riddle Hsu6393ad12020-03-02 23:56:32 +0800451 assertFalse(wallpaperWindowToken.hasFixedRotationTransform());
452 }
453
454 private ActivityRecord createHomeActivity() {
455 final ActivityRecord homeActivity = new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
456 .setStack(mRootHomeTask)
457 .setCreateTask(true)
458 .build();
459 // Avoid {@link RecentsAnimationController.TaskAnimationAdapter#createRemoteAnimationTarget}
460 // returning null when calling {@link RecentsAnimationController#createAppAnimations}.
461 homeActivity.setVisibility(true);
462 return homeActivity;
Vadim Caen2a9ccc92020-01-29 12:21:41 +0100463 }
464
Riddle Hsu70a920c2020-05-05 17:20:32 +0800465 private static void initializeRecentsAnimationController(RecentsAnimationController controller,
466 ActivityRecord activity) {
467 controller.initialize(activity.getActivityType(), new SparseBooleanArray(), activity);
468 }
469
Winson Chungda876c92018-04-05 18:31:06 -0700470 private static void verifyNoMoreInteractionsExceptAsBinder(IInterface binder) {
471 verify(binder, atLeast(0)).asBinder();
472 verifyNoMoreInteractions(binder);
473 }
474}