• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm;
18 
19 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
20 import static android.window.StartingWindowRemovalInfo.DEFER_MODE_NONE;
21 import static android.window.StartingWindowRemovalInfo.DEFER_MODE_NORMAL;
22 import static android.window.StartingWindowRemovalInfo.DEFER_MODE_ROTATION;
23 
24 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_WINDOW_ORGANIZER;
25 import static com.android.server.wm.ActivityTaskManagerService.enforceTaskPermission;
26 import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
27 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_STARTING_REVEAL;
28 import static com.android.server.wm.WindowOrganizerController.configurationsAreEqualForOrganizer;
29 
30 import android.annotation.NonNull;
31 import android.annotation.Nullable;
32 import android.app.ActivityManager;
33 import android.app.ActivityManager.RunningTaskInfo;
34 import android.app.WindowConfiguration;
35 import android.content.Intent;
36 import android.content.pm.ParceledListSlice;
37 import android.content.res.Configuration;
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.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 
69 /**
70  * Stores the TaskOrganizers associated with a given windowing mode and
71  * their associated state.
72  */
73 class TaskOrganizerController extends ITaskOrganizerController.Stub {
74     private static final String TAG = "TaskOrganizerController";
75 
76     @VisibleForTesting
77     class DeathRecipient implements IBinder.DeathRecipient {
78         ITaskOrganizer mTaskOrganizer;
79 
DeathRecipient(ITaskOrganizer organizer)80         DeathRecipient(ITaskOrganizer organizer) {
81             mTaskOrganizer = organizer;
82         }
83 
84         @Override
binderDied()85         public void binderDied() {
86             synchronized (mGlobalLock) {
87                 final TaskOrganizerState state = mTaskOrganizerStates.get(
88                         mTaskOrganizer.asBinder());
89                 if (state != null) {
90                     state.dispose();
91                 }
92             }
93         }
94     }
95 
96     /**
97      * A wrapper class around ITaskOrganizer to ensure that the calls are made in the right
98      * lifecycle order since we may be updating the visibility of task surface controls in a pending
99      * transaction before they are presented to the task org.
100      */
101     private static class TaskOrganizerCallbacks {
102         final ITaskOrganizer mTaskOrganizer;
103 
TaskOrganizerCallbacks(ITaskOrganizer taskOrg)104         TaskOrganizerCallbacks(ITaskOrganizer taskOrg) {
105             mTaskOrganizer = taskOrg;
106         }
107 
getBinder()108         IBinder getBinder() {
109             return mTaskOrganizer.asBinder();
110         }
111 
prepareLeash(Task task, String reason)112         SurfaceControl prepareLeash(Task task, String reason) {
113             return new SurfaceControl(task.getSurfaceControl(), reason);
114         }
115 
onTaskAppeared(Task task)116         void onTaskAppeared(Task task) {
117             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task appeared taskId=%d", task.mTaskId);
118             final RunningTaskInfo taskInfo = task.getTaskInfo();
119             try {
120                 mTaskOrganizer.onTaskAppeared(taskInfo, prepareLeash(task,
121                         "TaskOrganizerController.onTaskAppeared"));
122             } catch (RemoteException e) {
123                 Slog.e(TAG, "Exception sending onTaskAppeared callback", e);
124             }
125         }
126 
onTaskVanished(Task task)127         void onTaskVanished(Task task) {
128             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task vanished taskId=%d", task.mTaskId);
129             final RunningTaskInfo taskInfo = task.getTaskInfo();
130             try {
131                 mTaskOrganizer.onTaskVanished(taskInfo);
132             } catch (RemoteException e) {
133                 Slog.e(TAG, "Exception sending onTaskVanished callback", e);
134             }
135         }
136 
onTaskInfoChanged(Task task, ActivityManager.RunningTaskInfo taskInfo)137         void onTaskInfoChanged(Task task, ActivityManager.RunningTaskInfo taskInfo) {
138             if (!task.mTaskAppearedSent) {
139                 // Skip if the task has not yet received taskAppeared().
140                 return;
141             }
142             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task info changed taskId=%d", task.mTaskId);
143             if (!task.isOrganized()) {
144                 // This is safe to ignore if the task is no longer organized
145                 return;
146             }
147             try {
148                 // Purposely notify of task info change immediately instead of deferring (like
149                 // appear and vanish) to allow info changes (such as new PIP params) to flow
150                 // without waiting.
151                 mTaskOrganizer.onTaskInfoChanged(taskInfo);
152             } catch (RemoteException e) {
153                 Slog.e(TAG, "Exception sending onTaskInfoChanged callback", e);
154             }
155         }
156 
onBackPressedOnTaskRoot(Task task)157         void onBackPressedOnTaskRoot(Task task) {
158             ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Task back pressed on root taskId=%d",
159                     task.mTaskId);
160             if (!task.mTaskAppearedSent) {
161                 // Skip if the task has not yet received taskAppeared().
162                 return;
163             }
164             if (!task.isOrganized()) {
165                 // This is safe to ignore if the task is no longer organized
166                 return;
167             }
168             try {
169                 mTaskOrganizer.onBackPressedOnTaskRoot(task.getTaskInfo());
170             } catch (Exception e) {
171                 Slog.e(TAG, "Exception sending onBackPressedOnTaskRoot callback", e);
172             }
173         }
174     }
175 
176     /**
177      * Maintains a list of all the pending events for a given {@link android.window.TaskOrganizer}
178      */
179     static final class TaskOrganizerPendingEventsQueue {
180         private final WeakHashMap<Task, RunningTaskInfo> mLastSentTaskInfos = new WeakHashMap<>();
181         private final TaskOrganizerState mOrganizerState;
182         private RunningTaskInfo mTmpTaskInfo;
183         // Pending task events due to layout deferred.
184         private final ArrayList<PendingTaskEvent> mPendingTaskEvents = new ArrayList<>();
185 
TaskOrganizerPendingEventsQueue(TaskOrganizerState taskOrganizerState)186         TaskOrganizerPendingEventsQueue(TaskOrganizerState taskOrganizerState) {
187             mOrganizerState = taskOrganizerState;
188         }
189 
190         @VisibleForTesting
getPendingEventList()191         public ArrayList<PendingTaskEvent> getPendingEventList() {
192             return mPendingTaskEvents;
193         }
194 
numPendingTaskEvents()195         int numPendingTaskEvents() {
196             return mPendingTaskEvents.size();
197         }
198 
clearPendingTaskEvents()199         void clearPendingTaskEvents() {
200             mPendingTaskEvents.clear();
201         }
202 
addPendingTaskEvent(PendingTaskEvent event)203         void addPendingTaskEvent(PendingTaskEvent event) {
204             mPendingTaskEvents.add(event);
205         }
206 
removePendingTaskEvent(PendingTaskEvent event)207         void removePendingTaskEvent(PendingTaskEvent event) {
208             mPendingTaskEvents.remove(event);
209         }
210 
211         /**
212          * Removes all the pending task events for the given {@code task}.
213          *
214          * @param task
215          * @return true if a {@link PendingTaskEvent#EVENT_APPEARED} is still pending for the given
216          * {code task}.
217          */
removePendingTaskEvents(Task task)218         boolean removePendingTaskEvents(Task task) {
219             boolean foundPendingAppearedEvents = false;
220             for (int i = mPendingTaskEvents.size() - 1; i >= 0; i--) {
221                 PendingTaskEvent entry = mPendingTaskEvents.get(i);
222                 if (task.mTaskId == entry.mTask.mTaskId) {
223                     // This task is vanished so remove all pending event of it.
224                     mPendingTaskEvents.remove(i);
225 
226                     if (entry.mEventType == PendingTaskEvent.EVENT_APPEARED) {
227                         foundPendingAppearedEvents = true;
228                     }
229                 }
230             }
231             return foundPendingAppearedEvents;
232         }
233 
234         @Nullable
getPendingTaskEvent(Task task, int type)235         private PendingTaskEvent getPendingTaskEvent(Task task, int type) {
236             for (int i = mPendingTaskEvents.size() - 1; i >= 0; i--) {
237                 PendingTaskEvent entry = mPendingTaskEvents.get(i);
238                 if (task.mTaskId == entry.mTask.mTaskId && type == entry.mEventType) {
239                     return entry;
240                 }
241             }
242             return null;
243         }
244 
245         @VisibleForTesting
246         @Nullable
getPendingLifecycleTaskEvent(Task task)247         PendingTaskEvent getPendingLifecycleTaskEvent(Task task) {
248             for (int i = mPendingTaskEvents.size() - 1; i >= 0; i--) {
249                 PendingTaskEvent entry = mPendingTaskEvents.get(i);
250                 if (task.mTaskId == entry.mTask.mTaskId && entry.isLifecycleEvent()) {
251                     return entry;
252                 }
253             }
254             return null;
255         }
256 
dispatchPendingEvents()257         void dispatchPendingEvents() {
258             if (mPendingTaskEvents.isEmpty()) {
259                 return;
260             }
261             for (int i = 0, n = mPendingTaskEvents.size(); i < n; i++) {
262                 dispatchPendingEvent(mPendingTaskEvents.get(i));
263             }
264             mPendingTaskEvents.clear();
265         }
266 
dispatchPendingEvent(PendingTaskEvent event)267         private void dispatchPendingEvent(PendingTaskEvent event) {
268             final Task task = event.mTask;
269             switch (event.mEventType) {
270                 case PendingTaskEvent.EVENT_APPEARED:
271                     if (task.taskAppearedReady()) {
272                         mOrganizerState.mOrganizer.onTaskAppeared(task);
273                     }
274                     break;
275                 case PendingTaskEvent.EVENT_VANISHED:
276                     mOrganizerState.mOrganizer.onTaskVanished(task);
277                     mLastSentTaskInfos.remove(task);
278                     break;
279                 case PendingTaskEvent.EVENT_INFO_CHANGED:
280                     dispatchTaskInfoChanged(event.mTask, event.mForce);
281                     break;
282                 case PendingTaskEvent.EVENT_ROOT_BACK_PRESSED:
283                     mOrganizerState.mOrganizer.onBackPressedOnTaskRoot(task);
284                     break;
285             }
286         }
287 
dispatchTaskInfoChanged(Task task, boolean force)288         private void dispatchTaskInfoChanged(Task task, boolean force) {
289             RunningTaskInfo lastInfo = mLastSentTaskInfos.get(task);
290             if (mTmpTaskInfo == null) {
291                 mTmpTaskInfo = new RunningTaskInfo();
292             }
293             mTmpTaskInfo.configuration.unset();
294             task.fillTaskInfo(mTmpTaskInfo);
295 
296             boolean changed = !mTmpTaskInfo
297                     .equalsForTaskOrganizer(lastInfo)
298                     || !configurationsAreEqualForOrganizer(
299                     mTmpTaskInfo.configuration,
300                     lastInfo.configuration);
301             if (!(changed || force)) {
302                 // mTmpTaskInfo will be reused next time.
303                 return;
304             }
305             final RunningTaskInfo newInfo = mTmpTaskInfo;
306             mLastSentTaskInfos.put(task,
307                     mTmpTaskInfo);
308             // Since we've stored this, clean up the reference so a new one will be created next
309             // time.
310             // Transferring it this way means we only have to construct new RunningTaskInfos when
311             // they change.
312             mTmpTaskInfo = null;
313 
314             if (task.isOrganized()) {
315                 // Because we defer sending taskAppeared() until the app has drawn, we may receive a
316                 // configuration change before the state actually has the task registered. As such
317                 // we should ignore these change events to the organizer until taskAppeared(). If
318                 // the task was created by the organizer, then we always send the info change.
319                 mOrganizerState.mOrganizer.onTaskInfoChanged(task, newInfo);
320             }
321         }
322     }
323 
324     @VisibleForTesting
325     class TaskOrganizerState {
326         private final TaskOrganizerCallbacks mOrganizer;
327         private final DeathRecipient mDeathRecipient;
328         private final ArrayList<Task> mOrganizedTasks = new ArrayList<>();
329         private final TaskOrganizerPendingEventsQueue mPendingEventsQueue;
330         private final int mUid;
331 
TaskOrganizerState(ITaskOrganizer organizer, int uid)332         TaskOrganizerState(ITaskOrganizer organizer, int uid) {
333             mOrganizer = new TaskOrganizerCallbacks(organizer);
334             mDeathRecipient = new DeathRecipient(organizer);
335             mPendingEventsQueue = new TaskOrganizerPendingEventsQueue(this);
336             try {
337                 organizer.asBinder().linkToDeath(mDeathRecipient, 0);
338             } catch (RemoteException e) {
339                 Slog.e(TAG, "TaskOrganizer failed to register death recipient");
340             }
341             mUid = uid;
342         }
343 
344         @VisibleForTesting
getDeathRecipient()345         DeathRecipient getDeathRecipient() {
346             return mDeathRecipient;
347         }
348 
349         @VisibleForTesting
getPendingEventsQueue()350         TaskOrganizerPendingEventsQueue getPendingEventsQueue() {
351             return mPendingEventsQueue;
352         }
353 
354         /**
355          * Register this task with this state, but doesn't trigger the task appeared callback to
356          * the organizer.
357          */
addTaskWithoutCallback(Task t, String reason)358         SurfaceControl addTaskWithoutCallback(Task t, String reason) {
359             t.mTaskAppearedSent = true;
360             if (!mOrganizedTasks.contains(t)) {
361                 mOrganizedTasks.add(t);
362             }
363             return mOrganizer.prepareLeash(t, reason);
364         }
365 
addTask(Task t)366         private boolean addTask(Task t) {
367             if (t.mTaskAppearedSent) {
368                 return false;
369             }
370 
371             if (!mOrganizedTasks.contains(t)) {
372                 mOrganizedTasks.add(t);
373             }
374 
375             if (t.taskAppearedReady()) {
376                 t.mTaskAppearedSent = true;
377                 return true;
378             }
379             return false;
380         }
381 
removeTask(Task t, boolean removeFromSystem)382         private boolean removeTask(Task t, boolean removeFromSystem) {
383             mOrganizedTasks.remove(t);
384             mInterceptBackPressedOnRootTasks.remove(t.mTaskId);
385             boolean taskAppearedSent = t.mTaskAppearedSent;
386             if (taskAppearedSent) {
387                 if (t.getSurfaceControl() != null) {
388                     t.migrateToNewSurfaceControl(t.getSyncTransaction());
389                 }
390                 t.mTaskAppearedSent = false;
391             }
392             if (removeFromSystem) {
393                 mService.removeTask(t);
394             }
395             return taskAppearedSent;
396         }
397 
dispose()398         void dispose() {
399             // Move organizer from managing specific windowing modes
400             mTaskOrganizers.remove(mOrganizer.mTaskOrganizer);
401 
402             // Update tasks currently managed by this organizer to the next one available if
403             // possible.
404             while (!mOrganizedTasks.isEmpty()) {
405                 final Task t = mOrganizedTasks.get(0);
406                 if (t.mCreatedByOrganizer) {
407                     // The tasks created by this organizer should ideally be deleted when this
408                     // organizer is disposed off to avoid inconsistent behavior.
409                     t.removeImmediately();
410                 } else {
411                     t.updateTaskOrganizerState();
412                 }
413                 if (mOrganizedTasks.contains(t)) {
414                     // updateTaskOrganizerState should remove the task from the list, but still
415                     // check it again to avoid while-loop isn't terminate.
416                     if (removeTask(t, t.mRemoveWithTaskOrganizer)) {
417                         TaskOrganizerController.this.onTaskVanishedInternal(this, t);
418                     }
419                 }
420                 if (mService.getTransitionController().isShellTransitionsEnabled()) {
421                     // dispose is only called outside of transitions (eg during unregister). Since
422                     // we "migrate" surfaces when replacing organizers, visibility gets delegated
423                     // to transitions; however, since there is no transition at this point, we have
424                     // to manually show the surface here.
425                     if (t.mTaskOrganizer != null && t.getSurfaceControl() != null) {
426                         t.getSyncTransaction().show(t.getSurfaceControl());
427                     }
428                 }
429             }
430 
431             // Pending events queue for this organizer need to be cleared because this organizer
432             // has either died or unregistered itself.
433             mPendingEventsQueue.clearPendingTaskEvents();
434             mTaskOrganizerStates.remove(mOrganizer.getBinder());
435         }
436 
unlinkDeath()437         void unlinkDeath() {
438             mOrganizer.getBinder().unlinkToDeath(mDeathRecipient, 0);
439         }
440     }
441 
442     static class PendingTaskEvent {
443         static final int EVENT_APPEARED = 0;
444         static final int EVENT_VANISHED = 1;
445         static final int EVENT_INFO_CHANGED = 2;
446         static final int EVENT_ROOT_BACK_PRESSED = 3;
447 
448         final int mEventType;
449         final Task mTask;
450         final ITaskOrganizer mTaskOrg;
451         boolean mForce;
452 
PendingTaskEvent(Task task, int event)453         PendingTaskEvent(Task task, int event) {
454             this(task, task.mTaskOrganizer, event);
455         }
456 
PendingTaskEvent(Task task, ITaskOrganizer taskOrg, int eventType)457         PendingTaskEvent(Task task, ITaskOrganizer taskOrg, int eventType) {
458             mTask = task;
459             mTaskOrg = taskOrg;
460             mEventType = eventType;
461         }
462 
isLifecycleEvent()463         boolean isLifecycleEvent() {
464             return mEventType == EVENT_APPEARED || mEventType == EVENT_VANISHED
465                     || mEventType == EVENT_INFO_CHANGED;
466         }
467     }
468 
469     private final ActivityTaskManagerService mService;
470     private final WindowManagerGlobalLock mGlobalLock;
471 
472     // List of task organizers by priority
473     private final ArrayDeque<ITaskOrganizer> mTaskOrganizers = new ArrayDeque<>();
474     private final ArrayMap<IBinder, TaskOrganizerState> mTaskOrganizerStates = new ArrayMap<>();
475     // Set of organized tasks (by taskId) that dispatch back pressed to their organizers
476     private final HashSet<Integer> mInterceptBackPressedOnRootTasks = new HashSet<>();
477 
TaskOrganizerController(ActivityTaskManagerService atm)478     TaskOrganizerController(ActivityTaskManagerService atm) {
479         mService = atm;
480         mGlobalLock = atm.mGlobalLock;
481     }
482 
483     @Override
onTransact(int code, Parcel data, Parcel reply, int flags)484     public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
485             throws RemoteException {
486         try {
487             return super.onTransact(code, data, reply, flags);
488         } catch (RuntimeException e) {
489             throw ActivityTaskManagerService.logAndRethrowRuntimeExceptionOnTransact(TAG, e);
490         }
491     }
492 
493     /**
494      * Register a TaskOrganizer to manage tasks as they enter the a supported windowing mode.
495      */
496     @Override
registerTaskOrganizer(ITaskOrganizer organizer)497     public ParceledListSlice<TaskAppearedInfo> registerTaskOrganizer(ITaskOrganizer organizer) {
498         enforceTaskPermission("registerTaskOrganizer()");
499         final int uid = Binder.getCallingUid();
500         final long origId = Binder.clearCallingIdentity();
501         try {
502             final ArrayList<TaskAppearedInfo> taskInfos = new ArrayList<>();
503             final Runnable withGlobalLock = () -> {
504                 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Register task organizer=%s uid=%d",
505                         organizer.asBinder(), uid);
506                 if (!mTaskOrganizerStates.containsKey(organizer.asBinder())) {
507                     mTaskOrganizers.add(organizer);
508                     mTaskOrganizerStates.put(organizer.asBinder(),
509                             new TaskOrganizerState(organizer, uid));
510                 }
511 
512                 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
513                 mService.mRootWindowContainer.forAllTasks((task) -> {
514                     boolean returnTask = !task.mCreatedByOrganizer;
515                     task.updateTaskOrganizerState(returnTask /* skipTaskAppeared */);
516                     // It is possible for the task to not yet have a surface control, so ensure that
517                     // the update succeeded in setting the organizer for the task before returning
518                     if (task.isOrganized() && returnTask) {
519                         SurfaceControl taskLeash = state.addTaskWithoutCallback(task,
520                                 "TaskOrganizerController.registerTaskOrganizer");
521                         taskInfos.add(new TaskAppearedInfo(task.getTaskInfo(), taskLeash));
522                     }
523                 });
524             };
525             if (mService.getTransitionController().isShellTransitionsEnabled()) {
526                 mService.getTransitionController().mRunningLock.runWhenIdle(1000, withGlobalLock);
527             } else {
528                 synchronized (mGlobalLock) {
529                     withGlobalLock.run();
530                 }
531             }
532             return new ParceledListSlice<>(taskInfos);
533         } finally {
534             Binder.restoreCallingIdentity(origId);
535         }
536     }
537 
538     @Override
unregisterTaskOrganizer(ITaskOrganizer organizer)539     public void unregisterTaskOrganizer(ITaskOrganizer organizer) {
540         enforceTaskPermission("unregisterTaskOrganizer()");
541         final int uid = Binder.getCallingUid();
542         final long origId = Binder.clearCallingIdentity();
543         try {
544             final Runnable withGlobalLock = () -> {
545                 final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
546                 if (state == null) {
547                     return;
548                 }
549                 ProtoLog.v(WM_DEBUG_WINDOW_ORGANIZER, "Unregister task organizer=%s uid=%d",
550                         organizer.asBinder(), uid);
551                 state.unlinkDeath();
552                 state.dispose();
553             };
554             if (mService.getTransitionController().isShellTransitionsEnabled()) {
555                 mService.getTransitionController().mRunningLock.runWhenIdle(1000, withGlobalLock);
556             } else {
557                 synchronized (mGlobalLock) {
558                     withGlobalLock.run();
559                 }
560             }
561         } finally {
562             Binder.restoreCallingIdentity(origId);
563         }
564     }
565 
566     /**
567      * @return the task organizer key for a given windowing mode.
568      */
getTaskOrganizer()569     ITaskOrganizer getTaskOrganizer() {
570         return mTaskOrganizers.peekLast();
571     }
572 
573     // Capture the animation surface control for activity's main window
574     static class StartingWindowAnimationAdaptor implements AnimationAdapter {
575 
576         @Override
getShowWallpaper()577         public boolean getShowWallpaper() {
578             return false;
579         }
580 
581         @Override
startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t, int type, @NonNull SurfaceAnimator.OnAnimationFinishedCallback finishCallback)582         public void startAnimation(SurfaceControl animationLeash, SurfaceControl.Transaction t,
583                 int type, @NonNull SurfaceAnimator.OnAnimationFinishedCallback finishCallback) {
584         }
585 
586         @Override
onAnimationCancelled(SurfaceControl animationLeash)587         public void onAnimationCancelled(SurfaceControl animationLeash) {
588         }
589 
590         @Override
getDurationHint()591         public long getDurationHint() {
592             return 0;
593         }
594 
595         @Override
getStatusBarTransitionsStartTime()596         public long getStatusBarTransitionsStartTime() {
597             return 0;
598         }
599 
600         @Override
dump(PrintWriter pw, String prefix)601         public void dump(PrintWriter pw, String prefix) {
602         }
603 
604         @Override
dumpDebug(ProtoOutputStream proto)605         public void dumpDebug(ProtoOutputStream proto) {
606         }
607     }
608 
applyStartingWindowAnimation(WindowState window)609     static SurfaceControl applyStartingWindowAnimation(WindowState window) {
610         final SurfaceControl.Transaction t = window.getPendingTransaction();
611         final StartingWindowAnimationAdaptor adaptor = new StartingWindowAnimationAdaptor();
612         window.startAnimation(t, adaptor, false, ANIMATION_TYPE_STARTING_REVEAL);
613         final SurfaceControl leash = window.getAnimationLeash();
614         if (leash == null) {
615             Slog.e(TAG, "Cannot start starting window animation, the window " + window
616                     + " was removed");
617             return null;
618         }
619         t.setPosition(leash, window.mSurfacePosition.x, window.mSurfacePosition.y);
620         return leash;
621     }
622 
addStartingWindow(Task task, ActivityRecord activity, int launchTheme, TaskSnapshot taskSnapshot)623     boolean addStartingWindow(Task task, ActivityRecord activity, int launchTheme,
624             TaskSnapshot taskSnapshot) {
625         final Task rootTask = task.getRootTask();
626         if (rootTask == null || activity.mStartingData == null) {
627             return false;
628         }
629         final ITaskOrganizer lastOrganizer = getTaskOrganizer();
630         if (lastOrganizer == null) {
631             return false;
632         }
633         final StartingWindowInfo info = task.getStartingWindowInfo(activity);
634         if (launchTheme != 0) {
635             info.splashScreenThemeResId = launchTheme;
636         }
637         info.taskSnapshot = taskSnapshot;
638         info.appToken = activity.token;
639         // make this happen prior than prepare surface
640         try {
641             lastOrganizer.addStartingWindow(info);
642         } catch (RemoteException e) {
643             Slog.e(TAG, "Exception sending onTaskStart callback", e);
644             return false;
645         }
646         return true;
647     }
648 
removeStartingWindow(Task task, ITaskOrganizer taskOrganizer, boolean prepareAnimation, boolean hasImeSurface)649     void removeStartingWindow(Task task, ITaskOrganizer taskOrganizer, boolean prepareAnimation,
650             boolean hasImeSurface) {
651         final Task rootTask = task.getRootTask();
652         if (rootTask == null) {
653             return;
654         }
655         final ITaskOrganizer lastOrganizer = taskOrganizer != null ? taskOrganizer
656                 : getTaskOrganizer();
657         if (lastOrganizer == null) {
658             return;
659         }
660         final StartingWindowRemovalInfo removalInfo = new StartingWindowRemovalInfo();
661         removalInfo.taskId = task.mTaskId;
662         removalInfo.playRevealAnimation = prepareAnimation
663                 && task.getDisplayContent() != null
664                 && task.getDisplayInfo().state == Display.STATE_ON;
665         final boolean playShiftUpAnimation = !task.inMultiWindowMode();
666         final ActivityRecord topActivity = task.topActivityContainsStartingWindow();
667         if (topActivity != null) {
668             // Set defer remove mode for IME
669             final DisplayContent dc = topActivity.getDisplayContent();
670             if (hasImeSurface) {
671                 if (topActivity.isVisibleRequested() && dc.mInputMethodWindow != null
672                         && dc.isFixedRotationLaunchingApp(topActivity)) {
673                     removalInfo.deferRemoveMode = DEFER_MODE_ROTATION;
674                 } else {
675                     removalInfo.deferRemoveMode = DEFER_MODE_NORMAL;
676                 }
677             }
678 
679             final WindowState mainWindow =
680                     topActivity.findMainWindow(false/* includeStartingApp */);
681             // No app window for this activity, app might be crashed.
682             // Remove starting window immediately without playing reveal animation.
683             if (mainWindow == null || mainWindow.mRemoved) {
684                 removalInfo.playRevealAnimation = false;
685             } else if (removalInfo.playRevealAnimation && playShiftUpAnimation) {
686                 removalInfo.roundedCornerRadius =
687                         topActivity.mAppCompatController.getLetterboxPolicy()
688                                 .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 
handleInterceptBackPressedOnTaskRoot(Task task)1131     public boolean handleInterceptBackPressedOnTaskRoot(Task task) {
1132         if (!shouldInterceptBackPressedOnRootTask(task)) {
1133             return false;
1134         }
1135         final TaskOrganizerPendingEventsQueue pendingEventsQueue =
1136                 mTaskOrganizerStates.get(task.mTaskOrganizer.asBinder())
1137                         .mPendingEventsQueue;
1138         if (pendingEventsQueue == null) {
1139             Slog.w(TAG, "cannot get handle BackPressedOnTaskRoot because organizerState is "
1140                     + "not present");
1141             return false;
1142         }
1143 
1144         PendingTaskEvent pendingVanished =
1145                 pendingEventsQueue.getPendingTaskEvent(task,
1146                         PendingTaskEvent.EVENT_VANISHED);
1147         if (pendingVanished != null) {
1148             // This task will vanish before this callback so just ignore.
1149             return false;
1150         }
1151 
1152         PendingTaskEvent pending = pendingEventsQueue.getPendingTaskEvent(
1153                 task, PendingTaskEvent.EVENT_ROOT_BACK_PRESSED);
1154         if (pending == null) {
1155             pending = new PendingTaskEvent(task, PendingTaskEvent.EVENT_ROOT_BACK_PRESSED);
1156         } else {
1157             // Pending already exist, remove and add for re-ordering.
1158             pendingEventsQueue.removePendingTaskEvent(pending);
1159         }
1160         pendingEventsQueue.addPendingTaskEvent(pending);
1161         mService.mWindowManager.mWindowPlacerLocked.requestTraversal();
1162         return true;
1163     }
1164 
shouldInterceptBackPressedOnRootTask(Task task)1165     boolean shouldInterceptBackPressedOnRootTask(Task task) {
1166         return task != null && task.isOrganized()
1167                 && mInterceptBackPressedOnRootTasks.contains(task.mTaskId);
1168     }
1169 
dump(PrintWriter pw, String prefix)1170     public void dump(PrintWriter pw, String prefix) {
1171         final String innerPrefix = prefix + "  ";
1172         pw.print(prefix); pw.println("TaskOrganizerController:");
1173         final ITaskOrganizer lastOrganizer = mTaskOrganizers.peekLast();
1174         for (ITaskOrganizer organizer : mTaskOrganizers) {
1175             final TaskOrganizerState state = mTaskOrganizerStates.get(organizer.asBinder());
1176             final ArrayList<Task> tasks = state.mOrganizedTasks;
1177             pw.print(innerPrefix + "  ");
1178             pw.print(state.mOrganizer.mTaskOrganizer + " uid=" + state.mUid);
1179             if (lastOrganizer == organizer) {
1180                 pw.print(" (active)");
1181             }
1182             pw.println(':');
1183             for (int k = 0; k < tasks.size(); k++) {
1184                 final Task task = tasks.get(k);
1185                 final int mode = task.getWindowingMode();
1186                 pw.println(innerPrefix + "    ("
1187                         + WindowConfiguration.windowingModeToString(mode) + ") " + task);
1188             }
1189 
1190         }
1191         pw.println();
1192     }
1193 
1194     @VisibleForTesting
getTaskOrganizerState(IBinder taskOrganizer)1195     TaskOrganizerState getTaskOrganizerState(IBinder taskOrganizer) {
1196         return mTaskOrganizerStates.get(taskOrganizer);
1197     }
1198 
1199     @VisibleForTesting
getTaskOrganizerPendingEvents(IBinder taskOrganizer)1200     TaskOrganizerPendingEventsQueue getTaskOrganizerPendingEvents(IBinder taskOrganizer) {
1201         return mTaskOrganizerStates.get(taskOrganizer).mPendingEventsQueue;
1202     }
1203 }
1204