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