blob: 2289f8572b93889fdb71f4c7ec7d5f9deb3afe0d [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
17package com.android.server.am;
18
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -070019import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070020import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
21import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
22import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
Wale Ogunwaleab5de372017-10-18 06:46:31 -070023import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070024import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
25import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY;
26import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
27import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
28import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
29import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
30import static android.view.Display.DEFAULT_DISPLAY;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070031import static android.view.Display.FLAG_PRIVATE;
32import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
33import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_STACK;
34import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_STACK;
35import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
36import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
37import static com.android.server.am.proto.ActivityDisplayProto.CONFIGURATION_CONTAINER;
38import static com.android.server.am.proto.ActivityDisplayProto.STACKS;
39import static com.android.server.am.proto.ActivityDisplayProto.ID;
40
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -070041import android.annotation.Nullable;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070042import android.app.ActivityManagerInternal;
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -070043import android.app.ActivityOptions;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070044import android.app.WindowConfiguration;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070045import android.util.IntArray;
46import android.util.Slog;
47import android.util.proto.ProtoOutputStream;
48import android.view.Display;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -070049import com.android.internal.annotations.VisibleForTesting;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070050import com.android.server.wm.ConfigurationContainer;
51
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -070052import java.io.PrintWriter;
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070053import java.util.ArrayList;
54
55/**
56 * Exactly one of these classes per Display in the system. Capable of holding zero or more
57 * attached {@link ActivityStack}s.
58 */
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -070059class ActivityDisplay extends ConfigurationContainer<ActivityStack> {
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070060 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityDisplay" : TAG_AM;
61 private static final String TAG_STACK = TAG + POSTFIX_STACK;
62
63 static final int POSITION_TOP = Integer.MAX_VALUE;
64 static final int POSITION_BOTTOM = Integer.MIN_VALUE;
65
66 private ActivityStackSupervisor mSupervisor;
67 /** Actual Display this object tracks. */
68 int mDisplayId;
69 Display mDisplay;
70
71 /** All of the stacks on this display. Order matters, topmost stack is in front of all other
72 * stacks, bottommost behind. Accessed directly by ActivityManager package classes */
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -070073 private final ArrayList<ActivityStack> mStacks = new ArrayList<>();
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070074
75 /** Array of all UIDs that are present on the display. */
76 private IntArray mDisplayAccessUIDs = new IntArray();
77
78 /** All tokens used to put activities on this stack to sleep (including mOffToken) */
79 final ArrayList<ActivityManagerInternal.SleepToken> mAllSleepTokens = new ArrayList<>();
80 /** The token acquired by ActivityStackSupervisor to put stacks on the display to sleep */
81 ActivityManagerInternal.SleepToken mOffToken;
82
83 private boolean mSleeping;
84
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -070085 // Cached reference to some special stacks we tend to get a lot so we don't need to loop
86 // through the list to find them.
87 private ActivityStack mHomeStack = null;
88 private ActivityStack mRecentsStack = null;
89 private ActivityStack mPinnedStack = null;
90 private ActivityStack mSplitScreenPrimaryStack = null;
91
Wale Ogunwale9dcf9462017-09-19 15:13:01 -070092 ActivityDisplay(ActivityStackSupervisor supervisor, int displayId) {
93 mSupervisor = supervisor;
94 mDisplayId = displayId;
95 final Display display = supervisor.mDisplayManager.getDisplay(displayId);
96 if (display == null) {
97 throw new IllegalStateException("Display does not exist displayId=" + displayId);
98 }
99 mDisplay = display;
100 }
101
102 void addChild(ActivityStack stack, int position) {
103 if (position == POSITION_BOTTOM) {
104 position = 0;
105 } else if (position == POSITION_TOP) {
106 position = mStacks.size();
107 }
108 if (DEBUG_STACK) Slog.v(TAG_STACK, "addChild: attaching " + stack
109 + " to displayId=" + mDisplayId + " position=" + position);
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700110 addStackReferenceIfNeeded(stack);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700111 positionChildAt(stack, position);
112 mSupervisor.mService.updateSleepIfNeededLocked();
113 }
114
115 void removeChild(ActivityStack stack) {
116 if (DEBUG_STACK) Slog.v(TAG_STACK, "removeChild: detaching " + stack
117 + " from displayId=" + mDisplayId);
118 mStacks.remove(stack);
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700119 removeStackReferenceIfNeeded(stack);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700120 mSupervisor.mService.updateSleepIfNeededLocked();
121 }
122
123 void positionChildAtTop(ActivityStack stack) {
124 positionChildAt(stack, mStacks.size());
125 }
126
127 void positionChildAtBottom(ActivityStack stack) {
128 positionChildAt(stack, 0);
129 }
130
131 private void positionChildAt(ActivityStack stack, int position) {
132 mStacks.remove(stack);
133 mStacks.add(getTopInsertPosition(stack, position), stack);
134 }
135
136 private int getTopInsertPosition(ActivityStack stack, int candidatePosition) {
137 int position = mStacks.size();
138 if (position > 0) {
139 final ActivityStack topStack = mStacks.get(position - 1);
140 if (topStack.getWindowConfiguration().isAlwaysOnTop() && topStack != stack) {
141 // If the top stack is always on top, we move this stack just below it.
142 position--;
143 }
144 }
145 return Math.min(position, candidatePosition);
146 }
147
148 <T extends ActivityStack> T getStack(int stackId) {
149 for (int i = mStacks.size() - 1; i >= 0; --i) {
150 final ActivityStack stack = mStacks.get(i);
151 if (stack.mStackId == stackId) {
152 return (T) stack;
153 }
154 }
155 return null;
156 }
157
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700158 /**
159 * @return the topmost stack on the display that is compatible with the input windowing mode and
160 * activity type. {@code null} means no compatible stack on the display.
161 * @see ConfigurationContainer#isCompatible(int, int)
162 */
163 <T extends ActivityStack> T getStack(int windowingMode, int activityType) {
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700164 if (activityType == ACTIVITY_TYPE_HOME) {
165 return (T) mHomeStack;
166 } else if (activityType == ACTIVITY_TYPE_RECENTS) {
167 return (T) mRecentsStack;
168 }
169 if (windowingMode == WINDOWING_MODE_PINNED) {
170 return (T) mPinnedStack;
171 } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
172 return (T) mSplitScreenPrimaryStack;
173 }
Wale Ogunwaleab5de372017-10-18 06:46:31 -0700174
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700175 for (int i = mStacks.size() - 1; i >= 0; --i) {
176 final ActivityStack stack = mStacks.get(i);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700177 if (stack.isCompatible(windowingMode, activityType)) {
178 return (T) stack;
179 }
180 }
181 return null;
182 }
183
Wale Ogunwaleab5de372017-10-18 06:46:31 -0700184 private boolean alwaysCreateStack(int windowingMode, int activityType) {
185 // Always create a stack for fullscreen, freeform, and split-screen-secondary windowing
186 // modes so that we can manage visual ordering and return types correctly.
187 return activityType == ACTIVITY_TYPE_STANDARD
188 && (windowingMode == WINDOWING_MODE_FULLSCREEN
189 || windowingMode == WINDOWING_MODE_FREEFORM
190 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
191 }
192
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700193 /**
Wale Ogunwaleab5de372017-10-18 06:46:31 -0700194 * Returns an existing stack compatible with the windowing mode and activity type or creates one
195 * if a compatible stack doesn't exist.
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700196 * @see #getStack(int, int)
197 * @see #createStack(int, int, boolean)
198 */
199 <T extends ActivityStack> T getOrCreateStack(int windowingMode, int activityType,
200 boolean onTop) {
Wale Ogunwaleab5de372017-10-18 06:46:31 -0700201 if (!alwaysCreateStack(windowingMode, activityType)) {
202 T stack = getStack(windowingMode, activityType);
203 if (stack != null) {
204 return stack;
205 }
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700206 }
207 return createStack(windowingMode, activityType, onTop);
208 }
209
Wale Ogunwale68278562017-09-23 17:13:55 -0700210 /**
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700211 * Returns an existing stack compatible with the input params or creates one
212 * if a compatible stack doesn't exist.
213 * @see #getOrCreateStack(int, int, boolean)
214 */
215 <T extends ActivityStack> T getOrCreateStack(@Nullable ActivityRecord r,
216 @Nullable ActivityOptions options, @Nullable TaskRecord candidateTask, int activityType,
217 boolean onTop) {
218 final int windowingMode = resolveWindowingMode(r, options, candidateTask, activityType);
219 return getOrCreateStack(windowingMode, activityType, onTop);
220 }
221
222 /**
Wale Ogunwale68278562017-09-23 17:13:55 -0700223 * Creates a stack matching the input windowing mode and activity type on this display.
224 * @param windowingMode The windowing mode the stack should be created in. If
225 * {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will
226 * be created in {@link WindowConfiguration#WINDOWING_MODE_FULLSCREEN}.
227 * @param activityType The activityType the stack should be created in. If
228 * {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will
229 * be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}.
230 * @param onTop If true the stack will be created at the top of the display, else at the bottom.
231 * @return The newly created stack.
232 */
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700233 <T extends ActivityStack> T createStack(int windowingMode, int activityType, boolean onTop) {
234
Wale Ogunwale68278562017-09-23 17:13:55 -0700235 if (activityType == ACTIVITY_TYPE_UNDEFINED) {
236 // Can't have an undefined stack type yet...so re-map to standard. Anyone that wants
237 // anything else should be passing it in anyways...
238 activityType = ACTIVITY_TYPE_STANDARD;
239 }
240
241 if (activityType != ACTIVITY_TYPE_STANDARD) {
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700242 // For now there can be only one stack of a particular non-standard activity type on a
243 // display. So, get that ignoring whatever windowing mode it is currently in.
244 T stack = getStack(WINDOWING_MODE_UNDEFINED, activityType);
245 if (stack != null) {
246 throw new IllegalArgumentException("Stack=" + stack + " of activityType="
247 + activityType + " already on display=" + this + ". Can't have multiple.");
248 }
249 }
250
251 final ActivityManagerService service = mSupervisor.mService;
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700252 if (!isWindowingModeSupported(windowingMode, service.mSupportsMultiWindow,
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700253 service.mSupportsSplitScreenMultiWindow, service.mSupportsFreeformWindowManagement,
254 service.mSupportsPictureInPicture, activityType)) {
255 throw new IllegalArgumentException("Can't create stack for unsupported windowingMode="
256 + windowingMode);
257 }
258
259 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
260 // TODO: Should be okay to have stacks with with undefined windowing mode long term, but
261 // have to set them to something for now due to logic that depending on them.
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700262 windowingMode = getWindowingMode(); // Put in current display's windowing mode
263 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
264 // Else fullscreen for now...
265 windowingMode = WINDOWING_MODE_FULLSCREEN;
266 }
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700267 }
268
Wale Ogunwale44f036f2017-09-29 05:09:09 -0700269 final int stackId = mSupervisor.getNextStackId();
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700270 return createStackUnchecked(windowingMode, activityType, stackId, onTop);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700271 }
272
273 @VisibleForTesting
274 <T extends ActivityStack> T createStackUnchecked(int windowingMode, int activityType,
275 int stackId, boolean onTop) {
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700276 if (windowingMode == WINDOWING_MODE_PINNED) {
277 return (T) new PinnedActivityStack(this, stackId, mSupervisor, onTop);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700278 }
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800279 return (T) new ActivityStack(
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700280 this, stackId, mSupervisor, windowingMode, activityType, onTop);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700281 }
282
Wale Ogunwale68278562017-09-23 17:13:55 -0700283 /**
284 * Removes stacks in the input windowing modes from the system if they are of activity type
285 * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
286 */
287 void removeStacksInWindowingModes(int... windowingModes) {
288 if (windowingModes == null || windowingModes.length == 0) {
289 return;
290 }
291
292 for (int j = windowingModes.length - 1 ; j >= 0; --j) {
293 final int windowingMode = windowingModes[j];
294 for (int i = mStacks.size() - 1; i >= 0; --i) {
295 final ActivityStack stack = mStacks.get(i);
296 if (!stack.isActivityTypeStandardOrUndefined()) {
297 continue;
298 }
299 if (stack.getWindowingMode() != windowingMode) {
300 continue;
301 }
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700302 mSupervisor.removeStack(stack);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700303 }
304 }
305 }
306
Wale Ogunwale68278562017-09-23 17:13:55 -0700307 void removeStacksWithActivityTypes(int... activityTypes) {
308 if (activityTypes == null || activityTypes.length == 0) {
309 return;
310 }
311
312 for (int j = activityTypes.length - 1 ; j >= 0; --j) {
313 final int activityType = activityTypes[j];
314 for (int i = mStacks.size() - 1; i >= 0; --i) {
315 final ActivityStack stack = mStacks.get(i);
316 if (stack.getActivityType() == activityType) {
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700317 mSupervisor.removeStack(stack);
Wale Ogunwale68278562017-09-23 17:13:55 -0700318 }
319 }
320 }
321 }
322
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700323 void onStackWindowingModeChanged(ActivityStack stack) {
324 removeStackReferenceIfNeeded(stack);
325 addStackReferenceIfNeeded(stack);
326 }
327
328 private void addStackReferenceIfNeeded(ActivityStack stack) {
329 final int activityType = stack.getActivityType();
330 final int windowingMode = stack.getWindowingMode();
331
332 if (activityType == ACTIVITY_TYPE_HOME) {
333 if (mHomeStack != null && mHomeStack != stack) {
334 throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack="
335 + mHomeStack + " already exist on display=" + this + " stack=" + stack);
336 }
337 mHomeStack = stack;
338 } else if (activityType == ACTIVITY_TYPE_RECENTS) {
339 if (mRecentsStack != null && mRecentsStack != stack) {
340 throw new IllegalArgumentException("addStackReferenceIfNeeded: recents stack="
341 + mRecentsStack + " already exist on display=" + this + " stack=" + stack);
342 }
343 mRecentsStack = stack;
344 }
345 if (windowingMode == WINDOWING_MODE_PINNED) {
346 if (mPinnedStack != null && mPinnedStack != stack) {
347 throw new IllegalArgumentException("addStackReferenceIfNeeded: pinned stack="
348 + mPinnedStack + " already exist on display=" + this
349 + " stack=" + stack);
350 }
351 mPinnedStack = stack;
352 } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
353 if (mSplitScreenPrimaryStack != null && mSplitScreenPrimaryStack != stack) {
354 throw new IllegalArgumentException("addStackReferenceIfNeeded:"
355 + " split-screen-primary" + " stack=" + mSplitScreenPrimaryStack
356 + " already exist on display=" + this + " stack=" + stack);
357 }
358 mSplitScreenPrimaryStack = stack;
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800359 onSplitScreenModeActivated();
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700360 }
361 }
362
363 private void removeStackReferenceIfNeeded(ActivityStack stack) {
364 if (stack == mHomeStack) {
365 mHomeStack = null;
366 } else if (stack == mRecentsStack) {
367 mRecentsStack = null;
368 } else if (stack == mPinnedStack) {
369 mPinnedStack = null;
370 } else if (stack == mSplitScreenPrimaryStack) {
371 mSplitScreenPrimaryStack = null;
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800372 // Inform the reset of the system that split-screen mode was dismissed so things like
373 // resizing all the other stacks can take place.
374 onSplitScreenModeDismissed();
375 }
376 }
377
378 private void onSplitScreenModeDismissed() {
379 mSupervisor.mWindowManager.deferSurfaceLayout();
380 try {
381 // Adjust the windowing mode of any stack in secondary split-screen to fullscreen.
382 for (int i = mStacks.size() - 1; i >= 0; --i) {
383 final ActivityStack otherStack = mStacks.get(i);
384 if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
385 continue;
386 }
387 otherStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
388 }
389 } finally {
390 mSupervisor.mWindowManager.continueSurfaceLayout();
391 }
392 }
393
394 private void onSplitScreenModeActivated() {
395 mSupervisor.mWindowManager.deferSurfaceLayout();
396 try {
397 // Adjust the windowing mode of any affected by split-screen to split-screen secondary.
398 for (int i = mStacks.size() - 1; i >= 0; --i) {
399 final ActivityStack otherStack = mStacks.get(i);
400 if (otherStack == mSplitScreenPrimaryStack
401 || !otherStack.affectedBySplitScreenResize()) {
402 continue;
403 }
404 otherStack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
405 }
406 } finally {
407 mSupervisor.mWindowManager.continueSurfaceLayout();
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700408 }
409 }
410
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700411 /**
412 * Returns true if the {@param windowingMode} is supported based on other parameters passed in.
413 * @param windowingMode The windowing mode we are checking support for.
414 * @param supportsMultiWindow If we should consider support for multi-window mode in general.
415 * @param supportsSplitScreen If we should consider support for split-screen multi-window.
416 * @param supportsFreeform If we should consider support for freeform multi-window.
417 * @param supportsPip If we should consider support for picture-in-picture mutli-window.
418 * @param activityType The activity type under consideration.
419 * @return true if the windowing mode is supported.
420 */
421 private boolean isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow,
422 boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip,
423 int activityType) {
424
425 if (windowingMode == WINDOWING_MODE_UNDEFINED
426 || windowingMode == WINDOWING_MODE_FULLSCREEN) {
427 return true;
428 }
429 if (!supportsMultiWindow) {
430 return false;
431 }
432
433 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
434 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
Wale Ogunwale2b07da82017-11-08 14:52:40 -0800435 return supportsSplitScreen
436 && WindowConfiguration.supportSplitScreenWindowingMode(activityType);
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700437 }
438
439 if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) {
440 return false;
441 }
442
443 if (!supportsPip && windowingMode == WINDOWING_MODE_PINNED) {
444 return false;
445 }
446 return true;
447 }
448
449 int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options,
450 @Nullable TaskRecord task, int activityType) {
451
452 // First preference if the windowing mode in the activity options if set.
453 int windowingMode = (options != null)
454 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED;
455
456 // If windowing mode is unset, then next preference is the candidate task, then the
457 // activity record.
458 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
459 if (task != null) {
460 windowingMode = task.getWindowingMode();
461 }
462 if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) {
463 windowingMode = r.getWindowingMode();
464 }
465 if (windowingMode == WINDOWING_MODE_UNDEFINED) {
466 // Use the display's windowing mode.
467 windowingMode = getWindowingMode();
468 }
469 }
470
471 // Make sure the windowing mode we are trying to use makes sense for what is supported.
472 final ActivityManagerService service = mSupervisor.mService;
473 boolean supportsMultiWindow = service.mSupportsMultiWindow;
474 boolean supportsSplitScreen = service.mSupportsSplitScreenMultiWindow;
475 boolean supportsFreeform = service.mSupportsFreeformWindowManagement;
476 boolean supportsPip = service.mSupportsPictureInPicture;
477 if (supportsMultiWindow) {
478 if (task != null) {
479 supportsMultiWindow = task.isResizeable();
480 supportsSplitScreen = task.supportsSplitScreenWindowingMode();
481 // TODO: Do we need to check for freeform and Pip support here?
482 } else if (r != null) {
483 supportsMultiWindow = r.isResizeable();
484 supportsSplitScreen = r.supportsSplitScreenWindowingMode();
485 supportsFreeform = r.supportsFreeform();
486 supportsPip = r.supportsPictureInPicture();
487 }
488 }
489
490 final boolean inSplitScreenMode = hasSplitScreenPrimaryStack();
491 if (!inSplitScreenMode
492 && windowingMode == WINDOWING_MODE_FULLSCREEN_OR_SPLIT_SCREEN_SECONDARY) {
493 // Switch to fullscreen windowing mode if we are not in split-screen mode and we are
494 // trying to launch in split-screen secondary.
495 windowingMode = WINDOWING_MODE_FULLSCREEN;
496 } else if (inSplitScreenMode && windowingMode == WINDOWING_MODE_FULLSCREEN
497 && supportsSplitScreen) {
498 windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
499 }
500
501 if (windowingMode != WINDOWING_MODE_UNDEFINED
502 && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen,
503 supportsFreeform, supportsPip, activityType)) {
504 return windowingMode;
505 }
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800506 // Try to use the display's windowing mode otherwise fallback to fullscreen.
507 windowingMode = getWindowingMode();
508 return windowingMode != WINDOWING_MODE_UNDEFINED
509 ? windowingMode : WINDOWING_MODE_FULLSCREEN;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700510 }
511
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700512 /**
513 * Get the topmost stack on the display. It may be different from focused stack, because
514 * focus may be on another display.
515 */
516 ActivityStack getTopStack() {
517 return mStacks.isEmpty() ? null : mStacks.get(mStacks.size() - 1);
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700518 }
519
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700520 boolean isTopStack(ActivityStack stack) {
521 return stack == getTopStack();
522 }
523
524 int getIndexOf(ActivityStack stack) {
525 return mStacks.indexOf(stack);
526 }
527
528 void onLockTaskPackagesUpdated() {
529 for (int i = mStacks.size() - 1; i >= 0; --i) {
530 mStacks.get(i).onLockTaskPackagesUpdated();
531 }
532 }
533
Wale Ogunwale7e1f5f52017-10-18 15:19:59 -0700534 /** We are in the process of exiting split-screen mode. */
535 void onExitingSplitScreenMode() {
536 // Remove reference to the primary-split-screen stack so it no longer has any effect on the
537 // display. For example, we want to be able to create fullscreen stack for standard activity
538 // types when exiting split-screen mode.
539 mSplitScreenPrimaryStack = null;
540 }
541
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700542 ActivityStack getSplitScreenPrimaryStack() {
543 return mSplitScreenPrimaryStack;
544 }
545
546 boolean hasSplitScreenPrimaryStack() {
547 return mSplitScreenPrimaryStack != null;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700548 }
549
550 PinnedActivityStack getPinnedStack() {
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700551 return (PinnedActivityStack) mPinnedStack;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700552 }
553
554 boolean hasPinnedStack() {
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700555 return mPinnedStack != null;
Wale Ogunwale04a05ac2017-09-17 21:35:02 -0700556 }
557
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700558 @Override
559 public String toString() {
560 return "ActivityDisplay={" + mDisplayId + " numStacks=" + mStacks.size() + "}";
561 }
562
563 @Override
564 protected int getChildCount() {
565 return mStacks.size();
566 }
567
568 @Override
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700569 protected ActivityStack getChildAt(int index) {
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700570 return mStacks.get(index);
571 }
572
573 @Override
574 protected ConfigurationContainer getParent() {
575 return mSupervisor;
576 }
577
578 boolean isPrivate() {
579 return (mDisplay.getFlags() & FLAG_PRIVATE) != 0;
580 }
581
582 boolean isUidPresent(int uid) {
583 for (ActivityStack stack : mStacks) {
584 if (stack.isUidPresent(uid)) {
585 return true;
586 }
587 }
588 return false;
589 }
590
591 /** Update and get all UIDs that are present on the display and have access to it. */
592 IntArray getPresentUIDs() {
593 mDisplayAccessUIDs.clear();
594 for (ActivityStack stack : mStacks) {
595 stack.getPresentUIDs(mDisplayAccessUIDs);
596 }
597 return mDisplayAccessUIDs;
598 }
599
600 boolean shouldDestroyContentOnRemove() {
601 return mDisplay.getRemoveMode() == REMOVE_MODE_DESTROY_CONTENT;
602 }
603
604 boolean shouldSleep() {
605 return (mStacks.isEmpty() || !mAllSleepTokens.isEmpty())
606 && (mSupervisor.mService.mRunningVoice == null);
607 }
608
609 boolean isSleeping() {
610 return mSleeping;
611 }
612
613 void setIsSleeping(boolean asleep) {
614 mSleeping = asleep;
615 }
616
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700617 public void dump(PrintWriter pw, String prefix) {
Wale Ogunwale30e441d2017-11-09 08:28:45 -0800618 pw.println(prefix + "displayId=" + mDisplayId + " stacks=" + mStacks.size());
619 final String myPrefix = prefix + " ";
620 if (mHomeStack != null) {
621 pw.println(myPrefix + "mHomeStack=" + mHomeStack);
622 }
623 if (mRecentsStack != null) {
624 pw.println(myPrefix + "mRecentsStack=" + mRecentsStack);
625 }
626 if (mPinnedStack != null) {
627 pw.println(myPrefix + "mPinnedStack=" + mPinnedStack);
628 }
629 if (mSplitScreenPrimaryStack != null) {
630 pw.println(myPrefix + "mSplitScreenPrimaryStack=" + mSplitScreenPrimaryStack);
631 }
Wale Ogunwalea0f5b5e2017-10-11 09:37:23 -0700632 }
633
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700634 public void writeToProto(ProtoOutputStream proto, long fieldId) {
635 final long token = proto.start(fieldId);
Adrian Roos4921ccf2017-09-28 16:54:06 +0200636 super.writeToProto(proto, CONFIGURATION_CONTAINER, false /* trim */);
Wale Ogunwale9dcf9462017-09-19 15:13:01 -0700637 proto.write(ID, mDisplayId);
638 for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
639 final ActivityStack stack = mStacks.get(stackNdx);
640 stack.writeToProto(proto, STACKS);
641 }
642 proto.end(token);
643 }
644}