1 /*
2  * Copyright (C) 2020 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.WindowConfiguration.ACTIVITY_TYPE_HOME;
21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
22 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
23 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
24 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
25 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
26 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
27 import static android.content.Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT;
28 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
29 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
30 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
31 
32 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ORIENTATION;
33 import static com.android.server.wm.ActivityRecord.State.RESUMED;
34 import static com.android.server.wm.ActivityTaskManagerService.TAG_ROOT_TASK;
35 import static com.android.server.wm.DisplayContent.alwaysCreateRootTask;
36 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ROOT_TASK;
37 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
38 
39 import android.annotation.ColorInt;
40 import android.annotation.Nullable;
41 import android.app.ActivityOptions;
42 import android.app.WindowConfiguration;
43 import android.content.pm.ActivityInfo;
44 import android.content.pm.ActivityInfo.ScreenOrientation;
45 import android.content.res.Configuration;
46 import android.graphics.Color;
47 import android.os.UserHandle;
48 import android.util.IntArray;
49 import android.util.Slog;
50 import android.view.RemoteAnimationTarget;
51 import android.view.SurfaceControl;
52 import android.view.WindowManager;
53 
54 import com.android.internal.annotations.VisibleForTesting;
55 import com.android.internal.protolog.common.ProtoLog;
56 import com.android.internal.util.ArrayUtils;
57 import com.android.internal.util.function.pooled.PooledLambda;
58 import com.android.internal.util.function.pooled.PooledPredicate;
59 import com.android.server.wm.LaunchParamsController.LaunchParams;
60 
61 import java.io.PrintWriter;
62 import java.util.ArrayList;
63 import java.util.Arrays;
64 import java.util.function.BiFunction;
65 import java.util.function.Consumer;
66 import java.util.function.Function;
67 import java.util.function.Predicate;
68 
69 /**
70  * {@link DisplayArea} that represents a section of a screen that contains app window containers.
71  *
72  * The children can be either {@link Task} or {@link TaskDisplayArea}.
73  */
74 final class TaskDisplayArea extends DisplayArea<WindowContainer> {
75 
76     DisplayContent mDisplayContent;
77 
78     /**
79      * Keeps track of the last set color layer so that it can be reset during surface migrations.
80      */
81     private @ColorInt int mBackgroundColor = 0;
82 
83     /**
84      * This counter is used to make sure we don't prematurely clear the background color in the
85      * case that background color animations are interleaved.
86      * NOTE: The last set color will remain until the counter is reset to 0, which means that an
87      * animation background color may sometime remain after the animation has finished through an
88      * animation with a different background color if an animation starts after and ends before
89      * another where both set different background colors. However, this is not a concern as
90      * currently all task animation backgrounds are the same color.
91      */
92     private int mColorLayerCounter = 0;
93 
94     // Cached reference to some special tasks we tend to get a lot so we don't need to loop
95     // through the list to find them.
96     private Task mRootHomeTask;
97     private Task mRootPinnedTask;
98 
99     private final ArrayList<WindowContainer> mTmpAlwaysOnTopChildren = new ArrayList<>();
100     private final ArrayList<WindowContainer> mTmpNormalChildren = new ArrayList<>();
101     private final ArrayList<WindowContainer> mTmpHomeChildren = new ArrayList<>();
102     private final IntArray mTmpNeedsZBoostIndexes = new IntArray();
103 
104     private ArrayList<Task> mTmpTasks = new ArrayList<>();
105 
106     private ActivityTaskManagerService mAtmService;
107 
108     private RootWindowContainer mRootWindowContainer;
109 
110     // Launch root tasks by activityType then by windowingMode.
111     static private class LaunchRootTaskDef {
112         Task task;
113         int[] windowingModes;
114         int[] activityTypes;
115 
contains(int windowingMode, int activityType)116         boolean contains(int windowingMode, int activityType) {
117             return ArrayUtils.contains(windowingModes, windowingMode)
118                     && ArrayUtils.contains(activityTypes, activityType);
119         }
120     }
121     private final ArrayList<LaunchRootTaskDef> mLaunchRootTasks = new ArrayList<>();
122 
123     /**
124      * A launch root task for activity launching with {@link FLAG_ACTIVITY_LAUNCH_ADJACENT} flag.
125      */
126     @VisibleForTesting
127     Task mLaunchAdjacentFlagRootTask;
128 
129     /**
130      * A focusable root task that is purposely to be positioned at the top. Although the root
131      * task may not have the topmost index, it is used as a preferred candidate to prevent being
132      * unable to resume target root task properly when there are other focusable always-on-top
133      * root tasks.
134      */
135     @VisibleForTesting
136     Task mPreferredTopFocusableRootTask;
137 
138     /**
139      * If this is the same as {@link #getFocusedRootTask} then the activity on the top of the
140      * focused root task has been resumed. If root tasks are changing position this will hold the
141      * old root task until the new root task becomes resumed after which it will be set to
142      * current focused root task.
143      */
144     Task mLastFocusedRootTask;
145     /**
146      * All of the root tasks on this display. Order matters, topmost root task is in front of all
147      * other root tasks, bottommost behind. Accessed directly by ActivityManager package classes.
148      * Any calls changing the list should also call {@link #onRootTaskOrderChanged(Task)}.
149      */
150     private ArrayList<OnRootTaskOrderChangedListener> mRootTaskOrderChangedCallbacks =
151             new ArrayList<>();
152 
153     /**
154      * The task display area is removed from the system and we are just waiting for all activities
155      * on it to be finished before removing this object.
156      */
157     private boolean mRemoved;
158 
159     /**
160      * The id of a leaf task that most recently being moved to front.
161      */
162     private int mLastLeafTaskToFrontId;
163 
164     /**
165      * Whether this TaskDisplayArea was created by a {@link android.window.DisplayAreaOrganizer}.
166      * If {@code true}, this will be removed when the organizer is unregistered.
167      */
168     final boolean mCreatedByOrganizer;
169 
170     /**
171      * True if this TaskDisplayArea can have a home task
172      * {@link WindowConfiguration#ACTIVITY_TYPE_HOME}
173      */
174     private final boolean mCanHostHomeTask;
175 
176     private final Configuration mTempConfiguration = new Configuration();
177 
TaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name, int displayAreaFeature)178     TaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name,
179                     int displayAreaFeature) {
180         this(displayContent, service, name, displayAreaFeature, false /* createdByOrganizer */,
181                 true /* canHostHomeTask */);
182     }
183 
TaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name, int displayAreaFeature, boolean createdByOrganizer)184     TaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name,
185                     int displayAreaFeature, boolean createdByOrganizer) {
186         this(displayContent, service, name, displayAreaFeature, createdByOrganizer,
187                 true /* canHostHomeTask */);
188     }
189 
TaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name, int displayAreaFeature, boolean createdByOrganizer, boolean canHostHomeTask)190     TaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name,
191                     int displayAreaFeature, boolean createdByOrganizer,
192                     boolean canHostHomeTask) {
193         super(service, Type.ANY, name, displayAreaFeature);
194         mDisplayContent = displayContent;
195         mRootWindowContainer = service.mRoot;
196         mAtmService = service.mAtmService;
197         mCreatedByOrganizer = createdByOrganizer;
198         mCanHostHomeTask = canHostHomeTask;
199     }
200 
201     /**
202      * Returns the topmost root task on the display that is compatible with the input windowing mode
203      * and activity type. Null is no compatible root task on the display.
204      */
205     @Nullable
getRootTask(int windowingMode, int activityType)206     Task getRootTask(int windowingMode, int activityType) {
207         if (activityType == ACTIVITY_TYPE_HOME) {
208             return mRootHomeTask;
209         }
210         if (windowingMode == WINDOWING_MODE_PINNED) {
211             return mRootPinnedTask;
212         }
213         return getRootTask(rootTask -> {
214             if (activityType == ACTIVITY_TYPE_UNDEFINED
215                     && windowingMode == rootTask.getWindowingMode()) {
216                 // Passing in undefined type means we want to match the topmost root task with the
217                 // windowing mode.
218                 return true;
219             }
220             return rootTask.isCompatible(windowingMode, activityType);
221         });
222     }
223 
224     @VisibleForTesting
225     Task getTopRootTask() {
226         return getRootTask(alwaysTruePredicate());
227     }
228 
229     @Nullable
230     Task getRootHomeTask() {
231         return mRootHomeTask;
232     }
233 
234     Task getRootPinnedTask() {
235         return mRootPinnedTask;
236     }
237 
238     ArrayList<Task> getVisibleTasks() {
239         final ArrayList<Task> visibleTasks = new ArrayList<>();
240         forAllTasks(task -> {
241             if (task.isLeafTask() && task.isVisible()) {
242                 visibleTasks.add(task);
243             }
244         });
245         return visibleTasks;
246     }
247 
248     void onRootTaskWindowingModeChanged(Task rootTask) {
249         removeRootTaskReferenceIfNeeded(rootTask);
250         addRootTaskReferenceIfNeeded(rootTask);
251         if (rootTask == mRootPinnedTask && getTopRootTask() != rootTask) {
252             // Looks like this root task changed windowing mode to pinned. Move it to the top.
253             positionChildAt(POSITION_TOP, rootTask, false /* includingParents */);
254         }
255     }
256 
257     void addRootTaskReferenceIfNeeded(Task rootTask) {
258         if (rootTask.isActivityTypeHome()) {
259             if (mRootHomeTask != null) {
260                 if (!rootTask.isDescendantOf(mRootHomeTask)) {
261                     throw new IllegalArgumentException("addRootTaskReferenceIfNeeded: root home"
262                             + " task=" + mRootHomeTask + " already exist on display=" + this
263                             + " rootTask=" + rootTask);
264                 }
265             } else {
266                 mRootHomeTask = rootTask;
267             }
268         }
269 
270         if (!rootTask.isRootTask()) {
271             return;
272         }
273         final int windowingMode = rootTask.getWindowingMode();
274         if (windowingMode == WINDOWING_MODE_PINNED) {
275             if (mRootPinnedTask != null) {
276                 throw new IllegalArgumentException(
277                         "addRootTaskReferenceIfNeeded: root pinned task=" + mRootPinnedTask
278                                 + " already exist on display=" + this + " rootTask=" + rootTask);
279             }
280             mRootPinnedTask = rootTask;
281         }
282     }
283 
284     void removeRootTaskReferenceIfNeeded(Task rootTask) {
285         if (rootTask == mRootHomeTask) {
286             mRootHomeTask = null;
287         } else if (rootTask == mRootPinnedTask) {
288             mRootPinnedTask = null;
289         }
290     }
291 
292     @Override
293     void setInitialSurfaceControlProperties(SurfaceControl.Builder b) {
294         // We want an effect layer instead of the default container layer so that we can set a
295         // background color on it for task animations.
296         b.setEffectLayer();
297         super.setInitialSurfaceControlProperties(b);
298     }
299 
300     @Override
301     void addChild(WindowContainer child, int position) {
302         if (child.asTaskDisplayArea() != null) {
303             if (DEBUG_ROOT_TASK) {
304                 Slog.d(TAG_WM, "Set TaskDisplayArea=" + child + " on taskDisplayArea=" + this);
305             }
306             super.addChild(child, position);
307         } else if (child.asTask() != null) {
308             addChildTask(child.asTask(), position);
309         } else {
310             throw new IllegalArgumentException(
311                     "TaskDisplayArea can only add Task and TaskDisplayArea, but found "
312                             + child);
313         }
314     }
315 
316     private void addChildTask(Task task, int position) {
317         if (DEBUG_ROOT_TASK) Slog.d(TAG_WM, "Set task=" + task + " on taskDisplayArea=" + this);
318 
319         addRootTaskReferenceIfNeeded(task);
320         position = findPositionForRootTask(position, task, true /* adding */);
321 
322         super.addChild(task, position);
323         if (mPreferredTopFocusableRootTask != null
324                 && task.isFocusable()
325                 && mPreferredTopFocusableRootTask.compareTo(task) < 0) {
326             // Clear preferred top because the adding focusable task has a higher z-order.
327             mPreferredTopFocusableRootTask = null;
328         }
329 
330         // Update the top resumed activity because the preferred top focusable task may be changed.
331         mAtmService.mTaskSupervisor.updateTopResumedActivityIfNeeded("addChildTask");
332 
333         mAtmService.updateSleepIfNeededLocked();
334         onRootTaskOrderChanged(task);
335     }
336 
337     @Override
338     protected void removeChild(WindowContainer child) {
339         if (child.asTaskDisplayArea() != null) {
340             super.removeChild(child);
341         } else if (child.asTask() != null) {
342             removeChildTask(child.asTask());
343         } else {
344             throw new IllegalArgumentException(
345                     "TaskDisplayArea can only remove Task and TaskDisplayArea, but found "
346                             + child);
347         }
348     }
349 
350     private void removeChildTask(Task task) {
351         super.removeChild(task);
352         onRootTaskRemoved(task);
353         mAtmService.updateSleepIfNeededLocked();
354         removeRootTaskReferenceIfNeeded(task);
355     }
356 
357     @Override
358     boolean isOnTop() {
359         // Considered always on top
360         return true;
361     }
362 
363     @Override
364     void positionChildAt(int position, WindowContainer child, boolean includingParents) {
365         if (child.asTaskDisplayArea() != null) {
366             super.positionChildAt(position, child, includingParents);
367         } else if (child.asTask() != null) {
368             positionChildTaskAt(position, child.asTask(), includingParents);
369         } else {
370             throw new IllegalArgumentException(
371                     "TaskDisplayArea can only position Task and TaskDisplayArea, but found "
372                             + child);
373         }
374     }
375 
376     private void positionChildTaskAt(int position, Task child, boolean includingParents) {
377         final boolean moveToTop = position >= getChildCount() - 1;
378         final boolean moveToBottom = position <= 0;
379 
380         final int oldPosition = mChildren.indexOf(child);
381         if (child.isAlwaysOnTop() && !moveToTop) {
382             // This root task is always-on-top, override the default behavior.
383             Slog.w(TAG_WM, "Ignoring move of always-on-top root task=" + this + " to bottom");
384 
385             // Moving to its current position, as we must call super but we don't want to
386             // perform any meaningful action.
387             super.positionChildAt(oldPosition, child, false /* includingParents */);
388             return;
389         }
390         // We don't allow untrusted display to top when root task moves to top,
391         // until user tapping this display to change display position as top intentionally.
392         //
393         // Displays with {@code mDontMoveToTop} property set to {@code true} won't be
394         // allowed to top neither.
395         if ((!mDisplayContent.isTrusted() || mDisplayContent.mDontMoveToTop)
396                 && !getParent().isOnTop()) {
397             includingParents = false;
398         }
399         final int targetPosition = findPositionForRootTask(position, child, false /* adding */);
400         super.positionChildAt(targetPosition, child, false /* includingParents */);
401 
402         if (includingParents && getParent() != null && (moveToTop || moveToBottom)) {
403             getParent().positionChildAt(moveToTop ? POSITION_TOP : POSITION_BOTTOM,
404                     this /* child */, true /* includingParents */);
405         }
406 
407         child.updateTaskMovement(moveToTop, moveToBottom, targetPosition);
408 
409         // The insert position may be adjusted to non-top when there is always-on-top root task.
410         // Since the original position is preferred to be top, the root task should have higher
411         // priority when we are looking for top focusable root task. The condition {@code
412         // wasContained} restricts the preferred root task is set only when moving an existing
413         // root task to top instead of adding a new root task that may be too early (e.g. in the
414         // middle of launching or reparenting).
415         final boolean isTopFocusableTask = moveToTop && child != mRootPinnedTask
416                 && child.isTopActivityFocusable();
417         if (isTopFocusableTask) {
418             mPreferredTopFocusableRootTask =
419                     child.shouldBeVisible(null /* starting */) ? child : null;
420         } else if (mPreferredTopFocusableRootTask == child) {
421             mPreferredTopFocusableRootTask = null;
422         }
423 
424         // Update the top resumed activity because the preferred top focusable task may be changed.
425         mAtmService.mTaskSupervisor.updateTopResumedActivityIfNeeded("positionChildTaskAt");
426 
427         if (mChildren.indexOf(child) != oldPosition) {
428             onRootTaskOrderChanged(child);
429         }
430     }
431 
432     void onLeafTaskRemoved(int taskId) {
433         if (mLastLeafTaskToFrontId == taskId) {
434             mLastLeafTaskToFrontId = INVALID_TASK_ID;
435         }
436     }
437 
438     void onLeafTaskMoved(Task t, boolean toTop, boolean toBottom) {
439         if (toBottom) {
440             mAtmService.getTaskChangeNotificationController().notifyTaskMovedToBack(
441                     t.getTaskInfo());
442         }
443 
444         if (!toTop) {
445             if (t.mTaskId == mLastLeafTaskToFrontId) {
446                 mLastLeafTaskToFrontId = INVALID_TASK_ID;
447 
448                 // If the previous front-most task is moved to the back, then notify of the new
449                 // front-most task.
450                 final ActivityRecord topMost = getTopMostActivity();
451                 if (topMost != null) {
452                     mAtmService.getTaskChangeNotificationController().notifyTaskMovedToFront(
453                             topMost.getTask().getTaskInfo());
454                 }
455             }
456             return;
457         }
458         if (t.mTaskId == mLastLeafTaskToFrontId || t.topRunningActivityLocked() == null) {
459             return;
460         }
461 
462         mLastLeafTaskToFrontId = t.mTaskId;
463         EventLogTags.writeWmTaskToFront(t.mUserId, t.mTaskId, getDisplayId());
464         // Notifying only when a leaf task moved to front. Or the listeners would be notified
465         // couple times from the leaf task all the way up to the root task.
466         mAtmService.getTaskChangeNotificationController().notifyTaskMovedToFront(t.getTaskInfo());
467     }
468 
469     @Override
470     void onChildPositionChanged(WindowContainer child) {
471         super.onChildPositionChanged(child);
472         mRootWindowContainer.invalidateTaskLayers();
473     }
474 
475     @Override
476     boolean forAllTaskDisplayAreas(Predicate<TaskDisplayArea> callback,
477             boolean traverseTopToBottom) {
478         // Apply the callback to all TDAs at or below this container. If the callback returns true,
479         // stop early.
480         if (traverseTopToBottom) {
481             // When it is top to bottom, run on child TDA first as they are on top of the parent.
482             return super.forAllTaskDisplayAreas(callback, traverseTopToBottom)
483                     || callback.test(this);
484         }
485         return callback.test(this) || super.forAllTaskDisplayAreas(callback, traverseTopToBottom);
486     }
487 
488     @Override
489     void forAllTaskDisplayAreas(Consumer<TaskDisplayArea> callback, boolean traverseTopToBottom) {
490         if (traverseTopToBottom) {
491             super.forAllTaskDisplayAreas(callback, traverseTopToBottom);
492             callback.accept(this);
493         } else {
494             callback.accept(this);
495             super.forAllTaskDisplayAreas(callback, traverseTopToBottom);
496         }
497     }
498 
499     @Nullable
500     @Override
501     <R> R reduceOnAllTaskDisplayAreas(BiFunction<TaskDisplayArea, R, R> accumulator,
502             @Nullable R initValue, boolean traverseTopToBottom) {
503         if (traverseTopToBottom) {
504             final R result =
505                     super.reduceOnAllTaskDisplayAreas(accumulator, initValue, traverseTopToBottom);
506             return accumulator.apply(this, result);
507         } else {
508             final R result = accumulator.apply(this, initValue);
509             return super.reduceOnAllTaskDisplayAreas(accumulator, result, traverseTopToBottom);
510 
511         }
512     }
513 
514     @Nullable
515     @Override
516     <R> R getItemFromTaskDisplayAreas(Function<TaskDisplayArea, R> callback,
517             boolean traverseTopToBottom) {
518         if (traverseTopToBottom) {
519             final R item = super.getItemFromTaskDisplayAreas(callback, traverseTopToBottom);
520             return item != null ? item : callback.apply(this);
521         } else {
522             final R item = callback.apply(this);
523             return item != null
524                     ? item
525                     : super.getItemFromTaskDisplayAreas(callback, traverseTopToBottom);
526         }
527     }
528 
529     /**
530      * Assigns a priority number to root task types. This priority defines an order between the
531      * types of root task that are added to the task display area.
532      *
533      * Higher priority number indicates that the root task should have a higher z-order.
534      *
535      * For child {@link TaskDisplayArea}, it will be the priority of its top child.
536      *
537      * @return the priority of the root task
538      */
539     private int getPriority(WindowContainer child) {
540         final TaskDisplayArea tda = child.asTaskDisplayArea();
541         if (tda != null) {
542             // Use the top child priority as the TaskDisplayArea priority.
543             return tda.getPriority(tda.getTopChild());
544         }
545         final Task rootTask = child.asTask();
546         if (mWmService.mAssistantOnTopOfDream && rootTask.isActivityTypeAssistant()) return 4;
547         if (rootTask.isActivityTypeDream()) return 3;
548         if (rootTask.inPinnedWindowingMode()) return 2;
549         if (rootTask.isAlwaysOnTop()) return 1;
550         return 0;
551     }
552 
553     private int findMinPositionForRootTask(Task rootTask) {
554         int minPosition = POSITION_BOTTOM;
555         for (int i = 0; i < mChildren.size(); ++i) {
556             if (getPriority(mChildren.get(i)) < getPriority(rootTask)) {
557                 minPosition = i;
558             } else {
559                 break;
560             }
561         }
562 
563         if (rootTask.isAlwaysOnTop()) {
564             // Since a root task could be repositioned while still being one of the children, we
565             // check if this always-on-top root task already exists and if so, set the minPosition
566             // to its previous position.
567             // Use mChildren.indexOf instead of getTaskIndexOf because we need to place the rootTask
568             // as a direct child.
569             final int currentIndex = mChildren.indexOf(rootTask);
570             if (currentIndex > minPosition) {
571                 minPosition = currentIndex;
572             }
573         }
574         return minPosition;
575     }
576 
577     private int findMaxPositionForRootTask(Task rootTask) {
578         for (int i = mChildren.size() - 1; i >= 0; --i) {
579             final WindowContainer curr = mChildren.get(i);
580             // Since a root task could be repositioned while still being one of the children, we
581             // check if 'curr' is the same root task and skip it if so
582             final boolean sameRootTask = curr == rootTask;
583             if (getPriority(curr) <= getPriority(rootTask) && !sameRootTask) {
584                 return i;
585             }
586         }
587         return 0;
588     }
589 
590     /**
591      * When root task is added or repositioned, find a proper position for it.
592      *
593      * The order is defined as:
594      * - Dream is on top of everything
595      * - PiP is directly below the Dream
596      * - always-on-top root tasks are directly below PiP; new always-on-top root tasks are added
597      * above existing ones
598      * - other non-always-on-top root tasks come directly below always-on-top root tasks; new
599      * non-always-on-top root tasks are added directly below always-on-top root tasks and above
600      * existing non-always-on-top root tasks
601      * - if {@link #mAssistantOnTopOfDream} is enabled, then Assistant is on top of everything
602      * (including the Dream); otherwise, it is a normal non-always-on-top root task
603      *
604      * @param requestedPosition Position requested by caller.
605      * @param rootTask          Root task to be added or positioned.
606      * @param adding            Flag indicates whether we're adding a new root task or positioning
607      *                          an existing.
608      * @return The proper position for the root task.
609      */
610     private int findPositionForRootTask(int requestedPosition, Task rootTask, boolean adding) {
611         // The max possible position we can insert the root task at.
612         int maxPosition = findMaxPositionForRootTask(rootTask);
613         // The min possible position we can insert the root task at.
614         int minPosition = findMinPositionForRootTask(rootTask);
615 
616         // Cap the requested position to something reasonable for the previous position check
617         // below.
618         if (requestedPosition == POSITION_TOP) {
619             requestedPosition = mChildren.size();
620         } else if (requestedPosition == POSITION_BOTTOM) {
621             requestedPosition = 0;
622         }
623 
624         int targetPosition = requestedPosition;
625         targetPosition = Math.min(targetPosition, maxPosition);
626         targetPosition = Math.max(targetPosition, minPosition);
627 
628         int prevPosition = mChildren.indexOf(rootTask);
629         // The positions we calculated above (maxPosition, minPosition) do not take into
630         // consideration the following edge cases.
631         // 1) We need to adjust the position depending on the value "adding".
632         // 2) When we are moving a root task to another position, we also need to adjust the
633         //    position depending on whether the root task is moving to a higher or lower position.
634         if ((targetPosition != requestedPosition) && (adding || targetPosition < prevPosition)) {
635             targetPosition++;
636         }
637 
638         return targetPosition;
639     }
640 
641     @Override
642     @ScreenOrientation
643     int getOrientation(@ScreenOrientation int candidate) {
644         final int orientation = super.getOrientation(candidate);
645         if (!canSpecifyOrientation(orientation)) {
646             mLastOrientationSource = null;
647             // We only respect orientation of the focused TDA, which can be a child of this TDA.
648             return reduceOnAllTaskDisplayAreas((taskDisplayArea, taskOrientation) -> {
649                 if (taskDisplayArea == this || taskOrientation != SCREEN_ORIENTATION_UNSET) {
650                     return taskOrientation;
651                 }
652                 return taskDisplayArea.getOrientation(candidate);
653             }, SCREEN_ORIENTATION_UNSET);
654         }
655 
656         if (orientation != SCREEN_ORIENTATION_UNSET
657                 && orientation != SCREEN_ORIENTATION_BEHIND) {
658             ProtoLog.v(WM_DEBUG_ORIENTATION,
659                     "App is requesting an orientation, return %d for display id=%d",
660                     orientation, mDisplayContent.mDisplayId);
661             return orientation;
662         }
663 
664         ProtoLog.v(WM_DEBUG_ORIENTATION,
665                 "No app is requesting an orientation, return %d for display id=%d",
666                 mDisplayContent.getLastOrientation(), mDisplayContent.mDisplayId);
667         // The next app has not been requested to be visible, so we keep the current orientation
668         // to prevent freezing/unfreezing the display too early.
669         return mDisplayContent.getLastOrientation();
670     }
671 
672     @Override
673     void assignChildLayers(SurfaceControl.Transaction t) {
674         assignRootTaskOrdering(t);
675 
676         for (int i = 0; i < mChildren.size(); i++) {
677             mChildren.get(i).assignChildLayers(t);
678         }
679     }
680 
681     void assignRootTaskOrdering(SurfaceControl.Transaction t) {
682         if (getParent() == null) {
683             return;
684         }
685         mTmpAlwaysOnTopChildren.clear();
686         mTmpHomeChildren.clear();
687         mTmpNormalChildren.clear();
688         for (int i = 0; i < mChildren.size(); ++i) {
689             final WindowContainer child = mChildren.get(i);
690             final TaskDisplayArea childTda = child.asTaskDisplayArea();
691             if (childTda != null) {
692                 final Task childTdaTopRootTask = childTda.getTopRootTask();
693                 if (childTdaTopRootTask == null) {
694                     mTmpNormalChildren.add(childTda);
695                 } else if (childTdaTopRootTask.isAlwaysOnTop()) {
696                     mTmpAlwaysOnTopChildren.add(childTda);
697                 } else if (childTdaTopRootTask.isActivityTypeHome()) {
698                     mTmpHomeChildren.add(childTda);
699                 } else {
700                     mTmpNormalChildren.add(childTda);
701                 }
702                 continue;
703             }
704 
705             final Task childTask = child.asTask();
706             if (childTask.isAlwaysOnTop()) {
707                 mTmpAlwaysOnTopChildren.add(childTask);
708             } else if (childTask.isActivityTypeHome()) {
709                 mTmpHomeChildren.add(childTask);
710             } else {
711                 mTmpNormalChildren.add(childTask);
712             }
713         }
714 
715         int layer = 0;
716         // Place root home tasks to the bottom.
717         layer = adjustRootTaskLayer(t, mTmpHomeChildren, layer);
718         layer = adjustRootTaskLayer(t, mTmpNormalChildren, layer);
719         adjustRootTaskLayer(t, mTmpAlwaysOnTopChildren, layer);
720     }
721 
722     /**
723      * Adjusts the layer of the root task which belongs to the same group.
724      * Note that there are three root task groups: home rootTasks, always on top rootTasks, and
725      * normal rootTasks.
726      *
727      * @param startLayer   The beginning layer of this group of rootTasks.
728      * @return The adjusted layer value.
729      */
730     private int adjustRootTaskLayer(SurfaceControl.Transaction t,
731             ArrayList<WindowContainer> children, int startLayer) {
732         mTmpNeedsZBoostIndexes.clear();
733         final int childCount = children.size();
734         boolean hasAdjacentTask = false;
735         for (int i = 0; i < childCount; i++) {
736             final WindowContainer child = children.get(i);
737             final TaskDisplayArea childTda = child.asTaskDisplayArea();
738             final boolean childNeedsZBoost = childTda != null
739                     ? childTda.childrenNeedZBoost()
740                     : child.needsZBoost();
741 
742             if (childNeedsZBoost) {
743                 mTmpNeedsZBoostIndexes.add(i);
744                 continue;
745             }
746 
747             child.assignLayer(t, startLayer++);
748         }
749 
750         final int zBoostSize = mTmpNeedsZBoostIndexes.size();
751         for (int i = 0; i < zBoostSize; i++) {
752             final WindowContainer child = children.get(mTmpNeedsZBoostIndexes.get(i));
753             child.assignLayer(t, startLayer++);
754         }
755         return startLayer;
756     }
757 
758     private boolean childrenNeedZBoost() {
759         final boolean[] needsZBoost = new boolean[1];
760         forAllRootTasks(task -> {
761             needsZBoost[0] |= task.needsZBoost();
762         });
763         return needsZBoost[0];
764     }
765 
766     @Override
767     RemoteAnimationTarget createRemoteAnimationTarget(
768             RemoteAnimationController.RemoteAnimationRecord record) {
769         final ActivityRecord activity = getTopMostActivity();
770         return activity != null ? activity.createRemoteAnimationTarget(record) : null;
771     }
772 
773     void setBackgroundColor(@ColorInt int colorInt) {
774         setBackgroundColor(colorInt, false /* restore */);
775     }
776 
777     void setBackgroundColor(@ColorInt int colorInt, boolean restore) {
778         mBackgroundColor = colorInt;
779         Color color = Color.valueOf(colorInt);
780 
781         // We don't want to increment the mColorLayerCounter if we are restoring the background
782         // color after a surface migration because in that case the mColorLayerCounter already
783         // accounts for setting that background color.
784         if (!restore) {
785             mColorLayerCounter++;
786         }
787 
788         // Only apply the background color if the TDA is actually attached and has a valid surface
789         // to set the background color on. We still want to keep track of the background color state
790         // even if we are not showing it for when/if the TDA is reattached and gets a valid surface
791         if (mSurfaceControl != null) {
792             getPendingTransaction()
793                     .setColor(mSurfaceControl,
794                             new float[]{color.red(), color.green(), color.blue()});
795             scheduleAnimation();
796         }
797     }
798 
799     void clearBackgroundColor() {
800         mColorLayerCounter--;
801 
802         // Only clear the color layer if we have received the same amounts of clear as set
803         // requests and TDA has a non null surface control (i.e. is attached)
804         if (mColorLayerCounter == 0 && mSurfaceControl != null) {
805             getPendingTransaction().unsetColor(mSurfaceControl);
806             scheduleAnimation();
807         }
808     }
809 
810     @Override
811     void migrateToNewSurfaceControl(SurfaceControl.Transaction t) {
812         super.migrateToNewSurfaceControl(t);
813 
814         if (mColorLayerCounter > 0) {
815             setBackgroundColor(mBackgroundColor, true /* restore */);
816         }
817 
818         reassignLayer(t);
819         scheduleAnimation();
820     }
821 
822     void onRootTaskRemoved(Task rootTask) {
823         if (ActivityTaskManagerDebugConfig.DEBUG_ROOT_TASK) {
824             Slog.v(TAG_ROOT_TASK, "onRootTaskRemoved: detaching " + rootTask + " from displayId="
825                     + mDisplayContent.mDisplayId);
826         }
827         if (mPreferredTopFocusableRootTask == rootTask) {
828             mPreferredTopFocusableRootTask = null;
829         }
830         if (mLaunchAdjacentFlagRootTask == rootTask) {
831             mLaunchAdjacentFlagRootTask = null;
832         }
833         mDisplayContent.releaseSelfIfNeeded();
834         onRootTaskOrderChanged(rootTask);
835     }
836 
837     /**
838      * Moves/reparents `task` to the back of whatever container the root home task is in. This is
839      * for when we just want to move a task to "the back" vs. a specific place. The primary use-case
840      * is to make sure that moved-to-back apps go into secondary split when in split-screen mode.
841      */
842     void positionTaskBehindHome(Task task) {
843         final Task home = getOrCreateRootHomeTask();
844         final WindowContainer homeParent = home.getParent();
845         final Task homeParentTask = homeParent != null ? homeParent.asTask() : null;
846         if (homeParentTask == null) {
847             // reparent throws if parent didn't change...
848             if (task.getParent() == this) {
849                 positionChildAt(POSITION_BOTTOM, task, false /*includingParents*/);
850             } else {
851                 task.reparent(this, false /* onTop */);
852             }
853         } else if (homeParentTask == task.getParent()) {
854             // Apparently reparent early-outs if same root task, so we have to explicitly reorder.
855             homeParentTask.positionChildAtBottom(task);
856         } else {
857             task.reparent(homeParentTask, false /* toTop */,
858                     Task.REPARENT_LEAVE_ROOT_TASK_IN_PLACE, false /* animate */,
859                     false /* deferResume */, "positionTaskBehindHome");
860         }
861     }
862 
863     /**
864      * Returns an existing root task compatible with the windowing mode and activity type or
865      * creates one if a compatible root task doesn't exist.
866      *
867      * @see #getOrCreateRootTask(int, int, boolean, Task, Task, ActivityOptions, int)
868      */
869     Task getOrCreateRootTask(int windowingMode, int activityType, boolean onTop) {
870         return getOrCreateRootTask(windowingMode, activityType, onTop, null /* candidateTask */,
871                 null /* sourceTask */, null /* options */, 0 /* intent */);
872     }
873 
874     /**
875      * When two level tasks are required for given windowing mode and activity type, returns an
876      * existing compatible root task or creates a new one.
877      * For one level task, the candidate task would be reused to also be the root task or create
878      * a new root task if no candidate task.
879      *
880      * @param windowingMode The windowing mode the root task should be created in.
881      * @param activityType  The activityType the root task should be created in.
882      * @param onTop         If true the root task will be created at the top of the display,
883      *                      else at the bottom.
884      * @param candidateTask The possible task the activity might be launched in. Can be null.
885      * @param sourceTask    The task requesting to start activity. Used to determine which of the
886      *                      adjacent roots should be launch root of the new task. Can be null.
887      * @param options       The activity options used to the launch. Can be null.
888      * @param launchFlags   The launch flags for this launch.
889      * @return The root task to use for the launch.
890      * @see #getRootTask(int, int)
891      */
892     Task getOrCreateRootTask(int windowingMode, int activityType, boolean onTop,
893             @Nullable Task candidateTask, @Nullable Task sourceTask,
894             @Nullable ActivityOptions options, int launchFlags) {
895         final int resolvedWindowingMode =
896                 windowingMode == WINDOWING_MODE_UNDEFINED ? getWindowingMode() : windowingMode;
897         // Need to pass in a determined windowing mode to see if a new root task should be created,
898         // so use its parent's windowing mode if it is undefined.
899         if (!alwaysCreateRootTask(resolvedWindowingMode, activityType)) {
900             Task rootTask = getRootTask(resolvedWindowingMode, activityType);
901             if (rootTask != null) {
902                 return rootTask;
903             }
904         } else if (candidateTask != null) {
905             final int position = onTop ? POSITION_TOP : POSITION_BOTTOM;
906             final Task launchParentTask = getLaunchRootTask(resolvedWindowingMode, activityType,
907                     options, sourceTask, launchFlags, candidateTask);
908             if (launchParentTask != null) {
909                 if (candidateTask.getParent() == null) {
910                     launchParentTask.addChild(candidateTask, position);
911                 } else if (candidateTask.getParent() != launchParentTask) {
912                     candidateTask.reparent(launchParentTask, position);
913                 }
914             } else if (candidateTask.getDisplayArea() != this
915                     || candidateTask.getRootTask().mReparentLeafTaskIfRelaunch) {
916                 if (candidateTask.getParent() == null) {
917                     addChild(candidateTask, position);
918                 } else {
919                     candidateTask.reparent(this, onTop);
920                 }
921             }
922             // Update windowing mode if necessary, e.g. launch into a different windowing mode.
923             if (windowingMode != WINDOWING_MODE_UNDEFINED && candidateTask.isRootTask()
924                     && candidateTask.getWindowingMode() != windowingMode) {
925                 candidateTask.mTransitionController.collect(candidateTask);
926                 candidateTask.setWindowingMode(windowingMode);
927             }
928             return candidateTask.getRootTask();
929         }
930         return new Task.Builder(mAtmService)
931                 .setWindowingMode(windowingMode)
932                 .setActivityType(activityType)
933                 .setOnTop(onTop)
934                 .setParent(this)
935                 .setSourceTask(sourceTask)
936                 .setActivityOptions(options)
937                 .setLaunchFlags(launchFlags)
938                 .build();
939     }
940 
941     /**
942      * Returns an existing root task compatible with the input params or creates one
943      * if a compatible root task doesn't exist.
944      *
945      * @see #getOrCreateRootTask(int, int, boolean)
946      */
947     Task getOrCreateRootTask(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
948             @Nullable Task candidateTask, @Nullable Task sourceTask,
949             @Nullable LaunchParams launchParams, int launchFlags, int activityType, boolean onTop) {
950         int windowingMode = WINDOWING_MODE_UNDEFINED;
951         if (launchParams != null) {
952             // If launchParams isn't null, windowing mode is already resolved.
953             windowingMode = launchParams.mWindowingMode;
954         } else if (options != null) {
955             // If launchParams is null and options isn't let's use the windowing mode in the
956             // options.
957             windowingMode = options.getLaunchWindowingMode();
958         }
959         // Validate that our desired windowingMode will work under the current conditions.
960         // UNDEFINED windowing mode is a valid result and means that the new root task will inherit
961         // it's display's windowing mode.
962         windowingMode = validateWindowingMode(windowingMode, r, candidateTask);
963         return getOrCreateRootTask(windowingMode, activityType, onTop, candidateTask, sourceTask,
964                 options, launchFlags);
965     }
966 
967     @VisibleForTesting
968     int getNextRootTaskId() {
969         return mAtmService.mTaskSupervisor.getNextTaskIdForUser();
970     }
971 
972     Task createRootTask(int windowingMode, int activityType, boolean onTop) {
973         return createRootTask(windowingMode, activityType, onTop, null /* activityOptions */);
974     }
975 
976     /**
977      * A convinenit method of creating a root task by providing windowing mode and activity type
978      * on this display.
979      *
980      * @param windowingMode      The windowing mode the root task should be created in. If
981      *                           {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the
982      *                           root task will inherit its parent's windowing mode.
983      * @param activityType       The activityType the root task should be created in. If
984      *                           {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the
985      *                           root task will be created in
986      *                           {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
987      * @param onTop              If true the root task will be created at the top of the display,
988      *                           else at the bottom.
989      * @param opts               The activity options.
990      * @return The newly created root task.
991      */
992     Task createRootTask(int windowingMode, int activityType, boolean onTop, ActivityOptions opts) {
993         return new Task.Builder(mAtmService)
994                 .setWindowingMode(windowingMode)
995                 .setActivityType(activityType)
996                 .setParent(this)
997                 .setOnTop(onTop)
998                 .setActivityOptions(opts)
999                 .build();
1000     }
1001 
1002     // TODO: Also clear when task is removed from system?
1003     void setLaunchRootTask(Task rootTask, int[] windowingModes, int[] activityTypes) {
1004         if (!rootTask.mCreatedByOrganizer) {
1005             throw new IllegalArgumentException(
1006                     "Can't set not mCreatedByOrganizer as launch root tr=" + rootTask);
1007         }
1008 
1009         LaunchRootTaskDef def = getLaunchRootTaskDef(rootTask);
1010         if (def != null) {
1011             // Remove so we add to the end of the list.
1012             mLaunchRootTasks.remove(def);
1013         } else {
1014             def = new LaunchRootTaskDef();
1015             def.task = rootTask;
1016         }
1017 
1018         def.activityTypes = activityTypes;
1019         def.windowingModes = windowingModes;
1020         if (!ArrayUtils.isEmpty(windowingModes) || !ArrayUtils.isEmpty(activityTypes)) {
1021             mLaunchRootTasks.add(def);
1022         }
1023     }
1024 
1025     void removeLaunchRootTask(Task rootTask) {
1026         LaunchRootTaskDef def = getLaunchRootTaskDef(rootTask);
1027         if (def != null) {
1028             mLaunchRootTasks.remove(def);
1029         }
1030     }
1031 
1032     void setLaunchAdjacentFlagRootTask(@Nullable Task adjacentFlagRootTask) {
1033         if (adjacentFlagRootTask != null) {
1034             if (!adjacentFlagRootTask.mCreatedByOrganizer) {
1035                 throw new IllegalArgumentException(
1036                         "Can't set not mCreatedByOrganizer as launch adjacent flag root tr="
1037                                 + adjacentFlagRootTask);
1038             }
1039 
1040             if (adjacentFlagRootTask.getAdjacentTaskFragment() == null) {
1041                 throw new UnsupportedOperationException(
1042                         "Can't set non-adjacent root as launch adjacent flag root tr="
1043                                 + adjacentFlagRootTask);
1044             }
1045         }
1046 
1047         mLaunchAdjacentFlagRootTask = adjacentFlagRootTask;
1048     }
1049 
1050     private @Nullable LaunchRootTaskDef getLaunchRootTaskDef(Task rootTask) {
1051         LaunchRootTaskDef def = null;
1052         for (int i = mLaunchRootTasks.size() - 1; i >= 0; --i) {
1053             if (mLaunchRootTasks.get(i).task.mTaskId != rootTask.mTaskId) continue;
1054             def = mLaunchRootTasks.get(i);
1055             break;
1056         }
1057         return def;
1058     }
1059 
1060     @Nullable
1061     Task getLaunchRootTask(int windowingMode, int activityType, @Nullable ActivityOptions options,
1062             @Nullable Task sourceTask, int launchFlags) {
1063         return getLaunchRootTask(windowingMode, activityType, options, sourceTask, launchFlags,
1064                 null /* candidateTask */);
1065     }
1066 
1067     @Nullable
1068     Task getLaunchRootTask(int windowingMode, int activityType, @Nullable ActivityOptions options,
1069             @Nullable Task sourceTask, int launchFlags, @Nullable Task candidateTask) {
1070         // Try to use the launch root task in options if available.
1071         if (options != null) {
1072             final Task launchRootTask = Task.fromWindowContainerToken(options.getLaunchRootTask());
1073             // We only allow this for created by organizer tasks.
1074             if (launchRootTask != null && launchRootTask.mCreatedByOrganizer) {
1075                 return launchRootTask;
1076             }
1077         }
1078 
1079         // Use launch-adjacent-flag-root if launching with launch-adjacent flag.
1080         if ((launchFlags & FLAG_ACTIVITY_LAUNCH_ADJACENT) != 0
1081                 && mLaunchAdjacentFlagRootTask != null) {
1082             if (sourceTask != null && sourceTask == candidateTask) {
1083                 // Do nothing when task that is getting opened is same as the source.
1084             } else if (sourceTask != null
1085                     && mLaunchAdjacentFlagRootTask.getAdjacentTask() != null
1086                     && (sourceTask == mLaunchAdjacentFlagRootTask
1087                     || sourceTask.isDescendantOf(mLaunchAdjacentFlagRootTask))) {
1088                 // If the adjacent launch is coming from the same root, launch to
1089                 // adjacent root instead.
1090                 return mLaunchAdjacentFlagRootTask.getAdjacentTask();
1091             } else {
1092                 return mLaunchAdjacentFlagRootTask;
1093             }
1094         }
1095 
1096         for (int i = mLaunchRootTasks.size() - 1; i >= 0; --i) {
1097             if (mLaunchRootTasks.get(i).contains(windowingMode, activityType)) {
1098                 final Task launchRootTask = mLaunchRootTasks.get(i).task;
1099                 final Task adjacentRootTask = launchRootTask != null
1100                         ? launchRootTask.getAdjacentTask() : null;
1101                 if (sourceTask != null && adjacentRootTask != null
1102                         && (sourceTask == adjacentRootTask
1103                         || sourceTask.isDescendantOf(adjacentRootTask))) {
1104                     return adjacentRootTask;
1105                 } else {
1106                     return launchRootTask;
1107                 }
1108             }
1109         }
1110 
1111         // If a task is launching from a created-by-organizer task, it should be launched into the
1112         // same created-by-organizer task as well. Unless, the candidate task is already positioned
1113         // in the another adjacent task.
1114         if (sourceTask != null && (candidateTask == null
1115                 // A pinned task relaunching should be handled by its task organizer. Skip fallback
1116                 // launch target of a pinned task from source task.
1117                 || candidateTask.getWindowingMode() != WINDOWING_MODE_PINNED)) {
1118             final Task adjacentTarget = sourceTask.getAdjacentTask();
1119             if (adjacentTarget != null) {
1120                 if (candidateTask != null
1121                         && (candidateTask == adjacentTarget
1122                         || candidateTask.isDescendantOf(adjacentTarget))) {
1123                     return adjacentTarget;
1124                 }
1125                 return sourceTask.getCreatedByOrganizerTask();
1126             }
1127         }
1128 
1129         return null;
1130     }
1131 
1132     /**
1133      * Get the preferred focusable root task in priority. If the preferred root task does not exist,
1134      * find a focusable and visible root task from the top of root tasks in this display.
1135      */
1136     Task getFocusedRootTask() {
1137         if (mPreferredTopFocusableRootTask != null) {
1138             return mPreferredTopFocusableRootTask;
1139         }
1140 
1141         for (int i = mChildren.size() - 1; i >= 0; --i) {
1142             final WindowContainer child = mChildren.get(i);
1143             if (child.asTaskDisplayArea() != null) {
1144                 final Task rootTask = child.asTaskDisplayArea().getFocusedRootTask();
1145                 if (rootTask != null) {
1146                     return rootTask;
1147                 }
1148                 continue;
1149             }
1150 
1151             final Task rootTask = mChildren.get(i).asTask();
1152             if (rootTask.isFocusableAndVisible()) {
1153                 return rootTask;
1154             }
1155         }
1156 
1157         return null;
1158     }
1159 
1160     Task getNextFocusableRootTask(Task currentFocus, boolean ignoreCurrent) {
1161         final int currentWindowingMode = currentFocus != null
1162                 ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
1163 
1164         Task candidate = null;
1165         for (int i = mChildren.size() - 1; i >= 0; --i) {
1166             final WindowContainer child = mChildren.get(i);
1167             if (child.asTaskDisplayArea() != null) {
1168                 final Task rootTask = child.asTaskDisplayArea()
1169                         .getNextFocusableRootTask(currentFocus, ignoreCurrent);
1170                 if (rootTask != null) {
1171                     return rootTask;
1172                 }
1173                 continue;
1174             }
1175 
1176             final Task rootTask = mChildren.get(i).asTask();
1177             if (ignoreCurrent && rootTask == currentFocus) {
1178                 continue;
1179             }
1180             if (!rootTask.isFocusableAndVisible()) {
1181                 continue;
1182             }
1183 
1184             return rootTask;
1185         }
1186         return candidate;
1187     }
1188 
1189     ActivityRecord getFocusedActivity() {
1190         final Task focusedRootTask = getFocusedRootTask();
1191         if (focusedRootTask == null) {
1192             return null;
1193         }
1194         // TODO(b/111541062): Move this into Task#getResumedActivity()
1195         // Check if the focused root task has the resumed activity
1196         ActivityRecord resumedActivity = focusedRootTask.getTopResumedActivity();
1197         if (resumedActivity == null || resumedActivity.app == null) {
1198             // If there is no registered resumed activity in the root task or it is not running -
1199             // try to use previously resumed one.
1200             resumedActivity = focusedRootTask.getTopPausingActivity();
1201             if (resumedActivity == null || resumedActivity.app == null) {
1202                 // If previously resumed activity doesn't work either - find the topmost running
1203                 // activity that can be focused.
1204                 resumedActivity = focusedRootTask.topRunningActivity(true /* focusableOnly */);
1205             }
1206         }
1207         return resumedActivity;
1208     }
1209 
1210     Task getLastFocusedRootTask() {
1211         return mLastFocusedRootTask;
1212     }
1213 
1214     void updateLastFocusedRootTask(Task prevFocusedTask, String updateLastFocusedTaskReason) {
1215         if (updateLastFocusedTaskReason == null) {
1216             return;
1217         }
1218 
1219         final Task currentFocusedTask = getFocusedRootTask();
1220         if (currentFocusedTask == prevFocusedTask) {
1221             return;
1222         }
1223 
1224         // Clear last paused activity if focused root task changed while sleeping, so that the
1225         // top activity of current focused task can be resumed.
1226         if (mDisplayContent.isSleeping() && currentFocusedTask != null) {
1227             currentFocusedTask.clearLastPausedActivity();
1228         }
1229 
1230         mLastFocusedRootTask = prevFocusedTask;
1231         EventLogTags.writeWmFocusedRootTask(mRootWindowContainer.mCurrentUser,
1232                 mDisplayContent.mDisplayId,
1233                 currentFocusedTask == null ? -1 : currentFocusedTask.getRootTaskId(),
1234                 mLastFocusedRootTask == null ? -1 : mLastFocusedRootTask.getRootTaskId(),
1235                 updateLastFocusedTaskReason);
1236     }
1237 
1238     boolean allResumedActivitiesComplete() {
1239         for (int i = mChildren.size() - 1; i >= 0; --i) {
1240             final WindowContainer child = mChildren.get(i);
1241             if (child.asTaskDisplayArea() != null) {
1242                 if (!child.asTaskDisplayArea().allResumedActivitiesComplete()) {
1243                     return false;
1244                 }
1245                 continue;
1246             }
1247 
1248             final ActivityRecord r = mChildren.get(i).asTask().getTopResumedActivity();
1249             if (r != null && !r.isState(RESUMED)) {
1250                 return false;
1251             }
1252         }
1253         final Task currentFocusedRootTask = getFocusedRootTask();
1254         if (ActivityTaskManagerDebugConfig.DEBUG_ROOT_TASK) {
1255             Slog.d(TAG_ROOT_TASK, "allResumedActivitiesComplete: currentFocusedRootTask "
1256                     + "changing from=" + mLastFocusedRootTask + " to=" + currentFocusedRootTask);
1257         }
1258         mLastFocusedRootTask = currentFocusedRootTask;
1259         return true;
1260     }
1261 
1262     /**
1263      * Pause all activities in either all of the root tasks or just the back root tasks. This is
1264      * done before resuming a new activity and to make sure that previously active activities are
1265      * paused in root tasks that are no longer visible or in pinned windowing mode. This does not
1266      * pause activities in visible root tasks, so if an activity is launched within the same root
1267      * task, hen we should explicitly pause that root task's top activity.
1268      *
1269      * @param resuming    The resuming activity.
1270      * @return {@code true} if any activity was paused as a result of this call.
1271      */
1272     boolean pauseBackTasks(ActivityRecord resuming) {
1273         final int[] someActivityPaused = {0};
1274         forAllLeafTasks(leafTask -> {
1275             if (leafTask.pauseActivityIfNeeded(resuming, "pauseBackTasks")) {
1276                 someActivityPaused[0]++;
1277             }
1278         }, true /* traverseTopToBottom */);
1279         return someActivityPaused[0] > 0;
1280     }
1281 
1282 
1283     /**
1284      * Returns true if the {@param windowingMode} is supported based on other parameters passed in.
1285      *
1286      * @param windowingMode       The windowing mode we are checking support for.
1287      * @param supportsMultiWindow If we should consider support for multi-window mode in general.
1288      * @param supportsFreeform    If we should consider support for freeform multi-window.
1289      * @param supportsPip         If we should consider support for picture-in-picture mutli-window.
1290      * @return true if the windowing mode is supported.
1291      */
1292     static boolean isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow,
1293             boolean supportsFreeform, boolean supportsPip) {
1294 
1295         if (windowingMode == WINDOWING_MODE_UNDEFINED
1296                 || windowingMode == WINDOWING_MODE_FULLSCREEN) {
1297             return true;
1298         }
1299         if (!supportsMultiWindow) {
1300             return false;
1301         }
1302 
1303         if (windowingMode == WINDOWING_MODE_MULTI_WINDOW) {
1304             return true;
1305         }
1306 
1307         if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) {
1308             return false;
1309         }
1310 
1311         if (!supportsPip && windowingMode == WINDOWING_MODE_PINNED) {
1312             return false;
1313         }
1314         return true;
1315     }
1316 
1317     /**
1318      * Resolves the windowing mode that an {@link ActivityRecord} would be in if started on this
1319      * display with the provided parameters.
1320      *
1321      * @param r            The ActivityRecord in question.
1322      * @param options      Options to start with.
1323      * @param task         The task within-which the activity would start.
1324      * @param activityType The type of activity to start.
1325      * @return The resolved (not UNDEFINED) windowing-mode that the activity would be in.
1326      */
1327     int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
1328             @Nullable Task task) {
1329 
1330         // First preference if the windowing mode in the activity options if set.
1331         int windowingMode = (options != null)
1332                 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
1333 
1334         // If windowing mode is unset, then next preference is the candidate task, then the
1335         // activity record.
1336         if (windowingMode == WINDOWING_MODE_UNDEFINED) {
1337             if (task != null) {
1338                 windowingMode = task.getWindowingMode();
1339             }
1340             if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) {
1341                 windowingMode = r.getWindowingMode();
1342             }
1343             if (windowingMode == WINDOWING_MODE_UNDEFINED) {
1344                 // Use the display's windowing mode.
1345                 windowingMode = getWindowingMode();
1346             }
1347         }
1348         windowingMode = validateWindowingMode(windowingMode, r, task);
1349         return windowingMode != WINDOWING_MODE_UNDEFINED
1350                 ? windowingMode : WINDOWING_MODE_FULLSCREEN;
1351     }
1352 
1353     /**
1354      * Check if the requested windowing-mode is appropriate for the specified task and/or activity
1355      * on this display.
1356      *
1357      * @param windowingMode The windowing-mode to validate.
1358      * @param r             The {@link ActivityRecord} to check against.
1359      * @param task          The {@link Task} to check against.
1360      * @return {@code true} if windowingMode is valid, {@code false} otherwise.
1361      */
1362     boolean isValidWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task
1363     ) {
1364         // Make sure the windowing mode we are trying to use makes sense for what is supported.
1365         boolean supportsMultiWindow = mAtmService.mSupportsMultiWindow;
1366         boolean supportsFreeform = mAtmService.mSupportsFreeformWindowManagement;
1367         boolean supportsPip = mAtmService.mSupportsPictureInPicture;
1368         if (supportsMultiWindow) {
1369             if (task != null) {
1370                 supportsFreeform = task.supportsFreeformInDisplayArea(this);
1371                 supportsMultiWindow = task.supportsMultiWindowInDisplayArea(this)
1372                         // When the activity needs to be moved to PIP while the Task is not in PIP,
1373                         // it can be moved to a new created PIP Task, so WINDOWING_MODE_PINNED is
1374                         // always valid for Task as long as the device supports it.
1375                         || (windowingMode == WINDOWING_MODE_PINNED && supportsPip);
1376             } else if (r != null) {
1377                 supportsFreeform = r.supportsFreeformInDisplayArea(this);
1378                 supportsPip = r.supportsPictureInPicture();
1379                 supportsMultiWindow = r.supportsMultiWindowInDisplayArea(this);
1380             }
1381         }
1382 
1383         return windowingMode != WINDOWING_MODE_UNDEFINED
1384                 && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsFreeform,
1385                 supportsPip);
1386     }
1387 
1388     /**
1389      * Check that the requested windowing-mode is appropriate for the specified task and/or activity
1390      * on this display.
1391      *
1392      * @param windowingMode The windowing-mode to validate.
1393      * @param r             The {@link ActivityRecord} to check against.
1394      * @param task          The {@link Task} to check against.
1395      * @return The provided windowingMode or the closest valid mode which is appropriate.
1396      */
1397     int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task) {
1398         if (!isValidWindowingMode(windowingMode, r, task)) {
1399             return WINDOWING_MODE_UNDEFINED;
1400         }
1401         return windowingMode;
1402     }
1403 
1404     /**
1405      * Whether we can show non-resizable activities in multi window below this
1406      * {@link TaskDisplayArea}
1407      */
1408     boolean supportsNonResizableMultiWindow() {
1409         final int configSupportsNonResizableMultiWindow =
1410                 mAtmService.mSupportsNonResizableMultiWindow;
1411         if (mAtmService.mDevEnableNonResizableMultiWindow
1412                 || configSupportsNonResizableMultiWindow == 1) {
1413             // Device override to support.
1414             return true;
1415         }
1416         if (configSupportsNonResizableMultiWindow == -1) {
1417             // Device override to not support.
1418             return false;
1419         }
1420         // Support on large screen.
1421         return isLargeEnoughForMultiWindow();
1422     }
1423 
1424     /**
1425      * Whether we can show activity requesting the given min width/height in multi window below
1426      * this {@link TaskDisplayArea}.
1427      */
1428     boolean supportsActivityMinWidthHeightMultiWindow(int minWidth, int minHeight,
1429             @Nullable ActivityInfo activityInfo) {
1430         if (activityInfo != null && !activityInfo.shouldCheckMinWidthHeightForMultiWindow()) {
1431             return true;
1432         }
1433         if (minWidth <= 0 && minHeight <= 0) {
1434             // No request min width/height.
1435             return true;
1436         }
1437         final int configRespectsActivityMinWidthHeightMultiWindow =
1438                 mAtmService.mRespectsActivityMinWidthHeightMultiWindow;
1439         if (configRespectsActivityMinWidthHeightMultiWindow == -1) {
1440             // Device override to ignore min width/height.
1441             return true;
1442         }
1443         if (configRespectsActivityMinWidthHeightMultiWindow == 0
1444                 && isLargeEnoughForMultiWindow()) {
1445             // Ignore min width/height on large screen.
1446             return true;
1447         }
1448         // Check if the request min width/height is supported in multi window.
1449         final Configuration config = getConfiguration();
1450         final int orientation = config.orientation;
1451         if (orientation == ORIENTATION_LANDSCAPE) {
1452             final int maxSupportMinWidth = (int) (mAtmService.mMinPercentageMultiWindowSupportWidth
1453                     * config.screenWidthDp * mDisplayContent.getDisplayMetrics().density);
1454             return minWidth <= maxSupportMinWidth;
1455         } else {
1456             final int maxSupportMinHeight =
1457                     (int) (mAtmService.mMinPercentageMultiWindowSupportHeight
1458                             * config.screenHeightDp * mDisplayContent.getDisplayMetrics().density);
1459             return minHeight <= maxSupportMinHeight;
1460         }
1461     }
1462 
1463     /**
1464      * Whether this is large enough to support non-resizable, and activities with min width/height
1465      * in multi window.
1466      */
1467     private boolean isLargeEnoughForMultiWindow() {
1468         return getConfiguration().smallestScreenWidthDp
1469                 >= WindowManager.LARGE_SCREEN_SMALLEST_SCREEN_WIDTH_DP;
1470     }
1471 
1472     boolean isTopRootTask(Task rootTask) {
1473         return rootTask == getTopRootTask();
1474     }
1475 
1476     ActivityRecord topRunningActivity() {
1477         return topRunningActivity(false /* considerKeyguardState */);
1478     }
1479 
1480     /**
1481      * Returns the top running activity in the focused root task. In the case the focused root
1482      * task has no such activity, the next focusable root task on this display is returned.
1483      *
1484      * @param considerKeyguardState Indicates whether the locked state should be considered. if
1485      *                              {@code true} and the keyguard is locked, only activities that
1486      *                              can be shown on top of the keyguard will be considered.
1487      * @return The top running activity. {@code null} if none is available.
1488      */
1489     ActivityRecord topRunningActivity(boolean considerKeyguardState) {
1490         ActivityRecord topRunning = null;
1491         final Task focusedRootTask = getFocusedRootTask();
1492         if (focusedRootTask != null) {
1493             topRunning = focusedRootTask.topRunningActivity();
1494         }
1495 
1496         // Look in other focusable root tasks.
1497         if (topRunning == null) {
1498             for (int i = mChildren.size() - 1; i >= 0; --i) {
1499                 final WindowContainer child = mChildren.get(i);
1500                 if (child.asTaskDisplayArea() != null) {
1501                     topRunning =
1502                             child.asTaskDisplayArea().topRunningActivity(considerKeyguardState);
1503                     if (topRunning != null) {
1504                         break;
1505                     }
1506                     continue;
1507                 }
1508                 final Task rootTask = mChildren.get(i).asTask();
1509                 // Only consider focusable root tasks other than the current focused one.
1510                 if (rootTask == focusedRootTask || !rootTask.isTopActivityFocusable()) {
1511                     continue;
1512                 }
1513                 topRunning = rootTask.topRunningActivity();
1514                 if (topRunning != null) {
1515                     break;
1516                 }
1517             }
1518         }
1519 
1520         // This activity can be considered the top running activity if we are not considering
1521         // the locked state, the keyguard isn't locked, or we can show when locked.
1522         if (topRunning != null && considerKeyguardState
1523                 && mRootWindowContainer.mTaskSupervisor.getKeyguardController()
1524                 .isKeyguardLocked(topRunning.getDisplayId())
1525                 && !topRunning.canShowWhenLocked()) {
1526             return null;
1527         }
1528 
1529         return topRunning;
1530     }
1531 
1532     protected int getRootTaskCount() {
1533         final int[] count = new int[1];
1534         forAllRootTasks(task -> {
1535             count[0]++;
1536         });
1537         return count[0];
1538     }
1539 
1540     @Nullable
1541     Task getOrCreateRootHomeTask() {
1542         return getOrCreateRootHomeTask(false /* onTop */);
1543     }
1544 
1545     /**
1546      * Returns the existing root home task or creates and returns a new one if it should exist
1547      * for the display.
1548      *
1549      * @param onTop Only be used when there is no existing root home task. If true the root home
1550      *              task will be created at the top of the display, else at the bottom.
1551      */
1552     @Nullable
1553     Task getOrCreateRootHomeTask(boolean onTop) {
1554         Task homeTask = getRootHomeTask();
1555         // Take into account if this TaskDisplayArea can have a home task before trying to
1556         // create the root task
1557         if (homeTask == null && canHostHomeTask()) {
1558             homeTask = createRootTask(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, onTop);
1559         }
1560         return homeTask;
1561     }
1562 
1563     /**
1564      * Returns the topmost root task on the display that is compatible with the input windowing
1565      * mode. Null is no compatible root task on the display.
1566      */
1567     Task getTopRootTaskInWindowingMode(int windowingMode) {
1568         return getRootTask(windowingMode, ACTIVITY_TYPE_UNDEFINED);
1569     }
1570 
1571     void moveHomeRootTaskToFront(String reason) {
1572         final Task homeRootTask = getOrCreateRootHomeTask();
1573         if (homeRootTask != null) {
1574             homeRootTask.moveToFront(reason);
1575         }
1576     }
1577 
1578     /**
1579      * Moves the focusable home activity to top. If there is no such activity, the root home task
1580      * will still move to top.
1581      */
1582     void moveHomeActivityToTop(String reason) {
1583         final ActivityRecord top = getHomeActivity();
1584         if (top == null) {
1585             moveHomeRootTaskToFront(reason);
1586             return;
1587         }
1588         top.moveFocusableActivityToTop(reason);
1589     }
1590 
1591     @Nullable
1592     ActivityRecord getHomeActivity() {
1593         return getHomeActivityForUser(mRootWindowContainer.mCurrentUser);
1594     }
1595 
1596     @Nullable
1597     ActivityRecord getHomeActivityForUser(int userId) {
1598         final Task rootHomeTask = getRootHomeTask();
1599         if (rootHomeTask == null) {
1600             return null;
1601         }
1602 
1603         final PooledPredicate p = PooledLambda.obtainPredicate(
1604                 TaskDisplayArea::isHomeActivityForUser, PooledLambda.__(ActivityRecord.class),
1605                 userId);
1606         final ActivityRecord r = rootHomeTask.getActivity(p);
1607         p.recycle();
1608         return r;
1609     }
1610 
1611     private static boolean isHomeActivityForUser(ActivityRecord r, int userId) {
1612         return r.isActivityTypeHome() && (userId == UserHandle.USER_ALL || r.mUserId == userId);
1613     }
1614 
1615     /**
1616      * Adjusts the {@param rootTask} behind the last visible rootTask in the display if necessary.
1617      * Generally used in conjunction with {@link #moveRootTaskBehindRootTask}.
1618      */
1619     // TODO(b/151575894): Remove special root task movement methods.
1620     void moveRootTaskBehindBottomMostVisibleRootTask(Task rootTask) {
1621         if (rootTask.shouldBeVisible(null)) {
1622             // Skip if the root task is already visible
1623             return;
1624         }
1625 
1626         // Move the root task to the bottom to not affect the following visibility checks
1627         rootTask.getParent().positionChildAt(POSITION_BOTTOM, rootTask,
1628                 false /* includingParents */);
1629 
1630         // Find the next position where the root task should be placed
1631         final boolean isRootTask = rootTask.isRootTask();
1632         final int numRootTasks =
1633                 isRootTask ? mChildren.size() : rootTask.getParent().getChildCount();
1634         for (int rootTaskNdx = 0; rootTaskNdx < numRootTasks; rootTaskNdx++) {
1635             Task s;
1636             if (isRootTask) {
1637                 final WindowContainer child = mChildren.get(rootTaskNdx);
1638                 if (child.asTaskDisplayArea() != null) {
1639                     s = child.asTaskDisplayArea().getBottomMostVisibleRootTask(rootTask);
1640                 } else {
1641                     s = child.asTask();
1642                 }
1643             } else {
1644                 s = rootTask.getParent().getChildAt(rootTaskNdx).asTask();
1645             }
1646             if (s == rootTask || s == null) {
1647                 continue;
1648             }
1649             final int winMode = s.getWindowingMode();
1650             final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN;
1651             if (s.shouldBeVisible(null) && isValidWindowingMode) {
1652                 // Move the provided root task to behind this root task
1653                 final int position = Math.max(0, rootTaskNdx - 1);
1654                 rootTask.getParent().positionChildAt(position, rootTask,
1655                         false /*includingParents */);
1656                 break;
1657             }
1658         }
1659     }
1660 
1661     @Nullable
1662     private Task getBottomMostVisibleRootTask(Task excludeRootTask) {
1663         return getRootTask(task -> {
1664             final int winMode = task.getWindowingMode();
1665             final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN;
1666             return task.shouldBeVisible(null) && isValidWindowingMode;
1667         }, false /* traverseTopToBottom */);
1668     }
1669 
1670     /**
1671      * Moves the {@param rootTask} behind the given {@param behindRootTask} if possible. If
1672      * {@param behindRootTask} is not currently in the display, then then the root task is moved
1673      * to the back. Generally used in conjunction with
1674      * {@link #moveRootTaskBehindBottomMostVisibleRootTask}.
1675      */
1676     void moveRootTaskBehindRootTask(Task rootTask, Task behindRootTask) {
1677         if (behindRootTask == null || behindRootTask == rootTask) {
1678             return;
1679         }
1680 
1681         final WindowContainer parent = rootTask.getParent();
1682         if (parent == null || parent != behindRootTask.getParent()) {
1683             return;
1684         }
1685 
1686         // Note that positionChildAt will first remove the given root task before inserting into the
1687         // list, so we need to adjust the insertion index to account for the removed index
1688         // TODO: Remove this logic when WindowContainer.positionChildAt() is updated to adjust the
1689         //       position internally
1690         final int rootTaskIndex = parent.mChildren.indexOf(rootTask);
1691         final int behindRootTaskIndex = parent.mChildren.indexOf(behindRootTask);
1692         final int insertIndex = rootTaskIndex <= behindRootTaskIndex
1693                 ? behindRootTaskIndex - 1 : behindRootTaskIndex;
1694         final int position = Math.max(0, insertIndex);
1695         parent.positionChildAt(position, rootTask, false /* includingParents */);
1696     }
1697 
1698     boolean hasPinnedTask() {
1699         return getRootPinnedTask() != null;
1700     }
1701 
1702     /**
1703      * @return the root task currently above the {@param rootTask}. Can be null if the
1704      * {@param rootTask} is already top-most.
1705      */
1706     static Task getRootTaskAbove(Task rootTask) {
1707         final WindowContainer wc = rootTask.getParent();
1708         final int index = wc.mChildren.indexOf(rootTask) + 1;
1709         return (index < wc.mChildren.size()) ? (Task) wc.mChildren.get(index) : null;
1710     }
1711 
1712     /** Returns true if the root task in the windowing mode is visible. */
1713     boolean isRootTaskVisible(int windowingMode) {
1714         final Task rootTask = getTopRootTaskInWindowingMode(windowingMode);
1715         return rootTask != null && rootTask.isVisible();
1716     }
1717 
1718     void removeRootTask(Task rootTask) {
1719         removeChild(rootTask);
1720     }
1721 
1722     int getDisplayId() {
1723         return mDisplayContent.getDisplayId();
1724     }
1725 
1726     boolean isRemoved() {
1727         return mRemoved;
1728     }
1729 
1730     /**
1731      * Adds a listener to be notified whenever the root task order in the display changes. Currently
1732      * only used by the {@link RecentsAnimation} to determine whether to interrupt and cancel the
1733      * current animation when the system state changes.
1734      */
1735     void registerRootTaskOrderChangedListener(OnRootTaskOrderChangedListener listener) {
1736         if (!mRootTaskOrderChangedCallbacks.contains(listener)) {
1737             mRootTaskOrderChangedCallbacks.add(listener);
1738         }
1739     }
1740 
1741     /**
1742      * Removes a previously registered root task order change listener.
1743      */
1744     void unregisterRootTaskOrderChangedListener(OnRootTaskOrderChangedListener listener) {
1745         mRootTaskOrderChangedCallbacks.remove(listener);
1746     }
1747 
1748     /**
1749      * Notifies of a root task order change
1750      *
1751      * @param rootTask The root task which triggered the order change
1752      */
1753     void onRootTaskOrderChanged(Task rootTask) {
1754         for (int i = mRootTaskOrderChangedCallbacks.size() - 1; i >= 0; i--) {
1755             mRootTaskOrderChangedCallbacks.get(i).onRootTaskOrderChanged(rootTask);
1756         }
1757     }
1758 
1759     @Override
1760     boolean canCreateRemoteAnimationTarget() {
1761         // In the legacy transition system, promoting animation target from TaskFragment to
1762         // TaskDisplayArea prevents running finish animation. See b/194649929.
1763         return WindowManagerService.sEnableShellTransitions;
1764     }
1765 
1766     /**
1767      * Exposes the home task capability of the TaskDisplayArea
1768      */
1769     boolean canHostHomeTask() {
1770         return mDisplayContent.isHomeSupported() && mCanHostHomeTask;
1771     }
1772 
1773     /**
1774      * Callback for when the order of the root tasks in the display changes.
1775      */
1776     interface OnRootTaskOrderChangedListener {
1777         void onRootTaskOrderChanged(Task rootTask);
1778     }
1779 
1780     void ensureActivitiesVisible(ActivityRecord starting, boolean notifyClients) {
1781         mAtmService.mTaskSupervisor.beginActivityVisibilityUpdate();
1782         try {
1783             forAllRootTasks(rootTask -> {
1784                 rootTask.ensureActivitiesVisible(starting, notifyClients);
1785             });
1786         } finally {
1787             mAtmService.mTaskSupervisor.endActivityVisibilityUpdate();
1788         }
1789     }
1790 
1791     /**
1792      * Removes the root tasks in the node applying the content removal node from the display.
1793      *
1794      * @return last reparented root task, or {@code null} if the root tasks had to be destroyed.
1795      */
1796     Task remove() {
1797         mPreferredTopFocusableRootTask = null;
1798         // TODO(b/153090332): Allow setting content removal mode per task display area
1799         final boolean destroyContentOnRemoval = mDisplayContent.shouldDestroyContentOnRemove();
1800         final TaskDisplayArea toDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
1801         Task lastReparentedRootTask = null;
1802 
1803         // Root tasks could be reparented from the removed display area to other display area. After
1804         // reparenting the last root task of the removed display area, the display area becomes
1805         // ready to be released (no more root tasks). But, we cannot release it at that moment
1806         // or the related WindowContainer will also be removed. So, we set display area as removed
1807         // after reparenting root task finished.
1808         // Keep the order from bottom to top.
1809         int numRootTasks = mChildren.size();
1810 
1811         for (int i = 0; i < numRootTasks; i++) {
1812             final WindowContainer child = mChildren.get(i);
1813             if (child.asTaskDisplayArea() != null) {
1814                 lastReparentedRootTask = child.asTaskDisplayArea().remove();
1815                 continue;
1816             }
1817             final Task task = mChildren.get(i).asTask();
1818             // Always finish non-standard type root tasks and root tasks created by a organizer.
1819             // TODO: For root tasks created by organizer, consider reparenting children tasks if
1820             //       the use case arises in the future.
1821             if (destroyContentOnRemoval
1822                     || !task.isActivityTypeStandardOrUndefined()
1823                     || task.mCreatedByOrganizer) {
1824                 task.remove(false /* withTransition */, "removeTaskDisplayArea");
1825             } else {
1826                 // Reparent task to corresponding launch root or display area.
1827                 final WindowContainer launchRoot = toDisplayArea.getLaunchRootTask(
1828                                         task.getWindowingMode(),
1829                                         task.getActivityType(),
1830                                         null /* options */,
1831                                         null /* sourceTask */,
1832                                         0 /* launchFlags */);
1833                 task.reparent(launchRoot == null ? toDisplayArea : launchRoot, POSITION_TOP);
1834 
1835                 // If the task is going to be reparented to the non-fullscreen root TDA and the task
1836                 // is set to FULLSCREEN explicitly, we keep the windowing mode as is. Otherwise, the
1837                 // task will inherit the display windowing mode unexpectedly.
1838                 final boolean keepWindowingMode = launchRoot == null
1839                         && task.getRequestedOverrideWindowingMode() == WINDOWING_MODE_FULLSCREEN
1840                         && toDisplayArea.getWindowingMode() != WINDOWING_MODE_FULLSCREEN;
1841                 if (!keepWindowingMode) {
1842                     // Set the windowing mode to undefined to let the root task inherited the
1843                     // windowing mode.
1844                     task.setWindowingMode(WINDOWING_MODE_UNDEFINED);
1845                 }
1846                 lastReparentedRootTask = task;
1847             }
1848             // Root task may be removed from this display. Ensure each root task will be processed
1849             // and the loop will end.
1850             i -= numRootTasks - mChildren.size();
1851             numRootTasks = mChildren.size();
1852         }
1853 
1854         if (lastReparentedRootTask != null && !lastReparentedRootTask.isRootTask()) {
1855             // Update focus when the last reparented root task is not a root task anymore.
1856             // (For example, if it has been reparented to a split screen root task, move the
1857             // focus to the split root task)
1858             lastReparentedRootTask.getRootTask().moveToFront("display-removed");
1859         }
1860 
1861         mRemoved = true;
1862 
1863         return lastReparentedRootTask;
1864     }
1865 
1866     /** Whether this task display area can request orientation. */
1867     boolean canSpecifyOrientation(@ScreenOrientation int orientation) {
1868         // Only allow to specify orientation if this TDA is the last focused one on this logical
1869         // display that can request orientation request.
1870         return mDisplayContent.getOrientationRequestingTaskDisplayArea() == this
1871                 && !shouldIgnoreOrientationRequest(orientation);
1872     }
1873 
1874     void clearPreferredTopFocusableRootTask() {
1875         mPreferredTopFocusableRootTask = null;
1876     }
1877 
1878     @Override
1879     public void setWindowingMode(int windowingMode) {
1880         mTempConfiguration.setTo(getRequestedOverrideConfiguration());
1881         WindowConfiguration tempRequestWindowConfiguration = mTempConfiguration.windowConfiguration;
1882         tempRequestWindowConfiguration.setWindowingMode(windowingMode);
1883         onRequestedOverrideConfigurationChanged(mTempConfiguration);
1884     }
1885 
1886     @Override
1887     TaskDisplayArea getTaskDisplayArea() {
1888         return this;
1889     }
1890 
1891     @Override
1892     boolean isTaskDisplayArea() {
1893         return true;
1894     }
1895 
1896     @Override
1897     TaskDisplayArea asTaskDisplayArea() {
1898         return this;
1899     }
1900 
1901     @Override
1902     void dump(PrintWriter pw, String prefix, boolean dumpAll) {
1903         pw.println(prefix + "TaskDisplayArea " + getName());
1904         final String doublePrefix = prefix + "  ";
1905         super.dump(pw, doublePrefix, dumpAll);
1906         if (mPreferredTopFocusableRootTask != null) {
1907             pw.println(doublePrefix + "mPreferredTopFocusableRootTask="
1908                     + mPreferredTopFocusableRootTask);
1909         }
1910         if (mLastFocusedRootTask != null) {
1911             pw.println(doublePrefix + "mLastFocusedRootTask=" + mLastFocusedRootTask);
1912         }
1913 
1914         final String triplePrefix = doublePrefix + "  ";
1915 
1916         if (mLaunchRootTasks.size() > 0) {
1917             pw.println(doublePrefix + "mLaunchRootTasks:");
1918             for (int i = mLaunchRootTasks.size() - 1; i >= 0; --i) {
1919                 final LaunchRootTaskDef def = mLaunchRootTasks.get(i);
1920                 pw.println(triplePrefix
1921                         + Arrays.toString(def.activityTypes) + " "
1922                         + Arrays.toString(def.windowingModes) + " "
1923                         + " task=" + def.task);
1924             }
1925         }
1926 
1927         pw.println(doublePrefix + "Application tokens in top down Z order:");
1928         for (int index = getChildCount() - 1; index >= 0; --index) {
1929             final WindowContainer child = getChildAt(index);
1930             if (child.asTaskDisplayArea() != null) {
1931                 child.dump(pw, doublePrefix, dumpAll);
1932                 continue;
1933             }
1934             final Task rootTask = child.asTask();
1935             pw.println(doublePrefix + "* " + rootTask.toFullString());
1936             rootTask.dump(pw, triplePrefix, dumpAll);
1937         }
1938     }
1939 }
1940