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