blob: 9d229df1967ea8f3c610d5a8241b472bb9c23438 [file] [log] [blame]
Robert Carr8a2f9132019-11-11 15:03:15 -08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.wm;
18
Evan Rosky0037e5f2019-11-05 10:26:24 -080019import static android.Manifest.permission.MANAGE_ACTIVITY_STACKS;
Louis Changa009c762020-02-26 11:21:31 +080020import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
Robert Carr00c0dbe2020-01-24 15:30:24 -080021import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
Evan Rosky0037e5f2019-11-05 10:26:24 -080022import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
Robert Carr8a2f9132019-11-11 15:03:15 -080023
Wale Ogunwale568f9f412020-03-21 22:27:35 -070024import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_CONFIGS;
25import static com.android.server.wm.WindowOrganizerController.CONTROLLABLE_WINDOW_CONFIGS;
Evan Rosky0037e5f2019-11-05 10:26:24 -080026
27import android.annotation.Nullable;
Winson Chung1b5d0552020-04-06 19:28:49 -070028import android.app.ActivityManager;
Evan Rosky0037e5f2019-11-05 10:26:24 -080029import android.app.ActivityManager.RunningTaskInfo;
Winson Chung1df39e22020-04-09 14:30:55 -070030import android.app.ActivityManager.TaskDescription;
Evan Roskyb8540a02020-03-25 16:30:24 -070031import android.app.WindowConfiguration;
Louis Changa009c762020-02-26 11:21:31 +080032import android.content.Intent;
Evan Rosky0037e5f2019-11-05 10:26:24 -080033import android.content.pm.ActivityInfo;
Evan Rosky0037e5f2019-11-05 10:26:24 -080034import android.os.Binder;
Robert Carr8a2f9132019-11-11 15:03:15 -080035import android.os.IBinder;
36import android.os.RemoteException;
37import android.util.Slog;
Winson Chungaff506b2020-03-21 22:56:31 -070038import android.util.SparseArray;
Wale Ogunwale57946582020-03-21 14:29:07 -070039import android.window.ITaskOrganizer;
Louis Changa009c762020-02-26 11:21:31 +080040import android.window.ITaskOrganizerController;
Wale Ogunwaleadf116e2020-03-27 16:36:01 -070041import android.window.WindowContainerToken;
Evan Rosky0037e5f2019-11-05 10:26:24 -080042
Winson Chung1b5d0552020-04-06 19:28:49 -070043import com.android.internal.annotations.VisibleForTesting;
Evan Rosky29d4a0a2020-02-04 16:40:44 -080044import com.android.internal.util.ArrayUtils;
Robert Carr8a2f9132019-11-11 15:03:15 -080045
Winson Chung268eccb2020-03-26 13:43:44 -070046import java.io.PrintWriter;
Robert Carr8a2f9132019-11-11 15:03:15 -080047import java.util.ArrayList;
48import java.util.HashMap;
Winson Chungaff506b2020-03-21 22:56:31 -070049import java.util.LinkedList;
Evan Roskya8fde152020-01-07 19:09:13 -080050import java.util.List;
Evan Rosky0037e5f2019-11-05 10:26:24 -080051import java.util.WeakHashMap;
Winson Chung1b5d0552020-04-06 19:28:49 -070052import java.util.function.Consumer;
Robert Carr8a2f9132019-11-11 15:03:15 -080053
54/**
55 * Stores the TaskOrganizers associated with a given windowing mode and
56 * their associated state.
57 */
Wale Ogunwale568f9f412020-03-21 22:27:35 -070058class TaskOrganizerController extends ITaskOrganizerController.Stub {
Robert Carr8a2f9132019-11-11 15:03:15 -080059 private static final String TAG = "TaskOrganizerController";
Evan Roskyb8540a02020-03-25 16:30:24 -070060 private static final LinkedList<IBinder> EMPTY_LIST = new LinkedList<>();
Robert Carr8a2f9132019-11-11 15:03:15 -080061
Evan Roskyf64f5da2020-03-16 13:47:48 -070062 /**
63 * Masks specifying which configurations are important to report back to an organizer when
64 * changed.
65 */
66 private static final int REPORT_CONFIGS = CONTROLLABLE_CONFIGS;
67 private static final int REPORT_WINDOW_CONFIGS = CONTROLLABLE_WINDOW_CONFIGS;
68
Evan Rosky0037e5f2019-11-05 10:26:24 -080069 private final WindowManagerGlobalLock mGlobalLock;
Robert Carr8a2f9132019-11-11 15:03:15 -080070
71 private class DeathRecipient implements IBinder.DeathRecipient {
Robert Carr8a2f9132019-11-11 15:03:15 -080072 ITaskOrganizer mTaskOrganizer;
73
Evan Roskyb8540a02020-03-25 16:30:24 -070074 DeathRecipient(ITaskOrganizer organizer) {
Robert Carr8a2f9132019-11-11 15:03:15 -080075 mTaskOrganizer = organizer;
Robert Carr8a2f9132019-11-11 15:03:15 -080076 }
77
78 @Override
79 public void binderDied() {
80 synchronized (mGlobalLock) {
Winson Chungaff506b2020-03-21 22:56:31 -070081 final TaskOrganizerState state = mTaskOrganizerStates.remove(
82 mTaskOrganizer.asBinder());
Riddle Hsu3c290512020-03-30 22:12:52 +080083 if (state != null) {
84 state.dispose();
85 }
Robert Carr8a2f9132019-11-11 15:03:15 -080086 }
87 }
Winson Chung1b5d0552020-04-06 19:28:49 -070088 }
89
90 /**
91 * A wrapper class around ITaskOrganizer to ensure that the calls are made in the right
92 * lifecycle order since we may be updating the visibility of task surface controls in a pending
93 * transaction before they are presented to the task org.
94 */
95 private class TaskOrganizerCallbacks {
96 final WindowManagerService mService;
97 final ITaskOrganizer mTaskOrganizer;
98 final Consumer<Runnable> mDeferTaskOrgCallbacksConsumer;
99
100 TaskOrganizerCallbacks(WindowManagerService wm, ITaskOrganizer taskOrg,
101 Consumer<Runnable> deferTaskOrgCallbacksConsumer) {
102 mService = wm;
103 mDeferTaskOrgCallbacksConsumer = deferTaskOrgCallbacksConsumer;
104 mTaskOrganizer = taskOrg;
105 }
106
107 IBinder getBinder() {
108 return mTaskOrganizer.asBinder();
109 }
110
111 void onTaskAppeared(Task task) {
112 final RunningTaskInfo taskInfo = task.getTaskInfo();
113 mDeferTaskOrgCallbacksConsumer.accept(() -> {
114 try {
115 mTaskOrganizer.onTaskAppeared(taskInfo);
116 } catch (RemoteException e) {
117 Slog.e(TAG, "Exception sending onTaskAppeared callback", e);
118 }
119 });
120 }
121
122
123 void onTaskVanished(Task task) {
124 final RunningTaskInfo taskInfo = task.getTaskInfo();
125 mDeferTaskOrgCallbacksConsumer.accept(() -> {
126 try {
127 mTaskOrganizer.onTaskVanished(taskInfo);
128 } catch (RemoteException e) {
129 Slog.e(TAG, "Exception sending onTaskVanished callback", e);
130 }
131 });
132 }
133
134 void onTaskInfoChanged(Task task, ActivityManager.RunningTaskInfo taskInfo) {
Winson Chung8b5d23a2020-04-06 19:23:23 -0700135 if (!task.mCreatedByOrganizer && !task.mTaskAppearedSent) {
136 // Skip if the task has not yet received taskAppeared(), except for tasks created
137 // by the organizer that don't receive that signal
138 return;
139 }
Winson Chung1b5d0552020-04-06 19:28:49 -0700140 mDeferTaskOrgCallbacksConsumer.accept(() -> {
141 if (!task.isOrganized()) {
142 // This is safe to ignore if the task is no longer organized
143 return;
144 }
145 try {
146 mTaskOrganizer.onTaskInfoChanged(taskInfo);
147 } catch (RemoteException e) {
148 Slog.e(TAG, "Exception sending onTaskInfoChanged callback", e);
149 }
150 });
151 }
152
153 void onBackPressedOnTaskRoot(Task task) {
Winson Chung8b5d23a2020-04-06 19:23:23 -0700154 if (!task.mCreatedByOrganizer && !task.mTaskAppearedSent) {
155 // Skip if the task has not yet received taskAppeared(), except for tasks created
156 // by the organizer that don't receive that signal
157 return;
158 }
Winson Chung1b5d0552020-04-06 19:28:49 -0700159 mDeferTaskOrgCallbacksConsumer.accept(() -> {
160 if (!task.isOrganized()) {
161 // This is safe to ignore if the task is no longer organized
162 return;
163 }
164 try {
165 mTaskOrganizer.onBackPressedOnTaskRoot(task.getTaskInfo());
166 } catch (Exception e) {
167 Slog.e(TAG, "Exception sending onBackPressedOnTaskRoot callback", e);
168 }
169 });
170 }
171 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800172
Winson Chungaff506b2020-03-21 22:56:31 -0700173 private class TaskOrganizerState {
Winson Chung1b5d0552020-04-06 19:28:49 -0700174 private final TaskOrganizerCallbacks mOrganizer;
Winson Chungaff506b2020-03-21 22:56:31 -0700175 private final DeathRecipient mDeathRecipient;
Winson Chungaff506b2020-03-21 22:56:31 -0700176 private final ArrayList<Task> mOrganizedTasks = new ArrayList<>();
Winson Chung268eccb2020-03-26 13:43:44 -0700177 private final int mUid;
Winson Chunga1f869d2020-03-21 23:02:48 -0700178 private boolean mInterceptBackPressedOnTaskRoot;
Robert Carr8a2f9132019-11-11 15:03:15 -0800179
Winson Chung268eccb2020-03-26 13:43:44 -0700180 TaskOrganizerState(ITaskOrganizer organizer, int uid) {
Winson Chung1b5d0552020-04-06 19:28:49 -0700181 final Consumer<Runnable> deferTaskOrgCallbacksConsumer =
182 mDeferTaskOrgCallbacksConsumer != null
183 ? mDeferTaskOrgCallbacksConsumer
184 : mService.mWindowManager.mAnimator::addAfterPrepareSurfacesRunnable;
185 mOrganizer = new TaskOrganizerCallbacks(mService.mWindowManager, organizer,
186 deferTaskOrgCallbacksConsumer);
Evan Roskyb8540a02020-03-25 16:30:24 -0700187 mDeathRecipient = new DeathRecipient(organizer);
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800188 try {
189 organizer.asBinder().linkToDeath(mDeathRecipient, 0);
190 } catch (RemoteException e) {
191 Slog.e(TAG, "TaskOrganizer failed to register death recipient");
192 }
Winson Chung268eccb2020-03-26 13:43:44 -0700193 mUid = uid;
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800194 }
195
Winson Chunga1f869d2020-03-21 23:02:48 -0700196 void setInterceptBackPressedOnTaskRoot(boolean interceptBackPressed) {
197 mInterceptBackPressedOnTaskRoot = interceptBackPressed;
198 }
199
Robert Carr8a2f9132019-11-11 15:03:15 -0800200 void addTask(Task t) {
Louis Chang9d35a3a2020-04-06 17:23:02 +0800201 if (t.mTaskAppearedSent) return;
202
203 if (!mOrganizedTasks.contains(t)) {
204 mOrganizedTasks.add(t);
205 }
206 if (t.taskAppearedReady()) {
Winson Chung8b5d23a2020-04-06 19:23:23 -0700207 t.mTaskAppearedSent = true;
208 mOrganizer.onTaskAppeared(t);
Winson Chungd2fb07e2020-04-06 18:17:21 +0000209 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800210 }
211
212 void removeTask(Task t) {
Louis Chang9d35a3a2020-04-06 17:23:02 +0800213 if (t.mTaskAppearedSent) {
chaviwda7b3c22020-04-24 11:25:08 -0700214 t.migrateToNewSurfaceControl();
Winson Chung8b5d23a2020-04-06 19:23:23 -0700215 t.mTaskAppearedSent = false;
216 mOrganizer.onTaskVanished(t);
Winson Chungd2fb07e2020-04-06 18:17:21 +0000217 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800218 mOrganizedTasks.remove(t);
219 }
220
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800221 void dispose() {
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700222 // Move organizer from managing specific windowing modes
Evan Roskyb8540a02020-03-25 16:30:24 -0700223 for (int i = mTaskOrganizersForWindowingMode.size() - 1; i >= 0; --i) {
Winson Chung1b5d0552020-04-06 19:28:49 -0700224 mTaskOrganizersForWindowingMode.valueAt(i).remove(mOrganizer.getBinder());
Evan Roskyb8540a02020-03-25 16:30:24 -0700225 }
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800226
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700227 // Update tasks currently managed by this organizer to the next one available if
228 // possible.
229 while (!mOrganizedTasks.isEmpty()) {
230 final Task t = mOrganizedTasks.get(0);
231 t.updateTaskOrganizerState(true /* forceUpdate */);
232 if (mOrganizedTasks.contains(t)) {
233 removeTask(t);
234 }
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800235 }
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700236
237 // Remove organizer state after removing tasks so we get a chance to send
238 // onTaskVanished.
239 mTaskOrganizerStates.remove(asBinder());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800240 }
241
242 void unlinkDeath() {
Winson Chung1b5d0552020-04-06 19:28:49 -0700243 mOrganizer.getBinder().unlinkToDeath(mDeathRecipient, 0);
Robert Carr8a2f9132019-11-11 15:03:15 -0800244 }
Winson Chungaff506b2020-03-21 22:56:31 -0700245 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800246
Evan Roskyb8540a02020-03-25 16:30:24 -0700247 private final SparseArray<LinkedList<IBinder>> mTaskOrganizersForWindowingMode =
Winson Chungaff506b2020-03-21 22:56:31 -0700248 new SparseArray<>();
249 private final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap<>();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800250 private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>();
251 private final ArrayList<Task> mPendingTaskInfoChanges = new ArrayList<>();
252
Winson Chung1b5d0552020-04-06 19:28:49 -0700253 private final ActivityTaskManagerService mService;
Robert Carr8a2f9132019-11-11 15:03:15 -0800254
Winson Chung1b5d0552020-04-06 19:28:49 -0700255 private RunningTaskInfo mTmpTaskInfo;
256 private Consumer<Runnable> mDeferTaskOrgCallbacksConsumer;
Evan Rosky0037e5f2019-11-05 10:26:24 -0800257
258 TaskOrganizerController(ActivityTaskManagerService atm) {
Robert Carr8a2f9132019-11-11 15:03:15 -0800259 mService = atm;
Evan Rosky0037e5f2019-11-05 10:26:24 -0800260 mGlobalLock = atm.mGlobalLock;
261 }
262
263 private void enforceStackPermission(String func) {
264 mService.mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, func);
Robert Carr8a2f9132019-11-11 15:03:15 -0800265 }
266
Robert Carr8a2f9132019-11-11 15:03:15 -0800267 /**
Winson Chung1b5d0552020-04-06 19:28:49 -0700268 * Specifies the consumer to run to defer the task org callbacks. Can be overridden while
269 * testing to allow the callbacks to be sent synchronously.
270 */
271 @VisibleForTesting
272 public void setDeferTaskOrgCallbacksConsumer(Consumer<Runnable> consumer) {
273 mDeferTaskOrgCallbacksConsumer = consumer;
274 }
275
276 /**
Robert Carr8a2f9132019-11-11 15:03:15 -0800277 * Register a TaskOrganizer to manage tasks as they enter the given windowing mode.
278 * If there was already a TaskOrganizer for this windowing mode it will be evicted
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800279 * but will continue to organize it's existing tasks.
Robert Carr8a2f9132019-11-11 15:03:15 -0800280 */
Evan Rosky0037e5f2019-11-05 10:26:24 -0800281 @Override
282 public void registerTaskOrganizer(ITaskOrganizer organizer, int windowingMode) {
Evan Roskyb8540a02020-03-25 16:30:24 -0700283 if (windowingMode == WINDOWING_MODE_PINNED) {
284 if (!mService.mSupportsPictureInPicture) {
285 throw new UnsupportedOperationException("Picture in picture is not supported on "
286 + "this device");
287 }
288 } else if (WindowConfiguration.isSplitScreenWindowingMode(windowingMode)) {
289 if (!mService.mSupportsSplitScreenMultiWindow) {
290 throw new UnsupportedOperationException("Split-screen is not supported on this "
291 + "device");
292 }
293 } else if (windowingMode == WINDOWING_MODE_MULTI_WINDOW) {
294 if (!mService.mSupportsMultiWindow) {
295 throw new UnsupportedOperationException("Multi-window is not supported on this "
296 + "device");
297 }
298 } else {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800299 throw new UnsupportedOperationException("As of now only Pinned/Split/Multiwindow"
300 + " windowing modes are supported for registerTaskOrganizer");
Robert Carr8a2f9132019-11-11 15:03:15 -0800301 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800302 enforceStackPermission("registerTaskOrganizer()");
Winson Chung268eccb2020-03-26 13:43:44 -0700303 final int uid = Binder.getCallingUid();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800304 final long origId = Binder.clearCallingIdentity();
Robert Carr8a2f9132019-11-11 15:03:15 -0800305 try {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800306 synchronized (mGlobalLock) {
Winson Chung77338ab2020-03-09 16:32:34 -0700307 if (getTaskOrganizer(windowingMode) != null) {
308 Slog.w(TAG, "Task organizer already exists for windowing mode: "
309 + windowingMode);
310 }
Winson Chungaff506b2020-03-21 22:56:31 -0700311
Evan Roskyb8540a02020-03-25 16:30:24 -0700312 LinkedList<IBinder> orgs = mTaskOrganizersForWindowingMode.get(windowingMode);
313 if (orgs == null) {
314 orgs = new LinkedList<>();
315 mTaskOrganizersForWindowingMode.put(windowingMode, orgs);
Winson Chungaff506b2020-03-21 22:56:31 -0700316 }
Evan Roskyb8540a02020-03-25 16:30:24 -0700317 orgs.add(organizer.asBinder());
318 if (!mTaskOrganizerStates.containsKey(organizer.asBinder())) {
319 mTaskOrganizerStates.put(organizer.asBinder(),
Winson Chung268eccb2020-03-26 13:43:44 -0700320 new TaskOrganizerState(organizer, uid));
Evan Roskyb8540a02020-03-25 16:30:24 -0700321 }
Winson Chung77338ab2020-03-09 16:32:34 -0700322
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700323 mService.mRootWindowContainer.forAllTasks((task) -> {
324 if (task.getWindowingMode() == windowingMode) {
325 task.updateTaskOrganizerState(true /* forceUpdate */);
326 }
327 });
Evan Rosky0037e5f2019-11-05 10:26:24 -0800328 }
329 } finally {
330 Binder.restoreCallingIdentity(origId);
Robert Carr8a2f9132019-11-11 15:03:15 -0800331 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800332 }
333
Winson Chung8a168902020-03-12 22:39:22 -0700334 @Override
335 public void unregisterTaskOrganizer(ITaskOrganizer organizer) {
Riddle Hsu3c290512020-03-30 22:12:52 +0800336 enforceStackPermission("unregisterTaskOrganizer()");
337 final long origId = Binder.clearCallingIdentity();
338 try {
339 synchronized (mGlobalLock) {
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700340 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
Riddle Hsu3c290512020-03-30 22:12:52 +0800341 if (state == null) {
342 return;
343 }
344 state.unlinkDeath();
345 state.dispose();
346 }
347 } finally {
348 Binder.restoreCallingIdentity(origId);
349 }
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800350 }
351
Robert Carr8a2f9132019-11-11 15:03:15 -0800352 ITaskOrganizer getTaskOrganizer(int windowingMode) {
Evan Roskyb8540a02020-03-25 16:30:24 -0700353 final IBinder organizer =
354 mTaskOrganizersForWindowingMode.get(windowingMode, EMPTY_LIST).peekLast();
355 if (organizer == null) {
356 return null;
357 }
358 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer);
Robert Carr8a2f9132019-11-11 15:03:15 -0800359 if (state == null) {
360 return null;
361 }
Winson Chung1b5d0552020-04-06 19:28:49 -0700362 return state.mOrganizer.mTaskOrganizer;
Robert Carr8a2f9132019-11-11 15:03:15 -0800363 }
364
Robert Carr8a2f9132019-11-11 15:03:15 -0800365 void onTaskAppeared(ITaskOrganizer organizer, Task task) {
Robert Carre10ee3d2019-11-11 15:03:15 -0800366 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
Robert Carr8a2f9132019-11-11 15:03:15 -0800367 state.addTask(task);
Robert Carr8a2f9132019-11-11 15:03:15 -0800368 }
369
370 void onTaskVanished(ITaskOrganizer organizer, Task task) {
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800371 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700372 if (state != null) {
373 state.removeTask(task);
374 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800375 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800376
377 @Override
378 public RunningTaskInfo createRootTask(int displayId, int windowingMode) {
379 enforceStackPermission("createRootTask()");
380 final long origId = Binder.clearCallingIdentity();
381 try {
382 synchronized (mGlobalLock) {
383 DisplayContent display = mService.mRootWindowContainer.getDisplayContent(displayId);
384 if (display == null) {
385 return null;
386 }
Louis Changa009c762020-02-26 11:21:31 +0800387
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700388 final Task task = display.getDefaultTaskDisplayArea().createStack(windowingMode,
Wale Ogunwalec27e1ac2020-03-31 13:18:47 -0700389 ACTIVITY_TYPE_UNDEFINED, false /* onTop */, null /* info */, new Intent(),
390 true /* createdByOrganizer */);
Louis Changa009c762020-02-26 11:21:31 +0800391 RunningTaskInfo out = task.getTaskInfo();
392 mLastSentTaskInfos.put(task, out);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800393 return out;
394 }
395 } finally {
396 Binder.restoreCallingIdentity(origId);
397 }
398 }
399
400 @Override
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700401 public boolean deleteRootTask(WindowContainerToken token) {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800402 enforceStackPermission("deleteRootTask()");
403 final long origId = Binder.clearCallingIdentity();
404 try {
405 synchronized (mGlobalLock) {
Louis Changa009c762020-02-26 11:21:31 +0800406 final Task task = WindowContainer.fromBinder(token.asBinder()).asTask();
407 if (task == null) return false;
408 if (!task.mCreatedByOrganizer) {
409 throw new IllegalArgumentException(
410 "Attempt to delete task not created by organizer task=" + task);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800411 }
Louis Changa009c762020-02-26 11:21:31 +0800412 task.removeImmediately();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800413 return true;
414 }
415 } finally {
416 Binder.restoreCallingIdentity(origId);
417 }
418 }
419
420 void dispatchPendingTaskInfoChanges() {
421 if (mService.mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) {
422 return;
423 }
424 for (int i = 0, n = mPendingTaskInfoChanges.size(); i < n; ++i) {
425 dispatchTaskInfoChanged(mPendingTaskInfoChanges.get(i), false /* force */);
426 }
427 mPendingTaskInfoChanges.clear();
428 }
429
430 void dispatchTaskInfoChanged(Task task, boolean force) {
431 if (!force && mService.mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) {
432 // Defer task info reporting while layout is deferred. This is because layout defer
433 // blocks tend to do lots of re-ordering which can mess up animations in receivers.
434 mPendingTaskInfoChanges.remove(task);
435 mPendingTaskInfoChanges.add(task);
436 return;
437 }
438 RunningTaskInfo lastInfo = mLastSentTaskInfos.get(task);
439 if (mTmpTaskInfo == null) {
440 mTmpTaskInfo = new RunningTaskInfo();
441 }
Evan Roskyf64f5da2020-03-16 13:47:48 -0700442 mTmpTaskInfo.configuration.unset();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800443 task.fillTaskInfo(mTmpTaskInfo);
444 boolean changed = lastInfo == null
445 || mTmpTaskInfo.topActivityType != lastInfo.topActivityType
Hongwei Wang85cf41f2020-01-15 15:14:47 -0800446 || mTmpTaskInfo.isResizable() != lastInfo.isResizable()
Winson Chung1df39e22020-04-09 14:30:55 -0700447 || mTmpTaskInfo.pictureInPictureParams != lastInfo.pictureInPictureParams
448 || !TaskDescription.equals(mTmpTaskInfo.taskDescription, lastInfo.taskDescription);
Evan Roskyf64f5da2020-03-16 13:47:48 -0700449 if (!changed) {
450 int cfgChanges = mTmpTaskInfo.configuration.diff(lastInfo.configuration);
451 final int winCfgChanges = (cfgChanges & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0
452 ? (int) mTmpTaskInfo.configuration.windowConfiguration.diff(
453 lastInfo.configuration.windowConfiguration,
454 true /* compareUndefined */) : 0;
455 if ((winCfgChanges & REPORT_WINDOW_CONFIGS) == 0) {
456 cfgChanges &= ~ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
457 }
458 changed = (cfgChanges & REPORT_CONFIGS) != 0;
459 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800460 if (!(changed || force)) {
461 return;
462 }
463 final RunningTaskInfo newInfo = mTmpTaskInfo;
464 mLastSentTaskInfos.put(task, mTmpTaskInfo);
465 // Since we've stored this, clean up the reference so a new one will be created next time.
466 // Transferring it this way means we only have to construct new RunningTaskInfos when they
467 // change.
468 mTmpTaskInfo = null;
469
Winson Chung1b5d0552020-04-06 19:28:49 -0700470 if (task.isOrganized()) {
Winson Chung8b5d23a2020-04-06 19:23:23 -0700471 // Because we defer sending taskAppeared() until the app has drawn, we may receive a
472 // configuration change before the state actually has the task registered. As such we
473 // should ignore these change events to the organizer until taskAppeared(). If the task
474 // was created by the organizer, then we always send the info change.
Winson Chung1b5d0552020-04-06 19:28:49 -0700475 final TaskOrganizerState state = mTaskOrganizerStates.get(
476 task.mTaskOrganizer.asBinder());
Winson Chung8b5d23a2020-04-06 19:23:23 -0700477 if (state != null) {
478 state.mOrganizer.onTaskInfoChanged(task, newInfo);
479 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800480 }
481 }
482
483 @Override
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700484 public WindowContainerToken getImeTarget(int displayId) {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800485 enforceStackPermission("getImeTarget()");
486 final long origId = Binder.clearCallingIdentity();
487 try {
488 synchronized (mGlobalLock) {
489 DisplayContent dc = mService.mWindowManager.mRoot
490 .getDisplayContent(displayId);
491 if (dc == null || dc.mInputMethodTarget == null) {
492 return null;
493 }
494 // Avoid WindowState#getRootTask() so we don't attribute system windows to a task.
495 final Task task = dc.mInputMethodTarget.getTask();
496 if (task == null) {
497 return null;
498 }
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700499 return task.getRootTask().mRemoteToken.toWindowContainerToken();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800500 }
501 } finally {
502 Binder.restoreCallingIdentity(origId);
503 }
504 }
505
506 @Override
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700507 public void setLaunchRoot(int displayId, @Nullable WindowContainerToken token) {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800508 enforceStackPermission("setLaunchRoot()");
509 final long origId = Binder.clearCallingIdentity();
510 try {
511 synchronized (mGlobalLock) {
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700512 TaskDisplayArea defaultTaskDisplayArea = mService.mRootWindowContainer
513 .getDisplayContent(displayId).getDefaultTaskDisplayArea();
514 if (defaultTaskDisplayArea == null) {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800515 return;
516 }
Louis Changa009c762020-02-26 11:21:31 +0800517 Task task = token == null
518 ? null : WindowContainer.fromBinder(token.asBinder()).asTask();
519 if (task == null) {
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700520 defaultTaskDisplayArea.mLaunchRootTask = null;
Evan Rosky0037e5f2019-11-05 10:26:24 -0800521 return;
522 }
Louis Changa009c762020-02-26 11:21:31 +0800523 if (!task.mCreatedByOrganizer) {
524 throw new IllegalArgumentException("Attempt to set task not created by "
525 + "organizer as launch root task=" + task);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800526 }
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700527 if (task.getDisplayArea() == null
528 || task.getDisplayArea().getDisplayId() != displayId) {
Louis Changa009c762020-02-26 11:21:31 +0800529 throw new RuntimeException("Can't set launch root for display " + displayId
530 + " to task on display " + task.getDisplayContent().getDisplayId());
531 }
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700532 task.getDisplayArea().mLaunchRootTask = task;
Evan Rosky0037e5f2019-11-05 10:26:24 -0800533 }
534 } finally {
535 Binder.restoreCallingIdentity(origId);
536 }
537 }
538
Evan Roskya8fde152020-01-07 19:09:13 -0800539 @Override
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700540 public List<RunningTaskInfo> getChildTasks(WindowContainerToken parent,
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800541 @Nullable int[] activityTypes) {
Evan Roskya8fde152020-01-07 19:09:13 -0800542 enforceStackPermission("getChildTasks()");
543 final long ident = Binder.clearCallingIdentity();
544 try {
545 synchronized (mGlobalLock) {
546 if (parent == null) {
547 throw new IllegalArgumentException("Can't get children of null parent");
548 }
549 final WindowContainer container = WindowContainer.fromBinder(parent.asBinder());
550 if (container == null) {
551 Slog.e(TAG, "Can't get children of " + parent + " because it is not valid.");
552 return null;
553 }
Louis Changa009c762020-02-26 11:21:31 +0800554 final Task task = container.asTask();
555 if (task == null) {
556 Slog.e(TAG, container + " is not a task...");
557 return null;
558 }
559 // For now, only support returning children of tasks created by the organizer.
560 if (!task.mCreatedByOrganizer) {
Evan Roskya8fde152020-01-07 19:09:13 -0800561 Slog.w(TAG, "Can only get children of root tasks created via createRootTask");
562 return null;
563 }
564 ArrayList<RunningTaskInfo> out = new ArrayList<>();
Louis Changa009c762020-02-26 11:21:31 +0800565 for (int i = task.getChildCount() - 1; i >= 0; --i) {
566 final Task child = task.getChildAt(i).asTask();
567 if (child == null) continue;
568 if (activityTypes != null
569 && !ArrayUtils.contains(activityTypes, child.getActivityType())) {
570 continue;
Evan Roskya8fde152020-01-07 19:09:13 -0800571 }
Louis Changa009c762020-02-26 11:21:31 +0800572 out.add(child.getTaskInfo());
Evan Roskya8fde152020-01-07 19:09:13 -0800573 }
574 return out;
575 }
576 } finally {
577 Binder.restoreCallingIdentity(ident);
578 }
579 }
580
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800581 @Override
582 public List<RunningTaskInfo> getRootTasks(int displayId, @Nullable int[] activityTypes) {
583 enforceStackPermission("getRootTasks()");
584 final long ident = Binder.clearCallingIdentity();
585 try {
586 synchronized (mGlobalLock) {
587 final DisplayContent dc =
588 mService.mRootWindowContainer.getDisplayContent(displayId);
589 if (dc == null) {
590 throw new IllegalArgumentException("Display " + displayId + " doesn't exist");
591 }
592 ArrayList<RunningTaskInfo> out = new ArrayList<>();
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700593 for (int tdaNdx = dc.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
594 final TaskDisplayArea taskDisplayArea = dc.getTaskDisplayAreaAt(tdaNdx);
595 for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
596 final Task task = taskDisplayArea.getStackAt(sNdx);
597 if (activityTypes != null
598 && !ArrayUtils.contains(activityTypes, task.getActivityType())) {
599 continue;
600 }
601 out.add(task.getTaskInfo());
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800602 }
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800603 }
604 return out;
605 }
606 } finally {
607 Binder.restoreCallingIdentity(ident);
608 }
609 }
Winson Chung268eccb2020-03-26 13:43:44 -0700610
Winson Chunga1f869d2020-03-21 23:02:48 -0700611 @Override
612 public void setInterceptBackPressedOnTaskRoot(ITaskOrganizer organizer,
613 boolean interceptBackPressed) {
614 enforceStackPermission("setInterceptBackPressedOnTaskRoot()");
615 final long origId = Binder.clearCallingIdentity();
616 try {
617 synchronized (mGlobalLock) {
618 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
619 if (state != null) {
620 state.setInterceptBackPressedOnTaskRoot(interceptBackPressed);
621 }
622 }
623 } finally {
624 Binder.restoreCallingIdentity(origId);
625 }
626 }
627
628 public boolean handleInterceptBackPressedOnTaskRoot(Task task) {
629 if (task == null || !task.isOrganized()) {
630 return false;
631 }
632
633 final TaskOrganizerState state = mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder());
634 if (!state.mInterceptBackPressedOnTaskRoot) {
635 return false;
636 }
637
Winson Chung1b5d0552020-04-06 19:28:49 -0700638 state.mOrganizer.onBackPressedOnTaskRoot(task);
Winson Chunga1f869d2020-03-21 23:02:48 -0700639 return true;
640 }
641
Winson Chung268eccb2020-03-26 13:43:44 -0700642 public void dump(PrintWriter pw, String prefix) {
643 final String innerPrefix = prefix + " ";
644 pw.print(prefix); pw.println("TaskOrganizerController:");
645 pw.print(innerPrefix); pw.println("Per windowing mode:");
646 for (int i = 0; i < mTaskOrganizersForWindowingMode.size(); i++) {
647 final int windowingMode = mTaskOrganizersForWindowingMode.keyAt(i);
648 final List<IBinder> taskOrgs = mTaskOrganizersForWindowingMode.valueAt(i);
649 pw.println(innerPrefix + " "
650 + WindowConfiguration.windowingModeToString(windowingMode) + ":");
651 for (int j = 0; j < taskOrgs.size(); j++) {
652 final TaskOrganizerState state = mTaskOrganizerStates.get(taskOrgs.get(j));
653 final ArrayList<Task> tasks = state.mOrganizedTasks;
654 pw.print(innerPrefix + " ");
Winson Chung1b5d0552020-04-06 19:28:49 -0700655 pw.println(state.mOrganizer.mTaskOrganizer + " uid=" + state.mUid + ":");
Winson Chung268eccb2020-03-26 13:43:44 -0700656 for (int k = 0; k < tasks.size(); k++) {
657 pw.println(innerPrefix + " " + tasks.get(k));
658 }
659 }
660
661 }
662 pw.println();
663 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800664}