blob: 2ea58a028a0abff72a14376b90a12a7963ed0a1d [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;
Wale Ogunwaleadf116e2020-03-27 16:36:01 -070029import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
30import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
Robert Carre10ee3d2019-11-11 15:03:15 -080031import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
Robert Carr8a2f9132019-11-11 15:03:15 -080032
Wale Ogunwale0d465192020-01-23 19:14:44 -080033import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000034import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
Robert Carr8a2f9132019-11-11 15:03:15 -080035import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
Evan Roskya8fde152020-01-07 19:09:13 -080036import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
Rob Carr25376512020-03-09 15:23:19 -070037import static com.android.dx.mockito.inline.extended.ExtendedMockito.reset;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000038import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
Robert Carr8a2f9132019-11-11 15:03:15 -080039import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
40import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
Robert Carr8a2f9132019-11-11 15:03:15 -080041import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
chaviw6630d852020-04-15 19:06:56 -070042import static com.android.server.wm.DisplayArea.Type.ABOVE_TASKS;
Louis Changa009c762020-02-26 11:21:31 +080043import static com.android.server.wm.WindowContainer.POSITION_TOP;
Robert Carr8a2f9132019-11-11 15:03:15 -080044
Evan Rosky0037e5f2019-11-05 10:26:24 -080045import static org.junit.Assert.assertEquals;
Jorim Jaggi2a3002a2020-02-17 15:57:34 +000046import static org.junit.Assert.assertFalse;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000047import static org.junit.Assert.assertNotNull;
Evan Rosky0037e5f2019-11-05 10:26:24 -080048import static org.junit.Assert.assertTrue;
49import static org.mockito.ArgumentMatchers.any;
Robert Carrf6690d12020-02-04 14:16:21 -080050import static org.mockito.ArgumentMatchers.anyBoolean;
Robert Carre10ee3d2019-11-11 15:03:15 -080051import static org.mockito.ArgumentMatchers.anyInt;
Evan Rosky0037e5f2019-11-05 10:26:24 -080052
Winson Chung1df39e22020-04-09 14:30:55 -070053import android.app.ActivityManager;
Evan Rosky0037e5f2019-11-05 10:26:24 -080054import android.app.ActivityManager.RunningTaskInfo;
55import android.app.ActivityManager.StackInfo;
Winson Chunga1f869d2020-03-21 23:02:48 -070056import android.app.IRequestFinishCallback;
Robert Carrf6690d12020-02-04 14:16:21 -080057import android.app.PictureInPictureParams;
Evan Roskyaf9f27c2020-02-18 18:58:35 +000058import android.content.pm.ActivityInfo;
Evan Rosky0037e5f2019-11-05 10:26:24 -080059import android.content.res.Configuration;
Robert Carr8a2f9132019-11-11 15:03:15 -080060import android.graphics.Rect;
Robert Carr8a2f9132019-11-11 15:03:15 -080061import android.os.Binder;
Evan Roskya8fde152020-01-07 19:09:13 -080062import android.os.IBinder;
Robert Carr8a2f9132019-11-11 15:03:15 -080063import android.os.RemoteException;
Evan Rosky0037e5f2019-11-05 10:26:24 -080064import android.platform.test.annotations.Presubmit;
Evan Roskya8fde152020-01-07 19:09:13 -080065import android.util.ArrayMap;
Robert Carrf6690d12020-02-04 14:16:21 -080066import android.util.Rational;
Evan Rosky0037e5f2019-11-05 10:26:24 -080067import android.view.Display;
chaviw7de50002020-04-27 12:33:30 -070068import android.view.SurfaceControl;
Wale Ogunwale57946582020-03-21 14:29:07 -070069import android.window.ITaskOrganizer;
70import android.window.WindowContainerTransaction;
Robert Carr8a2f9132019-11-11 15:03:15 -080071
72import androidx.test.filters.SmallTest;
73
Winson Chung1b5d0552020-04-06 19:28:49 -070074import org.junit.Before;
Robert Carr8a2f9132019-11-11 15:03:15 -080075import org.junit.Test;
76import org.junit.runner.RunWith;
77
Evan Rosky0037e5f2019-11-05 10:26:24 -080078import java.util.ArrayList;
79import java.util.List;
80
Robert Carr8a2f9132019-11-11 15:03:15 -080081/**
Wale Ogunwale57946582020-03-21 14:29:07 -070082 * Test class for {@link ITaskOrganizer} and {@link android.window.ITaskOrganizerController}.
Robert Carr8a2f9132019-11-11 15:03:15 -080083 *
84 * Build/Install/Run:
Wale Ogunwale20ab6d42020-04-13 07:30:59 -070085 * atest WmTests:WindowOrganizerTests
Robert Carr8a2f9132019-11-11 15:03:15 -080086 */
87@SmallTest
88@Presubmit
89@RunWith(WindowTestRunner.class)
chaviw6630d852020-04-15 19:06:56 -070090public class WindowOrganizerTests extends WindowTestsBase {
Robert Carr00c0dbe2020-01-24 15:30:24 -080091 private ITaskOrganizer registerMockOrganizer(int windowingMode) {
Robert Carr8a2f9132019-11-11 15:03:15 -080092 final ITaskOrganizer organizer = mock(ITaskOrganizer.class);
93 when(organizer.asBinder()).thenReturn(new Binder());
94
Evan Rosky0037e5f2019-11-05 10:26:24 -080095 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(
96 organizer, windowingMode);
Robert Carr8a2f9132019-11-11 15:03:15 -080097
98 return organizer;
99 }
100
Robert Carr00c0dbe2020-01-24 15:30:24 -0800101 private ITaskOrganizer registerMockOrganizer() {
102 return registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
103 }
104
Robert Carrde96c8a2020-03-24 15:22:21 -0700105 Task createTask(ActivityStack stack, boolean fakeDraw) {
106 final Task task = createTaskInStack(stack, 0);
107
108 if (fakeDraw) {
109 task.setHasBeenVisible(true);
110 }
111 return task;
112 }
113
114 Task createTask(ActivityStack stack) {
115 // Fake draw notifications for most of our tests.
116 return createTask(stack, true);
117 }
118
119 ActivityStack createStack() {
120 return createTaskStackOnDisplay(mDisplayContent);
121 }
122
Winson Chung1b5d0552020-04-06 19:28:49 -0700123 @Before
124 public void setUp() {
125 // We defer callbacks since we need to adjust task surface visibility, but for these tests,
126 // just run the callbacks synchronously
127 mWm.mAtmService.mTaskOrganizerController.setDeferTaskOrgCallbacksConsumer((r) -> r.run());
128 }
129
Robert Carr8a2f9132019-11-11 15:03:15 -0800130 @Test
131 public void testAppearVanish() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700132 final ActivityStack stack = createStack();
133 final Task task = createTask(stack);
Robert Carr00c0dbe2020-01-24 15:30:24 -0800134 final ITaskOrganizer organizer = registerMockOrganizer();
Robert Carr8a2f9132019-11-11 15:03:15 -0800135
136 task.setTaskOrganizer(organizer);
chaviw7de50002020-04-27 12:33:30 -0700137 verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
138
Robert Carr8a2f9132019-11-11 15:03:15 -0800139
140 task.removeImmediately();
Wale Ogunwaledec34082020-03-22 09:45:00 -0700141 verify(organizer).onTaskVanished(any());
Robert Carr8a2f9132019-11-11 15:03:15 -0800142 }
143
144 @Test
Robert Carrde96c8a2020-03-24 15:22:21 -0700145 public void testAppearWaitsForVisibility() throws RemoteException {
146 final ActivityStack stack = createStack();
147 final Task task = createTask(stack, false);
148 final ITaskOrganizer organizer = registerMockOrganizer();
149
150 task.setTaskOrganizer(organizer);
151
chaviw7de50002020-04-27 12:33:30 -0700152 verify(organizer, never())
153 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carrde96c8a2020-03-24 15:22:21 -0700154 task.setHasBeenVisible(true);
155 assertTrue(stack.getHasBeenVisible());
156
chaviw7de50002020-04-27 12:33:30 -0700157 verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carrde96c8a2020-03-24 15:22:21 -0700158
159 task.removeImmediately();
160 verify(organizer).onTaskVanished(any());
161 }
162
163 @Test
164 public void testNoVanishedIfNoAppear() throws RemoteException {
165 final ActivityStack stack = createStack();
166 final Task task = createTask(stack, false /* hasBeenVisible */);
167 final ITaskOrganizer organizer = registerMockOrganizer();
168
169 // In this test we skip making the Task visible, and verify
170 // that even though a TaskOrganizer is set remove doesn't emit
171 // a vanish callback, because we never emitted appear.
172 task.setTaskOrganizer(organizer);
chaviw7de50002020-04-27 12:33:30 -0700173 verify(organizer, never())
174 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carrde96c8a2020-03-24 15:22:21 -0700175 task.removeImmediately();
176 verify(organizer, never()).onTaskVanished(any());
177 }
178
179 @Test
Robert Carr8a2f9132019-11-11 15:03:15 -0800180 public void testSwapOrganizer() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700181 final ActivityStack stack = createStack();
182 final Task task = createTask(stack);
Robert Carr00c0dbe2020-01-24 15:30:24 -0800183 final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
184 final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED);
Robert Carr8a2f9132019-11-11 15:03:15 -0800185
186 task.setTaskOrganizer(organizer);
chaviw7de50002020-04-27 12:33:30 -0700187 verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carr8a2f9132019-11-11 15:03:15 -0800188 task.setTaskOrganizer(organizer2);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700189 verify(organizer).onTaskVanished(any());
chaviw7de50002020-04-27 12:33:30 -0700190 verify(organizer2).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carr8a2f9132019-11-11 15:03:15 -0800191 }
192
193 @Test
Robert Carr00c0dbe2020-01-24 15:30:24 -0800194 public void testSwapWindowingModes() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700195 final ActivityStack stack = createStack();
196 final Task task = createTask(stack);
Robert Carr00c0dbe2020-01-24 15:30:24 -0800197 final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
198 final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED);
Rob Carrab179782020-03-10 12:50:30 -0700199
Robert Carr00c0dbe2020-01-24 15:30:24 -0800200 stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
chaviw7de50002020-04-27 12:33:30 -0700201 verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carr00c0dbe2020-01-24 15:30:24 -0800202 stack.setWindowingMode(WINDOWING_MODE_PINNED);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700203 verify(organizer).onTaskVanished(any());
chaviw7de50002020-04-27 12:33:30 -0700204 verify(organizer2).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carr00c0dbe2020-01-24 15:30:24 -0800205 }
206
207 @Test
Louis Chang9d35a3a2020-04-06 17:23:02 +0800208 public void testTaskNoDraw() throws RemoteException {
209 final ActivityStack stack = createStack();
210 final Task task = createTask(stack, false /* fakeDraw */);
211 final ITaskOrganizer organizer = registerMockOrganizer();
212
213 stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
chaviw7de50002020-04-27 12:33:30 -0700214 verify(organizer, never())
215 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Louis Chang9d35a3a2020-04-06 17:23:02 +0800216 assertTrue(stack.isOrganized());
217
218 mWm.mAtmService.mTaskOrganizerController.unregisterTaskOrganizer(organizer);
219 verify(organizer, never()).onTaskVanished(any());
220 assertFalse(stack.isOrganized());
221 }
222
223 @Test
Robert Carr8a2f9132019-11-11 15:03:15 -0800224 public void testClearOrganizer() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700225 final ActivityStack stack = createStack();
226 final Task task = createTask(stack);
Robert Carr00c0dbe2020-01-24 15:30:24 -0800227 final ITaskOrganizer organizer = registerMockOrganizer();
Robert Carr8a2f9132019-11-11 15:03:15 -0800228
Robert Carr9fd095b2020-01-24 14:40:06 -0800229 stack.setTaskOrganizer(organizer);
chaviw7de50002020-04-27 12:33:30 -0700230 verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Wale Ogunwaledec34082020-03-22 09:45:00 -0700231 assertTrue(stack.isOrganized());
Robert Carr8a2f9132019-11-11 15:03:15 -0800232
Robert Carr9fd095b2020-01-24 14:40:06 -0800233 stack.setTaskOrganizer(null);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700234 verify(organizer).onTaskVanished(any());
235 assertFalse(stack.isOrganized());
Robert Carr8a2f9132019-11-11 15:03:15 -0800236 }
237
238 @Test
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800239 public void testUnregisterOrganizer() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700240 final ActivityStack stack = createStack();
241 final Task task = createTask(stack);
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800242 final ITaskOrganizer organizer = registerMockOrganizer();
243
244 stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
chaviw7de50002020-04-27 12:33:30 -0700245 verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Wale Ogunwaledec34082020-03-22 09:45:00 -0700246 assertTrue(stack.isOrganized());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800247
248 mWm.mAtmService.mTaskOrganizerController.unregisterTaskOrganizer(organizer);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700249 verify(organizer).onTaskVanished(any());
250 assertFalse(stack.isOrganized());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800251 }
252
253 @Test
254 public void testUnregisterOrganizerReturnsRegistrationToPrevious() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700255 final ActivityStack stack = createStack();
256 final Task task = createTask(stack);
257 final ActivityStack stack2 = createStack();
258 final Task task2 = createTask(stack2);
259 final ActivityStack stack3 = createStack();
260 final Task task3 = createTask(stack3);
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800261 final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
262
263 // First organizer is registered, verify a task appears when changing windowing mode
264 stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
chaviw7de50002020-04-27 12:33:30 -0700265 verify(organizer, times(1))
266 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Wale Ogunwaledec34082020-03-22 09:45:00 -0700267 assertTrue(stack.isOrganized());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800268
269 // Now we replace the registration and1 verify the new organizer receives tasks
270 // newly entering the windowing mode.
271 final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
272 stack2.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700273 // One each for task and task2
chaviw7de50002020-04-27 12:33:30 -0700274 verify(organizer2, times(2))
275 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700276 verify(organizer2, times(0)).onTaskVanished(any());
277 // One for task
278 verify(organizer).onTaskVanished(any());
Wale Ogunwaledec34082020-03-22 09:45:00 -0700279 assertTrue(stack2.isOrganized());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800280
281 // Now we unregister the second one, the first one should automatically be reregistered
282 // so we verify that it's now seeing changes.
283 mWm.mAtmService.mTaskOrganizerController.unregisterTaskOrganizer(organizer2);
chaviw7de50002020-04-27 12:33:30 -0700284 verify(organizer, times(3))
285 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700286 verify(organizer2, times(2)).onTaskVanished(any());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800287
288 stack3.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
chaviw7de50002020-04-27 12:33:30 -0700289 verify(organizer, times(4))
290 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700291 verify(organizer2, times(2)).onTaskVanished(any());
Wale Ogunwaledec34082020-03-22 09:45:00 -0700292 assertTrue(stack3.isOrganized());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800293 }
294
295 @Test
Robert Carr8a2f9132019-11-11 15:03:15 -0800296 public void testRegisterTaskOrganizerStackWindowingModeChanges() throws RemoteException {
Robert Carr00c0dbe2020-01-24 15:30:24 -0800297 final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED);
Robert Carr8a2f9132019-11-11 15:03:15 -0800298
Robert Carrde96c8a2020-03-24 15:22:21 -0700299 final ActivityStack stack = createStack();
300 final Task task = createTask(stack);
301 final Task task2 = createTask(stack);
Robert Carr8a2f9132019-11-11 15:03:15 -0800302 stack.setWindowingMode(WINDOWING_MODE_PINNED);
chaviw7de50002020-04-27 12:33:30 -0700303 verify(organizer, times(1))
304 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carr8a2f9132019-11-11 15:03:15 -0800305
306 stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700307 verify(organizer, times(1)).onTaskVanished(any());
Robert Carr8a2f9132019-11-11 15:03:15 -0800308 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800309
310 @Test
Winson Chung77338ab2020-03-09 16:32:34 -0700311 public void testRegisterTaskOrganizerWithExistingTasks() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700312 final ActivityStack stack = createStack();
313 final Task task = createTask(stack);
Winson Chung77338ab2020-03-09 16:32:34 -0700314 stack.setWindowingMode(WINDOWING_MODE_PINNED);
315
316 final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED);
chaviw7de50002020-04-27 12:33:30 -0700317 verify(organizer, times(1))
318 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Winson Chung77338ab2020-03-09 16:32:34 -0700319 }
320
321 @Test
Evan Rosky0037e5f2019-11-05 10:26:24 -0800322 public void testTaskTransaction() {
323 removeGlobalMinSizeRestriction();
324 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
325 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
326 final Task task = stack.getTopMostTask();
chaviw6630d852020-04-15 19:06:56 -0700327 testTransaction(task);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800328 }
329
330 @Test
331 public void testStackTransaction() {
332 removeGlobalMinSizeRestriction();
333 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
334 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
335 StackInfo info =
336 mWm.mAtmService.getStackInfo(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700337 assertEquals(stack.mRemoteToken.toWindowContainerToken(), info.stackToken);
chaviw6630d852020-04-15 19:06:56 -0700338 testTransaction(stack);
339 }
340
341 @Test
342 public void testDisplayAreaTransaction() {
343 removeGlobalMinSizeRestriction();
344 final DisplayArea displayArea = new DisplayArea<>(mWm, ABOVE_TASKS, "DisplayArea");
345 testTransaction(displayArea);
346 }
347
348 private void testTransaction(WindowContainer wc) {
349 WindowContainerTransaction t = new WindowContainerTransaction();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800350 Rect newBounds = new Rect(10, 10, 100, 100);
chaviw6630d852020-04-15 19:06:56 -0700351 t.setBounds(wc.mRemoteToken.toWindowContainerToken(), new Rect(10, 10, 100, 100));
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700352 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
chaviw6630d852020-04-15 19:06:56 -0700353 assertEquals(newBounds, wc.getBounds());
Evan Rosky0037e5f2019-11-05 10:26:24 -0800354 }
355
356 @Test
Robert Carr2bed6212020-02-20 16:55:07 -0800357 public void testSetWindowingMode() {
358 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
chaviw6630d852020-04-15 19:06:56 -0700359 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
360 testSetWindowingMode(stack);
361
362 final DisplayArea displayArea = new DisplayArea<>(mWm, ABOVE_TASKS, "DisplayArea");
363 displayArea.setWindowingMode(WINDOWING_MODE_FREEFORM);
364 testSetWindowingMode(displayArea);
365 }
366
367 private void testSetWindowingMode(WindowContainer wc) {
Robert Carr2bed6212020-02-20 16:55:07 -0800368 final WindowContainerTransaction t = new WindowContainerTransaction();
chaviw6630d852020-04-15 19:06:56 -0700369 t.setWindowingMode(wc.mRemoteToken.toWindowContainerToken(), WINDOWING_MODE_FULLSCREEN);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700370 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
chaviw6630d852020-04-15 19:06:56 -0700371 assertEquals(WINDOWING_MODE_FULLSCREEN, wc.getWindowingMode());
Robert Carr2bed6212020-02-20 16:55:07 -0800372 }
373
374 @Test
375 public void testSetActivityWindowingMode() {
376 final ActivityRecord record = makePipableActivity();
377 final ActivityStack stack = record.getStack();
378 final WindowContainerTransaction t = new WindowContainerTransaction();
379
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700380 t.setWindowingMode(stack.mRemoteToken.toWindowContainerToken(), WINDOWING_MODE_PINNED);
381 t.setActivityWindowingMode(
382 stack.mRemoteToken.toWindowContainerToken(), WINDOWING_MODE_FULLSCREEN);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700383 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Robert Carr2bed6212020-02-20 16:55:07 -0800384
385 assertEquals(WINDOWING_MODE_FULLSCREEN, record.getWindowingMode());
386 assertEquals(WINDOWING_MODE_PINNED, stack.getWindowingMode());
387 }
388
389 @Test
Robert Carrf6878a42019-12-18 02:13:12 -0800390 public void testContainerFocusableChanges() {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800391 removeGlobalMinSizeRestriction();
392 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
393 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
394 final Task task = stack.getTopMostTask();
395 WindowContainerTransaction t = new WindowContainerTransaction();
396 assertTrue(task.isFocusable());
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700397 t.setFocusable(stack.mRemoteToken.toWindowContainerToken(), false);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700398 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800399 assertFalse(task.isFocusable());
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700400 t.setFocusable(stack.mRemoteToken.toWindowContainerToken(), true);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700401 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Robert Carrf6878a42019-12-18 02:13:12 -0800402 assertTrue(task.isFocusable());
403 }
404
405 @Test
406 public void testContainerHiddenChanges() {
407 removeGlobalMinSizeRestriction();
408 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
409 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
410 WindowContainerTransaction t = new WindowContainerTransaction();
411 assertTrue(stack.shouldBeVisible(null));
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700412 t.setHidden(stack.mRemoteToken.toWindowContainerToken(), true);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700413 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Robert Carrf6878a42019-12-18 02:13:12 -0800414 assertFalse(stack.shouldBeVisible(null));
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700415 t.setHidden(stack.mRemoteToken.toWindowContainerToken(), false);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700416 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Robert Carrf6878a42019-12-18 02:13:12 -0800417 assertTrue(stack.shouldBeVisible(null));
Evan Rosky0037e5f2019-11-05 10:26:24 -0800418 }
419
420 @Test
Evan Rosky05ec8862020-02-28 19:37:04 -0800421 public void testOverrideConfigSize() {
422 removeGlobalMinSizeRestriction();
423 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
424 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
425 final Task task = stack.getTopMostTask();
426 WindowContainerTransaction t = new WindowContainerTransaction();
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700427 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Evan Rosky05ec8862020-02-28 19:37:04 -0800428 final int origScreenWDp = task.getConfiguration().screenHeightDp;
429 final int origScreenHDp = task.getConfiguration().screenHeightDp;
430 t = new WindowContainerTransaction();
431 // verify that setting config overrides on parent restricts children.
chaviw6630d852020-04-15 19:06:56 -0700432 t.setScreenSizeDp(stack.mRemoteToken
Evan Roskyc440b4e2020-04-17 15:11:22 -0700433 .toWindowContainerToken(), origScreenWDp, origScreenHDp / 2);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700434 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Evan Roskyc440b4e2020-04-17 15:11:22 -0700435 assertEquals(origScreenHDp / 2, task.getConfiguration().screenHeightDp);
Evan Rosky05ec8862020-02-28 19:37:04 -0800436 t = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700437 t.setScreenSizeDp(stack.mRemoteToken.toWindowContainerToken(), SCREEN_WIDTH_DP_UNDEFINED,
438 SCREEN_HEIGHT_DP_UNDEFINED);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700439 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Evan Roskyc440b4e2020-04-17 15:11:22 -0700440 assertEquals(origScreenHDp, task.getConfiguration().screenHeightDp);
Evan Rosky05ec8862020-02-28 19:37:04 -0800441 }
442
443 @Test
Evan Rosky0037e5f2019-11-05 10:26:24 -0800444 public void testCreateDeleteRootTasks() {
445 RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
446 Display.DEFAULT_DISPLAY,
447 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
448 assertEquals(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
449 info1.configuration.windowConfiguration.getWindowingMode());
450 assertEquals(ACTIVITY_TYPE_UNDEFINED, info1.topActivityType);
451
452 RunningTaskInfo info2 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
453 Display.DEFAULT_DISPLAY,
454 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
455 assertEquals(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
456 info2.configuration.windowConfiguration.getWindowingMode());
457 assertEquals(ACTIVITY_TYPE_UNDEFINED, info2.topActivityType);
458
459 DisplayContent dc = mWm.mRoot.getDisplayContent(Display.DEFAULT_DISPLAY);
Louis Changa009c762020-02-26 11:21:31 +0800460 List<Task> infos = getTasksCreatedByOrganizer(dc);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800461 assertEquals(2, infos.size());
462
463 assertTrue(mWm.mAtmService.mTaskOrganizerController.deleteRootTask(info1.token));
Louis Changa009c762020-02-26 11:21:31 +0800464 infos = getTasksCreatedByOrganizer(dc);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800465 assertEquals(1, infos.size());
466 assertEquals(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, infos.get(0).getWindowingMode());
467 }
468
469 @Test
470 public void testTileAddRemoveChild() {
Louis Changa009c762020-02-26 11:21:31 +0800471 ITaskOrganizer listener = new ITaskOrganizer.Stub() {
472 @Override
chaviw7de50002020-04-27 12:33:30 -0700473 public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { }
Louis Changa009c762020-02-26 11:21:31 +0800474
475 @Override
476 public void onTaskVanished(RunningTaskInfo container) { }
477
478 @Override
479 public void onTaskInfoChanged(RunningTaskInfo info) throws RemoteException {
480 }
Winson Chunga1f869d2020-03-21 23:02:48 -0700481
482 @Override
483 public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
484 }
Louis Changa009c762020-02-26 11:21:31 +0800485 };
486 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener,
487 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800488 RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
489 mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
490
491 final ActivityStack stack = createTaskStackOnDisplay(
492 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
493 assertEquals(mDisplayContent.getWindowingMode(), stack.getWindowingMode());
Louis Changa009c762020-02-26 11:21:31 +0800494 WindowContainerTransaction wct = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700495 wct.reparent(stack.mRemoteToken.toWindowContainerToken(), info1.token, true /* onTop */);
Louis Changa009c762020-02-26 11:21:31 +0800496 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800497 assertEquals(info1.configuration.windowConfiguration.getWindowingMode(),
498 stack.getWindowingMode());
499
500 // Info should reflect new membership
Louis Changa009c762020-02-26 11:21:31 +0800501 List<Task> infos = getTasksCreatedByOrganizer(mDisplayContent);
502 info1 = infos.get(0).getTaskInfo();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800503 assertEquals(ACTIVITY_TYPE_STANDARD, info1.topActivityType);
504
505 // Children inherit configuration
506 Rect newSize = new Rect(10, 10, 300, 300);
Louis Changa009c762020-02-26 11:21:31 +0800507 Task task1 = WindowContainer.fromBinder(info1.token.asBinder()).asTask();
508 Configuration c = new Configuration(task1.getRequestedOverrideConfiguration());
Evan Rosky0037e5f2019-11-05 10:26:24 -0800509 c.windowConfiguration.setBounds(newSize);
Riddle Hsudd49c632020-04-30 22:39:51 +0800510 doNothing().when(stack).adjustForMinimalTaskDimensions(any(), any(), any());
Louis Changa009c762020-02-26 11:21:31 +0800511 task1.onRequestedOverrideConfigurationChanged(c);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800512 assertEquals(newSize, stack.getBounds());
513
Louis Changa009c762020-02-26 11:21:31 +0800514 wct = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700515 wct.reparent(stack.mRemoteToken.toWindowContainerToken(), null, true /* onTop */);
Louis Changa009c762020-02-26 11:21:31 +0800516 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800517 assertEquals(mDisplayContent.getWindowingMode(), stack.getWindowingMode());
Louis Changa009c762020-02-26 11:21:31 +0800518 infos = getTasksCreatedByOrganizer(mDisplayContent);
519 info1 = infos.get(0).getTaskInfo();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800520 assertEquals(ACTIVITY_TYPE_UNDEFINED, info1.topActivityType);
521 }
522
523 @Test
524 public void testTaskInfoCallback() {
525 final ArrayList<RunningTaskInfo> lastReportedTiles = new ArrayList<>();
526 final boolean[] called = {false};
527 ITaskOrganizer listener = new ITaskOrganizer.Stub() {
528 @Override
chaviw7de50002020-04-27 12:33:30 -0700529 public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800530
531 @Override
Wale Ogunwaledec34082020-03-22 09:45:00 -0700532 public void onTaskVanished(RunningTaskInfo container) { }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800533
534 @Override
Evan Rosky0037e5f2019-11-05 10:26:24 -0800535 public void onTaskInfoChanged(RunningTaskInfo info) throws RemoteException {
536 lastReportedTiles.add(info);
537 called[0] = true;
538 }
Winson Chunga1f869d2020-03-21 23:02:48 -0700539
540 @Override
541 public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
542 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800543 };
544 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener,
545 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
546 RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
547 mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
548 lastReportedTiles.clear();
549 called[0] = false;
550
551 final ActivityStack stack = createTaskStackOnDisplay(
552 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
Louis Changa009c762020-02-26 11:21:31 +0800553 Task task1 = WindowContainer.fromBinder(info1.token.asBinder()).asTask();
554 WindowContainerTransaction wct = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700555 wct.reparent(stack.mRemoteToken.toWindowContainerToken(), info1.token, true /* onTop */);
Louis Changa009c762020-02-26 11:21:31 +0800556 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800557 assertTrue(called[0]);
558 assertEquals(ACTIVITY_TYPE_STANDARD, lastReportedTiles.get(0).topActivityType);
559
560 lastReportedTiles.clear();
561 called[0] = false;
562 final ActivityStack stack2 = createTaskStackOnDisplay(
563 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, mDisplayContent);
Louis Changa009c762020-02-26 11:21:31 +0800564 wct = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700565 wct.reparent(stack2.mRemoteToken.toWindowContainerToken(), info1.token, true /* onTop */);
Louis Changa009c762020-02-26 11:21:31 +0800566 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800567 assertTrue(called[0]);
568 assertEquals(ACTIVITY_TYPE_HOME, lastReportedTiles.get(0).topActivityType);
569
570 lastReportedTiles.clear();
571 called[0] = false;
Louis Changa009c762020-02-26 11:21:31 +0800572 task1.positionChildAt(POSITION_TOP, stack, false /* includingParents */);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800573 assertTrue(called[0]);
574 assertEquals(ACTIVITY_TYPE_STANDARD, lastReportedTiles.get(0).topActivityType);
575
576 lastReportedTiles.clear();
577 called[0] = false;
Louis Changa009c762020-02-26 11:21:31 +0800578 wct = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700579 wct.reparent(stack.mRemoteToken.toWindowContainerToken(), null, true /* onTop */);
580 wct.reparent(stack2.mRemoteToken.toWindowContainerToken(), null, true /* onTop */);
Louis Changa009c762020-02-26 11:21:31 +0800581 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800582 assertTrue(called[0]);
583 assertEquals(ACTIVITY_TYPE_UNDEFINED, lastReportedTiles.get(0).topActivityType);
584 }
585
Evan Roskya8fde152020-01-07 19:09:13 -0800586 @Test
587 public void testHierarchyTransaction() {
588 final ArrayMap<IBinder, RunningTaskInfo> lastReportedTiles = new ArrayMap<>();
589 ITaskOrganizer listener = new ITaskOrganizer.Stub() {
590 @Override
chaviw7de50002020-04-27 12:33:30 -0700591 public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { }
Evan Roskya8fde152020-01-07 19:09:13 -0800592
593 @Override
Wale Ogunwaledec34082020-03-22 09:45:00 -0700594 public void onTaskVanished(RunningTaskInfo container) { }
Evan Roskya8fde152020-01-07 19:09:13 -0800595
596 @Override
Evan Roskya8fde152020-01-07 19:09:13 -0800597 public void onTaskInfoChanged(RunningTaskInfo info) {
598 lastReportedTiles.put(info.token.asBinder(), info);
599 }
Winson Chunga1f869d2020-03-21 23:02:48 -0700600
601 @Override
602 public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
603 }
Evan Roskya8fde152020-01-07 19:09:13 -0800604 };
605 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(
Louis Changa009c762020-02-26 11:21:31 +0800606 listener, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
607 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(
Evan Roskya8fde152020-01-07 19:09:13 -0800608 listener, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
609 RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
Louis Changa009c762020-02-26 11:21:31 +0800610 mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
Evan Roskya8fde152020-01-07 19:09:13 -0800611 RunningTaskInfo info2 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
612 mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
613
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800614 final int initialRootTaskCount = mWm.mAtmService.mTaskOrganizerController.getRootTasks(
615 mDisplayContent.mDisplayId, null /* activityTypes */).size();
616
Evan Roskya8fde152020-01-07 19:09:13 -0800617 final ActivityStack stack = createTaskStackOnDisplay(
618 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
619 final ActivityStack stack2 = createTaskStackOnDisplay(
620 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, mDisplayContent);
621
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800622 // Check getRootTasks works
623 List<RunningTaskInfo> roots = mWm.mAtmService.mTaskOrganizerController.getRootTasks(
624 mDisplayContent.mDisplayId, null /* activityTypes */);
625 assertEquals(initialRootTaskCount + 2, roots.size());
626
Evan Roskya8fde152020-01-07 19:09:13 -0800627 lastReportedTiles.clear();
628 WindowContainerTransaction wct = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700629 wct.reparent(stack.mRemoteToken.toWindowContainerToken(), info1.token, true /* onTop */);
630 wct.reparent(stack2.mRemoteToken.toWindowContainerToken(), info2.token, true /* onTop */);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700631 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Roskya8fde152020-01-07 19:09:13 -0800632 assertFalse(lastReportedTiles.isEmpty());
633 assertEquals(ACTIVITY_TYPE_STANDARD,
634 lastReportedTiles.get(info1.token.asBinder()).topActivityType);
635 assertEquals(ACTIVITY_TYPE_HOME,
636 lastReportedTiles.get(info2.token.asBinder()).topActivityType);
637
638 lastReportedTiles.clear();
639 wct = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700640 wct.reparent(stack2.mRemoteToken.toWindowContainerToken(), info1.token, false /* onTop */);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700641 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Roskya8fde152020-01-07 19:09:13 -0800642 assertFalse(lastReportedTiles.isEmpty());
643 // Standard should still be on top of tile 1, so no change there
644 assertFalse(lastReportedTiles.containsKey(info1.token.asBinder()));
645 // But tile 2 has no children, so should become undefined
646 assertEquals(ACTIVITY_TYPE_UNDEFINED,
647 lastReportedTiles.get(info2.token.asBinder()).topActivityType);
648
649 // Check the getChildren call
650 List<RunningTaskInfo> children =
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800651 mWm.mAtmService.mTaskOrganizerController.getChildTasks(info1.token,
652 null /* activityTypes */);
Evan Roskya8fde152020-01-07 19:09:13 -0800653 assertEquals(2, children.size());
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800654 children = mWm.mAtmService.mTaskOrganizerController.getChildTasks(info2.token,
655 null /* activityTypes */);
Evan Roskya8fde152020-01-07 19:09:13 -0800656 assertEquals(0, children.size());
657
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800658 // Check that getRootTasks doesn't include children of tiles
659 roots = mWm.mAtmService.mTaskOrganizerController.getRootTasks(mDisplayContent.mDisplayId,
660 null /* activityTypes */);
661 assertEquals(initialRootTaskCount, roots.size());
662
Evan Roskya8fde152020-01-07 19:09:13 -0800663 lastReportedTiles.clear();
664 wct = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700665 wct.reorder(stack2.mRemoteToken.toWindowContainerToken(), true /* onTop */);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700666 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Roskya8fde152020-01-07 19:09:13 -0800667 // Home should now be on top. No change occurs in second tile, so not reported
668 assertEquals(1, lastReportedTiles.size());
669 assertEquals(ACTIVITY_TYPE_HOME,
670 lastReportedTiles.get(info1.token.asBinder()).topActivityType);
671 }
672
Louis Changa009c762020-02-26 11:21:31 +0800673 private List<Task> getTasksCreatedByOrganizer(DisplayContent dc) {
674 ArrayList<Task> out = new ArrayList<>();
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700675 for (int tdaNdx = dc.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
676 final TaskDisplayArea taskDisplayArea = dc.getTaskDisplayAreaAt(tdaNdx);
677 for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
678 final Task t = taskDisplayArea.getStackAt(sNdx);
679 if (t.mCreatedByOrganizer) out.add(t);
680 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800681 }
682 return out;
683 }
Robert Carre10ee3d2019-11-11 15:03:15 -0800684
685 @Test
686 public void testTrivialBLASTCallback() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700687 final ActivityStack stackController1 = createStack();
688 final Task task = createTask(stackController1);
Robert Carre10ee3d2019-11-11 15:03:15 -0800689 final ITaskOrganizer organizer = registerMockOrganizer();
690
Robert Carr8ccc4fc2020-03-13 10:48:49 -0700691 spyOn(task);
692 doReturn(true).when(task).isVisible();
693
Robert Carre10ee3d2019-11-11 15:03:15 -0800694 BLASTSyncEngine bse = new BLASTSyncEngine();
695
696 BLASTSyncEngine.TransactionReadyListener transactionListener =
chaviw6630d852020-04-15 19:06:56 -0700697 mock(BLASTSyncEngine.TransactionReadyListener.class);
Robert Carre10ee3d2019-11-11 15:03:15 -0800698
699 int id = bse.startSyncSet(transactionListener);
700 bse.addToSyncSet(id, task);
701 bse.setReady(id);
702 // Since this task has no windows the sync is trivial and completes immediately.
703 verify(transactionListener)
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700704 .onTransactionReady(anyInt(), any());
Robert Carre10ee3d2019-11-11 15:03:15 -0800705 }
706
707 @Test
Robert Carr8ccc4fc2020-03-13 10:48:49 -0700708 public void testOverlappingBLASTCallback() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700709 final ActivityStack stackController1 = createStack();
710 final Task task = createTask(stackController1);
Robert Carr8ccc4fc2020-03-13 10:48:49 -0700711 final ITaskOrganizer organizer = registerMockOrganizer();
712
713 spyOn(task);
714 doReturn(true).when(task).isVisible();
715 final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
716 makeWindowVisible(w);
717
718 BLASTSyncEngine bse = new BLASTSyncEngine();
719
720 BLASTSyncEngine.TransactionReadyListener transactionListener =
chaviw6630d852020-04-15 19:06:56 -0700721 mock(BLASTSyncEngine.TransactionReadyListener.class);
Robert Carr8ccc4fc2020-03-13 10:48:49 -0700722
723 int id = bse.startSyncSet(transactionListener);
724 assertEquals(true, bse.addToSyncSet(id, task));
725 bse.setReady(id);
726
727 int id2 = bse.startSyncSet(transactionListener);
728 // We should be rejected from the second sync since we are already
729 // in one.
730 assertEquals(false, bse.addToSyncSet(id2, task));
731 w.finishDrawing(null);
732 assertEquals(true, bse.addToSyncSet(id2, task));
733 bse.setReady(id2);
734 }
735
736 @Test
Robert Carre10ee3d2019-11-11 15:03:15 -0800737 public void testBLASTCallbackWithWindow() {
Robert Carrde96c8a2020-03-24 15:22:21 -0700738 final ActivityStack stackController1 = createStack();
739 final Task task = createTask(stackController1);
Robert Carre10ee3d2019-11-11 15:03:15 -0800740 final ITaskOrganizer organizer = registerMockOrganizer();
741 final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
Rob Carrcba6a722020-03-10 12:41:06 -0700742 makeWindowVisible(w);
Robert Carre10ee3d2019-11-11 15:03:15 -0800743
744 BLASTSyncEngine bse = new BLASTSyncEngine();
745
746 BLASTSyncEngine.TransactionReadyListener transactionListener =
chaviw6630d852020-04-15 19:06:56 -0700747 mock(BLASTSyncEngine.TransactionReadyListener.class);
Robert Carre10ee3d2019-11-11 15:03:15 -0800748
749 int id = bse.startSyncSet(transactionListener);
750 bse.addToSyncSet(id, task);
751 bse.setReady(id);
752 // Since we have a window we have to wait for it to draw to finish sync.
753 verify(transactionListener, never())
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700754 .onTransactionReady(anyInt(), any());
Robert Carre10ee3d2019-11-11 15:03:15 -0800755 w.finishDrawing(null);
756 verify(transactionListener)
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700757 .onTransactionReady(anyInt(), any());
Robert Carre10ee3d2019-11-11 15:03:15 -0800758 }
Robert Carrf6690d12020-02-04 14:16:21 -0800759
Rob Carr25376512020-03-09 15:23:19 -0700760 @Test
Rob Carrcba6a722020-03-10 12:41:06 -0700761 public void testBLASTCallbackWithInvisibleWindow() {
Robert Carrde96c8a2020-03-24 15:22:21 -0700762 final ActivityStack stackController1 = createStack();
763 final Task task = createTask(stackController1);
Rob Carrcba6a722020-03-10 12:41:06 -0700764 final ITaskOrganizer organizer = registerMockOrganizer();
765 final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
766
767 BLASTSyncEngine bse = new BLASTSyncEngine();
768
769 BLASTSyncEngine.TransactionReadyListener transactionListener =
chaviw6630d852020-04-15 19:06:56 -0700770 mock(BLASTSyncEngine.TransactionReadyListener.class);
Rob Carrcba6a722020-03-10 12:41:06 -0700771
772 int id = bse.startSyncSet(transactionListener);
773 bse.addToSyncSet(id, task);
774 bse.setReady(id);
775
776 // Since the window was invisible, the Task had no visible leaves and the sync should
777 // complete as soon as we call setReady.
778 verify(transactionListener)
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700779 .onTransactionReady(anyInt(), any());
Rob Carrcba6a722020-03-10 12:41:06 -0700780 }
781
782 @Test
Rob Carr25376512020-03-09 15:23:19 -0700783 public void testBLASTCallbackWithChildWindow() {
Robert Carrde96c8a2020-03-24 15:22:21 -0700784 final ActivityStack stackController1 = createStack();
785 final Task task = createTask(stackController1);
Rob Carr25376512020-03-09 15:23:19 -0700786 final ITaskOrganizer organizer = registerMockOrganizer();
787 final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
788 final WindowState child = createWindow(w, TYPE_APPLICATION, "Other Window");
789
790 w.mActivityRecord.setVisible(true);
791 makeWindowVisible(w, child);
792
793 BLASTSyncEngine bse = new BLASTSyncEngine();
794
795 BLASTSyncEngine.TransactionReadyListener transactionListener =
chaviw6630d852020-04-15 19:06:56 -0700796 mock(BLASTSyncEngine.TransactionReadyListener.class);
Rob Carr25376512020-03-09 15:23:19 -0700797
798 int id = bse.startSyncSet(transactionListener);
799 assertEquals(true, bse.addToSyncSet(id, task));
800 bse.setReady(id);
801 w.finishDrawing(null);
802
803 // Since we have a child window we still shouldn't be done.
804 verify(transactionListener, never())
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700805 .onTransactionReady(anyInt(), any());
Rob Carr25376512020-03-09 15:23:19 -0700806 reset(transactionListener);
807
808 child.finishDrawing(null);
809 // Ah finally! Done
810 verify(transactionListener)
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700811 .onTransactionReady(anyInt(), any());
Rob Carr25376512020-03-09 15:23:19 -0700812 }
813
Robert Carrf6690d12020-02-04 14:16:21 -0800814 class StubOrganizer extends ITaskOrganizer.Stub {
815 RunningTaskInfo mInfo;
816
817 @Override
chaviw7de50002020-04-27 12:33:30 -0700818 public void onTaskAppeared(RunningTaskInfo info, SurfaceControl leash) {
Robert Carrf6690d12020-02-04 14:16:21 -0800819 mInfo = info;
820 }
821 @Override
Wale Ogunwaledec34082020-03-22 09:45:00 -0700822 public void onTaskVanished(RunningTaskInfo info) {
Robert Carrf6690d12020-02-04 14:16:21 -0800823 }
824 @Override
Robert Carrf6690d12020-02-04 14:16:21 -0800825 public void onTaskInfoChanged(RunningTaskInfo info) {
826 }
Winson Chunga1f869d2020-03-21 23:02:48 -0700827 @Override
828 public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
829 }
Robert Carrf6690d12020-02-04 14:16:21 -0800830 };
831
832 private ActivityRecord makePipableActivity() {
833 final ActivityRecord record = createActivityRecord(mDisplayContent,
834 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
835 record.info.flags |= ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
836 spyOn(record);
837 doReturn(true).when(record).checkEnterPictureInPictureState(any(), anyBoolean());
Robert Carrde96c8a2020-03-24 15:22:21 -0700838
Jorim Jaggi785edb42020-05-08 12:34:47 +0000839 record.getRootTask().setHasBeenVisible(true);
Robert Carrf6690d12020-02-04 14:16:21 -0800840 return record;
841 }
842
843 @Test
844 public void testEnterPipParams() {
845 final StubOrganizer o = new StubOrganizer();
846 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(o, WINDOWING_MODE_PINNED);
847 final ActivityRecord record = makePipableActivity();
848
chaviw6630d852020-04-15 19:06:56 -0700849 final PictureInPictureParams p = new PictureInPictureParams.Builder()
850 .setAspectRatio(new Rational(1, 2)).build();
Robert Carrf6690d12020-02-04 14:16:21 -0800851 assertTrue(mWm.mAtmService.enterPictureInPictureMode(record.token, p));
852 waitUntilHandlersIdle();
853 assertNotNull(o.mInfo);
854 assertNotNull(o.mInfo.pictureInPictureParams);
855 }
856
857 @Test
858 public void testChangePipParams() {
859 class ChangeSavingOrganizer extends StubOrganizer {
860 RunningTaskInfo mChangedInfo;
861 @Override
862 public void onTaskInfoChanged(RunningTaskInfo info) {
863 mChangedInfo = info;
864 }
865 }
866 ChangeSavingOrganizer o = new ChangeSavingOrganizer();
867 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(o, WINDOWING_MODE_PINNED);
868
869 final ActivityRecord record = makePipableActivity();
chaviw6630d852020-04-15 19:06:56 -0700870 final PictureInPictureParams p = new PictureInPictureParams.Builder()
871 .setAspectRatio(new Rational(1, 2)).build();
Robert Carrf6690d12020-02-04 14:16:21 -0800872 assertTrue(mWm.mAtmService.enterPictureInPictureMode(record.token, p));
873 waitUntilHandlersIdle();
874 assertNotNull(o.mInfo);
875 assertNotNull(o.mInfo.pictureInPictureParams);
876
chaviw6630d852020-04-15 19:06:56 -0700877 final PictureInPictureParams p2 = new PictureInPictureParams.Builder()
878 .setAspectRatio(new Rational(3, 4)).build();
Robert Carrf6690d12020-02-04 14:16:21 -0800879 mWm.mAtmService.setPictureInPictureParams(record.token, p2);
880 waitUntilHandlersIdle();
881 assertNotNull(o.mChangedInfo);
882 assertNotNull(o.mChangedInfo.pictureInPictureParams);
883 final Rational ratio = o.mChangedInfo.pictureInPictureParams.getAspectRatioRational();
884 assertEquals(3, ratio.getNumerator());
885 assertEquals(4, ratio.getDenominator());
886 }
Robert Carrde96c8a2020-03-24 15:22:21 -0700887
888 @Test
Winson Chung1df39e22020-04-09 14:30:55 -0700889 public void testChangeTaskDescription() {
890 class ChangeSavingOrganizer extends StubOrganizer {
891 RunningTaskInfo mChangedInfo;
892 @Override
893 public void onTaskInfoChanged(RunningTaskInfo info) {
894 mChangedInfo = info;
895 }
896 }
897 ChangeSavingOrganizer o = new ChangeSavingOrganizer();
898 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(o,
899 WINDOWING_MODE_MULTI_WINDOW);
900
901 final ActivityStack stack = createStack();
902 final Task task = createTask(stack);
903 final ActivityRecord record = WindowTestUtils.createActivityRecordInTask(
904 stack.mDisplayContent, task);
905
906 stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
907 record.setTaskDescription(new ActivityManager.TaskDescription("TestDescription"));
908 waitUntilHandlersIdle();
909 assertEquals("TestDescription", o.mChangedInfo.taskDescription.getLabel());
910 }
911
912 @Test
Robert Carrde96c8a2020-03-24 15:22:21 -0700913 public void testPreventDuplicateAppear() throws RemoteException {
914 final ActivityStack stack = createStack();
915 final Task task = createTask(stack);
916 final ITaskOrganizer organizer = registerMockOrganizer();
917
918 task.setTaskOrganizer(organizer);
919 // setHasBeenVisible was already called once by the set-up code.
920 task.setHasBeenVisible(true);
chaviw7de50002020-04-27 12:33:30 -0700921 verify(organizer, times(1))
922 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carrde96c8a2020-03-24 15:22:21 -0700923
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700924 task.setTaskOrganizer(null);
925 verify(organizer, times(1)).onTaskVanished(any());
Robert Carrde96c8a2020-03-24 15:22:21 -0700926 task.setTaskOrganizer(organizer);
chaviw7de50002020-04-27 12:33:30 -0700927 verify(organizer, times(2))
928 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carrde96c8a2020-03-24 15:22:21 -0700929
930 task.removeImmediately();
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700931 verify(organizer, times(2)).onTaskVanished(any());
Robert Carrde96c8a2020-03-24 15:22:21 -0700932 }
Winson Chunga1f869d2020-03-21 23:02:48 -0700933
934 @Test
935 public void testInterceptBackPressedOnTaskRoot() throws RemoteException {
936 final ActivityStack stack = createStack();
937 final Task task = createTask(stack);
938 final ActivityRecord activity = WindowTestUtils.createActivityRecordInTask(
939 stack.mDisplayContent, task);
940 final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
941
942 // Setup the task to be controlled by the MW mode organizer
943 stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
944 assertTrue(stack.isOrganized());
945
946 // Verify a back pressed does not call the organizer
947 mWm.mAtmService.onBackPressedOnTaskRoot(activity.token,
948 new IRequestFinishCallback.Default());
949 verify(organizer, never()).onBackPressedOnTaskRoot(any());
950
951 // Enable intercepting back
952 mWm.mAtmService.mTaskOrganizerController.setInterceptBackPressedOnTaskRoot(organizer,
953 true);
954
955 // Verify now that the back press does call the organizer
956 mWm.mAtmService.onBackPressedOnTaskRoot(activity.token,
957 new IRequestFinishCallback.Default());
958 verify(organizer, times(1)).onBackPressedOnTaskRoot(any());
959 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800960}