• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.wm;
18 
19 import static android.app.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 
776     /** Reset the mPreferredTopFocusableRootTask if it is or below the given task. */
resetPreferredTopFocusableRootTaskIfNeeded(Task task)777     void resetPreferredTopFocusableRootTaskIfNeeded(Task task) {
778         if (mPreferredTopFocusableStack != null
779                 && mPreferredTopFocusableStack.compareTo(task) <= 0) {
780             mPreferredTopFocusableStack = null;
781         }
782     }
783 
positionStackAt(int position, ActivityStack child, boolean includingParents)784     void positionStackAt(int position, ActivityStack child, boolean includingParents) {
785         positionChildAt(position, child, includingParents);
786         mDisplayContent.layoutAndAssignWindowLayersIfNeeded();
787     }
788 
positionStackAtTop(ActivityStack stack, boolean includingParents)789     void positionStackAtTop(ActivityStack stack, boolean includingParents) {
790         positionStackAtTop(stack, includingParents, null /* updateLastFocusedStackReason */);
791     }
792 
positionStackAtTop(ActivityStack stack, boolean includingParents, String updateLastFocusedStackReason)793     void positionStackAtTop(ActivityStack stack, boolean includingParents,
794             String updateLastFocusedStackReason) {
795         positionStackAt(stack, getStackCount(), includingParents,
796                 updateLastFocusedStackReason);
797     }
798 
positionStackAtBottom(ActivityStack stack)799     void positionStackAtBottom(ActivityStack stack) {
800         positionStackAtBottom(stack, null /* updateLastFocusedStackReason */);
801     }
802 
positionStackAtBottom(ActivityStack stack, String updateLastFocusedStackReason)803     void positionStackAtBottom(ActivityStack stack, String updateLastFocusedStackReason) {
804         positionStackAt(stack, 0, false /* includingParents */,
805                 updateLastFocusedStackReason);
806     }
807 
positionStackAt(ActivityStack stack, int position)808     void positionStackAt(ActivityStack stack, int position) {
809         positionStackAt(stack, position, false /* includingParents */,
810                 null /* updateLastFocusedStackReason */);
811     }
812 
positionStackAt(ActivityStack stack, int position, boolean includingParents, String updateLastFocusedStackReason)813     void positionStackAt(ActivityStack stack, int position, boolean includingParents,
814             String updateLastFocusedStackReason) {
815         // TODO: Keep in sync with WindowContainer.positionChildAt(), once we change that to adjust
816         //       the position internally, also update the logic here
817         final ActivityStack prevFocusedStack = updateLastFocusedStackReason != null
818                 ? getFocusedStack() : null;
819         final boolean wasContained = mChildren.contains(stack);
820         if (mDisplayContent.mSingleTaskInstance && getStackCount() == 1 && !wasContained) {
821             throw new IllegalStateException(
822                     "positionStackAt: Can only have one task on display=" + this);
823         }
824 
825         // Since positionChildAt() is called during the creation process of pinned stacks,
826         // ActivityStack#getStack() can be null.
827         positionStackAt(position, stack, includingParents);
828 
829         if (updateLastFocusedStackReason != null) {
830             final ActivityStack currentFocusedStack = getFocusedStack();
831             if (currentFocusedStack != prevFocusedStack) {
832                 mLastFocusedStack = prevFocusedStack;
833                 EventLogTags.writeWmFocusedStack(mRootWindowContainer.mCurrentUser,
834                         mDisplayContent.mDisplayId,
835                         currentFocusedStack == null ? -1 : currentFocusedStack.getRootTaskId(),
836                         mLastFocusedStack == null ? -1 : mLastFocusedStack.getRootTaskId(),
837                         updateLastFocusedStackReason);
838             }
839         }
840 
841         onStackOrderChanged(stack);
842     }
843 
844     /**
845      * Moves/reparents `task` to the back of whatever container the home stack is in. This is for
846      * when we just want to move a task to "the back" vs. a specific place. The primary use-case
847      * is to make sure that moved-to-back apps go into secondary split when in split-screen mode.
848      */
positionTaskBehindHome(ActivityStack task)849     void positionTaskBehindHome(ActivityStack task) {
850         final ActivityStack home = getOrCreateRootHomeTask();
851         final WindowContainer homeParent = home.getParent();
852         final Task homeParentTask = homeParent != null ? homeParent.asTask() : null;
853         if (homeParentTask == null) {
854             // reparent throws if parent didn't change...
855             if (task.getParent() == this) {
856                 positionStackAtBottom(task);
857             } else {
858                 task.reparent(this, false /* onTop */);
859             }
860         } else if (homeParentTask == task.getParent()) {
861             // Apparently reparent early-outs if same stack, so we have to explicitly reorder.
862             ((ActivityStack) homeParentTask).positionChildAtBottom(task);
863         } else {
864             task.reparent((ActivityStack) homeParentTask, false /* toTop */,
865                     Task.REPARENT_LEAVE_STACK_IN_PLACE, false /* animate */,
866                     false /* deferResume */, "positionTaskBehindHome");
867         }
868     }
869 
getStack(int rootTaskId)870     ActivityStack getStack(int rootTaskId) {
871         for (int i = getStackCount() - 1; i >= 0; --i) {
872             final ActivityStack stack = getStackAt(i);
873             if (stack.getRootTaskId() == rootTaskId) {
874                 return stack;
875             }
876         }
877         return null;
878     }
879 
880     /**
881      * Returns an existing stack compatible with the windowing mode and activity type or creates one
882      * if a compatible stack doesn't exist.
883      * @see #getOrCreateStack(int, int, boolean, Intent, Task)
884      */
getOrCreateStack(int windowingMode, int activityType, boolean onTop)885     ActivityStack getOrCreateStack(int windowingMode, int activityType, boolean onTop) {
886         return getOrCreateStack(windowingMode, activityType, onTop, null /* intent */,
887                 null /* candidateTask */);
888     }
889 
890     /**
891      * When two level tasks are required for given windowing mode and activity type, returns an
892      * existing compatible root task or creates a new one.
893      * For one level task, the candidate task would be reused to also be the root task or create
894      * a new root task if no candidate task.
895      * @see #getStack(int, int)
896      * @see #createStack(int, int, boolean)
897      */
getOrCreateStack(int windowingMode, int activityType, boolean onTop, Intent intent, Task candidateTask)898     ActivityStack getOrCreateStack(int windowingMode, int activityType, boolean onTop,
899             Intent intent, Task candidateTask) {
900         // Need to pass in a determined windowing mode to see if a new stack should be created,
901         // so use its parent's windowing mode if it is undefined.
902         if (!alwaysCreateStack(
903                 windowingMode != WINDOWING_MODE_UNDEFINED ? windowingMode : getWindowingMode(),
904                 activityType)) {
905             ActivityStack stack = getStack(windowingMode, activityType);
906             if (stack != null) {
907                 return stack;
908             }
909         } else if (candidateTask != null) {
910             final ActivityStack stack = (ActivityStack) candidateTask;
911             final int position = onTop ? POSITION_TOP : POSITION_BOTTOM;
912             Task launchRootTask = updateLaunchRootTask(windowingMode);
913 
914             if (launchRootTask != null) {
915                 if (stack.getParent() == null) {
916                     launchRootTask.addChild(stack, position);
917                 } else if (stack.getParent() != launchRootTask) {
918                     stack.reparent(launchRootTask, position);
919                 }
920             } else if (stack.getDisplayArea() != this || !stack.isRootTask()) {
921                 if (stack.getParent() == null) {
922                     addChild(stack, position);
923                 } else {
924                     stack.reparent(this, onTop);
925                 }
926             }
927             // Update windowing mode if necessary, e.g. moving a pinned task to fullscreen.
928             if (candidateTask.getWindowingMode() != windowingMode) {
929                 candidateTask.setWindowingMode(windowingMode);
930             }
931             return stack;
932         }
933         return createStack(windowingMode, activityType, onTop, null /*info*/, intent,
934                 false /* createdByOrganizer */);
935     }
936 
937     /**
938      * Returns an existing stack compatible with the input params or creates one
939      * if a compatible stack doesn't exist.
940      * @see #getOrCreateStack(int, int, boolean)
941      */
getOrCreateStack(@ullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable Task candidateTask, int activityType, boolean onTop)942     ActivityStack getOrCreateStack(@Nullable ActivityRecord r,
943             @Nullable ActivityOptions options, @Nullable Task candidateTask, int activityType,
944             boolean onTop) {
945         // First preference is the windowing mode in the activity options if set.
946         int windowingMode = (options != null)
947                 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
948         // Validate that our desired windowingMode will work under the current conditions.
949         // UNDEFINED windowing mode is a valid result and means that the new stack will inherit
950         // it's display's windowing mode.
951         windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType);
952         return getOrCreateStack(windowingMode, activityType, onTop, null /* intent */,
953                 candidateTask);
954     }
955 
956     @VisibleForTesting
getNextStackId()957     int getNextStackId() {
958         return mAtmService.mStackSupervisor.getNextTaskIdForUser();
959     }
960 
createStack(int windowingMode, int activityType, boolean onTop)961     ActivityStack createStack(int windowingMode, int activityType, boolean onTop) {
962         return createStack(windowingMode, activityType, onTop, null /* info */, null /* intent */,
963                 false /* createdByOrganizer */);
964     }
965 
966     /**
967      * Creates a stack matching the input windowing mode and activity type on this display.
968      * @param windowingMode The windowing mode the stack should be created in. If
969      *                      {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will
970      *                      inherit its parent's windowing mode.
971      * @param activityType The activityType the stack should be created in. If
972      *                     {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will
973      *                     be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
974      * @param onTop If true the stack will be created at the top of the display, else at the bottom.
975      * @param info The started activity info.
976      * @param intent The intent that started this task.
977      * @param createdByOrganizer @{code true} if this is created by task organizer, @{code false}
978      *                          otherwise.
979      * @return The newly created stack.
980      */
createStack(int windowingMode, int activityType, boolean onTop, ActivityInfo info, Intent intent, boolean createdByOrganizer)981     ActivityStack createStack(int windowingMode, int activityType, boolean onTop, ActivityInfo info,
982             Intent intent, boolean createdByOrganizer) {
983         if (mDisplayContent.mSingleTaskInstance && getStackCount() > 0) {
984             // Create stack on default display instead since this display can only contain 1 stack.
985             // TODO: Kinda a hack, but better that having the decision at each call point. Hoping
986             // this goes away once ActivityView is no longer using virtual displays.
987             return mRootWindowContainer.getDefaultTaskDisplayArea().createStack(
988                     windowingMode, activityType, onTop, info, intent, createdByOrganizer);
989         }
990 
991         if (activityType == ACTIVITY_TYPE_UNDEFINED && !createdByOrganizer) {
992             // Can't have an undefined stack type yet...so re-map to standard. Anyone that wants
993             // anything else should be passing it in anyways...except for the task organizer.
994             activityType = ACTIVITY_TYPE_STANDARD;
995         }
996 
997         if (activityType != ACTIVITY_TYPE_STANDARD && activityType != ACTIVITY_TYPE_UNDEFINED) {
998             // For now there can be only one stack of a particular non-standard activity type on a
999             // display. So, get that ignoring whatever windowing mode it is currently in.
1000             ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
1001             if (stack != null) {
1002                 throw new IllegalArgumentException("Stack=" + stack + " of activityType="
1003                         + activityType + " already on display=" + this + ". Can't have multiple.");
1004             }
1005         }
1006 
1007         if (!isWindowingModeSupported(windowingMode, mAtmService.mSupportsMultiWindow,
1008                 mAtmService.mSupportsSplitScreenMultiWindow,
1009                 mAtmService.mSupportsFreeformWindowManagement,
1010                 mAtmService.mSupportsPictureInPicture, activityType)) {
1011             throw new IllegalArgumentException("Can't create stack for unsupported windowingMode="
1012                     + windowingMode);
1013         }
1014 
1015         if (windowingMode == WINDOWING_MODE_PINNED && getRootPinnedTask() != null) {
1016             // Only 1 stack can be PINNED at a time, so dismiss the existing one
1017             getRootPinnedTask().dismissPip();
1018         }
1019 
1020         final int stackId = getNextStackId();
1021         return createStackUnchecked(windowingMode, activityType, stackId, onTop, info, intent,
1022                 createdByOrganizer);
1023     }
1024 
1025     /** @return the root task to create the next task in. */
updateLaunchRootTask(int windowingMode)1026     private Task updateLaunchRootTask(int windowingMode) {
1027         if (!isSplitScreenWindowingMode(windowingMode)) {
1028             // Only split-screen windowing modes can do this currently...
1029             return null;
1030         }
1031         for (int i = getStackCount() - 1; i >= 0; --i) {
1032             final Task t = getStackAt(i);
1033             if (!t.mCreatedByOrganizer || t.getRequestedOverrideWindowingMode() != windowingMode) {
1034                 continue;
1035             }
1036             // If not already set, pick a launch root which is not the one we are launching into.
1037             if (mLaunchRootTask == null) {
1038                 for (int j = 0, n = getStackCount(); j < n; ++j) {
1039                     final Task tt = getStackAt(j);
1040                     if (tt.mCreatedByOrganizer && tt != t) {
1041                         mLaunchRootTask = tt;
1042                         break;
1043                     }
1044                 }
1045             }
1046             return t;
1047         }
1048         return mLaunchRootTask;
1049     }
1050 
1051     @VisibleForTesting
createStackUnchecked(int windowingMode, int activityType, int stackId, boolean onTop, ActivityInfo info, Intent intent, boolean createdByOrganizer)1052     ActivityStack createStackUnchecked(int windowingMode, int activityType, int stackId,
1053             boolean onTop, ActivityInfo info, Intent intent, boolean createdByOrganizer) {
1054         if (windowingMode == WINDOWING_MODE_PINNED && activityType != ACTIVITY_TYPE_STANDARD) {
1055             throw new IllegalArgumentException("Stack with windowing mode cannot with non standard "
1056                     + "activity type.");
1057         }
1058         if (info == null) {
1059             info = new ActivityInfo();
1060             info.applicationInfo = new ApplicationInfo();
1061         }
1062 
1063         // Task created by organizer are added as root.
1064         Task launchRootTask = createdByOrganizer ? null : updateLaunchRootTask(windowingMode);
1065         if (launchRootTask != null) {
1066             // Since this stack will be put into a root task, its windowingMode will be inherited.
1067             windowingMode = WINDOWING_MODE_UNDEFINED;
1068         }
1069 
1070         final ActivityStack stack = new ActivityStack(mAtmService, stackId, activityType,
1071                 info, intent, createdByOrganizer);
1072         if (launchRootTask != null) {
1073             launchRootTask.addChild(stack, onTop ? POSITION_TOP : POSITION_BOTTOM);
1074             if (onTop) {
1075                 positionStackAtTop((ActivityStack) launchRootTask, false /* includingParents */);
1076             }
1077         } else {
1078             addChild(stack, onTop ? POSITION_TOP : POSITION_BOTTOM);
1079             stack.setWindowingMode(windowingMode, true /* creating */);
1080         }
1081         return stack;
1082     }
1083 
1084     /**
1085      * Get the preferred focusable stack in priority. If the preferred stack does not exist, find a
1086      * focusable and visible stack from the top of stacks in this display.
1087      */
getFocusedStack()1088     ActivityStack getFocusedStack() {
1089         if (mPreferredTopFocusableStack != null) {
1090             return mPreferredTopFocusableStack;
1091         }
1092 
1093         for (int i = getStackCount() - 1; i >= 0; --i) {
1094             final ActivityStack stack = getStackAt(i);
1095             if (stack.isFocusableAndVisible()) {
1096                 return stack;
1097             }
1098         }
1099 
1100         return null;
1101     }
1102 
getNextFocusableStack(ActivityStack currentFocus, boolean ignoreCurrent)1103     ActivityStack getNextFocusableStack(ActivityStack currentFocus, boolean ignoreCurrent) {
1104         final int currentWindowingMode = currentFocus != null
1105                 ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
1106 
1107         ActivityStack candidate = null;
1108         for (int i = getStackCount() - 1; i >= 0; --i) {
1109             final ActivityStack stack = getStackAt(i);
1110             if (ignoreCurrent && stack == currentFocus) {
1111                 continue;
1112             }
1113             if (!stack.isFocusableAndVisible()) {
1114                 continue;
1115             }
1116 
1117             if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
1118                     && candidate == null && stack.inSplitScreenPrimaryWindowingMode()) {
1119                 // If the currently focused stack is in split-screen secondary we save off the
1120                 // top primary split-screen stack as a candidate for focus because we might
1121                 // prefer focus to move to an other stack to avoid primary split-screen stack
1122                 // overlapping with a fullscreen stack when a fullscreen stack is higher in z
1123                 // than the next split-screen stack. Assistant stack, I am looking at you...
1124                 // We only move the focus to the primary-split screen stack if there isn't a
1125                 // better alternative.
1126                 candidate = stack;
1127                 continue;
1128             }
1129             if (candidate != null && stack.inSplitScreenSecondaryWindowingMode()) {
1130                 // Use the candidate stack since we are now at the secondary split-screen.
1131                 return candidate;
1132             }
1133             return stack;
1134         }
1135         return candidate;
1136     }
1137 
getFocusedActivity()1138     ActivityRecord getFocusedActivity() {
1139         final ActivityStack focusedStack = getFocusedStack();
1140         if (focusedStack == null) {
1141             return null;
1142         }
1143         // TODO(b/111541062): Move this into ActivityStack#getResumedActivity()
1144         // Check if the focused stack has the resumed activity
1145         ActivityRecord resumedActivity = focusedStack.getResumedActivity();
1146         if (resumedActivity == null || resumedActivity.app == null) {
1147             // If there is no registered resumed activity in the stack or it is not running -
1148             // try to use previously resumed one.
1149             resumedActivity = focusedStack.mPausingActivity;
1150             if (resumedActivity == null || resumedActivity.app == null) {
1151                 // If previously resumed activity doesn't work either - find the topmost running
1152                 // activity that can be focused.
1153                 resumedActivity = focusedStack.topRunningActivity(true /* focusableOnly */);
1154             }
1155         }
1156         return resumedActivity;
1157     }
1158 
getLastFocusedStack()1159     ActivityStack getLastFocusedStack() {
1160         return mLastFocusedStack;
1161     }
1162 
allResumedActivitiesComplete()1163     boolean allResumedActivitiesComplete() {
1164         for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
1165             final ActivityRecord r = getStackAt(stackNdx).getResumedActivity();
1166             if (r != null && !r.isState(RESUMED)) {
1167                 return false;
1168             }
1169         }
1170         final ActivityStack currentFocusedStack = getFocusedStack();
1171         if (ActivityTaskManagerDebugConfig.DEBUG_STACK) {
1172             Slog.d(TAG_STACK, "allResumedActivitiesComplete: mLastFocusedStack changing from="
1173                     + mLastFocusedStack + " to=" + currentFocusedStack);
1174         }
1175         mLastFocusedStack = currentFocusedStack;
1176         return true;
1177     }
1178 
1179     /**
1180      * Pause all activities in either all of the stacks or just the back stacks. This is done before
1181      * resuming a new activity and to make sure that previously active activities are
1182      * paused in stacks that are no longer visible or in pinned windowing mode. This does not
1183      * pause activities in visible stacks, so if an activity is launched within the same stack/task,
1184      * then we should explicitly pause that stack's top activity.
1185      * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
1186      * @param resuming The resuming activity.
1187      * @return {@code true} if any activity was paused as a result of this call.
1188      */
pauseBackStacks(boolean userLeaving, ActivityRecord resuming)1189     boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming) {
1190         boolean someActivityPaused = false;
1191         for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
1192             final ActivityStack stack = getStackAt(stackNdx);
1193             final ActivityRecord resumedActivity = stack.getResumedActivity();
1194             if (resumedActivity != null
1195                     && (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
1196                     || !stack.isTopActivityFocusable())) {
1197                 if (DEBUG_STATES) {
1198                     Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack
1199                             + " mResumedActivity=" + resumedActivity);
1200                 }
1201                 someActivityPaused |= stack.startPausingLocked(userLeaving, false /* uiSleeping*/,
1202                         resuming);
1203             }
1204         }
1205         return someActivityPaused;
1206     }
1207 
1208     /**
1209      * Find task for putting the Activity in.
1210      */
findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplayArea, RootWindowContainer.FindTaskResult result)1211     void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplayArea,
1212             RootWindowContainer.FindTaskResult result) {
1213         mTmpFindTaskResult.clear();
1214         for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
1215             final ActivityStack stack = getStackAt(stackNdx);
1216             if (!r.hasCompatibleActivityType(stack) && stack.isLeafTask()) {
1217                 if (DEBUG_TASKS) {
1218                     Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) " + stack);
1219                 }
1220                 continue;
1221             }
1222 
1223             mTmpFindTaskResult.process(r, stack);
1224             // It is possible to have tasks in multiple stacks with the same root affinity, so
1225             // we should keep looking after finding an affinity match to see if there is a
1226             // better match in another stack. Also, task affinity isn't a good enough reason
1227             // to target a display which isn't the source of the intent, so skip any affinity
1228             // matches not on the specified display.
1229             if (mTmpFindTaskResult.mRecord != null) {
1230                 if (mTmpFindTaskResult.mIdealMatch) {
1231                     result.setTo(mTmpFindTaskResult);
1232                     return;
1233                 } else if (isPreferredDisplayArea) {
1234                     // Note: since the traversing through the stacks is top down, the floating
1235                     // tasks should always have lower priority than any affinity-matching tasks
1236                     // in the fullscreen stacks
1237                     result.setTo(mTmpFindTaskResult);
1238                 }
1239             }
1240         }
1241     }
1242 
1243     /**
1244      * Removes stacks in the input windowing modes from the system if they are of activity type
1245      * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
1246      */
removeStacksInWindowingModes(int... windowingModes)1247     void removeStacksInWindowingModes(int... windowingModes) {
1248         if (windowingModes == null || windowingModes.length == 0) {
1249             return;
1250         }
1251 
1252         // Collect the stacks that are necessary to be removed instead of performing the removal
1253         // by looping mStacks, so that we don't miss any stacks after the stack size changed or
1254         // stacks reordered.
1255         final ArrayList<ActivityStack> stacks = new ArrayList<>();
1256         for (int j = windowingModes.length - 1; j >= 0; --j) {
1257             final int windowingMode = windowingModes[j];
1258             for (int i = getStackCount() - 1; i >= 0; --i) {
1259                 final ActivityStack stack = getStackAt(i);
1260                 if (!stack.isActivityTypeStandardOrUndefined()) {
1261                     continue;
1262                 }
1263                 if (stack.getWindowingMode() != windowingMode) {
1264                     continue;
1265                 }
1266                 stacks.add(stack);
1267             }
1268         }
1269 
1270         for (int i = stacks.size() - 1; i >= 0; --i) {
1271             mRootWindowContainer.mStackSupervisor.removeStack(stacks.get(i));
1272         }
1273     }
1274 
removeStacksWithActivityTypes(int... activityTypes)1275     void removeStacksWithActivityTypes(int... activityTypes) {
1276         if (activityTypes == null || activityTypes.length == 0) {
1277             return;
1278         }
1279 
1280         // Collect the stacks that are necessary to be removed instead of performing the removal
1281         // by looping mStacks, so that we don't miss any stacks after the stack size changed or
1282         // stacks reordered.
1283         final ArrayList<ActivityStack> stacks = new ArrayList<>();
1284         for (int j = activityTypes.length - 1; j >= 0; --j) {
1285             final int activityType = activityTypes[j];
1286             for (int i = getStackCount() - 1; i >= 0; --i) {
1287                 final ActivityStack stack = getStackAt(i);
1288                 // Collect the root tasks that are currently being organized.
1289                 if (stack.mCreatedByOrganizer) {
1290                     for (int k = stack.getChildCount() - 1; k >= 0; --k) {
1291                         final ActivityStack childStack = (ActivityStack) stack.getChildAt(k);
1292                         if (childStack.getActivityType() == activityType) {
1293                             stacks.add(childStack);
1294                         }
1295                     }
1296                 } else if (stack.getActivityType() == activityType) {
1297                     stacks.add(stack);
1298                 }
1299             }
1300         }
1301 
1302         for (int i = stacks.size() - 1; i >= 0; --i) {
1303             mRootWindowContainer.mStackSupervisor.removeStack(stacks.get(i));
1304         }
1305     }
1306 
onSplitScreenModeDismissed()1307     void onSplitScreenModeDismissed() {
1308         onSplitScreenModeDismissed(null /* toTop */);
1309     }
1310 
onSplitScreenModeDismissed(ActivityStack toTop)1311     void onSplitScreenModeDismissed(ActivityStack toTop) {
1312         mAtmService.deferWindowLayout();
1313         try {
1314             mLaunchRootTask = null;
1315             moveSplitScreenTasksToFullScreen();
1316         } finally {
1317             final ActivityStack topFullscreenStack = toTop != null
1318                     ? toTop : getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN);
1319             final ActivityStack homeStack = getOrCreateRootHomeTask();
1320             if (homeStack != null && ((topFullscreenStack != null && !isTopStack(homeStack))
1321                     || toTop != null)) {
1322                 // Whenever split-screen is dismissed we want the home stack directly behind the
1323                 // current top fullscreen stack so it shows up when the top stack is finished.
1324                 // Or, if the caller specified a stack to be on top after split-screen is dismissed.
1325                 // TODO: Would be better to use ActivityDisplay.positionChildAt() for this, however
1326                 // ActivityDisplay doesn't have a direct controller to WM side yet. We can switch
1327                 // once we have that.
1328                 homeStack.moveToFront("onSplitScreenModeDismissed");
1329                 topFullscreenStack.moveToFront("onSplitScreenModeDismissed");
1330             }
1331             mAtmService.continueWindowLayout();
1332         }
1333     }
1334 
moveSplitScreenTasksToFullScreen()1335     private void moveSplitScreenTasksToFullScreen() {
1336         final WindowContainerTransaction wct = new WindowContainerTransaction();
1337         mTmpTasks.clear();
1338         forAllTasks(task -> {
1339             if (task.mCreatedByOrganizer && task.inSplitScreenWindowingMode() && task.hasChild()) {
1340                 mTmpTasks.add(task);
1341             }
1342         });
1343 
1344         for (int i = mTmpTasks.size() - 1; i >= 0; i--) {
1345             final Task root = mTmpTasks.get(i);
1346             for (int j = 0; j < root.getChildCount(); j++) {
1347                 wct.reparent(root.getChildAt(j).mRemoteToken.toWindowContainerToken(),
1348                         null, true /* toTop */);
1349             }
1350         }
1351         mAtmService.mWindowOrganizerController.applyTransaction(wct);
1352     }
1353 
1354     /**
1355      * Returns true if the {@param windowingMode} is supported based on other parameters passed in.
1356      * @param windowingMode The windowing mode we are checking support for.
1357      * @param supportsMultiWindow If we should consider support for multi-window mode in general.
1358      * @param supportsSplitScreen If we should consider support for split-screen multi-window.
1359      * @param supportsFreeform If we should consider support for freeform multi-window.
1360      * @param supportsPip If we should consider support for picture-in-picture mutli-window.
1361      * @param activityType The activity type under consideration.
1362      * @return true if the windowing mode is supported.
1363      */
isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow, boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip, int activityType)1364     private boolean isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow,
1365             boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip,
1366             int activityType) {
1367 
1368         if (windowingMode == WINDOWING_MODE_UNDEFINED
1369                 || windowingMode == WINDOWING_MODE_FULLSCREEN) {
1370             return true;
1371         }
1372         if (!supportsMultiWindow) {
1373             return false;
1374         }
1375 
1376         if (windowingMode == WINDOWING_MODE_MULTI_WINDOW) {
1377             return true;
1378         }
1379 
1380         if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
1381                 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
1382             return supportsSplitScreen
1383                     && WindowConfiguration.supportSplitScreenWindowingMode(activityType);
1384         }
1385 
1386         if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) {
1387             return false;
1388         }
1389 
1390         if (!supportsPip && windowingMode == WINDOWING_MODE_PINNED) {
1391             return false;
1392         }
1393         return true;
1394     }
1395 
1396     /**
1397      * Resolves the windowing mode that an {@link ActivityRecord} would be in if started on this
1398      * display with the provided parameters.
1399      *
1400      * @param r The ActivityRecord in question.
1401      * @param options Options to start with.
1402      * @param task The task within-which the activity would start.
1403      * @param activityType The type of activity to start.
1404      * @return The resolved (not UNDEFINED) windowing-mode that the activity would be in.
1405      */
resolveWindowingMode(@ullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable Task task, int activityType)1406     int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
1407             @Nullable Task task, int activityType) {
1408 
1409         // First preference if the windowing mode in the activity options if set.
1410         int windowingMode = (options != null)
1411                 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
1412 
1413         // If windowing mode is unset, then next preference is the candidate task, then the
1414         // activity record.
1415         if (windowingMode == WINDOWING_MODE_UNDEFINED) {
1416             if (task != null) {
1417                 windowingMode = task.getWindowingMode();
1418             }
1419             if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) {
1420                 windowingMode = r.getWindowingMode();
1421             }
1422             if (windowingMode == WINDOWING_MODE_UNDEFINED) {
1423                 // Use the display's windowing mode.
1424                 windowingMode = getWindowingMode();
1425             }
1426         }
1427         windowingMode = validateWindowingMode(windowingMode, r, task, activityType);
1428         return windowingMode != WINDOWING_MODE_UNDEFINED
1429                 ? windowingMode : WINDOWING_MODE_FULLSCREEN;
1430     }
1431 
1432     /**
1433      * Check if the requested windowing-mode is appropriate for the specified task and/or activity
1434      * on this display.
1435      *
1436      * @param windowingMode The windowing-mode to validate.
1437      * @param r The {@link ActivityRecord} to check against.
1438      * @param task The {@link Task} to check against.
1439      * @param activityType An activity type.
1440      * @return {@code true} if windowingMode is valid, {@code false} otherwise.
1441      */
isValidWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task, int activityType)1442     boolean isValidWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task,
1443             int activityType) {
1444         // Make sure the windowing mode we are trying to use makes sense for what is supported.
1445         boolean supportsMultiWindow = mAtmService.mSupportsMultiWindow;
1446         boolean supportsSplitScreen = mAtmService.mSupportsSplitScreenMultiWindow;
1447         boolean supportsFreeform = mAtmService.mSupportsFreeformWindowManagement;
1448         boolean supportsPip = mAtmService.mSupportsPictureInPicture;
1449         if (supportsMultiWindow) {
1450             if (task != null) {
1451                 supportsMultiWindow = task.isResizeable();
1452                 supportsSplitScreen = task.supportsSplitScreenWindowingMode();
1453                 // TODO: Do we need to check for freeform and Pip support here?
1454             } else if (r != null) {
1455                 supportsMultiWindow = r.isResizeable();
1456                 supportsSplitScreen = r.supportsSplitScreenWindowingMode();
1457                 supportsFreeform = r.supportsFreeform();
1458                 supportsPip = r.supportsPictureInPicture();
1459             }
1460         }
1461 
1462         return windowingMode != WINDOWING_MODE_UNDEFINED
1463                 && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen,
1464                         supportsFreeform, supportsPip, activityType);
1465     }
1466 
1467     /**
1468      * Check that the requested windowing-mode is appropriate for the specified task and/or activity
1469      * on this display.
1470      *
1471      * @param windowingMode The windowing-mode to validate.
1472      * @param r The {@link ActivityRecord} to check against.
1473      * @param task The {@link Task} to check against.
1474      * @param activityType An activity type.
1475      * @return The provided windowingMode or the closest valid mode which is appropriate.
1476      */
validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task, int activityType)1477     int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task,
1478             int activityType) {
1479         final boolean inSplitScreenMode = isSplitScreenModeActivated();
1480         if (!inSplitScreenMode && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
1481             // Switch to the display's windowing mode if we are not in split-screen mode and we are
1482             // trying to launch in split-screen secondary.
1483             windowingMode = WINDOWING_MODE_UNDEFINED;
1484         } else if (inSplitScreenMode && windowingMode == WINDOWING_MODE_UNDEFINED) {
1485             windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
1486         }
1487         if (!isValidWindowingMode(windowingMode, r, task, activityType)) {
1488             return WINDOWING_MODE_UNDEFINED;
1489         }
1490         return windowingMode;
1491     }
1492 
isTopStack(ActivityStack stack)1493     boolean isTopStack(ActivityStack stack) {
1494         return stack == getTopStack();
1495     }
1496 
isTopNotPinnedStack(ActivityStack stack)1497     boolean isTopNotPinnedStack(ActivityStack stack) {
1498         for (int i = getStackCount() - 1; i >= 0; --i) {
1499             final ActivityStack current = getStackAt(i);
1500             if (!current.inPinnedWindowingMode()) {
1501                 return current == stack;
1502             }
1503         }
1504         return false;
1505     }
1506 
topRunningActivity()1507     ActivityRecord topRunningActivity() {
1508         return topRunningActivity(false /* considerKeyguardState */);
1509     }
1510 
1511     /**
1512      * Returns the top running activity in the focused stack. In the case the focused stack has no
1513      * such activity, the next focusable stack on this display is returned.
1514      *
1515      * @param considerKeyguardState Indicates whether the locked state should be considered. if
1516      *                              {@code true} and the keyguard is locked, only activities that
1517      *                              can be shown on top of the keyguard will be considered.
1518      * @return The top running activity. {@code null} if none is available.
1519      */
topRunningActivity(boolean considerKeyguardState)1520     ActivityRecord topRunningActivity(boolean considerKeyguardState) {
1521         ActivityRecord topRunning = null;
1522         final ActivityStack focusedStack = getFocusedStack();
1523         if (focusedStack != null) {
1524             topRunning = focusedStack.topRunningActivity();
1525         }
1526 
1527         // Look in other focusable stacks.
1528         if (topRunning == null) {
1529             for (int i = getStackCount() - 1; i >= 0; --i) {
1530                 final ActivityStack stack = getStackAt(i);
1531                 // Only consider focusable stacks other than the current focused one.
1532                 if (stack == focusedStack || !stack.isTopActivityFocusable()) {
1533                     continue;
1534                 }
1535                 topRunning = stack.topRunningActivity();
1536                 if (topRunning != null) {
1537                     break;
1538                 }
1539             }
1540         }
1541 
1542         // This activity can be considered the top running activity if we are not considering
1543         // the locked state, the keyguard isn't locked, or we can show when locked.
1544         if (topRunning != null && considerKeyguardState
1545                 && mRootWindowContainer.mStackSupervisor.getKeyguardController()
1546                 .isKeyguardLocked()
1547                 && !topRunning.canShowWhenLocked()) {
1548             return null;
1549         }
1550 
1551         return topRunning;
1552     }
1553 
getStackCount()1554     protected int getStackCount() {
1555         return mChildren.size();
1556     }
1557 
getStackAt(int index)1558     protected ActivityStack getStackAt(int index) {
1559         return mChildren.get(index);
1560     }
1561 
1562     @Nullable
getOrCreateRootHomeTask()1563     ActivityStack getOrCreateRootHomeTask() {
1564         return getOrCreateRootHomeTask(false /* onTop */);
1565     }
1566 
1567     /**
1568      * Returns the existing home stack or creates and returns a new one if it should exist for the
1569      * display.
1570      * @param onTop Only be used when there is no existing home stack. If true the home stack will
1571      *              be created at the top of the display, else at the bottom.
1572      */
1573     @Nullable
getOrCreateRootHomeTask(boolean onTop)1574     ActivityStack getOrCreateRootHomeTask(boolean onTop) {
1575         ActivityStack homeTask = getRootHomeTask();
1576         if (homeTask == null && mDisplayContent.supportsSystemDecorations()) {
1577             homeTask = createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, onTop);
1578         }
1579         return homeTask;
1580     }
1581 
isSplitScreenModeActivated()1582     boolean isSplitScreenModeActivated() {
1583         Task task = getRootSplitScreenPrimaryTask();
1584         return task != null && task.hasChild();
1585     }
1586 
1587     /**
1588      * Returns the topmost stack on the display that is compatible with the input windowing mode.
1589      * Null is no compatible stack on the display.
1590      */
getTopStackInWindowingMode(int windowingMode)1591     ActivityStack getTopStackInWindowingMode(int windowingMode) {
1592         return getStack(windowingMode, ACTIVITY_TYPE_UNDEFINED);
1593     }
1594 
moveHomeStackToFront(String reason)1595     void moveHomeStackToFront(String reason) {
1596         final ActivityStack homeStack = getOrCreateRootHomeTask();
1597         if (homeStack != null) {
1598             homeStack.moveToFront(reason);
1599         }
1600     }
1601 
1602     /**
1603      * Moves the focusable home activity to top. If there is no such activity, the home stack will
1604      * still move to top.
1605      */
moveHomeActivityToTop(String reason)1606     void moveHomeActivityToTop(String reason) {
1607         final ActivityRecord top = getHomeActivity();
1608         if (top == null) {
1609             moveHomeStackToFront(reason);
1610             return;
1611         }
1612         top.moveFocusableActivityToTop(reason);
1613     }
1614 
1615     @Nullable
getHomeActivity()1616     ActivityRecord getHomeActivity() {
1617         return getHomeActivityForUser(mRootWindowContainer.mCurrentUser);
1618     }
1619 
1620     @Nullable
getHomeActivityForUser(int userId)1621     ActivityRecord getHomeActivityForUser(int userId) {
1622         final ActivityStack homeStack = getRootHomeTask();
1623         if (homeStack == null) {
1624             return null;
1625         }
1626 
1627         final PooledPredicate p = PooledLambda.obtainPredicate(
1628                 TaskDisplayArea::isHomeActivityForUser, PooledLambda.__(ActivityRecord.class),
1629                 userId);
1630         final ActivityRecord r = homeStack.getActivity(p);
1631         p.recycle();
1632         return r;
1633     }
1634 
isHomeActivityForUser(ActivityRecord r, int userId)1635     private static boolean isHomeActivityForUser(ActivityRecord r, int userId) {
1636         return r.isActivityTypeHome() && (userId == UserHandle.USER_ALL || r.mUserId == userId);
1637     }
1638 
1639     /**
1640      * Adjusts the {@param stack} behind the last visible stack in the display if necessary.
1641      * Generally used in conjunction with {@link #moveStackBehindStack}.
1642      */
1643     // TODO(b/151575894): Remove special stack movement methods.
moveStackBehindBottomMostVisibleStack(ActivityStack stack)1644     void moveStackBehindBottomMostVisibleStack(ActivityStack stack) {
1645         if (stack.shouldBeVisible(null)) {
1646             // Skip if the stack is already visible
1647             return;
1648         }
1649 
1650         final boolean isRootTask = stack.isRootTask();
1651         if (isRootTask) {
1652             // Move the stack to the bottom to not affect the following visibility checks
1653             positionStackAtBottom(stack);
1654         } else {
1655             stack.getParent().positionChildAt(POSITION_BOTTOM, stack, false /* includingParents */);
1656         }
1657 
1658         // Find the next position where the stack should be placed
1659         final int numStacks = isRootTask ? getStackCount() : stack.getParent().getChildCount();
1660         for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
1661             final ActivityStack s = isRootTask ? getStackAt(stackNdx)
1662                     : (ActivityStack) stack.getParent().getChildAt(stackNdx);
1663             if (s == stack) {
1664                 continue;
1665             }
1666             final int winMode = s.getWindowingMode();
1667             final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN
1668                     || winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
1669             if (s.shouldBeVisible(null) && isValidWindowingMode) {
1670                 // Move the provided stack to behind this stack
1671                 final int position = Math.max(0, stackNdx - 1);
1672                 if (isRootTask) {
1673                     positionStackAt(stack, position);
1674                 } else {
1675                     stack.getParent().positionChildAt(position, stack, false /*includingParents */);
1676                 }
1677                 break;
1678             }
1679         }
1680     }
1681 
1682     /**
1683      * Moves the {@param stack} behind the given {@param behindStack} if possible. If
1684      * {@param behindStack} is not currently in the display, then then the stack is moved to the
1685      * back. Generally used in conjunction with {@link #moveStackBehindBottomMostVisibleStack}.
1686      */
moveStackBehindStack(ActivityStack stack, ActivityStack behindStack)1687     void moveStackBehindStack(ActivityStack stack, ActivityStack behindStack) {
1688         if (behindStack == null || behindStack == stack) {
1689             return;
1690         }
1691 
1692         final WindowContainer parent = stack.getParent();
1693         if (parent == null || parent != behindStack.getParent()) {
1694             return;
1695         }
1696 
1697         // Note that positionChildAt will first remove the given stack before inserting into the
1698         // list, so we need to adjust the insertion index to account for the removed index
1699         // TODO: Remove this logic when WindowContainer.positionChildAt() is updated to adjust the
1700         //       position internally
1701         final int stackIndex = parent.mChildren.indexOf(stack);
1702         final int behindStackIndex = parent.mChildren.indexOf(behindStack);
1703         final int insertIndex = stackIndex <= behindStackIndex
1704                 ? behindStackIndex - 1 : behindStackIndex;
1705         final int position = Math.max(0, insertIndex);
1706         if (stack.isRootTask()) {
1707             positionStackAt(stack, position);
1708         } else {
1709             parent.positionChildAt(position, stack, false /* includingParents */);
1710         }
1711     }
1712 
hasPinnedTask()1713     boolean hasPinnedTask() {
1714         return getRootPinnedTask() != null;
1715     }
1716 
1717     /**
1718      * @return the stack currently above the {@param stack}. Can be null if the {@param stack} is
1719      *         already top-most.
1720      */
getStackAbove(ActivityStack stack)1721     static ActivityStack getStackAbove(ActivityStack stack) {
1722         final WindowContainer wc = stack.getParent();
1723         final int index = wc.mChildren.indexOf(stack) + 1;
1724         return (index < wc.mChildren.size()) ? (ActivityStack) wc.mChildren.get(index) : null;
1725     }
1726 
1727     /** Returns true if the stack in the windowing mode is visible. */
isStackVisible(int windowingMode)1728     boolean isStackVisible(int windowingMode) {
1729         final ActivityStack stack = getTopStackInWindowingMode(windowingMode);
1730         return stack != null && stack.isVisible();
1731     }
1732 
removeStack(ActivityStack stack)1733     void removeStack(ActivityStack stack) {
1734         removeChild(stack);
1735     }
1736 
getDisplayId()1737     int getDisplayId() {
1738         return mDisplayContent.getDisplayId();
1739     }
1740 
isRemoved()1741     boolean isRemoved() {
1742         return mRemoved;
1743     }
1744 
1745     /**
1746      * Adds a listener to be notified whenever the stack order in the display changes. Currently
1747      * only used by the {@link RecentsAnimation} to determine whether to interrupt and cancel the
1748      * current animation when the system state changes.
1749      */
registerStackOrderChangedListener(OnStackOrderChangedListener listener)1750     void registerStackOrderChangedListener(OnStackOrderChangedListener listener) {
1751         if (!mStackOrderChangedCallbacks.contains(listener)) {
1752             mStackOrderChangedCallbacks.add(listener);
1753         }
1754     }
1755 
1756     /**
1757      * Removes a previously registered stack order change listener.
1758      */
unregisterStackOrderChangedListener(OnStackOrderChangedListener listener)1759     void unregisterStackOrderChangedListener(OnStackOrderChangedListener listener) {
1760         mStackOrderChangedCallbacks.remove(listener);
1761     }
1762 
1763     /**
1764      * Notifies of a stack order change
1765      * @param stack The stack which triggered the order change
1766      */
onStackOrderChanged(ActivityStack stack)1767     void onStackOrderChanged(ActivityStack stack) {
1768         for (int i = mStackOrderChangedCallbacks.size() - 1; i >= 0; i--) {
1769             mStackOrderChangedCallbacks.get(i).onStackOrderChanged(stack);
1770         }
1771     }
1772 
1773     @Override
canCreateRemoteAnimationTarget()1774     boolean canCreateRemoteAnimationTarget() {
1775         return true;
1776     }
1777 
1778     /**
1779      * Callback for when the order of the stacks in the display changes.
1780      */
1781     interface OnStackOrderChangedListener {
onStackOrderChanged(ActivityStack stack)1782         void onStackOrderChanged(ActivityStack stack);
1783     }
1784 
ensureActivitiesVisible(ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients)1785     void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
1786             boolean preserveWindows, boolean notifyClients) {
1787         mAtmService.mStackSupervisor.beginActivityVisibilityUpdate();
1788         try {
1789             for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) {
1790                 final ActivityStack stack = getStackAt(stackNdx);
1791                 stack.ensureActivitiesVisible(starting, configChanges, preserveWindows,
1792                         notifyClients);
1793             }
1794         } finally {
1795             mAtmService.mStackSupervisor.endActivityVisibilityUpdate();
1796         }
1797     }
1798 
prepareFreezingTaskBounds()1799     void prepareFreezingTaskBounds() {
1800         for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
1801             final ActivityStack stack = getChildAt(stackNdx);
1802             stack.prepareFreezingTaskBounds();
1803         }
1804     }
1805 
1806     /**
1807      * Removes the stacks in the node applying the content removal node from the display.
1808      * @return last reparented stack, or {@code null} if the stacks had to be destroyed.
1809      */
remove()1810     ActivityStack remove() {
1811         mPreferredTopFocusableStack = null;
1812         // TODO(b/153090332): Allow setting content removal mode per task display area
1813         final boolean destroyContentOnRemoval = mDisplayContent.shouldDestroyContentOnRemove();
1814         final TaskDisplayArea toDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea();
1815         ActivityStack lastReparentedStack = null;
1816 
1817         // Stacks could be reparented from the removed display area to other display area. After
1818         // reparenting the last stack of the removed display area, the display area becomes ready to
1819         // be released (no more ActivityStack-s). But, we cannot release it at that moment or the
1820         // related WindowContainer will also be removed. So, we set display area as removed after
1821         // reparenting stack finished.
1822         // Keep the order from bottom to top.
1823         int numStacks = getStackCount();
1824 
1825         final boolean splitScreenActivated = toDisplayArea.isSplitScreenModeActivated();
1826         final ActivityStack rootStack = splitScreenActivated ? toDisplayArea
1827                 .getTopStackInWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) : null;
1828         for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
1829             final ActivityStack stack = getStackAt(stackNdx);
1830             // Always finish non-standard type stacks.
1831             if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) {
1832                 stack.finishAllActivitiesImmediately();
1833             } else {
1834                 // Reparent the stack to the root task of secondary-split-screen or display area.
1835                 stack.reparent(stack.supportsSplitScreenWindowingMode() && rootStack != null
1836                         ? rootStack : toDisplayArea, POSITION_TOP);
1837 
1838                 // Set the windowing mode to undefined by default to let the stack inherited the
1839                 // windowing mode.
1840                 stack.setWindowingMode(WINDOWING_MODE_UNDEFINED);
1841                 lastReparentedStack = stack;
1842             }
1843             // Stacks may be removed from this display. Ensure each stack will be processed
1844             // and the loop will end.
1845             stackNdx -= numStacks - getStackCount();
1846             numStacks = getStackCount();
1847         }
1848         if (lastReparentedStack != null && splitScreenActivated) {
1849             if (!lastReparentedStack.supportsSplitScreenWindowingMode()) {
1850                 mAtmService.getTaskChangeNotificationController()
1851                         .notifyActivityDismissingDockedStack();
1852                 toDisplayArea.onSplitScreenModeDismissed(lastReparentedStack);
1853             } else if (rootStack != null) {
1854                 // update focus
1855                 rootStack.moveToFront("display-removed");
1856             }
1857         }
1858 
1859         mRemoved = true;
1860 
1861         return lastReparentedStack;
1862     }
1863 
1864 
1865     @Override
dump(PrintWriter pw, String prefix, boolean dumpAll)1866     void dump(PrintWriter pw, String prefix, boolean dumpAll) {
1867         pw.println(prefix + "TaskDisplayArea " + getName());
1868         final String doublePrefix = prefix + "  ";
1869         super.dump(pw, doublePrefix, dumpAll);
1870         if (mPreferredTopFocusableStack != null) {
1871             pw.println(doublePrefix + "mPreferredTopFocusableStack=" + mPreferredTopFocusableStack);
1872         }
1873         if (mLastFocusedStack != null) {
1874             pw.println(doublePrefix + "mLastFocusedStack=" + mLastFocusedStack);
1875         }
1876         final String triplePrefix = doublePrefix + "  ";
1877         pw.println(doublePrefix + "Application tokens in top down Z order:");
1878         for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
1879             final ActivityStack stack = getChildAt(stackNdx);
1880             pw.println(doublePrefix + "* " + stack);
1881             stack.dump(pw, triplePrefix, dumpAll);
1882         }
1883     }
1884 }
1885