blob: d65b084ca8c1cc325310580ae79c4ee44e22cfc0 [file] [log] [blame]
Andrii Kuliand2765632016-12-12 22:26:34 -08001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070014 * limitations under the License.
Andrii Kuliand2765632016-12-12 22:26:34 -080015 */
16
17package com.android.server.wm;
18
Wale Ogunwaleea5e87f2020-02-10 08:33:05 -080019import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
Bryce Lee61fbcbc2017-03-10 14:14:03 -080020import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
21import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
22
Wale Ogunwaleea5e87f2020-02-10 08:33:05 -080023import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
Riddle Hsu6619acb2019-02-20 19:12:57 +080024import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
25import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Wale Ogunwalea733c792019-10-16 21:31:15 -070026import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
27import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
lumark9bca6b42019-10-17 18:35:22 +080028import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
29import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
Riddle Hsu6619acb2019-02-20 19:12:57 +080030
Andrii Kuliand2765632016-12-12 22:26:34 -080031import static org.junit.Assert.assertEquals;
Yunfan Chen279f5582018-12-12 15:24:50 -080032import static org.junit.Assert.assertNotEquals;
33import static org.junit.Assert.assertNotNull;
Andrii Kuliand2765632016-12-12 22:26:34 -080034import static org.junit.Assert.assertNull;
Wale Ogunwalea733c792019-10-16 21:31:15 -070035import static org.mockito.ArgumentMatchers.any;
chaviw9177c772020-03-24 11:35:22 -070036import static org.mockito.ArgumentMatchers.anyInt;
37import static org.mockito.ArgumentMatchers.eq;
lumarkbde15132019-12-18 22:29:43 +080038import static org.mockito.Mockito.clearInvocations;
Brett Chabota26eda92018-07-23 13:08:30 -070039
Wale Ogunwaleea5e87f2020-02-10 08:33:05 -080040import android.app.WindowConfiguration;
Yunfan Chen279f5582018-12-12 15:24:50 -080041import android.graphics.Rect;
Brett Chabota26eda92018-07-23 13:08:30 -070042import android.platform.test.annotations.Presubmit;
43
44import androidx.test.filters.SmallTest;
Brett Chabota26eda92018-07-23 13:08:30 -070045
46import org.junit.Test;
Riddle Hsu73f53572019-09-23 23:13:01 +080047import org.junit.runner.RunWith;
Andrii Kuliand2765632016-12-12 22:26:34 -080048
49/**
Louis Changdc077272019-11-12 16:52:56 +080050 * Tests for the {@link ActivityStack} class.
Andrii Kuliand2765632016-12-12 22:26:34 -080051 *
52 * Build/Install/Run:
Riddle Hsu73f53572019-09-23 23:13:01 +080053 * atest WmTests:TaskStackTests
Andrii Kuliand2765632016-12-12 22:26:34 -080054 */
55@SmallTest
56@Presubmit
Riddle Hsu73f53572019-09-23 23:13:01 +080057@RunWith(WindowTestRunner.class)
Andrii Kuliand2765632016-12-12 22:26:34 -080058public class TaskStackTests extends WindowTestsBase {
59
60 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070061 public void testStackPositionChildAt() {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -070062 final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
Andrii Kuliand2765632016-12-12 22:26:34 -080063 final Task task1 = createTaskInStack(stack, 0 /* userId */);
64 final Task task2 = createTaskInStack(stack, 1 /* userId */);
65
66 // Current user task should be moved to top.
Louis Changcdec0802019-11-11 11:45:07 +080067 stack.positionChildAt(WindowContainer.POSITION_TOP, task1, false /* includingParents */);
Andrii Kuliand2765632016-12-12 22:26:34 -080068 assertEquals(stack.mChildren.get(0), task2);
69 assertEquals(stack.mChildren.get(1), task1);
70
71 // Non-current user won't be moved to top.
Louis Changcdec0802019-11-11 11:45:07 +080072 stack.positionChildAt(WindowContainer.POSITION_TOP, task2, false /* includingParents */);
Andrii Kuliand2765632016-12-12 22:26:34 -080073 assertEquals(stack.mChildren.get(0), task2);
74 assertEquals(stack.mChildren.get(1), task1);
Louis Changedbda502020-04-27 15:51:42 +080075
76 // Non-leaf task should be moved to top regardless of the user id.
77 createTaskInStack((ActivityStack) task2, 0 /* userId */);
78 createTaskInStack((ActivityStack) task2, 1 /* userId */);
79 stack.positionChildAt(WindowContainer.POSITION_TOP, task2, false /* includingParents */);
80 assertEquals(stack.mChildren.get(0), task1);
81 assertEquals(stack.mChildren.get(1), task2);
Andrii Kuliand2765632016-12-12 22:26:34 -080082 }
Andrii Kulian45a61fe2017-01-05 16:53:19 -080083
84 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -070085 public void testClosingAppDifferentStackOrientation() {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -070086 final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
Bryce Lee61fbcbc2017-03-10 14:14:03 -080087 final Task task1 = createTaskInStack(stack, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -070088 ActivityRecord activity1 =
89 WindowTestUtils.createTestActivityRecord(mDisplayContent);
90 task1.addChild(activity1, 0);
91 activity1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
Bryce Lee61fbcbc2017-03-10 14:14:03 -080092
93 final Task task2 = createTaskInStack(stack, 1 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -070094 ActivityRecord activity2=
95 WindowTestUtils.createTestActivityRecord(mDisplayContent);
96 task2.addChild(activity2, 0);
97 activity2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
Bryce Lee61fbcbc2017-03-10 14:14:03 -080098
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -070099 assertEquals(SCREEN_ORIENTATION_PORTRAIT, stack.getOrientation());
Garfield Tane8d84ab2019-10-11 09:49:40 -0700100 mDisplayContent.mClosingApps.add(activity2);
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700101 assertEquals(SCREEN_ORIENTATION_LANDSCAPE, stack.getOrientation());
Bryce Lee61fbcbc2017-03-10 14:14:03 -0800102 }
103
104 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700105 public void testMoveTaskToBackDifferentStackOrientation() {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700106 final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
Bryce Lee61fbcbc2017-03-10 14:14:03 -0800107 final Task task1 = createTaskInStack(stack, 0 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700108 ActivityRecord activity1 =
109 WindowTestUtils.createTestActivityRecord(mDisplayContent);
110 task1.addChild(activity1, 0);
111 activity1.setOrientation(SCREEN_ORIENTATION_LANDSCAPE);
Bryce Lee61fbcbc2017-03-10 14:14:03 -0800112
113 final Task task2 = createTaskInStack(stack, 1 /* userId */);
Garfield Tane8d84ab2019-10-11 09:49:40 -0700114 ActivityRecord activity2 =
115 WindowTestUtils.createTestActivityRecord(mDisplayContent);
116 task2.addChild(activity2, 0);
117 activity2.setOrientation(SCREEN_ORIENTATION_PORTRAIT);
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700118 assertEquals(SCREEN_ORIENTATION_PORTRAIT, stack.getOrientation());
Bryce Lee61fbcbc2017-03-10 14:14:03 -0800119 }
120
121 @Test
Tadashi G. Takaokab6e148c2018-11-03 02:59:06 -0700122 public void testStackRemoveImmediately() {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700123 final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
Andrii Kulian45a61fe2017-01-05 16:53:19 -0800124 final Task task = createTaskInStack(stack, 0 /* userId */);
Wale Ogunwale0b3d2922019-12-30 08:55:07 -0800125 assertEquals(stack, task.getStack());
Andrii Kulian45a61fe2017-01-05 16:53:19 -0800126
127 // Remove stack and check if its child is also removed.
128 stack.removeImmediately();
129 assertNull(stack.getDisplayContent());
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800130 assertNull(task.getParent());
Andrii Kulian45a61fe2017-01-05 16:53:19 -0800131 }
Yunfan Chen279f5582018-12-12 15:24:50 -0800132
133 @Test
134 public void testRemoveContainer() {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700135 final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
Wale Ogunwalea733c792019-10-16 21:31:15 -0700136 final Task task = createTaskInStack(stack, 0 /* userId */);
Yunfan Chen279f5582018-12-12 15:24:50 -0800137
138 assertNotNull(stack);
139 assertNotNull(task);
140 stack.removeIfPossible();
141 // Assert that the container was removed.
142 assertNull(stack.getParent());
143 assertEquals(0, stack.getChildCount());
144 assertNull(stack.getDisplayContent());
145 assertNull(task.getDisplayContent());
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800146 assertNull(task.getParent());
Yunfan Chen279f5582018-12-12 15:24:50 -0800147 }
148
149 @Test
150 public void testRemoveContainer_deferRemoval() {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700151 final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
Wale Ogunwalea733c792019-10-16 21:31:15 -0700152 final Task task = createTaskInStack(stack, 0 /* userId */);
Yunfan Chen279f5582018-12-12 15:24:50 -0800153
154 // Stack removal is deferred if one of its child is animating.
Wale Ogunwale8f93b642019-12-26 12:10:52 -0800155 doReturn(true).when(stack).hasWindowsAlive();
chaviw9177c772020-03-24 11:35:22 -0700156 doReturn(true).when(task).isAnimating(eq(TRANSITION | CHILDREN), anyInt());
Yunfan Chen279f5582018-12-12 15:24:50 -0800157
158 stack.removeIfPossible();
159 // For the case of deferred removal the task controller will still be connected to the its
160 // container until the stack window container is removed.
161 assertNotNull(stack.getParent());
162 assertNotEquals(0, stack.getChildCount());
163 assertNotNull(task);
164
165 stack.removeImmediately();
166 // After removing, the task will be isolated.
167 assertNull(task.getParent());
168 assertEquals(0, task.getChildCount());
Yunfan Chen279f5582018-12-12 15:24:50 -0800169 }
170
171 @Test
172 public void testReparent() {
173 // Create first stack on primary display.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700174 final ActivityStack stack1 = createTaskStackOnDisplay(mDisplayContent);
Wale Ogunwalea733c792019-10-16 21:31:15 -0700175 final Task task1 = createTaskInStack(stack1, 0 /* userId */);
Yunfan Chen279f5582018-12-12 15:24:50 -0800176
177 // Create second display and put second stack on it.
178 final DisplayContent dc = createNewDisplay();
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700179 final ActivityStack stack2 = createTaskStackOnDisplay(dc);
Yunfan Chen279f5582018-12-12 15:24:50 -0800180
181 // Reparent
lumarkbde15132019-12-18 22:29:43 +0800182 clearInvocations(task1); // reset the number of onDisplayChanged for task.
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700183 stack1.reparent(dc.getDefaultTaskDisplayArea(), true /* onTop */);
Yunfan Chen279f5582018-12-12 15:24:50 -0800184 assertEquals(dc, stack1.getDisplayContent());
185 final int stack1PositionInParent = stack1.getParent().mChildren.indexOf(stack1);
186 final int stack2PositionInParent = stack1.getParent().mChildren.indexOf(stack2);
187 assertEquals(stack1PositionInParent, stack2PositionInParent + 1);
Wale Ogunwalea733c792019-10-16 21:31:15 -0700188 verify(task1, times(1)).onDisplayChanged(any());
Yunfan Chen279f5582018-12-12 15:24:50 -0800189 }
Riddle Hsu6619acb2019-02-20 19:12:57 +0800190
191 @Test
192 public void testStackOutset() {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700193 final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
Riddle Hsu6619acb2019-02-20 19:12:57 +0800194 final int stackOutset = 10;
Riddle Hsu73f53572019-09-23 23:13:01 +0800195 spyOn(stack);
Louis Chang2570e332020-04-10 11:58:49 +0800196 doReturn(stackOutset).when(stack).getTaskOutset();
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700197 doReturn(true).when(stack).inMultiWindowMode();
Riddle Hsu6619acb2019-02-20 19:12:57 +0800198
Wale Ogunwaleea5e87f2020-02-10 08:33:05 -0800199 // Mock the resolved override windowing mode to non-fullscreen
200 final WindowConfiguration windowConfiguration =
201 stack.getResolvedOverrideConfiguration().windowConfiguration;
202 spyOn(windowConfiguration);
203 doReturn(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
204 .when(windowConfiguration).getWindowingMode();
205
206 // Prevent adjust task dimensions
Riddle Hsudd49c632020-04-30 22:39:51 +0800207 doNothing().when(stack).adjustForMinimalTaskDimensions(any(), any(), any());
Wale Ogunwaleea5e87f2020-02-10 08:33:05 -0800208
Riddle Hsu6619acb2019-02-20 19:12:57 +0800209 final Rect stackBounds = new Rect(200, 200, 800, 1000);
210 // Update surface position and size by the given bounds.
211 stack.setBounds(stackBounds);
212
213 assertEquals(stackBounds.width() + 2 * stackOutset, stack.getLastSurfaceSize().x);
214 assertEquals(stackBounds.height() + 2 * stackOutset, stack.getLastSurfaceSize().y);
215 assertEquals(stackBounds.left - stackOutset, stack.getLastSurfacePosition().x);
216 assertEquals(stackBounds.top - stackOutset, stack.getLastSurfacePosition().y);
217 }
Evan Rosky660b1752020-04-15 18:07:15 -0700218
219 @Test
220 public void testActivityAndTaskGetsProperType() {
221 final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
222 final Task task1 = createTaskInStack(stack, 0 /* userId */);
223 ActivityRecord activity1 = WindowTestUtils.createTestActivityRecord(mDisplayContent);
224
225 // First activity should become standard
226 task1.addChild(activity1, 0);
227 assertEquals(WindowConfiguration.ACTIVITY_TYPE_STANDARD, activity1.getActivityType());
228 assertEquals(WindowConfiguration.ACTIVITY_TYPE_STANDARD, task1.getActivityType());
229
230 // Second activity should also become standard
231 ActivityRecord activity2 = WindowTestUtils.createTestActivityRecord(mDisplayContent);
232 task1.addChild(activity2, WindowContainer.POSITION_TOP);
233 assertEquals(WindowConfiguration.ACTIVITY_TYPE_STANDARD, activity2.getActivityType());
234 assertEquals(WindowConfiguration.ACTIVITY_TYPE_STANDARD, task1.getActivityType());
235 }
Andrii Kuliand2765632016-12-12 22:26:34 -0800236}