blob: a33b454d51dca1f568ff8acc636e55101839f1d4 [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;
32import static android.view.Display.DEFAULT_DISPLAY;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070033import static android.view.Display.FLAG_PRIVATE;
34import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
Louis Chang7d0037c2018-08-13 12:42:06 +080035
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070036import static com.android.server.am.ActivityDisplayProto.CONFIGURATION_CONTAINER;
Andrii Kulianab132ee2018-07-24 22:10:21 +080037import static com.android.server.am.ActivityDisplayProto.FOCUSED_STACK_ID;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070038import static com.android.server.am.ActivityDisplayProto.ID;
Andrii Kulianab132ee2018-07-24 22:10:21 +080039import static com.android.server.am.ActivityDisplayProto.RESUMED_ACTIVITY;
Wale Ogunwale9e737db2018-12-17 15:42:37 -080040import static com.android.server.am.ActivityDisplayProto.SINGLE_TASK_INSTANCE;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070041import static com.android.server.am.ActivityDisplayProto.STACKS;
Wale Ogunwale59507092018-10-29 09:00:30 -070042import static com.android.server.wm.ActivityStack.ActivityState.RESUMED;
Andrii Kulian0c869cc2019-02-06 19:50:32 -080043import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
Wale Ogunwale59507092018-10-29 09:00:30 -070044import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS;
45import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK;
46import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES;
47import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS;
48import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STACK;
49import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
50import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
Wale Ogunwaled32da472018-11-16 07:19:28 -080051import static com.android.server.wm.RootActivityContainer.FindTaskResult;
52import static com.android.server.wm.RootActivityContainer.TAG_STATES;
Wale Ogunwale3a256e62018-12-06 14:41:18 -080053import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_FOCUS_LIGHT;
54import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
55import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070056
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -070057import android.annotation.Nullable;
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -070058import android.app.ActivityOptions;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070059import android.app.WindowConfiguration;
Evan Roskye747c3e2018-10-30 20:06:41 -070060import android.content.res.Configuration;
Bryce Leef3c6a472017-11-14 14:53:06 -080061import android.graphics.Point;
Wale Ogunwale3a256e62018-12-06 14:41:18 -080062import android.os.IBinder;
Louis Changbd48dca2018-08-29 17:44:34 +080063import android.os.UserHandle;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070064import android.util.IntArray;
65import android.util.Slog;
66import android.util.proto.ProtoOutputStream;
67import android.view.Display;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070068
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070069import com.android.internal.annotations.VisibleForTesting;
Wale Ogunwale59507092018-10-29 09:00:30 -070070import com.android.server.am.EventLogTags;
Wale Ogunwale9e4f3e02018-05-17 09:35:39 -070071
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -070072import java.io.PrintWriter;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070073import java.util.ArrayList;
74
75/**
76 * Exactly one of these classes per Display in the system. Capable of holding zero or more
77 * attached {@link ActivityStack}s.
78 */
Winson Chung59a47ded2018-01-25 17:46:06 +000079class ActivityDisplay extends ConfigurationContainer<ActivityStack>
80 implements WindowContainerListener {
Wale Ogunwale98875612018-10-12 07:53:02 -070081 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityDisplay" : TAG_ATM;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070082 private static final String TAG_STACK = TAG + POSTFIX_STACK;
83
84 static final int POSITION_TOP = Integer.MAX_VALUE;
85 static final int POSITION_BOTTOM = Integer.MIN_VALUE;
86
Bryce Leed9cce2c2017-12-04 16:16:27 -080087
88 /**
89 * Counter for next free stack ID to use for dynamic activity stacks. Unique across displays.
90 */
91 private static int sNextFreeStackId = 0;
92
Wale Ogunwaled32da472018-11-16 07:19:28 -080093 private ActivityTaskManagerService mService;
94 private RootActivityContainer mRootActivityContainer;
Wale Ogunwale3a256e62018-12-06 14:41:18 -080095 // TODO: Remove once unification is complete.
96 DisplayContent mDisplayContent;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070097 /** Actual Display this object tracks. */
98 int mDisplayId;
99 Display mDisplay;
100
Winson Chung0f7ec962018-05-03 18:03:15 -0700101 /**
102 * All of the stacks on this display. Order matters, topmost stack is in front of all other
103 * stacks, bottommost behind. Accessed directly by ActivityManager package classes. Any calls
104 * changing the list should also call {@link #onStackOrderChanged()}.
105 */
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700106 private final ArrayList<ActivityStack> mStacks = new ArrayList<>();
Winson Chung0f7ec962018-05-03 18:03:15 -0700107 private ArrayList<OnStackOrderChangedListener> mStackOrderChangedCallbacks = new ArrayList<>();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700108
109 /** Array of all UIDs that are present on the display. */
110 private IntArray mDisplayAccessUIDs = new IntArray();
111
112 /** All tokens used to put activities on this stack to sleep (including mOffToken) */
Wale Ogunwale6767eae2018-05-03 15:52:51 -0700113 final ArrayList<ActivityTaskManagerInternal.SleepToken> mAllSleepTokens = new ArrayList<>();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700114 /** The token acquired by ActivityStackSupervisor to put stacks on the display to sleep */
Wale Ogunwale6767eae2018-05-03 15:52:51 -0700115 ActivityTaskManagerInternal.SleepToken mOffToken;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700116
117 private boolean mSleeping;
118
Louis Chang7d0037c2018-08-13 12:42:06 +0800119 /**
120 * The display is removed from the system and we are just waiting for all activities on it to be
121 * finished before removing this object.
122 */
123 private boolean mRemoved;
124
Wale Ogunwale9e737db2018-12-17 15:42:37 -0800125 /** The display can only contain one task. */
126 private boolean mSingleTaskInstance;
127
Riddle Hsu75016992018-09-20 20:37:14 +0800128 /**
Riddle Hsu7b766fd2019-01-28 21:14:59 +0800129 * Non-null if the last size compatibility mode activity is using non-native screen
130 * configuration. The activity is not able to put in multi-window mode, so it exists only one
131 * per display.
132 */
133 private ActivityRecord mLastCompatModeActivity;
134
135 /**
Riddle Hsu75016992018-09-20 20:37:14 +0800136 * A focusable stack that is purposely to be positioned at the top. Although the stack may not
137 * have the topmost index, it is used as a preferred candidate to prevent being unable to resume
138 * target stack properly when there are other focusable always-on-top stacks.
139 */
140 private ActivityStack mPreferredTopFocusableStack;
141
Riddle Hsubbb63c22018-10-03 12:28:29 +0800142 /**
143 * If this is the same as {@link #getFocusedStack} then the activity on the top of the focused
144 * stack has been resumed. If stacks are changing position this will hold the old stack until
145 * the new stack becomes resumed after which it will be set to current focused stack.
146 */
147 private ActivityStack mLastFocusedStack;
148
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700149 // Cached reference to some special stacks we tend to get a lot so we don't need to loop
150 // through the list to find them.
151 private ActivityStack mHomeStack = null;
152 private ActivityStack mRecentsStack = null;
153 private ActivityStack mPinnedStack = null;
154 private ActivityStack mSplitScreenPrimaryStack = null;
155
Bryce Leef3c6a472017-11-14 14:53:06 -0800156 // Used in updating the display size
157 private Point mTmpDisplaySize = new Point();
158
Louis Changc85b1a32018-08-14 16:40:53 +0800159 private final FindTaskResult mTmpFindTaskResult = new FindTaskResult();
160
Wale Ogunwaled32da472018-11-16 07:19:28 -0800161 ActivityDisplay(RootActivityContainer root, Display display) {
162 mRootActivityContainer = root;
163 mService = root.mService;
Wale Ogunwale45477b52018-03-06 12:24:19 -0800164 mDisplayId = display.getDisplayId();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700165 mDisplay = display;
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800166 mDisplayContent = createDisplayContent();
Bryce Leef3c6a472017-11-14 14:53:06 -0800167 updateBounds();
168 }
169
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800170 protected DisplayContent createDisplayContent() {
171 return mService.mWindowManager.mRoot.createDisplayContent(mDisplay, this);
Winson Chung59a47ded2018-01-25 17:46:06 +0000172 }
173
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800174 private void updateBounds() {
Evan Roskye747c3e2018-10-30 20:06:41 -0700175 mDisplay.getRealSize(mTmpDisplaySize);
Bryce Leef3c6a472017-11-14 14:53:06 -0800176 setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700177 }
178
Riddle Hsuf53da812018-08-15 22:00:27 +0800179 void onDisplayChanged() {
180 // The window policy is responsible for stopping activities on the default display.
181 final int displayId = mDisplay.getDisplayId();
182 if (displayId != DEFAULT_DISPLAY) {
183 final int displayState = mDisplay.getState();
184 if (displayState == Display.STATE_OFF && mOffToken == null) {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800185 mOffToken = mService.acquireSleepToken("Display-off", displayId);
Riddle Hsuf53da812018-08-15 22:00:27 +0800186 } else if (displayState == Display.STATE_ON && mOffToken != null) {
187 mOffToken.release();
188 mOffToken = null;
189 }
190 }
191
192 updateBounds();
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800193 if (mDisplayContent != null) {
194 mDisplayContent.updateDisplayInfo();
195 mService.mWindowManager.requestTraversal();
196 }
Riddle Hsuf53da812018-08-15 22:00:27 +0800197 }
198
Riddle Hsua75a9452018-11-23 20:12:31 +0800199 @Override
200 public void onInitializeOverrideConfiguration(Configuration config) {
Evan Roskydfe3da72018-10-26 17:21:06 -0700201 getRequestedOverrideConfiguration().updateFrom(config);
Riddle Hsua75a9452018-11-23 20:12:31 +0800202 }
203
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700204 void addChild(ActivityStack stack, int position) {
205 if (position == POSITION_BOTTOM) {
206 position = 0;
207 } else if (position == POSITION_TOP) {
208 position = mStacks.size();
209 }
210 if (DEBUG_STACK) Slog.v(TAG_STACK, "addChild: attaching " + stack
211 + " to displayId=" + mDisplayId + " position=" + position);
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700212 addStackReferenceIfNeeded(stack);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700213 positionChildAt(stack, position);
Wale Ogunwaled32da472018-11-16 07:19:28 -0800214 mService.updateSleepIfNeededLocked();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700215 }
216
217 void removeChild(ActivityStack stack) {
218 if (DEBUG_STACK) Slog.v(TAG_STACK, "removeChild: detaching " + stack
219 + " from displayId=" + mDisplayId);
220 mStacks.remove(stack);
Riddle Hsu75016992018-09-20 20:37:14 +0800221 if (mPreferredTopFocusableStack == stack) {
222 mPreferredTopFocusableStack = null;
223 }
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700224 removeStackReferenceIfNeeded(stack);
Louis Chang7d0037c2018-08-13 12:42:06 +0800225 releaseSelfIfNeeded();
Wale Ogunwaled32da472018-11-16 07:19:28 -0800226 mService.updateSleepIfNeededLocked();
Winson Chung65d66d32018-12-13 17:48:39 -0800227 onStackOrderChanged(stack);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700228 }
229
Riddle Hsu57831b52018-07-27 00:31:48 +0800230 void positionChildAtTop(ActivityStack stack, boolean includingParents) {
Riddle Hsubbb63c22018-10-03 12:28:29 +0800231 positionChildAtTop(stack, includingParents, null /* updateLastFocusedStackReason */);
232 }
233
234 void positionChildAtTop(ActivityStack stack, boolean includingParents,
235 String updateLastFocusedStackReason) {
236 positionChildAt(stack, mStacks.size(), includingParents, updateLastFocusedStackReason);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700237 }
238
239 void positionChildAtBottom(ActivityStack stack) {
Riddle Hsubbb63c22018-10-03 12:28:29 +0800240 positionChildAtBottom(stack, null /* updateLastFocusedStackReason */);
241 }
242
243 void positionChildAtBottom(ActivityStack stack, String updateLastFocusedStackReason) {
244 positionChildAt(stack, 0, false /* includingParents */, updateLastFocusedStackReason);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700245 }
246
247 private void positionChildAt(ActivityStack stack, int position) {
Riddle Hsubbb63c22018-10-03 12:28:29 +0800248 positionChildAt(stack, position, false /* includingParents */,
249 null /* updateLastFocusedStackReason */);
Riddle Hsu57831b52018-07-27 00:31:48 +0800250 }
251
Riddle Hsubbb63c22018-10-03 12:28:29 +0800252 private void positionChildAt(ActivityStack stack, int position, boolean includingParents,
253 String updateLastFocusedStackReason) {
Winson Chung123e07a2018-02-27 11:47:16 -0800254 // TODO: Keep in sync with WindowContainer.positionChildAt(), once we change that to adjust
255 // the position internally, also update the logic here
Riddle Hsubbb63c22018-10-03 12:28:29 +0800256 final ActivityStack prevFocusedStack = updateLastFocusedStackReason != null
257 ? getFocusedStack() : null;
Riddle Hsu75016992018-09-20 20:37:14 +0800258 final boolean wasContained = mStacks.remove(stack);
Wale Ogunwale9e737db2018-12-17 15:42:37 -0800259 if (mSingleTaskInstance && getChildCount() > 0) {
260 throw new IllegalStateException(
261 "positionChildAt: Can only have one child on display=" + this);
262 }
Winson Chung59a47ded2018-01-25 17:46:06 +0000263 final int insertPosition = getTopInsertPosition(stack, position);
264 mStacks.add(insertPosition, stack);
Riddle Hsu75016992018-09-20 20:37:14 +0800265
266 // The insert position may be adjusted to non-top when there is always-on-top stack. Since
267 // the original position is preferred to be top, the stack should have higher priority when
268 // we are looking for top focusable stack. The condition {@code wasContained} restricts the
269 // preferred stack is set only when moving an existing stack to top instead of adding a new
270 // stack that may be too early (e.g. in the middle of launching or reparenting).
271 if (wasContained && position >= mStacks.size() - 1 && stack.isFocusableAndVisible()) {
272 mPreferredTopFocusableStack = stack;
273 } else if (mPreferredTopFocusableStack == stack) {
274 mPreferredTopFocusableStack = null;
275 }
276
Riddle Hsubbb63c22018-10-03 12:28:29 +0800277 if (updateLastFocusedStackReason != null) {
278 final ActivityStack currentFocusedStack = getFocusedStack();
279 if (currentFocusedStack != prevFocusedStack) {
280 mLastFocusedStack = prevFocusedStack;
Wale Ogunwaled32da472018-11-16 07:19:28 -0800281 EventLogTags.writeAmFocusedStack(mRootActivityContainer.mCurrentUser, mDisplayId,
Riddle Hsubbb63c22018-10-03 12:28:29 +0800282 currentFocusedStack == null ? -1 : currentFocusedStack.getStackId(),
283 mLastFocusedStack == null ? -1 : mLastFocusedStack.getStackId(),
284 updateLastFocusedStackReason);
285 }
286 }
287
Kazuki Takise048e2662018-06-27 17:05:11 +0900288 // Since positionChildAt() is called during the creation process of pinned stacks,
Yunfan Chen279f5582018-12-12 15:24:50 -0800289 // ActivityStack#getStack() can be null. In this special case,
Kazuki Takise048e2662018-06-27 17:05:11 +0900290 // since DisplayContest#positionStackAt() is called in TaskStack#onConfigurationChanged(),
291 // we don't have to call WindowContainerController#positionChildAt() here.
Yunfan Chen279f5582018-12-12 15:24:50 -0800292 if (stack.getTaskStack() != null && mDisplayContent != null) {
Wale Ogunwale3a256e62018-12-06 14:41:18 -0800293 mDisplayContent.positionStackAt(insertPosition,
Yunfan Chen279f5582018-12-12 15:24:50 -0800294 stack.getTaskStack(), includingParents);
Kazuki Takise048e2662018-06-27 17:05:11 +0900295 }
Evan Roskyc5abbd82018-10-05 16:02:19 -0700296 if (!wasContained) {
297 stack.setParent(this);
298 }
Winson Chung65d66d32018-12-13 17:48:39 -0800299 onStackOrderChanged(stack);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700300 }
301
302 private int getTopInsertPosition(ActivityStack stack, int candidatePosition) {
303 int position = mStacks.size();
Kazuki Takise148d00a2018-05-31 15:32:19 +0900304 if (stack.inPinnedWindowingMode()) {
305 // Stack in pinned windowing mode is z-ordered on-top of all other stacks so okay to
306 // just return the candidate position.
307 return Math.min(position, candidatePosition);
308 }
309 while (position > 0) {
310 final ActivityStack targetStack = mStacks.get(position - 1);
311 if (!targetStack.isAlwaysOnTop()) {
312 // We reached a stack that isn't always-on-top.
313 break;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700314 }
Kazuki Takise148d00a2018-05-31 15:32:19 +0900315 if (stack.isAlwaysOnTop() && !targetStack.inPinnedWindowingMode()) {
316 // Always on-top non-pinned windowing mode stacks can go anywhere below pinned stack.
317 break;
318 }
319 position--;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700320 }
321 return Math.min(position, candidatePosition);
322 }
323
324 <T extends ActivityStack> T getStack(int stackId) {
325 for (int i = mStacks.size() - 1; i >= 0; --i) {
326 final ActivityStack stack = mStacks.get(i);
327 if (stack.mStackId == stackId) {
328 return (T) stack;
329 }
330 }
331 return null;
332 }
333
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700334 /**
335 * @return the topmost stack on the display that is compatible with the input windowing mode and
336 * activity type. {@code null} means no compatible stack on the display.
337 * @see ConfigurationContainer#isCompatible(int, int)
338 */
339 <T extends ActivityStack> T getStack(int windowingMode, int activityType) {
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700340 if (activityType == ACTIVITY_TYPE_HOME) {
341 return (T) mHomeStack;
342 } else if (activityType == ACTIVITY_TYPE_RECENTS) {
343 return (T) mRecentsStack;
344 }
345 if (windowingMode == WINDOWING_MODE_PINNED) {
346 return (T) mPinnedStack;
347 } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
348 return (T) mSplitScreenPrimaryStack;
349 }
Wale Ogunwaleab5de372017-10-18 06:46:31 -0700350
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700351 for (int i = mStacks.size() - 1; i >= 0; --i) {
352 final ActivityStack stack = mStacks.get(i);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700353 if (stack.isCompatible(windowingMode, activityType)) {
354 return (T) stack;
355 }
356 }
357 return null;
358 }
359
Wale Ogunwaleab5de372017-10-18 06:46:31 -0700360 private boolean alwaysCreateStack(int windowingMode, int activityType) {
361 // Always create a stack for fullscreen, freeform, and split-screen-secondary windowing
362 // modes so that we can manage visual ordering and return types correctly.
363 return activityType == ACTIVITY_TYPE_STANDARD
364 && (windowingMode == WINDOWING_MODE_FULLSCREEN
365 || windowingMode == WINDOWING_MODE_FREEFORM
366 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
367 }
368
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700369 /**
Wale Ogunwaleab5de372017-10-18 06:46:31 -0700370 * Returns an existing stack compatible with the windowing mode and activity type or creates one
371 * if a compatible stack doesn't exist.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700372 * @see #getStack(int, int)
373 * @see #createStack(int, int, boolean)
374 */
375 <T extends ActivityStack> T getOrCreateStack(int windowingMode, int activityType,
376 boolean onTop) {
Wale Ogunwaleab5de372017-10-18 06:46:31 -0700377 if (!alwaysCreateStack(windowingMode, activityType)) {
378 T stack = getStack(windowingMode, activityType);
379 if (stack != null) {
380 return stack;
381 }
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700382 }
383 return createStack(windowingMode, activityType, onTop);
384 }
385
Wale Ogunwale68278562017-09-23 17:13:55 -0700386 /**
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700387 * Returns an existing stack compatible with the input params or creates one
388 * if a compatible stack doesn't exist.
389 * @see #getOrCreateStack(int, int, boolean)
390 */
391 <T extends ActivityStack> T getOrCreateStack(@Nullable ActivityRecord r,
392 @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, int activityType,
393 boolean onTop) {
Evan Rosky10475742018-09-05 19:02:48 -0700394 // First preference is the windowing mode in the activity options if set.
395 int windowingMode = (options != null)
396 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
397 // Validate that our desired windowingMode will work under the current conditions.
398 // UNDEFINED windowing mode is a valid result and means that the new stack will inherit
399 // it's display's windowing mode.
400 windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType);
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700401 return getOrCreateStack(windowingMode, activityType, onTop);
402 }
403
Louis Changf2835df2018-10-17 15:14:45 +0800404 @VisibleForTesting
405 int getNextStackId() {
Bryce Leed9cce2c2017-12-04 16:16:27 -0800406 return sNextFreeStackId++;
407 }
408
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700409 /**
Wale Ogunwale68278562017-09-23 17:13:55 -0700410 * Creates a stack matching the input windowing mode and activity type on this display.
411 * @param windowingMode The windowing mode the stack should be created in. If
412 * {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will
Evan Rosky10475742018-09-05 19:02:48 -0700413 * inherit it's parent's windowing mode.
Wale Ogunwale68278562017-09-23 17:13:55 -0700414 * @param activityType The activityType the stack should be created in. If
415 * {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will
416 * be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
417 * @param onTop If true the stack will be created at the top of the display, else at the bottom.
418 * @return The newly created stack.
419 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700420 <T extends ActivityStack> T createStack(int windowingMode, int activityType, boolean onTop) {
421
Wale Ogunwale9e737db2018-12-17 15:42:37 -0800422 if (mSingleTaskInstance && getChildCount() > 0) {
423 // Create stack on default display instead since this display can only contain 1 stack.
424 // TODO: Kinda a hack, but better that having the decision at each call point. Hoping
425 // this goes away once ActivityView is no longer using virtual displays.
426 return mRootActivityContainer.getDefaultDisplay().createStack(
427 windowingMode, activityType, onTop);
428 }
429
Wale Ogunwale68278562017-09-23 17:13:55 -0700430 if (activityType == ACTIVITY_TYPE_UNDEFINED) {
431 // Can't have an undefined stack type yet...so re-map to standard. Anyone that wants
432 // anything else should be passing it in anyways...
433 activityType = ACTIVITY_TYPE_STANDARD;
434 }
435
436 if (activityType != ACTIVITY_TYPE_STANDARD) {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700437 // For now there can be only one stack of a particular non-standard activity type on a
438 // display. So, get that ignoring whatever windowing mode it is currently in.
439 T stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
440 if (stack != null) {
441 throw new IllegalArgumentException("Stack=" + stack + " of activityType="
442 + activityType + " already on display=" + this + ". Can't have multiple.");
443 }
444 }
445
Wale Ogunwaled32da472018-11-16 07:19:28 -0800446 if (!isWindowingModeSupported(windowingMode, mService.mSupportsMultiWindow,
447 mService.mSupportsSplitScreenMultiWindow,
448 mService.mSupportsFreeformWindowManagement, mService.mSupportsPictureInPicture,
449 activityType)) {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700450 throw new IllegalArgumentException("Can't create stack for unsupported windowingMode="
451 + windowingMode);
452 }
453
Bryce Leed9cce2c2017-12-04 16:16:27 -0800454 final int stackId = getNextStackId();
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700455 return createStackUnchecked(windowingMode, activityType, stackId, onTop);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700456 }
457
458 @VisibleForTesting
459 <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
460 int stackId, boolean onTop) {
Yunfan Chen279f5582018-12-12 15:24:50 -0800461 if (windowingMode == WINDOWING_MODE_PINNED && activityType != ACTIVITY_TYPE_STANDARD) {
462 throw new IllegalArgumentException("Stack with windowing mode cannot with non standard "
463 + "activity type.");
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700464 }
Wale Ogunwaled32da472018-11-16 07:19:28 -0800465 return (T) new ActivityStack(this, stackId,
Yunfan Chen279f5582018-12-12 15:24:50 -0800466 mRootActivityContainer.mStackSupervisor, windowingMode, activityType, onTop);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700467 }
468
Riddle Hsu75016992018-09-20 20:37:14 +0800469 /**
470 * Get the preferred focusable stack in priority. If the preferred stack does not exist, find a
471 * focusable and visible stack from the top of stacks in this display.
472 */
Andrii Kulian52d255c2018-07-13 11:32:19 -0700473 ActivityStack getFocusedStack() {
Riddle Hsu75016992018-09-20 20:37:14 +0800474 if (mPreferredTopFocusableStack != null) {
475 return mPreferredTopFocusableStack;
476 }
477
Andrii Kulian52d255c2018-07-13 11:32:19 -0700478 for (int i = mStacks.size() - 1; i >= 0; --i) {
479 final ActivityStack stack = mStacks.get(i);
Riddle Hsu75016992018-09-20 20:37:14 +0800480 if (stack.isFocusableAndVisible()) {
Andrii Kulian52d255c2018-07-13 11:32:19 -0700481 return stack;
482 }
483 }
484
485 return null;
486 }
487
Andrii Kulianab132ee2018-07-24 22:10:21 +0800488 ActivityStack getNextFocusableStack() {
489 return getNextFocusableStack(null /* currentFocus */, false /* ignoreCurrent */);
490 }
491
492 ActivityStack getNextFocusableStack(ActivityStack currentFocus, boolean ignoreCurrent) {
493 final int currentWindowingMode = currentFocus != null
494 ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED;
495
496 ActivityStack candidate = null;
497 for (int i = mStacks.size() - 1; i >= 0; --i) {
498 final ActivityStack stack = mStacks.get(i);
499 if (ignoreCurrent && stack == currentFocus) {
500 continue;
501 }
Riddle Hsu75016992018-09-20 20:37:14 +0800502 if (!stack.isFocusableAndVisible()) {
Andrii Kulianab132ee2018-07-24 22:10:21 +0800503 continue;
504 }
505
506 if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
507 && candidate == null && stack.inSplitScreenPrimaryWindowingMode()) {
508 // If the currently focused stack is in split-screen secondary we save off the
509 // top primary split-screen stack as a candidate for focus because we might
510 // prefer focus to move to an other stack to avoid primary split-screen stack
511 // overlapping with a fullscreen stack when a fullscreen stack is higher in z
512 // than the next split-screen stack. Assistant stack, I am looking at you...
513 // We only move the focus to the primary-split screen stack if there isn't a
514 // better alternative.
515 candidate = stack;
516 continue;
517 }
518 if (candidate != null && stack.inSplitScreenSecondaryWindowingMode()) {
519 // Use the candidate stack since we are now at the secondary split-screen.
520 return candidate;
521 }
522 return stack;
523 }
524 return candidate;
525 }
526
Andrii Kulian52d255c2018-07-13 11:32:19 -0700527 ActivityRecord getResumedActivity() {
528 final ActivityStack focusedStack = getFocusedStack();
529 if (focusedStack == null) {
530 return null;
531 }
532 // TODO(b/111541062): Move this into ActivityStack#getResumedActivity()
533 // Check if the focused stack has the resumed activity
534 ActivityRecord resumedActivity = focusedStack.getResumedActivity();
535 if (resumedActivity == null || resumedActivity.app == null) {
536 // If there is no registered resumed activity in the stack or it is not running -
537 // try to use previously resumed one.
538 resumedActivity = focusedStack.mPausingActivity;
539 if (resumedActivity == null || resumedActivity.app == null) {
540 // If previously resumed activity doesn't work either - find the topmost running
541 // activity that can be focused.
542 resumedActivity = focusedStack.topRunningActivityLocked(true /* focusableOnly */);
543 }
544 }
545 return resumedActivity;
546 }
547
Riddle Hsubbb63c22018-10-03 12:28:29 +0800548 ActivityStack getLastFocusedStack() {
549 return mLastFocusedStack;
550 }
551
552 boolean allResumedActivitiesComplete() {
553 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
554 final ActivityRecord r = mStacks.get(stackNdx).getResumedActivity();
555 if (r != null && !r.isState(RESUMED)) {
556 return false;
557 }
558 }
559 final ActivityStack currentFocusedStack = getFocusedStack();
560 if (DEBUG_STACK) {
561 Slog.d(TAG_STACK, "allResumedActivitiesComplete: mLastFocusedStack changing from="
562 + mLastFocusedStack + " to=" + currentFocusedStack);
563 }
564 mLastFocusedStack = currentFocusedStack;
565 return true;
566 }
567
Wale Ogunwale68278562017-09-23 17:13:55 -0700568 /**
Andrii Kulian6b321512019-01-23 06:37:00 +0000569 * Pause all activities in either all of the stacks or just the back stacks. This is done before
570 * resuming a new activity and to make sure that previously active activities are
571 * paused in stacks that are no longer visible or in pinned windowing mode. This does not
572 * pause activities in visible stacks, so if an activity is launched within the same stack/task,
573 * then we should explicitly pause that stack's top activity.
Andrii Kulianab132ee2018-07-24 22:10:21 +0800574 * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
575 * @param resuming The resuming activity.
576 * @param dontWait The resuming activity isn't going to wait for all activities to be paused
577 * before resuming.
Andrii Kulian6b321512019-01-23 06:37:00 +0000578 * @return {@code true} if any activity was paused as a result of this call.
Andrii Kulianab132ee2018-07-24 22:10:21 +0800579 */
580 boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
581 boolean someActivityPaused = false;
582 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
583 final ActivityStack stack = mStacks.get(stackNdx);
Andrii Kulian6b321512019-01-23 06:37:00 +0000584 final ActivityRecord resumedActivity = stack.getResumedActivity();
585 if (resumedActivity != null
Andrii Kulian0c869cc2019-02-06 19:50:32 -0800586 && (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE
587 || !stack.isFocusable())) {
Andrii Kulianab132ee2018-07-24 22:10:21 +0800588 if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
Andrii Kulian6b321512019-01-23 06:37:00 +0000589 " mResumedActivity=" + resumedActivity);
Andrii Kulianab132ee2018-07-24 22:10:21 +0800590 someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
591 dontWait);
592 }
593 }
594 return someActivityPaused;
595 }
596
597 /**
Louis Changc85b1a32018-08-14 16:40:53 +0800598 * Find task for putting the Activity in.
599 */
600 void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplay,
601 FindTaskResult result) {
602 mTmpFindTaskResult.clear();
603 for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
604 final ActivityStack stack = getChildAt(stackNdx);
605 if (!r.hasCompatibleActivityType(stack)) {
606 if (DEBUG_TASKS) {
607 Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) " + stack);
608 }
609 continue;
610 }
611
612 stack.findTaskLocked(r, mTmpFindTaskResult);
613 // It is possible to have tasks in multiple stacks with the same root affinity, so
614 // we should keep looking after finding an affinity match to see if there is a
615 // better match in another stack. Also, task affinity isn't a good enough reason
616 // to target a display which isn't the source of the intent, so skip any affinity
617 // matches not on the specified display.
618 if (mTmpFindTaskResult.mRecord != null) {
619 if (mTmpFindTaskResult.mIdealMatch) {
620 result.setTo(mTmpFindTaskResult);
621 return;
622 } else if (isPreferredDisplay) {
623 // Note: since the traversing through the stacks is top down, the floating
624 // tasks should always have lower priority than any affinity-matching tasks
625 // in the fullscreen stacks
626 result.setTo(mTmpFindTaskResult);
627 }
628 }
629 }
630 }
631
632 /**
Wale Ogunwale68278562017-09-23 17:13:55 -0700633 * Removes stacks in the input windowing modes from the system if they are of activity type
634 * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
635 */
636 void removeStacksInWindowingModes(int... windowingModes) {
637 if (windowingModes == null || windowingModes.length == 0) {
638 return;
639 }
640
Louis Changf787e532019-01-15 12:46:49 +0800641 // Collect the stacks that are necessary to be removed instead of performing the removal
642 // by looping mStacks, so that we don't miss any stacks after the stack size changed or
643 // stacks reordered.
644 final ArrayList<ActivityStack> stacks = new ArrayList<>();
Wale Ogunwale68278562017-09-23 17:13:55 -0700645 for (int j = windowingModes.length - 1 ; j >= 0; --j) {
646 final int windowingMode = windowingModes[j];
647 for (int i = mStacks.size() - 1; i >= 0; --i) {
648 final ActivityStack stack = mStacks.get(i);
649 if (!stack.isActivityTypeStandardOrUndefined()) {
650 continue;
651 }
652 if (stack.getWindowingMode() != windowingMode) {
653 continue;
654 }
Louis Changf787e532019-01-15 12:46:49 +0800655 stacks.add(stack);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700656 }
657 }
Louis Changf787e532019-01-15 12:46:49 +0800658
659 for (int i = stacks.size() - 1; i >= 0; --i) {
660 mRootActivityContainer.mStackSupervisor.removeStack(stacks.get(i));
661 }
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700662 }
663
Wale Ogunwale68278562017-09-23 17:13:55 -0700664 void removeStacksWithActivityTypes(int... activityTypes) {
665 if (activityTypes == null || activityTypes.length == 0) {
666 return;
667 }
668
Louis Changf787e532019-01-15 12:46:49 +0800669 // Collect the stacks that are necessary to be removed instead of performing the removal
670 // by looping mStacks, so that we don't miss any stacks after the stack size changed or
671 // stacks reordered.
672 final ArrayList<ActivityStack> stacks = new ArrayList<>();
Wale Ogunwale68278562017-09-23 17:13:55 -0700673 for (int j = activityTypes.length - 1 ; j >= 0; --j) {
674 final int activityType = activityTypes[j];
675 for (int i = mStacks.size() - 1; i >= 0; --i) {
676 final ActivityStack stack = mStacks.get(i);
677 if (stack.getActivityType() == activityType) {
Louis Changf787e532019-01-15 12:46:49 +0800678 stacks.add(stack);
Wale Ogunwale68278562017-09-23 17:13:55 -0700679 }
680 }
681 }
Louis Changf787e532019-01-15 12:46:49 +0800682
683 for (int i = stacks.size() - 1; i >= 0; --i) {
684 mRootActivityContainer.mStackSupervisor.removeStack(stacks.get(i));
685 }
Wale Ogunwale68278562017-09-23 17:13:55 -0700686 }
687
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700688 void onStackWindowingModeChanged(ActivityStack stack) {
689 removeStackReferenceIfNeeded(stack);
690 addStackReferenceIfNeeded(stack);
691 }
692
693 private void addStackReferenceIfNeeded(ActivityStack stack) {
694 final int activityType = stack.getActivityType();
695 final int windowingMode = stack.getWindowingMode();
696
697 if (activityType == ACTIVITY_TYPE_HOME) {
698 if (mHomeStack != null && mHomeStack != stack) {
Louis Chang7d0037c2018-08-13 12:42:06 +0800699 throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700700 + mHomeStack + " already exist on display=" + this + " stack=" + stack);
701 }
Louis Chang7d0037c2018-08-13 12:42:06 +0800702 mHomeStack = stack;
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700703 } else if (activityType == ACTIVITY_TYPE_RECENTS) {
704 if (mRecentsStack != null && mRecentsStack != stack) {
705 throw new IllegalArgumentException("addStackReferenceIfNeeded: recents stack="
706 + mRecentsStack + " already exist on display=" + this + " stack=" + stack);
707 }
708 mRecentsStack = stack;
709 }
710 if (windowingMode == WINDOWING_MODE_PINNED) {
711 if (mPinnedStack != null && mPinnedStack != stack) {
712 throw new IllegalArgumentException("addStackReferenceIfNeeded: pinned stack="
713 + mPinnedStack + " already exist on display=" + this
714 + " stack=" + stack);
715 }
716 mPinnedStack = stack;
717 } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
718 if (mSplitScreenPrimaryStack != null && mSplitScreenPrimaryStack != stack) {
719 throw new IllegalArgumentException("addStackReferenceIfNeeded:"
720 + " split-screen-primary" + " stack=" + mSplitScreenPrimaryStack
721 + " already exist on display=" + this + " stack=" + stack);
722 }
723 mSplitScreenPrimaryStack = stack;
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800724 onSplitScreenModeActivated();
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700725 }
726 }
727
728 private void removeStackReferenceIfNeeded(ActivityStack stack) {
729 if (stack == mHomeStack) {
730 mHomeStack = null;
731 } else if (stack == mRecentsStack) {
732 mRecentsStack = null;
733 } else if (stack == mPinnedStack) {
734 mPinnedStack = null;
735 } else if (stack == mSplitScreenPrimaryStack) {
736 mSplitScreenPrimaryStack = null;
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800737 // Inform the reset of the system that split-screen mode was dismissed so things like
738 // resizing all the other stacks can take place.
739 onSplitScreenModeDismissed();
740 }
741 }
742
743 private void onSplitScreenModeDismissed() {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800744 mRootActivityContainer.mWindowManager.deferSurfaceLayout();
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800745 try {
746 // Adjust the windowing mode of any stack in secondary split-screen to fullscreen.
747 for (int i = mStacks.size() - 1; i >= 0; --i) {
748 final ActivityStack otherStack = mStacks.get(i);
749 if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
750 continue;
751 }
Evan Rosky10475742018-09-05 19:02:48 -0700752 otherStack.setWindowingMode(WINDOWING_MODE_UNDEFINED, false /* animate */,
Andrii Kulian9da138a2018-04-24 17:12:44 -0700753 false /* showRecents */, false /* enteringSplitScreenMode */,
Evan Roskyc5abbd82018-10-05 16:02:19 -0700754 true /* deferEnsuringVisibility */, false /* creating */);
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800755 }
756 } finally {
Wale Ogunwale1dbc5c82017-12-08 08:12:20 -0800757 final ActivityStack topFullscreenStack =
Wale Ogunwalef3257852018-01-24 08:52:28 -0800758 getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN);
Wale Ogunwale1dbc5c82017-12-08 08:12:20 -0800759 if (topFullscreenStack != null && mHomeStack != null && !isTopStack(mHomeStack)) {
Wale Ogunwaleeb76b762017-11-17 10:08:04 -0800760 // Whenever split-screen is dismissed we want the home stack directly behind the
Wale Ogunwale1dbc5c82017-12-08 08:12:20 -0800761 // current top fullscreen stack so it shows up when the top stack is finished.
Wale Ogunwaleeb76b762017-11-17 10:08:04 -0800762 // TODO: Would be better to use ActivityDisplay.positionChildAt() for this, however
763 // ActivityDisplay doesn't have a direct controller to WM side yet. We can switch
764 // once we have that.
765 mHomeStack.moveToFront("onSplitScreenModeDismissed");
Wale Ogunwale1dbc5c82017-12-08 08:12:20 -0800766 topFullscreenStack.moveToFront("onSplitScreenModeDismissed");
Wale Ogunwaleeb76b762017-11-17 10:08:04 -0800767 }
Wale Ogunwaled32da472018-11-16 07:19:28 -0800768 mRootActivityContainer.mWindowManager.continueSurfaceLayout();
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800769 }
770 }
771
772 private void onSplitScreenModeActivated() {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800773 mRootActivityContainer.mWindowManager.deferSurfaceLayout();
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800774 try {
775 // Adjust the windowing mode of any affected by split-screen to split-screen secondary.
776 for (int i = mStacks.size() - 1; i >= 0; --i) {
777 final ActivityStack otherStack = mStacks.get(i);
778 if (otherStack == mSplitScreenPrimaryStack
779 || !otherStack.affectedBySplitScreenResize()) {
780 continue;
781 }
Wale Ogunwaledf262f52017-12-07 18:17:12 -0800782 otherStack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
783 false /* animate */, false /* showRecents */,
Evan Roskyc5abbd82018-10-05 16:02:19 -0700784 true /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */,
785 false /* creating */);
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800786 }
787 } finally {
Wale Ogunwaled32da472018-11-16 07:19:28 -0800788 mRootActivityContainer.mWindowManager.continueSurfaceLayout();
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700789 }
790 }
791
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700792 /**
793 * Returns true if the {@param windowingMode} is supported based on other parameters passed in.
794 * @param windowingMode The windowing mode we are checking support for.
795 * @param supportsMultiWindow If we should consider support for multi-window mode in general.
796 * @param supportsSplitScreen If we should consider support for split-screen multi-window.
797 * @param supportsFreeform If we should consider support for freeform multi-window.
798 * @param supportsPip If we should consider support for picture-in-picture mutli-window.
799 * @param activityType The activity type under consideration.
800 * @return true if the windowing mode is supported.
801 */
802 private boolean isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow,
803 boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip,
804 int activityType) {
805
806 if (windowingMode == WINDOWING_MODE_UNDEFINED
807 || windowingMode == WINDOWING_MODE_FULLSCREEN) {
808 return true;
809 }
810 if (!supportsMultiWindow) {
811 return false;
812 }
813
Evan Rosky10475742018-09-05 19:02:48 -0700814 final int displayWindowingMode = getWindowingMode();
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700815 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
816 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
Wale Ogunwale2b07da82017-11-08 14:52:40 -0800817 return supportsSplitScreen
Evan Rosky10475742018-09-05 19:02:48 -0700818 && WindowConfiguration.supportSplitScreenWindowingMode(activityType)
819 // Freeform windows and split-screen windows don't mix well, so prevent
820 // split windowing modes on freeform displays.
821 && displayWindowingMode != WINDOWING_MODE_FREEFORM;
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700822 }
823
824 if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) {
825 return false;
826 }
827
828 if (!supportsPip && windowingMode == WINDOWING_MODE_PINNED) {
829 return false;
830 }
831 return true;
832 }
833
Evan Rosky10475742018-09-05 19:02:48 -0700834 /**
835 * Resolves the windowing mode that an {@link ActivityRecord} would be in if started on this
836 * display with the provided parameters.
837 *
838 * @param r The ActivityRecord in question.
839 * @param options Options to start with.
840 * @param task The task within-which the activity would start.
841 * @param activityType The type of activity to start.
842 * @return The resolved (not UNDEFINED) windowing-mode that the activity would be in.
843 */
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700844 int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
845 @Nullable TaskRecord task, int activityType) {
846
847 // First preference if the windowing mode in the activity options if set.
848 int windowingMode = (options != null)
849 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
850
851 // If windowing mode is unset, then next preference is the candidate task, then the
852 // activity record.
853 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
854 if (task != null) {
855 windowingMode = task.getWindowingMode();
856 }
857 if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) {
858 windowingMode = r.getWindowingMode();
859 }
860 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
861 // Use the display's windowing mode.
862 windowingMode = getWindowingMode();
863 }
864 }
Evan Rosky10475742018-09-05 19:02:48 -0700865 windowingMode = validateWindowingMode(windowingMode, r, task, activityType);
866 return windowingMode != WINDOWING_MODE_UNDEFINED
867 ? windowingMode : WINDOWING_MODE_FULLSCREEN;
Evan Rosky9ba524e2018-01-03 16:27:56 -0800868 }
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700869
Evan Rosky9ba524e2018-01-03 16:27:56 -0800870 /**
871 * Check that the requested windowing-mode is appropriate for the specified task and/or activity
872 * on this display.
873 *
874 * @param windowingMode The windowing-mode to validate.
875 * @param r The {@link ActivityRecord} to check against.
876 * @param task The {@link TaskRecord} to check against.
877 * @param activityType An activity type.
878 * @return The provided windowingMode or the closest valid mode which is appropriate.
879 */
880 int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r,
881 @Nullable TaskRecord task, int activityType) {
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700882 // Make sure the windowing mode we are trying to use makes sense for what is supported.
Wale Ogunwaled32da472018-11-16 07:19:28 -0800883 boolean supportsMultiWindow = mService.mSupportsMultiWindow;
884 boolean supportsSplitScreen = mService.mSupportsSplitScreenMultiWindow;
885 boolean supportsFreeform = mService.mSupportsFreeformWindowManagement;
886 boolean supportsPip = mService.mSupportsPictureInPicture;
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700887 if (supportsMultiWindow) {
888 if (task != null) {
889 supportsMultiWindow = task.isResizeable();
890 supportsSplitScreen = task.supportsSplitScreenWindowingMode();
891 // TODO: Do we need to check for freeform and Pip support here?
892 } else if (r != null) {
893 supportsMultiWindow = r.isResizeable();
894 supportsSplitScreen = r.supportsSplitScreenWindowingMode();
895 supportsFreeform = r.supportsFreeform();
896 supportsPip = r.supportsPictureInPicture();
897 }
898 }
899
900 final boolean inSplitScreenMode = hasSplitScreenPrimaryStack();
901 if (!inSplitScreenMode
902 && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) {
Evan Rosky10475742018-09-05 19:02:48 -0700903 // 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 -0700904 // trying to launch in split-screen secondary.
Evan Rosky10475742018-09-05 19:02:48 -0700905 windowingMode = WINDOWING_MODE_UNDEFINED;
906 } else if (inSplitScreenMode && (windowingMode == WINDOWING_MODE_FULLSCREEN
907 || windowingMode == WINDOWING_MODE_UNDEFINED)
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700908 && supportsSplitScreen) {
909 windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
910 }
911
912 if (windowingMode != WINDOWING_MODE_UNDEFINED
913 && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen,
Evan Rosky10475742018-09-05 19:02:48 -0700914 supportsFreeform, supportsPip, activityType)) {
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700915 return windowingMode;
916 }
Evan Rosky10475742018-09-05 19:02:48 -0700917 return WINDOWING_MODE_UNDEFINED;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700918 }
919
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700920 /**
921 * Get the topmost stack on the display. It may be different from focused stack, because
Andrii Kulian52d255c2018-07-13 11:32:19 -0700922 * some stacks are not focusable (e.g. PiP).
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700923 */
924 ActivityStack getTopStack() {
925 return mStacks.isEmpty() ? null : mStacks.get(mStacks.size() - 1);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700926 }
927
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700928 boolean isTopStack(ActivityStack stack) {
929 return stack == getTopStack();
930 }
931
chaviw2c500982018-01-04 17:05:05 -0800932 boolean isTopNotPinnedStack(ActivityStack stack) {
Wale Ogunwale2cca8622017-12-11 08:40:13 -0800933 for (int i = mStacks.size() - 1; i >= 0; --i) {
934 final ActivityStack current = mStacks.get(i);
chaviw2c500982018-01-04 17:05:05 -0800935 if (!current.inPinnedWindowingMode()) {
Wale Ogunwale2cca8622017-12-11 08:40:13 -0800936 return current == stack;
937 }
938 }
939 return false;
940 }
941
Wale Ogunwalef3257852018-01-24 08:52:28 -0800942 ActivityStack getTopStackInWindowingMode(int windowingMode) {
943 for (int i = mStacks.size() - 1; i >= 0; --i) {
944 final ActivityStack current = mStacks.get(i);
945 if (windowingMode == current.getWindowingMode()) {
946 return current;
947 }
948 }
949 return null;
950 }
951
Riddle Hsue10cea52018-10-16 23:33:23 +0800952 ActivityRecord topRunningActivity() {
953 return topRunningActivity(false /* considerKeyguardState */);
954 }
955
956 /**
957 * Returns the top running activity in the focused stack. In the case the focused stack has no
958 * such activity, the next focusable stack on this display is returned.
959 *
960 * @param considerKeyguardState Indicates whether the locked state should be considered. if
961 * {@code true} and the keyguard is locked, only activities that
962 * can be shown on top of the keyguard will be considered.
963 * @return The top running activity. {@code null} if none is available.
964 */
965 ActivityRecord topRunningActivity(boolean considerKeyguardState) {
966 ActivityRecord topRunning = null;
967 final ActivityStack focusedStack = getFocusedStack();
968 if (focusedStack != null) {
969 topRunning = focusedStack.topRunningActivityLocked();
970 }
971
972 // Look in other focusable stacks.
973 if (topRunning == null) {
974 for (int i = mStacks.size() - 1; i >= 0; --i) {
975 final ActivityStack stack = mStacks.get(i);
976 // Only consider focusable stacks other than the current focused one.
977 if (stack == focusedStack || !stack.isFocusable()) {
978 continue;
979 }
980 topRunning = stack.topRunningActivityLocked();
981 if (topRunning != null) {
982 break;
983 }
984 }
985 }
986
987 // This activity can be considered the top running activity if we are not considering
988 // the locked state, the keyguard isn't locked, or we can show when locked.
989 if (topRunning != null && considerKeyguardState
Wale Ogunwaled32da472018-11-16 07:19:28 -0800990 && mRootActivityContainer.mStackSupervisor.getKeyguardController().isKeyguardLocked()
Riddle Hsue10cea52018-10-16 23:33:23 +0800991 && !topRunning.canShowWhenLocked()) {
992 return null;
993 }
994
995 return topRunning;
996 }
997
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700998 int getIndexOf(ActivityStack stack) {
999 return mStacks.indexOf(stack);
1000 }
1001
Evan Roskye747c3e2018-10-30 20:06:41 -07001002 @Override
Evan Roskydfe3da72018-10-26 17:21:06 -07001003 public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
1004 final int currRotation =
1005 getRequestedOverrideConfiguration().windowConfiguration.getRotation();
Evan Roskye747c3e2018-10-30 20:06:41 -07001006 if (currRotation != ROTATION_UNDEFINED
1007 && currRotation != overrideConfiguration.windowConfiguration.getRotation()
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001008 && mDisplayContent != null) {
1009 mDisplayContent.applyRotationLocked(currRotation,
Evan Roskye747c3e2018-10-30 20:06:41 -07001010 overrideConfiguration.windowConfiguration.getRotation());
1011 }
Evan Roskydfe3da72018-10-26 17:21:06 -07001012 super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001013 if (mDisplayContent != null) {
1014 mService.mWindowManager.setNewDisplayOverrideConfiguration(
1015 overrideConfiguration, mDisplayContent);
1016 }
Evan Roskye747c3e2018-10-30 20:06:41 -07001017 }
1018
1019 @Override
1020 public void onConfigurationChanged(Configuration newParentConfig) {
1021 // update resources before cascade so that docked/pinned stacks use the correct info
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001022 if (mDisplayContent != null) {
1023 mDisplayContent.preOnConfigurationChanged();
1024 }
Evan Roskye747c3e2018-10-30 20:06:41 -07001025 super.onConfigurationChanged(newParentConfig);
1026 }
1027
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001028 void onLockTaskPackagesUpdated() {
1029 for (int i = mStacks.size() - 1; i >= 0; --i) {
1030 mStacks.get(i).onLockTaskPackagesUpdated();
1031 }
1032 }
1033
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -07001034 /** We are in the process of exiting split-screen mode. */
1035 void onExitingSplitScreenMode() {
1036 // Remove reference to the primary-split-screen stack so it no longer has any effect on the
1037 // display. For example, we want to be able to create fullscreen stack for standard activity
1038 // types when exiting split-screen mode.
1039 mSplitScreenPrimaryStack = null;
1040 }
1041
Riddle Hsu7b766fd2019-01-28 21:14:59 +08001042 /** Checks whether the given activity is in size compatibility mode and notifies the change. */
1043 void handleActivitySizeCompatModeIfNeeded(ActivityRecord r) {
1044 if (!r.isState(RESUMED) || r.getWindowingMode() != WINDOWING_MODE_FULLSCREEN) {
1045 // The callback is only interested in the foreground changes of fullscreen activity.
1046 return;
1047 }
1048 if (!r.inSizeCompatMode()) {
1049 if (mLastCompatModeActivity != null) {
1050 mService.getTaskChangeNotificationController()
1051 .notifySizeCompatModeActivityChanged(mDisplayId, null /* activityToken */);
1052 }
1053 mLastCompatModeActivity = null;
1054 return;
1055 }
1056 if (mLastCompatModeActivity == r) {
1057 return;
1058 }
1059 mLastCompatModeActivity = r;
1060 mService.getTaskChangeNotificationController()
1061 .notifySizeCompatModeActivityChanged(mDisplayId, r.appToken);
1062 }
1063
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001064 ActivityStack getSplitScreenPrimaryStack() {
1065 return mSplitScreenPrimaryStack;
1066 }
1067
1068 boolean hasSplitScreenPrimaryStack() {
1069 return mSplitScreenPrimaryStack != null;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001070 }
1071
Yunfan Chen279f5582018-12-12 15:24:50 -08001072 ActivityStack getPinnedStack() {
1073 return mPinnedStack;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001074 }
1075
1076 boolean hasPinnedStack() {
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001077 return mPinnedStack != null;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -07001078 }
1079
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001080 @Override
1081 public String toString() {
1082 return "ActivityDisplay={" + mDisplayId + " numStacks=" + mStacks.size() + "}";
1083 }
1084
1085 @Override
1086 protected int getChildCount() {
1087 return mStacks.size();
1088 }
1089
1090 @Override
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001091 protected ActivityStack getChildAt(int index) {
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001092 return mStacks.get(index);
1093 }
1094
1095 @Override
1096 protected ConfigurationContainer getParent() {
Wale Ogunwaled32da472018-11-16 07:19:28 -08001097 return mRootActivityContainer;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001098 }
1099
1100 boolean isPrivate() {
1101 return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
1102 }
1103
1104 boolean isUidPresent(int uid) {
1105 for (ActivityStack stack : mStacks) {
1106 if (stack.isUidPresent(uid)) {
1107 return true;
1108 }
1109 }
1110 return false;
1111 }
1112
Louis Chang7d0037c2018-08-13 12:42:06 +08001113 /**
1114 * @see #mRemoved
1115 */
1116 boolean isRemoved() {
1117 return mRemoved;
1118 }
1119
Bryce Leef19cbe22018-02-02 15:09:21 -08001120 void remove() {
1121 final boolean destroyContentOnRemoval = shouldDestroyContentOnRemove();
Riddle Hsu402b4402018-11-06 17:23:15 +08001122 ActivityStack lastReparentedStack = null;
1123 mPreferredTopFocusableStack = null;
Louis Chang7d0037c2018-08-13 12:42:06 +08001124
1125 // Stacks could be reparented from the removed display to other display. While
1126 // reparenting the last stack of the removed display, the remove display is ready to be
1127 // released (no more ActivityStack). But, we cannot release it at that moment or the
1128 // related WindowContainer and WindowContainerController will also be removed. So, we
1129 // set display as removed after reparenting stack finished.
Wale Ogunwaled32da472018-11-16 07:19:28 -08001130 final ActivityDisplay toDisplay = mRootActivityContainer.getDefaultDisplay();
1131 mRootActivityContainer.mStackSupervisor.beginDeferResume();
Riddle Hsu402b4402018-11-06 17:23:15 +08001132 try {
1133 int numStacks = mStacks.size();
1134 // Keep the order from bottom to top.
1135 for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
1136 final ActivityStack stack = mStacks.get(stackNdx);
1137 // Always finish non-standard type stacks.
1138 if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) {
1139 stack.finishAllActivitiesLocked(true /* immediately */);
1140 } else {
1141 // If default display is in split-window mode, set windowing mode of the stack
1142 // to split-screen secondary. Otherwise, set the windowing mode to undefined by
1143 // default to let stack inherited the windowing mode from the new display.
1144 final int windowingMode = toDisplay.hasSplitScreenPrimaryStack()
1145 ? WINDOWING_MODE_SPLIT_SCREEN_SECONDARY
1146 : WINDOWING_MODE_UNDEFINED;
1147 stack.reparent(toDisplay, true /* onTop */, true /* displayRemoved */);
1148 stack.setWindowingMode(windowingMode);
1149 lastReparentedStack = stack;
1150 }
1151 // Stacks may be removed from this display. Ensure each stack will be processed and
1152 // the loop will end.
1153 stackNdx -= numStacks - mStacks.size();
1154 numStacks = mStacks.size();
Bryce Leef19cbe22018-02-02 15:09:21 -08001155 }
Riddle Hsu402b4402018-11-06 17:23:15 +08001156 } finally {
Wale Ogunwaled32da472018-11-16 07:19:28 -08001157 mRootActivityContainer.mStackSupervisor.endDeferResume();
Bryce Leef19cbe22018-02-02 15:09:21 -08001158 }
Louis Chang7d0037c2018-08-13 12:42:06 +08001159 mRemoved = true;
Bryce Leef19cbe22018-02-02 15:09:21 -08001160
Riddle Hsu402b4402018-11-06 17:23:15 +08001161 // Only update focus/visibility for the last one because there may be many stacks are
1162 // reparented and the intermediate states are unnecessary.
1163 if (lastReparentedStack != null) {
1164 lastReparentedStack.postReparent();
1165 }
Louis Chang7d0037c2018-08-13 12:42:06 +08001166 releaseSelfIfNeeded();
wilsonshih0299c8a2018-08-24 15:52:57 +08001167
Riddle Hsuf53da812018-08-15 22:00:27 +08001168 if (!mAllSleepTokens.isEmpty()) {
Wale Ogunwaled32da472018-11-16 07:19:28 -08001169 mRootActivityContainer.mSleepTokens.removeAll(mAllSleepTokens);
Riddle Hsuf53da812018-08-15 22:00:27 +08001170 mAllSleepTokens.clear();
Wale Ogunwaled32da472018-11-16 07:19:28 -08001171 mService.updateSleepIfNeededLocked();
Riddle Hsuf53da812018-08-15 22:00:27 +08001172 }
Louis Chang7d0037c2018-08-13 12:42:06 +08001173 }
1174
1175 private void releaseSelfIfNeeded() {
1176 if (mStacks.isEmpty() && mRemoved) {
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001177 mDisplayContent.removeIfPossible();
1178 mDisplayContent = null;
Wale Ogunwaled32da472018-11-16 07:19:28 -08001179 mRootActivityContainer.removeChild(this);
1180 mRootActivityContainer.mStackSupervisor
1181 .getKeyguardController().onDisplayRemoved(mDisplayId);
Louis Chang7d0037c2018-08-13 12:42:06 +08001182 }
Bryce Leef19cbe22018-02-02 15:09:21 -08001183 }
1184
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001185 /** Update and get all UIDs that are present on the display and have access to it. */
1186 IntArray getPresentUIDs() {
1187 mDisplayAccessUIDs.clear();
1188 for (ActivityStack stack : mStacks) {
1189 stack.getPresentUIDs(mDisplayAccessUIDs);
1190 }
1191 return mDisplayAccessUIDs;
1192 }
1193
Louis Changbd48dca2018-08-29 17:44:34 +08001194 /**
Andrii Kulian15cfb422018-11-07 13:38:49 -08001195 * Checks if system decorations should be shown on this display.
1196 *
Louis Changbd48dca2018-08-29 17:44:34 +08001197 * @see Display#FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS
1198 */
1199 boolean supportsSystemDecorations() {
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001200 return mDisplayContent.supportsSystemDecorations();
Louis Changbd48dca2018-08-29 17:44:34 +08001201 }
1202
Riddle Hsu402b4402018-11-06 17:23:15 +08001203 @VisibleForTesting
1204 boolean shouldDestroyContentOnRemove() {
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001205 return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT;
1206 }
1207
1208 boolean shouldSleep() {
1209 return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty())
Wale Ogunwaled32da472018-11-16 07:19:28 -08001210 && (mService.mRunningVoice == null);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001211 }
1212
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001213 void setFocusedApp(ActivityRecord r, boolean moveFocusNow) {
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001214 if (mDisplayContent == null) {
1215 return;
1216 }
1217 final AppWindowToken newFocus;
1218 final IBinder token = r.appToken;
1219 if (token == null) {
1220 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Clearing focused app, displayId="
1221 + mDisplayId);
1222 newFocus = null;
1223 } else {
1224 newFocus = mService.mWindowManager.mRoot.getAppWindowToken(token);
1225 if (newFocus == null) {
1226 Slog.w(TAG_WM, "Attempted to set focus to non-existing app token: " + token
1227 + ", displayId=" + mDisplayId);
1228 }
1229 if (DEBUG_FOCUS_LIGHT) Slog.v(TAG_WM, "Set focused app to: " + newFocus
1230 + " moveFocusNow=" + moveFocusNow + " displayId=" + mDisplayId);
1231 }
1232
1233 final boolean changed = mDisplayContent.setFocusedApp(newFocus);
1234 if (moveFocusNow && changed) {
1235 mService.mWindowManager.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
1236 true /*updateInputWindows*/);
1237 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +08001238 }
1239
Winson Chunge2d72172018-01-25 17:46:20 +00001240 /**
Winson Chung3e2980e2018-03-29 17:28:57 -07001241 * @return the stack currently above the {@param stack}. Can be null if the {@param stack} is
1242 * already top-most.
Winson Chunge2d72172018-01-25 17:46:20 +00001243 */
Winson Chung3e2980e2018-03-29 17:28:57 -07001244 ActivityStack getStackAbove(ActivityStack stack) {
1245 final int stackIndex = mStacks.indexOf(stack) + 1;
Winson Chunge2d72172018-01-25 17:46:20 +00001246 return (stackIndex < mStacks.size()) ? mStacks.get(stackIndex) : null;
1247 }
1248
1249 /**
Winson Chung3e2980e2018-03-29 17:28:57 -07001250 * Adjusts the {@param stack} behind the last visible stack in the display if necessary.
1251 * Generally used in conjunction with {@link #moveStackBehindStack}.
Winson Chunge2d72172018-01-25 17:46:20 +00001252 */
Winson Chung3e2980e2018-03-29 17:28:57 -07001253 void moveStackBehindBottomMostVisibleStack(ActivityStack stack) {
1254 if (stack.shouldBeVisible(null)) {
1255 // Skip if the stack is already visible
Winson Chunge2d72172018-01-25 17:46:20 +00001256 return;
1257 }
1258
Winson Chung3e2980e2018-03-29 17:28:57 -07001259 // Move the stack to the bottom to not affect the following visibility checks
1260 positionChildAtBottom(stack);
Winson Chunge2d72172018-01-25 17:46:20 +00001261
Winson Chung3e2980e2018-03-29 17:28:57 -07001262 // Find the next position where the stack should be placed
Winson Chunge2d72172018-01-25 17:46:20 +00001263 final int numStacks = mStacks.size();
1264 for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) {
Winson Chung3e2980e2018-03-29 17:28:57 -07001265 final ActivityStack s = mStacks.get(stackNdx);
1266 if (s == stack) {
Winson Chunge2d72172018-01-25 17:46:20 +00001267 continue;
1268 }
Winson Chung3e2980e2018-03-29 17:28:57 -07001269 final int winMode = s.getWindowingMode();
Winson Chunge2d72172018-01-25 17:46:20 +00001270 final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN ||
1271 winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
Winson Chung3e2980e2018-03-29 17:28:57 -07001272 if (s.shouldBeVisible(null) && isValidWindowingMode) {
1273 // Move the provided stack to behind this stack
1274 positionChildAt(stack, Math.max(0, stackNdx - 1));
Winson Chunge2d72172018-01-25 17:46:20 +00001275 break;
1276 }
1277 }
1278 }
1279
1280 /**
Winson Chung3e2980e2018-03-29 17:28:57 -07001281 * Moves the {@param stack} behind the given {@param behindStack} if possible. If
1282 * {@param behindStack} is not currently in the display, then then the stack is moved to the
1283 * back. Generally used in conjunction with {@link #moveStackBehindBottomMostVisibleStack}.
Winson Chunge2d72172018-01-25 17:46:20 +00001284 */
Winson Chung3e2980e2018-03-29 17:28:57 -07001285 void moveStackBehindStack(ActivityStack stack, ActivityStack behindStack) {
1286 if (behindStack == null || behindStack == stack) {
Winson Chunge2d72172018-01-25 17:46:20 +00001287 return;
1288 }
1289
Winson Chung123e07a2018-02-27 11:47:16 -08001290 // Note that positionChildAt will first remove the given stack before inserting into the
1291 // list, so we need to adjust the insertion index to account for the removed index
1292 // TODO: Remove this logic when WindowContainer.positionChildAt() is updated to adjust the
1293 // position internally
Winson Chung3e2980e2018-03-29 17:28:57 -07001294 final int stackIndex = mStacks.indexOf(stack);
Winson Chung123e07a2018-02-27 11:47:16 -08001295 final int behindStackIndex = mStacks.indexOf(behindStack);
Winson Chung3e2980e2018-03-29 17:28:57 -07001296 final int insertIndex = stackIndex <= behindStackIndex
Winson Chung123e07a2018-02-27 11:47:16 -08001297 ? behindStackIndex - 1 : behindStackIndex;
Winson Chung3e2980e2018-03-29 17:28:57 -07001298 positionChildAt(stack, Math.max(0, insertIndex));
Winson Chunge2d72172018-01-25 17:46:20 +00001299 }
1300
Louis Chang77ce34d2019-01-03 15:45:12 +08001301 void ensureActivitiesVisible(ActivityRecord starting, int configChanges,
1302 boolean preserveWindows, boolean notifyClients) {
1303 for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) {
1304 final ActivityStack stack = getChildAt(stackNdx);
1305 stack.ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows,
1306 notifyClients);
1307 }
1308 }
1309
Louis Changbd48dca2018-08-29 17:44:34 +08001310 void moveHomeStackToFront(String reason) {
1311 if (mHomeStack != null) {
1312 mHomeStack.moveToFront(reason);
1313 }
1314 }
1315
1316 /** Returns true if the focus activity was adjusted to the home stack top activity. */
1317 boolean moveHomeActivityToTop(String reason) {
1318 final ActivityRecord top = getHomeActivity();
1319 if (top == null) {
1320 return false;
1321 }
Louis Chang19443452018-10-09 12:10:21 +08001322 top.moveFocusableActivityToTop(reason);
Louis Changbd48dca2018-08-29 17:44:34 +08001323 return true;
1324 }
1325
1326 @Nullable
1327 ActivityStack getHomeStack() {
1328 return mHomeStack;
1329 }
1330
1331 @Nullable
1332 ActivityRecord getHomeActivity() {
Wale Ogunwaled32da472018-11-16 07:19:28 -08001333 return getHomeActivityForUser(mRootActivityContainer.mCurrentUser);
Louis Changbd48dca2018-08-29 17:44:34 +08001334 }
1335
1336 @Nullable
1337 ActivityRecord getHomeActivityForUser(int userId) {
1338 if (mHomeStack == null) {
1339 return null;
1340 }
1341
1342 final ArrayList<TaskRecord> tasks = mHomeStack.getAllTasks();
1343 for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
1344 final TaskRecord task = tasks.get(taskNdx);
1345 if (!task.isActivityTypeHome()) {
1346 continue;
1347 }
1348
1349 final ArrayList<ActivityRecord> activities = task.mActivities;
1350 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1351 final ActivityRecord r = activities.get(activityNdx);
1352 if (r.isActivityTypeHome()
Wale Ogunwale8b19de92018-11-29 19:58:26 -08001353 && ((userId == UserHandle.USER_ALL) || (r.mUserId == userId))) {
Louis Changbd48dca2018-08-29 17:44:34 +08001354 return r;
1355 }
1356 }
1357 }
1358 return null;
1359 }
1360
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001361 boolean isSleeping() {
1362 return mSleeping;
1363 }
1364
1365 void setIsSleeping(boolean asleep) {
1366 mSleeping = asleep;
1367 }
1368
Winson Chung0f7ec962018-05-03 18:03:15 -07001369 /**
1370 * Adds a listener to be notified whenever the stack order in the display changes. Currently
1371 * only used by the {@link RecentsAnimation} to determine whether to interrupt and cancel the
1372 * current animation when the system state changes.
1373 */
1374 void registerStackOrderChangedListener(OnStackOrderChangedListener listener) {
1375 if (!mStackOrderChangedCallbacks.contains(listener)) {
1376 mStackOrderChangedCallbacks.add(listener);
1377 }
1378 }
1379
1380 /**
1381 * Removes a previously registered stack order change listener.
1382 */
1383 void unregisterStackOrderChangedListener(OnStackOrderChangedListener listener) {
1384 mStackOrderChangedCallbacks.remove(listener);
1385 }
1386
Winson Chung65d66d32018-12-13 17:48:39 -08001387 /**
1388 * Notifies of a stack order change
1389 * @param stack The stack which triggered the order change
1390 */
1391 private void onStackOrderChanged(ActivityStack stack) {
Winson Chung0f7ec962018-05-03 18:03:15 -07001392 for (int i = mStackOrderChangedCallbacks.size() - 1; i >= 0; i--) {
Winson Chung65d66d32018-12-13 17:48:39 -08001393 mStackOrderChangedCallbacks.get(i).onStackOrderChanged(stack);
Winson Chung0f7ec962018-05-03 18:03:15 -07001394 }
1395 }
1396
Chavi Weingarten3a748552018-05-14 17:32:42 +00001397 /**
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001398 * See {@link DisplayContent#deferUpdateImeTarget()}
Chavi Weingarten3a748552018-05-14 17:32:42 +00001399 */
1400 public void deferUpdateImeTarget() {
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001401 if (mDisplayContent != null) {
1402 mDisplayContent.deferUpdateImeTarget();
1403 }
Chavi Weingarten3a748552018-05-14 17:32:42 +00001404 }
1405
1406 /**
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001407 * See {@link DisplayContent#deferUpdateImeTarget()}
Chavi Weingarten3a748552018-05-14 17:32:42 +00001408 */
1409 public void continueUpdateImeTarget() {
Wale Ogunwale3a256e62018-12-06 14:41:18 -08001410 if (mDisplayContent != null) {
1411 mDisplayContent.continueUpdateImeTarget();
1412 }
Chavi Weingarten3a748552018-05-14 17:32:42 +00001413 }
1414
Wale Ogunwale9e737db2018-12-17 15:42:37 -08001415 void setDisplayToSingleTaskInstance() {
1416 final int childCount = getChildCount();
1417 if (childCount > 1) {
1418 throw new IllegalArgumentException("Display already has multiple stacks. display="
1419 + this);
1420 }
1421 if (childCount > 0) {
1422 final ActivityStack stack = getChildAt(0);
1423 if (stack.getChildCount() > 1) {
1424 throw new IllegalArgumentException("Display stack already has multiple tasks."
1425 + " display=" + this + " stack=" + stack);
1426 }
1427 }
1428
1429 mSingleTaskInstance = true;
1430 }
1431
1432 /** Returns true if the display can only contain one task */
1433 boolean isSingleTaskInstance() {
1434 return mSingleTaskInstance;
1435 }
1436
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001437 public void dump(PrintWriter pw, String prefix) {
Wale Ogunwale9e737db2018-12-17 15:42:37 -08001438 pw.println(prefix + "displayId=" + mDisplayId + " stacks=" + mStacks.size()
1439 + (mSingleTaskInstance ? " mSingleTaskInstance" : ""));
Wale Ogunwale30e441d2017-11-09 08:28:45 -08001440 final String myPrefix = prefix + " ";
1441 if (mHomeStack != null) {
1442 pw.println(myPrefix + "mHomeStack=" + mHomeStack);
1443 }
1444 if (mRecentsStack != null) {
1445 pw.println(myPrefix + "mRecentsStack=" + mRecentsStack);
1446 }
1447 if (mPinnedStack != null) {
1448 pw.println(myPrefix + "mPinnedStack=" + mPinnedStack);
1449 }
1450 if (mSplitScreenPrimaryStack != null) {
1451 pw.println(myPrefix + "mSplitScreenPrimaryStack=" + mSplitScreenPrimaryStack);
1452 }
Riddle Hsu75016992018-09-20 20:37:14 +08001453 if (mPreferredTopFocusableStack != null) {
1454 pw.println(myPrefix + "mPreferredTopFocusableStack=" + mPreferredTopFocusableStack);
1455 }
Riddle Hsubbb63c22018-10-03 12:28:29 +08001456 if (mLastFocusedStack != null) {
1457 pw.println(myPrefix + "mLastFocusedStack=" + mLastFocusedStack);
1458 }
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -07001459 }
1460
Bryce Lee77a7dd62018-01-22 15:47:09 -08001461 public void dumpStacks(PrintWriter pw) {
1462 for (int i = mStacks.size() - 1; i >= 0; --i) {
1463 pw.print(mStacks.get(i).mStackId);
1464 if (i > 0) {
1465 pw.print(",");
1466 }
1467 }
1468 }
1469
Nataniel Borges023ecb52019-01-16 14:15:43 -08001470 public void writeToProto(ProtoOutputStream proto, long fieldId,
1471 @WindowTraceLogLevel int logLevel) {
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001472 final long token = proto.start(fieldId);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001473 super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001474 proto.write(ID, mDisplayId);
Wale Ogunwale9e737db2018-12-17 15:42:37 -08001475 proto.write(SINGLE_TASK_INSTANCE, mSingleTaskInstance);
Andrii Kulianab132ee2018-07-24 22:10:21 +08001476 final ActivityStack focusedStack = getFocusedStack();
1477 if (focusedStack != null) {
1478 proto.write(FOCUSED_STACK_ID, focusedStack.mStackId);
1479 final ActivityRecord focusedActivity = focusedStack.getDisplay().getResumedActivity();
1480 if (focusedActivity != null) {
1481 focusedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY);
1482 }
1483 } else {
1484 proto.write(FOCUSED_STACK_ID, INVALID_STACK_ID);
1485 }
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001486 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1487 final ActivityStack stack = mStacks.get(stackNdx);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001488 stack.writeToProto(proto, STACKS, logLevel);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001489 }
1490 proto.end(token);
1491 }
Winson Chung0f7ec962018-05-03 18:03:15 -07001492
1493 /**
1494 * Callback for when the order of the stacks in the display changes.
1495 */
1496 interface OnStackOrderChangedListener {
Winson Chung65d66d32018-12-13 17:48:39 -08001497 void onStackOrderChanged(ActivityStack stack);
Winson Chung0f7ec962018-05-03 18:03:15 -07001498 }
Wale Ogunwale9dcf9462017-09-19 15:13:01 -07001499}