blob: a96f40143e0f6938eb0022b334d88a6c99fd59ce [file] [log] [blame]
Robert Carr8a2f9132019-11-11 15:03:15 -08001/*
Evan Rosky0037e5f2019-11-05 10:26:24 -08002 * Copyright (C) 2020 The Android Open Source Project
Robert Carr8a2f9132019-11-11 15:03:15 -08003 *
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
17package com.android.server.wm;
18
Evan Rosky0037e5f2019-11-05 10:26:24 -080019import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
20import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
21import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
22import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Robert Carr8a2f9132019-11-11 15:03:15 -080023import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
Robert Carr00c0dbe2020-01-24 15:30:24 -080024import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
Evan Rosky0037e5f2019-11-05 10:26:24 -080025import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
26import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
27import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
28import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Robert Carre10ee3d2019-11-11 15:03:15 -080029import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
Robert Carr8a2f9132019-11-11 15:03:15 -080030
Wale Ogunwale0d465192020-01-23 19:14:44 -080031import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000032import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
Robert Carr8a2f9132019-11-11 15:03:15 -080033import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
Evan Roskya8fde152020-01-07 19:09:13 -080034import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
Rob Carr25376512020-03-09 15:23:19 -070035import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000036import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Robert Carr8a2f9132019-11-11 15:03:15 -080037import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
38import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
Robert Carr8a2f9132019-11-11 15:03:15 -080039import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
40
Evan Rosky0037e5f2019-11-05 10:26:24 -080041import static org.junit.Assert.assertEquals;
Jorim Jaggi2a3002a2020-02-17 15:57:34 +000042import static org.junit.Assert.assertFalse;
Evan Rosky05ec8862020-02-28 19:37:04 -080043import static org.junit.Assert.assertNotEquals;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000044import static org.junit.Assert.assertNotNull;
Evan Rosky0037e5f2019-11-05 10:26:24 -080045import static org.junit.Assert.assertTrue;
46import static org.mockito.ArgumentMatchers.any;
Robert Carrf6690d12020-02-04 14:16:21 -080047import static org.mockito.ArgumentMatchers.anyBoolean;
Robert Carre10ee3d2019-11-11 15:03:15 -080048import static org.mockito.ArgumentMatchers.anyInt;
Evan Rosky0037e5f2019-11-05 10:26:24 -080049
50import android.app.ActivityManager.RunningTaskInfo;
51import android.app.ActivityManager.StackInfo;
Robert Carrf6690d12020-02-04 14:16:21 -080052import android.app.PictureInPictureParams;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000053import android.content.pm.ActivityInfo;
Evan Rosky0037e5f2019-11-05 10:26:24 -080054import android.content.res.Configuration;
Robert Carr8a2f9132019-11-11 15:03:15 -080055import android.graphics.Rect;
Robert Carr8a2f9132019-11-11 15:03:15 -080056import android.os.Binder;
Evan Roskya8fde152020-01-07 19:09:13 -080057import android.os.IBinder;
Robert Carr8a2f9132019-11-11 15:03:15 -080058import android.os.RemoteException;
Evan Rosky0037e5f2019-11-05 10:26:24 -080059import android.platform.test.annotations.Presubmit;
Evan Roskya8fde152020-01-07 19:09:13 -080060import android.util.ArrayMap;
Robert Carrf6690d12020-02-04 14:16:21 -080061import android.util.Rational;
Evan Rosky0037e5f2019-11-05 10:26:24 -080062import android.view.Display;
Wale Ogunwale57946582020-03-21 14:29:07 -070063import android.window.ITaskOrganizer;
64import android.window.WindowContainerTransaction;
Robert Carr8a2f9132019-11-11 15:03:15 -080065
66import androidx.test.filters.SmallTest;
67
68import org.junit.Test;
69import org.junit.runner.RunWith;
70
Evan Rosky0037e5f2019-11-05 10:26:24 -080071import java.util.ArrayList;
72import java.util.List;
73
Robert Carr8a2f9132019-11-11 15:03:15 -080074/**
Wale Ogunwale57946582020-03-21 14:29:07 -070075 * Test class for {@link ITaskOrganizer} and {@link android.window.ITaskOrganizerController}.
Robert Carr8a2f9132019-11-11 15:03:15 -080076 *
77 * Build/Install/Run:
78 * atest WmTests:TaskOrganizerTests
79 */
80@SmallTest
81@Presubmit
82@RunWith(WindowTestRunner.class)
83public class TaskOrganizerTests extends WindowTestsBase {
Robert Carr00c0dbe2020-01-24 15:30:24 -080084 private ITaskOrganizer registerMockOrganizer(int windowingMode) {
Robert Carr8a2f9132019-11-11 15:03:15 -080085 final ITaskOrganizer organizer = mock(ITaskOrganizer.class);
86 when(organizer.asBinder()).thenReturn(new Binder());
87
Evan Rosky0037e5f2019-11-05 10:26:24 -080088 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(
89 organizer, windowingMode);
Robert Carr8a2f9132019-11-11 15:03:15 -080090
91 return organizer;
92 }
93
Robert Carr00c0dbe2020-01-24 15:30:24 -080094 private ITaskOrganizer registerMockOrganizer() {
95 return registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
96 }
97
Robert Carr8a2f9132019-11-11 15:03:15 -080098 @Test
99 public void testAppearVanish() throws RemoteException {
100 final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
101 final Task task = createTaskInStack(stack, 0 /* userId */);
Robert Carr00c0dbe2020-01-24 15:30:24 -0800102 final ITaskOrganizer organizer = registerMockOrganizer();
Robert Carr8a2f9132019-11-11 15:03:15 -0800103
104 task.setTaskOrganizer(organizer);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700105 verify(organizer).onTaskAppeared(any());
Robert Carr8a2f9132019-11-11 15:03:15 -0800106
107 task.removeImmediately();
Wale Ogunwaledec34082020-03-22 09:45:00 -0700108 verify(organizer).onTaskVanished(any());
Robert Carr8a2f9132019-11-11 15:03:15 -0800109 }
110
111 @Test
112 public void testSwapOrganizer() throws RemoteException {
113 final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
114 final Task task = createTaskInStack(stack, 0 /* userId */);
Robert Carr00c0dbe2020-01-24 15:30:24 -0800115 final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
116 final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED);
Robert Carr8a2f9132019-11-11 15:03:15 -0800117
118 task.setTaskOrganizer(organizer);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700119 verify(organizer).onTaskAppeared(any());
Robert Carr8a2f9132019-11-11 15:03:15 -0800120 task.setTaskOrganizer(organizer2);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700121 verify(organizer).onTaskVanished(any());
122 verify(organizer2).onTaskAppeared(any());
Robert Carr8a2f9132019-11-11 15:03:15 -0800123 }
124
125 @Test
Robert Carr00c0dbe2020-01-24 15:30:24 -0800126 public void testSwapWindowingModes() throws RemoteException {
127 final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
128 final Task task = createTaskInStack(stack, 0 /* userId */);
129 final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
130 final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED);
Rob Carrab179782020-03-10 12:50:30 -0700131
Robert Carr00c0dbe2020-01-24 15:30:24 -0800132 stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700133 verify(organizer).onTaskAppeared(any());
Robert Carr00c0dbe2020-01-24 15:30:24 -0800134 stack.setWindowingMode(WINDOWING_MODE_PINNED);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700135 verify(organizer).onTaskVanished(any());
136 verify(organizer2).onTaskAppeared(any());
Robert Carr00c0dbe2020-01-24 15:30:24 -0800137 }
138
139 @Test
Robert Carr8a2f9132019-11-11 15:03:15 -0800140 public void testClearOrganizer() throws RemoteException {
141 final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
142 final Task task = createTaskInStack(stack, 0 /* userId */);
Robert Carr00c0dbe2020-01-24 15:30:24 -0800143 final ITaskOrganizer organizer = registerMockOrganizer();
Robert Carr8a2f9132019-11-11 15:03:15 -0800144
Robert Carr9fd095b2020-01-24 14:40:06 -0800145 stack.setTaskOrganizer(organizer);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700146 verify(organizer).onTaskAppeared(any());
147 assertTrue(stack.isOrganized());
Robert Carr8a2f9132019-11-11 15:03:15 -0800148
Robert Carr9fd095b2020-01-24 14:40:06 -0800149 stack.setTaskOrganizer(null);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700150 verify(organizer).onTaskVanished(any());
151 assertFalse(stack.isOrganized());
Robert Carr8a2f9132019-11-11 15:03:15 -0800152 }
153
154 @Test
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800155 public void testUnregisterOrganizer() throws RemoteException {
156 final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
157 final Task task = createTaskInStack(stack, 0 /* userId */);
158 final ITaskOrganizer organizer = registerMockOrganizer();
159
160 stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700161 verify(organizer).onTaskAppeared(any());
162 assertTrue(stack.isOrganized());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800163
164 mWm.mAtmService.mTaskOrganizerController.unregisterTaskOrganizer(organizer);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700165 verify(organizer).onTaskVanished(any());
166 assertFalse(stack.isOrganized());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800167 }
168
169 @Test
170 public void testUnregisterOrganizerReturnsRegistrationToPrevious() throws RemoteException {
171 final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
172 final Task task = createTaskInStack(stack, 0 /* userId */);
173 final ActivityStack stack2 = createTaskStackOnDisplay(mDisplayContent);
174 final Task task2 = createTaskInStack(stack2, 0 /* userId */);
175 final ActivityStack stack3 = createTaskStackOnDisplay(mDisplayContent);
176 final Task task3 = createTaskInStack(stack3, 0 /* userId */);
177 final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
178
179 // First organizer is registered, verify a task appears when changing windowing mode
180 stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700181 verify(organizer, times(1)).onTaskAppeared(any());
182 assertTrue(stack.isOrganized());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800183
184 // Now we replace the registration and1 verify the new organizer receives tasks
185 // newly entering the windowing mode.
186 final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
187 stack2.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700188 verify(organizer2).onTaskAppeared(any());
189 assertTrue(stack2.isOrganized());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800190
191 // Now we unregister the second one, the first one should automatically be reregistered
192 // so we verify that it's now seeing changes.
193 mWm.mAtmService.mTaskOrganizerController.unregisterTaskOrganizer(organizer2);
194
195 stack3.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700196 verify(organizer, times(2)).onTaskAppeared(any());
197 assertTrue(stack3.isOrganized());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800198 }
199
200 @Test
Robert Carr8a2f9132019-11-11 15:03:15 -0800201 public void testRegisterTaskOrganizerStackWindowingModeChanges() throws RemoteException {
Robert Carr00c0dbe2020-01-24 15:30:24 -0800202 final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED);
Robert Carr8a2f9132019-11-11 15:03:15 -0800203
204 final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
205 final Task task = createTaskInStack(stack, 0 /* userId */);
206 final Task task2 = createTaskInStack(stack, 0 /* userId */);
207 stack.setWindowingMode(WINDOWING_MODE_PINNED);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700208 verify(organizer, times(1)).onTaskAppeared(any());
Robert Carr8a2f9132019-11-11 15:03:15 -0800209
210 stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700211 verify(organizer, times(1)).onTaskVanished(any());
Robert Carr8a2f9132019-11-11 15:03:15 -0800212 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800213
214 @Test
Winson Chung77338ab2020-03-09 16:32:34 -0700215 public void testRegisterTaskOrganizerWithExistingTasks() throws RemoteException {
216 final ActivityStack stack = createTaskStackOnDisplay(mDisplayContent);
217 final Task task = createTaskInStack(stack, 0 /* userId */);
218 stack.setWindowingMode(WINDOWING_MODE_PINNED);
219
220 final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700221 verify(organizer, times(1)).onTaskAppeared(any());
Winson Chung77338ab2020-03-09 16:32:34 -0700222 }
223
224 @Test
Evan Rosky0037e5f2019-11-05 10:26:24 -0800225 public void testTaskTransaction() {
226 removeGlobalMinSizeRestriction();
227 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
228 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
229 final Task task = stack.getTopMostTask();
230 WindowContainerTransaction t = new WindowContainerTransaction();
231 Rect newBounds = new Rect(10, 10, 100, 100);
232 t.setBounds(task.mRemoteToken, new Rect(10, 10, 100, 100));
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700233 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800234 assertEquals(newBounds, task.getBounds());
235 }
236
237 @Test
238 public void testStackTransaction() {
239 removeGlobalMinSizeRestriction();
240 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
241 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
242 StackInfo info =
243 mWm.mAtmService.getStackInfo(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
244 WindowContainerTransaction t = new WindowContainerTransaction();
245 assertEquals(stack.mRemoteToken, info.stackToken);
246 Rect newBounds = new Rect(10, 10, 100, 100);
247 t.setBounds(info.stackToken, new Rect(10, 10, 100, 100));
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700248 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800249 assertEquals(newBounds, stack.getBounds());
250 }
251
252 @Test
Robert Carr2bed6212020-02-20 16:55:07 -0800253 public void testSetWindowingMode() {
254 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
255 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
256 final WindowContainerTransaction t = new WindowContainerTransaction();
257
258 t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700259 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Robert Carr2bed6212020-02-20 16:55:07 -0800260
261 assertEquals(WINDOWING_MODE_FULLSCREEN, stack.getWindowingMode());
262 }
263
264 @Test
265 public void testSetActivityWindowingMode() {
266 final ActivityRecord record = makePipableActivity();
267 final ActivityStack stack = record.getStack();
268 final WindowContainerTransaction t = new WindowContainerTransaction();
269
270 t.setWindowingMode(stack.mRemoteToken, WINDOWING_MODE_PINNED);
271 t.setActivityWindowingMode(stack.mRemoteToken, WINDOWING_MODE_FULLSCREEN);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700272 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Robert Carr2bed6212020-02-20 16:55:07 -0800273
274 assertEquals(WINDOWING_MODE_FULLSCREEN, record.getWindowingMode());
275 assertEquals(WINDOWING_MODE_PINNED, stack.getWindowingMode());
276 }
277
278 @Test
Robert Carrf6878a42019-12-18 02:13:12 -0800279 public void testContainerFocusableChanges() {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800280 removeGlobalMinSizeRestriction();
281 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
282 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
283 final Task task = stack.getTopMostTask();
284 WindowContainerTransaction t = new WindowContainerTransaction();
285 assertTrue(task.isFocusable());
286 t.setFocusable(stack.mRemoteToken, false);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700287 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800288 assertFalse(task.isFocusable());
Robert Carrf6878a42019-12-18 02:13:12 -0800289 t.setFocusable(stack.mRemoteToken, true);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700290 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Robert Carrf6878a42019-12-18 02:13:12 -0800291 assertTrue(task.isFocusable());
292 }
293
294 @Test
295 public void testContainerHiddenChanges() {
296 removeGlobalMinSizeRestriction();
297 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
298 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
299 WindowContainerTransaction t = new WindowContainerTransaction();
300 assertTrue(stack.shouldBeVisible(null));
301 t.setHidden(stack.mRemoteToken, true);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700302 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Robert Carrf6878a42019-12-18 02:13:12 -0800303 assertFalse(stack.shouldBeVisible(null));
304 t.setHidden(stack.mRemoteToken, false);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700305 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Robert Carrf6878a42019-12-18 02:13:12 -0800306 assertTrue(stack.shouldBeVisible(null));
Evan Rosky0037e5f2019-11-05 10:26:24 -0800307 }
308
309 @Test
Evan Rosky05ec8862020-02-28 19:37:04 -0800310 public void testOverrideConfigSize() {
311 removeGlobalMinSizeRestriction();
312 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
313 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
314 final Task task = stack.getTopMostTask();
315 WindowContainerTransaction t = new WindowContainerTransaction();
316 t.setBounds(task.mRemoteToken, new Rect(10, 10, 100, 100));
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700317 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Evan Rosky05ec8862020-02-28 19:37:04 -0800318 final int origScreenWDp = task.getConfiguration().screenHeightDp;
319 final int origScreenHDp = task.getConfiguration().screenHeightDp;
320 t = new WindowContainerTransaction();
321 // verify that setting config overrides on parent restricts children.
322 t.setScreenSizeDp(stack.mRemoteToken, origScreenWDp, origScreenHDp);
323 t.setBounds(task.mRemoteToken, new Rect(10, 10, 150, 200));
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700324 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Evan Rosky05ec8862020-02-28 19:37:04 -0800325 assertEquals(origScreenHDp, task.getConfiguration().screenHeightDp);
326 t = new WindowContainerTransaction();
327 t.setScreenSizeDp(stack.mRemoteToken, Configuration.SCREEN_WIDTH_DP_UNDEFINED,
328 Configuration.SCREEN_HEIGHT_DP_UNDEFINED);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700329 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Evan Rosky05ec8862020-02-28 19:37:04 -0800330 assertNotEquals(origScreenHDp, task.getConfiguration().screenHeightDp);
331 }
332
333 @Test
Evan Rosky0037e5f2019-11-05 10:26:24 -0800334 public void testCreateDeleteRootTasks() {
335 RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
336 Display.DEFAULT_DISPLAY,
337 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
338 assertEquals(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
339 info1.configuration.windowConfiguration.getWindowingMode());
340 assertEquals(ACTIVITY_TYPE_UNDEFINED, info1.topActivityType);
341
342 RunningTaskInfo info2 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
343 Display.DEFAULT_DISPLAY,
344 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
345 assertEquals(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
346 info2.configuration.windowConfiguration.getWindowingMode());
347 assertEquals(ACTIVITY_TYPE_UNDEFINED, info2.topActivityType);
348
349 DisplayContent dc = mWm.mRoot.getDisplayContent(Display.DEFAULT_DISPLAY);
350 List<TaskTile> infos = getTaskTiles(dc);
351 assertEquals(2, infos.size());
352
353 assertTrue(mWm.mAtmService.mTaskOrganizerController.deleteRootTask(info1.token));
354 infos = getTaskTiles(dc);
355 assertEquals(1, infos.size());
356 assertEquals(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, infos.get(0).getWindowingMode());
357 }
358
359 @Test
360 public void testTileAddRemoveChild() {
361 RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
362 mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
363
364 final ActivityStack stack = createTaskStackOnDisplay(
365 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
366 assertEquals(mDisplayContent.getWindowingMode(), stack.getWindowingMode());
367 TaskTile tile1 = TaskTile.forToken(info1.token.asBinder());
368 tile1.addChild(stack, 0 /* index */);
369 assertEquals(info1.configuration.windowConfiguration.getWindowingMode(),
370 stack.getWindowingMode());
371
372 // Info should reflect new membership
373 List<TaskTile> tiles = getTaskTiles(mDisplayContent);
Winson Chung66b08f02020-03-03 14:32:35 -0800374 info1 = tiles.get(0).getTaskInfo();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800375 assertEquals(ACTIVITY_TYPE_STANDARD, info1.topActivityType);
376
377 // Children inherit configuration
378 Rect newSize = new Rect(10, 10, 300, 300);
379 Configuration c = new Configuration(tile1.getRequestedOverrideConfiguration());
380 c.windowConfiguration.setBounds(newSize);
Wale Ogunwale0d465192020-01-23 19:14:44 -0800381 doNothing().when(stack).adjustForMinimalTaskDimensions(any(), any());
Evan Rosky0037e5f2019-11-05 10:26:24 -0800382 tile1.onRequestedOverrideConfigurationChanged(c);
383 assertEquals(newSize, stack.getBounds());
384
385 tile1.removeChild(stack);
386 assertEquals(mDisplayContent.getWindowingMode(), stack.getWindowingMode());
Evan Rosky0037e5f2019-11-05 10:26:24 -0800387 tiles = getTaskTiles(mDisplayContent);
Winson Chung66b08f02020-03-03 14:32:35 -0800388 info1 = tiles.get(0).getTaskInfo();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800389 assertEquals(ACTIVITY_TYPE_UNDEFINED, info1.topActivityType);
390 }
391
392 @Test
393 public void testTaskInfoCallback() {
394 final ArrayList<RunningTaskInfo> lastReportedTiles = new ArrayList<>();
395 final boolean[] called = {false};
396 ITaskOrganizer listener = new ITaskOrganizer.Stub() {
397 @Override
Wale Ogunwaledec34082020-03-22 09:45:00 -0700398 public void onTaskAppeared(RunningTaskInfo taskInfo) { }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800399
400 @Override
Wale Ogunwaledec34082020-03-22 09:45:00 -0700401 public void onTaskVanished(RunningTaskInfo container) { }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800402
403 @Override
Evan Rosky0037e5f2019-11-05 10:26:24 -0800404 public void onTaskInfoChanged(RunningTaskInfo info) throws RemoteException {
405 lastReportedTiles.add(info);
406 called[0] = true;
407 }
408 };
409 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener,
410 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
411 RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
412 mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
413 lastReportedTiles.clear();
414 called[0] = false;
415
416 final ActivityStack stack = createTaskStackOnDisplay(
417 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
418 TaskTile tile1 = TaskTile.forToken(info1.token.asBinder());
419 tile1.addChild(stack, 0 /* index */);
420 assertTrue(called[0]);
421 assertEquals(ACTIVITY_TYPE_STANDARD, lastReportedTiles.get(0).topActivityType);
422
423 lastReportedTiles.clear();
424 called[0] = false;
425 final ActivityStack stack2 = createTaskStackOnDisplay(
426 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, mDisplayContent);
427 tile1.addChild(stack2, 0 /* index */);
428 assertTrue(called[0]);
429 assertEquals(ACTIVITY_TYPE_HOME, lastReportedTiles.get(0).topActivityType);
430
431 lastReportedTiles.clear();
432 called[0] = false;
433 mDisplayContent.positionStackAtTop(stack, false /* includingParents */);
434 assertTrue(called[0]);
435 assertEquals(ACTIVITY_TYPE_STANDARD, lastReportedTiles.get(0).topActivityType);
436
437 lastReportedTiles.clear();
438 called[0] = false;
439 tile1.removeAllChildren();
440 assertTrue(called[0]);
441 assertEquals(ACTIVITY_TYPE_UNDEFINED, lastReportedTiles.get(0).topActivityType);
442 }
443
Evan Roskya8fde152020-01-07 19:09:13 -0800444 @Test
445 public void testHierarchyTransaction() {
446 final ArrayMap<IBinder, RunningTaskInfo> lastReportedTiles = new ArrayMap<>();
447 ITaskOrganizer listener = new ITaskOrganizer.Stub() {
448 @Override
Wale Ogunwaledec34082020-03-22 09:45:00 -0700449 public void onTaskAppeared(RunningTaskInfo taskInfo) { }
Evan Roskya8fde152020-01-07 19:09:13 -0800450
451 @Override
Wale Ogunwaledec34082020-03-22 09:45:00 -0700452 public void onTaskVanished(RunningTaskInfo container) { }
Evan Roskya8fde152020-01-07 19:09:13 -0800453
454 @Override
Evan Roskya8fde152020-01-07 19:09:13 -0800455 public void onTaskInfoChanged(RunningTaskInfo info) {
456 lastReportedTiles.put(info.token.asBinder(), info);
457 }
458 };
459 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(
460 listener, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
461 RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
462 mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
463 RunningTaskInfo info2 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
464 mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
465
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800466 final int initialRootTaskCount = mWm.mAtmService.mTaskOrganizerController.getRootTasks(
467 mDisplayContent.mDisplayId, null /* activityTypes */).size();
468
Evan Roskya8fde152020-01-07 19:09:13 -0800469 final ActivityStack stack = createTaskStackOnDisplay(
470 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
471 final ActivityStack stack2 = createTaskStackOnDisplay(
472 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, mDisplayContent);
473
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800474 // Check getRootTasks works
475 List<RunningTaskInfo> roots = mWm.mAtmService.mTaskOrganizerController.getRootTasks(
476 mDisplayContent.mDisplayId, null /* activityTypes */);
477 assertEquals(initialRootTaskCount + 2, roots.size());
478
Evan Roskya8fde152020-01-07 19:09:13 -0800479 lastReportedTiles.clear();
480 WindowContainerTransaction wct = new WindowContainerTransaction();
481 wct.reparent(stack.mRemoteToken, info1.token, true /* onTop */);
482 wct.reparent(stack2.mRemoteToken, info2.token, true /* onTop */);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700483 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Roskya8fde152020-01-07 19:09:13 -0800484 assertFalse(lastReportedTiles.isEmpty());
485 assertEquals(ACTIVITY_TYPE_STANDARD,
486 lastReportedTiles.get(info1.token.asBinder()).topActivityType);
487 assertEquals(ACTIVITY_TYPE_HOME,
488 lastReportedTiles.get(info2.token.asBinder()).topActivityType);
489
490 lastReportedTiles.clear();
491 wct = new WindowContainerTransaction();
492 wct.reparent(stack2.mRemoteToken, info1.token, false /* onTop */);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700493 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Roskya8fde152020-01-07 19:09:13 -0800494 assertFalse(lastReportedTiles.isEmpty());
495 // Standard should still be on top of tile 1, so no change there
496 assertFalse(lastReportedTiles.containsKey(info1.token.asBinder()));
497 // But tile 2 has no children, so should become undefined
498 assertEquals(ACTIVITY_TYPE_UNDEFINED,
499 lastReportedTiles.get(info2.token.asBinder()).topActivityType);
500
501 // Check the getChildren call
502 List<RunningTaskInfo> children =
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800503 mWm.mAtmService.mTaskOrganizerController.getChildTasks(info1.token,
504 null /* activityTypes */);
Evan Roskya8fde152020-01-07 19:09:13 -0800505 assertEquals(2, children.size());
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800506 children = mWm.mAtmService.mTaskOrganizerController.getChildTasks(info2.token,
507 null /* activityTypes */);
Evan Roskya8fde152020-01-07 19:09:13 -0800508 assertEquals(0, children.size());
509
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800510 // Check that getRootTasks doesn't include children of tiles
511 roots = mWm.mAtmService.mTaskOrganizerController.getRootTasks(mDisplayContent.mDisplayId,
512 null /* activityTypes */);
513 assertEquals(initialRootTaskCount, roots.size());
514
Evan Roskya8fde152020-01-07 19:09:13 -0800515 lastReportedTiles.clear();
516 wct = new WindowContainerTransaction();
517 wct.reorder(stack2.mRemoteToken, true /* onTop */);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700518 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Roskya8fde152020-01-07 19:09:13 -0800519 // Home should now be on top. No change occurs in second tile, so not reported
520 assertEquals(1, lastReportedTiles.size());
521 assertEquals(ACTIVITY_TYPE_HOME,
522 lastReportedTiles.get(info1.token.asBinder()).topActivityType);
523 }
524
Evan Rosky0037e5f2019-11-05 10:26:24 -0800525 private List<TaskTile> getTaskTiles(DisplayContent dc) {
526 ArrayList<TaskTile> out = new ArrayList<>();
527 for (int i = dc.getStackCount() - 1; i >= 0; --i) {
Evan Roskyaf9f27c2020-02-18 18:58:35 +0000528 final TaskTile t = dc.getStackAt(i).asTile();
529 if (t != null) {
530 out.add(t);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800531 }
532 }
533 return out;
534 }
Robert Carre10ee3d2019-11-11 15:03:15 -0800535
536 @Test
537 public void testTrivialBLASTCallback() throws RemoteException {
538 final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
539 final Task task = createTaskInStack(stackController1, 0 /* userId */);
540 final ITaskOrganizer organizer = registerMockOrganizer();
541
Robert Carr8ccc4fc2020-03-13 10:48:49 -0700542 spyOn(task);
543 doReturn(true).when(task).isVisible();
544
Robert Carre10ee3d2019-11-11 15:03:15 -0800545 BLASTSyncEngine bse = new BLASTSyncEngine();
546
547 BLASTSyncEngine.TransactionReadyListener transactionListener =
548 mock(BLASTSyncEngine.TransactionReadyListener.class);
549
550 int id = bse.startSyncSet(transactionListener);
551 bse.addToSyncSet(id, task);
552 bse.setReady(id);
553 // Since this task has no windows the sync is trivial and completes immediately.
554 verify(transactionListener)
555 .transactionReady(anyInt(), any());
556 }
557
558 @Test
Robert Carr8ccc4fc2020-03-13 10:48:49 -0700559 public void testOverlappingBLASTCallback() throws RemoteException {
560 final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
561 final Task task = createTaskInStack(stackController1, 0 /* userId */);
562 final ITaskOrganizer organizer = registerMockOrganizer();
563
564 spyOn(task);
565 doReturn(true).when(task).isVisible();
566 final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
567 makeWindowVisible(w);
568
569 BLASTSyncEngine bse = new BLASTSyncEngine();
570
571 BLASTSyncEngine.TransactionReadyListener transactionListener =
572 mock(BLASTSyncEngine.TransactionReadyListener.class);
573
574 int id = bse.startSyncSet(transactionListener);
575 assertEquals(true, bse.addToSyncSet(id, task));
576 bse.setReady(id);
577
578 int id2 = bse.startSyncSet(transactionListener);
579 // We should be rejected from the second sync since we are already
580 // in one.
581 assertEquals(false, bse.addToSyncSet(id2, task));
582 w.finishDrawing(null);
583 assertEquals(true, bse.addToSyncSet(id2, task));
584 bse.setReady(id2);
585 }
586
587 @Test
Robert Carre10ee3d2019-11-11 15:03:15 -0800588 public void testBLASTCallbackWithWindow() {
589 final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
590 final Task task = createTaskInStack(stackController1, 0 /* userId */);
591 final ITaskOrganizer organizer = registerMockOrganizer();
592 final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
Rob Carrcba6a722020-03-10 12:41:06 -0700593 makeWindowVisible(w);
Robert Carre10ee3d2019-11-11 15:03:15 -0800594
595 BLASTSyncEngine bse = new BLASTSyncEngine();
596
597 BLASTSyncEngine.TransactionReadyListener transactionListener =
598 mock(BLASTSyncEngine.TransactionReadyListener.class);
599
600 int id = bse.startSyncSet(transactionListener);
601 bse.addToSyncSet(id, task);
602 bse.setReady(id);
603 // Since we have a window we have to wait for it to draw to finish sync.
604 verify(transactionListener, never())
605 .transactionReady(anyInt(), any());
606 w.finishDrawing(null);
607 verify(transactionListener)
608 .transactionReady(anyInt(), any());
609 }
Robert Carrf6690d12020-02-04 14:16:21 -0800610
Rob Carr25376512020-03-09 15:23:19 -0700611 @Test
Rob Carrcba6a722020-03-10 12:41:06 -0700612 public void testBLASTCallbackWithInvisibleWindow() {
613 final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
614 final Task task = createTaskInStack(stackController1, 0 /* userId */);
615 final ITaskOrganizer organizer = registerMockOrganizer();
616 final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
617
618 BLASTSyncEngine bse = new BLASTSyncEngine();
619
620 BLASTSyncEngine.TransactionReadyListener transactionListener =
621 mock(BLASTSyncEngine.TransactionReadyListener.class);
622
623 int id = bse.startSyncSet(transactionListener);
624 bse.addToSyncSet(id, task);
625 bse.setReady(id);
626
627 // Since the window was invisible, the Task had no visible leaves and the sync should
628 // complete as soon as we call setReady.
629 verify(transactionListener)
630 .transactionReady(anyInt(), any());
631 }
632
633 @Test
Rob Carr25376512020-03-09 15:23:19 -0700634 public void testBLASTCallbackWithChildWindow() {
635 final ActivityStack stackController1 = createTaskStackOnDisplay(mDisplayContent);
636 final Task task = createTaskInStack(stackController1, 0 /* userId */);
637 final ITaskOrganizer organizer = registerMockOrganizer();
638 final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
639 final WindowState child = createWindow(w, TYPE_APPLICATION, "Other Window");
640
641 w.mActivityRecord.setVisible(true);
642 makeWindowVisible(w, child);
643
644 BLASTSyncEngine bse = new BLASTSyncEngine();
645
646 BLASTSyncEngine.TransactionReadyListener transactionListener =
647 mock(BLASTSyncEngine.TransactionReadyListener.class);
648
649 int id = bse.startSyncSet(transactionListener);
650 assertEquals(true, bse.addToSyncSet(id, task));
651 bse.setReady(id);
652 w.finishDrawing(null);
653
654 // Since we have a child window we still shouldn't be done.
655 verify(transactionListener, never())
656 .transactionReady(anyInt(), any());
657 reset(transactionListener);
658
659 child.finishDrawing(null);
660 // Ah finally! Done
661 verify(transactionListener)
662 .transactionReady(anyInt(), any());
663 }
664
Robert Carrf6690d12020-02-04 14:16:21 -0800665 class StubOrganizer extends ITaskOrganizer.Stub {
666 RunningTaskInfo mInfo;
667
668 @Override
Wale Ogunwaledec34082020-03-22 09:45:00 -0700669 public void onTaskAppeared(RunningTaskInfo info) {
Robert Carrf6690d12020-02-04 14:16:21 -0800670 mInfo = info;
671 }
672 @Override
Wale Ogunwaledec34082020-03-22 09:45:00 -0700673 public void onTaskVanished(RunningTaskInfo info) {
Robert Carrf6690d12020-02-04 14:16:21 -0800674 }
675 @Override
Robert Carrf6690d12020-02-04 14:16:21 -0800676 public void onTaskInfoChanged(RunningTaskInfo info) {
677 }
678 };
679
680 private ActivityRecord makePipableActivity() {
681 final ActivityRecord record = createActivityRecord(mDisplayContent,
682 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
683 record.info.flags |= ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
684 spyOn(record);
685 doReturn(true).when(record).checkEnterPictureInPictureState(any(), anyBoolean());
686 return record;
687 }
688
689 @Test
690 public void testEnterPipParams() {
691 final StubOrganizer o = new StubOrganizer();
692 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(o, WINDOWING_MODE_PINNED);
693 final ActivityRecord record = makePipableActivity();
694
695 final PictureInPictureParams p =
696 new PictureInPictureParams.Builder().setAspectRatio(new Rational(1, 2)).build();
697 assertTrue(mWm.mAtmService.enterPictureInPictureMode(record.token, p));
698 waitUntilHandlersIdle();
699 assertNotNull(o.mInfo);
700 assertNotNull(o.mInfo.pictureInPictureParams);
701 }
702
703 @Test
704 public void testChangePipParams() {
705 class ChangeSavingOrganizer extends StubOrganizer {
706 RunningTaskInfo mChangedInfo;
707 @Override
708 public void onTaskInfoChanged(RunningTaskInfo info) {
709 mChangedInfo = info;
710 }
711 }
712 ChangeSavingOrganizer o = new ChangeSavingOrganizer();
713 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(o, WINDOWING_MODE_PINNED);
714
715 final ActivityRecord record = makePipableActivity();
716 final PictureInPictureParams p =
717 new PictureInPictureParams.Builder().setAspectRatio(new Rational(1, 2)).build();
718 assertTrue(mWm.mAtmService.enterPictureInPictureMode(record.token, p));
719 waitUntilHandlersIdle();
720 assertNotNull(o.mInfo);
721 assertNotNull(o.mInfo.pictureInPictureParams);
722
723 final PictureInPictureParams p2 =
724 new PictureInPictureParams.Builder().setAspectRatio(new Rational(3, 4)).build();
725 mWm.mAtmService.setPictureInPictureParams(record.token, p2);
726 waitUntilHandlersIdle();
727 assertNotNull(o.mChangedInfo);
728 assertNotNull(o.mChangedInfo.pictureInPictureParams);
729 final Rational ratio = o.mChangedInfo.pictureInPictureParams.getAspectRatioRational();
730 assertEquals(3, ratio.getNumerator());
731 assertEquals(4, ratio.getDenominator());
732 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800733}