blob: 86c8dc57557cf29aa1c5523684e09e4285d0617d [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());
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700183 }
184
Riddle Hsuf53da812018-08-15 22:00:27 +0800185 void onDisplayChanged() {
186 // The window policy is responsible for stopping activities on the default display.
187 final int displayId = mDisplay.getDisplayId();
188 if (displayId != DEFAULT_DISPLAY) {
189 final int displayState = mDisplay.getState();
190 if (displayState == Display.STATE_OFF && mOffToken == null) {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800191 mOffToken = mService.acquireSleepToken("Display-off", displayId);
Riddle Hsuf53da812018-08-15 22:00:27 +0800192 } else if (displayState == Display.STATE_ON && mOffToken != null) {
193 mOffToken.release();
194 mOffToken = null;
195 }
196 }
197
Wale Ogunwale8a1860a2019-06-05 08:57:19 -0700198 mDisplay.getRealSize(mTmpDisplaySize);
199 setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800200 if (mDisplayContent != null) {
201 mDisplayContent.updateDisplayInfo();
202 mService.mWindowManager.requestTraversal();
203 }
Riddle Hsuf53da812018-08-15 22:00:27 +0800204 }
205
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700206 // TODO(display-unify): Merge with addChild below.
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700207 void addChild(ActivityStack stack, int position) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700208 addChild(stack, position, false /*fromDc*/);
209 }
210
211 void addChild(ActivityStack stack, int position, boolean fromDc) {
212 boolean toTop = position == POSITION_TOP;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700213 if (position == POSITION_BOTTOM) {
214 position = 0;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700215 } else if (toTop) {
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700216 position = mStacks.size();
217 }
218 if (DEBUG_STACK) Slog.v(TAG_STACK, "addChild: attaching " + stack
219 + " to displayId=" + mDisplayId + " position=" + position);
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700220 addStackReferenceIfNeeded(stack);
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700221 if (!fromDc) {
222 mDisplayContent.setStackOnDisplay(stack, position);
223 }
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700224 positionChildAt(stack, position);
Wale Ogunwaled32da472018-11-16 07:19:28 -0800225 mService.updateSleepIfNeededLocked();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700226 }
227
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700228 // TODO(display-unify): Merge with removeChild below.
229 void onChildRemoved(ActivityStack stack) {
230 if (!mStacks.remove(stack)) {
231 // Stack no longer here!
232 return;
233 }
234
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700235 if (DEBUG_STACK) Slog.v(TAG_STACK, "removeChild: detaching " + stack
236 + " from displayId=" + mDisplayId);
Riddle Hsu75016992018-09-20 20:37:14 +0800237 if (mPreferredTopFocusableStack == stack) {
238 mPreferredTopFocusableStack = null;
239 }
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700240 removeStackReferenceIfNeeded(stack);
Louis Chang7d0037c2018-08-13 12:42:06 +0800241 releaseSelfIfNeeded();
Wale Ogunwaled32da472018-11-16 07:19:28 -0800242 mService.updateSleepIfNeededLocked();
Winson Chung65d66d32018-12-13 17:48:39 -0800243 onStackOrderChanged(stack);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700244 }
245
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700246 void removeChild(ActivityStack stack) {
247 mDisplayContent.removeStackFromDisplay(stack);
248 }
249
Riddle Hsu57831b52018-07-27 00:31:48 +0800250 void positionChildAtTop(ActivityStack stack, boolean includingParents) {
Riddle Hsubbb63c22018-10-03 12:28:29 +0800251 positionChildAtTop(stack, includingParents, null /* updateLastFocusedStackReason */);
252 }
253
254 void positionChildAtTop(ActivityStack stack, boolean includingParents,
255 String updateLastFocusedStackReason) {
256 positionChildAt(stack, mStacks.size(), includingParents, updateLastFocusedStackReason);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700257 }
258
259 void positionChildAtBottom(ActivityStack stack) {
Riddle Hsubbb63c22018-10-03 12:28:29 +0800260 positionChildAtBottom(stack, null /* updateLastFocusedStackReason */);
261 }
262
263 void positionChildAtBottom(ActivityStack stack, String updateLastFocusedStackReason) {
264 positionChildAt(stack, 0, false /* includingParents */, updateLastFocusedStackReason);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700265 }
266
267 private void positionChildAt(ActivityStack stack, int position) {
Riddle Hsubbb63c22018-10-03 12:28:29 +0800268 positionChildAt(stack, position, false /* includingParents */,
269 null /* updateLastFocusedStackReason */);
Riddle Hsu57831b52018-07-27 00:31:48 +0800270 }
271
Riddle Hsubbb63c22018-10-03 12:28:29 +0800272 private void positionChildAt(ActivityStack stack, int position, boolean includingParents,
273 String updateLastFocusedStackReason) {
Winson Chung123e07a2018-02-27 11:47:16 -0800274 // TODO: Keep in sync with WindowContainer.positionChildAt(), once we change that to adjust
275 // the position internally, also update the logic here
Riddle Hsubbb63c22018-10-03 12:28:29 +0800276 final ActivityStack prevFocusedStack = updateLastFocusedStackReason != null
277 ? getFocusedStack() : null;
Riddle Hsu75016992018-09-20 20:37:14 +0800278 final boolean wasContained = mStacks.remove(stack);
Wale Ogunwale9e737db2018-12-17 15:42:37 -0800279 if (mSingleTaskInstance && getChildCount() > 0) {
280 throw new IllegalStateException(
281 "positionChildAt: Can only have one child on display=" + this);
282 }
Winson Chung59a47ded2018-01-25 17:46:06 +0000283 final int insertPosition = getTopInsertPosition(stack, position);
284 mStacks.add(insertPosition, stack);
Riddle Hsu75016992018-09-20 20:37:14 +0800285
286 // The insert position may be adjusted to non-top when there is always-on-top stack. Since
287 // the original position is preferred to be top, the stack should have higher priority when
288 // we are looking for top focusable stack. The condition {@code wasContained} restricts the
289 // preferred stack is set only when moving an existing stack to top instead of adding a new
290 // stack that may be too early (e.g. in the middle of launching or reparenting).
291 if (wasContained && position >= mStacks.size() - 1 && stack.isFocusableAndVisible()) {
292 mPreferredTopFocusableStack = stack;
293 } else if (mPreferredTopFocusableStack == stack) {
294 mPreferredTopFocusableStack = null;
295 }
296
Riddle Hsubbb63c22018-10-03 12:28:29 +0800297 if (updateLastFocusedStackReason != null) {
298 final ActivityStack currentFocusedStack = getFocusedStack();
299 if (currentFocusedStack != prevFocusedStack) {
300 mLastFocusedStack = prevFocusedStack;
Wale Ogunwaled32da472018-11-16 07:19:28 -0800301 EventLogTags.writeAmFocusedStack(mRootActivityContainer.mCurrentUser, mDisplayId,
Riddle Hsubbb63c22018-10-03 12:28:29 +0800302 currentFocusedStack == null ? -1 : currentFocusedStack.getStackId(),
303 mLastFocusedStack == null ? -1 : mLastFocusedStack.getStackId(),
304 updateLastFocusedStackReason);
305 }
306 }
307
Kazuki Takise048e2662018-06-27 17:05:11 +0900308 // Since positionChildAt() is called during the creation process of pinned stacks,
Riddle Hsu5947c362019-09-23 18:52:36 +0800309 // ActivityStack#getStack() can be null.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700310 if (mDisplayContent != null) {
311 mDisplayContent.positionStackAt(insertPosition, stack, includingParents);
Evan Roskyc5abbd82018-10-05 16:02:19 -0700312 }
Winson Chung65d66d32018-12-13 17:48:39 -0800313 onStackOrderChanged(stack);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700314 }
315
316 private int getTopInsertPosition(ActivityStack stack, int candidatePosition) {
317 int position = mStacks.size();
Kazuki Takise148d00a2018-05-31 15:32:19 +0900318 if (stack.inPinnedWindowingMode()) {
319 // Stack in pinned windowing mode is z-ordered on-top of all other stacks so okay to
320 // just return the candidate position.
321 return Math.min(position, candidatePosition);
322 }
323 while (position > 0) {
324 final ActivityStack targetStack = mStacks.get(position - 1);
325 if (!targetStack.isAlwaysOnTop()) {
326 // We reached a stack that isn't always-on-top.
327 break;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700328 }
Kazuki Takise148d00a2018-05-31 15:32:19 +0900329 if (stack.isAlwaysOnTop() && !targetStack.inPinnedWindowingMode()) {
330 // Always on-top non-pinned windowing mode stacks can go anywhere below pinned stack.
331 break;
332 }
333 position--;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700334 }
335 return Math.min(position, candidatePosition);
336 }
337
338 <T extends ActivityStack> T getStack(int stackId) {
339 for (int i = mStacks.size() - 1; i >= 0; --i) {
340 final ActivityStack stack = mStacks.get(i);
341 if (stack.mStackId == stackId) {
342 return (T) stack;
343 }
344 }
345 return null;
346 }
347
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700348 /**
349 * @return the topmost stack on the display that is compatible with the input windowing mode and
350 * activity type. {@code null} means no compatible stack on the display.
351 * @see ConfigurationContainer#isCompatible(int, int)
352 */
353 <T extends ActivityStack> T getStack(int windowingMode, int activityType) {
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700354 if (activityType == ACTIVITY_TYPE_HOME) {
355 return (T) mHomeStack;
356 } else if (activityType == ACTIVITY_TYPE_RECENTS) {
357 return (T) mRecentsStack;
358 }
359 if (windowingMode == WINDOWING_MODE_PINNED) {
360 return (T) mPinnedStack;
361 } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
362 return (T) mSplitScreenPrimaryStack;
363 }
Wale Ogunwaleab5de372017-10-18 06:46:31 -0700364
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700365 for (int i = mStacks.size() - 1; i >= 0; --i) {
366 final ActivityStack stack = mStacks.get(i);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700367 if (stack.isCompatible(windowingMode, activityType)) {
368 return (T) stack;
369 }
370 }
371 return null;
372 }
373
Louis Chang9d6ba282019-02-20 17:22:10 +0800374 boolean alwaysCreateStack(int windowingMode, int activityType) {
Wale Ogunwaleab5de372017-10-18 06:46:31 -0700375 // Always create a stack for fullscreen, freeform, and split-screen-secondary windowing
376 // modes so that we can manage visual ordering and return types correctly.
377 return activityType == ACTIVITY_TYPE_STANDARD
378 && (windowingMode == WINDOWING_MODE_FULLSCREEN
379 || windowingMode == WINDOWING_MODE_FREEFORM
380 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
381 }
382
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700383 /**
Wale Ogunwaleab5de372017-10-18 06:46:31 -0700384 * Returns an existing stack compatible with the windowing mode and activity type or creates one
385 * if a compatible stack doesn't exist.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700386 * @see #getStack(int, int)
387 * @see #createStack(int, int, boolean)
388 */
389 <T extends ActivityStack> T getOrCreateStack(int windowingMode, int activityType,
390 boolean onTop) {
Wale Ogunwaleab5de372017-10-18 06:46:31 -0700391 if (!alwaysCreateStack(windowingMode, activityType)) {
392 T stack = getStack(windowingMode, activityType);
393 if (stack != null) {
394 return stack;
395 }
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700396 }
397 return createStack(windowingMode, activityType, onTop);
398 }
399
Wale Ogunwale68278562017-09-23 17:13:55 -0700400 /**
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700401 * Returns an existing stack compatible with the input params or creates one
402 * if a compatible stack doesn't exist.
403 * @see #getOrCreateStack(int, int, boolean)
404 */
405 <T extends ActivityStack> T getOrCreateStack(@Nullable ActivityRecord r,
406 @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, int activityType,
407 boolean onTop) {
Evan Rosky10475742018-09-05 19:02:48 -0700408 // First preference is the windowing mode in the activity options if set.
409 int windowingMode = (options != null)
410 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
411 // Validate that our desired windowingMode will work under the current conditions.
412 // UNDEFINED windowing mode is a valid result and means that the new stack will inherit
413 // it's display's windowing mode.
414 windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType);
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700415 return getOrCreateStack(windowingMode, activityType, onTop);
416 }
417
Louis Changf2835df2018-10-17 15:14:45 +0800418 @VisibleForTesting
419 int getNextStackId() {
Bryce Leed9cce2c2017-12-04 16:16:27 -0800420 return sNextFreeStackId++;
421 }
422
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700423 /**
Wale Ogunwale68278562017-09-23 17:13:55 -0700424 * Creates a stack matching the input windowing mode and activity type on this display.
425 * @param windowingMode The windowing mode the stack should be created in. If
426 * {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will
Evan Rosky10475742018-09-05 19:02:48 -0700427 * inherit it's parent's windowing mode.
Wale Ogunwale68278562017-09-23 17:13:55 -0700428 * @param activityType The activityType the stack should be created in. If
429 * {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will
430 * be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
431 * @param onTop If true the stack will be created at the top of the display, else at the bottom.
432 * @return The newly created stack.
433 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700434 <T extends ActivityStack> T createStack(int windowingMode, int activityType, boolean onTop) {
435
Wale Ogunwale9e737db2018-12-17 15:42:37 -0800436 if (mSingleTaskInstance && getChildCount() > 0) {
437 // Create stack on default display instead since this display can only contain 1 stack.
438 // TODO: Kinda a hack, but better that having the decision at each call point. Hoping
439 // this goes away once ActivityView is no longer using virtual displays.
440 return mRootActivityContainer.getDefaultDisplay().createStack(
441 windowingMode, activityType, onTop);
442 }
443
Wale Ogunwale68278562017-09-23 17:13:55 -0700444 if (activityType == ACTIVITY_TYPE_UNDEFINED) {
445 // Can't have an undefined stack type yet...so re-map to standard. Anyone that wants
446 // anything else should be passing it in anyways...
447 activityType = ACTIVITY_TYPE_STANDARD;
448 }
449
450 if (activityType != ACTIVITY_TYPE_STANDARD) {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700451 // For now there can be only one stack of a particular non-standard activity type on a
452 // display. So, get that ignoring whatever windowing mode it is currently in.
453 T stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
454 if (stack != null) {
455 throw new IllegalArgumentException("Stack=" + stack + " of activityType="
456 + activityType + " already on display=" + this + ". Can't have multiple.");
457 }
458 }
459
Wale Ogunwaled32da472018-11-16 07:19:28 -0800460 if (!isWindowingModeSupported(windowingMode, mService.mSupportsMultiWindow,
461 mService.mSupportsSplitScreenMultiWindow,
462 mService.mSupportsFreeformWindowManagement, mService.mSupportsPictureInPicture,
463 activityType)) {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700464 throw new IllegalArgumentException("Can't create stack for unsupported windowingMode="
465 + windowingMode);
466 }
467
Bryce Leed9cce2c2017-12-04 16:16:27 -0800468 final int stackId = getNextStackId();
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700469 return createStackUnchecked(windowingMode, activityType, stackId, onTop);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700470 }
471
472 @VisibleForTesting
473 <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
474 int stackId, boolean onTop) {
Yunfan Chen279f5582018-12-12 15:24:50 -0800475 if (windowingMode == WINDOWING_MODE_PINNED && activityType != ACTIVITY_TYPE_STANDARD) {
476 throw new IllegalArgumentException("Stack with windowing mode cannot with non standard "
477 + "activity type.");
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700478 }
Wale Ogunwaled32da472018-11-16 07:19:28 -0800479 return (T) new ActivityStack(this, stackId,
Yunfan Chen279f5582018-12-12 15:24:50 -0800480 mRootActivityContainer.mStackSupervisor, windowingMode, activityType, onTop);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700481 }
482
Riddle Hsu75016992018-09-20 20:37:14 +0800483 /**
484 * Get the preferred focusable stack in priority. If the preferred stack does not exist, find a
485 * focusable and visible stack from the top of stacks in this display.
486 */
Andrii Kulian52d255c2018-07-13 11:32:19 -0700487 ActivityStack getFocusedStack() {
Riddle Hsu75016992018-09-20 20:37:14 +0800488 if (mPreferredTopFocusableStack != null) {
489 return mPreferredTopFocusableStack;
490 }
491
Andrii Kulian52d255c2018-07-13 11:32:19 -0700492 for (int i = mStacks.size() - 1; i >= 0; --i) {
493 final ActivityStack stack = mStacks.get(i);
Riddle Hsu75016992018-09-20 20:37:14 +0800494 if (stack.isFocusableAndVisible()) {
Andrii Kulian52d255c2018-07-13 11:32:19 -0700495 return stack;
496 }
497 }
498
499 return null;
500 }
501
Andrii Kulianab132ee2018-07-24 22:10:21 +0800502 ActivityStack getNextFocusableStack(ActivityStack currentFocus, boolean ignoreCurrent) {
503 final int currentWindowingMode = currentFocus != null
504 ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
505
506 ActivityStack candidate = null;
507 for (int i = mStacks.size() - 1; i >= 0; --i) {
508 final ActivityStack stack = mStacks.get(i);
509 if (ignoreCurrent && stack == currentFocus) {
510 continue;
511 }
Riddle Hsu75016992018-09-20 20:37:14 +0800512 if (!stack.isFocusableAndVisible()) {
Andrii Kulianab132ee2018-07-24 22:10:21 +0800513 continue;
514 }
515
516 if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
517 && candidate == null && stack.inSplitScreenPrimaryWindowingMode()) {
518 // If the currently focused stack is in split-screen secondary we save off the
519 // top primary split-screen stack as a candidate for focus because we might
520 // prefer focus to move to an other stack to avoid primary split-screen stack
521 // overlapping with a fullscreen stack when a fullscreen stack is higher in z
522 // than the next split-screen stack. Assistant stack, I am looking at you...
523 // We only move the focus to the primary-split screen stack if there isn't a
524 // better alternative.
525 candidate = stack;
526 continue;
527 }
528 if (candidate != null && stack.inSplitScreenSecondaryWindowingMode()) {
529 // Use the candidate stack since we are now at the secondary split-screen.
530 return candidate;
531 }
532 return stack;
533 }
534 return candidate;
535 }
536
Andrii Kulian52d255c2018-07-13 11:32:19 -0700537 ActivityRecord getResumedActivity() {
538 final ActivityStack focusedStack = getFocusedStack();
539 if (focusedStack == null) {
540 return null;
541 }
542 // TODO(b/111541062): Move this into ActivityStack#getResumedActivity()
543 // Check if the focused stack has the resumed activity
544 ActivityRecord resumedActivity = focusedStack.getResumedActivity();
545 if (resumedActivity == null || resumedActivity.app == null) {
546 // If there is no registered resumed activity in the stack or it is not running -
547 // try to use previously resumed one.
548 resumedActivity = focusedStack.mPausingActivity;
549 if (resumedActivity == null || resumedActivity.app == null) {
550 // If previously resumed activity doesn't work either - find the topmost running
551 // activity that can be focused.
552 resumedActivity = focusedStack.topRunningActivityLocked(true /* focusableOnly */);
553 }
554 }
555 return resumedActivity;
556 }
557
Riddle Hsubbb63c22018-10-03 12:28:29 +0800558 ActivityStack getLastFocusedStack() {
559 return mLastFocusedStack;
560 }
561
562 boolean allResumedActivitiesComplete() {
563 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
564 final ActivityRecord r = mStacks.get(stackNdx).getResumedActivity();
565 if (r != null && !r.isState(RESUMED)) {
566 return false;
567 }
568 }
569 final ActivityStack currentFocusedStack = getFocusedStack();
570 if (DEBUG_STACK) {
571 Slog.d(TAG_STACK, "allResumedActivitiesComplete: mLastFocusedStack changing from="
572 + mLastFocusedStack + " to=" + currentFocusedStack);
573 }
574 mLastFocusedStack = currentFocusedStack;
575 return true;
576 }
577
Wale Ogunwale68278562017-09-23 17:13:55 -0700578 /**
Andrii Kulian6b321512019-01-23 06:37:00 +0000579 * Pause all activities in either all of the stacks or just the back stacks. This is done before
580 * resuming a new activity and to make sure that previously active activities are
581 * paused in stacks that are no longer visible or in pinned windowing mode. This does not
582 * pause activities in visible stacks, so if an activity is launched within the same stack/task,
583 * then we should explicitly pause that stack's top activity.
Andrii Kulianab132ee2018-07-24 22:10:21 +0800584 * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
585 * @param resuming The resuming activity.
Andrii Kulian6b321512019-01-23 06:37:00 +0000586 * @return {@code true} if any activity was paused as a result of this call.
Andrii Kulianab132ee2018-07-24 22:10:21 +0800587 */
Louis Chang7b03ad92019-08-21 12:32:33 +0800588 boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming) {
Andrii Kulianab132ee2018-07-24 22:10:21 +0800589 boolean someActivityPaused = false;
590 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
591 final ActivityStack stack = mStacks.get(stackNdx);
Andrii Kulian6b321512019-01-23 06:37:00 +0000592 final ActivityRecord resumedActivity = stack.getResumedActivity();
593 if (resumedActivity != null
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800594 && (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
595 || !stack.isFocusable())) {
Andrii Kulianab132ee2018-07-24 22:10:21 +0800596 if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
Andrii Kulian6b321512019-01-23 06:37:00 +0000597 " mResumedActivity=" + resumedActivity);
Louis Chang7b03ad92019-08-21 12:32:33 +0800598 someActivityPaused |= stack.startPausingLocked(userLeaving, false /* uiSleeping*/,
599 resuming);
Andrii Kulianab132ee2018-07-24 22:10:21 +0800600 }
601 }
602 return someActivityPaused;
603 }
604
605 /**
Louis Changc85b1a32018-08-14 16:40:53 +0800606 * Find task for putting the Activity in.
607 */
608 void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplay,
609 FindTaskResult result) {
610 mTmpFindTaskResult.clear();
611 for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
612 final ActivityStack stack = getChildAt(stackNdx);
613 if (!r.hasCompatibleActivityType(stack)) {
614 if (DEBUG_TASKS) {
615 Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) " + stack);
616 }
617 continue;
618 }
619
620 stack.findTaskLocked(r, mTmpFindTaskResult);
621 // It is possible to have tasks in multiple stacks with the same root affinity, so
622 // we should keep looking after finding an affinity match to see if there is a
623 // better match in another stack. Also, task affinity isn't a good enough reason
624 // to target a display which isn't the source of the intent, so skip any affinity
625 // matches not on the specified display.
626 if (mTmpFindTaskResult.mRecord != null) {
627 if (mTmpFindTaskResult.mIdealMatch) {
628 result.setTo(mTmpFindTaskResult);
629 return;
630 } else if (isPreferredDisplay) {
631 // Note: since the traversing through the stacks is top down, the floating
632 // tasks should always have lower priority than any affinity-matching tasks
633 // in the fullscreen stacks
634 result.setTo(mTmpFindTaskResult);
635 }
636 }
637 }
638 }
639
640 /**
Wale Ogunwale68278562017-09-23 17:13:55 -0700641 * Removes stacks in the input windowing modes from the system if they are of activity type
642 * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
643 */
644 void removeStacksInWindowingModes(int... windowingModes) {
645 if (windowingModes == null || windowingModes.length == 0) {
646 return;
647 }
648
Louis Changf787e532019-01-15 12:46:49 +0800649 // Collect the stacks that are necessary to be removed instead of performing the removal
650 // by looping mStacks, so that we don't miss any stacks after the stack size changed or
651 // stacks reordered.
652 final ArrayList<ActivityStack> stacks = new ArrayList<>();
Wale Ogunwale68278562017-09-23 17:13:55 -0700653 for (int j = windowingModes.length - 1 ; j >= 0; --j) {
654 final int windowingMode = windowingModes[j];
655 for (int i = mStacks.size() - 1; i >= 0; --i) {
656 final ActivityStack stack = mStacks.get(i);
657 if (!stack.isActivityTypeStandardOrUndefined()) {
658 continue;
659 }
660 if (stack.getWindowingMode() != windowingMode) {
661 continue;
662 }
Louis Changf787e532019-01-15 12:46:49 +0800663 stacks.add(stack);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700664 }
665 }
Louis Changf787e532019-01-15 12:46:49 +0800666
667 for (int i = stacks.size() - 1; i >= 0; --i) {
668 mRootActivityContainer.mStackSupervisor.removeStack(stacks.get(i));
669 }
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700670 }
671
Wale Ogunwale68278562017-09-23 17:13:55 -0700672 void removeStacksWithActivityTypes(int... activityTypes) {
673 if (activityTypes == null || activityTypes.length == 0) {
674 return;
675 }
676
Louis Changf787e532019-01-15 12:46:49 +0800677 // Collect the stacks that are necessary to be removed instead of performing the removal
678 // by looping mStacks, so that we don't miss any stacks after the stack size changed or
679 // stacks reordered.
680 final ArrayList<ActivityStack> stacks = new ArrayList<>();
Wale Ogunwale68278562017-09-23 17:13:55 -0700681 for (int j = activityTypes.length - 1 ; j >= 0; --j) {
682 final int activityType = activityTypes[j];
683 for (int i = mStacks.size() - 1; i >= 0; --i) {
684 final ActivityStack stack = mStacks.get(i);
685 if (stack.getActivityType() == activityType) {
Louis Changf787e532019-01-15 12:46:49 +0800686 stacks.add(stack);
Wale Ogunwale68278562017-09-23 17:13:55 -0700687 }
688 }
689 }
Louis Changf787e532019-01-15 12:46:49 +0800690
691 for (int i = stacks.size() - 1; i >= 0; --i) {
692 mRootActivityContainer.mStackSupervisor.removeStack(stacks.get(i));
693 }
Wale Ogunwale68278562017-09-23 17:13:55 -0700694 }
695
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700696 void onStackWindowingModeChanged(ActivityStack stack) {
697 removeStackReferenceIfNeeded(stack);
698 addStackReferenceIfNeeded(stack);
699 }
700
701 private void addStackReferenceIfNeeded(ActivityStack stack) {
702 final int activityType = stack.getActivityType();
703 final int windowingMode = stack.getWindowingMode();
704
705 if (activityType == ACTIVITY_TYPE_HOME) {
706 if (mHomeStack != null && mHomeStack != stack) {
Louis Chang7d0037c2018-08-13 12:42:06 +0800707 throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700708 + mHomeStack + " already exist on display=" + this + " stack=" + stack);
709 }
Louis Chang7d0037c2018-08-13 12:42:06 +0800710 mHomeStack = stack;
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700711 } else if (activityType == ACTIVITY_TYPE_RECENTS) {
712 if (mRecentsStack != null && mRecentsStack != stack) {
713 throw new IllegalArgumentException("addStackReferenceIfNeeded: recents stack="
714 + mRecentsStack + " already exist on display=" + this + " stack=" + stack);
715 }
716 mRecentsStack = stack;
717 }
718 if (windowingMode == WINDOWING_MODE_PINNED) {
719 if (mPinnedStack != null && mPinnedStack != stack) {
720 throw new IllegalArgumentException("addStackReferenceIfNeeded: pinned stack="
721 + mPinnedStack + " already exist on display=" + this
722 + " stack=" + stack);
723 }
724 mPinnedStack = stack;
725 } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
726 if (mSplitScreenPrimaryStack != null && mSplitScreenPrimaryStack != stack) {
727 throw new IllegalArgumentException("addStackReferenceIfNeeded:"
728 + " split-screen-primary" + " stack=" + mSplitScreenPrimaryStack
729 + " already exist on display=" + this + " stack=" + stack);
730 }
731 mSplitScreenPrimaryStack = stack;
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800732 onSplitScreenModeActivated();
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700733 }
734 }
735
736 private void removeStackReferenceIfNeeded(ActivityStack stack) {
737 if (stack == mHomeStack) {
738 mHomeStack = null;
739 } else if (stack == mRecentsStack) {
740 mRecentsStack = null;
741 } else if (stack == mPinnedStack) {
742 mPinnedStack = null;
743 } else if (stack == mSplitScreenPrimaryStack) {
744 mSplitScreenPrimaryStack = null;
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800745 // Inform the reset of the system that split-screen mode was dismissed so things like
746 // resizing all the other stacks can take place.
747 onSplitScreenModeDismissed();
748 }
749 }
750
751 private void onSplitScreenModeDismissed() {
Riddle Hsua0022cd2019-09-09 21:12:41 +0800752 mService.deferWindowLayout();
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800753 try {
754 // Adjust the windowing mode of any stack in secondary split-screen to fullscreen.
755 for (int i = mStacks.size() - 1; i >= 0; --i) {
756 final ActivityStack otherStack = mStacks.get(i);
757 if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
758 continue;
759 }
Evan Rosky10475742018-09-05 19:02:48 -0700760 otherStack.setWindowingMode(WINDOWING_MODE_UNDEFINED, false /* animate */,
Andrii Kulian9da138a2018-04-24 17:12:44 -0700761 false /* showRecents */, false /* enteringSplitScreenMode */,
Evan Roskyc5abbd82018-10-05 16:02:19 -0700762 true /* deferEnsuringVisibility */, false /* creating */);
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800763 }
764 } finally {
Wale Ogunwale1dbc5c82017-12-08 08:12:20 -0800765 final ActivityStack topFullscreenStack =
Wale Ogunwalef3257852018-01-24 08:52:28 -0800766 getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN);
Wale Ogunwale1dbc5c82017-12-08 08:12:20 -0800767 if (topFullscreenStack != null && mHomeStack != null && !isTopStack(mHomeStack)) {
Wale Ogunwaleeb76b762017-11-17 10:08:04 -0800768 // Whenever split-screen is dismissed we want the home stack directly behind the
Wale Ogunwale1dbc5c82017-12-08 08:12:20 -0800769 // current top fullscreen stack so it shows up when the top stack is finished.
Wale Ogunwaleeb76b762017-11-17 10:08:04 -0800770 // TODO: Would be better to use ActivityDisplay.positionChildAt() for this, however
771 // ActivityDisplay doesn't have a direct controller to WM side yet. We can switch
772 // once we have that.
773 mHomeStack.moveToFront("onSplitScreenModeDismissed");
Wale Ogunwale1dbc5c82017-12-08 08:12:20 -0800774 topFullscreenStack.moveToFront("onSplitScreenModeDismissed");
Wale Ogunwaleeb76b762017-11-17 10:08:04 -0800775 }
Riddle Hsua0022cd2019-09-09 21:12:41 +0800776 mService.continueWindowLayout();
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800777 }
778 }
779
780 private void onSplitScreenModeActivated() {
Riddle Hsua0022cd2019-09-09 21:12:41 +0800781 mService.deferWindowLayout();
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800782 try {
783 // Adjust the windowing mode of any affected by split-screen to split-screen secondary.
784 for (int i = mStacks.size() - 1; i >= 0; --i) {
785 final ActivityStack otherStack = mStacks.get(i);
786 if (otherStack == mSplitScreenPrimaryStack
787 || !otherStack.affectedBySplitScreenResize()) {
788 continue;
789 }
Wale Ogunwaledf262f52017-12-07 18:17:12 -0800790 otherStack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
791 false /* animate */, false /* showRecents */,
Evan Roskyc5abbd82018-10-05 16:02:19 -0700792 true /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */,
793 false /* creating */);
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800794 }
795 } finally {
Riddle Hsua0022cd2019-09-09 21:12:41 +0800796 mService.continueWindowLayout();
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700797 }
798 }
799
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700800 /**
801 * Returns true if the {@param windowingMode} is supported based on other parameters passed in.
802 * @param windowingMode The windowing mode we are checking support for.
803 * @param supportsMultiWindow If we should consider support for multi-window mode in general.
804 * @param supportsSplitScreen If we should consider support for split-screen multi-window.
805 * @param supportsFreeform If we should consider support for freeform multi-window.
806 * @param supportsPip If we should consider support for picture-in-picture mutli-window.
807 * @param activityType The activity type under consideration.
808 * @return true if the windowing mode is supported.
809 */
810 private boolean isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow,
811 boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip,
812 int activityType) {
813
814 if (windowingMode == WINDOWING_MODE_UNDEFINED
815 || windowingMode == WINDOWING_MODE_FULLSCREEN) {
816 return true;
817 }
818 if (!supportsMultiWindow) {
819 return false;
820 }
821
Evan Rosky10475742018-09-05 19:02:48 -0700822 final int displayWindowingMode = getWindowingMode();
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700823 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
824 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
Wale Ogunwale2b07da82017-11-08 14:52:40 -0800825 return supportsSplitScreen
Evan Rosky10475742018-09-05 19:02:48 -0700826 && WindowConfiguration.supportSplitScreenWindowingMode(activityType)
827 // Freeform windows and split-screen windows don't mix well, so prevent
828 // split windowing modes on freeform displays.
829 && displayWindowingMode != WINDOWING_MODE_FREEFORM;
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700830 }
831
832 if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) {
833 return false;
834 }
835
836 if (!supportsPip && windowingMode == WINDOWING_MODE_PINNED) {
837 return false;
838 }
839 return true;
840 }
841
Evan Rosky10475742018-09-05 19:02:48 -0700842 /**
843 * Resolves the windowing mode that an {@link ActivityRecord} would be in if started on this
844 * display with the provided parameters.
845 *
846 * @param r The ActivityRecord in question.
847 * @param options Options to start with.
848 * @param task The task within-which the activity would start.
849 * @param activityType The type of activity to start.
850 * @return The resolved (not UNDEFINED) windowing-mode that the activity would be in.
851 */
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700852 int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
853 @Nullable TaskRecord task, int activityType) {
854
855 // First preference if the windowing mode in the activity options if set.
856 int windowingMode = (options != null)
857 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
858
859 // If windowing mode is unset, then next preference is the candidate task, then the
860 // activity record.
861 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
862 if (task != null) {
863 windowingMode = task.getWindowingMode();
864 }
865 if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) {
866 windowingMode = r.getWindowingMode();
867 }
868 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
869 // Use the display's windowing mode.
870 windowingMode = getWindowingMode();
871 }
872 }
Evan Rosky10475742018-09-05 19:02:48 -0700873 windowingMode = validateWindowingMode(windowingMode, r, task, activityType);
874 return windowingMode != WINDOWING_MODE_UNDEFINED
875 ? windowingMode : WINDOWING_MODE_FULLSCREEN;
Evan Rosky9ba524e2018-01-03 16:27:56 -0800876 }
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700877
Evan Rosky9ba524e2018-01-03 16:27:56 -0800878 /**
879 * Check that the requested windowing-mode is appropriate for the specified task and/or activity
880 * on this display.
881 *
882 * @param windowingMode The windowing-mode to validate.
883 * @param r The {@link ActivityRecord} to check against.
884 * @param task The {@link TaskRecord} to check against.
885 * @param activityType An activity type.
886 * @return The provided windowingMode or the closest valid mode which is appropriate.
887 */
888 int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r,
889 @Nullable TaskRecord task, int activityType) {
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700890 // Make sure the windowing mode we are trying to use makes sense for what is supported.
Wale Ogunwaled32da472018-11-16 07:19:28 -0800891 boolean supportsMultiWindow = mService.mSupportsMultiWindow;
892 boolean supportsSplitScreen = mService.mSupportsSplitScreenMultiWindow;
893 boolean supportsFreeform = mService.mSupportsFreeformWindowManagement;
894 boolean supportsPip = mService.mSupportsPictureInPicture;
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700895 if (supportsMultiWindow) {
896 if (task != null) {
897 supportsMultiWindow = task.isResizeable();
898 supportsSplitScreen = task.supportsSplitScreenWindowingMode();
899 // TODO: Do we need to check for freeform and Pip support here?
900 } else if (r != null) {
901 supportsMultiWindow = r.isResizeable();
902 supportsSplitScreen = r.supportsSplitScreenWindowingMode();
903 supportsFreeform = r.supportsFreeform();
904 supportsPip = r.supportsPictureInPicture();
905 }
906 }
907
908 final boolean inSplitScreenMode = hasSplitScreenPrimaryStack();
909 if (!inSplitScreenMode
910 && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) {
Evan Rosky10475742018-09-05 19:02:48 -0700911 // 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 -0700912 // trying to launch in split-screen secondary.
Evan Rosky10475742018-09-05 19:02:48 -0700913 windowingMode = WINDOWING_MODE_UNDEFINED;
914 } else if (inSplitScreenMode && (windowingMode == WINDOWING_MODE_FULLSCREEN
915 || windowingMode == WINDOWING_MODE_UNDEFINED)
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700916 && supportsSplitScreen) {
917 windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
918 }
919
920 if (windowingMode != WINDOWING_MODE_UNDEFINED
921 && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen,
Evan Rosky10475742018-09-05 19:02:48 -0700922 supportsFreeform, supportsPip, activityType)) {
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700923 return windowingMode;
924 }
Evan Rosky10475742018-09-05 19:02:48 -0700925 return WINDOWING_MODE_UNDEFINED;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700926 }
927
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700928 /**
929 * Get the topmost stack on the display. It may be different from focused stack, because
Andrii Kulian52d255c2018-07-13 11:32:19 -0700930 * some stacks are not focusable (e.g. PiP).
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700931 */
932 ActivityStack getTopStack() {
933 return mStacks.isEmpty() ? null : mStacks.get(mStacks.size() - 1);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700934 }
935
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700936 boolean isTopStack(ActivityStack stack) {
937 return stack == getTopStack();
938 }
939
chaviw2c500982018-01-04 17:05:05 -0800940 boolean isTopNotPinnedStack(ActivityStack stack) {
Wale Ogunwale2cca8622017-12-11 08:40:13 -0800941 for (int i = mStacks.size() - 1; i >= 0; --i) {
942 final ActivityStack current = mStacks.get(i);
chaviw2c500982018-01-04 17:05:05 -0800943 if (!current.inPinnedWindowingMode()) {
Wale Ogunwale2cca8622017-12-11 08:40:13 -0800944 return current == stack;
945 }
946 }
947 return false;
948 }
949
Wale Ogunwalef3257852018-01-24 08:52:28 -0800950 ActivityStack getTopStackInWindowingMode(int windowingMode) {
951 for (int i = mStacks.size() - 1; i >= 0; --i) {
952 final ActivityStack current = mStacks.get(i);
953 if (windowingMode == current.getWindowingMode()) {
954 return current;
955 }
956 }
957 return null;
958 }
959
Riddle Hsue10cea52018-10-16 23:33:23 +0800960 ActivityRecord topRunningActivity() {
961 return topRunningActivity(false /* considerKeyguardState */);
962 }
963
964 /**
965 * Returns the top running activity in the focused stack. In the case the focused stack has no
966 * such activity, the next focusable stack on this display is returned.
967 *
968 * @param considerKeyguardState Indicates whether the locked state should be considered. if
969 * {@code true} and the keyguard is locked, only activities that
970 * can be shown on top of the keyguard will be considered.
971 * @return The top running activity. {@code null} if none is available.
972 */
973 ActivityRecord topRunningActivity(boolean considerKeyguardState) {
974 ActivityRecord topRunning = null;
975 final ActivityStack focusedStack = getFocusedStack();
976 if (focusedStack != null) {
977 topRunning = focusedStack.topRunningActivityLocked();
978 }
979
980 // Look in other focusable stacks.
981 if (topRunning == null) {
982 for (int i = mStacks.size() - 1; i >= 0; --i) {
983 final ActivityStack stack = mStacks.get(i);
984 // Only consider focusable stacks other than the current focused one.
985 if (stack == focusedStack || !stack.isFocusable()) {
986 continue;
987 }
988 topRunning = stack.topRunningActivityLocked();
989 if (topRunning != null) {
990 break;
991 }
992 }
993 }
994
995 // This activity can be considered the top running activity if we are not considering
996 // the locked state, the keyguard isn't locked, or we can show when locked.
997 if (topRunning != null && considerKeyguardState
Wale Ogunwaled32da472018-11-16 07:19:28 -0800998 && mRootActivityContainer.mStackSupervisor.getKeyguardController().isKeyguardLocked()
Riddle Hsue10cea52018-10-16 23:33:23 +0800999 && !topRunning.canShowWhenLocked()) {
1000 return null;
1001 }
1002
1003 return topRunning;
1004 }
1005
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001006 int getIndexOf(ActivityStack stack) {
1007 return mStacks.indexOf(stack);
1008 }
1009
Shivam Agrawal1d3db652019-07-01 15:26:11 -07001010 boolean updateDisplayOverrideConfigurationLocked() {
1011 Configuration values = new Configuration();
1012 mDisplayContent.computeScreenConfiguration(values);
1013
Riddle Hsua0022cd2019-09-09 21:12:41 +08001014 mService.mH.sendMessage(PooledLambda.obtainMessage(
1015 ActivityManagerInternal::updateOomLevelsForDisplay, mService.mAmInternal,
1016 mDisplayId));
Shivam Agrawal1d3db652019-07-01 15:26:11 -07001017
1018 Settings.System.clearConfiguration(values);
1019 updateDisplayOverrideConfigurationLocked(values, null /* starting */,
1020 false /* deferResume */, mService.mTmpUpdateConfigurationResult);
1021 return mService.mTmpUpdateConfigurationResult.changes != 0;
1022 }
1023
1024 /**
1025 * Updates override configuration specific for the selected display. If no config is provided,
1026 * new one will be computed in WM based on current display info.
1027 */
1028 boolean updateDisplayOverrideConfigurationLocked(Configuration values,
1029 ActivityRecord starting, boolean deferResume,
1030 ActivityTaskManagerService.UpdateConfigurationResult result) {
1031
1032 int changes = 0;
1033 boolean kept = true;
1034
Riddle Hsua0022cd2019-09-09 21:12:41 +08001035 mService.deferWindowLayout();
Shivam Agrawal1d3db652019-07-01 15:26:11 -07001036 try {
1037 if (values != null) {
1038 if (mDisplayId == DEFAULT_DISPLAY) {
1039 // Override configuration of the default display duplicates global config, so
1040 // we're calling global config update instead for default display. It will also
1041 // apply the correct override config.
1042 changes = mService.updateGlobalConfigurationLocked(values,
1043 false /* initLocale */, false /* persistent */,
1044 UserHandle.USER_NULL /* userId */, deferResume);
1045 } else {
1046 changes = performDisplayOverrideConfigUpdate(values, deferResume);
1047 }
1048 }
1049
1050 kept = mService.ensureConfigAndVisibilityAfterUpdate(starting, changes);
1051 } finally {
Riddle Hsua0022cd2019-09-09 21:12:41 +08001052 mService.continueWindowLayout();
Shivam Agrawal1d3db652019-07-01 15:26:11 -07001053 }
1054
1055 if (result != null) {
1056 result.changes = changes;
1057 result.activityRelaunched = !kept;
1058 }
1059 return kept;
1060 }
1061
1062 int performDisplayOverrideConfigUpdate(Configuration values, boolean deferResume) {
1063 mTempConfig.setTo(getRequestedOverrideConfiguration());
1064 final int changes = mTempConfig.updateFrom(values);
1065 if (changes != 0) {
1066 Slog.i(TAG, "Override config changes=" + Integer.toHexString(changes) + " "
1067 + mTempConfig + " for displayId=" + mDisplayId);
1068 onRequestedOverrideConfigurationChanged(mTempConfig);
1069
1070 final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
1071 if (isDensityChange && mDisplayId == DEFAULT_DISPLAY) {
1072 mService.mAppWarnings.onDensityChanged();
1073
1074 // Post message to start process to avoid possible deadlock of calling into AMS with
1075 // the ATMS lock held.
1076 final Message msg = PooledLambda.obtainMessage(
1077 ActivityManagerInternal::killAllBackgroundProcessesExcept,
1078 mService.mAmInternal, N,
1079 ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
1080 mService.mH.sendMessage(msg);
1081 }
1082 }
1083 return changes;
1084 }
1085
Evan Roskye747c3e2018-10-30 20:06:41 -07001086 @Override
Evan Roskydfe3da72018-10-26 17:21:06 -07001087 public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
1088 final int currRotation =
1089 getRequestedOverrideConfiguration().windowConfiguration.getRotation();
Evan Roskye747c3e2018-10-30 20:06:41 -07001090 if (currRotation != ROTATION_UNDEFINED
1091 && currRotation != overrideConfiguration.windowConfiguration.getRotation()
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001092 && mDisplayContent != null) {
1093 mDisplayContent.applyRotationLocked(currRotation,
Evan Roskye747c3e2018-10-30 20:06:41 -07001094 overrideConfiguration.windowConfiguration.getRotation());
1095 }
Evan Roskydfe3da72018-10-26 17:21:06 -07001096 super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001097 if (mDisplayContent != null) {
1098 mService.mWindowManager.setNewDisplayOverrideConfiguration(
1099 overrideConfiguration, mDisplayContent);
1100 }
Riddle Hsua0022cd2019-09-09 21:12:41 +08001101 mService.addWindowLayoutReasons(
1102 ActivityTaskManagerService.LAYOUT_REASON_CONFIG_CHANGED);
Evan Roskye747c3e2018-10-30 20:06:41 -07001103 }
1104
1105 @Override
1106 public void onConfigurationChanged(Configuration newParentConfig) {
1107 // update resources before cascade so that docked/pinned stacks use the correct info
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001108 if (mDisplayContent != null) {
1109 mDisplayContent.preOnConfigurationChanged();
1110 }
Evan Roskye747c3e2018-10-30 20:06:41 -07001111 super.onConfigurationChanged(newParentConfig);
1112 }
1113
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001114 void onLockTaskPackagesUpdated() {
1115 for (int i = mStacks.size() - 1; i >= 0; --i) {
1116 mStacks.get(i).onLockTaskPackagesUpdated();
1117 }
1118 }
1119
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -07001120 /** We are in the process of exiting split-screen mode. */
1121 void onExitingSplitScreenMode() {
1122 // Remove reference to the primary-split-screen stack so it no longer has any effect on the
1123 // display. For example, we want to be able to create fullscreen stack for standard activity
1124 // types when exiting split-screen mode.
1125 mSplitScreenPrimaryStack = null;
1126 }
1127
Riddle Hsu7b766fd2019-01-28 21:14:59 +08001128 /** Checks whether the given activity is in size compatibility mode and notifies the change. */
1129 void handleActivitySizeCompatModeIfNeeded(ActivityRecord r) {
1130 if (!r.isState(RESUMED) || r.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
1131 // The callback is only interested in the foreground changes of fullscreen activity.
1132 return;
1133 }
1134 if (!r.inSizeCompatMode()) {
1135 if (mLastCompatModeActivity != null) {
1136 mService.getTaskChangeNotificationController()
1137 .notifySizeCompatModeActivityChanged(mDisplayId, null /* activityToken */);
1138 }
1139 mLastCompatModeActivity = null;
1140 return;
1141 }
1142 if (mLastCompatModeActivity == r) {
1143 return;
1144 }
1145 mLastCompatModeActivity = r;
1146 mService.getTaskChangeNotificationController()
1147 .notifySizeCompatModeActivityChanged(mDisplayId, r.appToken);
1148 }
1149
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001150 ActivityStack getSplitScreenPrimaryStack() {
1151 return mSplitScreenPrimaryStack;
1152 }
1153
1154 boolean hasSplitScreenPrimaryStack() {
1155 return mSplitScreenPrimaryStack != null;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001156 }
1157
Yunfan Chen279f5582018-12-12 15:24:50 -08001158 ActivityStack getPinnedStack() {
1159 return mPinnedStack;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001160 }
1161
1162 boolean hasPinnedStack() {
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001163 return mPinnedStack != null;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001164 }
1165
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001166 @Override
1167 public String toString() {
1168 return "ActivityDisplay={" + mDisplayId + " numStacks=" + mStacks.size() + "}";
1169 }
1170
1171 @Override
1172 protected int getChildCount() {
1173 return mStacks.size();
1174 }
1175
1176 @Override
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001177 protected ActivityStack getChildAt(int index) {
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001178 return mStacks.get(index);
1179 }
1180
1181 @Override
1182 protected ConfigurationContainer getParent() {
Wale Ogunwaled32da472018-11-16 07:19:28 -08001183 return mRootActivityContainer;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001184 }
1185
1186 boolean isPrivate() {
1187 return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
1188 }
1189
1190 boolean isUidPresent(int uid) {
1191 for (ActivityStack stack : mStacks) {
1192 if (stack.isUidPresent(uid)) {
1193 return true;
1194 }
1195 }
1196 return false;
1197 }
1198
Louis Chang7d0037c2018-08-13 12:42:06 +08001199 /**
1200 * @see #mRemoved
1201 */
1202 boolean isRemoved() {
1203 return mRemoved;
1204 }
1205
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001206 /**
1207 * @see #mRemoving
1208 */
1209 boolean isRemoving() {
1210 return mRemoving;
1211 }
1212
Bryce Leef19cbe22018-02-02 15:09:21 -08001213 void remove() {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001214 mRemoving = true;
Bryce Leef19cbe22018-02-02 15:09:21 -08001215 final boolean destroyContentOnRemoval = shouldDestroyContentOnRemove();
Riddle Hsu402b4402018-11-06 17:23:15 +08001216 ActivityStack lastReparentedStack = null;
1217 mPreferredTopFocusableStack = null;
Louis Chang7d0037c2018-08-13 12:42:06 +08001218
1219 // Stacks could be reparented from the removed display to other display. While
1220 // reparenting the last stack of the removed display, the remove display is ready to be
1221 // released (no more ActivityStack). But, we cannot release it at that moment or the
Riddle Hsu5947c362019-09-23 18:52:36 +08001222 // related WindowContainer will also be removed. So, we set display as removed after
1223 // reparenting stack finished.
Wale Ogunwaled32da472018-11-16 07:19:28 -08001224 final ActivityDisplay toDisplay = mRootActivityContainer.getDefaultDisplay();
1225 mRootActivityContainer.mStackSupervisor.beginDeferResume();
Riddle Hsu402b4402018-11-06 17:23:15 +08001226 try {
1227 int numStacks = mStacks.size();
1228 // Keep the order from bottom to top.
1229 for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
1230 final ActivityStack stack = mStacks.get(stackNdx);
1231 // Always finish non-standard type stacks.
1232 if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) {
Andrii Kuliande93eff2019-07-12 12:21:27 -07001233 stack.finishAllActivitiesImmediately();
Riddle Hsu402b4402018-11-06 17:23:15 +08001234 } else {
1235 // If default display is in split-window mode, set windowing mode of the stack
1236 // to split-screen secondary. Otherwise, set the windowing mode to undefined by
1237 // default to let stack inherited the windowing mode from the new display.
1238 final int windowingMode = toDisplay.hasSplitScreenPrimaryStack()
1239 ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
1240 : WINDOWING_MODE_UNDEFINED;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001241 stack.reparent(toDisplay.mDisplayContent, true /* onTop */);
Riddle Hsu402b4402018-11-06 17:23:15 +08001242 stack.setWindowingMode(windowingMode);
1243 lastReparentedStack = stack;
1244 }
1245 // Stacks may be removed from this display. Ensure each stack will be processed and
1246 // the loop will end.
1247 stackNdx -= numStacks - mStacks.size();
1248 numStacks = mStacks.size();
Bryce Leef19cbe22018-02-02 15:09:21 -08001249 }
Riddle Hsu402b4402018-11-06 17:23:15 +08001250 } finally {
Wale Ogunwaled32da472018-11-16 07:19:28 -08001251 mRootActivityContainer.mStackSupervisor.endDeferResume();
Bryce Leef19cbe22018-02-02 15:09:21 -08001252 }
Louis Chang7d0037c2018-08-13 12:42:06 +08001253 mRemoved = true;
Bryce Leef19cbe22018-02-02 15:09:21 -08001254
Riddle Hsu402b4402018-11-06 17:23:15 +08001255 // Only update focus/visibility for the last one because there may be many stacks are
1256 // reparented and the intermediate states are unnecessary.
1257 if (lastReparentedStack != null) {
1258 lastReparentedStack.postReparent();
1259 }
Louis Chang7d0037c2018-08-13 12:42:06 +08001260 releaseSelfIfNeeded();
wilsonshih0299c8a2018-08-24 15:52:57 +08001261
Riddle Hsuf53da812018-08-15 22:00:27 +08001262 if (!mAllSleepTokens.isEmpty()) {
Wale Ogunwaled32da472018-11-16 07:19:28 -08001263 mRootActivityContainer.mSleepTokens.removeAll(mAllSleepTokens);
Riddle Hsuf53da812018-08-15 22:00:27 +08001264 mAllSleepTokens.clear();
Wale Ogunwaled32da472018-11-16 07:19:28 -08001265 mService.updateSleepIfNeededLocked();
Riddle Hsuf53da812018-08-15 22:00:27 +08001266 }
Louis Chang7d0037c2018-08-13 12:42:06 +08001267 }
1268
1269 private void releaseSelfIfNeeded() {
Louis Changcc568712019-03-08 14:54:41 +08001270 if (!mRemoved || mDisplayContent == null) {
1271 return;
1272 }
1273
1274 final ActivityStack stack = mStacks.size() == 1 ? mStacks.get(0) : null;
1275 if (stack != null && stack.isActivityTypeHome() && stack.getAllTasks().isEmpty()) {
1276 // Release this display if an empty home stack is the only thing left.
1277 // Since it is the last stack, this display will be released along with the stack
1278 // removal.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001279 stack.removeIfPossible();
Louis Changcc568712019-03-08 14:54:41 +08001280 } else if (mStacks.isEmpty()) {
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001281 mDisplayContent.removeIfPossible();
1282 mDisplayContent = null;
Wale Ogunwaled32da472018-11-16 07:19:28 -08001283 mRootActivityContainer.removeChild(this);
1284 mRootActivityContainer.mStackSupervisor
1285 .getKeyguardController().onDisplayRemoved(mDisplayId);
Louis Chang7d0037c2018-08-13 12:42:06 +08001286 }
Bryce Leef19cbe22018-02-02 15:09:21 -08001287 }
1288
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001289 /** Update and get all UIDs that are present on the display and have access to it. */
1290 IntArray getPresentUIDs() {
1291 mDisplayAccessUIDs.clear();
1292 for (ActivityStack stack : mStacks) {
1293 stack.getPresentUIDs(mDisplayAccessUIDs);
1294 }
1295 return mDisplayAccessUIDs;
1296 }
1297
Louis Changbd48dca2018-08-29 17:44:34 +08001298 /**
Andrii Kulian15cfb422018-11-07 13:38:49 -08001299 * Checks if system decorations should be shown on this display.
1300 *
Louis Changbd48dca2018-08-29 17:44:34 +08001301 * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
1302 */
1303 boolean supportsSystemDecorations() {
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001304 return mDisplayContent.supportsSystemDecorations();
Louis Changbd48dca2018-08-29 17:44:34 +08001305 }
1306
Riddle Hsu402b4402018-11-06 17:23:15 +08001307 @VisibleForTesting
1308 boolean shouldDestroyContentOnRemove() {
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001309 return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT;
1310 }
1311
1312 boolean shouldSleep() {
1313 return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty())
Wale Ogunwaled32da472018-11-16 07:19:28 -08001314 && (mService.mRunningVoice == null);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001315 }
1316
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001317 void setFocusedApp(ActivityRecord r, boolean moveFocusNow) {
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001318 if (mDisplayContent == null) {
1319 return;
1320 }
Garfield Tane8d84ab2019-10-11 09:49:40 -07001321 final ActivityRecord newFocus;
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001322 final IBinder token = r.appToken;
1323 if (token == null) {
Adrian Roosb125e0b2019-10-02 14:55:14 +02001324 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT, "Clearing focused app, displayId=%d",
1325 mDisplayId);
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001326 newFocus = null;
1327 } else {
Garfield Tane8d84ab2019-10-11 09:49:40 -07001328 newFocus = mService.mWindowManager.mRoot.getActivityRecord(token);
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001329 if (newFocus == null) {
1330 Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token
1331 + ", displayId=" + mDisplayId);
1332 }
Adrian Roosb125e0b2019-10-02 14:55:14 +02001333 ProtoLog.v(WM_DEBUG_FOCUS_LIGHT,
1334 "Set focused app to: %s moveFocusNow=%b displayId=%d", newFocus,
1335 moveFocusNow, mDisplayId);
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001336 }
1337
1338 final boolean changed = mDisplayContent.setFocusedApp(newFocus);
1339 if (moveFocusNow && changed) {
1340 mService.mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
1341 true /*updateInputWindows*/);
1342 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001343 }
1344
Winson Chunge2d72172018-01-25 17:46:20 +00001345 /**
Winson Chung3e2980e2018-03-29 17:28:57 -07001346 * @return the stack currently above the {@param stack}. Can be null if the {@param stack} is
1347 * already top-most.
Winson Chunge2d72172018-01-25 17:46:20 +00001348 */
Winson Chung3e2980e2018-03-29 17:28:57 -07001349 ActivityStack getStackAbove(ActivityStack stack) {
1350 final int stackIndex = mStacks.indexOf(stack) + 1;
Winson Chunge2d72172018-01-25 17:46:20 +00001351 return (stackIndex < mStacks.size()) ? mStacks.get(stackIndex) : null;
1352 }
1353
1354 /**
Winson Chung3e2980e2018-03-29 17:28:57 -07001355 * Adjusts the {@param stack} behind the last visible stack in the display if necessary.
1356 * Generally used in conjunction with {@link #moveStackBehindStack}.
Winson Chunge2d72172018-01-25 17:46:20 +00001357 */
Winson Chung3e2980e2018-03-29 17:28:57 -07001358 void moveStackBehindBottomMostVisibleStack(ActivityStack stack) {
1359 if (stack.shouldBeVisible(null)) {
1360 // Skip if the stack is already visible
Winson Chunge2d72172018-01-25 17:46:20 +00001361 return;
1362 }
1363
Winson Chung3e2980e2018-03-29 17:28:57 -07001364 // Move the stack to the bottom to not affect the following visibility checks
1365 positionChildAtBottom(stack);
Winson Chunge2d72172018-01-25 17:46:20 +00001366
Winson Chung3e2980e2018-03-29 17:28:57 -07001367 // Find the next position where the stack should be placed
Winson Chunge2d72172018-01-25 17:46:20 +00001368 final int numStacks = mStacks.size();
1369 for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
Winson Chung3e2980e2018-03-29 17:28:57 -07001370 final ActivityStack s = mStacks.get(stackNdx);
1371 if (s == stack) {
Winson Chunge2d72172018-01-25 17:46:20 +00001372 continue;
1373 }
Winson Chung3e2980e2018-03-29 17:28:57 -07001374 final int winMode = s.getWindowingMode();
Winson Chunge2d72172018-01-25 17:46:20 +00001375 final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN ||
1376 winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
Winson Chung3e2980e2018-03-29 17:28:57 -07001377 if (s.shouldBeVisible(null) && isValidWindowingMode) {
1378 // Move the provided stack to behind this stack
1379 positionChildAt(stack, Math.max(0, stackNdx - 1));
Winson Chunge2d72172018-01-25 17:46:20 +00001380 break;
1381 }
1382 }
1383 }
1384
1385 /**
Winson Chung3e2980e2018-03-29 17:28:57 -07001386 * Moves the {@param stack} behind the given {@param behindStack} if possible. If
1387 * {@param behindStack} is not currently in the display, then then the stack is moved to the
1388 * back. Generally used in conjunction with {@link #moveStackBehindBottomMostVisibleStack}.
Winson Chunge2d72172018-01-25 17:46:20 +00001389 */
Winson Chung3e2980e2018-03-29 17:28:57 -07001390 void moveStackBehindStack(ActivityStack stack, ActivityStack behindStack) {
1391 if (behindStack == null || behindStack == stack) {
Winson Chunge2d72172018-01-25 17:46:20 +00001392 return;
1393 }
1394
Winson Chung123e07a2018-02-27 11:47:16 -08001395 // Note that positionChildAt will first remove the given stack before inserting into the
1396 // list, so we need to adjust the insertion index to account for the removed index
1397 // TODO: Remove this logic when WindowContainer.positionChildAt() is updated to adjust the
1398 // position internally
Winson Chung3e2980e2018-03-29 17:28:57 -07001399 final int stackIndex = mStacks.indexOf(stack);
Winson Chung123e07a2018-02-27 11:47:16 -08001400 final int behindStackIndex = mStacks.indexOf(behindStack);
Winson Chung3e2980e2018-03-29 17:28:57 -07001401 final int insertIndex = stackIndex <= behindStackIndex
Winson Chung123e07a2018-02-27 11:47:16 -08001402 ? behindStackIndex - 1 : behindStackIndex;
Winson Chung3e2980e2018-03-29 17:28:57 -07001403 positionChildAt(stack, Math.max(0, insertIndex));
Winson Chunge2d72172018-01-25 17:46:20 +00001404 }
1405
Louis Chang77ce34d2019-01-03 15:45:12 +08001406 void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
1407 boolean preserveWindows, boolean notifyClients) {
1408 for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
1409 final ActivityStack stack = getChildAt(stackNdx);
1410 stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
1411 notifyClients);
1412 }
1413 }
1414
Louis Changbd48dca2018-08-29 17:44:34 +08001415 void moveHomeStackToFront(String reason) {
1416 if (mHomeStack != null) {
1417 mHomeStack.moveToFront(reason);
1418 }
1419 }
1420
Riddle Hsu2b9a6d72019-04-24 23:55:11 +08001421 /**
1422 * Moves the focusable home activity to top. If there is no such activity, the home stack will
1423 * still move to top.
1424 */
1425 void moveHomeActivityToTop(String reason) {
Louis Changbd48dca2018-08-29 17:44:34 +08001426 final ActivityRecord top = getHomeActivity();
1427 if (top == null) {
Riddle Hsu2b9a6d72019-04-24 23:55:11 +08001428 moveHomeStackToFront(reason);
1429 return;
Louis Changbd48dca2018-08-29 17:44:34 +08001430 }
Louis Chang19443452018-10-09 12:10:21 +08001431 top.moveFocusableActivityToTop(reason);
Louis Changbd48dca2018-08-29 17:44:34 +08001432 }
1433
1434 @Nullable
1435 ActivityStack getHomeStack() {
1436 return mHomeStack;
1437 }
1438
1439 @Nullable
1440 ActivityRecord getHomeActivity() {
Wale Ogunwaled32da472018-11-16 07:19:28 -08001441 return getHomeActivityForUser(mRootActivityContainer.mCurrentUser);
Louis Changbd48dca2018-08-29 17:44:34 +08001442 }
1443
1444 @Nullable
1445 ActivityRecord getHomeActivityForUser(int userId) {
1446 if (mHomeStack == null) {
1447 return null;
1448 }
1449
1450 final ArrayList<TaskRecord> tasks = mHomeStack.getAllTasks();
1451 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
1452 final TaskRecord task = tasks.get(taskNdx);
1453 if (!task.isActivityTypeHome()) {
1454 continue;
1455 }
1456
Wale Ogunwale1a06f152019-10-11 11:26:30 +02001457 for (int activityNdx = task.getChildCount() - 1; activityNdx >= 0; --activityNdx) {
1458 final ActivityRecord r = task.getChildAt(activityNdx);
Louis Changbd48dca2018-08-29 17:44:34 +08001459 if (r.isActivityTypeHome()
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001460 && ((userId == UserHandle.USER_ALL) || (r.mUserId == userId))) {
Louis Changbd48dca2018-08-29 17:44:34 +08001461 return r;
1462 }
1463 }
1464 }
1465 return null;
1466 }
1467
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001468 boolean isSleeping() {
1469 return mSleeping;
1470 }
1471
1472 void setIsSleeping(boolean asleep) {
1473 mSleeping = asleep;
1474 }
1475
Winson Chung0f7ec962018-05-03 18:03:15 -07001476 /**
1477 * Adds a listener to be notified whenever the stack order in the display changes. Currently
1478 * only used by the {@link RecentsAnimation} to determine whether to interrupt and cancel the
1479 * current animation when the system state changes.
1480 */
1481 void registerStackOrderChangedListener(OnStackOrderChangedListener listener) {
1482 if (!mStackOrderChangedCallbacks.contains(listener)) {
1483 mStackOrderChangedCallbacks.add(listener);
1484 }
1485 }
1486
1487 /**
1488 * Removes a previously registered stack order change listener.
1489 */
1490 void unregisterStackOrderChangedListener(OnStackOrderChangedListener listener) {
1491 mStackOrderChangedCallbacks.remove(listener);
1492 }
1493
Winson Chung65d66d32018-12-13 17:48:39 -08001494 /**
1495 * Notifies of a stack order change
1496 * @param stack The stack which triggered the order change
1497 */
1498 private void onStackOrderChanged(ActivityStack stack) {
Winson Chung0f7ec962018-05-03 18:03:15 -07001499 for (int i = mStackOrderChangedCallbacks.size() - 1; i >= 0; i--) {
Winson Chung65d66d32018-12-13 17:48:39 -08001500 mStackOrderChangedCallbacks.get(i).onStackOrderChanged(stack);
Winson Chung0f7ec962018-05-03 18:03:15 -07001501 }
1502 }
1503
Chavi Weingarten3a748552018-05-14 17:32:42 +00001504 /**
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001505 * See {@link DisplayContent#deferUpdateImeTarget()}
Chavi Weingarten3a748552018-05-14 17:32:42 +00001506 */
1507 public void deferUpdateImeTarget() {
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001508 if (mDisplayContent != null) {
1509 mDisplayContent.deferUpdateImeTarget();
1510 }
Chavi Weingarten3a748552018-05-14 17:32:42 +00001511 }
1512
1513 /**
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001514 * See {@link DisplayContent#deferUpdateImeTarget()}
Chavi Weingarten3a748552018-05-14 17:32:42 +00001515 */
1516 public void continueUpdateImeTarget() {
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001517 if (mDisplayContent != null) {
1518 mDisplayContent.continueUpdateImeTarget();
1519 }
Chavi Weingarten3a748552018-05-14 17:32:42 +00001520 }
1521
Wale Ogunwale9e737db2018-12-17 15:42:37 -08001522 void setDisplayToSingleTaskInstance() {
1523 final int childCount = getChildCount();
1524 if (childCount > 1) {
1525 throw new IllegalArgumentException("Display already has multiple stacks. display="
1526 + this);
1527 }
1528 if (childCount > 0) {
1529 final ActivityStack stack = getChildAt(0);
1530 if (stack.getChildCount() > 1) {
1531 throw new IllegalArgumentException("Display stack already has multiple tasks."
1532 + " display=" + this + " stack=" + stack);
1533 }
1534 }
1535
1536 mSingleTaskInstance = true;
1537 }
1538
1539 /** Returns true if the display can only contain one task */
1540 boolean isSingleTaskInstance() {
1541 return mSingleTaskInstance;
1542 }
1543
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001544 @VisibleForTesting
1545 void removeAllTasks() {
1546 for (int i = getChildCount() - 1; i >= 0; --i) {
1547 final ActivityStack stack = getChildAt(i);
1548 final ArrayList<TaskRecord> tasks = stack.getAllTasks();
1549 for (int j = tasks.size() - 1; j >= 0; --j) {
Wale Ogunwale2322bed2019-10-10 17:24:19 +02001550 stack.removeChild(tasks.get(j), "removeAllTasks");
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001551 }
1552 }
1553 }
1554
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001555 public void dump(PrintWriter pw, String prefix) {
Wale Ogunwale9e737db2018-12-17 15:42:37 -08001556 pw.println(prefix + "displayId=" + mDisplayId + " stacks=" + mStacks.size()
1557 + (mSingleTaskInstance ? " mSingleTaskInstance" : ""));
Wale Ogunwale30e441d2017-11-09 08:28:45 -08001558 final String myPrefix = prefix + " ";
1559 if (mHomeStack != null) {
1560 pw.println(myPrefix + "mHomeStack=" + mHomeStack);
1561 }
1562 if (mRecentsStack != null) {
1563 pw.println(myPrefix + "mRecentsStack=" + mRecentsStack);
1564 }
1565 if (mPinnedStack != null) {
1566 pw.println(myPrefix + "mPinnedStack=" + mPinnedStack);
1567 }
1568 if (mSplitScreenPrimaryStack != null) {
1569 pw.println(myPrefix + "mSplitScreenPrimaryStack=" + mSplitScreenPrimaryStack);
1570 }
Riddle Hsu75016992018-09-20 20:37:14 +08001571 if (mPreferredTopFocusableStack != null) {
1572 pw.println(myPrefix + "mPreferredTopFocusableStack=" + mPreferredTopFocusableStack);
1573 }
Riddle Hsubbb63c22018-10-03 12:28:29 +08001574 if (mLastFocusedStack != null) {
1575 pw.println(myPrefix + "mLastFocusedStack=" + mLastFocusedStack);
1576 }
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001577 }
1578
Bryce Lee77a7dd62018-01-22 15:47:09 -08001579 public void dumpStacks(PrintWriter pw) {
1580 for (int i = mStacks.size() - 1; i >= 0; --i) {
1581 pw.print(mStacks.get(i).mStackId);
1582 if (i > 0) {
1583 pw.print(",");
1584 }
1585 }
1586 }
1587
Nataniel Borges023ecb52019-01-16 14:15:43 -08001588 public void writeToProto(ProtoOutputStream proto, long fieldId,
1589 @WindowTraceLogLevel int logLevel) {
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001590 final long token = proto.start(fieldId);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001591 super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001592 proto.write(ID, mDisplayId);
Wale Ogunwale9e737db2018-12-17 15:42:37 -08001593 proto.write(SINGLE_TASK_INSTANCE, mSingleTaskInstance);
Andrii Kulianab132ee2018-07-24 22:10:21 +08001594 final ActivityStack focusedStack = getFocusedStack();
1595 if (focusedStack != null) {
1596 proto.write(FOCUSED_STACK_ID, focusedStack.mStackId);
1597 final ActivityRecord focusedActivity = focusedStack.getDisplay().getResumedActivity();
1598 if (focusedActivity != null) {
1599 focusedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
1600 }
1601 } else {
1602 proto.write(FOCUSED_STACK_ID, INVALID_STACK_ID);
1603 }
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001604 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1605 final ActivityStack stack = mStacks.get(stackNdx);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001606 stack.writeToProto(proto, STACKS, logLevel);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001607 }
1608 proto.end(token);
1609 }
Winson Chung0f7ec962018-05-03 18:03:15 -07001610
1611 /**
1612 * Callback for when the order of the stacks in the display changes.
1613 */
1614 interface OnStackOrderChangedListener {
Winson Chung65d66d32018-12-13 17:48:39 -08001615 void onStackOrderChanged(ActivityStack stack);
Winson Chung0f7ec962018-05-03 18:03:15 -07001616 }
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001617}