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