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