blob: ebfc65e5d1e5a79b77f76211b8d47c6e0aab2d51 [file] [log] [blame]
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001/*
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
Wale Ogunwale59507092018-10-29 09:00:30 -070017package com.android.server.wm;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070018
Andrii Kulianab132ee2018-07-24 22:10:21 +080019import static android.app.ActivityTaskManager.INVALID_STACK_ID;
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -070020import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070021import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
22import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
23import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
Evan Roskye747c3e2018-10-30 20:06:41 -070024import static android.app.WindowConfiguration.ROTATION_UNDEFINED;
Wale Ogunwaleab5de372017-10-18 06:46:31 -070025import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070026import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
27import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
28import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
29import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
30import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
31import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
Shivam Agrawal1d3db652019-07-01 15:26:11 -070032import static android.os.Build.VERSION_CODES.N;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070033import static android.view.Display.DEFAULT_DISPLAY;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070034import static android.view.Display.FLAG_PRIVATE;
35import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
Louis Chang7d0037c2018-08-13 12:42:06 +080036
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070037import static com.android.server.am.ActivityDisplayProto.CONFIGURATION_CONTAINER;
Andrii Kulianab132ee2018-07-24 22:10:21 +080038import static com.android.server.am.ActivityDisplayProto.FOCUSED_STACK_ID;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070039import static com.android.server.am.ActivityDisplayProto.ID;
Andrii Kulianab132ee2018-07-24 22:10:21 +080040import static com.android.server.am.ActivityDisplayProto.RESUMED_ACTIVITY;
Wale Ogunwale9e737db2018-12-17 15:42:37 -080041import static com.android.server.am.ActivityDisplayProto.SINGLE_TASK_INSTANCE;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070042import static com.android.server.am.ActivityDisplayProto.STACKS;
Wale Ogunwale59507092018-10-29 09:00:30 -070043import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
Andrii Kulian0c869cc2019-02-06 19:50:32 -080044import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
Wale Ogunwale59507092018-10-29 09:00:30 -070045import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
46import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
47import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
48import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
49import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STACK;
50import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
51import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
Adrian Roosb125e0b2019-10-02 14:55:14 +020052import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_FOCUS_LIGHT;
Wale Ogunwaled32da472018-11-16 07:19:28 -080053import static com.android.server.wm.RootActivityContainer.FindTaskResult;
54import static com.android.server.wm.RootActivityContainer.TAG_STATES;
Wale Ogunwale3a256e62018-12-06 14:41:18 -080055import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
56import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070057
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -070058import android.annotation.Nullable;
Shivam Agrawal1d3db652019-07-01 15:26:11 -070059import android.app.ActivityManager;
60import android.app.ActivityManagerInternal;
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -070061import android.app.ActivityOptions;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070062import android.app.WindowConfiguration;
Shivam Agrawal1d3db652019-07-01 15:26:11 -070063import android.content.pm.ActivityInfo;
Evan Roskye747c3e2018-10-30 20:06:41 -070064import android.content.res.Configuration;
Bryce Leef3c6a472017-11-14 14:53:06 -080065import android.graphics.Point;
Wale Ogunwale3a256e62018-12-06 14:41:18 -080066import android.os.IBinder;
Shivam Agrawal1d3db652019-07-01 15:26:11 -070067import android.os.Message;
Louis Changbd48dca2018-08-29 17:44:34 +080068import android.os.UserHandle;
Shivam Agrawal1d3db652019-07-01 15:26:11 -070069import android.provider.Settings;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070070import android.util.IntArray;
71import android.util.Slog;
72import android.util.proto.ProtoOutputStream;
73import android.view.Display;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070074
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070075import com.android.internal.annotations.VisibleForTesting;
Shivam Agrawal1d3db652019-07-01 15:26:11 -070076import com.android.internal.util.function.pooled.PooledLambda;
Wale Ogunwale59507092018-10-29 09:00:30 -070077import com.android.server.am.EventLogTags;
Adrian Roosb125e0b2019-10-02 14:55:14 +020078import com.android.server.protolog.common.ProtoLog;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070079
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -070080import java.io.PrintWriter;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070081import java.util.ArrayList;
82
83/**
84 * Exactly one of these classes per Display in the system. Capable of holding zero or more
85 * attached {@link ActivityStack}s.
86 */
Riddle Hsu5947c362019-09-23 18:52:36 +080087class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
Wale Ogunwale98875612018-10-12 07:53:02 -070088 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityDisplay" : TAG_ATM;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070089 private static final String TAG_STACK = TAG + POSTFIX_STACK;
90
91 static final int POSITION_TOP = Integer.MAX_VALUE;
92 static final int POSITION_BOTTOM = Integer.MIN_VALUE;
93
Bryce Leed9cce2c2017-12-04 16:16:27 -080094
95 /**
96 * Counter for next free stack ID to use for dynamic activity stacks. Unique across displays.
97 */
98 private static int sNextFreeStackId = 0;
99
Wale Ogunwaled32da472018-11-16 07:19:28 -0800100 private ActivityTaskManagerService mService;
101 private RootActivityContainer mRootActivityContainer;
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800102 // TODO: Remove once unification is complete.
103 DisplayContent mDisplayContent;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700104 /** Actual Display this object tracks. */
105 int mDisplayId;
106 Display mDisplay;
107
Winson Chung0f7ec962018-05-03 18:03:15 -0700108 /**
109 * All of the stacks on this display. Order matters, topmost stack is in front of all other
110 * stacks, bottommost behind. Accessed directly by ActivityManager package classes. Any calls
111 * changing the list should also call {@link #onStackOrderChanged()}.
112 */
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700113 private final ArrayList<ActivityStack> mStacks = new ArrayList<>();
Winson Chung0f7ec962018-05-03 18:03:15 -0700114 private ArrayList<OnStackOrderChangedListener> mStackOrderChangedCallbacks = new ArrayList<>();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700115
116 /** Array of all UIDs that are present on the display. */
117 private IntArray mDisplayAccessUIDs = new IntArray();
118
119 /** All tokens used to put activities on this stack to sleep (including mOffToken) */
Wale Ogunwale6767eae2018-05-03 15:52:51 -0700120 final ArrayList<ActivityTaskManagerInternal.SleepToken> mAllSleepTokens = new ArrayList<>();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700121 /** The token acquired by ActivityStackSupervisor to put stacks on the display to sleep */
Wale Ogunwale6767eae2018-05-03 15:52:51 -0700122 ActivityTaskManagerInternal.SleepToken mOffToken;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700123
124 private boolean mSleeping;
125
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700126 /** We started the process of removing the display from the system. */
127 private boolean mRemoving;
128
Louis Chang7d0037c2018-08-13 12:42:06 +0800129 /**
130 * The display is removed from the system and we are just waiting for all activities on it to be
131 * finished before removing this object.
132 */
133 private boolean mRemoved;
134
Wale Ogunwale9e737db2018-12-17 15:42:37 -0800135 /** The display can only contain one task. */
136 private boolean mSingleTaskInstance;
137
Riddle Hsu75016992018-09-20 20:37:14 +0800138 /**
Riddle Hsu7b766fd2019-01-28 21:14:59 +0800139 * Non-null if the last size compatibility mode activity is using non-native screen
140 * configuration. The activity is not able to put in multi-window mode, so it exists only one
141 * per display.
142 */
143 private ActivityRecord mLastCompatModeActivity;
144
145 /**
Riddle Hsu75016992018-09-20 20:37:14 +0800146 * A focusable stack that is purposely to be positioned at the top. Although the stack may not
147 * have the topmost index, it is used as a preferred candidate to prevent being unable to resume
148 * target stack properly when there are other focusable always-on-top stacks.
149 */
150 private ActivityStack mPreferredTopFocusableStack;
151
Riddle Hsubbb63c22018-10-03 12:28:29 +0800152 /**
153 * If this is the same as {@link #getFocusedStack} then the activity on the top of the focused
154 * stack has been resumed. If stacks are changing position this will hold the old stack until
155 * the new stack becomes resumed after which it will be set to current focused stack.
156 */
157 private ActivityStack mLastFocusedStack;
158
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700159 // Cached reference to some special stacks we tend to get a lot so we don't need to loop
160 // through the list to find them.
161 private ActivityStack mHomeStack = null;
162 private ActivityStack mRecentsStack = null;
163 private ActivityStack mPinnedStack = null;
164 private ActivityStack mSplitScreenPrimaryStack = null;
165
Bryce Leef3c6a472017-11-14 14:53:06 -0800166 // Used in updating the display size
167 private Point mTmpDisplaySize = new Point();
168
Shivam Agrawal1d3db652019-07-01 15:26:11 -0700169 // Used in updating override configurations
170 private final Configuration mTempConfig = new Configuration();
171
Louis Changc85b1a32018-08-14 16:40:53 +0800172 private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
173
Wale Ogunwaled32da472018-11-16 07:19:28 -0800174 ActivityDisplay(RootActivityContainer root, Display display) {
175 mRootActivityContainer = root;
176 mService = root.mService;
Wale Ogunwale45477b52018-03-06 12:24:19 -0800177 mDisplayId = display.getDisplayId();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700178 mDisplay = display;
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700179 mDisplayContent = mService.mWindowManager.mRoot.createDisplayContent(mDisplay, this);
Shivam Agrawal6472e0e2019-07-03 16:27:49 -0700180 mDisplayContent.reconfigureDisplayLocked();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700181 onRequestedOverrideConfigurationChanged(
182 mDisplayContent.getRequestedOverrideConfiguration());
Evan Rosky69cace42019-09-20 16:28:13 -0700183 mService.mWindowManager.mDisplayNotificationController.dispatchDisplayAdded(this);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700184 }
185
Riddle Hsuf53da812018-08-15 22:00:27 +0800186 void onDisplayChanged() {
187 // The window policy is responsible for stopping activities on the default display.
188 final int displayId = mDisplay.getDisplayId();
189 if (displayId != DEFAULT_DISPLAY) {
190 final int displayState = mDisplay.getState();
191 if (displayState == Display.STATE_OFF && mOffToken == null) {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800192 mOffToken = mService.acquireSleepToken("Display-off", displayId);
Riddle Hsuf53da812018-08-15 22:00:27 +0800193 } else if (displayState == Display.STATE_ON && mOffToken != null) {
194 mOffToken.release();
195 mOffToken = null;
196 }
197 }
198
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700199 mDisplay.getRealSize(mTmpDisplaySize);
200 setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800201 if (mDisplayContent != null) {
202 mDisplayContent.updateDisplayInfo();
203 mService.mWindowManager.requestTraversal();
204 }
Riddle Hsuf53da812018-08-15 22:00:27 +0800205 }
206
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700207 // TODO(display-unify): Merge with addChild below.
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700208 void addChild(ActivityStack stack, int position) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700209 addChild(stack, position, false /*fromDc*/);
210 }
211
212 void addChild(ActivityStack stack, int position, boolean fromDc) {
213 boolean toTop = position == POSITION_TOP;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700214 if (position == POSITION_BOTTOM) {
215 position = 0;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700216 } else if (toTop) {
Louis Changba3f17a2019-11-11 12:29:17 +0800217 position = getChildCount();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700218 }
219 if (DEBUG_STACK) Slog.v(TAG_STACK, "addChild: attaching " + stack
220 + " to displayId=" + mDisplayId + " position=" + position);
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700221 addStackReferenceIfNeeded(stack);
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700222 if (!fromDc) {
223 mDisplayContent.setStackOnDisplay(stack, position);
224 }
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700225 positionChildAt(stack, position);
Wale Ogunwaled32da472018-11-16 07:19:28 -0800226 mService.updateSleepIfNeededLocked();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700227 }
228
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700229 // TODO(display-unify): Merge with removeChild below.
230 void onChildRemoved(ActivityStack stack) {
231 if (!mStacks.remove(stack)) {
232 // Stack no longer here!
233 return;
234 }
235
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700236 if (DEBUG_STACK) Slog.v(TAG_STACK, "removeChild: detaching " + stack
237 + " from displayId=" + mDisplayId);
Riddle Hsu75016992018-09-20 20:37:14 +0800238 if (mPreferredTopFocusableStack == stack) {
239 mPreferredTopFocusableStack = null;
240 }
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700241 removeStackReferenceIfNeeded(stack);
Louis Chang7d0037c2018-08-13 12:42:06 +0800242 releaseSelfIfNeeded();
Wale Ogunwaled32da472018-11-16 07:19:28 -0800243 mService.updateSleepIfNeededLocked();
Winson Chung65d66d32018-12-13 17:48:39 -0800244 onStackOrderChanged(stack);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700245 }
246
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700247 void removeChild(ActivityStack stack) {
248 mDisplayContent.removeStackFromDisplay(stack);
249 }
250
Riddle Hsu57831b52018-07-27 00:31:48 +0800251 void positionChildAtTop(ActivityStack stack, boolean includingParents) {
Riddle Hsubbb63c22018-10-03 12:28:29 +0800252 positionChildAtTop(stack, includingParents, null /* updateLastFocusedStackReason */);
253 }
254
255 void positionChildAtTop(ActivityStack stack, boolean includingParents,
256 String updateLastFocusedStackReason) {
Louis Changba3f17a2019-11-11 12:29:17 +0800257 positionChildAt(stack, getChildCount(), includingParents, updateLastFocusedStackReason);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700258 }
259
260 void positionChildAtBottom(ActivityStack stack) {
Riddle Hsubbb63c22018-10-03 12:28:29 +0800261 positionChildAtBottom(stack, null /* updateLastFocusedStackReason */);
262 }
263
264 void positionChildAtBottom(ActivityStack stack, String updateLastFocusedStackReason) {
265 positionChildAt(stack, 0, false /* includingParents */, updateLastFocusedStackReason);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700266 }
267
268 private void positionChildAt(ActivityStack stack, int position) {
Riddle Hsubbb63c22018-10-03 12:28:29 +0800269 positionChildAt(stack, position, false /* includingParents */,
270 null /* updateLastFocusedStackReason */);
Riddle Hsu57831b52018-07-27 00:31:48 +0800271 }
272
Riddle Hsubbb63c22018-10-03 12:28:29 +0800273 private void positionChildAt(ActivityStack stack, int position, boolean includingParents,
274 String updateLastFocusedStackReason) {
Winson Chung123e07a2018-02-27 11:47:16 -0800275 // TODO: Keep in sync with WindowContainer.positionChildAt(), once we change that to adjust
276 // the position internally, also update the logic here
Riddle Hsubbb63c22018-10-03 12:28:29 +0800277 final ActivityStack prevFocusedStack = updateLastFocusedStackReason != null
278 ? getFocusedStack() : null;
Riddle Hsu75016992018-09-20 20:37:14 +0800279 final boolean wasContained = mStacks.remove(stack);
Wale Ogunwale9e737db2018-12-17 15:42:37 -0800280 if (mSingleTaskInstance && getChildCount() > 0) {
281 throw new IllegalStateException(
282 "positionChildAt: Can only have one child on display=" + this);
283 }
Winson Chung59a47ded2018-01-25 17:46:06 +0000284 final int insertPosition = getTopInsertPosition(stack, position);
285 mStacks.add(insertPosition, stack);
Riddle Hsu75016992018-09-20 20:37:14 +0800286
287 // The insert position may be adjusted to non-top when there is always-on-top stack. Since
288 // the original position is preferred to be top, the stack should have higher priority when
289 // we are looking for top focusable stack. The condition {@code wasContained} restricts the
290 // preferred stack is set only when moving an existing stack to top instead of adding a new
291 // stack that may be too early (e.g. in the middle of launching or reparenting).
Louis Changba3f17a2019-11-11 12:29:17 +0800292 if (wasContained && position >= getChildCount() - 1 && stack.isFocusableAndVisible()) {
Riddle Hsu75016992018-09-20 20:37:14 +0800293 mPreferredTopFocusableStack = stack;
294 } else if (mPreferredTopFocusableStack == stack) {
295 mPreferredTopFocusableStack = null;
296 }
297
Riddle Hsubbb63c22018-10-03 12:28:29 +0800298 if (updateLastFocusedStackReason != null) {
299 final ActivityStack currentFocusedStack = getFocusedStack();
300 if (currentFocusedStack != prevFocusedStack) {
301 mLastFocusedStack = prevFocusedStack;
Wale Ogunwaled32da472018-11-16 07:19:28 -0800302 EventLogTags.writeAmFocusedStack(mRootActivityContainer.mCurrentUser, mDisplayId,
Riddle Hsubbb63c22018-10-03 12:28:29 +0800303 currentFocusedStack == null ? -1 : currentFocusedStack.getStackId(),
304 mLastFocusedStack == null ? -1 : mLastFocusedStack.getStackId(),
305 updateLastFocusedStackReason);
306 }
307 }
308
Kazuki Takise048e2662018-06-27 17:05:11 +0900309 // Since positionChildAt() is called during the creation process of pinned stacks,
Riddle Hsu5947c362019-09-23 18:52:36 +0800310 // ActivityStack#getStack() can be null.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700311 if (mDisplayContent != null) {
312 mDisplayContent.positionStackAt(insertPosition, stack, includingParents);
Evan Roskyc5abbd82018-10-05 16:02:19 -0700313 }
Winson Chung65d66d32018-12-13 17:48:39 -0800314 onStackOrderChanged(stack);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700315 }
316
317 private int getTopInsertPosition(ActivityStack stack, int candidatePosition) {
Louis Changba3f17a2019-11-11 12:29:17 +0800318 int position = getChildCount();
Kazuki Takise148d00a2018-05-31 15:32:19 +0900319 if (stack.inPinnedWindowingMode()) {
320 // Stack in pinned windowing mode is z-ordered on-top of all other stacks so okay to
321 // just return the candidate position.
322 return Math.min(position, candidatePosition);
323 }
324 while (position > 0) {
Louis Changba3f17a2019-11-11 12:29:17 +0800325 final ActivityStack targetStack = getChildAt(position - 1);
Kazuki Takise148d00a2018-05-31 15:32:19 +0900326 if (!targetStack.isAlwaysOnTop()) {
327 // We reached a stack that isn't always-on-top.
328 break;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700329 }
Kazuki Takise148d00a2018-05-31 15:32:19 +0900330 if (stack.isAlwaysOnTop() && !targetStack.inPinnedWindowingMode()) {
331 // Always on-top non-pinned windowing mode stacks can go anywhere below pinned stack.
332 break;
333 }
334 position--;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700335 }
336 return Math.min(position, candidatePosition);
337 }
338
339 <T extends ActivityStack> T getStack(int stackId) {
Louis Changba3f17a2019-11-11 12:29:17 +0800340 for (int i = getChildCount() - 1; i >= 0; --i) {
341 final ActivityStack stack = getChildAt(i);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700342 if (stack.mStackId == stackId) {
343 return (T) stack;
344 }
345 }
346 return null;
347 }
348
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700349 /**
350 * @return the topmost stack on the display that is compatible with the input windowing mode and
351 * activity type. {@code null} means no compatible stack on the display.
352 * @see ConfigurationContainer#isCompatible(int, int)
353 */
354 <T extends ActivityStack> T getStack(int windowingMode, int activityType) {
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700355 if (activityType == ACTIVITY_TYPE_HOME) {
356 return (T) mHomeStack;
357 } else if (activityType == ACTIVITY_TYPE_RECENTS) {
358 return (T) mRecentsStack;
359 }
360 if (windowingMode == WINDOWING_MODE_PINNED) {
361 return (T) mPinnedStack;
362 } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
363 return (T) mSplitScreenPrimaryStack;
364 }
Wale Ogunwaleab5de372017-10-18 06:46:31 -0700365
Louis Changba3f17a2019-11-11 12:29:17 +0800366 for (int i = getChildCount() - 1; i >= 0; --i) {
367 final ActivityStack stack = getChildAt(i);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700368 if (stack.isCompatible(windowingMode, activityType)) {
369 return (T) stack;
370 }
371 }
372 return null;
373 }
374
Louis Chang9d6ba282019-02-20 17:22:10 +0800375 boolean alwaysCreateStack(int windowingMode, int activityType) {
Wale Ogunwaleab5de372017-10-18 06:46:31 -0700376 // Always create a stack for fullscreen, freeform, and split-screen-secondary windowing
377 // modes so that we can manage visual ordering and return types correctly.
378 return activityType == ACTIVITY_TYPE_STANDARD
379 && (windowingMode == WINDOWING_MODE_FULLSCREEN
380 || windowingMode == WINDOWING_MODE_FREEFORM
381 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
382 }
383
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700384 /**
Wale Ogunwaleab5de372017-10-18 06:46:31 -0700385 * Returns an existing stack compatible with the windowing mode and activity type or creates one
386 * if a compatible stack doesn't exist.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700387 * @see #getStack(int, int)
388 * @see #createStack(int, int, boolean)
389 */
390 <T extends ActivityStack> T getOrCreateStack(int windowingMode, int activityType,
391 boolean onTop) {
Wale Ogunwaleab5de372017-10-18 06:46:31 -0700392 if (!alwaysCreateStack(windowingMode, activityType)) {
393 T stack = getStack(windowingMode, activityType);
394 if (stack != null) {
395 return stack;
396 }
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700397 }
398 return createStack(windowingMode, activityType, onTop);
399 }
400
Wale Ogunwale68278562017-09-23 17:13:55 -0700401 /**
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700402 * Returns an existing stack compatible with the input params or creates one
403 * if a compatible stack doesn't exist.
404 * @see #getOrCreateStack(int, int, boolean)
405 */
406 <T extends ActivityStack> T getOrCreateStack(@Nullable ActivityRecord r,
Louis Changcdec0802019-11-11 11:45:07 +0800407 @Nullable ActivityOptions options, @Nullable Task candidateTask, int activityType,
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700408 boolean onTop) {
Evan Rosky10475742018-09-05 19:02:48 -0700409 // First preference is the windowing mode in the activity options if set.
410 int windowingMode = (options != null)
411 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
412 // Validate that our desired windowingMode will work under the current conditions.
413 // UNDEFINED windowing mode is a valid result and means that the new stack will inherit
414 // it's display's windowing mode.
415 windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType);
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700416 return getOrCreateStack(windowingMode, activityType, onTop);
417 }
418
Louis Changf2835df2018-10-17 15:14:45 +0800419 @VisibleForTesting
420 int getNextStackId() {
Bryce Leed9cce2c2017-12-04 16:16:27 -0800421 return sNextFreeStackId++;
422 }
423
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700424 /**
Wale Ogunwale68278562017-09-23 17:13:55 -0700425 * Creates a stack matching the input windowing mode and activity type on this display.
426 * @param windowingMode The windowing mode the stack should be created in. If
427 * {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will
Evan Rosky10475742018-09-05 19:02:48 -0700428 * inherit it's parent's windowing mode.
Wale Ogunwale68278562017-09-23 17:13:55 -0700429 * @param activityType The activityType the stack should be created in. If
430 * {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will
431 * be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
432 * @param onTop If true the stack will be created at the top of the display, else at the bottom.
433 * @return The newly created stack.
434 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700435 <T extends ActivityStack> T createStack(int windowingMode, int activityType, boolean onTop) {
436
Wale Ogunwale9e737db2018-12-17 15:42:37 -0800437 if (mSingleTaskInstance && getChildCount() > 0) {
438 // Create stack on default display instead since this display can only contain 1 stack.
439 // TODO: Kinda a hack, but better that having the decision at each call point. Hoping
440 // this goes away once ActivityView is no longer using virtual displays.
441 return mRootActivityContainer.getDefaultDisplay().createStack(
442 windowingMode, activityType, onTop);
443 }
444
Wale Ogunwale68278562017-09-23 17:13:55 -0700445 if (activityType == ACTIVITY_TYPE_UNDEFINED) {
446 // Can't have an undefined stack type yet...so re-map to standard. Anyone that wants
447 // anything else should be passing it in anyways...
448 activityType = ACTIVITY_TYPE_STANDARD;
449 }
450
451 if (activityType != ACTIVITY_TYPE_STANDARD) {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700452 // For now there can be only one stack of a particular non-standard activity type on a
453 // display. So, get that ignoring whatever windowing mode it is currently in.
454 T stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
455 if (stack != null) {
456 throw new IllegalArgumentException("Stack=" + stack + " of activityType="
457 + activityType + " already on display=" + this + ". Can't have multiple.");
458 }
459 }
460
Wale Ogunwaled32da472018-11-16 07:19:28 -0800461 if (!isWindowingModeSupported(windowingMode, mService.mSupportsMultiWindow,
462 mService.mSupportsSplitScreenMultiWindow,
463 mService.mSupportsFreeformWindowManagement, mService.mSupportsPictureInPicture,
464 activityType)) {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700465 throw new IllegalArgumentException("Can't create stack for unsupported windowingMode="
466 + windowingMode);
467 }
468
Bryce Leed9cce2c2017-12-04 16:16:27 -0800469 final int stackId = getNextStackId();
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700470 return createStackUnchecked(windowingMode, activityType, stackId, onTop);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700471 }
472
473 @VisibleForTesting
474 <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
475 int stackId, boolean onTop) {
Yunfan Chen279f5582018-12-12 15:24:50 -0800476 if (windowingMode == WINDOWING_MODE_PINNED && activityType != ACTIVITY_TYPE_STANDARD) {
477 throw new IllegalArgumentException("Stack with windowing mode cannot with non standard "
478 + "activity type.");
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700479 }
Wale Ogunwaled32da472018-11-16 07:19:28 -0800480 return (T) new ActivityStack(this, stackId,
Yunfan Chen279f5582018-12-12 15:24:50 -0800481 mRootActivityContainer.mStackSupervisor, windowingMode, activityType, onTop);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700482 }
483
Riddle Hsu75016992018-09-20 20:37:14 +0800484 /**
485 * Get the preferred focusable stack in priority. If the preferred stack does not exist, find a
486 * focusable and visible stack from the top of stacks in this display.
487 */
Andrii Kulian52d255c2018-07-13 11:32:19 -0700488 ActivityStack getFocusedStack() {
Riddle Hsu75016992018-09-20 20:37:14 +0800489 if (mPreferredTopFocusableStack != null) {
490 return mPreferredTopFocusableStack;
491 }
492
Louis Changba3f17a2019-11-11 12:29:17 +0800493 for (int i = getChildCount() - 1; i >= 0; --i) {
494 final ActivityStack stack = getChildAt(i);
Riddle Hsu75016992018-09-20 20:37:14 +0800495 if (stack.isFocusableAndVisible()) {
Andrii Kulian52d255c2018-07-13 11:32:19 -0700496 return stack;
497 }
498 }
499
500 return null;
501 }
502
Andrii Kulianab132ee2018-07-24 22:10:21 +0800503 ActivityStack getNextFocusableStack(ActivityStack currentFocus, boolean ignoreCurrent) {
504 final int currentWindowingMode = currentFocus != null
505 ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
506
507 ActivityStack candidate = null;
Louis Changba3f17a2019-11-11 12:29:17 +0800508 for (int i = getChildCount() - 1; i >= 0; --i) {
509 final ActivityStack stack = getChildAt(i);
Andrii Kulianab132ee2018-07-24 22:10:21 +0800510 if (ignoreCurrent && stack == currentFocus) {
511 continue;
512 }
Riddle Hsu75016992018-09-20 20:37:14 +0800513 if (!stack.isFocusableAndVisible()) {
Andrii Kulianab132ee2018-07-24 22:10:21 +0800514 continue;
515 }
516
517 if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
518 && candidate == null && stack.inSplitScreenPrimaryWindowingMode()) {
519 // If the currently focused stack is in split-screen secondary we save off the
520 // top primary split-screen stack as a candidate for focus because we might
521 // prefer focus to move to an other stack to avoid primary split-screen stack
522 // overlapping with a fullscreen stack when a fullscreen stack is higher in z
523 // than the next split-screen stack. Assistant stack, I am looking at you...
524 // We only move the focus to the primary-split screen stack if there isn't a
525 // better alternative.
526 candidate = stack;
527 continue;
528 }
529 if (candidate != null && stack.inSplitScreenSecondaryWindowingMode()) {
530 // Use the candidate stack since we are now at the secondary split-screen.
531 return candidate;
532 }
533 return stack;
534 }
535 return candidate;
536 }
537
Andrii Kulian52d255c2018-07-13 11:32:19 -0700538 ActivityRecord getResumedActivity() {
539 final ActivityStack focusedStack = getFocusedStack();
540 if (focusedStack == null) {
541 return null;
542 }
543 // TODO(b/111541062): Move this into ActivityStack#getResumedActivity()
544 // Check if the focused stack has the resumed activity
545 ActivityRecord resumedActivity = focusedStack.getResumedActivity();
546 if (resumedActivity == null || resumedActivity.app == null) {
547 // If there is no registered resumed activity in the stack or it is not running -
548 // try to use previously resumed one.
549 resumedActivity = focusedStack.mPausingActivity;
550 if (resumedActivity == null || resumedActivity.app == null) {
551 // If previously resumed activity doesn't work either - find the topmost running
552 // activity that can be focused.
553 resumedActivity = focusedStack.topRunningActivityLocked(true /* focusableOnly */);
554 }
555 }
556 return resumedActivity;
557 }
558
Riddle Hsubbb63c22018-10-03 12:28:29 +0800559 ActivityStack getLastFocusedStack() {
560 return mLastFocusedStack;
561 }
562
563 boolean allResumedActivitiesComplete() {
Louis Changba3f17a2019-11-11 12:29:17 +0800564 for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
565 final ActivityRecord r = getChildAt(stackNdx).getResumedActivity();
Riddle Hsubbb63c22018-10-03 12:28:29 +0800566 if (r != null && !r.isState(RESUMED)) {
567 return false;
568 }
569 }
570 final ActivityStack currentFocusedStack = getFocusedStack();
571 if (DEBUG_STACK) {
572 Slog.d(TAG_STACK, "allResumedActivitiesComplete: mLastFocusedStack changing from="
573 + mLastFocusedStack + " to=" + currentFocusedStack);
574 }
575 mLastFocusedStack = currentFocusedStack;
576 return true;
577 }
578
Wale Ogunwale68278562017-09-23 17:13:55 -0700579 /**
Andrii Kulian6b321512019-01-23 06:37:00 +0000580 * Pause all activities in either all of the stacks or just the back stacks. This is done before
581 * resuming a new activity and to make sure that previously active activities are
582 * paused in stacks that are no longer visible or in pinned windowing mode. This does not
583 * pause activities in visible stacks, so if an activity is launched within the same stack/task,
584 * then we should explicitly pause that stack's top activity.
Andrii Kulianab132ee2018-07-24 22:10:21 +0800585 * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
586 * @param resuming The resuming activity.
Andrii Kulian6b321512019-01-23 06:37:00 +0000587 * @return {@code true} if any activity was paused as a result of this call.
Andrii Kulianab132ee2018-07-24 22:10:21 +0800588 */
Louis Chang7b03ad92019-08-21 12:32:33 +0800589 boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming) {
Andrii Kulianab132ee2018-07-24 22:10:21 +0800590 boolean someActivityPaused = false;
Louis Changba3f17a2019-11-11 12:29:17 +0800591 for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
592 final ActivityStack stack = getChildAt(stackNdx);
Andrii Kulian6b321512019-01-23 06:37:00 +0000593 final ActivityRecord resumedActivity = stack.getResumedActivity();
594 if (resumedActivity != null
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800595 && (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
596 || !stack.isFocusable())) {
Andrii Kulianab132ee2018-07-24 22:10:21 +0800597 if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
Andrii Kulian6b321512019-01-23 06:37:00 +0000598 " mResumedActivity=" + resumedActivity);
Louis Chang7b03ad92019-08-21 12:32:33 +0800599 someActivityPaused |= stack.startPausingLocked(userLeaving, false /* uiSleeping*/,
600 resuming);
Andrii Kulianab132ee2018-07-24 22:10:21 +0800601 }
602 }
603 return someActivityPaused;
604 }
605
606 /**
Louis Changc85b1a32018-08-14 16:40:53 +0800607 * Find task for putting the Activity in.
608 */
609 void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplay,
610 FindTaskResult result) {
611 mTmpFindTaskResult.clear();
612 for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
613 final ActivityStack stack = getChildAt(stackNdx);
614 if (!r.hasCompatibleActivityType(stack)) {
615 if (DEBUG_TASKS) {
616 Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) " + stack);
617 }
618 continue;
619 }
620
621 stack.findTaskLocked(r, mTmpFindTaskResult);
622 // It is possible to have tasks in multiple stacks with the same root affinity, so
623 // we should keep looking after finding an affinity match to see if there is a
624 // better match in another stack. Also, task affinity isn't a good enough reason
625 // to target a display which isn't the source of the intent, so skip any affinity
626 // matches not on the specified display.
627 if (mTmpFindTaskResult.mRecord != null) {
628 if (mTmpFindTaskResult.mIdealMatch) {
629 result.setTo(mTmpFindTaskResult);
630 return;
631 } else if (isPreferredDisplay) {
632 // Note: since the traversing through the stacks is top down, the floating
633 // tasks should always have lower priority than any affinity-matching tasks
634 // in the fullscreen stacks
635 result.setTo(mTmpFindTaskResult);
636 }
637 }
638 }
639 }
640
641 /**
Wale Ogunwale68278562017-09-23 17:13:55 -0700642 * Removes stacks in the input windowing modes from the system if they are of activity type
643 * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
644 */
645 void removeStacksInWindowingModes(int... windowingModes) {
646 if (windowingModes == null || windowingModes.length == 0) {
647 return;
648 }
649
Louis Changf787e532019-01-15 12:46:49 +0800650 // Collect the stacks that are necessary to be removed instead of performing the removal
651 // by looping mStacks, so that we don't miss any stacks after the stack size changed or
652 // stacks reordered.
653 final ArrayList<ActivityStack> stacks = new ArrayList<>();
Wale Ogunwale68278562017-09-23 17:13:55 -0700654 for (int j = windowingModes.length - 1 ; j >= 0; --j) {
655 final int windowingMode = windowingModes[j];
Louis Changba3f17a2019-11-11 12:29:17 +0800656 for (int i = getChildCount() - 1; i >= 0; --i) {
657 final ActivityStack stack = getChildAt(i);
Wale Ogunwale68278562017-09-23 17:13:55 -0700658 if (!stack.isActivityTypeStandardOrUndefined()) {
659 continue;
660 }
661 if (stack.getWindowingMode() != windowingMode) {
662 continue;
663 }
Louis Changf787e532019-01-15 12:46:49 +0800664 stacks.add(stack);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700665 }
666 }
Louis Changf787e532019-01-15 12:46:49 +0800667
668 for (int i = stacks.size() - 1; i >= 0; --i) {
669 mRootActivityContainer.mStackSupervisor.removeStack(stacks.get(i));
670 }
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700671 }
672
Wale Ogunwale68278562017-09-23 17:13:55 -0700673 void removeStacksWithActivityTypes(int... activityTypes) {
674 if (activityTypes == null || activityTypes.length == 0) {
675 return;
676 }
677
Louis Changf787e532019-01-15 12:46:49 +0800678 // Collect the stacks that are necessary to be removed instead of performing the removal
679 // by looping mStacks, so that we don't miss any stacks after the stack size changed or
680 // stacks reordered.
681 final ArrayList<ActivityStack> stacks = new ArrayList<>();
Wale Ogunwale68278562017-09-23 17:13:55 -0700682 for (int j = activityTypes.length - 1 ; j >= 0; --j) {
683 final int activityType = activityTypes[j];
Louis Changba3f17a2019-11-11 12:29:17 +0800684 for (int i = getChildCount() - 1; i >= 0; --i) {
685 final ActivityStack stack = getChildAt(i);
Wale Ogunwale68278562017-09-23 17:13:55 -0700686 if (stack.getActivityType() == activityType) {
Louis Changf787e532019-01-15 12:46:49 +0800687 stacks.add(stack);
Wale Ogunwale68278562017-09-23 17:13:55 -0700688 }
689 }
690 }
Louis Changf787e532019-01-15 12:46:49 +0800691
692 for (int i = stacks.size() - 1; i >= 0; --i) {
693 mRootActivityContainer.mStackSupervisor.removeStack(stacks.get(i));
694 }
Wale Ogunwale68278562017-09-23 17:13:55 -0700695 }
696
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700697 void onStackWindowingModeChanged(ActivityStack stack) {
698 removeStackReferenceIfNeeded(stack);
699 addStackReferenceIfNeeded(stack);
700 }
701
702 private void addStackReferenceIfNeeded(ActivityStack stack) {
703 final int activityType = stack.getActivityType();
704 final int windowingMode = stack.getWindowingMode();
705
706 if (activityType == ACTIVITY_TYPE_HOME) {
707 if (mHomeStack != null && mHomeStack != stack) {
Louis Chang7d0037c2018-08-13 12:42:06 +0800708 throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700709 + mHomeStack + " already exist on display=" + this + " stack=" + stack);
710 }
Louis Chang7d0037c2018-08-13 12:42:06 +0800711 mHomeStack = stack;
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700712 } else if (activityType == ACTIVITY_TYPE_RECENTS) {
713 if (mRecentsStack != null && mRecentsStack != stack) {
714 throw new IllegalArgumentException("addStackReferenceIfNeeded: recents stack="
715 + mRecentsStack + " already exist on display=" + this + " stack=" + stack);
716 }
717 mRecentsStack = stack;
718 }
719 if (windowingMode == WINDOWING_MODE_PINNED) {
720 if (mPinnedStack != null && mPinnedStack != stack) {
721 throw new IllegalArgumentException("addStackReferenceIfNeeded: pinned stack="
722 + mPinnedStack + " already exist on display=" + this
723 + " stack=" + stack);
724 }
725 mPinnedStack = stack;
726 } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
727 if (mSplitScreenPrimaryStack != null && mSplitScreenPrimaryStack != stack) {
728 throw new IllegalArgumentException("addStackReferenceIfNeeded:"
729 + " split-screen-primary" + " stack=" + mSplitScreenPrimaryStack
730 + " already exist on display=" + this + " stack=" + stack);
731 }
732 mSplitScreenPrimaryStack = stack;
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800733 onSplitScreenModeActivated();
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700734 }
735 }
736
737 private void removeStackReferenceIfNeeded(ActivityStack stack) {
738 if (stack == mHomeStack) {
739 mHomeStack = null;
740 } else if (stack == mRecentsStack) {
741 mRecentsStack = null;
742 } else if (stack == mPinnedStack) {
743 mPinnedStack = null;
744 } else if (stack == mSplitScreenPrimaryStack) {
745 mSplitScreenPrimaryStack = null;
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800746 // Inform the reset of the system that split-screen mode was dismissed so things like
747 // resizing all the other stacks can take place.
748 onSplitScreenModeDismissed();
749 }
750 }
751
752 private void onSplitScreenModeDismissed() {
Riddle Hsua0022cd2019-09-09 21:12:41 +0800753 mService.deferWindowLayout();
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800754 try {
755 // Adjust the windowing mode of any stack in secondary split-screen to fullscreen.
Louis Changba3f17a2019-11-11 12:29:17 +0800756 for (int i = getChildCount() - 1; i >= 0; --i) {
757 final ActivityStack otherStack = getChildAt(i);
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800758 if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
759 continue;
760 }
Evan Rosky10475742018-09-05 19:02:48 -0700761 otherStack.setWindowingMode(WINDOWING_MODE_UNDEFINED, false /* animate */,
Andrii Kulian9da138a2018-04-24 17:12:44 -0700762 false /* showRecents */, false /* enteringSplitScreenMode */,
Evan Roskyc5abbd82018-10-05 16:02:19 -0700763 true /* deferEnsuringVisibility */, false /* creating */);
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800764 }
765 } finally {
Wale Ogunwale1dbc5c82017-12-08 08:12:20 -0800766 final ActivityStack topFullscreenStack =
Wale Ogunwalef3257852018-01-24 08:52:28 -0800767 getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN);
Wale Ogunwale1dbc5c82017-12-08 08:12:20 -0800768 if (topFullscreenStack != null && mHomeStack != null && !isTopStack(mHomeStack)) {
Wale Ogunwaleeb76b762017-11-17 10:08:04 -0800769 // Whenever split-screen is dismissed we want the home stack directly behind the
Wale Ogunwale1dbc5c82017-12-08 08:12:20 -0800770 // current top fullscreen stack so it shows up when the top stack is finished.
Wale Ogunwaleeb76b762017-11-17 10:08:04 -0800771 // TODO: Would be better to use ActivityDisplay.positionChildAt() for this, however
772 // ActivityDisplay doesn't have a direct controller to WM side yet. We can switch
773 // once we have that.
774 mHomeStack.moveToFront("onSplitScreenModeDismissed");
Wale Ogunwale1dbc5c82017-12-08 08:12:20 -0800775 topFullscreenStack.moveToFront("onSplitScreenModeDismissed");
Wale Ogunwaleeb76b762017-11-17 10:08:04 -0800776 }
Riddle Hsua0022cd2019-09-09 21:12:41 +0800777 mService.continueWindowLayout();
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800778 }
779 }
780
781 private void onSplitScreenModeActivated() {
Riddle Hsua0022cd2019-09-09 21:12:41 +0800782 mService.deferWindowLayout();
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800783 try {
784 // Adjust the windowing mode of any affected by split-screen to split-screen secondary.
Louis Changba3f17a2019-11-11 12:29:17 +0800785 for (int i = getChildCount() - 1; i >= 0; --i) {
786 final ActivityStack otherStack = getChildAt(i);
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800787 if (otherStack == mSplitScreenPrimaryStack
788 || !otherStack.affectedBySplitScreenResize()) {
789 continue;
790 }
Wale Ogunwaledf262f52017-12-07 18:17:12 -0800791 otherStack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
792 false /* animate */, false /* showRecents */,
Evan Roskyc5abbd82018-10-05 16:02:19 -0700793 true /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */,
794 false /* creating */);
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800795 }
796 } finally {
Riddle Hsua0022cd2019-09-09 21:12:41 +0800797 mService.continueWindowLayout();
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700798 }
799 }
800
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700801 /**
802 * Returns true if the {@param windowingMode} is supported based on other parameters passed in.
803 * @param windowingMode The windowing mode we are checking support for.
804 * @param supportsMultiWindow If we should consider support for multi-window mode in general.
805 * @param supportsSplitScreen If we should consider support for split-screen multi-window.
806 * @param supportsFreeform If we should consider support for freeform multi-window.
807 * @param supportsPip If we should consider support for picture-in-picture mutli-window.
808 * @param activityType The activity type under consideration.
809 * @return true if the windowing mode is supported.
810 */
811 private boolean isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow,
812 boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip,
813 int activityType) {
814
815 if (windowingMode == WINDOWING_MODE_UNDEFINED
816 || windowingMode == WINDOWING_MODE_FULLSCREEN) {
817 return true;
818 }
819 if (!supportsMultiWindow) {
820 return false;
821 }
822
Evan Rosky10475742018-09-05 19:02:48 -0700823 final int displayWindowingMode = getWindowingMode();
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700824 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
825 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
Wale Ogunwale2b07da82017-11-08 14:52:40 -0800826 return supportsSplitScreen
Evan Rosky10475742018-09-05 19:02:48 -0700827 && WindowConfiguration.supportSplitScreenWindowingMode(activityType)
828 // Freeform windows and split-screen windows don't mix well, so prevent
829 // split windowing modes on freeform displays.
830 && displayWindowingMode != WINDOWING_MODE_FREEFORM;
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700831 }
832
833 if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) {
834 return false;
835 }
836
837 if (!supportsPip && windowingMode == WINDOWING_MODE_PINNED) {
838 return false;
839 }
840 return true;
841 }
842
Evan Rosky10475742018-09-05 19:02:48 -0700843 /**
844 * Resolves the windowing mode that an {@link ActivityRecord} would be in if started on this
845 * display with the provided parameters.
846 *
847 * @param r The ActivityRecord in question.
848 * @param options Options to start with.
849 * @param task The task within-which the activity would start.
850 * @param activityType The type of activity to start.
851 * @return The resolved (not UNDEFINED) windowing-mode that the activity would be in.
852 */
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700853 int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
Louis Changcdec0802019-11-11 11:45:07 +0800854 @Nullable Task task, int activityType) {
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700855
856 // First preference if the windowing mode in the activity options if set.
857 int windowingMode = (options != null)
858 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
859
860 // If windowing mode is unset, then next preference is the candidate task, then the
861 // activity record.
862 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
863 if (task != null) {
864 windowingMode = task.getWindowingMode();
865 }
866 if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) {
867 windowingMode = r.getWindowingMode();
868 }
869 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
870 // Use the display's windowing mode.
871 windowingMode = getWindowingMode();
872 }
873 }
Evan Rosky10475742018-09-05 19:02:48 -0700874 windowingMode = validateWindowingMode(windowingMode, r, task, activityType);
875 return windowingMode != WINDOWING_MODE_UNDEFINED
876 ? windowingMode : WINDOWING_MODE_FULLSCREEN;
Evan Rosky9ba524e2018-01-03 16:27:56 -0800877 }
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700878
Evan Rosky9ba524e2018-01-03 16:27:56 -0800879 /**
880 * Check that the requested windowing-mode is appropriate for the specified task and/or activity
881 * on this display.
882 *
883 * @param windowingMode The windowing-mode to validate.
884 * @param r The {@link ActivityRecord} to check against.
Louis Changcdec0802019-11-11 11:45:07 +0800885 * @param task The {@link Task} to check against.
Evan Rosky9ba524e2018-01-03 16:27:56 -0800886 * @param activityType An activity type.
887 * @return The provided windowingMode or the closest valid mode which is appropriate.
888 */
Louis Changcdec0802019-11-11 11:45:07 +0800889 int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task,
890 int activityType) {
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700891 // Make sure the windowing mode we are trying to use makes sense for what is supported.
Wale Ogunwaled32da472018-11-16 07:19:28 -0800892 boolean supportsMultiWindow = mService.mSupportsMultiWindow;
893 boolean supportsSplitScreen = mService.mSupportsSplitScreenMultiWindow;
894 boolean supportsFreeform = mService.mSupportsFreeformWindowManagement;
895 boolean supportsPip = mService.mSupportsPictureInPicture;
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700896 if (supportsMultiWindow) {
897 if (task != null) {
898 supportsMultiWindow = task.isResizeable();
899 supportsSplitScreen = task.supportsSplitScreenWindowingMode();
900 // TODO: Do we need to check for freeform and Pip support here?
901 } else if (r != null) {
902 supportsMultiWindow = r.isResizeable();
903 supportsSplitScreen = r.supportsSplitScreenWindowingMode();
904 supportsFreeform = r.supportsFreeform();
905 supportsPip = r.supportsPictureInPicture();
906 }
907 }
908
909 final boolean inSplitScreenMode = hasSplitScreenPrimaryStack();
910 if (!inSplitScreenMode
911 && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) {
Evan Rosky10475742018-09-05 19:02:48 -0700912 // Switch to the display's windowing mode if we are not in split-screen mode and we are
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700913 // trying to launch in split-screen secondary.
Evan Rosky10475742018-09-05 19:02:48 -0700914 windowingMode = WINDOWING_MODE_UNDEFINED;
915 } else if (inSplitScreenMode && (windowingMode == WINDOWING_MODE_FULLSCREEN
916 || windowingMode == WINDOWING_MODE_UNDEFINED)
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700917 && supportsSplitScreen) {
918 windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
919 }
920
921 if (windowingMode != WINDOWING_MODE_UNDEFINED
922 && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen,
Evan Rosky10475742018-09-05 19:02:48 -0700923 supportsFreeform, supportsPip, activityType)) {
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700924 return windowingMode;
925 }
Evan Rosky10475742018-09-05 19:02:48 -0700926 return WINDOWING_MODE_UNDEFINED;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700927 }
928
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700929 /**
930 * Get the topmost stack on the display. It may be different from focused stack, because
Andrii Kulian52d255c2018-07-13 11:32:19 -0700931 * some stacks are not focusable (e.g. PiP).
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700932 */
933 ActivityStack getTopStack() {
Louis Changba3f17a2019-11-11 12:29:17 +0800934 return mStacks.isEmpty() ? null : getChildAt(getChildCount() - 1);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700935 }
936
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700937 boolean isTopStack(ActivityStack stack) {
938 return stack == getTopStack();
939 }
940
chaviw2c500982018-01-04 17:05:05 -0800941 boolean isTopNotPinnedStack(ActivityStack stack) {
Louis Changba3f17a2019-11-11 12:29:17 +0800942 for (int i = getChildCount() - 1; i >= 0; --i) {
943 final ActivityStack current = getChildAt(i);
chaviw2c500982018-01-04 17:05:05 -0800944 if (!current.inPinnedWindowingMode()) {
Wale Ogunwale2cca8622017-12-11 08:40:13 -0800945 return current == stack;
946 }
947 }
948 return false;
949 }
950
Wale Ogunwalef3257852018-01-24 08:52:28 -0800951 ActivityStack getTopStackInWindowingMode(int windowingMode) {
Louis Changba3f17a2019-11-11 12:29:17 +0800952 for (int i = getChildCount() - 1; i >= 0; --i) {
953 final ActivityStack current = getChildAt(i);
Wale Ogunwalef3257852018-01-24 08:52:28 -0800954 if (windowingMode == current.getWindowingMode()) {
955 return current;
956 }
957 }
958 return null;
959 }
960
Riddle Hsue10cea52018-10-16 23:33:23 +0800961 ActivityRecord topRunningActivity() {
962 return topRunningActivity(false /* considerKeyguardState */);
963 }
964
965 /**
966 * Returns the top running activity in the focused stack. In the case the focused stack has no
967 * such activity, the next focusable stack on this display is returned.
968 *
969 * @param considerKeyguardState Indicates whether the locked state should be considered. if
970 * {@code true} and the keyguard is locked, only activities that
971 * can be shown on top of the keyguard will be considered.
972 * @return The top running activity. {@code null} if none is available.
973 */
974 ActivityRecord topRunningActivity(boolean considerKeyguardState) {
975 ActivityRecord topRunning = null;
976 final ActivityStack focusedStack = getFocusedStack();
977 if (focusedStack != null) {
978 topRunning = focusedStack.topRunningActivityLocked();
979 }
980
981 // Look in other focusable stacks.
982 if (topRunning == null) {
Louis Changba3f17a2019-11-11 12:29:17 +0800983 for (int i = getChildCount() - 1; i >= 0; --i) {
984 final ActivityStack stack = getChildAt(i);
Riddle Hsue10cea52018-10-16 23:33:23 +0800985 // Only consider focusable stacks other than the current focused one.
986 if (stack == focusedStack || !stack.isFocusable()) {
987 continue;
988 }
989 topRunning = stack.topRunningActivityLocked();
990 if (topRunning != null) {
991 break;
992 }
993 }
994 }
995
996 // This activity can be considered the top running activity if we are not considering
997 // the locked state, the keyguard isn't locked, or we can show when locked.
998 if (topRunning != null && considerKeyguardState
Wale Ogunwaled32da472018-11-16 07:19:28 -0800999 && mRootActivityContainer.mStackSupervisor.getKeyguardController().isKeyguardLocked()
Riddle Hsue10cea52018-10-16 23:33:23 +08001000 && !topRunning.canShowWhenLocked()) {
1001 return null;
1002 }
1003
1004 return topRunning;
1005 }
1006
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001007 int getIndexOf(ActivityStack stack) {
1008 return mStacks.indexOf(stack);
1009 }
1010
Shivam Agrawal1d3db652019-07-01 15:26:11 -07001011 boolean updateDisplayOverrideConfigurationLocked() {
1012 Configuration values = new Configuration();
1013 mDisplayContent.computeScreenConfiguration(values);
1014
Riddle Hsua0022cd2019-09-09 21:12:41 +08001015 mService.mH.sendMessage(PooledLambda.obtainMessage(
1016 ActivityManagerInternal::updateOomLevelsForDisplay, mService.mAmInternal,
1017 mDisplayId));
Shivam Agrawal1d3db652019-07-01 15:26:11 -07001018
1019 Settings.System.clearConfiguration(values);
1020 updateDisplayOverrideConfigurationLocked(values, null /* starting */,
1021 false /* deferResume */, mService.mTmpUpdateConfigurationResult);
1022 return mService.mTmpUpdateConfigurationResult.changes != 0;
1023 }
1024
1025 /**
1026 * Updates override configuration specific for the selected display. If no config is provided,
1027 * new one will be computed in WM based on current display info.
1028 */
1029 boolean updateDisplayOverrideConfigurationLocked(Configuration values,
1030 ActivityRecord starting, boolean deferResume,
1031 ActivityTaskManagerService.UpdateConfigurationResult result) {
1032
1033 int changes = 0;
1034 boolean kept = true;
1035
Riddle Hsua0022cd2019-09-09 21:12:41 +08001036 mService.deferWindowLayout();
Shivam Agrawal1d3db652019-07-01 15:26:11 -07001037 try {
1038 if (values != null) {
1039 if (mDisplayId == DEFAULT_DISPLAY) {
1040 // Override configuration of the default display duplicates global config, so
1041 // we're calling global config update instead for default display. It will also
1042 // apply the correct override config.
1043 changes = mService.updateGlobalConfigurationLocked(values,
1044 false /* initLocale */, false /* persistent */,
1045 UserHandle.USER_NULL /* userId */, deferResume);
1046 } else {
1047 changes = performDisplayOverrideConfigUpdate(values, deferResume);
1048 }
1049 }
1050
1051 kept = mService.ensureConfigAndVisibilityAfterUpdate(starting, changes);
1052 } finally {
Riddle Hsua0022cd2019-09-09 21:12:41 +08001053 mService.continueWindowLayout();
Shivam Agrawal1d3db652019-07-01 15:26:11 -07001054 }
1055
1056 if (result != null) {
1057 result.changes = changes;
1058 result.activityRelaunched = !kept;
1059 }
1060 return kept;
1061 }
1062
1063 int performDisplayOverrideConfigUpdate(Configuration values, boolean deferResume) {
1064 mTempConfig.setTo(getRequestedOverrideConfiguration());
1065 final int changes = mTempConfig.updateFrom(values);
1066 if (changes != 0) {
1067 Slog.i(TAG, "Override config changes=" + Integer.toHexString(changes) + " "
1068 + mTempConfig + " for displayId=" + mDisplayId);
1069 onRequestedOverrideConfigurationChanged(mTempConfig);
1070
1071 final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
1072 if (isDensityChange && mDisplayId == DEFAULT_DISPLAY) {
1073 mService.mAppWarnings.onDensityChanged();
1074
1075 // Post message to start process to avoid possible deadlock of calling into AMS with
1076 // the ATMS lock held.
1077 final Message msg = PooledLambda.obtainMessage(
1078 ActivityManagerInternal::killAllBackgroundProcessesExcept,
1079 mService.mAmInternal, N,
1080 ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
1081 mService.mH.sendMessage(msg);
1082 }
1083 }
1084 return changes;
1085 }
1086
Evan Roskye747c3e2018-10-30 20:06:41 -07001087 @Override
Evan Roskydfe3da72018-10-26 17:21:06 -07001088 public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
1089 final int currRotation =
1090 getRequestedOverrideConfiguration().windowConfiguration.getRotation();
Evan Roskye747c3e2018-10-30 20:06:41 -07001091 if (currRotation != ROTATION_UNDEFINED
1092 && currRotation != overrideConfiguration.windowConfiguration.getRotation()
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001093 && mDisplayContent != null) {
1094 mDisplayContent.applyRotationLocked(currRotation,
Evan Roskye747c3e2018-10-30 20:06:41 -07001095 overrideConfiguration.windowConfiguration.getRotation());
1096 }
Evan Roskydfe3da72018-10-26 17:21:06 -07001097 super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001098 if (mDisplayContent != null) {
1099 mService.mWindowManager.setNewDisplayOverrideConfiguration(
1100 overrideConfiguration, mDisplayContent);
1101 }
Riddle Hsua0022cd2019-09-09 21:12:41 +08001102 mService.addWindowLayoutReasons(
1103 ActivityTaskManagerService.LAYOUT_REASON_CONFIG_CHANGED);
Evan Roskye747c3e2018-10-30 20:06:41 -07001104 }
1105
1106 @Override
1107 public void onConfigurationChanged(Configuration newParentConfig) {
1108 // update resources before cascade so that docked/pinned stacks use the correct info
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001109 if (mDisplayContent != null) {
1110 mDisplayContent.preOnConfigurationChanged();
1111 }
Evan Roskye747c3e2018-10-30 20:06:41 -07001112 super.onConfigurationChanged(newParentConfig);
1113 }
1114
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001115 void onLockTaskPackagesUpdated() {
Louis Changba3f17a2019-11-11 12:29:17 +08001116 for (int i = getChildCount() - 1; i >= 0; --i) {
1117 getChildAt(i).onLockTaskPackagesUpdated();
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001118 }
1119 }
1120
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -07001121 /** We are in the process of exiting split-screen mode. */
1122 void onExitingSplitScreenMode() {
1123 // Remove reference to the primary-split-screen stack so it no longer has any effect on the
1124 // display. For example, we want to be able to create fullscreen stack for standard activity
1125 // types when exiting split-screen mode.
1126 mSplitScreenPrimaryStack = null;
1127 }
1128
Riddle Hsu7b766fd2019-01-28 21:14:59 +08001129 /** Checks whether the given activity is in size compatibility mode and notifies the change. */
1130 void handleActivitySizeCompatModeIfNeeded(ActivityRecord r) {
1131 if (!r.isState(RESUMED) || r.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
1132 // The callback is only interested in the foreground changes of fullscreen activity.
1133 return;
1134 }
1135 if (!r.inSizeCompatMode()) {
1136 if (mLastCompatModeActivity != null) {
1137 mService.getTaskChangeNotificationController()
1138 .notifySizeCompatModeActivityChanged(mDisplayId, null /* activityToken */);
1139 }
1140 mLastCompatModeActivity = null;
1141 return;
1142 }
1143 if (mLastCompatModeActivity == r) {
1144 return;
1145 }
1146 mLastCompatModeActivity = r;
1147 mService.getTaskChangeNotificationController()
1148 .notifySizeCompatModeActivityChanged(mDisplayId, r.appToken);
1149 }
1150
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001151 ActivityStack getSplitScreenPrimaryStack() {
1152 return mSplitScreenPrimaryStack;
1153 }
1154
1155 boolean hasSplitScreenPrimaryStack() {
1156 return mSplitScreenPrimaryStack != null;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001157 }
1158
Yunfan Chen279f5582018-12-12 15:24:50 -08001159 ActivityStack getPinnedStack() {
1160 return mPinnedStack;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001161 }
1162
1163 boolean hasPinnedStack() {
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001164 return mPinnedStack != null;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001165 }
1166
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001167 @Override
1168 public String toString() {
Louis Changba3f17a2019-11-11 12:29:17 +08001169 return "ActivityDisplay={" + mDisplayId + " numStacks=" + getChildCount() + "}";
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001170 }
1171
1172 @Override
1173 protected int getChildCount() {
1174 return mStacks.size();
1175 }
1176
1177 @Override
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001178 protected ActivityStack getChildAt(int index) {
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001179 return mStacks.get(index);
1180 }
1181
1182 @Override
1183 protected ConfigurationContainer getParent() {
Wale Ogunwaled32da472018-11-16 07:19:28 -08001184 return mRootActivityContainer;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001185 }
1186
1187 boolean isPrivate() {
1188 return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
1189 }
1190
1191 boolean isUidPresent(int uid) {
1192 for (ActivityStack stack : mStacks) {
1193 if (stack.isUidPresent(uid)) {
1194 return true;
1195 }
1196 }
1197 return false;
1198 }
1199
Louis Chang7d0037c2018-08-13 12:42:06 +08001200 /**
1201 * @see #mRemoved
1202 */
1203 boolean isRemoved() {
1204 return mRemoved;
1205 }
1206
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001207 /**
1208 * @see #mRemoving
1209 */
1210 boolean isRemoving() {
1211 return mRemoving;
1212 }
1213
Bryce Leef19cbe22018-02-02 15:09:21 -08001214 void remove() {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001215 mRemoving = true;
Bryce Leef19cbe22018-02-02 15:09:21 -08001216 final boolean destroyContentOnRemoval = shouldDestroyContentOnRemove();
Riddle Hsu402b4402018-11-06 17:23:15 +08001217 ActivityStack lastReparentedStack = null;
1218 mPreferredTopFocusableStack = null;
Louis Chang7d0037c2018-08-13 12:42:06 +08001219
1220 // Stacks could be reparented from the removed display to other display. While
1221 // reparenting the last stack of the removed display, the remove display is ready to be
1222 // released (no more ActivityStack). But, we cannot release it at that moment or the
Riddle Hsu5947c362019-09-23 18:52:36 +08001223 // related WindowContainer will also be removed. So, we set display as removed after
1224 // reparenting stack finished.
Wale Ogunwaled32da472018-11-16 07:19:28 -08001225 final ActivityDisplay toDisplay = mRootActivityContainer.getDefaultDisplay();
1226 mRootActivityContainer.mStackSupervisor.beginDeferResume();
Riddle Hsu402b4402018-11-06 17:23:15 +08001227 try {
Louis Changba3f17a2019-11-11 12:29:17 +08001228 int numStacks = getChildCount();
Riddle Hsu402b4402018-11-06 17:23:15 +08001229 // Keep the order from bottom to top.
1230 for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
Louis Changba3f17a2019-11-11 12:29:17 +08001231 final ActivityStack stack = getChildAt(stackNdx);
Riddle Hsu402b4402018-11-06 17:23:15 +08001232 // Always finish non-standard type stacks.
1233 if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) {
Andrii Kuliande93eff2019-07-12 12:21:27 -07001234 stack.finishAllActivitiesImmediately();
Riddle Hsu402b4402018-11-06 17:23:15 +08001235 } else {
1236 // If default display is in split-window mode, set windowing mode of the stack
1237 // to split-screen secondary. Otherwise, set the windowing mode to undefined by
1238 // default to let stack inherited the windowing mode from the new display.
1239 final int windowingMode = toDisplay.hasSplitScreenPrimaryStack()
1240 ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
1241 : WINDOWING_MODE_UNDEFINED;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001242 stack.reparent(toDisplay.mDisplayContent, true /* onTop */);
Riddle Hsu402b4402018-11-06 17:23:15 +08001243 stack.setWindowingMode(windowingMode);
1244 lastReparentedStack = stack;
1245 }
1246 // Stacks may be removed from this display. Ensure each stack will be processed and
1247 // the loop will end.
Louis Changba3f17a2019-11-11 12:29:17 +08001248 stackNdx -= numStacks - getChildCount();
1249 numStacks = getChildCount();
Bryce Leef19cbe22018-02-02 15:09:21 -08001250 }
Riddle Hsu402b4402018-11-06 17:23:15 +08001251 } finally {
Wale Ogunwaled32da472018-11-16 07:19:28 -08001252 mRootActivityContainer.mStackSupervisor.endDeferResume();
Bryce Leef19cbe22018-02-02 15:09:21 -08001253 }
Louis Chang7d0037c2018-08-13 12:42:06 +08001254 mRemoved = true;
Bryce Leef19cbe22018-02-02 15:09:21 -08001255
Riddle Hsu402b4402018-11-06 17:23:15 +08001256 // Only update focus/visibility for the last one because there may be many stacks are
1257 // reparented and the intermediate states are unnecessary.
1258 if (lastReparentedStack != null) {
1259 lastReparentedStack.postReparent();
1260 }
Louis Chang7d0037c2018-08-13 12:42:06 +08001261 releaseSelfIfNeeded();
wilsonshih0299c8a2018-08-24 15:52:57 +08001262
Riddle Hsuf53da812018-08-15 22:00:27 +08001263 if (!mAllSleepTokens.isEmpty()) {
Wale Ogunwaled32da472018-11-16 07:19:28 -08001264 mRootActivityContainer.mSleepTokens.removeAll(mAllSleepTokens);
Riddle Hsuf53da812018-08-15 22:00:27 +08001265 mAllSleepTokens.clear();
Wale Ogunwaled32da472018-11-16 07:19:28 -08001266 mService.updateSleepIfNeededLocked();
Riddle Hsuf53da812018-08-15 22:00:27 +08001267 }
Louis Chang7d0037c2018-08-13 12:42:06 +08001268 }
1269
1270 private void releaseSelfIfNeeded() {
Louis Changcc568712019-03-08 14:54:41 +08001271 if (!mRemoved || mDisplayContent == null) {
1272 return;
1273 }
1274
Louis Changba3f17a2019-11-11 12:29:17 +08001275 final ActivityStack stack = getChildCount() == 1 ? getChildAt(0) : null;
Louis Changcc568712019-03-08 14:54:41 +08001276 if (stack != null && stack.isActivityTypeHome() && stack.getAllTasks().isEmpty()) {
1277 // Release this display if an empty home stack is the only thing left.
1278 // Since it is the last stack, this display will be released along with the stack
1279 // removal.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001280 stack.removeIfPossible();
Louis Changcc568712019-03-08 14:54:41 +08001281 } else if (mStacks.isEmpty()) {
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001282 mDisplayContent.removeIfPossible();
1283 mDisplayContent = null;
Wale Ogunwaled32da472018-11-16 07:19:28 -08001284 mRootActivityContainer.removeChild(this);
1285 mRootActivityContainer.mStackSupervisor
1286 .getKeyguardController().onDisplayRemoved(mDisplayId);
Louis Chang7d0037c2018-08-13 12:42:06 +08001287 }
Bryce Leef19cbe22018-02-02 15:09:21 -08001288 }
1289
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001290 /** Update and get all UIDs that are present on the display and have access to it. */
1291 IntArray getPresentUIDs() {
1292 mDisplayAccessUIDs.clear();
1293 for (ActivityStack stack : mStacks) {
1294 stack.getPresentUIDs(mDisplayAccessUIDs);
1295 }
1296 return mDisplayAccessUIDs;
1297 }
1298
Louis Changbd48dca2018-08-29 17:44:34 +08001299 /**
Andrii Kulian15cfb422018-11-07 13:38:49 -08001300 * Checks if system decorations should be shown on this display.
1301 *
Louis Changbd48dca2018-08-29 17:44:34 +08001302 * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
1303 */
1304 boolean supportsSystemDecorations() {
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001305 return mDisplayContent.supportsSystemDecorations();
Louis Changbd48dca2018-08-29 17:44:34 +08001306 }
1307
Riddle Hsu402b4402018-11-06 17:23:15 +08001308 @VisibleForTesting
1309 boolean shouldDestroyContentOnRemove() {
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001310 return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT;
1311 }
1312
1313 boolean shouldSleep() {
1314 return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty())
Wale Ogunwaled32da472018-11-16 07:19:28 -08001315 && (mService.mRunningVoice == null);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001316 }
1317
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001318 void setFocusedApp(ActivityRecord r, boolean moveFocusNow) {
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001319 if (mDisplayContent == null) {
1320 return;
1321 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07001322 final ActivityRecord newFocus;
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001323 final IBinder token = r.appToken;
1324 if (token == null) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001325 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "Clearing focused app, displayId=%d",
1326 mDisplayId);
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001327 newFocus = null;
1328 } else {
Garfield Tane8d84ab2019-10-11 09:49:40 -07001329 newFocus = mService.mWindowManager.mRoot.getActivityRecord(token);
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001330 if (newFocus == null) {
1331 Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token
1332 + ", displayId=" + mDisplayId);
1333 }
Adrian Roosb125e0b2019-10-02 14:55:14 +02001334 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
1335 "Set focused app to: %s moveFocusNow=%b displayId=%d", newFocus,
1336 moveFocusNow, mDisplayId);
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001337 }
1338
1339 final boolean changed = mDisplayContent.setFocusedApp(newFocus);
1340 if (moveFocusNow && changed) {
1341 mService.mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
1342 true /*updateInputWindows*/);
1343 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001344 }
1345
Winson Chunge2d72172018-01-25 17:46:20 +00001346 /**
Winson Chung3e2980e2018-03-29 17:28:57 -07001347 * @return the stack currently above the {@param stack}. Can be null if the {@param stack} is
1348 * already top-most.
Winson Chunge2d72172018-01-25 17:46:20 +00001349 */
Winson Chung3e2980e2018-03-29 17:28:57 -07001350 ActivityStack getStackAbove(ActivityStack stack) {
1351 final int stackIndex = mStacks.indexOf(stack) + 1;
Louis Changba3f17a2019-11-11 12:29:17 +08001352 return (stackIndex < getChildCount()) ? getChildAt(stackIndex) : null;
Winson Chunge2d72172018-01-25 17:46:20 +00001353 }
1354
1355 /**
Winson Chung3e2980e2018-03-29 17:28:57 -07001356 * Adjusts the {@param stack} behind the last visible stack in the display if necessary.
1357 * Generally used in conjunction with {@link #moveStackBehindStack}.
Winson Chunge2d72172018-01-25 17:46:20 +00001358 */
Winson Chung3e2980e2018-03-29 17:28:57 -07001359 void moveStackBehindBottomMostVisibleStack(ActivityStack stack) {
1360 if (stack.shouldBeVisible(null)) {
1361 // Skip if the stack is already visible
Winson Chunge2d72172018-01-25 17:46:20 +00001362 return;
1363 }
1364
Winson Chung3e2980e2018-03-29 17:28:57 -07001365 // Move the stack to the bottom to not affect the following visibility checks
1366 positionChildAtBottom(stack);
Winson Chunge2d72172018-01-25 17:46:20 +00001367
Winson Chung3e2980e2018-03-29 17:28:57 -07001368 // Find the next position where the stack should be placed
Louis Changba3f17a2019-11-11 12:29:17 +08001369 final int numStacks = getChildCount();
Winson Chunge2d72172018-01-25 17:46:20 +00001370 for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
Louis Changba3f17a2019-11-11 12:29:17 +08001371 final ActivityStack s = getChildAt(stackNdx);
Winson Chung3e2980e2018-03-29 17:28:57 -07001372 if (s == stack) {
Winson Chunge2d72172018-01-25 17:46:20 +00001373 continue;
1374 }
Winson Chung3e2980e2018-03-29 17:28:57 -07001375 final int winMode = s.getWindowingMode();
Winson Chunge2d72172018-01-25 17:46:20 +00001376 final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN ||
1377 winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
Winson Chung3e2980e2018-03-29 17:28:57 -07001378 if (s.shouldBeVisible(null) && isValidWindowingMode) {
1379 // Move the provided stack to behind this stack
1380 positionChildAt(stack, Math.max(0, stackNdx - 1));
Winson Chunge2d72172018-01-25 17:46:20 +00001381 break;
1382 }
1383 }
1384 }
1385
1386 /**
Winson Chung3e2980e2018-03-29 17:28:57 -07001387 * Moves the {@param stack} behind the given {@param behindStack} if possible. If
1388 * {@param behindStack} is not currently in the display, then then the stack is moved to the
1389 * back. Generally used in conjunction with {@link #moveStackBehindBottomMostVisibleStack}.
Winson Chunge2d72172018-01-25 17:46:20 +00001390 */
Winson Chung3e2980e2018-03-29 17:28:57 -07001391 void moveStackBehindStack(ActivityStack stack, ActivityStack behindStack) {
1392 if (behindStack == null || behindStack == stack) {
Winson Chunge2d72172018-01-25 17:46:20 +00001393 return;
1394 }
1395
Winson Chung123e07a2018-02-27 11:47:16 -08001396 // Note that positionChildAt will first remove the given stack before inserting into the
1397 // list, so we need to adjust the insertion index to account for the removed index
1398 // TODO: Remove this logic when WindowContainer.positionChildAt() is updated to adjust the
1399 // position internally
Winson Chung3e2980e2018-03-29 17:28:57 -07001400 final int stackIndex = mStacks.indexOf(stack);
Winson Chung123e07a2018-02-27 11:47:16 -08001401 final int behindStackIndex = mStacks.indexOf(behindStack);
Winson Chung3e2980e2018-03-29 17:28:57 -07001402 final int insertIndex = stackIndex <= behindStackIndex
Winson Chung123e07a2018-02-27 11:47:16 -08001403 ? behindStackIndex - 1 : behindStackIndex;
Winson Chung3e2980e2018-03-29 17:28:57 -07001404 positionChildAt(stack, Math.max(0, insertIndex));
Winson Chunge2d72172018-01-25 17:46:20 +00001405 }
1406
Louis Chang77ce34d2019-01-03 15:45:12 +08001407 void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
1408 boolean preserveWindows, boolean notifyClients) {
1409 for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
1410 final ActivityStack stack = getChildAt(stackNdx);
1411 stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
1412 notifyClients);
1413 }
1414 }
1415
Louis Changbd48dca2018-08-29 17:44:34 +08001416 void moveHomeStackToFront(String reason) {
1417 if (mHomeStack != null) {
1418 mHomeStack.moveToFront(reason);
1419 }
1420 }
1421
Riddle Hsu2b9a6d72019-04-24 23:55:11 +08001422 /**
1423 * Moves the focusable home activity to top. If there is no such activity, the home stack will
1424 * still move to top.
1425 */
1426 void moveHomeActivityToTop(String reason) {
Louis Changbd48dca2018-08-29 17:44:34 +08001427 final ActivityRecord top = getHomeActivity();
1428 if (top == null) {
Riddle Hsu2b9a6d72019-04-24 23:55:11 +08001429 moveHomeStackToFront(reason);
1430 return;
Louis Changbd48dca2018-08-29 17:44:34 +08001431 }
Louis Chang19443452018-10-09 12:10:21 +08001432 top.moveFocusableActivityToTop(reason);
Louis Changbd48dca2018-08-29 17:44:34 +08001433 }
1434
1435 @Nullable
1436 ActivityStack getHomeStack() {
1437 return mHomeStack;
1438 }
1439
1440 @Nullable
1441 ActivityRecord getHomeActivity() {
Wale Ogunwaled32da472018-11-16 07:19:28 -08001442 return getHomeActivityForUser(mRootActivityContainer.mCurrentUser);
Louis Changbd48dca2018-08-29 17:44:34 +08001443 }
1444
1445 @Nullable
1446 ActivityRecord getHomeActivityForUser(int userId) {
1447 if (mHomeStack == null) {
1448 return null;
1449 }
1450
Louis Changcdec0802019-11-11 11:45:07 +08001451 final ArrayList<Task> tasks = mHomeStack.getAllTasks();
Louis Changbd48dca2018-08-29 17:44:34 +08001452 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
Louis Changcdec0802019-11-11 11:45:07 +08001453 final Task task = tasks.get(taskNdx);
Louis Changbd48dca2018-08-29 17:44:34 +08001454 if (!task.isActivityTypeHome()) {
1455 continue;
1456 }
1457
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001458 for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
1459 final ActivityRecord r = task.getChildAt(activityNdx);
Louis Changbd48dca2018-08-29 17:44:34 +08001460 if (r.isActivityTypeHome()
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001461 && ((userId == UserHandle.USER_ALL) || (r.mUserId == userId))) {
Louis Changbd48dca2018-08-29 17:44:34 +08001462 return r;
1463 }
1464 }
1465 }
1466 return null;
1467 }
1468
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001469 boolean isSleeping() {
1470 return mSleeping;
1471 }
1472
1473 void setIsSleeping(boolean asleep) {
1474 mSleeping = asleep;
1475 }
1476
Winson Chung0f7ec962018-05-03 18:03:15 -07001477 /**
1478 * Adds a listener to be notified whenever the stack order in the display changes. Currently
1479 * only used by the {@link RecentsAnimation} to determine whether to interrupt and cancel the
1480 * current animation when the system state changes.
1481 */
1482 void registerStackOrderChangedListener(OnStackOrderChangedListener listener) {
1483 if (!mStackOrderChangedCallbacks.contains(listener)) {
1484 mStackOrderChangedCallbacks.add(listener);
1485 }
1486 }
1487
1488 /**
1489 * Removes a previously registered stack order change listener.
1490 */
1491 void unregisterStackOrderChangedListener(OnStackOrderChangedListener listener) {
1492 mStackOrderChangedCallbacks.remove(listener);
1493 }
1494
Winson Chung65d66d32018-12-13 17:48:39 -08001495 /**
1496 * Notifies of a stack order change
1497 * @param stack The stack which triggered the order change
1498 */
1499 private void onStackOrderChanged(ActivityStack stack) {
Winson Chung0f7ec962018-05-03 18:03:15 -07001500 for (int i = mStackOrderChangedCallbacks.size() - 1; i >= 0; i--) {
Winson Chung65d66d32018-12-13 17:48:39 -08001501 mStackOrderChangedCallbacks.get(i).onStackOrderChanged(stack);
Winson Chung0f7ec962018-05-03 18:03:15 -07001502 }
1503 }
1504
Chavi Weingarten3a748552018-05-14 17:32:42 +00001505 /**
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001506 * See {@link DisplayContent#deferUpdateImeTarget()}
Chavi Weingarten3a748552018-05-14 17:32:42 +00001507 */
1508 public void deferUpdateImeTarget() {
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001509 if (mDisplayContent != null) {
1510 mDisplayContent.deferUpdateImeTarget();
1511 }
Chavi Weingarten3a748552018-05-14 17:32:42 +00001512 }
1513
1514 /**
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001515 * See {@link DisplayContent#deferUpdateImeTarget()}
Chavi Weingarten3a748552018-05-14 17:32:42 +00001516 */
1517 public void continueUpdateImeTarget() {
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001518 if (mDisplayContent != null) {
1519 mDisplayContent.continueUpdateImeTarget();
1520 }
Chavi Weingarten3a748552018-05-14 17:32:42 +00001521 }
1522
Wale Ogunwale9e737db2018-12-17 15:42:37 -08001523 void setDisplayToSingleTaskInstance() {
1524 final int childCount = getChildCount();
1525 if (childCount > 1) {
1526 throw new IllegalArgumentException("Display already has multiple stacks. display="
1527 + this);
1528 }
1529 if (childCount > 0) {
1530 final ActivityStack stack = getChildAt(0);
1531 if (stack.getChildCount() > 1) {
1532 throw new IllegalArgumentException("Display stack already has multiple tasks."
1533 + " display=" + this + " stack=" + stack);
1534 }
1535 }
1536
1537 mSingleTaskInstance = true;
1538 }
1539
1540 /** Returns true if the display can only contain one task */
1541 boolean isSingleTaskInstance() {
1542 return mSingleTaskInstance;
1543 }
1544
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001545 @VisibleForTesting
1546 void removeAllTasks() {
1547 for (int i = getChildCount() - 1; i >= 0; --i) {
1548 final ActivityStack stack = getChildAt(i);
Louis Changcdec0802019-11-11 11:45:07 +08001549 final ArrayList<Task> tasks = stack.getAllTasks();
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001550 for (int j = tasks.size() - 1; j >= 0; --j) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02001551 stack.removeChild(tasks.get(j), "removeAllTasks");
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001552 }
1553 }
1554 }
1555
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001556 public void dump(PrintWriter pw, String prefix) {
Louis Changba3f17a2019-11-11 12:29:17 +08001557 pw.println(prefix + "displayId=" + mDisplayId + " stacks=" + getChildCount()
Wale Ogunwale9e737db2018-12-17 15:42:37 -08001558 + (mSingleTaskInstance ? " mSingleTaskInstance" : ""));
Wale Ogunwale30e441d2017-11-09 08:28:45 -08001559 final String myPrefix = prefix + " ";
1560 if (mHomeStack != null) {
1561 pw.println(myPrefix + "mHomeStack=" + mHomeStack);
1562 }
1563 if (mRecentsStack != null) {
1564 pw.println(myPrefix + "mRecentsStack=" + mRecentsStack);
1565 }
1566 if (mPinnedStack != null) {
1567 pw.println(myPrefix + "mPinnedStack=" + mPinnedStack);
1568 }
1569 if (mSplitScreenPrimaryStack != null) {
1570 pw.println(myPrefix + "mSplitScreenPrimaryStack=" + mSplitScreenPrimaryStack);
1571 }
Riddle Hsu75016992018-09-20 20:37:14 +08001572 if (mPreferredTopFocusableStack != null) {
1573 pw.println(myPrefix + "mPreferredTopFocusableStack=" + mPreferredTopFocusableStack);
1574 }
Riddle Hsubbb63c22018-10-03 12:28:29 +08001575 if (mLastFocusedStack != null) {
1576 pw.println(myPrefix + "mLastFocusedStack=" + mLastFocusedStack);
1577 }
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001578 }
1579
Bryce Lee77a7dd62018-01-22 15:47:09 -08001580 public void dumpStacks(PrintWriter pw) {
Louis Changba3f17a2019-11-11 12:29:17 +08001581 for (int i = getChildCount() - 1; i >= 0; --i) {
1582 pw.print(getChildAt(i).mStackId);
Bryce Lee77a7dd62018-01-22 15:47:09 -08001583 if (i > 0) {
1584 pw.print(",");
1585 }
1586 }
1587 }
1588
Nataniel Borges023ecb52019-01-16 14:15:43 -08001589 public void writeToProto(ProtoOutputStream proto, long fieldId,
1590 @WindowTraceLogLevel int logLevel) {
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001591 final long token = proto.start(fieldId);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001592 super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001593 proto.write(ID, mDisplayId);
Wale Ogunwale9e737db2018-12-17 15:42:37 -08001594 proto.write(SINGLE_TASK_INSTANCE, mSingleTaskInstance);
Andrii Kulianab132ee2018-07-24 22:10:21 +08001595 final ActivityStack focusedStack = getFocusedStack();
1596 if (focusedStack != null) {
1597 proto.write(FOCUSED_STACK_ID, focusedStack.mStackId);
1598 final ActivityRecord focusedActivity = focusedStack.getDisplay().getResumedActivity();
1599 if (focusedActivity != null) {
1600 focusedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
1601 }
1602 } else {
1603 proto.write(FOCUSED_STACK_ID, INVALID_STACK_ID);
1604 }
Louis Changba3f17a2019-11-11 12:29:17 +08001605 for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
1606 final ActivityStack stack = getChildAt(stackNdx);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001607 stack.writeToProto(proto, STACKS, logLevel);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001608 }
1609 proto.end(token);
1610 }
Winson Chung0f7ec962018-05-03 18:03:15 -07001611
1612 /**
1613 * Callback for when the order of the stacks in the display changes.
1614 */
1615 interface OnStackOrderChangedListener {
Winson Chung65d66d32018-12-13 17:48:39 -08001616 void onStackOrderChanged(ActivityStack stack);
Winson Chung0f7ec962018-05-03 18:03:15 -07001617 }
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001618}