blob: 341e20946c3000d1c610595d06cce989ee97a2d9 [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;
chaviw54521692020-06-12 14:34:30 -070070import android.window.IWindowContainerTransactionCallback;
Wale Ogunwale57946582020-03-21 14:29:07 -070071import android.window.WindowContainerTransaction;
Robert Carr8a2f9132019-11-11 15:03:15 -080072
73import androidx.test.filters.SmallTest;
74
Winson Chung1b5d0552020-04-06 19:28:49 -070075import org.junit.Before;
Robert Carr8a2f9132019-11-11 15:03:15 -080076import org.junit.Test;
77import org.junit.runner.RunWith;
78
Evan Rosky0037e5f2019-11-05 10:26:24 -080079import java.util.ArrayList;
80import java.util.List;
81
Robert Carr8a2f9132019-11-11 15:03:15 -080082/**
Wale Ogunwale57946582020-03-21 14:29:07 -070083 * Test class for {@link ITaskOrganizer} and {@link android.window.ITaskOrganizerController}.
Robert Carr8a2f9132019-11-11 15:03:15 -080084 *
85 * Build/Install/Run:
Wale Ogunwale20ab6d42020-04-13 07:30:59 -070086 * atest WmTests:WindowOrganizerTests
Robert Carr8a2f9132019-11-11 15:03:15 -080087 */
88@SmallTest
89@Presubmit
90@RunWith(WindowTestRunner.class)
chaviw6630d852020-04-15 19:06:56 -070091public class WindowOrganizerTests extends WindowTestsBase {
Robert Carr00c0dbe2020-01-24 15:30:24 -080092 private ITaskOrganizer registerMockOrganizer(int windowingMode) {
Robert Carr8a2f9132019-11-11 15:03:15 -080093 final ITaskOrganizer organizer = mock(ITaskOrganizer.class);
94 when(organizer.asBinder()).thenReturn(new Binder());
95
Evan Rosky0037e5f2019-11-05 10:26:24 -080096 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(
97 organizer, windowingMode);
Robert Carr8a2f9132019-11-11 15:03:15 -080098
99 return organizer;
100 }
101
Robert Carr00c0dbe2020-01-24 15:30:24 -0800102 private ITaskOrganizer registerMockOrganizer() {
103 return registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
104 }
105
Robert Carrde96c8a2020-03-24 15:22:21 -0700106 Task createTask(ActivityStack stack, boolean fakeDraw) {
107 final Task task = createTaskInStack(stack, 0);
108
109 if (fakeDraw) {
110 task.setHasBeenVisible(true);
111 }
112 return task;
113 }
114
115 Task createTask(ActivityStack stack) {
116 // Fake draw notifications for most of our tests.
117 return createTask(stack, true);
118 }
119
120 ActivityStack createStack() {
121 return createTaskStackOnDisplay(mDisplayContent);
122 }
123
Winson Chung1b5d0552020-04-06 19:28:49 -0700124 @Before
125 public void setUp() {
126 // We defer callbacks since we need to adjust task surface visibility, but for these tests,
127 // just run the callbacks synchronously
128 mWm.mAtmService.mTaskOrganizerController.setDeferTaskOrgCallbacksConsumer((r) -> r.run());
129 }
130
Robert Carr8a2f9132019-11-11 15:03:15 -0800131 @Test
132 public void testAppearVanish() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700133 final ActivityStack stack = createStack();
134 final Task task = createTask(stack);
Robert Carr00c0dbe2020-01-24 15:30:24 -0800135 final ITaskOrganizer organizer = registerMockOrganizer();
Robert Carr8a2f9132019-11-11 15:03:15 -0800136
137 task.setTaskOrganizer(organizer);
chaviw7de50002020-04-27 12:33:30 -0700138 verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
139
Robert Carr8a2f9132019-11-11 15:03:15 -0800140
141 task.removeImmediately();
Wale Ogunwaledec34082020-03-22 09:45:00 -0700142 verify(organizer).onTaskVanished(any());
Robert Carr8a2f9132019-11-11 15:03:15 -0800143 }
144
145 @Test
Robert Carrde96c8a2020-03-24 15:22:21 -0700146 public void testAppearWaitsForVisibility() throws RemoteException {
147 final ActivityStack stack = createStack();
148 final Task task = createTask(stack, false);
149 final ITaskOrganizer organizer = registerMockOrganizer();
150
151 task.setTaskOrganizer(organizer);
152
chaviw7de50002020-04-27 12:33:30 -0700153 verify(organizer, never())
154 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carrde96c8a2020-03-24 15:22:21 -0700155 task.setHasBeenVisible(true);
156 assertTrue(stack.getHasBeenVisible());
157
chaviw7de50002020-04-27 12:33:30 -0700158 verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carrde96c8a2020-03-24 15:22:21 -0700159
160 task.removeImmediately();
161 verify(organizer).onTaskVanished(any());
162 }
163
164 @Test
165 public void testNoVanishedIfNoAppear() throws RemoteException {
166 final ActivityStack stack = createStack();
167 final Task task = createTask(stack, false /* hasBeenVisible */);
168 final ITaskOrganizer organizer = registerMockOrganizer();
169
170 // In this test we skip making the Task visible, and verify
171 // that even though a TaskOrganizer is set remove doesn't emit
172 // a vanish callback, because we never emitted appear.
173 task.setTaskOrganizer(organizer);
chaviw7de50002020-04-27 12:33:30 -0700174 verify(organizer, never())
175 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carrde96c8a2020-03-24 15:22:21 -0700176 task.removeImmediately();
177 verify(organizer, never()).onTaskVanished(any());
178 }
179
180 @Test
Robert Carr8a2f9132019-11-11 15:03:15 -0800181 public void testSwapOrganizer() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700182 final ActivityStack stack = createStack();
183 final Task task = createTask(stack);
Robert Carr00c0dbe2020-01-24 15:30:24 -0800184 final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
185 final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED);
Robert Carr8a2f9132019-11-11 15:03:15 -0800186
187 task.setTaskOrganizer(organizer);
chaviw7de50002020-04-27 12:33:30 -0700188 verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carr8a2f9132019-11-11 15:03:15 -0800189 task.setTaskOrganizer(organizer2);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700190 verify(organizer).onTaskVanished(any());
chaviw7de50002020-04-27 12:33:30 -0700191 verify(organizer2).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carr8a2f9132019-11-11 15:03:15 -0800192 }
193
194 @Test
Robert Carr00c0dbe2020-01-24 15:30:24 -0800195 public void testSwapWindowingModes() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700196 final ActivityStack stack = createStack();
197 final Task task = createTask(stack);
Robert Carr00c0dbe2020-01-24 15:30:24 -0800198 final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
199 final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_PINNED);
Rob Carrab179782020-03-10 12:50:30 -0700200
Robert Carr00c0dbe2020-01-24 15:30:24 -0800201 stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
chaviw7de50002020-04-27 12:33:30 -0700202 verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carr00c0dbe2020-01-24 15:30:24 -0800203 stack.setWindowingMode(WINDOWING_MODE_PINNED);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700204 verify(organizer).onTaskVanished(any());
chaviw7de50002020-04-27 12:33:30 -0700205 verify(organizer2).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carr00c0dbe2020-01-24 15:30:24 -0800206 }
207
208 @Test
Louis Chang9d35a3a2020-04-06 17:23:02 +0800209 public void testTaskNoDraw() throws RemoteException {
210 final ActivityStack stack = createStack();
211 final Task task = createTask(stack, false /* fakeDraw */);
212 final ITaskOrganizer organizer = registerMockOrganizer();
213
214 stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
chaviw7de50002020-04-27 12:33:30 -0700215 verify(organizer, never())
216 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Louis Chang9d35a3a2020-04-06 17:23:02 +0800217 assertTrue(stack.isOrganized());
218
219 mWm.mAtmService.mTaskOrganizerController.unregisterTaskOrganizer(organizer);
220 verify(organizer, never()).onTaskVanished(any());
221 assertFalse(stack.isOrganized());
222 }
223
224 @Test
Robert Carr8a2f9132019-11-11 15:03:15 -0800225 public void testClearOrganizer() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700226 final ActivityStack stack = createStack();
227 final Task task = createTask(stack);
Robert Carr00c0dbe2020-01-24 15:30:24 -0800228 final ITaskOrganizer organizer = registerMockOrganizer();
Robert Carr8a2f9132019-11-11 15:03:15 -0800229
Robert Carr9fd095b2020-01-24 14:40:06 -0800230 stack.setTaskOrganizer(organizer);
chaviw7de50002020-04-27 12:33:30 -0700231 verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Wale Ogunwaledec34082020-03-22 09:45:00 -0700232 assertTrue(stack.isOrganized());
Robert Carr8a2f9132019-11-11 15:03:15 -0800233
Robert Carr9fd095b2020-01-24 14:40:06 -0800234 stack.setTaskOrganizer(null);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700235 verify(organizer).onTaskVanished(any());
236 assertFalse(stack.isOrganized());
Robert Carr8a2f9132019-11-11 15:03:15 -0800237 }
238
239 @Test
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800240 public void testUnregisterOrganizer() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700241 final ActivityStack stack = createStack();
242 final Task task = createTask(stack);
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800243 final ITaskOrganizer organizer = registerMockOrganizer();
244
245 stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
chaviw7de50002020-04-27 12:33:30 -0700246 verify(organizer).onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Wale Ogunwaledec34082020-03-22 09:45:00 -0700247 assertTrue(stack.isOrganized());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800248
249 mWm.mAtmService.mTaskOrganizerController.unregisterTaskOrganizer(organizer);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700250 verify(organizer).onTaskVanished(any());
251 assertFalse(stack.isOrganized());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800252 }
253
254 @Test
255 public void testUnregisterOrganizerReturnsRegistrationToPrevious() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700256 final ActivityStack stack = createStack();
257 final Task task = createTask(stack);
258 final ActivityStack stack2 = createStack();
259 final Task task2 = createTask(stack2);
260 final ActivityStack stack3 = createStack();
261 final Task task3 = createTask(stack3);
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800262 final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
263
264 // First organizer is registered, verify a task appears when changing windowing mode
265 stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
chaviw7de50002020-04-27 12:33:30 -0700266 verify(organizer, times(1))
267 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Wale Ogunwaledec34082020-03-22 09:45:00 -0700268 assertTrue(stack.isOrganized());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800269
270 // Now we replace the registration and1 verify the new organizer receives tasks
271 // newly entering the windowing mode.
272 final ITaskOrganizer organizer2 = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
273 stack2.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700274 // One each for task and task2
chaviw7de50002020-04-27 12:33:30 -0700275 verify(organizer2, times(2))
276 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700277 verify(organizer2, times(0)).onTaskVanished(any());
278 // One for task
279 verify(organizer).onTaskVanished(any());
Wale Ogunwaledec34082020-03-22 09:45:00 -0700280 assertTrue(stack2.isOrganized());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800281
282 // Now we unregister the second one, the first one should automatically be reregistered
283 // so we verify that it's now seeing changes.
284 mWm.mAtmService.mTaskOrganizerController.unregisterTaskOrganizer(organizer2);
chaviw7de50002020-04-27 12:33:30 -0700285 verify(organizer, times(3))
286 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700287 verify(organizer2, times(2)).onTaskVanished(any());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800288
289 stack3.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
chaviw7de50002020-04-27 12:33:30 -0700290 verify(organizer, times(4))
291 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700292 verify(organizer2, times(2)).onTaskVanished(any());
Wale Ogunwaledec34082020-03-22 09:45:00 -0700293 assertTrue(stack3.isOrganized());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800294 }
295
296 @Test
Robert Carr8a2f9132019-11-11 15:03:15 -0800297 public void testRegisterTaskOrganizerStackWindowingModeChanges() throws RemoteException {
Robert Carr00c0dbe2020-01-24 15:30:24 -0800298 final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED);
Robert Carr8a2f9132019-11-11 15:03:15 -0800299
Robert Carrde96c8a2020-03-24 15:22:21 -0700300 final ActivityStack stack = createStack();
301 final Task task = createTask(stack);
302 final Task task2 = createTask(stack);
Robert Carr8a2f9132019-11-11 15:03:15 -0800303 stack.setWindowingMode(WINDOWING_MODE_PINNED);
chaviw7de50002020-04-27 12:33:30 -0700304 verify(organizer, times(1))
305 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carr8a2f9132019-11-11 15:03:15 -0800306
307 stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
Wale Ogunwaledec34082020-03-22 09:45:00 -0700308 verify(organizer, times(1)).onTaskVanished(any());
Robert Carr8a2f9132019-11-11 15:03:15 -0800309 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800310
311 @Test
Winson Chung77338ab2020-03-09 16:32:34 -0700312 public void testRegisterTaskOrganizerWithExistingTasks() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700313 final ActivityStack stack = createStack();
314 final Task task = createTask(stack);
Winson Chung77338ab2020-03-09 16:32:34 -0700315 stack.setWindowingMode(WINDOWING_MODE_PINNED);
316
317 final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_PINNED);
chaviw7de50002020-04-27 12:33:30 -0700318 verify(organizer, times(1))
319 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Winson Chung77338ab2020-03-09 16:32:34 -0700320 }
321
322 @Test
Evan Rosky0037e5f2019-11-05 10:26:24 -0800323 public void testTaskTransaction() {
324 removeGlobalMinSizeRestriction();
325 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
326 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
327 final Task task = stack.getTopMostTask();
chaviw6630d852020-04-15 19:06:56 -0700328 testTransaction(task);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800329 }
330
331 @Test
332 public void testStackTransaction() {
333 removeGlobalMinSizeRestriction();
334 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
335 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
336 StackInfo info =
337 mWm.mAtmService.getStackInfo(WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD);
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700338 assertEquals(stack.mRemoteToken.toWindowContainerToken(), info.stackToken);
chaviw6630d852020-04-15 19:06:56 -0700339 testTransaction(stack);
340 }
341
342 @Test
343 public void testDisplayAreaTransaction() {
344 removeGlobalMinSizeRestriction();
345 final DisplayArea displayArea = new DisplayArea<>(mWm, ABOVE_TASKS, "DisplayArea");
346 testTransaction(displayArea);
347 }
348
349 private void testTransaction(WindowContainer wc) {
350 WindowContainerTransaction t = new WindowContainerTransaction();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800351 Rect newBounds = new Rect(10, 10, 100, 100);
chaviw6630d852020-04-15 19:06:56 -0700352 t.setBounds(wc.mRemoteToken.toWindowContainerToken(), new Rect(10, 10, 100, 100));
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700353 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
chaviw6630d852020-04-15 19:06:56 -0700354 assertEquals(newBounds, wc.getBounds());
Evan Rosky0037e5f2019-11-05 10:26:24 -0800355 }
356
357 @Test
Robert Carr2bed6212020-02-20 16:55:07 -0800358 public void testSetWindowingMode() {
359 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
chaviw6630d852020-04-15 19:06:56 -0700360 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
361 testSetWindowingMode(stack);
362
363 final DisplayArea displayArea = new DisplayArea<>(mWm, ABOVE_TASKS, "DisplayArea");
364 displayArea.setWindowingMode(WINDOWING_MODE_FREEFORM);
365 testSetWindowingMode(displayArea);
366 }
367
368 private void testSetWindowingMode(WindowContainer wc) {
Robert Carr2bed6212020-02-20 16:55:07 -0800369 final WindowContainerTransaction t = new WindowContainerTransaction();
chaviw6630d852020-04-15 19:06:56 -0700370 t.setWindowingMode(wc.mRemoteToken.toWindowContainerToken(), WINDOWING_MODE_FULLSCREEN);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700371 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
chaviw6630d852020-04-15 19:06:56 -0700372 assertEquals(WINDOWING_MODE_FULLSCREEN, wc.getWindowingMode());
Robert Carr2bed6212020-02-20 16:55:07 -0800373 }
374
375 @Test
376 public void testSetActivityWindowingMode() {
377 final ActivityRecord record = makePipableActivity();
378 final ActivityStack stack = record.getStack();
379 final WindowContainerTransaction t = new WindowContainerTransaction();
380
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700381 t.setWindowingMode(stack.mRemoteToken.toWindowContainerToken(), WINDOWING_MODE_PINNED);
382 t.setActivityWindowingMode(
383 stack.mRemoteToken.toWindowContainerToken(), WINDOWING_MODE_FULLSCREEN);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700384 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Robert Carr2bed6212020-02-20 16:55:07 -0800385
386 assertEquals(WINDOWING_MODE_FULLSCREEN, record.getWindowingMode());
387 assertEquals(WINDOWING_MODE_PINNED, stack.getWindowingMode());
388 }
389
390 @Test
Robert Carrf6878a42019-12-18 02:13:12 -0800391 public void testContainerFocusableChanges() {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800392 removeGlobalMinSizeRestriction();
393 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
394 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
395 final Task task = stack.getTopMostTask();
396 WindowContainerTransaction t = new WindowContainerTransaction();
397 assertTrue(task.isFocusable());
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700398 t.setFocusable(stack.mRemoteToken.toWindowContainerToken(), false);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700399 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800400 assertFalse(task.isFocusable());
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700401 t.setFocusable(stack.mRemoteToken.toWindowContainerToken(), true);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700402 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Robert Carrf6878a42019-12-18 02:13:12 -0800403 assertTrue(task.isFocusable());
404 }
405
406 @Test
407 public void testContainerHiddenChanges() {
408 removeGlobalMinSizeRestriction();
409 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
410 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
411 WindowContainerTransaction t = new WindowContainerTransaction();
412 assertTrue(stack.shouldBeVisible(null));
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700413 t.setHidden(stack.mRemoteToken.toWindowContainerToken(), true);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700414 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Robert Carrf6878a42019-12-18 02:13:12 -0800415 assertFalse(stack.shouldBeVisible(null));
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700416 t.setHidden(stack.mRemoteToken.toWindowContainerToken(), false);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700417 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Robert Carrf6878a42019-12-18 02:13:12 -0800418 assertTrue(stack.shouldBeVisible(null));
Evan Rosky0037e5f2019-11-05 10:26:24 -0800419 }
420
421 @Test
Evan Rosky05ec8862020-02-28 19:37:04 -0800422 public void testOverrideConfigSize() {
423 removeGlobalMinSizeRestriction();
424 final ActivityStack stack = new ActivityTestsBase.StackBuilder(mWm.mRoot)
425 .setWindowingMode(WINDOWING_MODE_FREEFORM).build();
426 final Task task = stack.getTopMostTask();
427 WindowContainerTransaction t = new WindowContainerTransaction();
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700428 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Evan Rosky05ec8862020-02-28 19:37:04 -0800429 final int origScreenWDp = task.getConfiguration().screenHeightDp;
430 final int origScreenHDp = task.getConfiguration().screenHeightDp;
431 t = new WindowContainerTransaction();
432 // verify that setting config overrides on parent restricts children.
chaviw6630d852020-04-15 19:06:56 -0700433 t.setScreenSizeDp(stack.mRemoteToken
Evan Roskyc440b4e2020-04-17 15:11:22 -0700434 .toWindowContainerToken(), origScreenWDp, origScreenHDp / 2);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700435 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Evan Roskyc440b4e2020-04-17 15:11:22 -0700436 assertEquals(origScreenHDp / 2, task.getConfiguration().screenHeightDp);
Evan Rosky05ec8862020-02-28 19:37:04 -0800437 t = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700438 t.setScreenSizeDp(stack.mRemoteToken.toWindowContainerToken(), SCREEN_WIDTH_DP_UNDEFINED,
439 SCREEN_HEIGHT_DP_UNDEFINED);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700440 mWm.mAtmService.mWindowOrganizerController.applyTransaction(t);
Evan Roskyc440b4e2020-04-17 15:11:22 -0700441 assertEquals(origScreenHDp, task.getConfiguration().screenHeightDp);
Evan Rosky05ec8862020-02-28 19:37:04 -0800442 }
443
444 @Test
Evan Rosky0037e5f2019-11-05 10:26:24 -0800445 public void testCreateDeleteRootTasks() {
446 RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
447 Display.DEFAULT_DISPLAY,
448 WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
449 assertEquals(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
450 info1.configuration.windowConfiguration.getWindowingMode());
451 assertEquals(ACTIVITY_TYPE_UNDEFINED, info1.topActivityType);
452
453 RunningTaskInfo info2 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
454 Display.DEFAULT_DISPLAY,
455 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
456 assertEquals(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
457 info2.configuration.windowConfiguration.getWindowingMode());
458 assertEquals(ACTIVITY_TYPE_UNDEFINED, info2.topActivityType);
459
460 DisplayContent dc = mWm.mRoot.getDisplayContent(Display.DEFAULT_DISPLAY);
Louis Changa009c762020-02-26 11:21:31 +0800461 List<Task> infos = getTasksCreatedByOrganizer(dc);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800462 assertEquals(2, infos.size());
463
464 assertTrue(mWm.mAtmService.mTaskOrganizerController.deleteRootTask(info1.token));
Louis Changa009c762020-02-26 11:21:31 +0800465 infos = getTasksCreatedByOrganizer(dc);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800466 assertEquals(1, infos.size());
467 assertEquals(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, infos.get(0).getWindowingMode());
468 }
469
470 @Test
471 public void testTileAddRemoveChild() {
Louis Changa009c762020-02-26 11:21:31 +0800472 ITaskOrganizer listener = new ITaskOrganizer.Stub() {
473 @Override
chaviw7de50002020-04-27 12:33:30 -0700474 public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { }
Louis Changa009c762020-02-26 11:21:31 +0800475
476 @Override
477 public void onTaskVanished(RunningTaskInfo container) { }
478
479 @Override
480 public void onTaskInfoChanged(RunningTaskInfo info) throws RemoteException {
481 }
Winson Chunga1f869d2020-03-21 23:02:48 -0700482
483 @Override
484 public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
485 }
Louis Changa009c762020-02-26 11:21:31 +0800486 };
487 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener,
488 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800489 RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
490 mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
491
492 final ActivityStack stack = createTaskStackOnDisplay(
493 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
494 assertEquals(mDisplayContent.getWindowingMode(), stack.getWindowingMode());
Louis Changa009c762020-02-26 11:21:31 +0800495 WindowContainerTransaction wct = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700496 wct.reparent(stack.mRemoteToken.toWindowContainerToken(), info1.token, true /* onTop */);
Louis Changa009c762020-02-26 11:21:31 +0800497 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800498 assertEquals(info1.configuration.windowConfiguration.getWindowingMode(),
499 stack.getWindowingMode());
500
501 // Info should reflect new membership
Louis Changa009c762020-02-26 11:21:31 +0800502 List<Task> infos = getTasksCreatedByOrganizer(mDisplayContent);
503 info1 = infos.get(0).getTaskInfo();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800504 assertEquals(ACTIVITY_TYPE_STANDARD, info1.topActivityType);
505
506 // Children inherit configuration
507 Rect newSize = new Rect(10, 10, 300, 300);
Louis Changa009c762020-02-26 11:21:31 +0800508 Task task1 = WindowContainer.fromBinder(info1.token.asBinder()).asTask();
509 Configuration c = new Configuration(task1.getRequestedOverrideConfiguration());
Evan Rosky0037e5f2019-11-05 10:26:24 -0800510 c.windowConfiguration.setBounds(newSize);
Riddle Hsudd49c632020-04-30 22:39:51 +0800511 doNothing().when(stack).adjustForMinimalTaskDimensions(any(), any(), any());
Louis Changa009c762020-02-26 11:21:31 +0800512 task1.onRequestedOverrideConfigurationChanged(c);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800513 assertEquals(newSize, stack.getBounds());
514
Louis Changa009c762020-02-26 11:21:31 +0800515 wct = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700516 wct.reparent(stack.mRemoteToken.toWindowContainerToken(), null, true /* onTop */);
Louis Changa009c762020-02-26 11:21:31 +0800517 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800518 assertEquals(mDisplayContent.getWindowingMode(), stack.getWindowingMode());
Louis Changa009c762020-02-26 11:21:31 +0800519 infos = getTasksCreatedByOrganizer(mDisplayContent);
520 info1 = infos.get(0).getTaskInfo();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800521 assertEquals(ACTIVITY_TYPE_UNDEFINED, info1.topActivityType);
522 }
523
524 @Test
525 public void testTaskInfoCallback() {
526 final ArrayList<RunningTaskInfo> lastReportedTiles = new ArrayList<>();
527 final boolean[] called = {false};
528 ITaskOrganizer listener = new ITaskOrganizer.Stub() {
529 @Override
chaviw7de50002020-04-27 12:33:30 -0700530 public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800531
532 @Override
Wale Ogunwaledec34082020-03-22 09:45:00 -0700533 public void onTaskVanished(RunningTaskInfo container) { }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800534
535 @Override
Evan Rosky0037e5f2019-11-05 10:26:24 -0800536 public void onTaskInfoChanged(RunningTaskInfo info) throws RemoteException {
537 lastReportedTiles.add(info);
538 called[0] = true;
539 }
Winson Chunga1f869d2020-03-21 23:02:48 -0700540
541 @Override
542 public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
543 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800544 };
545 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(listener,
546 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
547 RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
548 mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
549 lastReportedTiles.clear();
550 called[0] = false;
551
552 final ActivityStack stack = createTaskStackOnDisplay(
553 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
Louis Changa009c762020-02-26 11:21:31 +0800554 Task task1 = WindowContainer.fromBinder(info1.token.asBinder()).asTask();
555 WindowContainerTransaction wct = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700556 wct.reparent(stack.mRemoteToken.toWindowContainerToken(), info1.token, true /* onTop */);
Louis Changa009c762020-02-26 11:21:31 +0800557 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800558 assertTrue(called[0]);
559 assertEquals(ACTIVITY_TYPE_STANDARD, lastReportedTiles.get(0).topActivityType);
560
561 lastReportedTiles.clear();
562 called[0] = false;
563 final ActivityStack stack2 = createTaskStackOnDisplay(
564 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, mDisplayContent);
Louis Changa009c762020-02-26 11:21:31 +0800565 wct = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700566 wct.reparent(stack2.mRemoteToken.toWindowContainerToken(), info1.token, true /* onTop */);
Louis Changa009c762020-02-26 11:21:31 +0800567 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800568 assertTrue(called[0]);
569 assertEquals(ACTIVITY_TYPE_HOME, lastReportedTiles.get(0).topActivityType);
570
571 lastReportedTiles.clear();
572 called[0] = false;
Louis Changa009c762020-02-26 11:21:31 +0800573 task1.positionChildAt(POSITION_TOP, stack, false /* includingParents */);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800574 assertTrue(called[0]);
575 assertEquals(ACTIVITY_TYPE_STANDARD, lastReportedTiles.get(0).topActivityType);
576
577 lastReportedTiles.clear();
578 called[0] = false;
Louis Changa009c762020-02-26 11:21:31 +0800579 wct = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700580 wct.reparent(stack.mRemoteToken.toWindowContainerToken(), null, true /* onTop */);
581 wct.reparent(stack2.mRemoteToken.toWindowContainerToken(), null, true /* onTop */);
Louis Changa009c762020-02-26 11:21:31 +0800582 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800583 assertTrue(called[0]);
584 assertEquals(ACTIVITY_TYPE_UNDEFINED, lastReportedTiles.get(0).topActivityType);
585 }
586
Evan Roskya8fde152020-01-07 19:09:13 -0800587 @Test
588 public void testHierarchyTransaction() {
589 final ArrayMap<IBinder, RunningTaskInfo> lastReportedTiles = new ArrayMap<>();
590 ITaskOrganizer listener = new ITaskOrganizer.Stub() {
591 @Override
chaviw7de50002020-04-27 12:33:30 -0700592 public void onTaskAppeared(RunningTaskInfo taskInfo, SurfaceControl leash) { }
Evan Roskya8fde152020-01-07 19:09:13 -0800593
594 @Override
Wale Ogunwaledec34082020-03-22 09:45:00 -0700595 public void onTaskVanished(RunningTaskInfo container) { }
Evan Roskya8fde152020-01-07 19:09:13 -0800596
597 @Override
Evan Roskya8fde152020-01-07 19:09:13 -0800598 public void onTaskInfoChanged(RunningTaskInfo info) {
599 lastReportedTiles.put(info.token.asBinder(), info);
600 }
Winson Chunga1f869d2020-03-21 23:02:48 -0700601
602 @Override
603 public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
604 }
Evan Roskya8fde152020-01-07 19:09:13 -0800605 };
606 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(
Louis Changa009c762020-02-26 11:21:31 +0800607 listener, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
608 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(
Evan Roskya8fde152020-01-07 19:09:13 -0800609 listener, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
610 RunningTaskInfo info1 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
Louis Changa009c762020-02-26 11:21:31 +0800611 mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
Evan Roskya8fde152020-01-07 19:09:13 -0800612 RunningTaskInfo info2 = mWm.mAtmService.mTaskOrganizerController.createRootTask(
613 mDisplayContent.mDisplayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
614
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800615 final int initialRootTaskCount = mWm.mAtmService.mTaskOrganizerController.getRootTasks(
616 mDisplayContent.mDisplayId, null /* activityTypes */).size();
617
Evan Roskya8fde152020-01-07 19:09:13 -0800618 final ActivityStack stack = createTaskStackOnDisplay(
619 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_STANDARD, mDisplayContent);
620 final ActivityStack stack2 = createTaskStackOnDisplay(
621 WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, mDisplayContent);
622
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800623 // Check getRootTasks works
624 List<RunningTaskInfo> roots = mWm.mAtmService.mTaskOrganizerController.getRootTasks(
625 mDisplayContent.mDisplayId, null /* activityTypes */);
626 assertEquals(initialRootTaskCount + 2, roots.size());
627
Evan Roskya8fde152020-01-07 19:09:13 -0800628 lastReportedTiles.clear();
629 WindowContainerTransaction wct = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700630 wct.reparent(stack.mRemoteToken.toWindowContainerToken(), info1.token, true /* onTop */);
631 wct.reparent(stack2.mRemoteToken.toWindowContainerToken(), info2.token, true /* onTop */);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700632 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Roskya8fde152020-01-07 19:09:13 -0800633 assertFalse(lastReportedTiles.isEmpty());
634 assertEquals(ACTIVITY_TYPE_STANDARD,
635 lastReportedTiles.get(info1.token.asBinder()).topActivityType);
636 assertEquals(ACTIVITY_TYPE_HOME,
637 lastReportedTiles.get(info2.token.asBinder()).topActivityType);
638
639 lastReportedTiles.clear();
640 wct = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700641 wct.reparent(stack2.mRemoteToken.toWindowContainerToken(), info1.token, false /* onTop */);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700642 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Roskya8fde152020-01-07 19:09:13 -0800643 assertFalse(lastReportedTiles.isEmpty());
644 // Standard should still be on top of tile 1, so no change there
645 assertFalse(lastReportedTiles.containsKey(info1.token.asBinder()));
646 // But tile 2 has no children, so should become undefined
647 assertEquals(ACTIVITY_TYPE_UNDEFINED,
648 lastReportedTiles.get(info2.token.asBinder()).topActivityType);
649
650 // Check the getChildren call
651 List<RunningTaskInfo> children =
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800652 mWm.mAtmService.mTaskOrganizerController.getChildTasks(info1.token,
653 null /* activityTypes */);
Evan Roskya8fde152020-01-07 19:09:13 -0800654 assertEquals(2, children.size());
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800655 children = mWm.mAtmService.mTaskOrganizerController.getChildTasks(info2.token,
656 null /* activityTypes */);
Evan Roskya8fde152020-01-07 19:09:13 -0800657 assertEquals(0, children.size());
658
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800659 // Check that getRootTasks doesn't include children of tiles
660 roots = mWm.mAtmService.mTaskOrganizerController.getRootTasks(mDisplayContent.mDisplayId,
661 null /* activityTypes */);
662 assertEquals(initialRootTaskCount, roots.size());
663
Evan Roskya8fde152020-01-07 19:09:13 -0800664 lastReportedTiles.clear();
665 wct = new WindowContainerTransaction();
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700666 wct.reorder(stack2.mRemoteToken.toWindowContainerToken(), true /* onTop */);
Wale Ogunwale568f9f412020-03-21 22:27:35 -0700667 mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
Evan Roskya8fde152020-01-07 19:09:13 -0800668 // Home should now be on top. No change occurs in second tile, so not reported
669 assertEquals(1, lastReportedTiles.size());
670 assertEquals(ACTIVITY_TYPE_HOME,
671 lastReportedTiles.get(info1.token.asBinder()).topActivityType);
672 }
673
Louis Changa009c762020-02-26 11:21:31 +0800674 private List<Task> getTasksCreatedByOrganizer(DisplayContent dc) {
675 ArrayList<Task> out = new ArrayList<>();
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700676 for (int tdaNdx = dc.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
677 final TaskDisplayArea taskDisplayArea = dc.getTaskDisplayAreaAt(tdaNdx);
678 for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
679 final Task t = taskDisplayArea.getStackAt(sNdx);
680 if (t.mCreatedByOrganizer) out.add(t);
681 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800682 }
683 return out;
684 }
Robert Carre10ee3d2019-11-11 15:03:15 -0800685
686 @Test
687 public void testTrivialBLASTCallback() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700688 final ActivityStack stackController1 = createStack();
689 final Task task = createTask(stackController1);
Robert Carre10ee3d2019-11-11 15:03:15 -0800690 final ITaskOrganizer organizer = registerMockOrganizer();
691
Robert Carr8ccc4fc2020-03-13 10:48:49 -0700692 spyOn(task);
693 doReturn(true).when(task).isVisible();
694
Robert Carre10ee3d2019-11-11 15:03:15 -0800695 BLASTSyncEngine bse = new BLASTSyncEngine();
696
697 BLASTSyncEngine.TransactionReadyListener transactionListener =
chaviw6630d852020-04-15 19:06:56 -0700698 mock(BLASTSyncEngine.TransactionReadyListener.class);
Robert Carre10ee3d2019-11-11 15:03:15 -0800699
700 int id = bse.startSyncSet(transactionListener);
701 bse.addToSyncSet(id, task);
702 bse.setReady(id);
703 // Since this task has no windows the sync is trivial and completes immediately.
704 verify(transactionListener)
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700705 .onTransactionReady(anyInt(), any());
Robert Carre10ee3d2019-11-11 15:03:15 -0800706 }
707
708 @Test
Robert Carr8ccc4fc2020-03-13 10:48:49 -0700709 public void testOverlappingBLASTCallback() throws RemoteException {
Robert Carrde96c8a2020-03-24 15:22:21 -0700710 final ActivityStack stackController1 = createStack();
711 final Task task = createTask(stackController1);
Robert Carr8ccc4fc2020-03-13 10:48:49 -0700712 final ITaskOrganizer organizer = registerMockOrganizer();
713
714 spyOn(task);
715 doReturn(true).when(task).isVisible();
716 final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
717 makeWindowVisible(w);
718
719 BLASTSyncEngine bse = new BLASTSyncEngine();
720
721 BLASTSyncEngine.TransactionReadyListener transactionListener =
chaviw6630d852020-04-15 19:06:56 -0700722 mock(BLASTSyncEngine.TransactionReadyListener.class);
Robert Carr8ccc4fc2020-03-13 10:48:49 -0700723
724 int id = bse.startSyncSet(transactionListener);
725 assertEquals(true, bse.addToSyncSet(id, task));
726 bse.setReady(id);
727
728 int id2 = bse.startSyncSet(transactionListener);
729 // We should be rejected from the second sync since we are already
730 // in one.
731 assertEquals(false, bse.addToSyncSet(id2, task));
chaviw355befd2020-06-23 08:11:46 -0700732 w.immediatelyNotifyBlastSync();
Robert Carr8ccc4fc2020-03-13 10:48:49 -0700733 assertEquals(true, bse.addToSyncSet(id2, task));
734 bse.setReady(id2);
735 }
736
737 @Test
Robert Carre10ee3d2019-11-11 15:03:15 -0800738 public void testBLASTCallbackWithWindow() {
Robert Carrde96c8a2020-03-24 15:22:21 -0700739 final ActivityStack stackController1 = createStack();
740 final Task task = createTask(stackController1);
Robert Carre10ee3d2019-11-11 15:03:15 -0800741 final ITaskOrganizer organizer = registerMockOrganizer();
742 final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
Rob Carrcba6a722020-03-10 12:41:06 -0700743 makeWindowVisible(w);
Robert Carre10ee3d2019-11-11 15:03:15 -0800744
745 BLASTSyncEngine bse = new BLASTSyncEngine();
746
747 BLASTSyncEngine.TransactionReadyListener transactionListener =
chaviw6630d852020-04-15 19:06:56 -0700748 mock(BLASTSyncEngine.TransactionReadyListener.class);
Robert Carre10ee3d2019-11-11 15:03:15 -0800749
750 int id = bse.startSyncSet(transactionListener);
751 bse.addToSyncSet(id, task);
752 bse.setReady(id);
753 // Since we have a window we have to wait for it to draw to finish sync.
754 verify(transactionListener, never())
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700755 .onTransactionReady(anyInt(), any());
chaviw355befd2020-06-23 08:11:46 -0700756 w.immediatelyNotifyBlastSync();
Robert Carre10ee3d2019-11-11 15:03:15 -0800757 verify(transactionListener)
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700758 .onTransactionReady(anyInt(), any());
Robert Carre10ee3d2019-11-11 15:03:15 -0800759 }
Robert Carrf6690d12020-02-04 14:16:21 -0800760
Rob Carr25376512020-03-09 15:23:19 -0700761 @Test
Robert Carr6a08d322020-05-19 10:21:55 -0700762 public void testBLASTCallbackNoDoubleAdd() {
763 final ActivityStack stackController1 = createStack();
764 final Task task = createTask(stackController1);
765 final ITaskOrganizer organizer = registerMockOrganizer();
766 final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
767 makeWindowVisible(w);
768
769 BLASTSyncEngine bse = new BLASTSyncEngine();
770
771 BLASTSyncEngine.TransactionReadyListener transactionListener =
772 mock(BLASTSyncEngine.TransactionReadyListener.class);
773
774 int id = bse.startSyncSet(transactionListener);
775 assertTrue(bse.addToSyncSet(id, w));
776 assertFalse(bse.addToSyncSet(id, w));
777
778 // Clean-up
779 bse.setReady(id);
780 }
781
782
783 @Test
Rob Carrcba6a722020-03-10 12:41:06 -0700784 public void testBLASTCallbackWithInvisibleWindow() {
Robert Carrde96c8a2020-03-24 15:22:21 -0700785 final ActivityStack stackController1 = createStack();
786 final Task task = createTask(stackController1);
Rob Carrcba6a722020-03-10 12:41:06 -0700787 final ITaskOrganizer organizer = registerMockOrganizer();
788 final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
789
790 BLASTSyncEngine bse = new BLASTSyncEngine();
791
792 BLASTSyncEngine.TransactionReadyListener transactionListener =
chaviw6630d852020-04-15 19:06:56 -0700793 mock(BLASTSyncEngine.TransactionReadyListener.class);
Rob Carrcba6a722020-03-10 12:41:06 -0700794
795 int id = bse.startSyncSet(transactionListener);
796 bse.addToSyncSet(id, task);
797 bse.setReady(id);
798
799 // Since the window was invisible, the Task had no visible leaves and the sync should
800 // complete as soon as we call setReady.
801 verify(transactionListener)
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700802 .onTransactionReady(anyInt(), any());
Rob Carrcba6a722020-03-10 12:41:06 -0700803 }
804
805 @Test
Rob Carr25376512020-03-09 15:23:19 -0700806 public void testBLASTCallbackWithChildWindow() {
Robert Carrde96c8a2020-03-24 15:22:21 -0700807 final ActivityStack stackController1 = createStack();
808 final Task task = createTask(stackController1);
Rob Carr25376512020-03-09 15:23:19 -0700809 final ITaskOrganizer organizer = registerMockOrganizer();
810 final WindowState w = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window");
811 final WindowState child = createWindow(w, TYPE_APPLICATION, "Other Window");
812
813 w.mActivityRecord.setVisible(true);
814 makeWindowVisible(w, child);
815
816 BLASTSyncEngine bse = new BLASTSyncEngine();
817
818 BLASTSyncEngine.TransactionReadyListener transactionListener =
chaviw6630d852020-04-15 19:06:56 -0700819 mock(BLASTSyncEngine.TransactionReadyListener.class);
Rob Carr25376512020-03-09 15:23:19 -0700820
821 int id = bse.startSyncSet(transactionListener);
822 assertEquals(true, bse.addToSyncSet(id, task));
823 bse.setReady(id);
chaviw355befd2020-06-23 08:11:46 -0700824 w.immediatelyNotifyBlastSync();
Rob Carr25376512020-03-09 15:23:19 -0700825
826 // Since we have a child window we still shouldn't be done.
827 verify(transactionListener, never())
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700828 .onTransactionReady(anyInt(), any());
Rob Carr25376512020-03-09 15:23:19 -0700829 reset(transactionListener);
830
chaviw355befd2020-06-23 08:11:46 -0700831 child.immediatelyNotifyBlastSync();
Rob Carr25376512020-03-09 15:23:19 -0700832 // Ah finally! Done
833 verify(transactionListener)
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700834 .onTransactionReady(anyInt(), any());
Rob Carr25376512020-03-09 15:23:19 -0700835 }
836
Robert Carrf6690d12020-02-04 14:16:21 -0800837 class StubOrganizer extends ITaskOrganizer.Stub {
838 RunningTaskInfo mInfo;
839
840 @Override
chaviw7de50002020-04-27 12:33:30 -0700841 public void onTaskAppeared(RunningTaskInfo info, SurfaceControl leash) {
Robert Carrf6690d12020-02-04 14:16:21 -0800842 mInfo = info;
843 }
844 @Override
Wale Ogunwaledec34082020-03-22 09:45:00 -0700845 public void onTaskVanished(RunningTaskInfo info) {
Robert Carrf6690d12020-02-04 14:16:21 -0800846 }
847 @Override
Robert Carrf6690d12020-02-04 14:16:21 -0800848 public void onTaskInfoChanged(RunningTaskInfo info) {
849 }
Winson Chunga1f869d2020-03-21 23:02:48 -0700850 @Override
851 public void onBackPressedOnTaskRoot(RunningTaskInfo taskInfo) {
852 }
Robert Carrf6690d12020-02-04 14:16:21 -0800853 };
854
855 private ActivityRecord makePipableActivity() {
856 final ActivityRecord record = createActivityRecord(mDisplayContent,
857 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
858 record.info.flags |= ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
859 spyOn(record);
860 doReturn(true).when(record).checkEnterPictureInPictureState(any(), anyBoolean());
Robert Carrde96c8a2020-03-24 15:22:21 -0700861
Evan Rosky2af969c2020-05-08 16:26:31 +0000862 record.getTask().setHasBeenVisible(true);
Robert Carrf6690d12020-02-04 14:16:21 -0800863 return record;
864 }
865
866 @Test
867 public void testEnterPipParams() {
868 final StubOrganizer o = new StubOrganizer();
869 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(o, WINDOWING_MODE_PINNED);
870 final ActivityRecord record = makePipableActivity();
871
chaviw6630d852020-04-15 19:06:56 -0700872 final PictureInPictureParams p = new PictureInPictureParams.Builder()
873 .setAspectRatio(new Rational(1, 2)).build();
Robert Carrf6690d12020-02-04 14:16:21 -0800874 assertTrue(mWm.mAtmService.enterPictureInPictureMode(record.token, p));
875 waitUntilHandlersIdle();
876 assertNotNull(o.mInfo);
877 assertNotNull(o.mInfo.pictureInPictureParams);
878 }
879
880 @Test
881 public void testChangePipParams() {
882 class ChangeSavingOrganizer extends StubOrganizer {
883 RunningTaskInfo mChangedInfo;
884 @Override
885 public void onTaskInfoChanged(RunningTaskInfo info) {
886 mChangedInfo = info;
887 }
888 }
889 ChangeSavingOrganizer o = new ChangeSavingOrganizer();
890 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(o, WINDOWING_MODE_PINNED);
891
892 final ActivityRecord record = makePipableActivity();
chaviw6630d852020-04-15 19:06:56 -0700893 final PictureInPictureParams p = new PictureInPictureParams.Builder()
894 .setAspectRatio(new Rational(1, 2)).build();
Robert Carrf6690d12020-02-04 14:16:21 -0800895 assertTrue(mWm.mAtmService.enterPictureInPictureMode(record.token, p));
896 waitUntilHandlersIdle();
897 assertNotNull(o.mInfo);
898 assertNotNull(o.mInfo.pictureInPictureParams);
899
chaviw6630d852020-04-15 19:06:56 -0700900 final PictureInPictureParams p2 = new PictureInPictureParams.Builder()
901 .setAspectRatio(new Rational(3, 4)).build();
Robert Carrf6690d12020-02-04 14:16:21 -0800902 mWm.mAtmService.setPictureInPictureParams(record.token, p2);
903 waitUntilHandlersIdle();
904 assertNotNull(o.mChangedInfo);
905 assertNotNull(o.mChangedInfo.pictureInPictureParams);
906 final Rational ratio = o.mChangedInfo.pictureInPictureParams.getAspectRatioRational();
907 assertEquals(3, ratio.getNumerator());
908 assertEquals(4, ratio.getDenominator());
909 }
Robert Carrde96c8a2020-03-24 15:22:21 -0700910
911 @Test
Winson Chung1df39e22020-04-09 14:30:55 -0700912 public void testChangeTaskDescription() {
913 class ChangeSavingOrganizer extends StubOrganizer {
914 RunningTaskInfo mChangedInfo;
915 @Override
916 public void onTaskInfoChanged(RunningTaskInfo info) {
917 mChangedInfo = info;
918 }
919 }
920 ChangeSavingOrganizer o = new ChangeSavingOrganizer();
921 mWm.mAtmService.mTaskOrganizerController.registerTaskOrganizer(o,
922 WINDOWING_MODE_MULTI_WINDOW);
923
924 final ActivityStack stack = createStack();
925 final Task task = createTask(stack);
926 final ActivityRecord record = WindowTestUtils.createActivityRecordInTask(
927 stack.mDisplayContent, task);
928
929 stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
930 record.setTaskDescription(new ActivityManager.TaskDescription("TestDescription"));
931 waitUntilHandlersIdle();
932 assertEquals("TestDescription", o.mChangedInfo.taskDescription.getLabel());
933 }
934
935 @Test
Robert Carrde96c8a2020-03-24 15:22:21 -0700936 public void testPreventDuplicateAppear() throws RemoteException {
937 final ActivityStack stack = createStack();
938 final Task task = createTask(stack);
939 final ITaskOrganizer organizer = registerMockOrganizer();
940
941 task.setTaskOrganizer(organizer);
942 // setHasBeenVisible was already called once by the set-up code.
943 task.setHasBeenVisible(true);
chaviw7de50002020-04-27 12:33:30 -0700944 verify(organizer, times(1))
945 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carrde96c8a2020-03-24 15:22:21 -0700946
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700947 task.setTaskOrganizer(null);
948 verify(organizer, times(1)).onTaskVanished(any());
Robert Carrde96c8a2020-03-24 15:22:21 -0700949 task.setTaskOrganizer(organizer);
chaviw7de50002020-04-27 12:33:30 -0700950 verify(organizer, times(2))
951 .onTaskAppeared(any(RunningTaskInfo.class), any(SurfaceControl.class));
Robert Carrde96c8a2020-03-24 15:22:21 -0700952
953 task.removeImmediately();
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700954 verify(organizer, times(2)).onTaskVanished(any());
Robert Carrde96c8a2020-03-24 15:22:21 -0700955 }
Winson Chunga1f869d2020-03-21 23:02:48 -0700956
957 @Test
958 public void testInterceptBackPressedOnTaskRoot() throws RemoteException {
959 final ActivityStack stack = createStack();
960 final Task task = createTask(stack);
961 final ActivityRecord activity = WindowTestUtils.createActivityRecordInTask(
962 stack.mDisplayContent, task);
963 final ITaskOrganizer organizer = registerMockOrganizer(WINDOWING_MODE_MULTI_WINDOW);
964
965 // Setup the task to be controlled by the MW mode organizer
966 stack.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
967 assertTrue(stack.isOrganized());
968
969 // Verify a back pressed does not call the organizer
970 mWm.mAtmService.onBackPressedOnTaskRoot(activity.token,
971 new IRequestFinishCallback.Default());
972 verify(organizer, never()).onBackPressedOnTaskRoot(any());
973
974 // Enable intercepting back
975 mWm.mAtmService.mTaskOrganizerController.setInterceptBackPressedOnTaskRoot(organizer,
976 true);
977
978 // Verify now that the back press does call the organizer
979 mWm.mAtmService.onBackPressedOnTaskRoot(activity.token,
980 new IRequestFinishCallback.Default());
981 verify(organizer, times(1)).onBackPressedOnTaskRoot(any());
982 }
chaviw54521692020-06-12 14:34:30 -0700983
984 @Test
985 public void testBLASTCallbackWithMultipleWindows() throws Exception {
986 final ActivityStack stackController = createStack();
987 final Task task = createTask(stackController);
988 final ITaskOrganizer organizer = registerMockOrganizer();
989 final WindowState w1 = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window 1");
990 final WindowState w2 = createAppWindow(task, TYPE_APPLICATION, "Enlightened Window 2");
991 makeWindowVisible(w1);
992 makeWindowVisible(w2);
993
994 IWindowContainerTransactionCallback mockCallback =
995 mock(IWindowContainerTransactionCallback.class);
996 int id = mWm.mAtmService.mWindowOrganizerController.startSyncWithOrganizer(mockCallback);
997
998 mWm.mAtmService.mWindowOrganizerController.addToSyncSet(id, task);
999 mWm.mAtmService.mWindowOrganizerController.setSyncReady(id);
1000
1001 // Since we have a window we have to wait for it to draw to finish sync.
1002 verify(mockCallback, never()).onTransactionReady(anyInt(), any());
1003 assertTrue(w1.useBLASTSync());
1004 assertTrue(w2.useBLASTSync());
chaviw355befd2020-06-23 08:11:46 -07001005 w1.immediatelyNotifyBlastSync();
chaviw54521692020-06-12 14:34:30 -07001006
1007 // Even though one Window finished drawing, both windows should still be using blast sync
1008 assertTrue(w1.useBLASTSync());
1009 assertTrue(w2.useBLASTSync());
1010
chaviw355befd2020-06-23 08:11:46 -07001011 w2.immediatelyNotifyBlastSync();
chaviw54521692020-06-12 14:34:30 -07001012 verify(mockCallback).onTransactionReady(anyInt(), any());
1013 assertFalse(w1.useBLASTSync());
1014 assertFalse(w2.useBLASTSync());
1015 }
Robert Carr8a2f9132019-11-11 15:03:15 -08001016}