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