blob: 1da1d116b93808f82a28cf1cf3bb05f1c67f2b5c [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;
chaviw7de50002020-04-27 12:33:30 -070039import android.view.SurfaceControl;
Wale Ogunwale57946582020-03-21 14:29:07 -070040import android.window.ITaskOrganizer;
Louis Changa009c762020-02-26 11:21:31 +080041import android.window.ITaskOrganizerController;
Wale Ogunwaleadf116e2020-03-27 16:36:01 -070042import android.window.WindowContainerToken;
Evan Rosky0037e5f2019-11-05 10:26:24 -080043
Winson Chung1b5d0552020-04-06 19:28:49 -070044import com.android.internal.annotations.VisibleForTesting;
Evan Rosky29d4a0a2020-02-04 16:40:44 -080045import com.android.internal.util.ArrayUtils;
Robert Carr8a2f9132019-11-11 15:03:15 -080046
Winson Chung268eccb2020-03-26 13:43:44 -070047import java.io.PrintWriter;
Robert Carr8a2f9132019-11-11 15:03:15 -080048import java.util.ArrayList;
49import java.util.HashMap;
Winson Chungaff506b2020-03-21 22:56:31 -070050import java.util.LinkedList;
Evan Roskya8fde152020-01-07 19:09:13 -080051import java.util.List;
Evan Rosky0037e5f2019-11-05 10:26:24 -080052import java.util.WeakHashMap;
Winson Chung1b5d0552020-04-06 19:28:49 -070053import java.util.function.Consumer;
Robert Carr8a2f9132019-11-11 15:03:15 -080054
55/**
56 * Stores the TaskOrganizers associated with a given windowing mode and
57 * their associated state.
58 */
Wale Ogunwale568f9f412020-03-21 22:27:35 -070059class TaskOrganizerController extends ITaskOrganizerController.Stub {
Robert Carr8a2f9132019-11-11 15:03:15 -080060 private static final String TAG = "TaskOrganizerController";
Evan Roskyb8540a02020-03-25 16:30:24 -070061 private static final LinkedList<IBinder> EMPTY_LIST = new LinkedList<>();
Robert Carr8a2f9132019-11-11 15:03:15 -080062
Evan Roskyf64f5da2020-03-16 13:47:48 -070063 /**
64 * Masks specifying which configurations are important to report back to an organizer when
65 * changed.
66 */
67 private static final int REPORT_CONFIGS = CONTROLLABLE_CONFIGS;
68 private static final int REPORT_WINDOW_CONFIGS = CONTROLLABLE_WINDOW_CONFIGS;
69
Evan Rosky0037e5f2019-11-05 10:26:24 -080070 private final WindowManagerGlobalLock mGlobalLock;
Robert Carr8a2f9132019-11-11 15:03:15 -080071
72 private class DeathRecipient implements IBinder.DeathRecipient {
Robert Carr8a2f9132019-11-11 15:03:15 -080073 ITaskOrganizer mTaskOrganizer;
74
Evan Roskyb8540a02020-03-25 16:30:24 -070075 DeathRecipient(ITaskOrganizer organizer) {
Robert Carr8a2f9132019-11-11 15:03:15 -080076 mTaskOrganizer = organizer;
Robert Carr8a2f9132019-11-11 15:03:15 -080077 }
78
79 @Override
80 public void binderDied() {
81 synchronized (mGlobalLock) {
Winson Chungaff506b2020-03-21 22:56:31 -070082 final TaskOrganizerState state = mTaskOrganizerStates.remove(
83 mTaskOrganizer.asBinder());
Riddle Hsu3c290512020-03-30 22:12:52 +080084 if (state != null) {
85 state.dispose();
86 }
Robert Carr8a2f9132019-11-11 15:03:15 -080087 }
88 }
Winson Chung1b5d0552020-04-06 19:28:49 -070089 }
90
91 /**
92 * A wrapper class around ITaskOrganizer to ensure that the calls are made in the right
93 * lifecycle order since we may be updating the visibility of task surface controls in a pending
94 * transaction before they are presented to the task org.
95 */
96 private class TaskOrganizerCallbacks {
97 final WindowManagerService mService;
98 final ITaskOrganizer mTaskOrganizer;
99 final Consumer<Runnable> mDeferTaskOrgCallbacksConsumer;
100
Winson Chung14a657c2020-05-28 10:47:40 -0700101 private final SurfaceControl.Transaction mTransaction;
102
Winson Chung1b5d0552020-04-06 19:28:49 -0700103 TaskOrganizerCallbacks(WindowManagerService wm, ITaskOrganizer taskOrg,
104 Consumer<Runnable> deferTaskOrgCallbacksConsumer) {
105 mService = wm;
106 mDeferTaskOrgCallbacksConsumer = deferTaskOrgCallbacksConsumer;
107 mTaskOrganizer = taskOrg;
Winson Chung14a657c2020-05-28 10:47:40 -0700108 mTransaction = wm.mTransactionFactory.get();
Winson Chung1b5d0552020-04-06 19:28:49 -0700109 }
110
111 IBinder getBinder() {
112 return mTaskOrganizer.asBinder();
113 }
114
115 void onTaskAppeared(Task task) {
Winson Chung14a657c2020-05-28 10:47:40 -0700116 final boolean visible = task.isVisible();
Winson Chung1b5d0552020-04-06 19:28:49 -0700117 final RunningTaskInfo taskInfo = task.getTaskInfo();
118 mDeferTaskOrgCallbacksConsumer.accept(() -> {
119 try {
chaviw7de50002020-04-27 12:33:30 -0700120 SurfaceControl outSurfaceControl = new SurfaceControl(task.getSurfaceControl());
Winson Chung14a657c2020-05-28 10:47:40 -0700121 if (!task.mCreatedByOrganizer && !visible) {
122 // To prevent flashes, we hide the task prior to sending the leash to the
123 // task org if the task has previously hidden (ie. when entering PIP)
124 mTransaction.hide(outSurfaceControl);
125 mTransaction.apply();
126 }
chaviw7de50002020-04-27 12:33:30 -0700127 mTaskOrganizer.onTaskAppeared(taskInfo, outSurfaceControl);
Winson Chung1b5d0552020-04-06 19:28:49 -0700128 } catch (RemoteException e) {
129 Slog.e(TAG, "Exception sending onTaskAppeared callback", e);
130 }
131 });
132 }
133
134
135 void onTaskVanished(Task task) {
136 final RunningTaskInfo taskInfo = task.getTaskInfo();
137 mDeferTaskOrgCallbacksConsumer.accept(() -> {
138 try {
139 mTaskOrganizer.onTaskVanished(taskInfo);
140 } catch (RemoteException e) {
141 Slog.e(TAG, "Exception sending onTaskVanished callback", e);
142 }
143 });
144 }
145
146 void onTaskInfoChanged(Task task, ActivityManager.RunningTaskInfo taskInfo) {
Winson Chung8b5d23a2020-04-06 19:23:23 -0700147 if (!task.mCreatedByOrganizer && !task.mTaskAppearedSent) {
148 // Skip if the task has not yet received taskAppeared(), except for tasks created
149 // by the organizer that don't receive that signal
150 return;
151 }
Winson Chung1b5d0552020-04-06 19:28:49 -0700152 mDeferTaskOrgCallbacksConsumer.accept(() -> {
153 if (!task.isOrganized()) {
154 // This is safe to ignore if the task is no longer organized
155 return;
156 }
157 try {
158 mTaskOrganizer.onTaskInfoChanged(taskInfo);
159 } catch (RemoteException e) {
160 Slog.e(TAG, "Exception sending onTaskInfoChanged callback", e);
161 }
162 });
163 }
164
165 void onBackPressedOnTaskRoot(Task task) {
Winson Chung8b5d23a2020-04-06 19:23:23 -0700166 if (!task.mCreatedByOrganizer && !task.mTaskAppearedSent) {
167 // Skip if the task has not yet received taskAppeared(), except for tasks created
168 // by the organizer that don't receive that signal
169 return;
170 }
Winson Chung1b5d0552020-04-06 19:28:49 -0700171 mDeferTaskOrgCallbacksConsumer.accept(() -> {
172 if (!task.isOrganized()) {
173 // This is safe to ignore if the task is no longer organized
174 return;
175 }
176 try {
177 mTaskOrganizer.onBackPressedOnTaskRoot(task.getTaskInfo());
178 } catch (Exception e) {
179 Slog.e(TAG, "Exception sending onBackPressedOnTaskRoot callback", e);
180 }
181 });
182 }
183 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800184
Winson Chungaff506b2020-03-21 22:56:31 -0700185 private class TaskOrganizerState {
Winson Chung1b5d0552020-04-06 19:28:49 -0700186 private final TaskOrganizerCallbacks mOrganizer;
Winson Chungaff506b2020-03-21 22:56:31 -0700187 private final DeathRecipient mDeathRecipient;
Winson Chungaff506b2020-03-21 22:56:31 -0700188 private final ArrayList<Task> mOrganizedTasks = new ArrayList<>();
Winson Chung268eccb2020-03-26 13:43:44 -0700189 private final int mUid;
Winson Chunga1f869d2020-03-21 23:02:48 -0700190 private boolean mInterceptBackPressedOnTaskRoot;
Robert Carr8a2f9132019-11-11 15:03:15 -0800191
Winson Chung268eccb2020-03-26 13:43:44 -0700192 TaskOrganizerState(ITaskOrganizer organizer, int uid) {
Winson Chung1b5d0552020-04-06 19:28:49 -0700193 final Consumer<Runnable> deferTaskOrgCallbacksConsumer =
194 mDeferTaskOrgCallbacksConsumer != null
195 ? mDeferTaskOrgCallbacksConsumer
196 : mService.mWindowManager.mAnimator::addAfterPrepareSurfacesRunnable;
197 mOrganizer = new TaskOrganizerCallbacks(mService.mWindowManager, organizer,
198 deferTaskOrgCallbacksConsumer);
Evan Roskyb8540a02020-03-25 16:30:24 -0700199 mDeathRecipient = new DeathRecipient(organizer);
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800200 try {
201 organizer.asBinder().linkToDeath(mDeathRecipient, 0);
202 } catch (RemoteException e) {
203 Slog.e(TAG, "TaskOrganizer failed to register death recipient");
204 }
Winson Chung268eccb2020-03-26 13:43:44 -0700205 mUid = uid;
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800206 }
207
Winson Chunga1f869d2020-03-21 23:02:48 -0700208 void setInterceptBackPressedOnTaskRoot(boolean interceptBackPressed) {
209 mInterceptBackPressedOnTaskRoot = interceptBackPressed;
210 }
211
Robert Carr8a2f9132019-11-11 15:03:15 -0800212 void addTask(Task t) {
Louis Chang9d35a3a2020-04-06 17:23:02 +0800213 if (t.mTaskAppearedSent) return;
214
215 if (!mOrganizedTasks.contains(t)) {
216 mOrganizedTasks.add(t);
217 }
218 if (t.taskAppearedReady()) {
Winson Chung8b5d23a2020-04-06 19:23:23 -0700219 t.mTaskAppearedSent = true;
220 mOrganizer.onTaskAppeared(t);
Winson Chungd2fb07e2020-04-06 18:17:21 +0000221 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800222 }
223
224 void removeTask(Task t) {
Louis Chang9d35a3a2020-04-06 17:23:02 +0800225 if (t.mTaskAppearedSent) {
chaviwda7b3c22020-04-24 11:25:08 -0700226 t.migrateToNewSurfaceControl();
Winson Chung8b5d23a2020-04-06 19:23:23 -0700227 t.mTaskAppearedSent = false;
228 mOrganizer.onTaskVanished(t);
Winson Chungd2fb07e2020-04-06 18:17:21 +0000229 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800230 mOrganizedTasks.remove(t);
231 }
232
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800233 void dispose() {
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700234 // Move organizer from managing specific windowing modes
Evan Roskyb8540a02020-03-25 16:30:24 -0700235 for (int i = mTaskOrganizersForWindowingMode.size() - 1; i >= 0; --i) {
Winson Chung1b5d0552020-04-06 19:28:49 -0700236 mTaskOrganizersForWindowingMode.valueAt(i).remove(mOrganizer.getBinder());
Evan Roskyb8540a02020-03-25 16:30:24 -0700237 }
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800238
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700239 // Update tasks currently managed by this organizer to the next one available if
240 // possible.
241 while (!mOrganizedTasks.isEmpty()) {
242 final Task t = mOrganizedTasks.get(0);
243 t.updateTaskOrganizerState(true /* forceUpdate */);
244 if (mOrganizedTasks.contains(t)) {
245 removeTask(t);
246 }
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800247 }
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700248
249 // Remove organizer state after removing tasks so we get a chance to send
250 // onTaskVanished.
251 mTaskOrganizerStates.remove(asBinder());
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800252 }
253
254 void unlinkDeath() {
Winson Chung1b5d0552020-04-06 19:28:49 -0700255 mOrganizer.getBinder().unlinkToDeath(mDeathRecipient, 0);
Robert Carr8a2f9132019-11-11 15:03:15 -0800256 }
Winson Chungaff506b2020-03-21 22:56:31 -0700257 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800258
Evan Roskyb8540a02020-03-25 16:30:24 -0700259 private final SparseArray<LinkedList<IBinder>> mTaskOrganizersForWindowingMode =
Winson Chungaff506b2020-03-21 22:56:31 -0700260 new SparseArray<>();
261 private final HashMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new HashMap<>();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800262 private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>();
263 private final ArrayList<Task> mPendingTaskInfoChanges = new ArrayList<>();
264
Winson Chung1b5d0552020-04-06 19:28:49 -0700265 private final ActivityTaskManagerService mService;
Robert Carr8a2f9132019-11-11 15:03:15 -0800266
Winson Chung1b5d0552020-04-06 19:28:49 -0700267 private RunningTaskInfo mTmpTaskInfo;
268 private Consumer<Runnable> mDeferTaskOrgCallbacksConsumer;
Evan Rosky0037e5f2019-11-05 10:26:24 -0800269
270 TaskOrganizerController(ActivityTaskManagerService atm) {
Robert Carr8a2f9132019-11-11 15:03:15 -0800271 mService = atm;
Evan Rosky0037e5f2019-11-05 10:26:24 -0800272 mGlobalLock = atm.mGlobalLock;
273 }
274
275 private void enforceStackPermission(String func) {
276 mService.mAmInternal.enforceCallingPermission(MANAGE_ACTIVITY_STACKS, func);
Robert Carr8a2f9132019-11-11 15:03:15 -0800277 }
278
Robert Carr8a2f9132019-11-11 15:03:15 -0800279 /**
Winson Chung1b5d0552020-04-06 19:28:49 -0700280 * Specifies the consumer to run to defer the task org callbacks. Can be overridden while
281 * testing to allow the callbacks to be sent synchronously.
282 */
283 @VisibleForTesting
284 public void setDeferTaskOrgCallbacksConsumer(Consumer<Runnable> consumer) {
285 mDeferTaskOrgCallbacksConsumer = consumer;
286 }
287
288 /**
Robert Carr8a2f9132019-11-11 15:03:15 -0800289 * Register a TaskOrganizer to manage tasks as they enter the given windowing mode.
290 * If there was already a TaskOrganizer for this windowing mode it will be evicted
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800291 * but will continue to organize it's existing tasks.
Robert Carr8a2f9132019-11-11 15:03:15 -0800292 */
Evan Rosky0037e5f2019-11-05 10:26:24 -0800293 @Override
294 public void registerTaskOrganizer(ITaskOrganizer organizer, int windowingMode) {
Evan Roskyb8540a02020-03-25 16:30:24 -0700295 if (windowingMode == WINDOWING_MODE_PINNED) {
296 if (!mService.mSupportsPictureInPicture) {
297 throw new UnsupportedOperationException("Picture in picture is not supported on "
298 + "this device");
299 }
300 } else if (WindowConfiguration.isSplitScreenWindowingMode(windowingMode)) {
301 if (!mService.mSupportsSplitScreenMultiWindow) {
302 throw new UnsupportedOperationException("Split-screen is not supported on this "
303 + "device");
304 }
305 } else if (windowingMode == WINDOWING_MODE_MULTI_WINDOW) {
306 if (!mService.mSupportsMultiWindow) {
307 throw new UnsupportedOperationException("Multi-window is not supported on this "
308 + "device");
309 }
310 } else {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800311 throw new UnsupportedOperationException("As of now only Pinned/Split/Multiwindow"
312 + " windowing modes are supported for registerTaskOrganizer");
Robert Carr8a2f9132019-11-11 15:03:15 -0800313 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800314 enforceStackPermission("registerTaskOrganizer()");
Winson Chung268eccb2020-03-26 13:43:44 -0700315 final int uid = Binder.getCallingUid();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800316 final long origId = Binder.clearCallingIdentity();
Robert Carr8a2f9132019-11-11 15:03:15 -0800317 try {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800318 synchronized (mGlobalLock) {
Winson Chung77338ab2020-03-09 16:32:34 -0700319 if (getTaskOrganizer(windowingMode) != null) {
320 Slog.w(TAG, "Task organizer already exists for windowing mode: "
321 + windowingMode);
322 }
Winson Chungaff506b2020-03-21 22:56:31 -0700323
Evan Roskyb8540a02020-03-25 16:30:24 -0700324 LinkedList<IBinder> orgs = mTaskOrganizersForWindowingMode.get(windowingMode);
325 if (orgs == null) {
326 orgs = new LinkedList<>();
327 mTaskOrganizersForWindowingMode.put(windowingMode, orgs);
Winson Chungaff506b2020-03-21 22:56:31 -0700328 }
Evan Roskyb8540a02020-03-25 16:30:24 -0700329 orgs.add(organizer.asBinder());
330 if (!mTaskOrganizerStates.containsKey(organizer.asBinder())) {
331 mTaskOrganizerStates.put(organizer.asBinder(),
Winson Chung268eccb2020-03-26 13:43:44 -0700332 new TaskOrganizerState(organizer, uid));
Evan Roskyb8540a02020-03-25 16:30:24 -0700333 }
Winson Chung77338ab2020-03-09 16:32:34 -0700334
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700335 mService.mRootWindowContainer.forAllTasks((task) -> {
336 if (task.getWindowingMode() == windowingMode) {
337 task.updateTaskOrganizerState(true /* forceUpdate */);
338 }
339 });
Evan Rosky0037e5f2019-11-05 10:26:24 -0800340 }
341 } finally {
342 Binder.restoreCallingIdentity(origId);
Robert Carr8a2f9132019-11-11 15:03:15 -0800343 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800344 }
345
Winson Chung8a168902020-03-12 22:39:22 -0700346 @Override
347 public void unregisterTaskOrganizer(ITaskOrganizer organizer) {
Riddle Hsu3c290512020-03-30 22:12:52 +0800348 enforceStackPermission("unregisterTaskOrganizer()");
349 final long origId = Binder.clearCallingIdentity();
350 try {
351 synchronized (mGlobalLock) {
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700352 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
Riddle Hsu3c290512020-03-30 22:12:52 +0800353 if (state == null) {
354 return;
355 }
356 state.unlinkDeath();
357 state.dispose();
358 }
359 } finally {
360 Binder.restoreCallingIdentity(origId);
361 }
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800362 }
363
Robert Carr8a2f9132019-11-11 15:03:15 -0800364 ITaskOrganizer getTaskOrganizer(int windowingMode) {
Evan Roskyb8540a02020-03-25 16:30:24 -0700365 final IBinder organizer =
366 mTaskOrganizersForWindowingMode.get(windowingMode, EMPTY_LIST).peekLast();
367 if (organizer == null) {
368 return null;
369 }
370 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer);
Robert Carr8a2f9132019-11-11 15:03:15 -0800371 if (state == null) {
372 return null;
373 }
Winson Chung1b5d0552020-04-06 19:28:49 -0700374 return state.mOrganizer.mTaskOrganizer;
Robert Carr8a2f9132019-11-11 15:03:15 -0800375 }
376
Robert Carr8a2f9132019-11-11 15:03:15 -0800377 void onTaskAppeared(ITaskOrganizer organizer, Task task) {
Robert Carre10ee3d2019-11-11 15:03:15 -0800378 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
Robert Carr8a2f9132019-11-11 15:03:15 -0800379 state.addTask(task);
Robert Carr8a2f9132019-11-11 15:03:15 -0800380 }
381
382 void onTaskVanished(ITaskOrganizer organizer, Task task) {
Robert Carr7d7c8ab2020-01-28 15:57:23 -0800383 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
Wale Ogunwale20ab6d42020-04-13 07:30:59 -0700384 if (state != null) {
385 state.removeTask(task);
386 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800387 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800388
389 @Override
390 public RunningTaskInfo createRootTask(int displayId, int windowingMode) {
391 enforceStackPermission("createRootTask()");
392 final long origId = Binder.clearCallingIdentity();
393 try {
394 synchronized (mGlobalLock) {
395 DisplayContent display = mService.mRootWindowContainer.getDisplayContent(displayId);
396 if (display == null) {
397 return null;
398 }
Louis Changa009c762020-02-26 11:21:31 +0800399
Andrii Kulian4c0fd0d2020-03-29 13:32:14 -0700400 final Task task = display.getDefaultTaskDisplayArea().createStack(windowingMode,
Wale Ogunwalec27e1ac2020-03-31 13:18:47 -0700401 ACTIVITY_TYPE_UNDEFINED, false /* onTop */, null /* info */, new Intent(),
402 true /* createdByOrganizer */);
Louis Changa009c762020-02-26 11:21:31 +0800403 RunningTaskInfo out = task.getTaskInfo();
404 mLastSentTaskInfos.put(task, out);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800405 return out;
406 }
407 } finally {
408 Binder.restoreCallingIdentity(origId);
409 }
410 }
411
412 @Override
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700413 public boolean deleteRootTask(WindowContainerToken token) {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800414 enforceStackPermission("deleteRootTask()");
415 final long origId = Binder.clearCallingIdentity();
416 try {
417 synchronized (mGlobalLock) {
Louis Changa009c762020-02-26 11:21:31 +0800418 final Task task = WindowContainer.fromBinder(token.asBinder()).asTask();
419 if (task == null) return false;
420 if (!task.mCreatedByOrganizer) {
421 throw new IllegalArgumentException(
422 "Attempt to delete task not created by organizer task=" + task);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800423 }
Louis Changa009c762020-02-26 11:21:31 +0800424 task.removeImmediately();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800425 return true;
426 }
427 } finally {
428 Binder.restoreCallingIdentity(origId);
429 }
430 }
431
432 void dispatchPendingTaskInfoChanges() {
433 if (mService.mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) {
434 return;
435 }
436 for (int i = 0, n = mPendingTaskInfoChanges.size(); i < n; ++i) {
437 dispatchTaskInfoChanged(mPendingTaskInfoChanges.get(i), false /* force */);
438 }
439 mPendingTaskInfoChanges.clear();
440 }
441
442 void dispatchTaskInfoChanged(Task task, boolean force) {
443 if (!force && mService.mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) {
444 // Defer task info reporting while layout is deferred. This is because layout defer
445 // blocks tend to do lots of re-ordering which can mess up animations in receivers.
446 mPendingTaskInfoChanges.remove(task);
447 mPendingTaskInfoChanges.add(task);
448 return;
449 }
450 RunningTaskInfo lastInfo = mLastSentTaskInfos.get(task);
451 if (mTmpTaskInfo == null) {
452 mTmpTaskInfo = new RunningTaskInfo();
453 }
Evan Roskyf64f5da2020-03-16 13:47:48 -0700454 mTmpTaskInfo.configuration.unset();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800455 task.fillTaskInfo(mTmpTaskInfo);
456 boolean changed = lastInfo == null
457 || mTmpTaskInfo.topActivityType != lastInfo.topActivityType
Hongwei Wang85cf41f2020-01-15 15:14:47 -0800458 || mTmpTaskInfo.isResizable() != lastInfo.isResizable()
Winson Chung1df39e22020-04-09 14:30:55 -0700459 || mTmpTaskInfo.pictureInPictureParams != lastInfo.pictureInPictureParams
460 || !TaskDescription.equals(mTmpTaskInfo.taskDescription, lastInfo.taskDescription);
Evan Roskyf64f5da2020-03-16 13:47:48 -0700461 if (!changed) {
462 int cfgChanges = mTmpTaskInfo.configuration.diff(lastInfo.configuration);
463 final int winCfgChanges = (cfgChanges & ActivityInfo.CONFIG_WINDOW_CONFIGURATION) != 0
464 ? (int) mTmpTaskInfo.configuration.windowConfiguration.diff(
465 lastInfo.configuration.windowConfiguration,
466 true /* compareUndefined */) : 0;
467 if ((winCfgChanges & REPORT_WINDOW_CONFIGS) == 0) {
468 cfgChanges &= ~ActivityInfo.CONFIG_WINDOW_CONFIGURATION;
469 }
470 changed = (cfgChanges & REPORT_CONFIGS) != 0;
471 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800472 if (!(changed || force)) {
473 return;
474 }
475 final RunningTaskInfo newInfo = mTmpTaskInfo;
476 mLastSentTaskInfos.put(task, mTmpTaskInfo);
477 // Since we've stored this, clean up the reference so a new one will be created next time.
478 // Transferring it this way means we only have to construct new RunningTaskInfos when they
479 // change.
480 mTmpTaskInfo = null;
481
Winson Chung1b5d0552020-04-06 19:28:49 -0700482 if (task.isOrganized()) {
Winson Chung8b5d23a2020-04-06 19:23:23 -0700483 // Because we defer sending taskAppeared() until the app has drawn, we may receive a
484 // configuration change before the state actually has the task registered. As such we
485 // should ignore these change events to the organizer until taskAppeared(). If the task
486 // was created by the organizer, then we always send the info change.
Winson Chung1b5d0552020-04-06 19:28:49 -0700487 final TaskOrganizerState state = mTaskOrganizerStates.get(
488 task.mTaskOrganizer.asBinder());
Winson Chung8b5d23a2020-04-06 19:23:23 -0700489 if (state != null) {
490 state.mOrganizer.onTaskInfoChanged(task, newInfo);
491 }
Evan Rosky0037e5f2019-11-05 10:26:24 -0800492 }
493 }
494
495 @Override
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700496 public WindowContainerToken getImeTarget(int displayId) {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800497 enforceStackPermission("getImeTarget()");
498 final long origId = Binder.clearCallingIdentity();
499 try {
500 synchronized (mGlobalLock) {
501 DisplayContent dc = mService.mWindowManager.mRoot
502 .getDisplayContent(displayId);
503 if (dc == null || dc.mInputMethodTarget == null) {
504 return null;
505 }
506 // Avoid WindowState#getRootTask() so we don't attribute system windows to a task.
507 final Task task = dc.mInputMethodTarget.getTask();
508 if (task == null) {
509 return null;
510 }
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700511 return task.getRootTask().mRemoteToken.toWindowContainerToken();
Evan Rosky0037e5f2019-11-05 10:26:24 -0800512 }
513 } finally {
514 Binder.restoreCallingIdentity(origId);
515 }
516 }
517
518 @Override
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700519 public void setLaunchRoot(int displayId, @Nullable WindowContainerToken token) {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800520 enforceStackPermission("setLaunchRoot()");
521 final long origId = Binder.clearCallingIdentity();
522 try {
523 synchronized (mGlobalLock) {
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700524 TaskDisplayArea defaultTaskDisplayArea = mService.mRootWindowContainer
525 .getDisplayContent(displayId).getDefaultTaskDisplayArea();
526 if (defaultTaskDisplayArea == null) {
Evan Rosky0037e5f2019-11-05 10:26:24 -0800527 return;
528 }
Louis Changa009c762020-02-26 11:21:31 +0800529 Task task = token == null
530 ? null : WindowContainer.fromBinder(token.asBinder()).asTask();
531 if (task == null) {
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700532 defaultTaskDisplayArea.mLaunchRootTask = null;
Evan Rosky0037e5f2019-11-05 10:26:24 -0800533 return;
534 }
Louis Changa009c762020-02-26 11:21:31 +0800535 if (!task.mCreatedByOrganizer) {
536 throw new IllegalArgumentException("Attempt to set task not created by "
537 + "organizer as launch root task=" + task);
Evan Rosky0037e5f2019-11-05 10:26:24 -0800538 }
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700539 if (task.getDisplayArea() == null
540 || task.getDisplayArea().getDisplayId() != displayId) {
Louis Changa009c762020-02-26 11:21:31 +0800541 throw new RuntimeException("Can't set launch root for display " + displayId
542 + " to task on display " + task.getDisplayContent().getDisplayId());
543 }
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700544 task.getDisplayArea().mLaunchRootTask = task;
Evan Rosky0037e5f2019-11-05 10:26:24 -0800545 }
546 } finally {
547 Binder.restoreCallingIdentity(origId);
548 }
549 }
550
Evan Roskya8fde152020-01-07 19:09:13 -0800551 @Override
Wale Ogunwaleadf116e2020-03-27 16:36:01 -0700552 public List<RunningTaskInfo> getChildTasks(WindowContainerToken parent,
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800553 @Nullable int[] activityTypes) {
Evan Roskya8fde152020-01-07 19:09:13 -0800554 enforceStackPermission("getChildTasks()");
555 final long ident = Binder.clearCallingIdentity();
556 try {
557 synchronized (mGlobalLock) {
558 if (parent == null) {
559 throw new IllegalArgumentException("Can't get children of null parent");
560 }
561 final WindowContainer container = WindowContainer.fromBinder(parent.asBinder());
562 if (container == null) {
563 Slog.e(TAG, "Can't get children of " + parent + " because it is not valid.");
564 return null;
565 }
Louis Changa009c762020-02-26 11:21:31 +0800566 final Task task = container.asTask();
567 if (task == null) {
568 Slog.e(TAG, container + " is not a task...");
569 return null;
570 }
571 // For now, only support returning children of tasks created by the organizer.
572 if (!task.mCreatedByOrganizer) {
Evan Roskya8fde152020-01-07 19:09:13 -0800573 Slog.w(TAG, "Can only get children of root tasks created via createRootTask");
574 return null;
575 }
576 ArrayList<RunningTaskInfo> out = new ArrayList<>();
Louis Changa009c762020-02-26 11:21:31 +0800577 for (int i = task.getChildCount() - 1; i >= 0; --i) {
578 final Task child = task.getChildAt(i).asTask();
579 if (child == null) continue;
580 if (activityTypes != null
581 && !ArrayUtils.contains(activityTypes, child.getActivityType())) {
582 continue;
Evan Roskya8fde152020-01-07 19:09:13 -0800583 }
Louis Changa009c762020-02-26 11:21:31 +0800584 out.add(child.getTaskInfo());
Evan Roskya8fde152020-01-07 19:09:13 -0800585 }
586 return out;
587 }
588 } finally {
589 Binder.restoreCallingIdentity(ident);
590 }
591 }
592
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800593 @Override
594 public List<RunningTaskInfo> getRootTasks(int displayId, @Nullable int[] activityTypes) {
595 enforceStackPermission("getRootTasks()");
596 final long ident = Binder.clearCallingIdentity();
597 try {
598 synchronized (mGlobalLock) {
599 final DisplayContent dc =
600 mService.mRootWindowContainer.getDisplayContent(displayId);
601 if (dc == null) {
602 throw new IllegalArgumentException("Display " + displayId + " doesn't exist");
603 }
604 ArrayList<RunningTaskInfo> out = new ArrayList<>();
Andrii Kulianf9df4a82020-03-31 12:09:27 -0700605 for (int tdaNdx = dc.getTaskDisplayAreaCount() - 1; tdaNdx >= 0; --tdaNdx) {
606 final TaskDisplayArea taskDisplayArea = dc.getTaskDisplayAreaAt(tdaNdx);
607 for (int sNdx = taskDisplayArea.getStackCount() - 1; sNdx >= 0; --sNdx) {
608 final Task task = taskDisplayArea.getStackAt(sNdx);
609 if (activityTypes != null
610 && !ArrayUtils.contains(activityTypes, task.getActivityType())) {
611 continue;
612 }
613 out.add(task.getTaskInfo());
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800614 }
Evan Rosky29d4a0a2020-02-04 16:40:44 -0800615 }
616 return out;
617 }
618 } finally {
619 Binder.restoreCallingIdentity(ident);
620 }
621 }
Winson Chung268eccb2020-03-26 13:43:44 -0700622
Winson Chunga1f869d2020-03-21 23:02:48 -0700623 @Override
624 public void setInterceptBackPressedOnTaskRoot(ITaskOrganizer organizer,
625 boolean interceptBackPressed) {
626 enforceStackPermission("setInterceptBackPressedOnTaskRoot()");
627 final long origId = Binder.clearCallingIdentity();
628 try {
629 synchronized (mGlobalLock) {
630 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
631 if (state != null) {
632 state.setInterceptBackPressedOnTaskRoot(interceptBackPressed);
633 }
634 }
635 } finally {
636 Binder.restoreCallingIdentity(origId);
637 }
638 }
639
640 public boolean handleInterceptBackPressedOnTaskRoot(Task task) {
641 if (task == null || !task.isOrganized()) {
642 return false;
643 }
644
645 final TaskOrganizerState state = mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder());
646 if (!state.mInterceptBackPressedOnTaskRoot) {
647 return false;
648 }
649
Winson Chung1b5d0552020-04-06 19:28:49 -0700650 state.mOrganizer.onBackPressedOnTaskRoot(task);
Winson Chunga1f869d2020-03-21 23:02:48 -0700651 return true;
652 }
653
Winson Chung268eccb2020-03-26 13:43:44 -0700654 public void dump(PrintWriter pw, String prefix) {
655 final String innerPrefix = prefix + " ";
656 pw.print(prefix); pw.println("TaskOrganizerController:");
657 pw.print(innerPrefix); pw.println("Per windowing mode:");
658 for (int i = 0; i < mTaskOrganizersForWindowingMode.size(); i++) {
659 final int windowingMode = mTaskOrganizersForWindowingMode.keyAt(i);
660 final List<IBinder> taskOrgs = mTaskOrganizersForWindowingMode.valueAt(i);
661 pw.println(innerPrefix + " "
662 + WindowConfiguration.windowingModeToString(windowingMode) + ":");
663 for (int j = 0; j < taskOrgs.size(); j++) {
664 final TaskOrganizerState state = mTaskOrganizerStates.get(taskOrgs.get(j));
665 final ArrayList<Task> tasks = state.mOrganizedTasks;
666 pw.print(innerPrefix + " ");
Winson Chung1b5d0552020-04-06 19:28:49 -0700667 pw.println(state.mOrganizer.mTaskOrganizer + " uid=" + state.mUid + ":");
Winson Chung268eccb2020-03-26 13:43:44 -0700668 for (int k = 0; k < tasks.size(); k++) {
669 pw.println(innerPrefix + " " + tasks.get(k));
670 }
671 }
672
673 }
674 pw.println();
675 }
Robert Carr8a2f9132019-11-11 15:03:15 -0800676}