blob: de2bba275171353cda5b134f510839ade3a2ad47 [file] [log] [blame]
Riddle Hsu75016992018-09-20 20:37:14 +08001/*
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
Wale Ogunwale59507092018-10-29 09:00:30 -070014 * limitations under the License
Riddle Hsu75016992018-09-20 20:37:14 +080015 */
16
Wale Ogunwale59507092018-10-29 09:00:30 -070017package com.android.server.wm;
Riddle Hsu75016992018-09-20 20:37:14 +080018
Riddle Hsu402b4402018-11-06 17:23:15 +080019import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
Riddle Hsu75016992018-09-20 20:37:14 +080020import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
Evan Roskyc5abbd82018-10-05 16:02:19 -070021import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Riddle Hsu75016992018-09-20 20:37:14 +080022import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
23import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
24import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
Riddle Hsue10cea52018-10-16 23:33:23 +080025import static android.content.pm.ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
Riddle Hsu75016992018-09-20 20:37:14 +080026
Riddle Hsu73f53572019-09-23 23:13:01 +080027import static com.android.dx.mockito.inline.extended.ExtendedMockito.clearInvocations;
Tadashi G. Takaokaa7a66952018-11-16 15:04:21 +090028import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
29import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
Tadashi G. Takaokaa7a66952018-11-16 15:04:21 +090030import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
Wale Ogunwale59507092018-10-29 09:00:30 -070031import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
Riddle Hsu75016992018-09-20 20:37:14 +080032
Riddle Hsubbb63c22018-10-03 12:28:29 +080033import static org.junit.Assert.assertEquals;
Evan Roskyc5abbd82018-10-05 16:02:19 -070034import static org.junit.Assert.assertFalse;
Riddle Hsue10cea52018-10-16 23:33:23 +080035import static org.junit.Assert.assertNull;
Riddle Hsu75016992018-09-20 20:37:14 +080036import static org.junit.Assert.assertTrue;
Riddle Hsu402b4402018-11-06 17:23:15 +080037import static org.mockito.ArgumentMatchers.any;
Louis Changf787e532019-01-15 12:46:49 +080038import static org.mockito.ArgumentMatchers.anyBoolean;
39import static org.mockito.ArgumentMatchers.eq;
40import static org.mockito.Mockito.doAnswer;
Riddle Hsu75016992018-09-20 20:37:14 +080041
42import android.platform.test.annotations.Presubmit;
Wale Ogunwale38f72bd2018-11-20 02:53:49 +000043
Riddle Hsu75016992018-09-20 20:37:14 +080044import androidx.test.filters.SmallTest;
Riddle Hsu75016992018-09-20 20:37:14 +080045
Riddle Hsu75016992018-09-20 20:37:14 +080046import org.junit.Test;
Riddle Hsu73f53572019-09-23 23:13:01 +080047import org.junit.runner.RunWith;
Riddle Hsu75016992018-09-20 20:37:14 +080048
49/**
50 * Tests for the {@link ActivityDisplay} class.
51 *
52 * Build/Install/Run:
53 * atest WmTests:ActivityDisplayTests
54 */
55@SmallTest
56@Presubmit
Riddle Hsu73f53572019-09-23 23:13:01 +080057@RunWith(WindowTestRunner.class)
Riddle Hsu75016992018-09-20 20:37:14 +080058public class ActivityDisplayTests extends ActivityTestsBase {
59
Riddle Hsubbb63c22018-10-03 12:28:29 +080060 @Test
61 public void testLastFocusedStackIsUpdatedWhenMovingStack() {
62 // Create a stack at bottom.
Wale Ogunwaled32da472018-11-16 07:19:28 -080063 final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
64 final ActivityStack stack =
65 new StackBuilder(mRootActivityContainer).setOnTop(!ON_TOP).build();
Riddle Hsubbb63c22018-10-03 12:28:29 +080066 final ActivityStack prevFocusedStack = display.getFocusedStack();
67
68 stack.moveToFront("moveStackToFront");
69 // After moving the stack to front, the previous focused should be the last focused.
70 assertTrue(stack.isFocusedStackOnDisplay());
71 assertEquals(prevFocusedStack, display.getLastFocusedStack());
72
73 stack.moveToBack("moveStackToBack", null /* task */);
74 // After moving the stack to back, the stack should be the last focused.
75 assertEquals(stack, display.getLastFocusedStack());
76 }
77
Riddle Hsu75016992018-09-20 20:37:14 +080078 /**
79 * This test simulates the picture-in-picture menu activity launches an activity to fullscreen
80 * stack. The fullscreen stack should be the top focused for resuming correctly.
81 */
82 @Test
83 public void testFullscreenStackCanBeFocusedWhenFocusablePinnedStackExists() {
84 // Create a pinned stack and move to front.
Wale Ogunwaled32da472018-11-16 07:19:28 -080085 final ActivityStack pinnedStack = mRootActivityContainer.getDefaultDisplay().createStack(
Riddle Hsu75016992018-09-20 20:37:14 +080086 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, ON_TOP);
Louis Changcdec0802019-11-11 11:45:07 +080087 final Task pinnedTask = new TaskBuilder(mService.mStackSupervisor)
Riddle Hsu75016992018-09-20 20:37:14 +080088 .setStack(pinnedStack).build();
89 new ActivityBuilder(mService).setActivityFlags(FLAG_ALWAYS_FOCUSABLE)
90 .setTask(pinnedTask).build();
91 pinnedStack.moveToFront("movePinnedStackToFront");
92
93 // The focused stack should be the pinned stack.
94 assertTrue(pinnedStack.isFocusedStackOnDisplay());
95
96 // Create a fullscreen stack and move to front.
97 final ActivityStack fullscreenStack = createFullscreenStackWithSimpleActivityAt(
Wale Ogunwaled32da472018-11-16 07:19:28 -080098 mRootActivityContainer.getDefaultDisplay());
Riddle Hsu75016992018-09-20 20:37:14 +080099 fullscreenStack.moveToFront("moveFullscreenStackToFront");
100
101 // The focused stack should be the fullscreen stack.
102 assertTrue(fullscreenStack.isFocusedStackOnDisplay());
103 }
104
105 /**
106 * Test {@link ActivityDisplay#mPreferredTopFocusableStack} will be cleared when the stack is
107 * removed or moved to back, and the focused stack will be according to z-order.
108 */
109 @Test
110 public void testStackShouldNotBeFocusedAfterMovingToBackOrRemoving() {
111 // Create a display which only contains 2 stacks.
112 final ActivityDisplay display = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
113 final ActivityStack stack1 = createFullscreenStackWithSimpleActivityAt(display);
114 final ActivityStack stack2 = createFullscreenStackWithSimpleActivityAt(display);
115
116 // Put stack1 and stack2 on top.
117 stack1.moveToFront("moveStack1ToFront");
118 stack2.moveToFront("moveStack2ToFront");
119 assertTrue(stack2.isFocusedStackOnDisplay());
120
121 // Stack1 should be focused after moving stack2 to back.
122 stack2.moveToBack("moveStack2ToBack", null /* task */);
123 assertTrue(stack1.isFocusedStackOnDisplay());
124
125 // Stack2 should be focused after removing stack1.
Louis Chang2453d062019-11-19 22:30:48 +0800126 display.removeStack(stack1);
Riddle Hsu75016992018-09-20 20:37:14 +0800127 assertTrue(stack2.isFocusedStackOnDisplay());
128 }
129
Riddle Hsu402b4402018-11-06 17:23:15 +0800130 /**
131 * Verifies {@link ActivityDisplay#remove} should not resume home stack on the removing display.
132 */
133 @Test
134 public void testNotResumeHomeStackOnRemovingDisplay() {
135 // Create a display which supports system decoration and allows reparenting stacks to
136 // another display when the display is removed.
Evan Rosky4a51dbc02019-09-11 17:28:07 -0700137 final ActivityDisplay display = new TestActivityDisplay.Builder(
138 mService, 1000, 1500).setSystemDecorations(true).build();
Riddle Hsu402b4402018-11-06 17:23:15 +0800139 doReturn(false).when(display).shouldDestroyContentOnRemove();
Riddle Hsu402b4402018-11-06 17:23:15 +0800140
141 // Put home stack on the display.
Riddle Hsu73f53572019-09-23 23:13:01 +0800142 final ActivityStack homeStack = new StackBuilder(mRootActivityContainer)
143 .setDisplay(display).setActivityType(ACTIVITY_TYPE_HOME).build();
Riddle Hsu402b4402018-11-06 17:23:15 +0800144
145 // Put a finishing standard activity which will be reparented.
146 final ActivityStack stack = createFullscreenStackWithSimpleActivityAt(display);
147 stack.topRunningActivityLocked().makeFinishingLocked();
148
Riddle Hsu73f53572019-09-23 23:13:01 +0800149 clearInvocations(homeStack);
Riddle Hsu402b4402018-11-06 17:23:15 +0800150 display.remove();
151
152 // The removed display should have no focused stack and its home stack should never resume.
153 assertNull(display.getFocusedStack());
Riddle Hsu73f53572019-09-23 23:13:01 +0800154 verify(homeStack, never()).resumeTopActivityUncheckedLocked(any(), any());
Riddle Hsu402b4402018-11-06 17:23:15 +0800155 }
156
Riddle Hsu75016992018-09-20 20:37:14 +0800157 private ActivityStack createFullscreenStackWithSimpleActivityAt(ActivityDisplay display) {
158 final ActivityStack fullscreenStack = display.createStack(
159 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, ON_TOP);
Louis Changcdec0802019-11-11 11:45:07 +0800160 final Task fullscreenTask = new TaskBuilder(mService.mStackSupervisor)
Riddle Hsu75016992018-09-20 20:37:14 +0800161 .setStack(fullscreenStack).build();
162 new ActivityBuilder(mService).setTask(fullscreenTask).build();
163 return fullscreenStack;
164 }
Riddle Hsue10cea52018-10-16 23:33:23 +0800165
166 /**
167 * Verifies the correct activity is returned when querying the top running activity.
168 */
169 @Test
170 public void testTopRunningActivity() {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800171 final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
Riddle Hsue10cea52018-10-16 23:33:23 +0800172 final KeyguardController keyguard = mSupervisor.getKeyguardController();
Wale Ogunwaled32da472018-11-16 07:19:28 -0800173 final ActivityStack stack = new StackBuilder(mRootActivityContainer).build();
Wale Ogunwale21e06482019-11-18 05:14:15 -0800174 final ActivityRecord activity = stack.getTopNonFinishingActivity();
Louis Changf2835df2018-10-17 15:14:45 +0800175
176 // Create empty stack on top.
177 final ActivityStack emptyStack =
Wale Ogunwaled32da472018-11-16 07:19:28 -0800178 new StackBuilder(mRootActivityContainer).setCreateActivity(false).build();
Riddle Hsue10cea52018-10-16 23:33:23 +0800179
180 // Make sure the top running activity is not affected when keyguard is not locked.
181 assertTopRunningActivity(activity, display);
182
183 // Check to make sure activity not reported when it cannot show on lock and lock is on.
184 doReturn(true).when(keyguard).isKeyguardLocked();
185 assertEquals(activity, display.topRunningActivity());
186 assertNull(display.topRunningActivity(true /* considerKeyguardState */));
187
Louis Changf2835df2018-10-17 15:14:45 +0800188 // Move stack with activity to top.
189 stack.moveToFront("testStackToFront");
Riddle Hsue10cea52018-10-16 23:33:23 +0800190 assertEquals(stack, display.getFocusedStack());
191 assertEquals(activity, display.topRunningActivity());
192 assertNull(display.topRunningActivity(true /* considerKeyguardState */));
193
194 // Add activity that should be shown on the keyguard.
195 final ActivityRecord showWhenLockedActivity = new ActivityBuilder(mService)
196 .setCreateTask(true)
197 .setStack(stack)
198 .setActivityFlags(FLAG_SHOW_WHEN_LOCKED)
199 .build();
200
201 // Ensure the show when locked activity is returned.
202 assertTopRunningActivity(showWhenLockedActivity, display);
203
Louis Changf2835df2018-10-17 15:14:45 +0800204 // Move empty stack to front. The running activity in focusable stack which below the
205 // empty stack should be returned.
206 emptyStack.moveToFront("emptyStackToFront");
207 assertEquals(stack, display.getFocusedStack());
Riddle Hsue10cea52018-10-16 23:33:23 +0800208 assertTopRunningActivity(showWhenLockedActivity, display);
209 }
210
211 private static void assertTopRunningActivity(ActivityRecord top, ActivityDisplay display) {
212 assertEquals(top, display.topRunningActivity());
213 assertEquals(top, display.topRunningActivity(true /* considerKeyguardState */));
214 }
Evan Roskyc5abbd82018-10-05 16:02:19 -0700215
216 /**
217 * This test enforces that alwaysOnTop stack is placed at proper position.
218 */
219 @Test
220 public void testAlwaysOnTopStackLocation() {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800221 final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
Evan Roskyc5abbd82018-10-05 16:02:19 -0700222 final ActivityStack alwaysOnTopStack = display.createStack(WINDOWING_MODE_FREEFORM,
223 ACTIVITY_TYPE_STANDARD, true /* onTop */);
224 final ActivityRecord activity = new ActivityBuilder(mService).setCreateTask(true)
225 .setStack(alwaysOnTopStack).build();
226 alwaysOnTopStack.setAlwaysOnTop(true);
Louis Chang2453d062019-11-19 22:30:48 +0800227 display.positionStackAtTop(alwaysOnTopStack, false /* includingParents */);
Evan Roskyc5abbd82018-10-05 16:02:19 -0700228 assertTrue(alwaysOnTopStack.isAlwaysOnTop());
229 // Ensure always on top state is synced to the children of the stack.
Wale Ogunwale21e06482019-11-18 05:14:15 -0800230 assertTrue(alwaysOnTopStack.getTopNonFinishingActivity().isAlwaysOnTop());
Evan Roskyc5abbd82018-10-05 16:02:19 -0700231 assertEquals(alwaysOnTopStack, display.getTopStack());
232
233 final ActivityStack pinnedStack = display.createStack(
234 WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD, true /* onTop */);
235 assertEquals(pinnedStack, display.getPinnedStack());
236 assertEquals(pinnedStack, display.getTopStack());
237
238 final ActivityStack anotherAlwaysOnTopStack = display.createStack(
239 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
240 anotherAlwaysOnTopStack.setAlwaysOnTop(true);
Louis Chang2453d062019-11-19 22:30:48 +0800241 display.positionStackAtTop(anotherAlwaysOnTopStack, false /* includingParents */);
Evan Roskyc5abbd82018-10-05 16:02:19 -0700242 assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
Louis Chang2453d062019-11-19 22:30:48 +0800243 int topPosition = display.getStackCount() - 1;
Evan Roskyc5abbd82018-10-05 16:02:19 -0700244 // Ensure the new alwaysOnTop stack is put below the pinned stack, but on top of the
245 // existing alwaysOnTop stack.
Louis Chang2453d062019-11-19 22:30:48 +0800246 assertEquals(anotherAlwaysOnTopStack, display.getStackAt(topPosition - 1));
Evan Roskyc5abbd82018-10-05 16:02:19 -0700247
248 final ActivityStack nonAlwaysOnTopStack = display.createStack(
249 WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, true /* onTop */);
250 assertEquals(display, nonAlwaysOnTopStack.getDisplay());
Louis Chang2453d062019-11-19 22:30:48 +0800251 topPosition = display.getStackCount() - 1;
Evan Roskyc5abbd82018-10-05 16:02:19 -0700252 // Ensure the non-alwaysOnTop stack is put below the three alwaysOnTop stacks, but above the
253 // existing other non-alwaysOnTop stacks.
Louis Chang2453d062019-11-19 22:30:48 +0800254 assertEquals(nonAlwaysOnTopStack, display.getStackAt(topPosition - 3));
Evan Roskyc5abbd82018-10-05 16:02:19 -0700255
256 anotherAlwaysOnTopStack.setAlwaysOnTop(false);
Louis Chang2453d062019-11-19 22:30:48 +0800257 display.positionStackAtTop(anotherAlwaysOnTopStack, false /* includingParents */);
Evan Roskyc5abbd82018-10-05 16:02:19 -0700258 assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
259 // Ensure, when always on top is turned off for a stack, the stack is put just below all
260 // other always on top stacks.
Louis Chang2453d062019-11-19 22:30:48 +0800261 assertEquals(anotherAlwaysOnTopStack, display.getStackAt(topPosition - 2));
Evan Roskyc5abbd82018-10-05 16:02:19 -0700262 anotherAlwaysOnTopStack.setAlwaysOnTop(true);
263
264 // Ensure always on top state changes properly when windowing mode changes.
265 anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
266 assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
Louis Chang2453d062019-11-19 22:30:48 +0800267 assertEquals(anotherAlwaysOnTopStack, display.getStackAt(topPosition - 2));
Evan Roskyc5abbd82018-10-05 16:02:19 -0700268 anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FREEFORM);
269 assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
Louis Chang2453d062019-11-19 22:30:48 +0800270 assertEquals(anotherAlwaysOnTopStack, display.getStackAt(topPosition - 1));
Evan Roskyc5abbd82018-10-05 16:02:19 -0700271 }
Louis Changf787e532019-01-15 12:46:49 +0800272
273 @Test
274 public void testRemoveStackInWindowingModes() {
275 removeStackTests(() -> mRootActivityContainer.removeStacksInWindowingModes(
276 WINDOWING_MODE_FULLSCREEN));
277 }
278
279 @Test
280 public void testRemoveStackWithActivityTypes() {
281 removeStackTests(
282 () -> mRootActivityContainer.removeStacksWithActivityTypes(ACTIVITY_TYPE_STANDARD));
283 }
284
285 private void removeStackTests(Runnable runnable) {
286 final ActivityDisplay display = mRootActivityContainer.getDefaultDisplay();
287 final ActivityStack stack1 = display.createStack(WINDOWING_MODE_FULLSCREEN,
288 ACTIVITY_TYPE_STANDARD, ON_TOP);
289 final ActivityStack stack2 = display.createStack(WINDOWING_MODE_FULLSCREEN,
290 ACTIVITY_TYPE_STANDARD, ON_TOP);
291 final ActivityStack stack3 = display.createStack(WINDOWING_MODE_FULLSCREEN,
292 ACTIVITY_TYPE_STANDARD, ON_TOP);
293 final ActivityStack stack4 = display.createStack(WINDOWING_MODE_FULLSCREEN,
294 ACTIVITY_TYPE_STANDARD, ON_TOP);
Louis Changcdec0802019-11-11 11:45:07 +0800295 final Task task1 = new TaskBuilder(mService.mStackSupervisor).setStack(stack1).build();
296 final Task task2 = new TaskBuilder(mService.mStackSupervisor).setStack(stack2).build();
297 final Task task3 = new TaskBuilder(mService.mStackSupervisor).setStack(stack3).build();
298 final Task task4 = new TaskBuilder(mService.mStackSupervisor).setStack(stack4).build();
Louis Changf787e532019-01-15 12:46:49 +0800299
300 // Reordering stacks while removing stacks.
301 doAnswer(invocation -> {
Louis Chang2453d062019-11-19 22:30:48 +0800302 display.positionStackAtTop(stack3, false);
Louis Changf787e532019-01-15 12:46:49 +0800303 return true;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700304 }).when(mSupervisor).removeTaskByIdLocked(eq(task4.mTaskId), anyBoolean(), anyBoolean(),
Louis Changf787e532019-01-15 12:46:49 +0800305 any());
306
307 // Removing stacks from the display while removing stacks.
308 doAnswer(invocation -> {
Louis Chang2453d062019-11-19 22:30:48 +0800309 display.removeStack(stack2);
Louis Changf787e532019-01-15 12:46:49 +0800310 return true;
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700311 }).when(mSupervisor).removeTaskByIdLocked(eq(task2.mTaskId), anyBoolean(), anyBoolean(),
Louis Changf787e532019-01-15 12:46:49 +0800312 any());
313
314 runnable.run();
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700315 verify(mSupervisor).removeTaskByIdLocked(eq(task4.mTaskId), anyBoolean(), anyBoolean(),
Louis Changf787e532019-01-15 12:46:49 +0800316 any());
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700317 verify(mSupervisor).removeTaskByIdLocked(eq(task3.mTaskId), anyBoolean(), anyBoolean(),
Louis Changf787e532019-01-15 12:46:49 +0800318 any());
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700319 verify(mSupervisor).removeTaskByIdLocked(eq(task2.mTaskId), anyBoolean(), anyBoolean(),
Louis Changf787e532019-01-15 12:46:49 +0800320 any());
Wale Ogunwale4e79a1c2019-10-05 20:52:40 -0700321 verify(mSupervisor).removeTaskByIdLocked(eq(task1.mTaskId), anyBoolean(), anyBoolean(),
Louis Changf787e532019-01-15 12:46:49 +0800322 any());
323 }
Riddle Hsu75016992018-09-20 20:37:14 +0800324}