blob: 9873031e0138c65d73e39f7b38a14d4996fc1b59 [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;
Evan Roskyb8540a02020-03-25 16:30:24 -070030import android.app.WindowConfiguration;
Louis Changa009c762020-02-26 11:21:31 +080031import android.content.Intent;
Evan Rosky0037e5f2019-11-05 10:26:24 -080032import android.content.pm.ActivityInfo;
Evan Rosky0037e5f2019-11-05 10:26:24 -080033import android.os.Binder;
Robert Carr8a2f9132019-11-11 15:03:15 -080034import android.os.IBinder;
35import android.os.RemoteException;
36import android.util.Slog;
Winson Chungaff506b2020-03-21 22:56:31 -070037import android.util.SparseArray;
Wale Ogunwale57946582020-03-21 14:29:07 -070038import android.window.ITaskOrganizer;
Louis Changa009c762020-02-26 11:21:31 +080039import android.window.ITaskOrganizerController;
Wale Ogunwaleadf116e2020-03-27 16:36:01 -070040import android.window.WindowContainerToken;
Evan Rosky0037e5f2019-11-05 10:26:24 -080041
Winson Chung1b5d0552020-04-06 19:28:49 -070042import com.android.internal.annotations.VisibleForTesting;
Evan Rosky29d4a0a2020-02-04 16:40:44 -080043import com.android.internal.util.ArrayUtils;
Robert Carr8a2f9132019-11-11 15:03:15 -080044
Winson Chung268eccb2020-03-26 13:43:44 -070045import java.io.PrintWriter;
Robert Carr8a2f9132019-11-11 15:03:15 -080046import java.util.ArrayList;
47import java.util.HashMap;
Winson Chungaff506b2020-03-21 22:56:31 -070048import java.util.LinkedList;
Evan Roskya8fde152020-01-07 19:09:13 -080049import java.util.List;
Evan Rosky0037e5f2019-11-05 10:26:24 -080050import java.util.WeakHashMap;
Winson Chung1b5d0552020-04-06 19:28:49 -070051import java.util.function.Consumer;
Robert Carr8a2f9132019-11-11 15:03:15 -080052
53/**
54 * Stores the TaskOrganizers associated with a given windowing mode and
55 * their associated state.
56 */
Wale Ogunwale568f9f412020-03-21 22:27:35 -070057class TaskOrganizerController extends ITaskOrganizerController.Stub {
Robert Carr8a2f9132019-11-11 15:03:15 -080058 private static final String TAG = "TaskOrganizerController";
Evan Roskyb8540a02020-03-25 16:30:24 -070059 private static final LinkedList<IBinder> EMPTY_LIST = new LinkedList<>();
Robert Carr8a2f9132019-11-11 15:03:15 -080060
Evan Roskyf64f5da2020-03-16 13:47:48 -070061 /**
62 * Masks specifying which configurations are important to report back to an organizer when
63 * changed.
64 */
65 private static final int REPORT_CONFIGS = CONTROLLABLE_CONFIGS;
66 private static final int REPORT_WINDOW_CONFIGS = CONTROLLABLE_WINDOW_CONFIGS;
67
Evan Rosky0037e5f2019-11-05 10:26:24 -080068 private final WindowManagerGlobalLock mGlobalLock;
Robert Carr8a2f9132019-11-11 15:03:15 -080069
70 private class DeathRecipient implements IBinder.DeathRecipient {
Robert Carr8a2f9132019-11-11 15:03:15 -080071 ITaskOrganizer mTaskOrganizer;
72
Evan Roskyb8540a02020-03-25 16:30:24 -070073 DeathRecipient(ITaskOrganizer organizer) {
Robert Carr8a2f9132019-11-11 15:03:15 -080074 mTaskOrganizer = organizer;
Robert Carr8a2f9132019-11-11 15:03:15 -080075 }
76
77 @Override
78 public void binderDied() {
79 synchronized (mGlobalLock) {
Winson Chungaff506b2020-03-21 22:56:31 -070080 final TaskOrganizerState state = mTaskOrganizerStates.remove(
81 mTaskOrganizer.asBinder());
Riddle Hsu3c290512020-03-30 22:12:52 +080082 if (state != null) {
83 state.dispose();
84 }
Robert Carr8a2f9132019-11-11 15:03:15 -080085 }
86 }
Winson Chung1b5d0552020-04-06 19:28:49 -070087 }
88
89 /**
90 * A wrapper class around ITaskOrganizer to ensure that the calls are made in the right
91 * lifecycle order since we may be updating the visibility of task surface controls in a pending
92 * transaction before they are presented to the task org.
93 */
94 private class TaskOrganizerCallbacks {
95 final WindowManagerService mService;
96 final ITaskOrganizer mTaskOrganizer;
97 final Consumer<Runnable> mDeferTaskOrgCallbacksConsumer;
98
99 TaskOrganizerCallbacks(WindowManagerService wm, ITaskOrganizer taskOrg,
100 Consumer<Runnable> deferTaskOrgCallbacksConsumer) {
101 mService = wm;
102 mDeferTaskOrgCallbacksConsumer = deferTaskOrgCallbacksConsumer;
103 mTaskOrganizer = taskOrg;
104 }
105
106 IBinder getBinder() {
107 return mTaskOrganizer.asBinder();
108 }
109
110 void onTaskAppeared(Task task) {
111 final RunningTaskInfo taskInfo = task.getTaskInfo();
112 mDeferTaskOrgCallbacksConsumer.accept(() -> {
113 try {
114 mTaskOrganizer.onTaskAppeared(taskInfo);
115 } catch (RemoteException e) {
116 Slog.e(TAG, "Exception sending onTaskAppeared callback", e);
117 }
118 });
119 }
120
121
122 void onTaskVanished(Task task) {
123 final RunningTaskInfo taskInfo = task.getTaskInfo();
124 mDeferTaskOrgCallbacksConsumer.accept(() -> {
125 try {
126 mTaskOrganizer.onTaskVanished(taskInfo);
127 } catch (RemoteException e) {
128 Slog.e(TAG, "Exception sending onTaskVanished callback", e);
129 }
130 });
131 }
132
133 void onTaskInfoChanged(Task task, ActivityManager.RunningTaskInfo taskInfo) {
Winson Chung8b5d23a2020-04-06 19:23:23 -0700134 if (!task.mCreatedByOrganizer && !task.mTaskAppearedSent) {
135 // Skip if the task has not yet received taskAppeared(), except for tasks created
136 // by the organizer that don't receive that signal
137 return;
138 }
Winson Chung1b5d0552020-04-06 19:28:49 -0700139 mDeferTaskOrgCallbacksConsumer.accept(() -> {
140 if (!task.isOrganized()) {
141 // This is safe to ignore if the task is no longer organized
142 return;
143 }
144 try {
145 mTaskOrganizer.onTaskInfoChanged(taskInfo);
146 } catch (RemoteException e) {
147 Slog.e(TAG, "Exception sending onTaskInfoChanged callback", e);
148 }
149 });
150 }
151
152 void onBackPressedOnTaskRoot(Task task) {
Winson Chung8b5d23a2020-04-06 19:23:23 -0700153 if (!task.mCreatedByOrganizer && !task.mTaskAppearedSent) {
154 // Skip if the task has not yet received taskAppeared(), except for tasks created
155 // by the organizer that don't receive that signal
156 return;
157 }
Winson Chung1b5d0552020-04-06 19:28:49 -0700158 mDeferTaskOrgCallbacksConsumer.accept(() -> {
159 if (!task.isOrganized()) {
160 // This is safe to ignore if the task is no longer organized
161 return;
162 }
163 try {
164 mTaskOrganizer.onBackPressedOnTaskRoot(task.getTaskInfo());
165 } catch (Exception e) {
166 Slog.e(TAG, "Exception sending onBackPressedOnTaskRoot callback", e);
167 }
168 });
169 }
170 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800171
Winson Chungaff506b2020-03-21 22:56:31 -0700172 private class TaskOrganizerState {
Winson Chung1b5d0552020-04-06 19:28:49 -0700173 private final TaskOrganizerCallbacks mOrganizer;
Winson Chungaff506b2020-03-21 22:56:31 -0700174 private final DeathRecipient mDeathRecipient;
Winson Chungaff506b2020-03-21 22:56:31 -0700175 private final ArrayList<Task> mOrganizedTasks = new ArrayList<>();
Winson Chung268eccb2020-03-26 13:43:44 -0700176 private final int mUid;
Winson Chunga1f869d2020-03-21 23:02:48 -0700177 private boolean mInterceptBackPressedOnTaskRoot;
Robert Carr8a2f9132019-11-11 15:03:15 -0800178
Winson Chung268eccb2020-03-26 13:43:44 -0700179 TaskOrganizerState(ITaskOrganizer organizer, int uid) {
Winson Chung1b5d0552020-04-06 19:28:49 -0700180 final Consumer<Runnable> deferTaskOrgCallbacksConsumer =
181 mDeferTaskOrgCallbacksConsumer != null
182 ? mDeferTaskOrgCallbacksConsumer
183 : mService.mWindowManager.mAnimator::addAfterPrepareSurfacesRunnable;
184 mOrganizer = new TaskOrganizerCallbacks(mService.mWindowManager, organizer,
185 deferTaskOrgCallbacksConsumer);
Evan Roskyb8540a02020-03-25 16:30:24 -0700186 mDeathRecipient = new DeathRecipient(organizer);
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800187 try {
188 organizer.asBinder().linkToDeath(mDeathRecipient, 0);
189 } catch (RemoteException e) {
190 Slog.e(TAG, "TaskOrganizer failed to register death recipient");
191 }
Winson Chung268eccb2020-03-26 13:43:44 -0700192 mUid = uid;
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800193 }
194
Winson Chunga1f869d2020-03-21 23:02:48 -0700195 void setInterceptBackPressedOnTaskRoot(boolean interceptBackPressed) {
196 mInterceptBackPressedOnTaskRoot = interceptBackPressed;
197 }
198
Robert Carr8a2f9132019-11-11 15:03:15 -0800199 void addTask(Task t) {
Louis Chang9d35a3a2020-04-06 17:23:02 +0800200 if (t.mTaskAppearedSent) return;
201
202 if (!mOrganizedTasks.contains(t)) {
203 mOrganizedTasks.add(t);
204 }
205 if (t.taskAppearedReady()) {
Winson Chung8b5d23a2020-04-06 19:23:23 -0700206 t.mTaskAppearedSent = true;
207 mOrganizer.onTaskAppeared(t);
Winson Chungd2fb07e2020-04-06 18:17:21 +0000208 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800209 }
210
211 void removeTask(Task t) {
Louis Chang9d35a3a2020-04-06 17:23:02 +0800212 if (t.mTaskAppearedSent) {
Winson Chung8b5d23a2020-04-06 19:23:23 -0700213 t.mTaskAppearedSent = false;
214 mOrganizer.onTaskVanished(t);
Winson Chungd2fb07e2020-04-06 18:17:21 +0000215 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800216 mOrganizedTasks.remove(t);
217 }
218
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800219 void dispose() {
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800220 releaseTasks();
Evan Roskyb8540a02020-03-25 16:30:24 -0700221 for (int i = mTaskOrganizersForWindowingMode.size() - 1; i >= 0; --i) {
Winson Chung1b5d0552020-04-06 19:28:49 -0700222 mTaskOrganizersForWindowingMode.valueAt(i).remove(mOrganizer.getBinder());
Evan Roskyb8540a02020-03-25 16:30:24 -0700223 }
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800224 }
225
Winson Chungaff506b2020-03-21 22:56:31 -0700226 private void releaseTasks() {
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800227 for (int i = mOrganizedTasks.size() - 1; i >= 0; i--) {
228 final Task t = mOrganizedTasks.get(i);
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800229 removeTask(t);
Winson Chungaff506b2020-03-21 22:56:31 -0700230 t.taskOrganizerUnregistered();
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800231 }
232 }
233
234 void unlinkDeath() {
Winson Chung1b5d0552020-04-06 19:28:49 -0700235 mOrganizer.getBinder().unlinkToDeath(mDeathRecipient, 0);
Robert Carr8a2f9132019-11-11 15:03:15 -0800236 }
Winson Chungaff506b2020-03-21 22:56:31 -0700237 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800238
Evan Roskyb8540a02020-03-25 16:30:24 -0700239 private final SparseArray<LinkedList<IBinder>> mTaskOrganizersForWindowingMode =
Winson Chungaff506b2020-03-21 22:56:31 -0700240 new SparseArray<>();
241 private final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap<>();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800242 private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>();
243 private final ArrayList<Task> mPendingTaskInfoChanges = new ArrayList<>();
244
Winson Chung1b5d0552020-04-06 19:28:49 -0700245 private final ActivityTaskManagerService mService;
Robert Carr8a2f9132019-11-11 15:03:15 -0800246
Winson Chung1b5d0552020-04-06 19:28:49 -0700247 private RunningTaskInfo mTmpTaskInfo;
248 private Consumer<Runnable> mDeferTaskOrgCallbacksConsumer;
Evan Rosky0037e5f2019-11-05 10:26:24 -0800249
250 TaskOrganizerController(ActivityTaskManagerService atm) {
Robert Carr8a2f9132019-11-11 15:03:15 -0800251 mService = atm;
Evan Rosky0037e5f2019-11-05 10:26:24 -0800252 mGlobalLock = atm.mGlobalLock;
253 }
254
255 private void enforceStackPermission(String func) {
256 mService.mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, func);
Robert Carr8a2f9132019-11-11 15:03:15 -0800257 }
258
Robert Carr8a2f9132019-11-11 15:03:15 -0800259 /**
Winson Chung1b5d0552020-04-06 19:28:49 -0700260 * Specifies the consumer to run to defer the task org callbacks. Can be overridden while
261 * testing to allow the callbacks to be sent synchronously.
262 */
263 @VisibleForTesting
264 public void setDeferTaskOrgCallbacksConsumer(Consumer<Runnable> consumer) {
265 mDeferTaskOrgCallbacksConsumer = consumer;
266 }
267
268 /**
Robert Carr8a2f9132019-11-11 15:03:15 -0800269 * Register a TaskOrganizer to manage tasks as they enter the given windowing mode.
270 * If there was already a TaskOrganizer for this windowing mode it will be evicted
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800271 * but will continue to organize it's existing tasks.
Robert Carr8a2f9132019-11-11 15:03:15 -0800272 */
Evan Rosky0037e5f2019-11-05 10:26:24 -0800273 @Override
274 public void registerTaskOrganizer(ITaskOrganizer organizer, int windowingMode) {
Evan Roskyb8540a02020-03-25 16:30:24 -0700275 if (windowingMode == WINDOWING_MODE_PINNED) {
276 if (!mService.mSupportsPictureInPicture) {
277 throw new UnsupportedOperationException("Picture in picture is not supported on "
278 + "this device");
279 }
280 } else if (WindowConfiguration.isSplitScreenWindowingMode(windowingMode)) {
281 if (!mService.mSupportsSplitScreenMultiWindow) {
282 throw new UnsupportedOperationException("Split-screen is not supported on this "
283 + "device");
284 }
285 } else if (windowingMode == WINDOWING_MODE_MULTI_WINDOW) {
286 if (!mService.mSupportsMultiWindow) {
287 throw new UnsupportedOperationException("Multi-window is not supported on this "
288 + "device");
289 }
290 } else {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800291 throw new UnsupportedOperationException("As of now only Pinned/Split/Multiwindow"
292 + " windowing modes are supported for registerTaskOrganizer");
Robert Carr8a2f9132019-11-11 15:03:15 -0800293 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800294 enforceStackPermission("registerTaskOrganizer()");
Winson Chung268eccb2020-03-26 13:43:44 -0700295 final int uid = Binder.getCallingUid();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800296 final long origId = Binder.clearCallingIdentity();
Robert Carr8a2f9132019-11-11 15:03:15 -0800297 try {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800298 synchronized (mGlobalLock) {
Winson Chung77338ab2020-03-09 16:32:34 -0700299 if (getTaskOrganizer(windowingMode) != null) {
300 Slog.w(TAG, "Task organizer already exists for windowing mode: "
301 + windowingMode);
302 }
Winson Chungaff506b2020-03-21 22:56:31 -0700303
Evan Roskyb8540a02020-03-25 16:30:24 -0700304 LinkedList<IBinder> orgs = mTaskOrganizersForWindowingMode.get(windowingMode);
305 if (orgs == null) {
306 orgs = new LinkedList<>();
307 mTaskOrganizersForWindowingMode.put(windowingMode, orgs);
Winson Chungaff506b2020-03-21 22:56:31 -0700308 }
Evan Roskyb8540a02020-03-25 16:30:24 -0700309 orgs.add(organizer.asBinder());
310 if (!mTaskOrganizerStates.containsKey(organizer.asBinder())) {
311 mTaskOrganizerStates.put(organizer.asBinder(),
Winson Chung268eccb2020-03-26 13:43:44 -0700312 new TaskOrganizerState(organizer, uid));
Evan Roskyb8540a02020-03-25 16:30:24 -0700313 }
Winson Chung77338ab2020-03-09 16:32:34 -0700314
Evan Roskyb8540a02020-03-25 16:30:24 -0700315 if (orgs.size() == 1) {
Winson Chung77338ab2020-03-09 16:32:34 -0700316 // Only in the case where this is the root task organizer for the given
317 // windowing mode, we add report all existing tasks in that mode to the new
318 // task organizer.
319 mService.mRootWindowContainer.forAllTasks((task) -> {
320 if (task.getWindowingMode() == windowingMode) {
321 task.updateTaskOrganizerState(true /* forceUpdate */);
322 }
323 });
324 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800325 }
326 } finally {
327 Binder.restoreCallingIdentity(origId);
Robert Carr8a2f9132019-11-11 15:03:15 -0800328 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800329 }
330
Winson Chung8a168902020-03-12 22:39:22 -0700331 @Override
332 public void unregisterTaskOrganizer(ITaskOrganizer organizer) {
Riddle Hsu3c290512020-03-30 22:12:52 +0800333 enforceStackPermission("unregisterTaskOrganizer()");
334 final long origId = Binder.clearCallingIdentity();
335 try {
336 synchronized (mGlobalLock) {
337 final TaskOrganizerState state = mTaskOrganizerStates.remove(organizer.asBinder());
338 if (state == null) {
339 return;
340 }
341 state.unlinkDeath();
342 state.dispose();
343 }
344 } finally {
345 Binder.restoreCallingIdentity(origId);
346 }
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800347 }
348
Robert Carr8a2f9132019-11-11 15:03:15 -0800349 ITaskOrganizer getTaskOrganizer(int windowingMode) {
Evan Roskyb8540a02020-03-25 16:30:24 -0700350 final IBinder organizer =
351 mTaskOrganizersForWindowingMode.get(windowingMode, EMPTY_LIST).peekLast();
352 if (organizer == null) {
353 return null;
354 }
355 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer);
Robert Carr8a2f9132019-11-11 15:03:15 -0800356 if (state == null) {
357 return null;
358 }
Winson Chung1b5d0552020-04-06 19:28:49 -0700359 return state.mOrganizer.mTaskOrganizer;
Robert Carr8a2f9132019-11-11 15:03:15 -0800360 }
361
Robert Carr8a2f9132019-11-11 15:03:15 -0800362 void onTaskAppeared(ITaskOrganizer organizer, Task task) {
Robert Carre10ee3d2019-11-11 15:03:15 -0800363 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
Robert Carr8a2f9132019-11-11 15:03:15 -0800364 state.addTask(task);
Robert Carr8a2f9132019-11-11 15:03:15 -0800365 }
366
367 void onTaskVanished(ITaskOrganizer organizer, Task task) {
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800368 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
Robert Carr8a2f9132019-11-11 15:03:15 -0800369 state.removeTask(task);
370 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800371
372 @Override
373 public RunningTaskInfo createRootTask(int displayId, int windowingMode) {
374 enforceStackPermission("createRootTask()");
375 final long origId = Binder.clearCallingIdentity();
376 try {
377 synchronized (mGlobalLock) {
378 DisplayContent display = mService.mRootWindowContainer.getDisplayContent(displayId);
379 if (display == null) {
380 return null;
381 }
Louis Changa009c762020-02-26 11:21:31 +0800382
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700383 final Task task = display.getDefaultTaskDisplayArea().createStack(windowingMode,
Wale Ogunwalec27e1ac2020-03-31 13:18:47 -0700384 ACTIVITY_TYPE_UNDEFINED, false /* onTop */, null /* info */, new Intent(),
385 true /* createdByOrganizer */);
Louis Changa009c762020-02-26 11:21:31 +0800386 RunningTaskInfo out = task.getTaskInfo();
387 mLastSentTaskInfos.put(task, out);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800388 return out;
389 }
390 } finally {
391 Binder.restoreCallingIdentity(origId);
392 }
393 }
394
395 @Override
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700396 public boolean deleteRootTask(WindowContainerToken token) {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800397 enforceStackPermission("deleteRootTask()");
398 final long origId = Binder.clearCallingIdentity();
399 try {
400 synchronized (mGlobalLock) {
Louis Changa009c762020-02-26 11:21:31 +0800401 final Task task = WindowContainer.fromBinder(token.asBinder()).asTask();
402 if (task == null) return false;
403 if (!task.mCreatedByOrganizer) {
404 throw new IllegalArgumentException(
405 "Attempt to delete task not created by organizer task=" + task);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800406 }
Louis Changa009c762020-02-26 11:21:31 +0800407 task.removeImmediately();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800408 return true;
409 }
410 } finally {
411 Binder.restoreCallingIdentity(origId);
412 }
413 }
414
415 void dispatchPendingTaskInfoChanges() {
416 if (mService.mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) {
417 return;
418 }
419 for (int i = 0, n = mPendingTaskInfoChanges.size(); i < n; ++i) {
420 dispatchTaskInfoChanged(mPendingTaskInfoChanges.get(i), false /* force */);
421 }
422 mPendingTaskInfoChanges.clear();
423 }
424
425 void dispatchTaskInfoChanged(Task task, boolean force) {
426 if (!force && mService.mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) {
427 // Defer task info reporting while layout is deferred. This is because layout defer
428 // blocks tend to do lots of re-ordering which can mess up animations in receivers.
429 mPendingTaskInfoChanges.remove(task);
430 mPendingTaskInfoChanges.add(task);
431 return;
432 }
433 RunningTaskInfo lastInfo = mLastSentTaskInfos.get(task);
434 if (mTmpTaskInfo == null) {
435 mTmpTaskInfo = new RunningTaskInfo();
436 }
Evan Roskyf64f5da2020-03-16 13:47:48 -0700437 mTmpTaskInfo.configuration.unset();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800438 task.fillTaskInfo(mTmpTaskInfo);
439 boolean changed = lastInfo == null
440 || mTmpTaskInfo.topActivityType != lastInfo.topActivityType
Hongwei Wang85cf41f2020-01-15 15:14:47 -0800441 || mTmpTaskInfo.isResizable() != lastInfo.isResizable()
442 || mTmpTaskInfo.pictureInPictureParams != lastInfo.pictureInPictureParams;
Evan Roskyf64f5da2020-03-16 13:47:48 -0700443 if (!changed) {
444 int cfgChanges = mTmpTaskInfo.configuration.diff(lastInfo.configuration);
445 final int winCfgChanges = (cfgChanges & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0
446 ? (int) mTmpTaskInfo.configuration.windowConfiguration.diff(
447 lastInfo.configuration.windowConfiguration,
448 true /* compareUndefined */) : 0;
449 if ((winCfgChanges & REPORT_WINDOW_CONFIGS) == 0) {
450 cfgChanges &= ~ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
451 }
452 changed = (cfgChanges & REPORT_CONFIGS) != 0;
453 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800454 if (!(changed || force)) {
455 return;
456 }
457 final RunningTaskInfo newInfo = mTmpTaskInfo;
458 mLastSentTaskInfos.put(task, mTmpTaskInfo);
459 // Since we've stored this, clean up the reference so a new one will be created next time.
460 // Transferring it this way means we only have to construct new RunningTaskInfos when they
461 // change.
462 mTmpTaskInfo = null;
463
Winson Chung1b5d0552020-04-06 19:28:49 -0700464 if (task.isOrganized()) {
Winson Chung8b5d23a2020-04-06 19:23:23 -0700465 // Because we defer sending taskAppeared() until the app has drawn, we may receive a
466 // configuration change before the state actually has the task registered. As such we
467 // should ignore these change events to the organizer until taskAppeared(). If the task
468 // was created by the organizer, then we always send the info change.
Winson Chung1b5d0552020-04-06 19:28:49 -0700469 final TaskOrganizerState state = mTaskOrganizerStates.get(
470 task.mTaskOrganizer.asBinder());
Winson Chung8b5d23a2020-04-06 19:23:23 -0700471 if (state != null) {
472 state.mOrganizer.onTaskInfoChanged(task, newInfo);
473 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800474 }
475 }
476
477 @Override
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700478 public WindowContainerToken getImeTarget(int displayId) {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800479 enforceStackPermission("getImeTarget()");
480 final long origId = Binder.clearCallingIdentity();
481 try {
482 synchronized (mGlobalLock) {
483 DisplayContent dc = mService.mWindowManager.mRoot
484 .getDisplayContent(displayId);
485 if (dc == null || dc.mInputMethodTarget == null) {
486 return null;
487 }
488 // Avoid WindowState#getRootTask() so we don't attribute system windows to a task.
489 final Task task = dc.mInputMethodTarget.getTask();
490 if (task == null) {
491 return null;
492 }
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700493 return task.getRootTask().mRemoteToken.toWindowContainerToken();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800494 }
495 } finally {
496 Binder.restoreCallingIdentity(origId);
497 }
498 }
499
500 @Override
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700501 public void setLaunchRoot(int displayId, @Nullable WindowContainerToken token) {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800502 enforceStackPermission("setLaunchRoot()");
503 final long origId = Binder.clearCallingIdentity();
504 try {
505 synchronized (mGlobalLock) {
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700506 TaskDisplayArea defaultTaskDisplayArea = mService.mRootWindowContainer
507 .getDisplayContent(displayId).getDefaultTaskDisplayArea();
508 if (defaultTaskDisplayArea == null) {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800509 return;
510 }
Louis Changa009c762020-02-26 11:21:31 +0800511 Task task = token == null
512 ? null : WindowContainer.fromBinder(token.asBinder()).asTask();
513 if (task == null) {
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700514 defaultTaskDisplayArea.mLaunchRootTask = null;
Evan Rosky0037e5f2019-11-05 10:26:24 -0800515 return;
516 }
Louis Changa009c762020-02-26 11:21:31 +0800517 if (!task.mCreatedByOrganizer) {
518 throw new IllegalArgumentException("Attempt to set task not created by "
519 + "organizer as launch root task=" + task);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800520 }
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700521 if (task.getDisplayArea() == null
522 || task.getDisplayArea().getDisplayId() != displayId) {
Louis Changa009c762020-02-26 11:21:31 +0800523 throw new RuntimeException("Can't set launch root for display " + displayId
524 + " to task on display " + task.getDisplayContent().getDisplayId());
525 }
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700526 task.getDisplayArea().mLaunchRootTask = task;
Evan Rosky0037e5f2019-11-05 10:26:24 -0800527 }
528 } finally {
529 Binder.restoreCallingIdentity(origId);
530 }
531 }
532
Evan Roskya8fde152020-01-07 19:09:13 -0800533 @Override
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700534 public List<RunningTaskInfo> getChildTasks(WindowContainerToken parent,
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800535 @Nullable int[] activityTypes) {
Evan Roskya8fde152020-01-07 19:09:13 -0800536 enforceStackPermission("getChildTasks()");
537 final long ident = Binder.clearCallingIdentity();
538 try {
539 synchronized (mGlobalLock) {
540 if (parent == null) {
541 throw new IllegalArgumentException("Can't get children of null parent");
542 }
543 final WindowContainer container = WindowContainer.fromBinder(parent.asBinder());
544 if (container == null) {
545 Slog.e(TAG, "Can't get children of " + parent + " because it is not valid.");
546 return null;
547 }
Louis Changa009c762020-02-26 11:21:31 +0800548 final Task task = container.asTask();
549 if (task == null) {
550 Slog.e(TAG, container + " is not a task...");
551 return null;
552 }
553 // For now, only support returning children of tasks created by the organizer.
554 if (!task.mCreatedByOrganizer) {
Evan Roskya8fde152020-01-07 19:09:13 -0800555 Slog.w(TAG, "Can only get children of root tasks created via createRootTask");
556 return null;
557 }
558 ArrayList<RunningTaskInfo> out = new ArrayList<>();
Louis Changa009c762020-02-26 11:21:31 +0800559 for (int i = task.getChildCount() - 1; i >= 0; --i) {
560 final Task child = task.getChildAt(i).asTask();
561 if (child == null) continue;
562 if (activityTypes != null
563 && !ArrayUtils.contains(activityTypes, child.getActivityType())) {
564 continue;
Evan Roskya8fde152020-01-07 19:09:13 -0800565 }
Louis Changa009c762020-02-26 11:21:31 +0800566 out.add(child.getTaskInfo());
Evan Roskya8fde152020-01-07 19:09:13 -0800567 }
568 return out;
569 }
570 } finally {
571 Binder.restoreCallingIdentity(ident);
572 }
573 }
574
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800575 @Override
576 public List<RunningTaskInfo> getRootTasks(int displayId, @Nullable int[] activityTypes) {
577 enforceStackPermission("getRootTasks()");
578 final long ident = Binder.clearCallingIdentity();
579 try {
580 synchronized (mGlobalLock) {
581 final DisplayContent dc =
582 mService.mRootWindowContainer.getDisplayContent(displayId);
583 if (dc == null) {
584 throw new IllegalArgumentException("Display " + displayId + " doesn't exist");
585 }
586 ArrayList<RunningTaskInfo> out = new ArrayList<>();
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700587 for (int tdaNdx = dc.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
588 final TaskDisplayArea taskDisplayArea = dc.getTaskDisplayAreaAt(tdaNdx);
589 for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
590 final Task task = taskDisplayArea.getStackAt(sNdx);
591 if (activityTypes != null
592 && !ArrayUtils.contains(activityTypes, task.getActivityType())) {
593 continue;
594 }
595 out.add(task.getTaskInfo());
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800596 }
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800597 }
598 return out;
599 }
600 } finally {
601 Binder.restoreCallingIdentity(ident);
602 }
603 }
Winson Chung268eccb2020-03-26 13:43:44 -0700604
Winson Chunga1f869d2020-03-21 23:02:48 -0700605 @Override
606 public void setInterceptBackPressedOnTaskRoot(ITaskOrganizer organizer,
607 boolean interceptBackPressed) {
608 enforceStackPermission("setInterceptBackPressedOnTaskRoot()");
609 final long origId = Binder.clearCallingIdentity();
610 try {
611 synchronized (mGlobalLock) {
612 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
613 if (state != null) {
614 state.setInterceptBackPressedOnTaskRoot(interceptBackPressed);
615 }
616 }
617 } finally {
618 Binder.restoreCallingIdentity(origId);
619 }
620 }
621
622 public boolean handleInterceptBackPressedOnTaskRoot(Task task) {
623 if (task == null || !task.isOrganized()) {
624 return false;
625 }
626
627 final TaskOrganizerState state = mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder());
628 if (!state.mInterceptBackPressedOnTaskRoot) {
629 return false;
630 }
631
Winson Chung1b5d0552020-04-06 19:28:49 -0700632 state.mOrganizer.onBackPressedOnTaskRoot(task);
Winson Chunga1f869d2020-03-21 23:02:48 -0700633 return true;
634 }
635
Winson Chung268eccb2020-03-26 13:43:44 -0700636 public void dump(PrintWriter pw, String prefix) {
637 final String innerPrefix = prefix + " ";
638 pw.print(prefix); pw.println("TaskOrganizerController:");
639 pw.print(innerPrefix); pw.println("Per windowing mode:");
640 for (int i = 0; i < mTaskOrganizersForWindowingMode.size(); i++) {
641 final int windowingMode = mTaskOrganizersForWindowingMode.keyAt(i);
642 final List<IBinder> taskOrgs = mTaskOrganizersForWindowingMode.valueAt(i);
643 pw.println(innerPrefix + " "
644 + WindowConfiguration.windowingModeToString(windowingMode) + ":");
645 for (int j = 0; j < taskOrgs.size(); j++) {
646 final TaskOrganizerState state = mTaskOrganizerStates.get(taskOrgs.get(j));
647 final ArrayList<Task> tasks = state.mOrganizedTasks;
648 pw.print(innerPrefix + " ");
Winson Chung1b5d0552020-04-06 19:28:49 -0700649 pw.println(state.mOrganizer.mTaskOrganizer + " uid=" + state.mUid + ":");
Winson Chung268eccb2020-03-26 13:43:44 -0700650 for (int k = 0; k < tasks.size(); k++) {
651 pw.println(innerPrefix + " " + tasks.get(k));
652 }
653 }
654
655 }
656 pw.println();
657 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800658}