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.WindowConfiguration.ACTIVITY_TYPE_HOME;
20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
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.app.WindowConfiguration.isSplitScreenWindowingMode;
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 
35 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
36 import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
37 import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
38 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
39 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
40 import static com.android.server.wm.ActivityTaskManagerService.TAG_STACK;
41 import static com.android.server.wm.DisplayContent.alwaysCreateStack;
42 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
43 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
44 import static com.android.server.wm.RootWindowContainer.TAG_STATES;
45 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK;
46 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
47 
48 import android.annotation.Nullable;
49 import android.app.ActivityOptions;
50 import android.app.WindowConfiguration;
51 import android.content.Intent;
52 import android.content.pm.ActivityInfo;
53 import android.content.pm.ApplicationInfo;
54 import android.os.UserHandle;
55 import android.util.IntArray;
56 import android.util.Slog;
57 import android.view.SurfaceControl;
58 import android.window.WindowContainerTransaction;
59 
60 import com.android.internal.annotations.VisibleForTesting;
61 import com.android.internal.util.ToBooleanFunction;
62 import com.android.internal.util.function.pooled.PooledLambda;
63 import com.android.internal.util.function.pooled.PooledPredicate;
64 import com.android.server.protolog.common.ProtoLog;
65 
66 import java.io.PrintWriter;
67 import java.util.ArrayList;
68 import java.util.List;
69 
70 /**
71  * {@link DisplayArea} that represents a section of a screen that contains app window containers.
72  */
73 final class TaskDisplayArea extends DisplayArea<ActivityStack> {
74 
75     DisplayContent mDisplayContent;
76 
77     /**
78      * A control placed at the appropriate level for transitions to occur.
79      */
80     private SurfaceControl mAppAnimationLayer;
81     private SurfaceControl mBoostedAppAnimationLayer;
82     private SurfaceControl mHomeAppAnimationLayer;
83 
84     /**
85      * Given that the split-screen divider does not have an AppWindowToken, it
86      * will have to live inside of a "NonAppWindowContainer". However, in visual Z order
87      * it will need to be interleaved with some of our children, appearing on top of
88      * both docked stacks but underneath any assistant stacks.
89      *
90      * To solve this problem we have this anchor control, which will always exist so
91      * we can always assign it the correct value in our {@link #assignChildLayers}.
92      * Likewise since it always exists, we can always
93      * assign the divider a layer relative to it. This way we prevent linking lifecycle
94      * events between tasks and the divider window.
95      */
96     private SurfaceControl mSplitScreenDividerAnchor;
97 
98     // Cached reference to some special tasks we tend to get a lot so we don't need to loop
99     // through the list to find them.
100     private ActivityStack mRootHomeTask;
101     private ActivityStack mRootPinnedTask;
102     private ActivityStack mRootSplitScreenPrimaryTask;
103 
104     // TODO(b/159029784): Remove when getStack() behavior is cleaned-up
105     private ActivityStack mRootRecentsTask;
106 
107     private final ArrayList<ActivityStack> mTmpAlwaysOnTopStacks = new ArrayList<>();
108     private final ArrayList<ActivityStack> mTmpNormalStacks = new ArrayList<>();
109     private final ArrayList<ActivityStack> mTmpHomeStacks = new ArrayList<>();
110     private final IntArray mTmpNeedsZBoostIndexes = new IntArray();
111     private int mTmpLayerForSplitScreenDividerAnchor;
112     private int mTmpLayerForAnimationLayer;
113 
114     private ArrayList<Task> mTmpTasks = new ArrayList<>();
115 
116     private ActivityTaskManagerService mAtmService;
117 
118     private RootWindowContainer mRootWindowContainer;
119 
120     // When non-null, new tasks get put into this root task.
121     Task mLaunchRootTask = null;
122 
123     /**
124      * A focusable stack that is purposely to be positioned at the top. Although the stack may not
125      * have the topmost index, it is used as a preferred candidate to prevent being unable to resume
126      * target stack properly when there are other focusable always-on-top stacks.
127      */
128     ActivityStack mPreferredTopFocusableStack;
129 
130     private final RootWindowContainer.FindTaskResult
131             mTmpFindTaskResult = new RootWindowContainer.FindTaskResult();
132 
133     /**
134      * If this is the same as {@link #getFocusedStack} then the activity on the top of the focused
135      * stack has been resumed. If stacks are changing position this will hold the old stack until
136      * the new stack becomes resumed after which it will be set to current focused stack.
137      */
138     ActivityStack mLastFocusedStack;
139     /**
140      * All of the stacks on this display. Order matters, topmost stack is in front of all other
141      * stacks, bottommost behind. Accessed directly by ActivityManager package classes. Any calls
142      * changing the list should also call {@link #onStackOrderChanged()}.
143      */
144     private ArrayList<OnStackOrderChangedListener> mStackOrderChangedCallbacks = new ArrayList<>();
145 
146     /**
147      * The task display area is removed from the system and we are just waiting for all activities
148      * on it to be finished before removing this object.
149      */
150     private boolean mRemoved;
151 
TaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name, int displayAreaFeature)152     TaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name,
153             int displayAreaFeature) {
154         super(service, Type.ANY, name, displayAreaFeature);
155         mDisplayContent = displayContent;
156         mRootWindowContainer = service.mRoot;
157         mAtmService = service.mAtmService;
158     }
159 
160     /**
161      * Returns the topmost stack on the display that is compatible with the input windowing mode
162      * and activity type. Null is no compatible stack on the display.
163      */
getStack(int windowingMode, int activityType)164     ActivityStack getStack(int windowingMode, int activityType) {
165         if (activityType == ACTIVITY_TYPE_HOME) {
166             return mRootHomeTask;
167         } else if (activityType == ACTIVITY_TYPE_RECENTS) {
168             return mRootRecentsTask;
169         }
170         if (windowingMode == WINDOWING_MODE_PINNED) {
171             return mRootPinnedTask;
172         } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
173             return mRootSplitScreenPrimaryTask;
174         }
175         for (int i = getChildCount() - 1; i >= 0; --i) {
176             final ActivityStack stack = getChildAt(i);
177             if (activityType == ACTIVITY_TYPE_UNDEFINED
178                     && windowingMode == stack.getWindowingMode()) {
179                 // Passing in undefined type means we want to match the topmost stack with the
180                 // windowing mode.
181                 return stack;
182             }
183             if (stack.isCompatible(windowingMode, activityType)) {
184                 return stack;
185             }
186         }
187         return null;
188     }
189 
190     @VisibleForTesting
getTopStack()191     ActivityStack getTopStack() {
192         final int count = getChildCount();
193         return count > 0 ? getChildAt(count - 1) : null;
194     }
195 
196     // TODO: Figure-out a way to remove since it might be a source of confusion.
getIndexOf(ActivityStack stack)197     int getIndexOf(ActivityStack stack) {
198         return mChildren.indexOf(stack);
199     }
200 
getRootHomeTask()201     @Nullable ActivityStack getRootHomeTask() {
202         return mRootHomeTask;
203     }
204 
getRootRecentsTask()205     @Nullable ActivityStack getRootRecentsTask() {
206         return mRootRecentsTask;
207     }
208 
getRootPinnedTask()209     ActivityStack getRootPinnedTask() {
210         return mRootPinnedTask;
211     }
212 
getRootSplitScreenPrimaryTask()213     ActivityStack getRootSplitScreenPrimaryTask() {
214         return mRootSplitScreenPrimaryTask;
215     }
216 
getRootSplitScreenSecondaryTask()217     ActivityStack getRootSplitScreenSecondaryTask() {
218         for (int i = mChildren.size() - 1; i >= 0; --i) {
219             if (mChildren.get(i).inSplitScreenSecondaryWindowingMode()) {
220                 return mChildren.get(i);
221             }
222         }
223         return null;
224     }
225 
getVisibleTasks()226     ArrayList<Task> getVisibleTasks() {
227         final ArrayList<Task> visibleTasks = new ArrayList<>();
228         forAllTasks(task -> {
229             if (task.isLeafTask() && task.isVisible()) {
230                 visibleTasks.add(task);
231             }
232         });
233         return visibleTasks;
234     }
235 
onStackWindowingModeChanged(ActivityStack stack)236     void onStackWindowingModeChanged(ActivityStack stack) {
237         removeStackReferenceIfNeeded(stack);
238         addStackReferenceIfNeeded(stack);
239         if (stack == mRootPinnedTask && getTopStack() != stack) {
240             // Looks like this stack changed windowing mode to pinned. Move it to the top.
241             positionChildAt(POSITION_TOP, stack, false /* includingParents */);
242         }
243     }
244 
addStackReferenceIfNeeded(ActivityStack stack)245     void addStackReferenceIfNeeded(ActivityStack stack) {
246         if (stack.isActivityTypeHome()) {
247             if (mRootHomeTask != null) {
248                 if (!stack.isDescendantOf(mRootHomeTask)) {
249                     throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
250                             + mRootHomeTask + " already exist on display=" + this
251                             + " stack=" + stack);
252                 }
253             } else {
254                 mRootHomeTask = stack;
255             }
256         } else if (stack.isActivityTypeRecents()) {
257             if (mRootRecentsTask != null) {
258                 if (!stack.isDescendantOf(mRootRecentsTask)) {
259                     throw new IllegalArgumentException("addStackReferenceIfNeeded: recents stack="
260                             + mRootRecentsTask + " already exist on display=" + this
261                             + " stack=" + stack);
262                 }
263             } else {
264                 mRootRecentsTask = stack;
265             }
266         }
267 
268         if (!stack.isRootTask()) {
269             return;
270         }
271         final int windowingMode = stack.getWindowingMode();
272         if (windowingMode == WINDOWING_MODE_PINNED) {
273             if (mRootPinnedTask != null) {
274                 throw new IllegalArgumentException(
275                         "addStackReferenceIfNeeded: pinned stack=" + mRootPinnedTask
276                                 + " already exist on display=" + this + " stack=" + stack);
277             }
278             mRootPinnedTask = stack;
279         } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
280             if (mRootSplitScreenPrimaryTask != null) {
281                 throw new IllegalArgumentException(
282                         "addStackReferenceIfNeeded: split screen primary stack="
283                                 + mRootSplitScreenPrimaryTask
284                                 + " already exist on display=" + this + " stack=" + stack);
285             }
286             mRootSplitScreenPrimaryTask = stack;
287         }
288     }
289 
removeStackReferenceIfNeeded(ActivityStack stack)290     void removeStackReferenceIfNeeded(ActivityStack stack) {
291         if (stack == mRootHomeTask) {
292             mRootHomeTask = null;
293         } else if (stack == mRootRecentsTask) {
294             mRootRecentsTask = null;
295         } else if (stack == mRootPinnedTask) {
296             mRootPinnedTask = null;
297         } else if (stack == mRootSplitScreenPrimaryTask) {
298             mRootSplitScreenPrimaryTask = null;
299         }
300     }
301 
302     @Override
addChild(ActivityStack stack, int position)303     void addChild(ActivityStack stack, int position) {
304         if (DEBUG_STACK) Slog.d(TAG_WM, "Set stack=" + stack + " on taskDisplayArea=" + this);
305         addStackReferenceIfNeeded(stack);
306         position = findPositionForStack(position, stack, true /* adding */);
307 
308         super.addChild(stack, position);
309         mAtmService.updateSleepIfNeededLocked();
310 
311         positionStackAt(stack, position);
312     }
313 
314     @Override
removeChild(ActivityStack stack)315     protected void removeChild(ActivityStack stack) {
316         super.removeChild(stack);
317         onStackRemoved(stack);
318         mAtmService.updateSleepIfNeededLocked();
319         removeStackReferenceIfNeeded(stack);
320     }
321 
322     @Override
isOnTop()323     boolean isOnTop() {
324         // Considered always on top
325         return true;
326     }
327 
328     @Override
positionChildAt(int position, ActivityStack child, boolean includingParents)329     void positionChildAt(int position, ActivityStack child, boolean includingParents) {
330         final boolean moveToTop = position >= getChildCount() - 1;
331         final boolean moveToBottom = (position == POSITION_BOTTOM || position == 0);
332 
333         // Reset mPreferredTopFocusableStack before positioning to top or {@link
334         // ActivityStackSupervisor#updateTopResumedActivityIfNeeded()} won't update the top
335         // resumed activity.
336         final boolean wasContained = mChildren.contains(child);
337         if (moveToTop && wasContained && child.isFocusable()) {
338             mPreferredTopFocusableStack = null;
339         }
340 
341         if (child.getWindowConfiguration().isAlwaysOnTop() && !moveToTop) {
342             // This stack is always-on-top, override the default behavior.
343             Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom");
344 
345             // Moving to its current position, as we must call super but we don't want to
346             // perform any meaningful action.
347             final int currentPosition = mChildren.indexOf(child);
348             super.positionChildAt(currentPosition, child, false /* includingParents */);
349             return;
350         }
351         // We don't allow untrusted display to top when task stack moves to top,
352         // until user tapping this display to change display position as top intentionally.
353         if (!mDisplayContent.isTrusted() && !getParent().isOnTop()) {
354             includingParents = false;
355         }
356         final int targetPosition = findPositionForStack(position, child, false /* adding */);
357         super.positionChildAt(targetPosition, child, false /* includingParents */);
358 
359         if (includingParents && (moveToTop || moveToBottom)) {
360             // The DisplayContent children do not re-order, but we still want to move the
361             // display of this stack container because the intention of positioning is to have
362             // higher z-order to gain focus.
363             mDisplayContent.positionDisplayAt(moveToTop ? POSITION_TOP : POSITION_BOTTOM,
364                     true /* includingParents */);
365         }
366 
367         child.updateTaskMovement(moveToTop);
368 
369         mDisplayContent.setLayoutNeeded();
370 
371         // The insert position may be adjusted to non-top when there is always-on-top stack. Since
372         // the original position is preferred to be top, the stack should have higher priority when
373         // we are looking for top focusable stack. The condition {@code wasContained} restricts the
374         // preferred stack is set only when moving an existing stack to top instead of adding a new
375         // stack that may be too early (e.g. in the middle of launching or reparenting).
376         if (moveToTop && child.isFocusableAndVisible()) {
377             mPreferredTopFocusableStack = child;
378         } else if (mPreferredTopFocusableStack == child) {
379             mPreferredTopFocusableStack = null;
380         }
381     }
382 
383     /**
384      * Assigns a priority number to stack types. This priority defines an order between the types
385      * of stacks that are added to the task display area.
386      *
387      * Higher priority number indicates that the stack should have a higher z-order.
388      *
389      * @return the priority of the stack
390      */
getPriority(ActivityStack stack)391     private int getPriority(ActivityStack stack) {
392         if (mWmService.mAssistantOnTopOfDream && stack.isActivityTypeAssistant()) return 4;
393         if (stack.isActivityTypeDream()) return 3;
394         if (stack.inPinnedWindowingMode()) return 2;
395         if (stack.isAlwaysOnTop()) return 1;
396         return 0;
397     }
398 
findMinPositionForStack(ActivityStack stack)399     private int findMinPositionForStack(ActivityStack stack) {
400         int minPosition = POSITION_BOTTOM;
401         for (int i = 0; i < mChildren.size(); ++i) {
402             if (getPriority(getStackAt(i)) < getPriority(stack)) {
403                 minPosition = i;
404             } else {
405                 break;
406             }
407         }
408 
409         if (stack.isAlwaysOnTop()) {
410             // Since a stack could be repositioned while still being one of the children, we check
411             // if this always-on-top stack already exists and if so, set the minPosition to its
412             // previous position.
413             final int currentIndex = getIndexOf(stack);
414             if (currentIndex > minPosition) {
415                 minPosition = currentIndex;
416             }
417         }
418         return minPosition;
419     }
420 
findMaxPositionForStack(ActivityStack stack)421     private int findMaxPositionForStack(ActivityStack stack) {
422         for (int i = mChildren.size() - 1; i >= 0; --i) {
423             final ActivityStack curr = getStackAt(i);
424             // Since a stack could be repositioned while still being one of the children, we check
425             // if 'curr' is the same stack and skip it if so
426             final boolean sameStack = curr == stack;
427             if (getPriority(curr) <= getPriority(stack) && !sameStack) {
428                 return i;
429             }
430         }
431         return 0;
432     }
433 
434     /**
435      * When stack is added or repositioned, find a proper position for it.
436      *
437      * The order is defined as:
438      *  - Dream is on top of everything
439      *  - PiP is directly below the Dream
440      *  - always-on-top stacks are directly below PiP; new always-on-top stacks are added above
441      *    existing ones
442      *  - other non-always-on-top stacks come directly below always-on-top stacks; new
443      *    non-always-on-top stacks are added directly below always-on-top stacks and above existing
444      *    non-always-on-top stacks
445      *  - if {@link #mAssistantOnTopOfDream} is enabled, then Assistant is on top of everything
446      *    (including the Dream); otherwise, it is a normal non-always-on-top stack
447      *
448      * @param requestedPosition Position requested by caller.
449      * @param stack Stack to be added or positioned.
450      * @param adding Flag indicates whether we're adding a new stack or positioning an existing.
451      * @return The proper position for the stack.
452      */
findPositionForStack(int requestedPosition, ActivityStack stack, boolean adding)453     private int findPositionForStack(int requestedPosition, ActivityStack stack, boolean adding) {
454         // The max possible position we can insert the stack at.
455         int maxPosition = findMaxPositionForStack(stack);
456         // The min possible position we can insert the stack at.
457         int minPosition = findMinPositionForStack(stack);
458 
459         // Cap the requested position to something reasonable for the previous position check
460         // below.
461         if (requestedPosition == POSITION_TOP) {
462             requestedPosition = mChildren.size();
463         } else if (requestedPosition == POSITION_BOTTOM) {
464             requestedPosition = 0;
465         }
466 
467         int targetPosition = requestedPosition;
468         targetPosition = Math.min(targetPosition, maxPosition);
469         targetPosition = Math.max(targetPosition, minPosition);
470 
471         int prevPosition = mChildren.indexOf(stack);
472         // The positions we calculated above (maxPosition, minPosition) do not take into
473         // consideration the following edge cases.
474         // 1) We need to adjust the position depending on the value "adding".
475         // 2) When we are moving a stack to another position, we also need to adjust the
476         //    position depending on whether the stack is moving to a higher or lower position.
477         if ((targetPosition != requestedPosition) && (adding || targetPosition < prevPosition)) {
478             targetPosition++;
479         }
480 
481         return targetPosition;
482     }
483 
484     @Override
forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)485     boolean forAllWindows(ToBooleanFunction<WindowState> callback,
486             boolean traverseTopToBottom) {
487         if (traverseTopToBottom) {
488             if (super.forAllWindows(callback, traverseTopToBottom)) {
489                 return true;
490             }
491             if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
492                 return true;
493             }
494         } else {
495             if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) {
496                 return true;
497             }
498             if (super.forAllWindows(callback, traverseTopToBottom)) {
499                 return true;
500             }
501         }
502         return false;
503     }
504 
forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)505     private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback,
506             boolean traverseTopToBottom) {
507         // For legacy reasons we process the TaskStack.mExitingActivities first here before the
508         // app tokens.
509         // TODO: Investigate if we need to continue to do this or if we can just process them
510         // in-order.
511         if (traverseTopToBottom) {
512             for (int i = mChildren.size() - 1; i >= 0; --i) {
513                 final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
514                 for (int j = activities.size() - 1; j >= 0; --j) {
515                     if (activities.get(j).forAllWindowsUnchecked(callback,
516                             traverseTopToBottom)) {
517                         return true;
518                     }
519                 }
520             }
521         } else {
522             final int count = mChildren.size();
523             for (int i = 0; i < count; ++i) {
524                 final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
525                 final int appTokensCount = activities.size();
526                 for (int j = 0; j < appTokensCount; j++) {
527                     if (activities.get(j).forAllWindowsUnchecked(callback,
528                             traverseTopToBottom)) {
529                         return true;
530                     }
531                 }
532             }
533         }
534         return false;
535     }
536 
setExitingTokensHasVisible(boolean hasVisible)537     void setExitingTokensHasVisible(boolean hasVisible) {
538         for (int i = mChildren.size() - 1; i >= 0; --i) {
539             final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
540             for (int j = activities.size() - 1; j >= 0; --j) {
541                 activities.get(j).hasVisible = hasVisible;
542             }
543         }
544     }
545 
removeExistingAppTokensIfPossible()546     void removeExistingAppTokensIfPossible() {
547         for (int i = mChildren.size() - 1; i >= 0; --i) {
548             final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities;
549             for (int j = activities.size() - 1; j >= 0; --j) {
550                 final ActivityRecord activity = activities.get(j);
551                 if (!activity.hasVisible && !mDisplayContent.mClosingApps.contains(activity)
552                         && (!activity.mIsExiting || activity.isEmpty())) {
553                     // Make sure there is no animation running on this activity, so any windows
554                     // associated with it will be removed as soon as their animations are
555                     // complete.
556                     cancelAnimation();
557                     ProtoLog.v(WM_DEBUG_ADD_REMOVE,
558                             "performLayout: Activity exiting now removed %s", activity);
559                     activity.removeIfPossible();
560                 }
561             }
562         }
563     }
564 
565     @Override
getOrientation(int candidate)566     int getOrientation(int candidate) {
567         if (isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) {
568             // Apps and their containers are not allowed to specify an orientation while using
569             // root tasks...except for the home stack if it is not resizable and currently
570             // visible (top of) its root task.
571             if (mRootHomeTask != null && !mRootHomeTask.isResizeable()) {
572                 // Manually nest one-level because because getOrientation() checks fillsParent()
573                 // which checks that requestedOverrideBounds() is empty. However, in this case,
574                 // it is not empty because it's been overridden to maintain the fullscreen size
575                 // within a smaller split-root.
576                 final Task topHomeTask = mRootHomeTask.getTopMostTask();
577                 final ActivityRecord topHomeActivity = topHomeTask.getTopNonFinishingActivity();
578                 // If a home activity is in the process of launching and isn't yet visible we
579                 // should still respect the stack's preferred orientation to ensure rotation occurs
580                 // before the home activity finishes launching.
581                 final boolean isHomeActivityLaunching = topHomeActivity != null
582                         && topHomeActivity.mVisibleRequested;
583                 if (topHomeTask.isVisible() || isHomeActivityLaunching) {
584                     final int orientation = topHomeTask.getOrientation();
585                     if (orientation != SCREEN_ORIENTATION_UNSET) {
586                         return orientation;
587                     }
588                 }
589             }
590             return SCREEN_ORIENTATION_UNSPECIFIED;
591         }
592 
593         final int orientation = super.getOrientation(candidate);
594         if (orientation != SCREEN_ORIENTATION_UNSET
595                 && orientation != SCREEN_ORIENTATION_BEHIND) {
596             ProtoLog.v(WM_DEBUG_ORIENTATION,
597                     "App is requesting an orientation, return %d for display id=%d",
598                     orientation, mDisplayContent.mDisplayId);
599             return orientation;
600         }
601 
602         ProtoLog.v(WM_DEBUG_ORIENTATION,
603                 "No app is requesting an orientation, return %d for display id=%d",
604                 mDisplayContent.getLastOrientation(), mDisplayContent.mDisplayId);
605         // The next app has not been requested to be visible, so we keep the current orientation
606         // to prevent freezing/unfreezing the display too early.
607         return mDisplayContent.getLastOrientation();
608     }
609 
610     @Override
assignChildLayers(SurfaceControl.Transaction t)611     void assignChildLayers(SurfaceControl.Transaction t) {
612         assignStackOrdering(t);
613 
614         for (int i = 0; i < mChildren.size(); i++) {
615             final ActivityStack s = mChildren.get(i);
616             s.assignChildLayers(t);
617         }
618     }
619 
assignStackOrdering(SurfaceControl.Transaction t)620     void assignStackOrdering(SurfaceControl.Transaction t) {
621         if (getParent() == null) {
622             return;
623         }
624         mTmpAlwaysOnTopStacks.clear();
625         mTmpHomeStacks.clear();
626         mTmpNormalStacks.clear();
627         for (int i = 0; i < mChildren.size(); ++i) {
628             final ActivityStack s = mChildren.get(i);
629             if (s.isAlwaysOnTop()) {
630                 mTmpAlwaysOnTopStacks.add(s);
631             } else if (s.isActivityTypeHome()) {
632                 mTmpHomeStacks.add(s);
633             } else {
634                 mTmpNormalStacks.add(s);
635             }
636         }
637 
638         int layer = 0;
639         // Place home stacks to the bottom.
640         layer = adjustRootTaskLayer(t, mTmpHomeStacks, layer, false /* normalStacks */);
641         // The home animation layer is between the home stacks and the normal stacks.
642         final int layerForHomeAnimationLayer = layer++;
643         mTmpLayerForSplitScreenDividerAnchor = layer++;
644         mTmpLayerForAnimationLayer = layer++;
645         layer = adjustRootTaskLayer(t, mTmpNormalStacks, layer, true /* normalStacks */);
646 
647         // The boosted animation layer is between the normal stacks and the always on top
648         // stacks.
649         final int layerForBoostedAnimationLayer = layer++;
650         adjustRootTaskLayer(t, mTmpAlwaysOnTopStacks, layer, false /* normalStacks */);
651 
652         t.setLayer(mHomeAppAnimationLayer, layerForHomeAnimationLayer);
653         t.setLayer(mAppAnimationLayer, mTmpLayerForAnimationLayer);
654         t.setLayer(mSplitScreenDividerAnchor, mTmpLayerForSplitScreenDividerAnchor);
655         t.setLayer(mBoostedAppAnimationLayer, layerForBoostedAnimationLayer);
656     }
657 
adjustNormalStackLayer(ActivityStack s, int layer)658     private int adjustNormalStackLayer(ActivityStack s, int layer) {
659         if (s.inSplitScreenWindowingMode()) {
660             // The split screen divider anchor is located above the split screen window.
661             mTmpLayerForSplitScreenDividerAnchor = layer++;
662         }
663         if (s.isTaskAnimating() || s.isAppTransitioning()) {
664             // The animation layer is located above the highest animating stack and no
665             // higher.
666             mTmpLayerForAnimationLayer = layer++;
667         }
668         return layer;
669     }
670 
671     /**
672      * Adjusts the layer of the stack which belongs to the same group.
673      * Note that there are three stack groups: home stacks, always on top stacks, and normal stacks.
674      *
675      * @param startLayer The beginning layer of this group of stacks.
676      * @param normalStacks Set {@code true} if this group is neither home nor always on top.
677      * @return The adjusted layer value.
678      */
adjustRootTaskLayer(SurfaceControl.Transaction t, ArrayList<ActivityStack> stacks, int startLayer, boolean normalStacks)679     private int adjustRootTaskLayer(SurfaceControl.Transaction t, ArrayList<ActivityStack> stacks,
680             int startLayer, boolean normalStacks) {
681         mTmpNeedsZBoostIndexes.clear();
682         final int stackSize = stacks.size();
683         for (int i = 0; i < stackSize; i++) {
684             final ActivityStack stack = stacks.get(i);
685             if (!stack.needsZBoost()) {
686                 stack.assignLayer(t, startLayer++);
687                 if (normalStacks) {
688                     startLayer = adjustNormalStackLayer(stack, startLayer);
689                 }
690             } else {
691                 mTmpNeedsZBoostIndexes.add(i);
692             }
693         }
694 
695         final int zBoostSize = mTmpNeedsZBoostIndexes.size();
696         for (int i = 0; i < zBoostSize; i++) {
697             final ActivityStack stack = stacks.get(mTmpNeedsZBoostIndexes.get(i));
698             stack.assignLayer(t, startLayer++);
699             if (normalStacks) {
700                 startLayer = adjustNormalStackLayer(stack, startLayer);
701             }
702         }
703         return startLayer;
704     }
705 
706     @Override
getAppAnimationLayer(@nimationLayer int animationLayer)707     SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
708         switch (animationLayer) {
709             case ANIMATION_LAYER_BOOSTED:
710                 return mBoostedAppAnimationLayer;
711             case ANIMATION_LAYER_HOME:
712                 return mHomeAppAnimationLayer;
713             case ANIMATION_LAYER_STANDARD:
714             default:
715                 return mAppAnimationLayer;
716         }
717     }
718 
getSplitScreenDividerAnchor()719     SurfaceControl getSplitScreenDividerAnchor() {
720         return mSplitScreenDividerAnchor;
721     }
722 
723     @Override
onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent)724     void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
725         if (getParent() != null) {
726             super.onParentChanged(newParent, oldParent, () -> {
727                 mAppAnimationLayer = makeChildSurface(null)
728                         .setName("animationLayer")
729                         .setCallsite("TaskDisplayArea.onParentChanged")
730                         .build();
731                 mBoostedAppAnimationLayer = makeChildSurface(null)
732                         .setName("boostedAnimationLayer")
733                         .setCallsite("TaskDisplayArea.onParentChanged")
734                         .build();
735                 mHomeAppAnimationLayer = makeChildSurface(null)
736                         .setName("homeAnimationLayer")
737                         .setCallsite("TaskDisplayArea.onParentChanged")
738                         .build();
739                 mSplitScreenDividerAnchor = makeChildSurface(null)
740                         .setName("splitScreenDividerAnchor")
741                         .setCallsite("TaskDisplayArea.onParentChanged")
742                         .build();
743                 getSyncTransaction()
744                         .show(mAppAnimationLayer)
745                         .show(mBoostedAppAnimationLayer)
746                         .show(mHomeAppAnimationLayer)
747                         .show(mSplitScreenDividerAnchor);
748             });
749         } else {
750             super.onParentChanged(newParent, oldParent);
751             mWmService.mTransactionFactory.get()
752                     .remove(mAppAnimationLayer)
753                     .remove(mBoostedAppAnimationLayer)
754                     .remove(mHomeAppAnimationLayer)
755                     .remove(mSplitScreenDividerAnchor)
756                     .apply();
757             mAppAnimationLayer = null;
758             mBoostedAppAnimationLayer = null;
759             mHomeAppAnimationLayer = null;
760             mSplitScreenDividerAnchor = null;
761         }
762     }
763 
onStackRemoved(ActivityStack stack)764     void onStackRemoved(ActivityStack stack) {
765         if (ActivityTaskManagerDebugConfig.DEBUG_STACK) {
766             Slog.v(TAG_STACK, "removeStack: detaching " + stack + " from displayId="
767                     + mDisplayContent.mDisplayId);
768         }
769         if (mPreferredTopFocusableStack == stack) {
770             mPreferredTopFocusableStack = null;
771         }
772         mDisplayContent.releaseSelfIfNeeded();
773         onStackOrderChanged(stack);
774     }
775 
resetPreferredTopFocusableStackIfBelow(Task task)776     void resetPreferredTopFocusableStackIfBelow(Task task) {
777         if (mPreferredTopFocusableStack != null
778                 && mPreferredTopFocusableStack.compareTo(task) < 0) {
779             mPreferredTopFocusableStack = null;
780         }
781     }
782 
positionStackAt(int position, ActivityStack child, boolean includingParents)783     void positionStackAt(int position, ActivityStack child, boolean includingParents) {
784         positionChildAt(position, child, includingParents);
785         mDisplayContent.layoutAndAssignWindowLayersIfNeeded();
786     }
787 
positionStackAtTop(ActivityStack stack, boolean includingParents)788     void positionStackAtTop(ActivityStack stack, boolean includingParents) {
789         positionStackAtTop(stack, includingParents, null /* updateLastFocusedStackReason */);
790     }
791 
positionStackAtTop(ActivityStack stack, boolean includingParents, String updateLastFocusedStackReason)792     void positionStackAtTop(ActivityStack stack, boolean includingParents,
793             String updateLastFocusedStackReason) {
794         positionStackAt(stack, getStackCount(), includingParents,
795                 updateLastFocusedStackReason);
796     }
797 
positionStackAtBottom(ActivityStack stack)798     void positionStackAtBottom(ActivityStack stack) {
799         positionStackAtBottom(stack, null /* updateLastFocusedStackReason */);
800     }
801 
positionStackAtBottom(ActivityStack stack, String updateLastFocusedStackReason)802     void positionStackAtBottom(ActivityStack stack, String updateLastFocusedStackReason) {
803         positionStackAt(stack, 0, false /* includingParents */,
804                 updateLastFocusedStackReason);
805     }
806 
positionStackAt(ActivityStack stack, int position)807     void positionStackAt(ActivityStack stack, int position) {
808         positionStackAt(stack, position, false /* includingParents */,
809                 null /* updateLastFocusedStackReason */);
810     }
811 
positionStackAt(ActivityStack stack, int position, boolean includingParents, String updateLastFocusedStackReason)812     void positionStackAt(ActivityStack stack, int position, boolean includingParents,
813             String updateLastFocusedStackReason) {
814         // TODO: Keep in sync with WindowContainer.positionChildAt(), once we change that to adjust
815         //       the position internally, also update the logic here
816         final ActivityStack prevFocusedStack = updateLastFocusedStackReason != null
817                 ? getFocusedStack() : null;
818         final boolean wasContained = mChildren.contains(stack);
819         if (mDisplayContent.mSingleTaskInstance && getStackCount() == 1 && !wasContained) {
820             throw new IllegalStateException(
821                     "positionStackAt: Can only have one task on display=" + this);
822         }
823 
824         // Since positionChildAt() is called during the creation process of pinned stacks,
825         // ActivityStack#getStack() can be null.
826         positionStackAt(position, stack, includingParents);
827 
828         if (updateLastFocusedStackReason != null) {
829             final ActivityStack currentFocusedStack = getFocusedStack();
830             if (currentFocusedStack != prevFocusedStack) {
831                 mLastFocusedStack = prevFocusedStack;
832                 EventLogTags.writeWmFocusedStack(mRootWindowContainer.mCurrentUser,
833                         mDisplayContent.mDisplayId,
834                         currentFocusedStack == null ? -1 : currentFocusedStack.getRootTaskId(),
835                         mLastFocusedStack == null ? -1 : mLastFocusedStack.getRootTaskId(),
836                         updateLastFocusedStackReason);
837             }
838         }
839 
840         onStackOrderChanged(stack);
841     }
842 
843     /**
844      * Moves/reparents `task` to the back of whatever container the home stack is in. This is for
845      * when we just want to move a task to "the back" vs. a specific place. The primary use-case
846      * is to make sure that moved-to-back apps go into secondary split when in split-screen mode.
847      */
positionTaskBehindHome(ActivityStack task)848     void positionTaskBehindHome(ActivityStack task) {
849         final ActivityStack home = getOrCreateRootHomeTask();
850         final WindowContainer homeParent = home.getParent();
851         final Task homeParentTask = homeParent != null ? homeParent.asTask() : null;
852         if (homeParentTask == null) {
853             // reparent throws if parent didn't change...
854             if (task.getParent() == this) {
855                 positionStackAtBottom(task);
856             } else {
857                 task.reparent(this, false /* onTop */);
858             }
859         } else if (homeParentTask == task.getParent()) {
860             // Apparently reparent early-outs if same stack, so we have to explicitly reorder.
861             ((ActivityStack) homeParentTask).positionChildAtBottom(task);
862         } else {
863             task.reparent((ActivityStack) homeParentTask, false /* toTop */,
864                     Task.REPARENT_LEAVE_STACK_IN_PLACE, false /* animate */,
865                     false /* deferResume */, "positionTaskBehindHome");
866         }
867     }
868 
getStack(int rootTaskId)869     ActivityStack getStack(int rootTaskId) {
870         for (int i = getStackCount() - 1; i >= 0; --i) {
871             final ActivityStack stack = getStackAt(i);
872             if (stack.getRootTaskId() == rootTaskId) {
873                 return stack;
874             }
875         }
876         return null;
877     }
878 
879     /**
880      * Returns an existing stack compatible with the windowing mode and activity type or creates one
881      * if a compatible stack doesn't exist.
882      * @see #getOrCreateStack(int, int, boolean, Intent, Task)
883      */
getOrCreateStack(int windowingMode, int activityType, boolean onTop)884     ActivityStack getOrCreateStack(int windowingMode, int activityType, boolean onTop) {
885         return getOrCreateStack(windowingMode, activityType, onTop, null /* intent */,
886                 null /* candidateTask */);
887     }
888 
889     /**
890      * When two level tasks are required for given windowing mode and activity type, returns an
891      * existing compatible root task or creates a new one.
892      * For one level task, the candidate task would be reused to also be the root task or create
893      * a new root task if no candidate task.
894      * @see #getStack(int, int)
895      * @see #createStack(int, int, boolean)
896      */
getOrCreateStack(int windowingMode, int activityType, boolean onTop, Intent intent, Task candidateTask)897     ActivityStack getOrCreateStack(int windowingMode, int activityType, boolean onTop,
898             Intent intent, Task candidateTask) {
899         // Need to pass in a determined windowing mode to see if a new stack should be created,
900         // so use its parent's windowing mode if it is undefined.
901         if (!alwaysCreateStack(
902                 windowingMode != WINDOWING_MODE_UNDEFINED ? windowingMode : getWindowingMode(),
903                 activityType)) {
904             ActivityStack stack = getStack(windowingMode, activityType);
905             if (stack != null) {
906                 return stack;
907             }
908         } else if (candidateTask != null) {
909             final ActivityStack stack = (ActivityStack) candidateTask;
910             final int position = onTop ? POSITION_TOP : POSITION_BOTTOM;
911             Task launchRootTask = updateLaunchRootTask(windowingMode);
912 
913             if (launchRootTask != null) {
914                 if (stack.getParent() == null) {
915                     launchRootTask.addChild(stack, position);
916                 } else if (stack.getParent() != launchRootTask) {
917                     stack.reparent(launchRootTask, position);
918                 }
919             } else if (stack.getDisplayArea() != this || !stack.isRootTask()) {
920                 if (stack.getParent() == null) {
921                     addChild(stack, position);
922                 } else {
923                     stack.reparent(this, onTop);
924                 }
925             }
926             // Update windowing mode if necessary, e.g. moving a pinned task to fullscreen.
927             if (candidateTask.getWindowingMode() != windowingMode) {
928                 candidateTask.setWindowingMode(windowingMode);
929             }
930             return stack;
931         }
932         return createStack(windowingMode, activityType, onTop, null /*info*/, intent,
933                 false /* createdByOrganizer */);
934     }
935 
936     /**
937      * Returns an existing stack compatible with the input params or creates one
938      * if a compatible stack doesn't exist.
939      * @see #getOrCreateStack(int, int, boolean)
940      */
getOrCreateStack(@ullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable Task candidateTask, int activityType, boolean onTop)941     ActivityStack getOrCreateStack(@Nullable ActivityRecord r,
942             @Nullable ActivityOptions options, @Nullable Task candidateTask, int activityType,
943             boolean onTop) {
944         // First preference is the windowing mode in the activity options if set.
945         int windowingMode = (options != null)
946                 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
947         // Validate that our desired windowingMode will work under the current conditions.
948         // UNDEFINED windowing mode is a valid result and means that the new stack will inherit
949         // it's display's windowing mode.
950         windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType);
951         return getOrCreateStack(windowingMode, activityType, onTop, null /* intent */,
952                 candidateTask);
953     }
954 
955     @VisibleForTesting
getNextStackId()956     int getNextStackId() {
957         return mAtmService.mStackSupervisor.getNextTaskIdForUser();
958     }
959 
createStack(int windowingMode, int activityType, boolean onTop)960     ActivityStack createStack(int windowingMode, int activityType, boolean onTop) {
961         return createStack(windowingMode, activityType, onTop, null /* info */, null /* intent */,
962                 false /* createdByOrganizer */);
963     }
964 
965     /**
966      * Creates a stack matching the input windowing mode and activity type on this display.
967      * @param windowingMode The windowing mode the stack should be created in. If
968      *                      {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will
969      *                      inherit its parent's windowing mode.
970      * @param activityType The activityType the stack should be created in. If
971      *                     {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will
972      *                     be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
973      * @param onTop If true the stack will be created at the top of the display, else at the bottom.
974      * @param info The started activity info.
975      * @param intent The intent that started this task.
976      * @param createdByOrganizer @{code true} if this is created by task organizer, @{code false}
977      *                          otherwise.
978      * @return The newly created stack.
979      */
createStack(int windowingMode, int activityType, boolean onTop, ActivityInfo info, Intent intent, boolean createdByOrganizer)980     ActivityStack createStack(int windowingMode, int activityType, boolean onTop, ActivityInfo info,
981             Intent intent, boolean createdByOrganizer) {
982         if (mDisplayContent.mSingleTaskInstance && getStackCount() > 0) {
983             // Create stack on default display instead since this display can only contain 1 stack.
984             // TODO: Kinda a hack, but better that having the decision at each call point. Hoping
985             // this goes away once ActivityView is no longer using virtual displays.
986             return mRootWindowContainer.getDefaultTaskDisplayArea().createStack(
987                     windowingMode, activityType, onTop, info, intent, createdByOrganizer);
988         }
989 
990         if (activityType == ACTIVITY_TYPE_UNDEFINED && !createdByOrganizer) {
991             // Can't have an undefined stack type yet...so re-map to standard. Anyone that wants
992             // anything else should be passing it in anyways...except for the task organizer.
993             activityType = ACTIVITY_TYPE_STANDARD;
994         }
995 
996         if (activityType != ACTIVITY_TYPE_STANDARD && activityType != ACTIVITY_TYPE_UNDEFINED) {
997             // For now there can be only one stack of a particular non-standard activity type on a
998             // display. So, get that ignoring whatever windowing mode it is currently in.
999             ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
1000             if (stack != null) {
1001                 throw new IllegalArgumentException("Stack=" + stack + " of activityType="
1002                         + activityType + " already on display=" + this + ". Can't have multiple.");
1003             }
1004         }
1005 
1006         if (!isWindowingModeSupported(windowingMode, mAtmService.mSupportsMultiWindow,
1007                 mAtmService.mSupportsSplitScreenMultiWindow,
1008                 mAtmService.mSupportsFreeformWindowManagement,
1009                 mAtmService.mSupportsPictureInPicture, activityType)) {
1010             throw new IllegalArgumentException("Can't create stack for unsupported windowingMode="
1011                     + windowingMode);
1012         }
1013 
1014         if (windowingMode == WINDOWING_MODE_PINNED && getRootPinnedTask() != null) {
1015             // Only 1 stack can be PINNED at a time, so dismiss the existing one
1016             getRootPinnedTask().dismissPip();
1017         }
1018 
1019         final int stackId = getNextStackId();
1020         return createStackUnchecked(windowingMode, activityType, stackId, onTop, info, intent,
1021                 createdByOrganizer);
1022     }
1023 
1024     /** @return the root task to create the next task in. */
updateLaunchRootTask(int windowingMode)1025     private Task updateLaunchRootTask(int windowingMode) {
1026         if (!isSplitScreenWindowingMode(windowingMode)) {
1027             // Only split-screen windowing modes can do this currently...
1028             return null;
1029         }
1030         for (int i = getStackCount() - 1; i >= 0; --i) {
1031             final Task t = getStackAt(i);
1032             if (!t.mCreatedByOrganizer || t.getRequestedOverrideWindowingMode() != windowingMode) {
1033                 continue;
1034             }
1035             // If not already set, pick a launch root which is not the one we are launching into.
1036             if (mLaunchRootTask == null) {
1037                 for (int j = 0, n = getStackCount(); j < n; ++j) {
1038                     final Task tt = getStackAt(j);
1039                     if (tt.mCreatedByOrganizer && tt != t) {
1040                         mLaunchRootTask = tt;
1041                         break;
1042                     }
1043                 }
1044             }
1045             return t;
1046         }
1047         return mLaunchRootTask;
1048     }
1049 
1050     @VisibleForTesting
createStackUnchecked(int windowingMode, int activityType, int stackId, boolean onTop, ActivityInfo info, Intent intent, boolean createdByOrganizer)1051     ActivityStack createStackUnchecked(int windowingMode, int activityType, int stackId,
1052             boolean onTop, ActivityInfo info, Intent intent, boolean createdByOrganizer) {
1053         if (windowingMode == WINDOWING_MODE_PINNED && activityType != ACTIVITY_TYPE_STANDARD) {
1054             throw new IllegalArgumentException("Stack with windowing mode cannot with non standard "
1055                     + "activity type.");
1056         }
1057         if (info == null) {
1058             info = new ActivityInfo();
1059             info.applicationInfo = new ApplicationInfo();
1060         }
1061 
1062         // Task created by organizer are added as root.
1063         Task launchRootTask = createdByOrganizer ? null : updateLaunchRootTask(windowingMode);
1064         if (launchRootTask != null) {
1065             // Since this stack will be put into a root task, its windowingMode will be inherited.
1066             windowingMode = WINDOWING_MODE_UNDEFINED;
1067         }
1068 
1069         final ActivityStack stack = new ActivityStack(mAtmService, stackId, activityType,
1070                 info, intent, createdByOrganizer);
1071         if (launchRootTask != null) {
1072             launchRootTask.addChild(stack, onTop ? POSITION_TOP : POSITION_BOTTOM);
1073             if (onTop) {
1074                 positionStackAtTop((ActivityStack) launchRootTask, false /* includingParents */);
1075             }
1076         } else {
1077             addChild(stack, onTop ? POSITION_TOP : POSITION_BOTTOM);
1078             stack.setWindowingMode(windowingMode, true /* creating */);
1079         }
1080         return stack;
1081     }
1082 
1083     /**
1084      * Get the preferred focusable stack in priority. If the preferred stack does not exist, find a
1085      * focusable and visible stack from the top of stacks in this display.
1086      */
getFocusedStack()1087     ActivityStack getFocusedStack() {
1088         if (mPreferredTopFocusableStack != null) {
1089             return mPreferredTopFocusableStack;
1090         }
1091 
1092         for (int i = getStackCount() - 1; i >= 0; --i) {
1093             final ActivityStack stack = getStackAt(i);
1094             if (stack.isFocusableAndVisible()) {
1095                 return stack;
1096             }
1097         }
1098 
1099         return null;
1100     }
1101 
getNextFocusableStack(ActivityStack currentFocus, boolean ignoreCurrent)1102     ActivityStack getNextFocusableStack(ActivityStack currentFocus, boolean ignoreCurrent) {
1103         final int currentWindowingMode = currentFocus != null
1104                 ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
1105 
1106         ActivityStack candidate = null;
1107         for (int i = getStackCount() - 1; i >= 0; --i) {
1108             final ActivityStack stack = getStackAt(i);
1109             if (ignoreCurrent && stack == currentFocus) {
1110                 continue;
1111             }
1112             if (!stack.isFocusableAndVisible()) {
1113                 continue;
1114             }
1115 
1116             if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
1117                     && candidate == null && stack.inSplitScreenPrimaryWindowingMode()) {
1118                 // If the currently focused stack is in split-screen secondary we save off the
1119                 // top primary split-screen stack as a candidate for focus because we might
1120                 // prefer focus to move to an other stack to avoid primary split-screen stack
1121                 // overlapping with a fullscreen stack when a fullscreen stack is higher in z
1122                 // than the next split-screen stack. Assistant stack, I am looking at you...
1123                 // We only move the focus to the primary-split screen stack if there isn't a
1124                 // better alternative.
1125                 candidate = stack;
1126                 continue;
1127             }
1128             if (candidate != null && stack.inSplitScreenSecondaryWindowingMode()) {
1129                 // Use the candidate stack since we are now at the secondary split-screen.
1130                 return candidate;
1131             }
1132             return stack;
1133         }
1134         return candidate;
1135     }
1136 
getFocusedActivity()1137     ActivityRecord getFocusedActivity() {
1138         final ActivityStack focusedStack = getFocusedStack();
1139         if (focusedStack == null) {
1140             return null;
1141         }
1142         // TODO(b/111541062): Move this into ActivityStack#getResumedActivity()
1143         // Check if the focused stack has the resumed activity
1144         ActivityRecord resumedActivity = focusedStack.getResumedActivity();
1145         if (resumedActivity == null || resumedActivity.app == null) {
1146             // If there is no registered resumed activity in the stack or it is not running -
1147             // try to use previously resumed one.
1148             resumedActivity = focusedStack.mPausingActivity;
1149             if (resumedActivity == null || resumedActivity.app == null) {
1150                 // If previously resumed activity doesn't work either - find the topmost running
1151                 // activity that can be focused.
1152                 resumedActivity = focusedStack.topRunningActivity(true /* focusableOnly */);
1153             }
1154         }
1155         return resumedActivity;
1156     }
1157 
getLastFocusedStack()1158     ActivityStack getLastFocusedStack() {
1159         return mLastFocusedStack;
1160     }
1161 
allResumedActivitiesComplete()1162     boolean allResumedActivitiesComplete() {
1163         for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
1164             final ActivityRecord r = getStackAt(stackNdx).getResumedActivity();
1165             if (r != null && !r.isState(RESUMED)) {
1166                 return false;
1167             }
1168         }
1169         final ActivityStack currentFocusedStack = getFocusedStack();
1170         if (ActivityTaskManagerDebugConfig.DEBUG_STACK) {
1171             Slog.d(TAG_STACK, "allResumedActivitiesComplete: mLastFocusedStack changing from="
1172                     + mLastFocusedStack + " to=" + currentFocusedStack);
1173         }
1174         mLastFocusedStack = currentFocusedStack;
1175         return true;
1176     }
1177 
1178     /**
1179      * Pause all activities in either all of the stacks or just the back stacks. This is done before
1180      * resuming a new activity and to make sure that previously active activities are
1181      * paused in stacks that are no longer visible or in pinned windowing mode. This does not
1182      * pause activities in visible stacks, so if an activity is launched within the same stack/task,
1183      * then we should explicitly pause that stack's top activity.
1184      * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
1185      * @param resuming The resuming activity.
1186      * @return {@code true} if any activity was paused as a result of this call.
1187      */
pauseBackStacks(boolean userLeaving, ActivityRecord resuming)1188     boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming) {
1189         boolean someActivityPaused = false;
1190         for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
1191             final ActivityStack stack = getStackAt(stackNdx);
1192             final ActivityRecord resumedActivity = stack.getResumedActivity();
1193             if (resumedActivity != null
1194                     && (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
1195                     || !stack.isTopActivityFocusable())) {
1196                 if (DEBUG_STATES) {
1197                     Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack
1198                             + " mResumedActivity=" + resumedActivity);
1199                 }
1200                 someActivityPaused |= stack.startPausingLocked(userLeaving, false /* uiSleeping*/,
1201                         resuming);
1202             }
1203         }
1204         return someActivityPaused;
1205     }
1206 
1207     /**
1208      * Find task for putting the Activity in.
1209      */
findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplayArea, RootWindowContainer.FindTaskResult result)1210     void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplayArea,
1211             RootWindowContainer.FindTaskResult result) {
1212         mTmpFindTaskResult.clear();
1213         for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
1214             final ActivityStack stack = getStackAt(stackNdx);
1215             if (!r.hasCompatibleActivityType(stack) && stack.isLeafTask()) {
1216                 if (DEBUG_TASKS) {
1217                     Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) " + stack);
1218                 }
1219                 continue;
1220             }
1221 
1222             mTmpFindTaskResult.process(r, stack);
1223             // It is possible to have tasks in multiple stacks with the same root affinity, so
1224             // we should keep looking after finding an affinity match to see if there is a
1225             // better match in another stack. Also, task affinity isn't a good enough reason
1226             // to target a display which isn't the source of the intent, so skip any affinity
1227             // matches not on the specified display.
1228             if (mTmpFindTaskResult.mRecord != null) {
1229                 if (mTmpFindTaskResult.mIdealMatch) {
1230                     result.setTo(mTmpFindTaskResult);
1231                     return;
1232                 } else if (isPreferredDisplayArea) {
1233                     // Note: since the traversing through the stacks is top down, the floating
1234                     // tasks should always have lower priority than any affinity-matching tasks
1235                     // in the fullscreen stacks
1236                     result.setTo(mTmpFindTaskResult);
1237                 }
1238             }
1239         }
1240     }
1241 
1242     /**
1243      * Removes stacks in the input windowing modes from the system if they are of activity type
1244      * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
1245      */
removeStacksInWindowingModes(int... windowingModes)1246     void removeStacksInWindowingModes(int... windowingModes) {
1247         if (windowingModes == null || windowingModes.length == 0) {
1248             return;
1249         }
1250 
1251         // Collect the stacks that are necessary to be removed instead of performing the removal
1252         // by looping mStacks, so that we don't miss any stacks after the stack size changed or
1253         // stacks reordered.
1254         final ArrayList<ActivityStack> stacks = new ArrayList<>();
1255         for (int j = windowingModes.length - 1; j >= 0; --j) {
1256             final int windowingMode = windowingModes[j];
1257             for (int i = getStackCount() - 1; i >= 0; --i) {
1258                 final ActivityStack stack = getStackAt(i);
1259                 if (!stack.isActivityTypeStandardOrUndefined()) {
1260                     continue;
1261                 }
1262                 if (stack.getWindowingMode() != windowingMode) {
1263                     continue;
1264                 }
1265                 stacks.add(stack);
1266             }
1267         }
1268 
1269         for (int i = stacks.size() - 1; i >= 0; --i) {
1270             mRootWindowContainer.mStackSupervisor.removeStack(stacks.get(i));
1271         }
1272     }
1273 
removeStacksWithActivityTypes(int... activityTypes)1274     void removeStacksWithActivityTypes(int... activityTypes) {
1275         if (activityTypes == null || activityTypes.length == 0) {
1276             return;
1277         }
1278 
1279         // Collect the stacks that are necessary to be removed instead of performing the removal
1280         // by looping mStacks, so that we don't miss any stacks after the stack size changed or
1281         // stacks reordered.
1282         final ArrayList<ActivityStack> stacks = new ArrayList<>();
1283         for (int j = activityTypes.length - 1; j >= 0; --j) {
1284             final int activityType = activityTypes[j];
1285             for (int i = getStackCount() - 1; i >= 0; --i) {
1286                 final ActivityStack stack = getStackAt(i);
1287                 // Collect the root tasks that are currently being organized.
1288                 if (stack.mCreatedByOrganizer) {
1289                     for (int k = stack.getChildCount() - 1; k >= 0; --k) {
1290                         final ActivityStack childStack = (ActivityStack) stack.getChildAt(k);
1291                         if (childStack.getActivityType() == activityType) {
1292                             stacks.add(childStack);
1293                         }
1294                     }
1295                 } else if (stack.getActivityType() == activityType) {
1296                     stacks.add(stack);
1297                 }
1298             }
1299         }
1300 
1301         for (int i = stacks.size() - 1; i >= 0; --i) {
1302             mRootWindowContainer.mStackSupervisor.removeStack(stacks.get(i));
1303         }
1304     }
1305 
onSplitScreenModeDismissed()1306     void onSplitScreenModeDismissed() {
1307         onSplitScreenModeDismissed(null /* toTop */);
1308     }
1309 
onSplitScreenModeDismissed(ActivityStack toTop)1310     void onSplitScreenModeDismissed(ActivityStack toTop) {
1311         mAtmService.deferWindowLayout();
1312         try {
1313             mLaunchRootTask = null;
1314             moveSplitScreenTasksToFullScreen();
1315         } finally {
1316             final ActivityStack topFullscreenStack = toTop != null
1317                     ? toTop : getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN);
1318             final ActivityStack homeStack = getOrCreateRootHomeTask();
1319             if (homeStack != null && ((topFullscreenStack != null && !isTopStack(homeStack))
1320                     || toTop != null)) {
1321                 // Whenever split-screen is dismissed we want the home stack directly behind the
1322                 // current top fullscreen stack so it shows up when the top stack is finished.
1323                 // Or, if the caller specified a stack to be on top after split-screen is dismissed.
1324                 // TODO: Would be better to use ActivityDisplay.positionChildAt() for this, however
1325                 // ActivityDisplay doesn't have a direct controller to WM side yet. We can switch
1326                 // once we have that.
1327                 homeStack.moveToFront("onSplitScreenModeDismissed");
1328                 topFullscreenStack.moveToFront("onSplitScreenModeDismissed");
1329             }
1330             mAtmService.continueWindowLayout();
1331         }
1332     }
1333 
moveSplitScreenTasksToFullScreen()1334     private void moveSplitScreenTasksToFullScreen() {
1335         final WindowContainerTransaction wct = new WindowContainerTransaction();
1336         mTmpTasks.clear();
1337         forAllTasks(task -> {
1338             if (task.mCreatedByOrganizer && task.inSplitScreenWindowingMode() && task.hasChild()) {
1339                 mTmpTasks.add(task);
1340             }
1341         });
1342 
1343         for (int i = mTmpTasks.size() - 1; i >= 0; i--) {
1344             final Task root = mTmpTasks.get(i);
1345             for (int j = 0; j < root.getChildCount(); j++) {
1346                 wct.reparent(root.getChildAt(j).mRemoteToken.toWindowContainerToken(),
1347                         null, true /* toTop */);
1348             }
1349         }
1350         mAtmService.mWindowOrganizerController.applyTransaction(wct);
1351     }
1352 
1353     /**
1354      * Returns true if the {@param windowingMode} is supported based on other parameters passed in.
1355      * @param windowingMode The windowing mode we are checking support for.
1356      * @param supportsMultiWindow If we should consider support for multi-window mode in general.
1357      * @param supportsSplitScreen If we should consider support for split-screen multi-window.
1358      * @param supportsFreeform If we should consider support for freeform multi-window.
1359      * @param supportsPip If we should consider support for picture-in-picture mutli-window.
1360      * @param activityType The activity type under consideration.
1361      * @return true if the windowing mode is supported.
1362      */
isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow, boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip, int activityType)1363     private boolean isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow,
1364             boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip,
1365             int activityType) {
1366 
1367         if (windowingMode == WINDOWING_MODE_UNDEFINED
1368                 || windowingMode == WINDOWING_MODE_FULLSCREEN) {
1369             return true;
1370         }
1371         if (!supportsMultiWindow) {
1372             return false;
1373         }
1374 
1375         if (windowingMode == WINDOWING_MODE_MULTI_WINDOW) {
1376             return true;
1377         }
1378 
1379         if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
1380                 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
1381             return supportsSplitScreen
1382                     && WindowConfiguration.supportSplitScreenWindowingMode(activityType);
1383         }
1384 
1385         if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) {
1386             return false;
1387         }
1388 
1389         if (!supportsPip && windowingMode == WINDOWING_MODE_PINNED) {
1390             return false;
1391         }
1392         return true;
1393     }
1394 
1395     /**
1396      * Resolves the windowing mode that an {@link ActivityRecord} would be in if started on this
1397      * display with the provided parameters.
1398      *
1399      * @param r The ActivityRecord in question.
1400      * @param options Options to start with.
1401      * @param task The task within-which the activity would start.
1402      * @param activityType The type of activity to start.
1403      * @return The resolved (not UNDEFINED) windowing-mode that the activity would be in.
1404      */
resolveWindowingMode(@ullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable Task task, int activityType)1405     int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
1406             @Nullable Task task, int activityType) {
1407 
1408         // First preference if the windowing mode in the activity options if set.
1409         int windowingMode = (options != null)
1410                 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
1411 
1412         // If windowing mode is unset, then next preference is the candidate task, then the
1413         // activity record.
1414         if (windowingMode == WINDOWING_MODE_UNDEFINED) {
1415             if (task != null) {
1416                 windowingMode = task.getWindowingMode();
1417             }
1418             if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) {
1419                 windowingMode = r.getWindowingMode();
1420             }
1421             if (windowingMode == WINDOWING_MODE_UNDEFINED) {
1422                 // Use the display's windowing mode.
1423                 windowingMode = getWindowingMode();
1424             }
1425         }
1426         windowingMode = validateWindowingMode(windowingMode, r, task, activityType);
1427         return windowingMode != WINDOWING_MODE_UNDEFINED
1428                 ? windowingMode : WINDOWING_MODE_FULLSCREEN;
1429     }
1430 
1431     /**
1432      * Check if the requested windowing-mode is appropriate for the specified task and/or activity
1433      * on this display.
1434      *
1435      * @param windowingMode The windowing-mode to validate.
1436      * @param r The {@link ActivityRecord} to check against.
1437      * @param task The {@link Task} to check against.
1438      * @param activityType An activity type.
1439      * @return {@code true} if windowingMode is valid, {@code false} otherwise.
1440      */
isValidWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task, int activityType)1441     boolean isValidWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task,
1442             int activityType) {
1443         // Make sure the windowing mode we are trying to use makes sense for what is supported.
1444         boolean supportsMultiWindow = mAtmService.mSupportsMultiWindow;
1445         boolean supportsSplitScreen = mAtmService.mSupportsSplitScreenMultiWindow;
1446         boolean supportsFreeform = mAtmService.mSupportsFreeformWindowManagement;
1447         boolean supportsPip = mAtmService.mSupportsPictureInPicture;
1448         if (supportsMultiWindow) {
1449             if (task != null) {
1450                 supportsMultiWindow = task.isResizeable();
1451                 supportsSplitScreen = task.supportsSplitScreenWindowingMode();
1452                 // TODO: Do we need to check for freeform and Pip support here?
1453             } else if (r != null) {
1454                 supportsMultiWindow = r.isResizeable();
1455                 supportsSplitScreen = r.supportsSplitScreenWindowingMode();
1456                 supportsFreeform = r.supportsFreeform();
1457                 supportsPip = r.supportsPictureInPicture();
1458             }
1459         }
1460 
1461         return windowingMode != WINDOWING_MODE_UNDEFINED
1462                 && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen,
1463                         supportsFreeform, supportsPip, activityType);
1464     }
1465 
1466     /**
1467      * Check that the requested windowing-mode is appropriate for the specified task and/or activity
1468      * on this display.
1469      *
1470      * @param windowingMode The windowing-mode to validate.
1471      * @param r The {@link ActivityRecord} to check against.
1472      * @param task The {@link Task} to check against.
1473      * @param activityType An activity type.
1474      * @return The provided windowingMode or the closest valid mode which is appropriate.
1475      */
validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task, int activityType)1476     int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task,
1477             int activityType) {
1478         final boolean inSplitScreenMode = isSplitScreenModeActivated();
1479         if (!inSplitScreenMode && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
1480             // Switch to the display's windowing mode if we are not in split-screen mode and we are
1481             // trying to launch in split-screen secondary.
1482             windowingMode = WINDOWING_MODE_UNDEFINED;
1483         } else if (inSplitScreenMode && windowingMode == WINDOWING_MODE_UNDEFINED) {
1484             windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
1485         }
1486         if (!isValidWindowingMode(windowingMode, r, task, activityType)) {
1487             return WINDOWING_MODE_UNDEFINED;
1488         }
1489         return windowingMode;
1490     }
1491 
isTopStack(ActivityStack stack)1492     boolean isTopStack(ActivityStack stack) {
1493         return stack == getTopStack();
1494     }
1495 
isTopNotPinnedStack(ActivityStack stack)1496     boolean isTopNotPinnedStack(ActivityStack stack) {
1497         for (int i = getStackCount() - 1; i >= 0; --i) {
1498             final ActivityStack current = getStackAt(i);
1499             if (!current.inPinnedWindowingMode()) {
1500                 return current == stack;
1501             }
1502         }
1503         return false;
1504     }
1505 
topRunningActivity()1506     ActivityRecord topRunningActivity() {
1507         return topRunningActivity(false /* considerKeyguardState */);
1508     }
1509 
1510     /**
1511      * Returns the top running activity in the focused stack. In the case the focused stack has no
1512      * such activity, the next focusable stack on this display is returned.
1513      *
1514      * @param considerKeyguardState Indicates whether the locked state should be considered. if
1515      *                              {@code true} and the keyguard is locked, only activities that
1516      *                              can be shown on top of the keyguard will be considered.
1517      * @return The top running activity. {@code null} if none is available.
1518      */
topRunningActivity(boolean considerKeyguardState)1519     ActivityRecord topRunningActivity(boolean considerKeyguardState) {
1520         ActivityRecord topRunning = null;
1521         final ActivityStack focusedStack = getFocusedStack();
1522         if (focusedStack != null) {
1523             topRunning = focusedStack.topRunningActivity();
1524         }
1525 
1526         // Look in other focusable stacks.
1527         if (topRunning == null) {
1528             for (int i = getStackCount() - 1; i >= 0; --i) {
1529                 final ActivityStack stack = getStackAt(i);
1530                 // Only consider focusable stacks other than the current focused one.
1531                 if (stack == focusedStack || !stack.isTopActivityFocusable()) {
1532                     continue;
1533                 }
1534                 topRunning = stack.topRunningActivity();
1535                 if (topRunning != null) {
1536                     break;
1537                 }
1538             }
1539         }
1540 
1541         // This activity can be considered the top running activity if we are not considering
1542         // the locked state, the keyguard isn't locked, or we can show when locked.
1543         if (topRunning != null && considerKeyguardState
1544                 && mRootWindowContainer.mStackSupervisor.getKeyguardController()
1545                 .isKeyguardLocked()
1546                 && !topRunning.canShowWhenLocked()) {
1547             return null;
1548         }
1549 
1550         return topRunning;
1551     }
1552 
getStackCount()1553     protected int getStackCount() {
1554         return mChildren.size();
1555     }
1556 
getStackAt(int index)1557     protected ActivityStack getStackAt(int index) {
1558         return mChildren.get(index);
1559     }
1560 
1561     @Nullable
getOrCreateRootHomeTask()1562     ActivityStack getOrCreateRootHomeTask() {
1563         return getOrCreateRootHomeTask(false /* onTop */);
1564     }
1565 
1566     /**
1567      * Returns the existing home stack or creates and returns a new one if it should exist for the
1568      * display.
1569      * @param onTop Only be used when there is no existing home stack. If true the home stack will
1570      *              be created at the top of the display, else at the bottom.
1571      */
1572     @Nullable
getOrCreateRootHomeTask(boolean onTop)1573     ActivityStack getOrCreateRootHomeTask(boolean onTop) {
1574         ActivityStack homeTask = getRootHomeTask();
1575         if (homeTask == null && mDisplayContent.supportsSystemDecorations()) {
1576             homeTask = createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, onTop);
1577         }
1578         return homeTask;
1579     }
1580 
isSplitScreenModeActivated()1581     boolean isSplitScreenModeActivated() {
1582         Task task = getRootSplitScreenPrimaryTask();
1583         return task != null && task.hasChild();
1584     }
1585 
1586     /**
1587      * Returns the topmost stack on the display that is compatible with the input windowing mode.
1588      * Null is no compatible stack on the display.
1589      */
getTopStackInWindowingMode(int windowingMode)1590     ActivityStack getTopStackInWindowingMode(int windowingMode) {
1591         return getStack(windowingMode, ACTIVITY_TYPE_UNDEFINED);
1592     }
1593 
moveHomeStackToFront(String reason)1594     void moveHomeStackToFront(String reason) {
1595         final ActivityStack homeStack = getOrCreateRootHomeTask();
1596         if (homeStack != null) {
1597             homeStack.moveToFront(reason);
1598         }
1599     }
1600 
1601     /**
1602      * Moves the focusable home activity to top. If there is no such activity, the home stack will
1603      * still move to top.
1604      */
moveHomeActivityToTop(String reason)1605     void moveHomeActivityToTop(String reason) {
1606         final ActivityRecord top = getHomeActivity();
1607         if (top == null) {
1608             moveHomeStackToFront(reason);
1609             return;
1610         }
1611         top.moveFocusableActivityToTop(reason);
1612     }
1613 
1614     @Nullable
getHomeActivity()1615     ActivityRecord getHomeActivity() {
1616         return getHomeActivityForUser(mRootWindowContainer.mCurrentUser);
1617     }
1618 
1619     @Nullable
getHomeActivityForUser(int userId)1620     ActivityRecord getHomeActivityForUser(int userId) {
1621         final ActivityStack homeStack = getRootHomeTask();
1622         if (homeStack == null) {
1623             return null;
1624         }
1625 
1626         final PooledPredicate p = PooledLambda.obtainPredicate(
1627                 TaskDisplayArea::isHomeActivityForUser, PooledLambda.__(ActivityRecord.class),
1628                 userId);
1629         final ActivityRecord r = homeStack.getActivity(p);
1630         p.recycle();
1631         return r;
1632     }
1633 
isHomeActivityForUser(ActivityRecord r, int userId)1634     private static boolean isHomeActivityForUser(ActivityRecord r, int userId) {
1635         return r.isActivityTypeHome() && (userId == UserHandle.USER_ALL || r.mUserId == userId);
1636     }
1637 
1638     /**
1639      * Adjusts the {@param stack} behind the last visible stack in the display if necessary.
1640      * Generally used in conjunction with {@link #moveStackBehindStack}.
1641      */
1642     // TODO(b/151575894): Remove special stack movement methods.
moveStackBehindBottomMostVisibleStack(ActivityStack stack)1643     void moveStackBehindBottomMostVisibleStack(ActivityStack stack) {
1644         if (stack.shouldBeVisible(null)) {
1645             // Skip if the stack is already visible
1646             return;
1647         }
1648 
1649         final boolean isRootTask = stack.isRootTask();
1650         if (isRootTask) {
1651             // Move the stack to the bottom to not affect the following visibility checks
1652             positionStackAtBottom(stack);
1653         } else {
1654             stack.getParent().positionChildAt(POSITION_BOTTOM, stack, false /* includingParents */);
1655         }
1656 
1657         // Find the next position where the stack should be placed
1658         final int numStacks = isRootTask ? getStackCount() : stack.getParent().getChildCount();
1659         for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
1660             final ActivityStack s = isRootTask ? getStackAt(stackNdx)
1661                     : (ActivityStack) stack.getParent().getChildAt(stackNdx);
1662             if (s == stack) {
1663                 continue;
1664             }
1665             final int winMode = s.getWindowingMode();
1666             final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN
1667                     || winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
1668             if (s.shouldBeVisible(null) && isValidWindowingMode) {
1669                 // Move the provided stack to behind this stack
1670                 final int position = Math.max(0, stackNdx - 1);
1671                 if (isRootTask) {
1672                     positionStackAt(stack, position);
1673                 } else {
1674                     stack.getParent().positionChildAt(position, stack, false /*includingParents */);
1675                 }
1676                 break;
1677             }
1678         }
1679     }
1680 
1681     /**
1682      * Moves the {@param stack} behind the given {@param behindStack} if possible. If
1683      * {@param behindStack} is not currently in the display, then then the stack is moved to the
1684      * back. Generally used in conjunction with {@link #moveStackBehindBottomMostVisibleStack}.
1685      */
moveStackBehindStack(ActivityStack stack, ActivityStack behindStack)1686     void moveStackBehindStack(ActivityStack stack, ActivityStack behindStack) {
1687         if (behindStack == null || behindStack == stack) {
1688             return;
1689         }
1690 
1691         final WindowContainer parent = stack.getParent();
1692         if (parent == null || parent != behindStack.getParent()) {
1693             return;
1694         }
1695 
1696         // Note that positionChildAt will first remove the given stack before inserting into the
1697         // list, so we need to adjust the insertion index to account for the removed index
1698         // TODO: Remove this logic when WindowContainer.positionChildAt() is updated to adjust the
1699         //       position internally
1700         final int stackIndex = parent.mChildren.indexOf(stack);
1701         final int behindStackIndex = parent.mChildren.indexOf(behindStack);
1702         final int insertIndex = stackIndex <= behindStackIndex
1703                 ? behindStackIndex - 1 : behindStackIndex;
1704         final int position = Math.max(0, insertIndex);
1705         if (stack.isRootTask()) {
1706             positionStackAt(stack, position);
1707         } else {
1708             parent.positionChildAt(position, stack, false /* includingParents */);
1709         }
1710     }
1711 
hasPinnedTask()1712     boolean hasPinnedTask() {
1713         return getRootPinnedTask() != null;
1714     }
1715 
1716     /**
1717      * @return the stack currently above the {@param stack}. Can be null if the {@param stack} is
1718      *         already top-most.
1719      */
getStackAbove(ActivityStack stack)1720     static ActivityStack getStackAbove(ActivityStack stack) {
1721         final WindowContainer wc = stack.getParent();
1722         final int index = wc.mChildren.indexOf(stack) + 1;
1723         return (index < wc.mChildren.size()) ? (ActivityStack) wc.mChildren.get(index) : null;
1724     }
1725 
1726     /** Returns true if the stack in the windowing mode is visible. */
isStackVisible(int windowingMode)1727     boolean isStackVisible(int windowingMode) {
1728         final ActivityStack stack = getTopStackInWindowingMode(windowingMode);
1729         return stack != null && stack.isVisible();
1730     }
1731 
removeStack(ActivityStack stack)1732     void removeStack(ActivityStack stack) {
1733         removeChild(stack);
1734     }
1735 
getDisplayId()1736     int getDisplayId() {
1737         return mDisplayContent.getDisplayId();
1738     }
1739 
isRemoved()1740     boolean isRemoved() {
1741         return mRemoved;
1742     }
1743 
1744     /**
1745      * Adds a listener to be notified whenever the stack order in the display changes. Currently
1746      * only used by the {@link RecentsAnimation} to determine whether to interrupt and cancel the
1747      * current animation when the system state changes.
1748      */
registerStackOrderChangedListener(OnStackOrderChangedListener listener)1749     void registerStackOrderChangedListener(OnStackOrderChangedListener listener) {
1750         if (!mStackOrderChangedCallbacks.contains(listener)) {
1751             mStackOrderChangedCallbacks.add(listener);
1752         }
1753     }
1754 
1755     /**
1756      * Removes a previously registered stack order change listener.
1757      */
unregisterStackOrderChangedListener(OnStackOrderChangedListener listener)1758     void unregisterStackOrderChangedListener(OnStackOrderChangedListener listener) {
1759         mStackOrderChangedCallbacks.remove(listener);
1760     }
1761 
1762     /**
1763      * Notifies of a stack order change
1764      * @param stack The stack which triggered the order change
1765      */
onStackOrderChanged(ActivityStack stack)1766     void onStackOrderChanged(ActivityStack stack) {
1767         for (int i = mStackOrderChangedCallbacks.size() - 1; i >= 0; i--) {
1768             mStackOrderChangedCallbacks.get(i).onStackOrderChanged(stack);
1769         }
1770     }
1771 
1772     @Override
canCreateRemoteAnimationTarget()1773     boolean canCreateRemoteAnimationTarget() {
1774         return true;
1775     }
1776 
1777     /**
1778      * Callback for when the order of the stacks in the display changes.
1779      */
1780     interface OnStackOrderChangedListener {
onStackOrderChanged(ActivityStack stack)1781         void onStackOrderChanged(ActivityStack stack);
1782     }
1783 
ensureActivitiesVisible(ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients)1784     void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
1785             boolean preserveWindows, boolean notifyClients) {
1786         mAtmService.mStackSupervisor.beginActivityVisibilityUpdate();
1787         try {
1788             for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
1789                 final ActivityStack stack = getStackAt(stackNdx);
1790                 stack.ensureActivitiesVisible(starting, configChanges, preserveWindows,
1791                         notifyClients);
1792             }
1793         } finally {
1794             mAtmService.mStackSupervisor.endActivityVisibilityUpdate();
1795         }
1796     }
1797 
prepareFreezingTaskBounds()1798     void prepareFreezingTaskBounds() {
1799         for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
1800             final ActivityStack stack = getChildAt(stackNdx);
1801             stack.prepareFreezingTaskBounds();
1802         }
1803     }
1804 
1805     /**
1806      * Removes the stacks in the node applying the content removal node from the display.
1807      * @return last reparented stack, or {@code null} if the stacks had to be destroyed.
1808      */
remove()1809     ActivityStack remove() {
1810         mPreferredTopFocusableStack = null;
1811         // TODO(b/153090332): Allow setting content removal mode per task display area
1812         final boolean destroyContentOnRemoval = mDisplayContent.shouldDestroyContentOnRemove();
1813         final TaskDisplayArea toDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
1814         ActivityStack lastReparentedStack = null;
1815 
1816         // Stacks could be reparented from the removed display area to other display area. After
1817         // reparenting the last stack of the removed display area, the display area becomes ready to
1818         // be released (no more ActivityStack-s). But, we cannot release it at that moment or the
1819         // related WindowContainer will also be removed. So, we set display area as removed after
1820         // reparenting stack finished.
1821         // Keep the order from bottom to top.
1822         int numStacks = getStackCount();
1823 
1824         final boolean splitScreenActivated = toDisplayArea.isSplitScreenModeActivated();
1825         final ActivityStack rootStack = splitScreenActivated ? toDisplayArea
1826                 .getTopStackInWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) : null;
1827         for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
1828             final ActivityStack stack = getStackAt(stackNdx);
1829             // Always finish non-standard type stacks.
1830             if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) {
1831                 stack.finishAllActivitiesImmediately();
1832             } else {
1833                 // Reparent the stack to the root task of secondary-split-screen or display area.
1834                 stack.reparent(stack.supportsSplitScreenWindowingMode() && rootStack != null
1835                         ? rootStack : toDisplayArea, POSITION_TOP);
1836 
1837                 // Set the windowing mode to undefined by default to let the stack inherited the
1838                 // windowing mode.
1839                 stack.setWindowingMode(WINDOWING_MODE_UNDEFINED);
1840                 lastReparentedStack = stack;
1841             }
1842             // Stacks may be removed from this display. Ensure each stack will be processed
1843             // and the loop will end.
1844             stackNdx -= numStacks - getStackCount();
1845             numStacks = getStackCount();
1846         }
1847         if (lastReparentedStack != null && splitScreenActivated) {
1848             if (!lastReparentedStack.supportsSplitScreenWindowingMode()) {
1849                 mAtmService.getTaskChangeNotificationController()
1850                         .notifyActivityDismissingDockedStack();
1851                 toDisplayArea.onSplitScreenModeDismissed(lastReparentedStack);
1852             } else if (rootStack != null) {
1853                 // update focus
1854                 rootStack.moveToFront("display-removed");
1855             }
1856         }
1857 
1858         mRemoved = true;
1859 
1860         return lastReparentedStack;
1861     }
1862 
1863 
1864     @Override
dump(PrintWriter pw, String prefix, boolean dumpAll)1865     void dump(PrintWriter pw, String prefix, boolean dumpAll) {
1866         pw.println(prefix + "TaskDisplayArea " + getName());
1867         final String doublePrefix = prefix + "  ";
1868         super.dump(pw, doublePrefix, dumpAll);
1869         if (mPreferredTopFocusableStack != null) {
1870             pw.println(doublePrefix + "mPreferredTopFocusableStack=" + mPreferredTopFocusableStack);
1871         }
1872         if (mLastFocusedStack != null) {
1873             pw.println(doublePrefix + "mLastFocusedStack=" + mLastFocusedStack);
1874         }
1875         final String triplePrefix = doublePrefix + "  ";
1876         pw.println(doublePrefix + "Application tokens in top down Z order:");
1877         for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
1878             final ActivityStack stack = getChildAt(stackNdx);
1879             pw.println(doublePrefix + "* " + stack);
1880             stack.dump(pw, triplePrefix, dumpAll);
1881         }
1882     }
1883 }
1884