• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.server.wm;
18 
19 import static android.app.TaskInfo.cameraCompatControlStateToString;
20 
21 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_ORGANIZER;
22 import static com.android.server.wm.ActivityTaskManagerService.enforceTaskPermission;
23 import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
24 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_STARTING_REVEAL;
25 import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer;
26 
27 import android.annotation.NonNull;
28 import android.annotation.Nullable;
29 import android.app.ActivityManager;
30 import android.app.ActivityManager.RunningTaskInfo;
31 import android.app.WindowConfiguration;
32 import android.content.Intent;
33 import android.content.pm.ParceledListSlice;
34 import android.graphics.Rect;
35 import android.os.Binder;
36 import android.os.IBinder;
37 import android.os.Parcel;
38 import android.os.RemoteException;
39 import android.util.ArrayMap;
40 import android.util.Slog;
41 import android.util.proto.ProtoOutputStream;
42 import android.view.Display;
43 import android.view.SurfaceControl;
44 import android.window.ITaskOrganizer;
45 import android.window.ITaskOrganizerController;
46 import android.window.SplashScreenView;
47 import android.window.StartingWindowInfo;
48 import android.window.StartingWindowRemovalInfo;
49 import android.window.TaskAppearedInfo;
50 import android.window.TaskSnapshot;
51 import android.window.WindowContainerToken;
52 
53 import com.android.internal.annotations.VisibleForTesting;
54 import com.android.internal.protolog.common.ProtoLog;
55 import com.android.internal.util.ArrayUtils;
56 
57 import java.io.PrintWriter;
58 import java.util.ArrayList;
59 import java.util.HashSet;
60 import java.util.LinkedList;
61 import java.util.List;
62 import java.util.WeakHashMap;
63 import java.util.function.Consumer;
64 
65 /**
66  * Stores the TaskOrganizers associated with a given windowing mode and
67  * their associated state.
68  */
69 class TaskOrganizerController extends ITaskOrganizerController.Stub {
70     private static final String TAG = "TaskOrganizerController";
71 
72     @VisibleForTesting
73     class DeathRecipient implements IBinder.DeathRecipient {
74         ITaskOrganizer mTaskOrganizer;
75 
DeathRecipient(ITaskOrganizer organizer)76         DeathRecipient(ITaskOrganizer organizer) {
77             mTaskOrganizer = organizer;
78         }
79 
80         @Override
binderDied()81         public void binderDied() {
82             synchronized (mGlobalLock) {
83                 final TaskOrganizerState state = mTaskOrganizerStates.get(
84                         mTaskOrganizer.asBinder());
85                 if (state != null) {
86                     state.dispose();
87                 }
88             }
89         }
90     }
91 
92     /**
93      * A wrapper class around ITaskOrganizer to ensure that the calls are made in the right
94      * lifecycle order since we may be updating the visibility of task surface controls in a pending
95      * transaction before they are presented to the task org.
96      */
97     private static class TaskOrganizerCallbacks {
98         final ITaskOrganizer mTaskOrganizer;
99         final Consumer<Runnable> mDeferTaskOrgCallbacksConsumer;
100 
TaskOrganizerCallbacks(ITaskOrganizer taskOrg, Consumer<Runnable> deferTaskOrgCallbacksConsumer)101         TaskOrganizerCallbacks(ITaskOrganizer taskOrg,
102                 Consumer<Runnable> deferTaskOrgCallbacksConsumer) {
103             mDeferTaskOrgCallbacksConsumer = deferTaskOrgCallbacksConsumer;
104             mTaskOrganizer = taskOrg;
105         }
106 
getBinder()107         IBinder getBinder() {
108             return mTaskOrganizer.asBinder();
109         }
110 
prepareLeash(Task task, String reason)111         SurfaceControl prepareLeash(Task task, String reason) {
112             return new SurfaceControl(task.getSurfaceControl(), reason);
113         }
114 
onTaskAppeared(Task task)115         void onTaskAppeared(Task task) {
116             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task appeared taskId=%d", task.mTaskId);
117             final RunningTaskInfo taskInfo = task.getTaskInfo();
118             try {
119                 mTaskOrganizer.onTaskAppeared(taskInfo, prepareLeash(task,
120                         "TaskOrganizerController.onTaskAppeared"));
121             } catch (RemoteException e) {
122                 Slog.e(TAG, "Exception sending onTaskAppeared callback", e);
123             }
124         }
125 
onTaskVanished(Task task)126         void onTaskVanished(Task task) {
127             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task vanished taskId=%d", task.mTaskId);
128             final RunningTaskInfo taskInfo = task.getTaskInfo();
129             try {
130                 mTaskOrganizer.onTaskVanished(taskInfo);
131             } catch (RemoteException e) {
132                 Slog.e(TAG, "Exception sending onTaskVanished callback", e);
133             }
134         }
135 
onTaskInfoChanged(Task task, ActivityManager.RunningTaskInfo taskInfo)136         void onTaskInfoChanged(Task task, ActivityManager.RunningTaskInfo taskInfo) {
137             if (!task.mTaskAppearedSent) {
138                 // Skip if the task has not yet received taskAppeared().
139                 return;
140             }
141             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task info changed taskId=%d", task.mTaskId);
142             if (!task.isOrganized()) {
143                 // This is safe to ignore if the task is no longer organized
144                 return;
145             }
146             try {
147                 // Purposely notify of task info change immediately instead of deferring (like
148                 // appear and vanish) to allow info changes (such as new PIP params) to flow
149                 // without waiting.
150                 mTaskOrganizer.onTaskInfoChanged(taskInfo);
151             } catch (RemoteException e) {
152                 Slog.e(TAG, "Exception sending onTaskInfoChanged callback", e);
153             }
154         }
155 
onBackPressedOnTaskRoot(Task task)156         void onBackPressedOnTaskRoot(Task task) {
157             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task back pressed on root taskId=%d",
158                     task.mTaskId);
159             if (!task.mTaskAppearedSent) {
160                 // Skip if the task has not yet received taskAppeared().
161                 return;
162             }
163             if (!task.isOrganized()) {
164                 // This is safe to ignore if the task is no longer organized
165                 return;
166             }
167             try {
168                 mTaskOrganizer.onBackPressedOnTaskRoot(task.getTaskInfo());
169             } catch (Exception e) {
170                 Slog.e(TAG, "Exception sending onBackPressedOnTaskRoot callback", e);
171             }
172         }
173     }
174 
175     /**
176      * Maintains a list of all the pending events for a given {@link android.window.TaskOrganizer}
177      */
178     static final class TaskOrganizerPendingEventsQueue {
179         private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>();
180         private final TaskOrganizerState mOrganizerState;
181         private RunningTaskInfo mTmpTaskInfo;
182         // Pending task events due to layout deferred.
183         private final ArrayList<PendingTaskEvent> mPendingTaskEvents = new ArrayList<>();
184 
TaskOrganizerPendingEventsQueue(TaskOrganizerState taskOrganizerState)185         TaskOrganizerPendingEventsQueue(TaskOrganizerState taskOrganizerState) {
186             mOrganizerState = taskOrganizerState;
187         }
188 
189         @VisibleForTesting
getPendingEventList()190         public ArrayList<PendingTaskEvent> getPendingEventList() {
191             return mPendingTaskEvents;
192         }
193 
numPendingTaskEvents()194         int numPendingTaskEvents() {
195             return mPendingTaskEvents.size();
196         }
197 
clearPendingTaskEvents()198         void clearPendingTaskEvents() {
199             mPendingTaskEvents.clear();
200         }
201 
addPendingTaskEvent(PendingTaskEvent event)202         void addPendingTaskEvent(PendingTaskEvent event) {
203             mPendingTaskEvents.add(event);
204         }
205 
removePendingTaskEvent(PendingTaskEvent event)206         void removePendingTaskEvent(PendingTaskEvent event) {
207             mPendingTaskEvents.remove(event);
208         }
209 
210         /**
211          * Removes all the pending task events for the given {@code task}.
212          *
213          * @param task
214          * @return true if a {@link PendingTaskEvent#EVENT_APPEARED} is still pending for the given
215          * {code task}.
216          */
removePendingTaskEvents(Task task)217         boolean removePendingTaskEvents(Task task) {
218             boolean foundPendingAppearedEvents = false;
219             for (int i = mPendingTaskEvents.size() - 1; i >= 0; i--) {
220                 PendingTaskEvent entry = mPendingTaskEvents.get(i);
221                 if (task.mTaskId == entry.mTask.mTaskId) {
222                     // This task is vanished so remove all pending event of it.
223                     mPendingTaskEvents.remove(i);
224 
225                     if (entry.mEventType == PendingTaskEvent.EVENT_APPEARED) {
226                         foundPendingAppearedEvents = true;
227                     }
228                 }
229             }
230             return foundPendingAppearedEvents;
231         }
232 
233         @Nullable
getPendingTaskEvent(Task task, int type)234         private PendingTaskEvent getPendingTaskEvent(Task task, int type) {
235             for (int i = mPendingTaskEvents.size() - 1; i >= 0; i--) {
236                 PendingTaskEvent entry = mPendingTaskEvents.get(i);
237                 if (task.mTaskId == entry.mTask.mTaskId && type == entry.mEventType) {
238                     return entry;
239                 }
240             }
241             return null;
242         }
243 
244         @VisibleForTesting
245         @Nullable
getPendingLifecycleTaskEvent(Task task)246         PendingTaskEvent getPendingLifecycleTaskEvent(Task task) {
247             for (int i = mPendingTaskEvents.size() - 1; i >= 0; i--) {
248                 PendingTaskEvent entry = mPendingTaskEvents.get(i);
249                 if (task.mTaskId == entry.mTask.mTaskId && entry.isLifecycleEvent()) {
250                     return entry;
251                 }
252             }
253             return null;
254         }
255 
dispatchPendingEvents()256         void dispatchPendingEvents() {
257             if (mPendingTaskEvents.isEmpty()) {
258                 return;
259             }
260             for (int i = 0, n = mPendingTaskEvents.size(); i < n; i++) {
261                 dispatchPendingEvent(mPendingTaskEvents.get(i));
262             }
263             mPendingTaskEvents.clear();
264         }
265 
dispatchPendingEvent(PendingTaskEvent event)266         private void dispatchPendingEvent(PendingTaskEvent event) {
267             final Task task = event.mTask;
268             switch (event.mEventType) {
269                 case PendingTaskEvent.EVENT_APPEARED:
270                     if (task.taskAppearedReady()) {
271                         mOrganizerState.mOrganizer.onTaskAppeared(task);
272                     }
273                     break;
274                 case PendingTaskEvent.EVENT_VANISHED:
275                     mOrganizerState.mOrganizer.onTaskVanished(task);
276                     mLastSentTaskInfos.remove(task);
277                     break;
278                 case PendingTaskEvent.EVENT_INFO_CHANGED:
279                     dispatchTaskInfoChanged(event.mTask, event.mForce);
280                     break;
281                 case PendingTaskEvent.EVENT_ROOT_BACK_PRESSED:
282                     mOrganizerState.mOrganizer.onBackPressedOnTaskRoot(task);
283                     break;
284             }
285         }
286 
dispatchTaskInfoChanged(Task task, boolean force)287         private void dispatchTaskInfoChanged(Task task, boolean force) {
288             RunningTaskInfo lastInfo = mLastSentTaskInfos.get(task);
289             if (mTmpTaskInfo == null) {
290                 mTmpTaskInfo = new RunningTaskInfo();
291             }
292             mTmpTaskInfo.configuration.unset();
293             task.fillTaskInfo(mTmpTaskInfo);
294 
295             boolean changed = !mTmpTaskInfo
296                     .equalsForTaskOrganizer(lastInfo)
297                     || !configurationsAreEqualForOrganizer(
298                     mTmpTaskInfo.configuration,
299                     lastInfo.configuration);
300             if (!(changed || force)) {
301                 // mTmpTaskInfo will be reused next time.
302                 return;
303             }
304             final RunningTaskInfo newInfo = mTmpTaskInfo;
305             mLastSentTaskInfos.put(task,
306                     mTmpTaskInfo);
307             // Since we've stored this, clean up the reference so a new one will be created next
308             // time.
309             // Transferring it this way means we only have to construct new RunningTaskInfos when
310             // they change.
311             mTmpTaskInfo = null;
312 
313             if (task.isOrganized()) {
314                 // Because we defer sending taskAppeared() until the app has drawn, we may receive a
315                 // configuration change before the state actually has the task registered. As such
316                 // we should ignore these change events to the organizer until taskAppeared(). If
317                 // the task was created by the organizer, then we always send the info change.
318                 mOrganizerState.mOrganizer.onTaskInfoChanged(task, newInfo);
319             }
320         }
321     }
322 
323     @VisibleForTesting
324     class TaskOrganizerState {
325         private final TaskOrganizerCallbacks mOrganizer;
326         private final DeathRecipient mDeathRecipient;
327         private final ArrayList<Task> mOrganizedTasks = new ArrayList<>();
328         private final TaskOrganizerPendingEventsQueue mPendingEventsQueue;
329         private final int mUid;
330 
TaskOrganizerState(ITaskOrganizer organizer, int uid)331         TaskOrganizerState(ITaskOrganizer organizer, int uid) {
332             final Consumer<Runnable> deferTaskOrgCallbacksConsumer =
333                     mDeferTaskOrgCallbacksConsumer != null
334                             ? mDeferTaskOrgCallbacksConsumer
335                             : mService.mWindowManager.mAnimator::addAfterPrepareSurfacesRunnable;
336             mOrganizer = new TaskOrganizerCallbacks(organizer, deferTaskOrgCallbacksConsumer);
337             mDeathRecipient = new DeathRecipient(organizer);
338             mPendingEventsQueue = new TaskOrganizerPendingEventsQueue(this);
339             try {
340                 organizer.asBinder().linkToDeath(mDeathRecipient, 0);
341             } catch (RemoteException e) {
342                 Slog.e(TAG, "TaskOrganizer failed to register death recipient");
343             }
344             mUid = uid;
345         }
346 
347         @VisibleForTesting
getDeathRecipient()348         DeathRecipient getDeathRecipient() {
349             return mDeathRecipient;
350         }
351 
352         @VisibleForTesting
getPendingEventsQueue()353         TaskOrganizerPendingEventsQueue getPendingEventsQueue() {
354             return mPendingEventsQueue;
355         }
356 
357         /**
358          * Register this task with this state, but doesn't trigger the task appeared callback to
359          * the organizer.
360          */
addTaskWithoutCallback(Task t, String reason)361         SurfaceControl addTaskWithoutCallback(Task t, String reason) {
362             t.mTaskAppearedSent = true;
363             if (!mOrganizedTasks.contains(t)) {
364                 mOrganizedTasks.add(t);
365             }
366             return mOrganizer.prepareLeash(t, reason);
367         }
368 
addTask(Task t)369         private boolean addTask(Task t) {
370             if (t.mTaskAppearedSent) {
371                 return false;
372             }
373 
374             if (!mOrganizedTasks.contains(t)) {
375                 mOrganizedTasks.add(t);
376             }
377 
378             if (t.taskAppearedReady()) {
379                 t.mTaskAppearedSent = true;
380                 return true;
381             }
382             return false;
383         }
384 
removeTask(Task t, boolean removeFromSystem)385         private boolean removeTask(Task t, boolean removeFromSystem) {
386             mOrganizedTasks.remove(t);
387             mInterceptBackPressedOnRootTasks.remove(t.mTaskId);
388             boolean taskAppearedSent = t.mTaskAppearedSent;
389             if (taskAppearedSent) {
390                 if (t.getSurfaceControl() != null) {
391                     t.migrateToNewSurfaceControl(t.getSyncTransaction());
392                 }
393                 t.mTaskAppearedSent = false;
394             }
395             if (removeFromSystem) {
396                 mService.removeTask(t.mTaskId);
397             }
398             return taskAppearedSent;
399         }
400 
dispose()401         void dispose() {
402             // Move organizer from managing specific windowing modes
403             mTaskOrganizers.remove(mOrganizer.mTaskOrganizer);
404 
405             // Update tasks currently managed by this organizer to the next one available if
406             // possible.
407             while (!mOrganizedTasks.isEmpty()) {
408                 final Task t = mOrganizedTasks.get(0);
409                 if (t.mCreatedByOrganizer) {
410                     // The tasks created by this organizer should ideally be deleted when this
411                     // organizer is disposed off to avoid inconsistent behavior.
412                     t.removeImmediately();
413                 } else {
414                     t.updateTaskOrganizerState();
415                 }
416                 if (mOrganizedTasks.contains(t)) {
417                     // updateTaskOrganizerState should remove the task from the list, but still
418                     // check it again to avoid while-loop isn't terminate.
419                     if (removeTask(t, t.mRemoveWithTaskOrganizer)) {
420                         TaskOrganizerController.this.onTaskVanishedInternal(this, t);
421                     }
422                 }
423                 if (mService.getTransitionController().isShellTransitionsEnabled()) {
424                     // dispose is only called outside of transitions (eg during unregister). Since
425                     // we "migrate" surfaces when replacing organizers, visibility gets delegated
426                     // to transitions; however, since there is no transition at this point, we have
427                     // to manually show the surface here.
428                     if (t.mTaskOrganizer != null && t.getSurfaceControl() != null) {
429                         t.getSyncTransaction().show(t.getSurfaceControl());
430                     }
431                 }
432             }
433 
434             // Pending events queue for this organizer need to be cleared because this organizer
435             // has either died or unregistered itself.
436             mPendingEventsQueue.clearPendingTaskEvents();
437             mTaskOrganizerStates.remove(mOrganizer.getBinder());
438         }
439 
unlinkDeath()440         void unlinkDeath() {
441             mOrganizer.getBinder().unlinkToDeath(mDeathRecipient, 0);
442         }
443     }
444 
445     static class PendingTaskEvent {
446         static final int EVENT_APPEARED = 0;
447         static final int EVENT_VANISHED = 1;
448         static final int EVENT_INFO_CHANGED = 2;
449         static final int EVENT_ROOT_BACK_PRESSED = 3;
450 
451         final int mEventType;
452         final Task mTask;
453         final ITaskOrganizer mTaskOrg;
454         boolean mForce;
455 
PendingTaskEvent(Task task, int event)456         PendingTaskEvent(Task task, int event) {
457             this(task, task.mTaskOrganizer, event);
458         }
459 
PendingTaskEvent(Task task, ITaskOrganizer taskOrg, int eventType)460         PendingTaskEvent(Task task, ITaskOrganizer taskOrg, int eventType) {
461             mTask = task;
462             mTaskOrg = taskOrg;
463             mEventType = eventType;
464         }
465 
isLifecycleEvent()466         boolean isLifecycleEvent() {
467             return mEventType == EVENT_APPEARED || mEventType == EVENT_VANISHED
468                     || mEventType == EVENT_INFO_CHANGED;
469         }
470     }
471 
472     private final ActivityTaskManagerService mService;
473     private final WindowManagerGlobalLock mGlobalLock;
474 
475     // List of task organizers by priority
476     private final LinkedList<ITaskOrganizer> mTaskOrganizers = new LinkedList<>();
477     private final ArrayMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new ArrayMap<>();
478     // Set of organized tasks (by taskId) that dispatch back pressed to their organizers
479     private final HashSet<Integer> mInterceptBackPressedOnRootTasks = new HashSet();
480 
481     private Consumer<Runnable> mDeferTaskOrgCallbacksConsumer;
482 
TaskOrganizerController(ActivityTaskManagerService atm)483     TaskOrganizerController(ActivityTaskManagerService atm) {
484         mService = atm;
485         mGlobalLock = atm.mGlobalLock;
486     }
487 
488     @Override
onTransact(int code, Parcel data, Parcel reply, int flags)489     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
490             throws RemoteException {
491         try {
492             return super.onTransact(code, data, reply, flags);
493         } catch (RuntimeException e) {
494             throw ActivityTaskManagerService.logAndRethrowRuntimeExceptionOnTransact(TAG, e);
495         }
496     }
497 
498     /**
499      * Specifies the consumer to run to defer the task org callbacks. Can be overridden while
500      * testing to allow the callbacks to be sent synchronously.
501      */
502     @VisibleForTesting
setDeferTaskOrgCallbacksConsumer(Consumer<Runnable> consumer)503     public void setDeferTaskOrgCallbacksConsumer(Consumer<Runnable> consumer) {
504         mDeferTaskOrgCallbacksConsumer = consumer;
505     }
506 
507     /**
508      * Register a TaskOrganizer to manage tasks as they enter the a supported windowing mode.
509      */
510     @Override
registerTaskOrganizer(ITaskOrganizer organizer)511     public ParceledListSlice<TaskAppearedInfo> registerTaskOrganizer(ITaskOrganizer organizer) {
512         enforceTaskPermission("registerTaskOrganizer()");
513         final int uid = Binder.getCallingUid();
514         final long origId = Binder.clearCallingIdentity();
515         try {
516             final ArrayList<TaskAppearedInfo> taskInfos = new ArrayList<>();
517             final Runnable withGlobalLock = () -> {
518                 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Register task organizer=%s uid=%d",
519                         organizer.asBinder(), uid);
520                 if (!mTaskOrganizerStates.containsKey(organizer.asBinder())) {
521                     mTaskOrganizers.add(organizer);
522                     mTaskOrganizerStates.put(organizer.asBinder(),
523                             new TaskOrganizerState(organizer, uid));
524                 }
525 
526                 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
527                 mService.mRootWindowContainer.forAllTasks((task) -> {
528                     boolean returnTask = !task.mCreatedByOrganizer;
529                     task.updateTaskOrganizerState(returnTask /* skipTaskAppeared */);
530                     // It is possible for the task to not yet have a surface control, so ensure that
531                     // the update succeeded in setting the organizer for the task before returning
532                     if (task.isOrganized() && returnTask) {
533                         SurfaceControl taskLeash = state.addTaskWithoutCallback(task,
534                                 "TaskOrganizerController.registerTaskOrganizer");
535                         taskInfos.add(new TaskAppearedInfo(task.getTaskInfo(), taskLeash));
536                     }
537                 });
538             };
539             if (mService.getTransitionController().isShellTransitionsEnabled()) {
540                 mService.getTransitionController().mRunningLock.runWhenIdle(1000, withGlobalLock);
541             } else {
542                 synchronized (mGlobalLock) {
543                     withGlobalLock.run();
544                 }
545             }
546             return new ParceledListSlice<>(taskInfos);
547         } finally {
548             Binder.restoreCallingIdentity(origId);
549         }
550     }
551 
552     @Override
unregisterTaskOrganizer(ITaskOrganizer organizer)553     public void unregisterTaskOrganizer(ITaskOrganizer organizer) {
554         enforceTaskPermission("unregisterTaskOrganizer()");
555         final int uid = Binder.getCallingUid();
556         final long origId = Binder.clearCallingIdentity();
557         try {
558             final Runnable withGlobalLock = () -> {
559                 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
560                 if (state == null) {
561                     return;
562                 }
563                 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Unregister task organizer=%s uid=%d",
564                         organizer.asBinder(), uid);
565                 state.unlinkDeath();
566                 state.dispose();
567             };
568             if (mService.getTransitionController().isShellTransitionsEnabled()) {
569                 mService.getTransitionController().mRunningLock.runWhenIdle(1000, withGlobalLock);
570             } else {
571                 synchronized (mGlobalLock) {
572                     withGlobalLock.run();
573                 }
574             }
575         } finally {
576             Binder.restoreCallingIdentity(origId);
577         }
578     }
579 
580     /**
581      * @return the task organizer key for a given windowing mode.
582      */
getTaskOrganizer()583     ITaskOrganizer getTaskOrganizer() {
584         return mTaskOrganizers.peekLast();
585     }
586 
587     // Capture the animation surface control for activity's main window
588     static class StartingWindowAnimationAdaptor implements AnimationAdapter {
589         SurfaceControl mAnimationLeash;
590         @Override
getShowWallpaper()591         public boolean getShowWallpaper() {
592             return false;
593         }
594 
595         @Override
startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t, int type, @NonNull SurfaceAnimator.OnAnimationFinishedCallback finishCallback)596         public void startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t,
597                 int type, @NonNull SurfaceAnimator.OnAnimationFinishedCallback finishCallback) {
598             mAnimationLeash = animationLeash;
599         }
600 
601         @Override
onAnimationCancelled(SurfaceControl animationLeash)602         public void onAnimationCancelled(SurfaceControl animationLeash) {
603             if (mAnimationLeash == animationLeash) {
604                 mAnimationLeash = null;
605             }
606         }
607 
608         @Override
getDurationHint()609         public long getDurationHint() {
610             return 0;
611         }
612 
613         @Override
getStatusBarTransitionsStartTime()614         public long getStatusBarTransitionsStartTime() {
615             return 0;
616         }
617 
618         @Override
dump(PrintWriter pw, String prefix)619         public void dump(PrintWriter pw, String prefix) {
620             pw.print(prefix + "StartingWindowAnimationAdaptor mCapturedLeash=");
621             pw.print(mAnimationLeash);
622             pw.println();
623         }
624 
625         @Override
dumpDebug(ProtoOutputStream proto)626         public void dumpDebug(ProtoOutputStream proto) {
627         }
628     }
629 
applyStartingWindowAnimation(WindowState window)630     static SurfaceControl applyStartingWindowAnimation(WindowState window) {
631         final SurfaceControl.Transaction t = window.getPendingTransaction();
632         final Rect mainFrame = window.getRelativeFrame();
633         final StartingWindowAnimationAdaptor adaptor = new StartingWindowAnimationAdaptor();
634         window.startAnimation(t, adaptor, false, ANIMATION_TYPE_STARTING_REVEAL);
635         if (adaptor.mAnimationLeash == null) {
636             Slog.e(TAG, "Cannot start starting window animation, the window " + window
637                     + " was removed");
638             return null;
639         }
640         t.setPosition(adaptor.mAnimationLeash, mainFrame.left, mainFrame.top);
641         return adaptor.mAnimationLeash;
642     }
643 
addStartingWindow(Task task, ActivityRecord activity, int launchTheme, TaskSnapshot taskSnapshot)644     boolean addStartingWindow(Task task, ActivityRecord activity, int launchTheme,
645             TaskSnapshot taskSnapshot) {
646         final Task rootTask = task.getRootTask();
647         if (rootTask == null || activity.mStartingData == null) {
648             return false;
649         }
650         final ITaskOrganizer lastOrganizer = mTaskOrganizers.peekLast();
651         if (lastOrganizer == null) {
652             return false;
653         }
654         final StartingWindowInfo info = task.getStartingWindowInfo(activity);
655         if (launchTheme != 0) {
656             info.splashScreenThemeResId = launchTheme;
657         }
658         info.taskSnapshot = taskSnapshot;
659         // make this happen prior than prepare surface
660         try {
661             lastOrganizer.addStartingWindow(info, activity.token);
662         } catch (RemoteException e) {
663             Slog.e(TAG, "Exception sending onTaskStart callback", e);
664             return false;
665         }
666         return true;
667     }
668 
removeStartingWindow(Task task, boolean prepareAnimation)669     void removeStartingWindow(Task task, boolean prepareAnimation) {
670         final Task rootTask = task.getRootTask();
671         if (rootTask == null) {
672             return;
673         }
674         final ITaskOrganizer lastOrganizer = mTaskOrganizers.peekLast();
675         if (lastOrganizer == null) {
676             return;
677         }
678         final StartingWindowRemovalInfo removalInfo = new StartingWindowRemovalInfo();
679         removalInfo.taskId = task.mTaskId;
680         removalInfo.playRevealAnimation = prepareAnimation
681                 && task.getDisplayInfo().state == Display.STATE_ON;
682         final boolean playShiftUpAnimation = !task.inMultiWindowMode();
683         final ActivityRecord topActivity = task.topActivityContainsStartingWindow();
684         if (topActivity != null) {
685             removalInfo.deferRemoveForIme = topActivity.mDisplayContent
686                     .mayImeShowOnLaunchingActivity(topActivity);
687             final WindowState mainWindow =
688                     topActivity.findMainWindow(false/* includeStartingApp */);
689             // No app window for this activity, app might be crashed.
690             // Remove starting window immediately without playing reveal animation.
691             if (mainWindow == null || mainWindow.mRemoved) {
692                 removalInfo.playRevealAnimation = false;
693             } else if (removalInfo.playRevealAnimation && playShiftUpAnimation) {
694                 removalInfo.roundedCornerRadius =
695                         topActivity.mLetterboxUiController.getRoundedCornersRadius(mainWindow);
696                 removalInfo.windowAnimationLeash = applyStartingWindowAnimation(mainWindow);
697                 removalInfo.mainFrame = mainWindow.getRelativeFrame();
698             }
699         }
700         try {
701             lastOrganizer.removeStartingWindow(removalInfo);
702         } catch (RemoteException e) {
703             Slog.e(TAG, "Exception sending onStartTaskFinished callback", e);
704         }
705     }
706 
copySplashScreenView(Task task)707     boolean copySplashScreenView(Task task) {
708         final Task rootTask = task.getRootTask();
709         if (rootTask == null) {
710             return false;
711         }
712         final ITaskOrganizer lastOrganizer = mTaskOrganizers.peekLast();
713         if (lastOrganizer == null) {
714             return false;
715         }
716         try {
717             lastOrganizer.copySplashScreenView(task.mTaskId);
718         } catch (RemoteException e) {
719             Slog.e(TAG, "Exception sending copyStartingWindowView callback", e);
720             return false;
721         }
722         return true;
723     }
724 
725     /**
726      * Notify the shell ({@link com.android.wm.shell.ShellTaskOrganizer} that the client has
727      * removed the splash screen view.
728      * @see com.android.wm.shell.ShellTaskOrganizer#onAppSplashScreenViewRemoved(int)
729      * @see SplashScreenView#remove()
730      */
onAppSplashScreenViewRemoved(Task task)731     public void onAppSplashScreenViewRemoved(Task task) {
732         final Task rootTask = task.getRootTask();
733         if (rootTask == null) {
734             return;
735         }
736         final ITaskOrganizer lastOrganizer = mTaskOrganizers.peekLast();
737         if (lastOrganizer == null) {
738             return;
739         }
740         try {
741             lastOrganizer.onAppSplashScreenViewRemoved(task.mTaskId);
742         } catch (RemoteException e) {
743             Slog.e(TAG, "Exception sending onAppSplashScreenViewRemoved callback", e);
744         }
745     }
746 
onTaskAppeared(ITaskOrganizer organizer, Task task)747     void onTaskAppeared(ITaskOrganizer organizer, Task task) {
748         final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
749         if (state != null && state.addTask(task)) {
750             final TaskOrganizerPendingEventsQueue pendingEvents =
751                     state.mPendingEventsQueue;
752             PendingTaskEvent pending = pendingEvents.getPendingTaskEvent(task,
753                     PendingTaskEvent.EVENT_APPEARED);
754             if (pending == null) {
755                 pendingEvents.addPendingTaskEvent(new PendingTaskEvent(task,
756                         PendingTaskEvent.EVENT_APPEARED));
757             }
758         }
759     }
760 
onTaskVanished(ITaskOrganizer organizer, Task task)761     void onTaskVanished(ITaskOrganizer organizer, Task task) {
762         final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
763         if (state != null && state.removeTask(task, task.mRemoveWithTaskOrganizer)) {
764             onTaskVanishedInternal(state, task);
765         }
766     }
767 
onTaskVanishedInternal(TaskOrganizerState organizerState, Task task)768     private void onTaskVanishedInternal(TaskOrganizerState organizerState, Task task) {
769         if (organizerState == null) {
770             Slog.i(TAG, "cannot send onTaskVanished because organizer state is not "
771                     + "present for this organizer");
772             return;
773         }
774         TaskOrganizerPendingEventsQueue pendingEventsQueue =
775                 organizerState.mPendingEventsQueue;
776         boolean hadPendingAppearedEvents =
777                 pendingEventsQueue.removePendingTaskEvents(task);
778         if (hadPendingAppearedEvents) {
779             return;
780         }
781         pendingEventsQueue.addPendingTaskEvent(new PendingTaskEvent(task,
782                 organizerState.mOrganizer.mTaskOrganizer, PendingTaskEvent.EVENT_VANISHED));
783     }
784 
785     @Override
createRootTask(int displayId, int windowingMode, @Nullable IBinder launchCookie, boolean removeWithTaskOrganizer)786     public void createRootTask(int displayId, int windowingMode, @Nullable IBinder launchCookie,
787             boolean removeWithTaskOrganizer) {
788         enforceTaskPermission("createRootTask()");
789         final long origId = Binder.clearCallingIdentity();
790         try {
791             synchronized (mGlobalLock) {
792                 DisplayContent display = mService.mRootWindowContainer.getDisplayContent(displayId);
793                 if (display == null) {
794                     ProtoLog.e(WM_DEBUG_WINDOW_ORGANIZER,
795                             "createRootTask unknown displayId=%d", displayId);
796                     return;
797                 }
798 
799                 createRootTask(display, windowingMode, launchCookie, removeWithTaskOrganizer);
800             }
801         } finally {
802             Binder.restoreCallingIdentity(origId);
803         }
804     }
805 
806     @VisibleForTesting
createRootTask(DisplayContent display, int windowingMode, @Nullable IBinder launchCookie)807     Task createRootTask(DisplayContent display, int windowingMode, @Nullable IBinder launchCookie) {
808         return createRootTask(display, windowingMode, launchCookie,
809                 false /* removeWithTaskOrganizer */);
810     }
811 
createRootTask(DisplayContent display, int windowingMode, @Nullable IBinder launchCookie, boolean removeWithTaskOrganizer)812     Task createRootTask(DisplayContent display, int windowingMode, @Nullable IBinder launchCookie,
813             boolean removeWithTaskOrganizer) {
814         ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Create root task displayId=%d winMode=%d",
815                 display.mDisplayId, windowingMode);
816         // We want to defer the task appear signal until the task is fully created and attached to
817         // to the hierarchy so that the complete starting configuration is in the task info we send
818         // over to the organizer.
819         final Task task = new Task.Builder(mService)
820                 .setWindowingMode(windowingMode)
821                 .setIntent(new Intent())
822                 .setCreatedByOrganizer(true)
823                 .setDeferTaskAppear(true)
824                 .setLaunchCookie(launchCookie)
825                 .setParent(display.getDefaultTaskDisplayArea())
826                 .setRemoveWithTaskOrganizer(removeWithTaskOrganizer)
827                 .build();
828         task.setDeferTaskAppear(false /* deferTaskAppear */);
829         return task;
830     }
831 
832     @Override
deleteRootTask(WindowContainerToken token)833     public boolean deleteRootTask(WindowContainerToken token) {
834         enforceTaskPermission("deleteRootTask()");
835         final long origId = Binder.clearCallingIdentity();
836         try {
837             synchronized (mGlobalLock) {
838                 final WindowContainer wc = WindowContainer.fromBinder(token.asBinder());
839                 if (wc == null) return false;
840                 final Task task = wc.asTask();
841                 if (task == null) return false;
842                 if (!task.mCreatedByOrganizer) {
843                     throw new IllegalArgumentException(
844                             "Attempt to delete task not created by organizer task=" + task);
845                 }
846 
847                 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Delete root task display=%d winMode=%d",
848                         task.getDisplayId(), task.getWindowingMode());
849                 task.remove(true /* withTransition */, "deleteRootTask");
850                 return true;
851             }
852         } finally {
853             Binder.restoreCallingIdentity(origId);
854         }
855     }
856 
dispatchPendingEvents()857     void dispatchPendingEvents() {
858         if (mService.mWindowManager.mWindowPlacerLocked.isLayoutDeferred()) {
859             return;
860         }
861         for (int taskOrgIdx = 0; taskOrgIdx < mTaskOrganizerStates.size(); taskOrgIdx++) {
862             TaskOrganizerState taskOrganizerState = mTaskOrganizerStates.valueAt(taskOrgIdx);
863             taskOrganizerState.mPendingEventsQueue.dispatchPendingEvents();
864         }
865     }
866 
reportImeDrawnOnTask(Task task)867     void reportImeDrawnOnTask(Task task) {
868         final TaskOrganizerState state = mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder());
869         if (state != null) {
870             try {
871                 state.mOrganizer.mTaskOrganizer.onImeDrawnOnTask(task.mTaskId);
872             } catch (RemoteException e) {
873                 Slog.e(TAG, "Exception sending onImeDrawnOnTask callback", e);
874             }
875         }
876     }
877 
onTaskInfoChanged(Task task, boolean force)878     void onTaskInfoChanged(Task task, boolean force) {
879         if (!task.mTaskAppearedSent) {
880             // Skip if task still not appeared.
881             return;
882         }
883         final TaskOrganizerState taskOrganizerState =
884                 mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder());
885         final TaskOrganizerPendingEventsQueue pendingEventsQueue =
886                 taskOrganizerState.mPendingEventsQueue;
887         if (pendingEventsQueue == null) {
888             Slog.i(TAG, "cannot send onTaskInfoChanged because pending events queue is not "
889                     + "present for this organizer");
890             return;
891         }
892         if (force && pendingEventsQueue.numPendingTaskEvents() == 0) {
893             // There are task-info changed events do not result in
894             // - RootWindowContainer#performSurfacePlacementNoTrace OR
895             // - WindowAnimator#animate
896             // For instance, when an app requesting aspect ratio change when in PiP mode.
897             // To solve this, we directly dispatch the pending event if there are no events queued (
898             // otherwise, all pending events should be dispatched on next drawn).
899             pendingEventsQueue.dispatchTaskInfoChanged(task, true /* force */);
900             return;
901         }
902 
903         // Defer task info reporting while layout is deferred. This is because layout defer
904         // blocks tend to do lots of re-ordering which can mess up animations in receivers.
905         PendingTaskEvent pending = pendingEventsQueue
906                 .getPendingLifecycleTaskEvent(task);
907         if (pending == null) {
908             pending = new PendingTaskEvent(task, PendingTaskEvent.EVENT_INFO_CHANGED);
909         } else {
910             if (pending.mEventType != PendingTaskEvent.EVENT_INFO_CHANGED) {
911                 // If queued event is appeared, it means task still not appeared so ignore
912                 // this info changed. If queued event is vanished, it means task should
913                 // will vanished early so do not need this info changed.
914                 return;
915             }
916             // Remove and add for re-ordering.
917             pendingEventsQueue.removePendingTaskEvent(pending);
918         }
919         pending.mForce |= force;
920         pendingEventsQueue.addPendingTaskEvent(pending);
921     }
922 
923     @Override
getImeTarget(int displayId)924     public WindowContainerToken getImeTarget(int displayId) {
925         enforceTaskPermission("getImeTarget()");
926         final long origId = Binder.clearCallingIdentity();
927         try {
928             synchronized (mGlobalLock) {
929                 final DisplayContent dc = mService.mWindowManager.mRoot
930                         .getDisplayContent(displayId);
931                 if (dc == null) {
932                     return null;
933                 }
934 
935                 final InsetsControlTarget imeLayeringTarget = dc.getImeTarget(IME_TARGET_LAYERING);
936                 if (imeLayeringTarget == null || imeLayeringTarget.getWindow() == null) {
937                     return null;
938                 }
939 
940                 // Avoid WindowState#getRootTask() so we don't attribute system windows to a task.
941                 final Task task = imeLayeringTarget.getWindow().getTask();
942                 if (task == null) {
943                     return null;
944                 }
945 
946                 return task.mRemoteToken.toWindowContainerToken();
947             }
948         } finally {
949             Binder.restoreCallingIdentity(origId);
950         }
951     }
952 
953     @Override
getChildTasks(WindowContainerToken parent, @Nullable int[] activityTypes)954     public List<RunningTaskInfo> getChildTasks(WindowContainerToken parent,
955             @Nullable int[] activityTypes) {
956         enforceTaskPermission("getChildTasks()");
957         final long ident = Binder.clearCallingIdentity();
958         try {
959             synchronized (mGlobalLock) {
960                 if (parent == null) {
961                     throw new IllegalArgumentException("Can't get children of null parent");
962                 }
963                 final WindowContainer container = WindowContainer.fromBinder(parent.asBinder());
964                 if (container == null) {
965                     Slog.e(TAG, "Can't get children of " + parent + " because it is not valid.");
966                     return null;
967                 }
968                 final Task task = container.asTask();
969                 if (task == null) {
970                     Slog.e(TAG, container + " is not a task...");
971                     return null;
972                 }
973                 // For now, only support returning children of tasks created by the organizer.
974                 if (!task.mCreatedByOrganizer) {
975                     Slog.w(TAG, "Can only get children of root tasks created via createRootTask");
976                     return null;
977                 }
978                 ArrayList<RunningTaskInfo> out = new ArrayList<>();
979                 for (int i = task.getChildCount() - 1; i >= 0; --i) {
980                     final Task child = task.getChildAt(i).asTask();
981                     if (child == null) continue;
982                     if (activityTypes != null
983                             && !ArrayUtils.contains(activityTypes, child.getActivityType())) {
984                         continue;
985                     }
986                     out.add(child.getTaskInfo());
987                 }
988                 return out;
989             }
990         } finally {
991             Binder.restoreCallingIdentity(ident);
992         }
993     }
994 
995     @Override
getRootTasks(int displayId, @Nullable int[] activityTypes)996     public List<RunningTaskInfo> getRootTasks(int displayId, @Nullable int[] activityTypes) {
997         enforceTaskPermission("getRootTasks()");
998         final long ident = Binder.clearCallingIdentity();
999         try {
1000             synchronized (mGlobalLock) {
1001                 final DisplayContent dc =
1002                         mService.mRootWindowContainer.getDisplayContent(displayId);
1003                 if (dc == null) {
1004                     throw new IllegalArgumentException("Display " + displayId + " doesn't exist");
1005                 }
1006                 final ArrayList<RunningTaskInfo> out = new ArrayList<>();
1007                 dc.forAllRootTasks(task -> {
1008                     if (activityTypes != null
1009                             && !ArrayUtils.contains(activityTypes, task.getActivityType())) {
1010                         return;
1011                     }
1012                     out.add(task.getTaskInfo());
1013                 });
1014                 return out;
1015             }
1016         } finally {
1017             Binder.restoreCallingIdentity(ident);
1018         }
1019     }
1020 
1021     @Override
setInterceptBackPressedOnTaskRoot(WindowContainerToken token, boolean interceptBackPressed)1022     public void setInterceptBackPressedOnTaskRoot(WindowContainerToken token,
1023             boolean interceptBackPressed) {
1024         enforceTaskPermission("setInterceptBackPressedOnTaskRoot()");
1025         final long origId = Binder.clearCallingIdentity();
1026         try {
1027             synchronized (mGlobalLock) {
1028                 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Set intercept back pressed on root=%b",
1029                         interceptBackPressed);
1030                 final WindowContainer wc = WindowContainer.fromBinder(token.asBinder());
1031                 if (wc == null) {
1032                     Slog.w(TAG, "Could not resolve window from token");
1033                     return;
1034                 }
1035                 final Task task = wc.asTask();
1036                 if (task == null) {
1037                     Slog.w(TAG, "Could not resolve task from token");
1038                     return;
1039                 }
1040                 if (interceptBackPressed) {
1041                     mInterceptBackPressedOnRootTasks.add(task.mTaskId);
1042                 } else {
1043                     mInterceptBackPressedOnRootTasks.remove(task.mTaskId);
1044                 }
1045             }
1046         } finally {
1047             Binder.restoreCallingIdentity(origId);
1048         }
1049     }
1050 
1051     @Override
restartTaskTopActivityProcessIfVisible(WindowContainerToken token)1052     public void restartTaskTopActivityProcessIfVisible(WindowContainerToken token) {
1053         enforceTaskPermission("restartTopActivityProcessIfVisible()");
1054         final long origId = Binder.clearCallingIdentity();
1055         try {
1056             synchronized (mGlobalLock) {
1057                 final WindowContainer wc = WindowContainer.fromBinder(token.asBinder());
1058                 if (wc == null) {
1059                     Slog.w(TAG, "Could not resolve window from token");
1060                     return;
1061                 }
1062                 final Task task = wc.asTask();
1063                 if (task == null) {
1064                     Slog.w(TAG, "Could not resolve task from token");
1065                     return;
1066                 }
1067                 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
1068                         "Restart top activity process of Task taskId=%d", task.mTaskId);
1069                 final ActivityRecord activity = task.getTopNonFinishingActivity();
1070                 if (activity != null) {
1071                     activity.restartProcessIfVisible();
1072                 }
1073             }
1074         } finally {
1075             Binder.restoreCallingIdentity(origId);
1076         }
1077     }
1078 
1079     @Override
updateCameraCompatControlState(WindowContainerToken token, int state)1080     public void updateCameraCompatControlState(WindowContainerToken token, int state) {
1081         enforceTaskPermission("updateCameraCompatControlState()");
1082         final long origId = Binder.clearCallingIdentity();
1083         try {
1084             synchronized (mGlobalLock) {
1085                 final WindowContainer wc = WindowContainer.fromBinder(token.asBinder());
1086                 if (wc == null) {
1087                     Slog.w(TAG, "Could not resolve window from token");
1088                     return;
1089                 }
1090                 final Task task = wc.asTask();
1091                 if (task == null) {
1092                     Slog.w(TAG, "Could not resolve task from token");
1093                     return;
1094                 }
1095                 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER,
1096                         "Update camera compat control state to %s for taskId=%d",
1097                         cameraCompatControlStateToString(state), task.mTaskId);
1098                 final ActivityRecord activity = task.getTopNonFinishingActivity();
1099                 if (activity != null) {
1100                     activity.updateCameraCompatStateFromUser(state);
1101                 }
1102             }
1103         } finally {
1104             Binder.restoreCallingIdentity(origId);
1105         }
1106     }
1107 
1108     @Override
setOrientationRequestPolicy(boolean isIgnoreOrientationRequestDisabled, @Nullable int[] fromOrientations, @Nullable int[] toOrientations)1109     public void setOrientationRequestPolicy(boolean isIgnoreOrientationRequestDisabled,
1110             @Nullable int[] fromOrientations, @Nullable int[] toOrientations) {
1111         enforceTaskPermission("setOrientationRequestPolicy()");
1112         final long origId = Binder.clearCallingIdentity();
1113         try {
1114             synchronized (mGlobalLock) {
1115                 mService.mWindowManager
1116                         .setOrientationRequestPolicy(isIgnoreOrientationRequestDisabled,
1117                                 fromOrientations, toOrientations);
1118             }
1119         } finally {
1120             Binder.restoreCallingIdentity(origId);
1121         }
1122     }
1123 
handleInterceptBackPressedOnTaskRoot(Task task)1124     public boolean handleInterceptBackPressedOnTaskRoot(Task task) {
1125         if (task == null || !task.isOrganized()
1126                 || !mInterceptBackPressedOnRootTasks.contains(task.mTaskId)) {
1127             return false;
1128         }
1129         final TaskOrganizerPendingEventsQueue pendingEventsQueue =
1130                 mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder())
1131                         .mPendingEventsQueue;
1132         if (pendingEventsQueue == null) {
1133             Slog.w(TAG, "cannot get handle BackPressedOnTaskRoot because organizerState is "
1134                     + "not present");
1135             return false;
1136         }
1137 
1138         PendingTaskEvent pendingVanished =
1139                 pendingEventsQueue.getPendingTaskEvent(task,
1140                         PendingTaskEvent.EVENT_VANISHED);
1141         if (pendingVanished != null) {
1142             // This task will vanish before this callback so just ignore.
1143             return false;
1144         }
1145 
1146         PendingTaskEvent pending = pendingEventsQueue.getPendingTaskEvent(
1147                 task, PendingTaskEvent.EVENT_ROOT_BACK_PRESSED);
1148         if (pending == null) {
1149             pending = new PendingTaskEvent(task, PendingTaskEvent.EVENT_ROOT_BACK_PRESSED);
1150         } else {
1151             // Pending already exist, remove and add for re-ordering.
1152             pendingEventsQueue.removePendingTaskEvent(pending);
1153         }
1154         pendingEventsQueue.addPendingTaskEvent(pending);
1155         mService.mWindowManager.mWindowPlacerLocked.requestTraversal();
1156         return true;
1157     }
1158 
dump(PrintWriter pw, String prefix)1159     public void dump(PrintWriter pw, String prefix) {
1160         final String innerPrefix = prefix + "  ";
1161         pw.print(prefix); pw.println("TaskOrganizerController:");
1162         for (final TaskOrganizerState state : mTaskOrganizerStates.values()) {
1163             final ArrayList<Task> tasks = state.mOrganizedTasks;
1164             pw.print(innerPrefix + "  ");
1165             pw.println(state.mOrganizer.mTaskOrganizer + " uid=" + state.mUid + ":");
1166             for (int k = 0; k < tasks.size(); k++) {
1167                 final Task task = tasks.get(k);
1168                 final int mode = task.getWindowingMode();
1169                 pw.println(innerPrefix + "    ("
1170                         + WindowConfiguration.windowingModeToString(mode) + ") " + task);
1171             }
1172 
1173         }
1174         pw.println();
1175     }
1176 
1177     @VisibleForTesting
getTaskOrganizerState(IBinder taskOrganizer)1178     TaskOrganizerState getTaskOrganizerState(IBinder taskOrganizer) {
1179         return mTaskOrganizerStates.get(taskOrganizer);
1180     }
1181 
1182     @VisibleForTesting
getTaskOrganizerPendingEvents(IBinder taskOrganizer)1183     TaskOrganizerPendingEventsQueue getTaskOrganizerPendingEvents(IBinder taskOrganizer) {
1184         return mTaskOrganizerStates.get(taskOrganizer).mPendingEventsQueue;
1185     }
1186 }
1187