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