1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.server.wm;
18 
19 import static android.app.ActivityTaskManager.INVALID_STACK_ID;
20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
23 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
24 import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
25 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
26 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
27 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
28 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
29 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
30 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
31 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
32 import static android.view.Display.DEFAULT_DISPLAY;
33 import static android.view.Display.FLAG_PRIVATE;
34 import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
35 
36 import static com.android.server.am.ActivityDisplayProto.CONFIGURATION_CONTAINER;
37 import static com.android.server.am.ActivityDisplayProto.FOCUSED_STACK_ID;
38 import static com.android.server.am.ActivityDisplayProto.ID;
39 import static com.android.server.am.ActivityDisplayProto.RESUMED_ACTIVITY;
40 import static com.android.server.am.ActivityDisplayProto.SINGLE_TASK_INSTANCE;
41 import static com.android.server.am.ActivityDisplayProto.STACKS;
42 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
43 import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
44 import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
45 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
46 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
47 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
48 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STACK;
49 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
50 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
51 import static com.android.server.wm.RootActivityContainer.FindTaskResult;
52 import static com.android.server.wm.RootActivityContainer.TAG_STATES;
53 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
54 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
55 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
56 
57 import android.annotation.Nullable;
58 import android.app.ActivityOptions;
59 import android.app.WindowConfiguration;
60 import android.content.res.Configuration;
61 import android.graphics.Point;
62 import android.os.IBinder;
63 import android.os.UserHandle;
64 import android.util.IntArray;
65 import android.util.Slog;
66 import android.util.proto.ProtoOutputStream;
67 import android.view.Display;
68 
69 import com.android.internal.annotations.VisibleForTesting;
70 import com.android.server.am.EventLogTags;
71 
72 import java.io.PrintWriter;
73 import java.util.ArrayList;
74 
75 /**
76  * Exactly one of these classes per Display in the system. Capable of holding zero or more
77  * attached {@link ActivityStack}s.
78  */
79 class ActivityDisplay extends ConfigurationContainer<ActivityStack>
80         implements WindowContainerListener {
81     private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityDisplay" : TAG_ATM;
82     private static final String TAG_STACK = TAG + POSTFIX_STACK;
83 
84     static final int POSITION_TOP = Integer.MAX_VALUE;
85     static final int POSITION_BOTTOM = Integer.MIN_VALUE;
86 
87 
88     /**
89      * Counter for next free stack ID to use for dynamic activity stacks. Unique across displays.
90      */
91     private static int sNextFreeStackId = 0;
92 
93     private ActivityTaskManagerService mService;
94     private RootActivityContainer mRootActivityContainer;
95     // TODO: Remove once unification is complete.
96     DisplayContent mDisplayContent;
97     /** Actual Display this object tracks. */
98     int mDisplayId;
99     Display mDisplay;
100 
101     /**
102      * All of the stacks on this display. Order matters, topmost stack is in front of all other
103      * stacks, bottommost behind. Accessed directly by ActivityManager package classes. Any calls
104      * changing the list should also call {@link #onStackOrderChanged()}.
105      */
106     private final ArrayList<ActivityStack> mStacks = new ArrayList<>();
107     private ArrayList<OnStackOrderChangedListener> mStackOrderChangedCallbacks = new ArrayList<>();
108 
109     /** Array of all UIDs that are present on the display. */
110     private IntArray mDisplayAccessUIDs = new IntArray();
111 
112     /** All tokens used to put activities on this stack to sleep (including mOffToken) */
113     final ArrayList<ActivityTaskManagerInternal.SleepToken> mAllSleepTokens = new ArrayList<>();
114     /** The token acquired by ActivityStackSupervisor to put stacks on the display to sleep */
115     ActivityTaskManagerInternal.SleepToken mOffToken;
116 
117     private boolean mSleeping;
118 
119     /**
120      * The display is removed from the system and we are just waiting for all activities on it to be
121      * finished before removing this object.
122      */
123     private boolean mRemoved;
124 
125     /** The display can only contain one task. */
126     private boolean mSingleTaskInstance;
127 
128     /**
129      * Non-null if the last size compatibility mode activity is using non-native screen
130      * configuration. The activity is not able to put in multi-window mode, so it exists only one
131      * per display.
132      */
133     private ActivityRecord mLastCompatModeActivity;
134 
135     /**
136      * A focusable stack that is purposely to be positioned at the top. Although the stack may not
137      * have the topmost index, it is used as a preferred candidate to prevent being unable to resume
138      * target stack properly when there are other focusable always-on-top stacks.
139      */
140     private ActivityStack mPreferredTopFocusableStack;
141 
142     /**
143      * If this is the same as {@link #getFocusedStack} then the activity on the top of the focused
144      * stack has been resumed. If stacks are changing position this will hold the old stack until
145      * the new stack becomes resumed after which it will be set to current focused stack.
146      */
147     private ActivityStack mLastFocusedStack;
148 
149     // Cached reference to some special stacks we tend to get a lot so we don't need to loop
150     // through the list to find them.
151     private ActivityStack mHomeStack = null;
152     private ActivityStack mRecentsStack = null;
153     private ActivityStack mPinnedStack = null;
154     private ActivityStack mSplitScreenPrimaryStack = null;
155 
156     // Used in updating the display size
157     private Point mTmpDisplaySize = new Point();
158 
159     private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
160 
ActivityDisplay(RootActivityContainer root, Display display)161     ActivityDisplay(RootActivityContainer root, Display display) {
162         mRootActivityContainer = root;
163         mService = root.mService;
164         mDisplayId = display.getDisplayId();
165         mDisplay = display;
166         mDisplayContent = createDisplayContent();
167         updateBounds();
168     }
169 
createDisplayContent()170     protected DisplayContent createDisplayContent() {
171         return mService.mWindowManager.mRoot.createDisplayContent(mDisplay, this);
172     }
173 
updateBounds()174     private void updateBounds() {
175         mDisplay.getRealSize(mTmpDisplaySize);
176         setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
177     }
178 
onDisplayChanged()179     void onDisplayChanged() {
180         // The window policy is responsible for stopping activities on the default display.
181         final int displayId = mDisplay.getDisplayId();
182         if (displayId != DEFAULT_DISPLAY) {
183             final int displayState = mDisplay.getState();
184             if (displayState == Display.STATE_OFF && mOffToken == null) {
185                 mOffToken = mService.acquireSleepToken("Display-off", displayId);
186             } else if (displayState == Display.STATE_ON && mOffToken != null) {
187                 mOffToken.release();
188                 mOffToken = null;
189             }
190         }
191 
192         updateBounds();
193         if (mDisplayContent != null) {
194             mDisplayContent.updateDisplayInfo();
195             mService.mWindowManager.requestTraversal();
196         }
197     }
198 
199     @Override
onInitializeOverrideConfiguration(Configuration config)200     public void onInitializeOverrideConfiguration(Configuration config) {
201         getRequestedOverrideConfiguration().updateFrom(config);
202     }
203 
addChild(ActivityStack stack, int position)204     void addChild(ActivityStack stack, int position) {
205         if (position == POSITION_BOTTOM) {
206             position = 0;
207         } else if (position == POSITION_TOP) {
208             position = mStacks.size();
209         }
210         if (DEBUG_STACK) Slog.v(TAG_STACK, "addChild: attaching " + stack
211                 + " to displayId=" + mDisplayId + " position=" + position);
212         addStackReferenceIfNeeded(stack);
213         positionChildAt(stack, position);
214         mService.updateSleepIfNeededLocked();
215     }
216 
removeChild(ActivityStack stack)217     void removeChild(ActivityStack stack) {
218         if (DEBUG_STACK) Slog.v(TAG_STACK, "removeChild: detaching " + stack
219                 + " from displayId=" + mDisplayId);
220         mStacks.remove(stack);
221         if (mPreferredTopFocusableStack == stack) {
222             mPreferredTopFocusableStack = null;
223         }
224         removeStackReferenceIfNeeded(stack);
225         releaseSelfIfNeeded();
226         mService.updateSleepIfNeededLocked();
227         onStackOrderChanged(stack);
228     }
229 
positionChildAtTop(ActivityStack stack, boolean includingParents)230     void positionChildAtTop(ActivityStack stack, boolean includingParents) {
231         positionChildAtTop(stack, includingParents, null /* updateLastFocusedStackReason */);
232     }
233 
positionChildAtTop(ActivityStack stack, boolean includingParents, String updateLastFocusedStackReason)234     void positionChildAtTop(ActivityStack stack, boolean includingParents,
235             String updateLastFocusedStackReason) {
236         positionChildAt(stack, mStacks.size(), includingParents, updateLastFocusedStackReason);
237     }
238 
positionChildAtBottom(ActivityStack stack)239     void positionChildAtBottom(ActivityStack stack) {
240         positionChildAtBottom(stack, null /* updateLastFocusedStackReason */);
241     }
242 
positionChildAtBottom(ActivityStack stack, String updateLastFocusedStackReason)243     void positionChildAtBottom(ActivityStack stack, String updateLastFocusedStackReason) {
244         positionChildAt(stack, 0, false /* includingParents */, updateLastFocusedStackReason);
245     }
246 
positionChildAt(ActivityStack stack, int position)247     private void positionChildAt(ActivityStack stack, int position) {
248         positionChildAt(stack, position, false /* includingParents */,
249                 null /* updateLastFocusedStackReason */);
250     }
251 
positionChildAt(ActivityStack stack, int position, boolean includingParents, String updateLastFocusedStackReason)252     private void positionChildAt(ActivityStack stack, int position, boolean includingParents,
253             String updateLastFocusedStackReason) {
254         // TODO: Keep in sync with WindowContainer.positionChildAt(), once we change that to adjust
255         //       the position internally, also update the logic here
256         final ActivityStack prevFocusedStack = updateLastFocusedStackReason != null
257                 ? getFocusedStack() : null;
258         final boolean wasContained = mStacks.remove(stack);
259         if (mSingleTaskInstance && getChildCount() > 0) {
260             throw new IllegalStateException(
261                     "positionChildAt: Can only have one child on display=" + this);
262         }
263         final int insertPosition = getTopInsertPosition(stack, position);
264         mStacks.add(insertPosition, stack);
265 
266         // The insert position may be adjusted to non-top when there is always-on-top stack. Since
267         // the original position is preferred to be top, the stack should have higher priority when
268         // we are looking for top focusable stack. The condition {@code wasContained} restricts the
269         // preferred stack is set only when moving an existing stack to top instead of adding a new
270         // stack that may be too early (e.g. in the middle of launching or reparenting).
271         if (wasContained && position >= mStacks.size() - 1 && stack.isFocusableAndVisible()) {
272             mPreferredTopFocusableStack = stack;
273         } else if (mPreferredTopFocusableStack == stack) {
274             mPreferredTopFocusableStack = null;
275         }
276 
277         if (updateLastFocusedStackReason != null) {
278             final ActivityStack currentFocusedStack = getFocusedStack();
279             if (currentFocusedStack != prevFocusedStack) {
280                 mLastFocusedStack = prevFocusedStack;
281                 EventLogTags.writeAmFocusedStack(mRootActivityContainer.mCurrentUser, mDisplayId,
282                         currentFocusedStack == null ? -1 : currentFocusedStack.getStackId(),
283                         mLastFocusedStack == null ? -1 : mLastFocusedStack.getStackId(),
284                         updateLastFocusedStackReason);
285             }
286         }
287 
288         // Since positionChildAt() is called during the creation process of pinned stacks,
289         // ActivityStack#getStack() can be null. In this special case,
290         // since DisplayContest#positionStackAt() is called in TaskStack#onConfigurationChanged(),
291         // we don't have to call WindowContainerController#positionChildAt() here.
292         if (stack.getTaskStack() != null && mDisplayContent != null) {
293             mDisplayContent.positionStackAt(insertPosition,
294                     stack.getTaskStack(), includingParents);
295         }
296         if (!wasContained) {
297             stack.setParent(this);
298         }
299         onStackOrderChanged(stack);
300     }
301 
getTopInsertPosition(ActivityStack stack, int candidatePosition)302     private int getTopInsertPosition(ActivityStack stack, int candidatePosition) {
303         int position = mStacks.size();
304         if (stack.inPinnedWindowingMode()) {
305             // Stack in pinned windowing mode is z-ordered on-top of all other stacks so okay to
306             // just return the candidate position.
307             return Math.min(position, candidatePosition);
308         }
309         while (position > 0) {
310             final ActivityStack targetStack = mStacks.get(position - 1);
311             if (!targetStack.isAlwaysOnTop()) {
312                 // We reached a stack that isn't always-on-top.
313                 break;
314             }
315             if (stack.isAlwaysOnTop() && !targetStack.inPinnedWindowingMode()) {
316                 // Always on-top non-pinned windowing mode stacks can go anywhere below pinned stack.
317                 break;
318             }
319             position--;
320         }
321         return Math.min(position, candidatePosition);
322     }
323 
getStack(int stackId)324     <T extends ActivityStack> T getStack(int stackId) {
325         for (int i = mStacks.size() - 1; i >= 0; --i) {
326             final ActivityStack stack = mStacks.get(i);
327             if (stack.mStackId == stackId) {
328                 return (T) stack;
329             }
330         }
331         return null;
332     }
333 
334     /**
335      * @return the topmost stack on the display that is compatible with the input windowing mode and
336      * activity type. {@code null} means no compatible stack on the display.
337      * @see ConfigurationContainer#isCompatible(int, int)
338      */
getStack(int windowingMode, int activityType)339     <T extends ActivityStack> T getStack(int windowingMode, int activityType) {
340         if (activityType == ACTIVITY_TYPE_HOME) {
341             return (T) mHomeStack;
342         } else if (activityType == ACTIVITY_TYPE_RECENTS) {
343             return (T) mRecentsStack;
344         }
345         if (windowingMode == WINDOWING_MODE_PINNED) {
346             return (T) mPinnedStack;
347         } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
348             return (T) mSplitScreenPrimaryStack;
349         }
350 
351         for (int i = mStacks.size() - 1; i >= 0; --i) {
352             final ActivityStack stack = mStacks.get(i);
353             if (stack.isCompatible(windowingMode, activityType)) {
354                 return (T) stack;
355             }
356         }
357         return null;
358     }
359 
alwaysCreateStack(int windowingMode, int activityType)360     private boolean alwaysCreateStack(int windowingMode, int activityType) {
361         // Always create a stack for fullscreen, freeform, and split-screen-secondary windowing
362         // modes so that we can manage visual ordering and return types correctly.
363         return activityType == ACTIVITY_TYPE_STANDARD
364                 && (windowingMode == WINDOWING_MODE_FULLSCREEN
365                 || windowingMode == WINDOWING_MODE_FREEFORM
366                 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
367     }
368 
369     /**
370      * Returns an existing stack compatible with the windowing mode and activity type or creates one
371      * if a compatible stack doesn't exist.
372      * @see #getStack(int, int)
373      * @see #createStack(int, int, boolean)
374      */
getOrCreateStack(int windowingMode, int activityType, boolean onTop)375     <T extends ActivityStack> T getOrCreateStack(int windowingMode, int activityType,
376             boolean onTop) {
377         if (!alwaysCreateStack(windowingMode, activityType)) {
378             T stack = getStack(windowingMode, activityType);
379             if (stack != null) {
380                 return stack;
381             }
382         }
383         return createStack(windowingMode, activityType, onTop);
384     }
385 
386     /**
387      * Returns an existing stack compatible with the input params or creates one
388      * if a compatible stack doesn't exist.
389      * @see #getOrCreateStack(int, int, boolean)
390      */
getOrCreateStack(@ullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, int activityType, boolean onTop)391     <T extends ActivityStack> T getOrCreateStack(@Nullable ActivityRecord r,
392             @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, int activityType,
393             boolean onTop) {
394         // First preference is the windowing mode in the activity options if set.
395         int windowingMode = (options != null)
396                 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
397         // Validate that our desired windowingMode will work under the current conditions.
398         // UNDEFINED windowing mode is a valid result and means that the new stack will inherit
399         // it's display's windowing mode.
400         windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType);
401         return getOrCreateStack(windowingMode, activityType, onTop);
402     }
403 
404     @VisibleForTesting
getNextStackId()405     int getNextStackId() {
406         return sNextFreeStackId++;
407     }
408 
409     /**
410      * Creates a stack matching the input windowing mode and activity type on this display.
411      * @param windowingMode The windowing mode the stack should be created in. If
412      *                      {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will
413      *                      inherit it's parent's windowing mode.
414      * @param activityType The activityType the stack should be created in. If
415      *                     {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will
416      *                     be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
417      * @param onTop If true the stack will be created at the top of the display, else at the bottom.
418      * @return The newly created stack.
419      */
createStack(int windowingMode, int activityType, boolean onTop)420     <T extends ActivityStack> T createStack(int windowingMode, int activityType, boolean onTop) {
421 
422         if (mSingleTaskInstance && getChildCount() > 0) {
423             // Create stack on default display instead since this display can only contain 1 stack.
424             // TODO: Kinda a hack, but better that having the decision at each call point. Hoping
425             // this goes away once ActivityView is no longer using virtual displays.
426             return mRootActivityContainer.getDefaultDisplay().createStack(
427                     windowingMode, activityType, onTop);
428         }
429 
430         if (activityType == ACTIVITY_TYPE_UNDEFINED) {
431             // Can't have an undefined stack type yet...so re-map to standard. Anyone that wants
432             // anything else should be passing it in anyways...
433             activityType = ACTIVITY_TYPE_STANDARD;
434         }
435 
436         if (activityType != ACTIVITY_TYPE_STANDARD) {
437             // For now there can be only one stack of a particular non-standard activity type on a
438             // display. So, get that ignoring whatever windowing mode it is currently in.
439             T stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
440             if (stack != null) {
441                 throw new IllegalArgumentException("Stack=" + stack + " of activityType="
442                         + activityType + " already on display=" + this + ". Can't have multiple.");
443             }
444         }
445 
446         if (!isWindowingModeSupported(windowingMode, mService.mSupportsMultiWindow,
447                 mService.mSupportsSplitScreenMultiWindow,
448                 mService.mSupportsFreeformWindowManagement, mService.mSupportsPictureInPicture,
449                 activityType)) {
450             throw new IllegalArgumentException("Can't create stack for unsupported windowingMode="
451                     + windowingMode);
452         }
453 
454         final int stackId = getNextStackId();
455         return createStackUnchecked(windowingMode, activityType, stackId, onTop);
456     }
457 
458     @VisibleForTesting
createStackUnchecked(int windowingMode, int activityType, int stackId, boolean onTop)459     <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
460             int stackId, boolean onTop) {
461         if (windowingMode == WINDOWING_MODE_PINNED && activityType != ACTIVITY_TYPE_STANDARD) {
462             throw new IllegalArgumentException("Stack with windowing mode cannot with non standard "
463                     + "activity type.");
464         }
465         return (T) new ActivityStack(this, stackId,
466                 mRootActivityContainer.mStackSupervisor, windowingMode, activityType, onTop);
467     }
468 
469     /**
470      * Get the preferred focusable stack in priority. If the preferred stack does not exist, find a
471      * focusable and visible stack from the top of stacks in this display.
472      */
getFocusedStack()473     ActivityStack getFocusedStack() {
474         if (mPreferredTopFocusableStack != null) {
475             return mPreferredTopFocusableStack;
476         }
477 
478         for (int i = mStacks.size() - 1; i >= 0; --i) {
479             final ActivityStack stack = mStacks.get(i);
480             if (stack.isFocusableAndVisible()) {
481                 return stack;
482             }
483         }
484 
485         return null;
486     }
487 
getNextFocusableStack()488     ActivityStack getNextFocusableStack() {
489         return getNextFocusableStack(null /* currentFocus */, false /* ignoreCurrent */);
490     }
491 
getNextFocusableStack(ActivityStack currentFocus, boolean ignoreCurrent)492     ActivityStack getNextFocusableStack(ActivityStack currentFocus, boolean ignoreCurrent) {
493         final int currentWindowingMode = currentFocus != null
494                 ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
495 
496         ActivityStack candidate = null;
497         for (int i = mStacks.size() - 1; i >= 0; --i) {
498             final ActivityStack stack = mStacks.get(i);
499             if (ignoreCurrent && stack == currentFocus) {
500                 continue;
501             }
502             if (!stack.isFocusableAndVisible()) {
503                 continue;
504             }
505 
506             if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
507                     && candidate == null && stack.inSplitScreenPrimaryWindowingMode()) {
508                 // If the currently focused stack is in split-screen secondary we save off the
509                 // top primary split-screen stack as a candidate for focus because we might
510                 // prefer focus to move to an other stack to avoid primary split-screen stack
511                 // overlapping with a fullscreen stack when a fullscreen stack is higher in z
512                 // than the next split-screen stack. Assistant stack, I am looking at you...
513                 // We only move the focus to the primary-split screen stack if there isn't a
514                 // better alternative.
515                 candidate = stack;
516                 continue;
517             }
518             if (candidate != null && stack.inSplitScreenSecondaryWindowingMode()) {
519                 // Use the candidate stack since we are now at the secondary split-screen.
520                 return candidate;
521             }
522             return stack;
523         }
524         return candidate;
525     }
526 
getResumedActivity()527     ActivityRecord getResumedActivity() {
528         final ActivityStack focusedStack = getFocusedStack();
529         if (focusedStack == null) {
530             return null;
531         }
532         // TODO(b/111541062): Move this into ActivityStack#getResumedActivity()
533         // Check if the focused stack has the resumed activity
534         ActivityRecord resumedActivity = focusedStack.getResumedActivity();
535         if (resumedActivity == null || resumedActivity.app == null) {
536             // If there is no registered resumed activity in the stack or it is not running -
537             // try to use previously resumed one.
538             resumedActivity = focusedStack.mPausingActivity;
539             if (resumedActivity == null || resumedActivity.app == null) {
540                 // If previously resumed activity doesn't work either - find the topmost running
541                 // activity that can be focused.
542                 resumedActivity = focusedStack.topRunningActivityLocked(true /* focusableOnly */);
543             }
544         }
545         return resumedActivity;
546     }
547 
getLastFocusedStack()548     ActivityStack getLastFocusedStack() {
549         return mLastFocusedStack;
550     }
551 
allResumedActivitiesComplete()552     boolean allResumedActivitiesComplete() {
553         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
554             final ActivityRecord r = mStacks.get(stackNdx).getResumedActivity();
555             if (r != null && !r.isState(RESUMED)) {
556                 return false;
557             }
558         }
559         final ActivityStack currentFocusedStack = getFocusedStack();
560         if (DEBUG_STACK) {
561             Slog.d(TAG_STACK, "allResumedActivitiesComplete: mLastFocusedStack changing from="
562                     + mLastFocusedStack + " to=" + currentFocusedStack);
563         }
564         mLastFocusedStack = currentFocusedStack;
565         return true;
566     }
567 
568     /**
569      * Pause all activities in either all of the stacks or just the back stacks. This is done before
570      * resuming a new activity and to make sure that previously active activities are
571      * paused in stacks that are no longer visible or in pinned windowing mode. This does not
572      * pause activities in visible stacks, so if an activity is launched within the same stack/task,
573      * then we should explicitly pause that stack's top activity.
574      * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
575      * @param resuming The resuming activity.
576      * @param dontWait The resuming activity isn't going to wait for all activities to be paused
577      *                 before resuming.
578      * @return {@code true} if any activity was paused as a result of this call.
579      */
pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait)580     boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
581         boolean someActivityPaused = false;
582         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
583             final ActivityStack stack = mStacks.get(stackNdx);
584             final ActivityRecord resumedActivity = stack.getResumedActivity();
585             if (resumedActivity != null
586                     && (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
587                         || !stack.isFocusable())) {
588                 if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
589                         " mResumedActivity=" + resumedActivity);
590                 someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
591                         dontWait);
592             }
593         }
594         return someActivityPaused;
595     }
596 
597     /**
598      * Find task for putting the Activity in.
599      */
findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplay, FindTaskResult result)600     void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplay,
601             FindTaskResult result) {
602         mTmpFindTaskResult.clear();
603         for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
604             final ActivityStack stack = getChildAt(stackNdx);
605             if (!r.hasCompatibleActivityType(stack)) {
606                 if (DEBUG_TASKS) {
607                     Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) " + stack);
608                 }
609                 continue;
610             }
611 
612             stack.findTaskLocked(r, mTmpFindTaskResult);
613             // It is possible to have tasks in multiple stacks with the same root affinity, so
614             // we should keep looking after finding an affinity match to see if there is a
615             // better match in another stack. Also, task affinity isn't a good enough reason
616             // to target a display which isn't the source of the intent, so skip any affinity
617             // matches not on the specified display.
618             if (mTmpFindTaskResult.mRecord != null) {
619                 if (mTmpFindTaskResult.mIdealMatch) {
620                     result.setTo(mTmpFindTaskResult);
621                     return;
622                 } else if (isPreferredDisplay) {
623                     // Note: since the traversing through the stacks is top down, the floating
624                     // tasks should always have lower priority than any affinity-matching tasks
625                     // in the fullscreen stacks
626                     result.setTo(mTmpFindTaskResult);
627                 }
628             }
629         }
630     }
631 
632     /**
633      * Removes stacks in the input windowing modes from the system if they are of activity type
634      * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
635      */
removeStacksInWindowingModes(int... windowingModes)636     void removeStacksInWindowingModes(int... windowingModes) {
637         if (windowingModes == null || windowingModes.length == 0) {
638             return;
639         }
640 
641         // Collect the stacks that are necessary to be removed instead of performing the removal
642         // by looping mStacks, so that we don't miss any stacks after the stack size changed or
643         // stacks reordered.
644         final ArrayList<ActivityStack> stacks = new ArrayList<>();
645         for (int j = windowingModes.length - 1 ; j >= 0; --j) {
646             final int windowingMode = windowingModes[j];
647             for (int i = mStacks.size() - 1; i >= 0; --i) {
648                 final ActivityStack stack = mStacks.get(i);
649                 if (!stack.isActivityTypeStandardOrUndefined()) {
650                     continue;
651                 }
652                 if (stack.getWindowingMode() != windowingMode) {
653                     continue;
654                 }
655                 stacks.add(stack);
656             }
657         }
658 
659         for (int i = stacks.size() - 1; i >= 0; --i) {
660             mRootActivityContainer.mStackSupervisor.removeStack(stacks.get(i));
661         }
662     }
663 
removeStacksWithActivityTypes(int... activityTypes)664     void removeStacksWithActivityTypes(int... activityTypes) {
665         if (activityTypes == null || activityTypes.length == 0) {
666             return;
667         }
668 
669         // Collect the stacks that are necessary to be removed instead of performing the removal
670         // by looping mStacks, so that we don't miss any stacks after the stack size changed or
671         // stacks reordered.
672         final ArrayList<ActivityStack> stacks = new ArrayList<>();
673         for (int j = activityTypes.length - 1 ; j >= 0; --j) {
674             final int activityType = activityTypes[j];
675             for (int i = mStacks.size() - 1; i >= 0; --i) {
676                 final ActivityStack stack = mStacks.get(i);
677                 if (stack.getActivityType() == activityType) {
678                     stacks.add(stack);
679                 }
680             }
681         }
682 
683         for (int i = stacks.size() - 1; i >= 0; --i) {
684             mRootActivityContainer.mStackSupervisor.removeStack(stacks.get(i));
685         }
686     }
687 
onStackWindowingModeChanged(ActivityStack stack)688     void onStackWindowingModeChanged(ActivityStack stack) {
689         removeStackReferenceIfNeeded(stack);
690         addStackReferenceIfNeeded(stack);
691     }
692 
addStackReferenceIfNeeded(ActivityStack stack)693     private void addStackReferenceIfNeeded(ActivityStack stack) {
694         final int activityType = stack.getActivityType();
695         final int windowingMode = stack.getWindowingMode();
696 
697         if (activityType == ACTIVITY_TYPE_HOME) {
698             if (mHomeStack != null && mHomeStack != stack) {
699                 throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
700                         + mHomeStack + " already exist on display=" + this + " stack=" + stack);
701             }
702             mHomeStack = stack;
703         } else if (activityType == ACTIVITY_TYPE_RECENTS) {
704             if (mRecentsStack != null && mRecentsStack != stack) {
705                 throw new IllegalArgumentException("addStackReferenceIfNeeded: recents stack="
706                         + mRecentsStack + " already exist on display=" + this + " stack=" + stack);
707             }
708             mRecentsStack = stack;
709         }
710         if (windowingMode == WINDOWING_MODE_PINNED) {
711             if (mPinnedStack != null && mPinnedStack != stack) {
712                 throw new IllegalArgumentException("addStackReferenceIfNeeded: pinned stack="
713                         + mPinnedStack + " already exist on display=" + this
714                         + " stack=" + stack);
715             }
716             mPinnedStack = stack;
717         } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
718             if (mSplitScreenPrimaryStack != null && mSplitScreenPrimaryStack != stack) {
719                 throw new IllegalArgumentException("addStackReferenceIfNeeded:"
720                         + " split-screen-primary" + " stack=" + mSplitScreenPrimaryStack
721                         + " already exist on display=" + this + " stack=" + stack);
722             }
723             mSplitScreenPrimaryStack = stack;
724             onSplitScreenModeActivated();
725         }
726     }
727 
removeStackReferenceIfNeeded(ActivityStack stack)728     private void removeStackReferenceIfNeeded(ActivityStack stack) {
729         if (stack == mHomeStack) {
730             mHomeStack = null;
731         } else if (stack == mRecentsStack) {
732             mRecentsStack = null;
733         } else if (stack == mPinnedStack) {
734             mPinnedStack = null;
735         } else if (stack == mSplitScreenPrimaryStack) {
736             mSplitScreenPrimaryStack = null;
737             // Inform the reset of the system that split-screen mode was dismissed so things like
738             // resizing all the other stacks can take place.
739             onSplitScreenModeDismissed();
740         }
741     }
742 
onSplitScreenModeDismissed()743     private void onSplitScreenModeDismissed() {
744         mRootActivityContainer.mWindowManager.deferSurfaceLayout();
745         try {
746             // Adjust the windowing mode of any stack in secondary split-screen to fullscreen.
747             for (int i = mStacks.size() - 1; i >= 0; --i) {
748                 final ActivityStack otherStack = mStacks.get(i);
749                 if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
750                     continue;
751                 }
752                 otherStack.setWindowingMode(WINDOWING_MODE_UNDEFINED, false /* animate */,
753                         false /* showRecents */, false /* enteringSplitScreenMode */,
754                         true /* deferEnsuringVisibility */, false /* creating */);
755             }
756         } finally {
757             final ActivityStack topFullscreenStack =
758                     getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN);
759             if (topFullscreenStack != null && mHomeStack != null && !isTopStack(mHomeStack)) {
760                 // Whenever split-screen is dismissed we want the home stack directly behind the
761                 // current top fullscreen stack so it shows up when the top stack is finished.
762                 // TODO: Would be better to use ActivityDisplay.positionChildAt() for this, however
763                 // ActivityDisplay doesn't have a direct controller to WM side yet. We can switch
764                 // once we have that.
765                 mHomeStack.moveToFront("onSplitScreenModeDismissed");
766                 topFullscreenStack.moveToFront("onSplitScreenModeDismissed");
767             }
768             mRootActivityContainer.mWindowManager.continueSurfaceLayout();
769         }
770     }
771 
onSplitScreenModeActivated()772     private void onSplitScreenModeActivated() {
773         mRootActivityContainer.mWindowManager.deferSurfaceLayout();
774         try {
775             // Adjust the windowing mode of any affected by split-screen to split-screen secondary.
776             for (int i = mStacks.size() - 1; i >= 0; --i) {
777                 final ActivityStack otherStack = mStacks.get(i);
778                 if (otherStack == mSplitScreenPrimaryStack
779                         || !otherStack.affectedBySplitScreenResize()) {
780                     continue;
781                 }
782                 otherStack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
783                         false /* animate */, false /* showRecents */,
784                         true /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */,
785                         false /* creating */);
786             }
787         } finally {
788             mRootActivityContainer.mWindowManager.continueSurfaceLayout();
789         }
790     }
791 
792     /**
793      * Returns true if the {@param windowingMode} is supported based on other parameters passed in.
794      * @param windowingMode The windowing mode we are checking support for.
795      * @param supportsMultiWindow If we should consider support for multi-window mode in general.
796      * @param supportsSplitScreen If we should consider support for split-screen multi-window.
797      * @param supportsFreeform If we should consider support for freeform multi-window.
798      * @param supportsPip If we should consider support for picture-in-picture mutli-window.
799      * @param activityType The activity type under consideration.
800      * @return true if the windowing mode is supported.
801      */
isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow, boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip, int activityType)802     private boolean isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow,
803             boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip,
804             int activityType) {
805 
806         if (windowingMode == WINDOWING_MODE_UNDEFINED
807                 || windowingMode == WINDOWING_MODE_FULLSCREEN) {
808             return true;
809         }
810         if (!supportsMultiWindow) {
811             return false;
812         }
813 
814         final int displayWindowingMode = getWindowingMode();
815         if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
816                 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
817             return supportsSplitScreen
818                     && WindowConfiguration.supportSplitScreenWindowingMode(activityType)
819                     // Freeform windows and split-screen windows don't mix well, so prevent
820                     // split windowing modes on freeform displays.
821                     && displayWindowingMode != WINDOWING_MODE_FREEFORM;
822         }
823 
824         if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) {
825             return false;
826         }
827 
828         if (!supportsPip && windowingMode == WINDOWING_MODE_PINNED) {
829             return false;
830         }
831         return true;
832     }
833 
834     /**
835      * Resolves the windowing mode that an {@link ActivityRecord} would be in if started on this
836      * display with the provided parameters.
837      *
838      * @param r The ActivityRecord in question.
839      * @param options Options to start with.
840      * @param task The task within-which the activity would start.
841      * @param activityType The type of activity to start.
842      * @return The resolved (not UNDEFINED) windowing-mode that the activity would be in.
843      */
resolveWindowingMode(@ullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable TaskRecord task, int activityType)844     int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
845             @Nullable TaskRecord task, int activityType) {
846 
847         // First preference if the windowing mode in the activity options if set.
848         int windowingMode = (options != null)
849                 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
850 
851         // If windowing mode is unset, then next preference is the candidate task, then the
852         // activity record.
853         if (windowingMode == WINDOWING_MODE_UNDEFINED) {
854             if (task != null) {
855                 windowingMode = task.getWindowingMode();
856             }
857             if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) {
858                 windowingMode = r.getWindowingMode();
859             }
860             if (windowingMode == WINDOWING_MODE_UNDEFINED) {
861                 // Use the display's windowing mode.
862                 windowingMode = getWindowingMode();
863             }
864         }
865         windowingMode = validateWindowingMode(windowingMode, r, task, activityType);
866         return windowingMode != WINDOWING_MODE_UNDEFINED
867                 ? windowingMode : WINDOWING_MODE_FULLSCREEN;
868     }
869 
870     /**
871      * Check that the requested windowing-mode is appropriate for the specified task and/or activity
872      * on this display.
873      *
874      * @param windowingMode The windowing-mode to validate.
875      * @param r The {@link ActivityRecord} to check against.
876      * @param task The {@link TaskRecord} to check against.
877      * @param activityType An activity type.
878      * @return The provided windowingMode or the closest valid mode which is appropriate.
879      */
validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable TaskRecord task, int activityType)880     int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r,
881         @Nullable TaskRecord task, int activityType) {
882         // Make sure the windowing mode we are trying to use makes sense for what is supported.
883         boolean supportsMultiWindow = mService.mSupportsMultiWindow;
884         boolean supportsSplitScreen = mService.mSupportsSplitScreenMultiWindow;
885         boolean supportsFreeform = mService.mSupportsFreeformWindowManagement;
886         boolean supportsPip = mService.mSupportsPictureInPicture;
887         if (supportsMultiWindow) {
888             if (task != null) {
889                 supportsMultiWindow = task.isResizeable();
890                 supportsSplitScreen = task.supportsSplitScreenWindowingMode();
891                 // TODO: Do we need to check for freeform and Pip support here?
892             } else if (r != null) {
893                 supportsMultiWindow = r.isResizeable();
894                 supportsSplitScreen = r.supportsSplitScreenWindowingMode();
895                 supportsFreeform = r.supportsFreeform();
896                 supportsPip = r.supportsPictureInPicture();
897             }
898         }
899 
900         final boolean inSplitScreenMode = hasSplitScreenPrimaryStack();
901         if (!inSplitScreenMode
902                 && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) {
903             // Switch to the display's windowing mode if we are not in split-screen mode and we are
904             // trying to launch in split-screen secondary.
905             windowingMode = WINDOWING_MODE_UNDEFINED;
906         } else if (inSplitScreenMode && (windowingMode == WINDOWING_MODE_FULLSCREEN
907                         || windowingMode == WINDOWING_MODE_UNDEFINED)
908                 && supportsSplitScreen) {
909             windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
910         }
911 
912         if (windowingMode != WINDOWING_MODE_UNDEFINED
913                 && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen,
914                         supportsFreeform, supportsPip, activityType)) {
915             return windowingMode;
916         }
917         return WINDOWING_MODE_UNDEFINED;
918     }
919 
920     /**
921      * Get the topmost stack on the display. It may be different from focused stack, because
922      * some stacks are not focusable (e.g. PiP).
923      */
getTopStack()924     ActivityStack getTopStack() {
925         return mStacks.isEmpty() ? null : mStacks.get(mStacks.size() - 1);
926     }
927 
isTopStack(ActivityStack stack)928     boolean isTopStack(ActivityStack stack) {
929         return stack == getTopStack();
930     }
931 
isTopNotPinnedStack(ActivityStack stack)932     boolean isTopNotPinnedStack(ActivityStack stack) {
933         for (int i = mStacks.size() - 1; i >= 0; --i) {
934             final ActivityStack current = mStacks.get(i);
935             if (!current.inPinnedWindowingMode()) {
936                 return current == stack;
937             }
938         }
939         return false;
940     }
941 
getTopStackInWindowingMode(int windowingMode)942     ActivityStack getTopStackInWindowingMode(int windowingMode) {
943         for (int i = mStacks.size() - 1; i >= 0; --i) {
944             final ActivityStack current = mStacks.get(i);
945             if (windowingMode == current.getWindowingMode()) {
946                 return current;
947             }
948         }
949         return null;
950     }
951 
topRunningActivity()952     ActivityRecord topRunningActivity() {
953         return topRunningActivity(false /* considerKeyguardState */);
954     }
955 
956     /**
957      * Returns the top running activity in the focused stack. In the case the focused stack has no
958      * such activity, the next focusable stack on this display is returned.
959      *
960      * @param considerKeyguardState Indicates whether the locked state should be considered. if
961      *                              {@code true} and the keyguard is locked, only activities that
962      *                              can be shown on top of the keyguard will be considered.
963      * @return The top running activity. {@code null} if none is available.
964      */
topRunningActivity(boolean considerKeyguardState)965     ActivityRecord topRunningActivity(boolean considerKeyguardState) {
966         ActivityRecord topRunning = null;
967         final ActivityStack focusedStack = getFocusedStack();
968         if (focusedStack != null) {
969             topRunning = focusedStack.topRunningActivityLocked();
970         }
971 
972         // Look in other focusable stacks.
973         if (topRunning == null) {
974             for (int i = mStacks.size() - 1; i >= 0; --i) {
975                 final ActivityStack stack = mStacks.get(i);
976                 // Only consider focusable stacks other than the current focused one.
977                 if (stack == focusedStack || !stack.isFocusable()) {
978                     continue;
979                 }
980                 topRunning = stack.topRunningActivityLocked();
981                 if (topRunning != null) {
982                     break;
983                 }
984             }
985         }
986 
987         // This activity can be considered the top running activity if we are not considering
988         // the locked state, the keyguard isn't locked, or we can show when locked.
989         if (topRunning != null && considerKeyguardState
990                 && mRootActivityContainer.mStackSupervisor.getKeyguardController().isKeyguardLocked()
991                 && !topRunning.canShowWhenLocked()) {
992             return null;
993         }
994 
995         return topRunning;
996     }
997 
getIndexOf(ActivityStack stack)998     int getIndexOf(ActivityStack stack) {
999         return mStacks.indexOf(stack);
1000     }
1001 
1002     @Override
onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration)1003     public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
1004         final int currRotation =
1005                 getRequestedOverrideConfiguration().windowConfiguration.getRotation();
1006         if (currRotation != ROTATION_UNDEFINED
1007                 && currRotation != overrideConfiguration.windowConfiguration.getRotation()
1008                 && mDisplayContent != null) {
1009             mDisplayContent.applyRotationLocked(currRotation,
1010                     overrideConfiguration.windowConfiguration.getRotation());
1011         }
1012         super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
1013         if (mDisplayContent != null) {
1014             mService.mWindowManager.setNewDisplayOverrideConfiguration(
1015                     overrideConfiguration, mDisplayContent);
1016         }
1017     }
1018 
1019     @Override
onConfigurationChanged(Configuration newParentConfig)1020     public void onConfigurationChanged(Configuration newParentConfig) {
1021         // update resources before cascade so that docked/pinned stacks use the correct info
1022         if (mDisplayContent != null) {
1023             mDisplayContent.preOnConfigurationChanged();
1024         }
1025         super.onConfigurationChanged(newParentConfig);
1026     }
1027 
onLockTaskPackagesUpdated()1028     void onLockTaskPackagesUpdated() {
1029         for (int i = mStacks.size() - 1; i >= 0; --i) {
1030             mStacks.get(i).onLockTaskPackagesUpdated();
1031         }
1032     }
1033 
1034     /** We are in the process of exiting split-screen mode. */
onExitingSplitScreenMode()1035     void onExitingSplitScreenMode() {
1036         // Remove reference to the primary-split-screen stack so it no longer has any effect on the
1037         // display. For example, we want to be able to create fullscreen stack for standard activity
1038         // types when exiting split-screen mode.
1039         mSplitScreenPrimaryStack = null;
1040     }
1041 
1042     /** Checks whether the given activity is in size compatibility mode and notifies the change. */
handleActivitySizeCompatModeIfNeeded(ActivityRecord r)1043     void handleActivitySizeCompatModeIfNeeded(ActivityRecord r) {
1044         if (!r.isState(RESUMED) || r.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
1045             // The callback is only interested in the foreground changes of fullscreen activity.
1046             return;
1047         }
1048         if (!r.inSizeCompatMode()) {
1049             if (mLastCompatModeActivity != null) {
1050                 mService.getTaskChangeNotificationController()
1051                         .notifySizeCompatModeActivityChanged(mDisplayId, null /* activityToken */);
1052             }
1053             mLastCompatModeActivity = null;
1054             return;
1055         }
1056         if (mLastCompatModeActivity == r) {
1057             return;
1058         }
1059         mLastCompatModeActivity = r;
1060         mService.getTaskChangeNotificationController()
1061                 .notifySizeCompatModeActivityChanged(mDisplayId, r.appToken);
1062     }
1063 
getSplitScreenPrimaryStack()1064     ActivityStack getSplitScreenPrimaryStack() {
1065         return mSplitScreenPrimaryStack;
1066     }
1067 
hasSplitScreenPrimaryStack()1068     boolean hasSplitScreenPrimaryStack() {
1069         return mSplitScreenPrimaryStack != null;
1070     }
1071 
getPinnedStack()1072     ActivityStack getPinnedStack() {
1073         return mPinnedStack;
1074     }
1075 
hasPinnedStack()1076     boolean hasPinnedStack() {
1077         return mPinnedStack != null;
1078     }
1079 
1080     @Override
toString()1081     public String toString() {
1082         return "ActivityDisplay={" + mDisplayId + " numStacks=" + mStacks.size() + "}";
1083     }
1084 
1085     @Override
getChildCount()1086     protected int getChildCount() {
1087         return mStacks.size();
1088     }
1089 
1090     @Override
getChildAt(int index)1091     protected ActivityStack getChildAt(int index) {
1092         return mStacks.get(index);
1093     }
1094 
1095     @Override
getParent()1096     protected ConfigurationContainer getParent() {
1097         return mRootActivityContainer;
1098     }
1099 
isPrivate()1100     boolean isPrivate() {
1101         return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
1102     }
1103 
isUidPresent(int uid)1104     boolean isUidPresent(int uid) {
1105         for (ActivityStack stack : mStacks) {
1106             if (stack.isUidPresent(uid)) {
1107                 return true;
1108             }
1109         }
1110         return false;
1111     }
1112 
1113     /**
1114      * @see #mRemoved
1115      */
isRemoved()1116     boolean isRemoved() {
1117         return mRemoved;
1118     }
1119 
remove()1120     void remove() {
1121         final boolean destroyContentOnRemoval = shouldDestroyContentOnRemove();
1122         ActivityStack lastReparentedStack = null;
1123         mPreferredTopFocusableStack = null;
1124 
1125         // Stacks could be reparented from the removed display to other display. While
1126         // reparenting the last stack of the removed display, the remove display is ready to be
1127         // released (no more ActivityStack). But, we cannot release it at that moment or the
1128         // related WindowContainer and WindowContainerController will also be removed. So, we
1129         // set display as removed after reparenting stack finished.
1130         final ActivityDisplay toDisplay = mRootActivityContainer.getDefaultDisplay();
1131         mRootActivityContainer.mStackSupervisor.beginDeferResume();
1132         try {
1133             int numStacks = mStacks.size();
1134             // Keep the order from bottom to top.
1135             for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
1136                 final ActivityStack stack = mStacks.get(stackNdx);
1137                 // Always finish non-standard type stacks.
1138                 if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) {
1139                     stack.finishAllActivitiesLocked(true /* immediately */);
1140                 } else {
1141                     // If default display is in split-window mode, set windowing mode of the stack
1142                     // to split-screen secondary. Otherwise, set the windowing mode to undefined by
1143                     // default to let stack inherited the windowing mode from the new display.
1144                     final int windowingMode = toDisplay.hasSplitScreenPrimaryStack()
1145                             ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
1146                             : WINDOWING_MODE_UNDEFINED;
1147                     stack.reparent(toDisplay, true /* onTop */, true /* displayRemoved */);
1148                     stack.setWindowingMode(windowingMode);
1149                     lastReparentedStack = stack;
1150                 }
1151                 // Stacks may be removed from this display. Ensure each stack will be processed and
1152                 // the loop will end.
1153                 stackNdx -= numStacks - mStacks.size();
1154                 numStacks = mStacks.size();
1155             }
1156         } finally {
1157             mRootActivityContainer.mStackSupervisor.endDeferResume();
1158         }
1159         mRemoved = true;
1160 
1161         // Only update focus/visibility for the last one because there may be many stacks are
1162         // reparented and the intermediate states are unnecessary.
1163         if (lastReparentedStack != null) {
1164             lastReparentedStack.postReparent();
1165         }
1166         releaseSelfIfNeeded();
1167 
1168         if (!mAllSleepTokens.isEmpty()) {
1169             mRootActivityContainer.mSleepTokens.removeAll(mAllSleepTokens);
1170             mAllSleepTokens.clear();
1171             mService.updateSleepIfNeededLocked();
1172         }
1173     }
1174 
releaseSelfIfNeeded()1175     private void releaseSelfIfNeeded() {
1176         if (!mRemoved || mDisplayContent == null) {
1177             return;
1178         }
1179 
1180         final ActivityStack stack = mStacks.size() == 1 ? mStacks.get(0) : null;
1181         if (stack != null && stack.isActivityTypeHome() && stack.getAllTasks().isEmpty()) {
1182             // Release this display if an empty home stack is the only thing left.
1183             // Since it is the last stack, this display will be released along with the stack
1184             // removal.
1185             stack.remove();
1186         } else if (mStacks.isEmpty()) {
1187             mDisplayContent.removeIfPossible();
1188             mDisplayContent = null;
1189             mRootActivityContainer.removeChild(this);
1190             mRootActivityContainer.mStackSupervisor
1191                     .getKeyguardController().onDisplayRemoved(mDisplayId);
1192         }
1193     }
1194 
1195     /** Update and get all UIDs that are present on the display and have access to it. */
getPresentUIDs()1196     IntArray getPresentUIDs() {
1197         mDisplayAccessUIDs.clear();
1198         for (ActivityStack stack : mStacks) {
1199             stack.getPresentUIDs(mDisplayAccessUIDs);
1200         }
1201         return mDisplayAccessUIDs;
1202     }
1203 
1204     /**
1205      * Checks if system decorations should be shown on this display.
1206      *
1207      * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
1208      */
supportsSystemDecorations()1209     boolean supportsSystemDecorations() {
1210         return mDisplayContent.supportsSystemDecorations();
1211     }
1212 
1213     @VisibleForTesting
shouldDestroyContentOnRemove()1214     boolean shouldDestroyContentOnRemove() {
1215         return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT;
1216     }
1217 
shouldSleep()1218     boolean shouldSleep() {
1219         return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty())
1220                 && (mService.mRunningVoice == null);
1221     }
1222 
setFocusedApp(ActivityRecord r, boolean moveFocusNow)1223     void setFocusedApp(ActivityRecord r, boolean moveFocusNow) {
1224         if (mDisplayContent == null) {
1225             return;
1226         }
1227         final AppWindowToken newFocus;
1228         final IBinder token = r.appToken;
1229         if (token == null) {
1230             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Clearing focused app, displayId="
1231                     + mDisplayId);
1232             newFocus = null;
1233         } else {
1234             newFocus = mService.mWindowManager.mRoot.getAppWindowToken(token);
1235             if (newFocus == null) {
1236                 Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token
1237                         + ", displayId=" + mDisplayId);
1238             }
1239             if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Set focused app to: " + newFocus
1240                     + " moveFocusNow=" + moveFocusNow + " displayId=" + mDisplayId);
1241         }
1242 
1243         final boolean changed = mDisplayContent.setFocusedApp(newFocus);
1244         if (moveFocusNow && changed) {
1245             mService.mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
1246                     true /*updateInputWindows*/);
1247         }
1248     }
1249 
1250     /**
1251      * @return the stack currently above the {@param stack}.  Can be null if the {@param stack} is
1252      *         already top-most.
1253      */
getStackAbove(ActivityStack stack)1254     ActivityStack getStackAbove(ActivityStack stack) {
1255         final int stackIndex = mStacks.indexOf(stack) + 1;
1256         return (stackIndex < mStacks.size()) ? mStacks.get(stackIndex) : null;
1257     }
1258 
1259     /**
1260      * Adjusts the {@param stack} behind the last visible stack in the display if necessary.
1261      * Generally used in conjunction with {@link #moveStackBehindStack}.
1262      */
moveStackBehindBottomMostVisibleStack(ActivityStack stack)1263     void moveStackBehindBottomMostVisibleStack(ActivityStack stack) {
1264         if (stack.shouldBeVisible(null)) {
1265             // Skip if the stack is already visible
1266             return;
1267         }
1268 
1269         // Move the stack to the bottom to not affect the following visibility checks
1270         positionChildAtBottom(stack);
1271 
1272         // Find the next position where the stack should be placed
1273         final int numStacks = mStacks.size();
1274         for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
1275             final ActivityStack s = mStacks.get(stackNdx);
1276             if (s == stack) {
1277                 continue;
1278             }
1279             final int winMode = s.getWindowingMode();
1280             final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN ||
1281                     winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
1282             if (s.shouldBeVisible(null) && isValidWindowingMode) {
1283                 // Move the provided stack to behind this stack
1284                 positionChildAt(stack, Math.max(0, stackNdx - 1));
1285                 break;
1286             }
1287         }
1288     }
1289 
1290     /**
1291      * Moves the {@param stack} behind the given {@param behindStack} if possible. If
1292      * {@param behindStack} is not currently in the display, then then the stack is moved to the
1293      * back. Generally used in conjunction with {@link #moveStackBehindBottomMostVisibleStack}.
1294      */
moveStackBehindStack(ActivityStack stack, ActivityStack behindStack)1295     void moveStackBehindStack(ActivityStack stack, ActivityStack behindStack) {
1296         if (behindStack == null || behindStack == stack) {
1297             return;
1298         }
1299 
1300         // Note that positionChildAt will first remove the given stack before inserting into the
1301         // list, so we need to adjust the insertion index to account for the removed index
1302         // TODO: Remove this logic when WindowContainer.positionChildAt() is updated to adjust the
1303         //       position internally
1304         final int stackIndex = mStacks.indexOf(stack);
1305         final int behindStackIndex = mStacks.indexOf(behindStack);
1306         final int insertIndex = stackIndex <= behindStackIndex
1307                 ? behindStackIndex - 1 : behindStackIndex;
1308         positionChildAt(stack, Math.max(0, insertIndex));
1309     }
1310 
ensureActivitiesVisible(ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients)1311     void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
1312             boolean preserveWindows, boolean notifyClients) {
1313         for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
1314             final ActivityStack stack = getChildAt(stackNdx);
1315             stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
1316                     notifyClients);
1317         }
1318     }
1319 
moveHomeStackToFront(String reason)1320     void moveHomeStackToFront(String reason) {
1321         if (mHomeStack != null) {
1322             mHomeStack.moveToFront(reason);
1323         }
1324     }
1325 
1326     /**
1327      * Moves the focusable home activity to top. If there is no such activity, the home stack will
1328      * still move to top.
1329      */
moveHomeActivityToTop(String reason)1330     void moveHomeActivityToTop(String reason) {
1331         final ActivityRecord top = getHomeActivity();
1332         if (top == null) {
1333             moveHomeStackToFront(reason);
1334             return;
1335         }
1336         top.moveFocusableActivityToTop(reason);
1337     }
1338 
1339     @Nullable
getHomeStack()1340     ActivityStack getHomeStack() {
1341         return mHomeStack;
1342     }
1343 
1344     @Nullable
getHomeActivity()1345     ActivityRecord getHomeActivity() {
1346         return getHomeActivityForUser(mRootActivityContainer.mCurrentUser);
1347     }
1348 
1349     @Nullable
getHomeActivityForUser(int userId)1350     ActivityRecord getHomeActivityForUser(int userId) {
1351         if (mHomeStack == null) {
1352             return null;
1353         }
1354 
1355         final ArrayList<TaskRecord> tasks = mHomeStack.getAllTasks();
1356         for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
1357             final TaskRecord task = tasks.get(taskNdx);
1358             if (!task.isActivityTypeHome()) {
1359                 continue;
1360             }
1361 
1362             final ArrayList<ActivityRecord> activities = task.mActivities;
1363             for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1364                 final ActivityRecord r = activities.get(activityNdx);
1365                 if (r.isActivityTypeHome()
1366                         && ((userId == UserHandle.USER_ALL) || (r.mUserId == userId))) {
1367                     return r;
1368                 }
1369             }
1370         }
1371         return null;
1372     }
1373 
isSleeping()1374     boolean isSleeping() {
1375         return mSleeping;
1376     }
1377 
setIsSleeping(boolean asleep)1378     void setIsSleeping(boolean asleep) {
1379         mSleeping = asleep;
1380     }
1381 
1382     /**
1383      * Adds a listener to be notified whenever the stack order in the display changes. Currently
1384      * only used by the {@link RecentsAnimation} to determine whether to interrupt and cancel the
1385      * current animation when the system state changes.
1386      */
registerStackOrderChangedListener(OnStackOrderChangedListener listener)1387     void registerStackOrderChangedListener(OnStackOrderChangedListener listener) {
1388         if (!mStackOrderChangedCallbacks.contains(listener)) {
1389             mStackOrderChangedCallbacks.add(listener);
1390         }
1391     }
1392 
1393     /**
1394      * Removes a previously registered stack order change listener.
1395      */
unregisterStackOrderChangedListener(OnStackOrderChangedListener listener)1396     void unregisterStackOrderChangedListener(OnStackOrderChangedListener listener) {
1397         mStackOrderChangedCallbacks.remove(listener);
1398     }
1399 
1400     /**
1401      * Notifies of a stack order change
1402      * @param stack The stack which triggered the order change
1403      */
onStackOrderChanged(ActivityStack stack)1404     private void onStackOrderChanged(ActivityStack stack) {
1405         for (int i = mStackOrderChangedCallbacks.size() - 1; i >= 0; i--) {
1406             mStackOrderChangedCallbacks.get(i).onStackOrderChanged(stack);
1407         }
1408     }
1409 
1410     /**
1411      * See {@link DisplayContent#deferUpdateImeTarget()}
1412      */
deferUpdateImeTarget()1413     public void deferUpdateImeTarget() {
1414         if (mDisplayContent != null) {
1415             mDisplayContent.deferUpdateImeTarget();
1416         }
1417     }
1418 
1419     /**
1420      * See {@link DisplayContent#deferUpdateImeTarget()}
1421      */
continueUpdateImeTarget()1422     public void continueUpdateImeTarget() {
1423         if (mDisplayContent != null) {
1424             mDisplayContent.continueUpdateImeTarget();
1425         }
1426     }
1427 
setDisplayToSingleTaskInstance()1428     void setDisplayToSingleTaskInstance() {
1429         final int childCount = getChildCount();
1430         if (childCount > 1) {
1431             throw new IllegalArgumentException("Display already has multiple stacks. display="
1432                     + this);
1433         }
1434         if (childCount > 0) {
1435             final ActivityStack stack = getChildAt(0);
1436             if (stack.getChildCount() > 1) {
1437                 throw new IllegalArgumentException("Display stack already has multiple tasks."
1438                         + " display=" + this + " stack=" + stack);
1439             }
1440         }
1441 
1442         mSingleTaskInstance = true;
1443     }
1444 
1445     /** Returns true if the display can only contain one task */
isSingleTaskInstance()1446     boolean isSingleTaskInstance() {
1447         return mSingleTaskInstance;
1448     }
1449 
dump(PrintWriter pw, String prefix)1450     public void dump(PrintWriter pw, String prefix) {
1451         pw.println(prefix + "displayId=" + mDisplayId + " stacks=" + mStacks.size()
1452                 + (mSingleTaskInstance ? " mSingleTaskInstance" : ""));
1453         final String myPrefix = prefix + " ";
1454         if (mHomeStack != null) {
1455             pw.println(myPrefix + "mHomeStack=" + mHomeStack);
1456         }
1457         if (mRecentsStack != null) {
1458             pw.println(myPrefix + "mRecentsStack=" + mRecentsStack);
1459         }
1460         if (mPinnedStack != null) {
1461             pw.println(myPrefix + "mPinnedStack=" + mPinnedStack);
1462         }
1463         if (mSplitScreenPrimaryStack != null) {
1464             pw.println(myPrefix + "mSplitScreenPrimaryStack=" + mSplitScreenPrimaryStack);
1465         }
1466         if (mPreferredTopFocusableStack != null) {
1467             pw.println(myPrefix + "mPreferredTopFocusableStack=" + mPreferredTopFocusableStack);
1468         }
1469         if (mLastFocusedStack != null) {
1470             pw.println(myPrefix + "mLastFocusedStack=" + mLastFocusedStack);
1471         }
1472     }
1473 
dumpStacks(PrintWriter pw)1474     public void dumpStacks(PrintWriter pw) {
1475         for (int i = mStacks.size() - 1; i >= 0; --i) {
1476             pw.print(mStacks.get(i).mStackId);
1477             if (i > 0) {
1478                 pw.print(",");
1479             }
1480         }
1481     }
1482 
writeToProto(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel)1483     public void writeToProto(ProtoOutputStream proto, long fieldId,
1484             @WindowTraceLogLevel int logLevel) {
1485         final long token = proto.start(fieldId);
1486         super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel);
1487         proto.write(ID, mDisplayId);
1488         proto.write(SINGLE_TASK_INSTANCE, mSingleTaskInstance);
1489         final ActivityStack focusedStack = getFocusedStack();
1490         if (focusedStack != null) {
1491             proto.write(FOCUSED_STACK_ID, focusedStack.mStackId);
1492             final ActivityRecord focusedActivity = focusedStack.getDisplay().getResumedActivity();
1493             if (focusedActivity != null) {
1494                 focusedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
1495             }
1496         } else {
1497             proto.write(FOCUSED_STACK_ID, INVALID_STACK_ID);
1498         }
1499         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1500             final ActivityStack stack = mStacks.get(stackNdx);
1501             stack.writeToProto(proto, STACKS, logLevel);
1502         }
1503         proto.end(token);
1504     }
1505 
1506     /**
1507      * Callback for when the order of the stacks in the display changes.
1508      */
1509     interface OnStackOrderChangedListener {
onStackOrderChanged(ActivityStack stack)1510         void onStackOrderChanged(ActivityStack stack);
1511     }
1512 }
1513