1 /* 2 * Copyright (C) 2020 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.WindowConfiguration.ACTIVITY_TYPE_HOME; 20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; 21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; 22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; 23 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; 24 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 25 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; 26 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; 27 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; 28 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; 29 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; 30 import static android.app.WindowConfiguration.isSplitScreenWindowingMode; 31 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND; 32 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; 33 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; 34 35 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED; 36 import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE; 37 import static com.android.server.wm.ActivityStackSupervisor.TAG_TASKS; 38 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES; 39 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS; 40 import static com.android.server.wm.ActivityTaskManagerService.TAG_STACK; 41 import static com.android.server.wm.DisplayContent.alwaysCreateStack; 42 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE; 43 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; 44 import static com.android.server.wm.RootWindowContainer.TAG_STATES; 45 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; 46 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 47 48 import android.annotation.Nullable; 49 import android.app.ActivityOptions; 50 import android.app.WindowConfiguration; 51 import android.content.Intent; 52 import android.content.pm.ActivityInfo; 53 import android.content.pm.ApplicationInfo; 54 import android.os.UserHandle; 55 import android.util.IntArray; 56 import android.util.Slog; 57 import android.view.SurfaceControl; 58 import android.window.WindowContainerTransaction; 59 60 import com.android.internal.annotations.VisibleForTesting; 61 import com.android.internal.util.ToBooleanFunction; 62 import com.android.internal.util.function.pooled.PooledLambda; 63 import com.android.internal.util.function.pooled.PooledPredicate; 64 import com.android.server.protolog.common.ProtoLog; 65 66 import java.io.PrintWriter; 67 import java.util.ArrayList; 68 import java.util.List; 69 70 /** 71 * {@link DisplayArea} that represents a section of a screen that contains app window containers. 72 */ 73 final class TaskDisplayArea extends DisplayArea<ActivityStack> { 74 75 DisplayContent mDisplayContent; 76 77 /** 78 * A control placed at the appropriate level for transitions to occur. 79 */ 80 private SurfaceControl mAppAnimationLayer; 81 private SurfaceControl mBoostedAppAnimationLayer; 82 private SurfaceControl mHomeAppAnimationLayer; 83 84 /** 85 * Given that the split-screen divider does not have an AppWindowToken, it 86 * will have to live inside of a "NonAppWindowContainer". However, in visual Z order 87 * it will need to be interleaved with some of our children, appearing on top of 88 * both docked stacks but underneath any assistant stacks. 89 * 90 * To solve this problem we have this anchor control, which will always exist so 91 * we can always assign it the correct value in our {@link #assignChildLayers}. 92 * Likewise since it always exists, we can always 93 * assign the divider a layer relative to it. This way we prevent linking lifecycle 94 * events between tasks and the divider window. 95 */ 96 private SurfaceControl mSplitScreenDividerAnchor; 97 98 // Cached reference to some special tasks we tend to get a lot so we don't need to loop 99 // through the list to find them. 100 private ActivityStack mRootHomeTask; 101 private ActivityStack mRootPinnedTask; 102 private ActivityStack mRootSplitScreenPrimaryTask; 103 104 // TODO(b/159029784): Remove when getStack() behavior is cleaned-up 105 private ActivityStack mRootRecentsTask; 106 107 private final ArrayList<ActivityStack> mTmpAlwaysOnTopStacks = new ArrayList<>(); 108 private final ArrayList<ActivityStack> mTmpNormalStacks = new ArrayList<>(); 109 private final ArrayList<ActivityStack> mTmpHomeStacks = new ArrayList<>(); 110 private final IntArray mTmpNeedsZBoostIndexes = new IntArray(); 111 private int mTmpLayerForSplitScreenDividerAnchor; 112 private int mTmpLayerForAnimationLayer; 113 114 private ArrayList<Task> mTmpTasks = new ArrayList<>(); 115 116 private ActivityTaskManagerService mAtmService; 117 118 private RootWindowContainer mRootWindowContainer; 119 120 // When non-null, new tasks get put into this root task. 121 Task mLaunchRootTask = null; 122 123 /** 124 * A focusable stack that is purposely to be positioned at the top. Although the stack may not 125 * have the topmost index, it is used as a preferred candidate to prevent being unable to resume 126 * target stack properly when there are other focusable always-on-top stacks. 127 */ 128 ActivityStack mPreferredTopFocusableStack; 129 130 private final RootWindowContainer.FindTaskResult 131 mTmpFindTaskResult = new RootWindowContainer.FindTaskResult(); 132 133 /** 134 * If this is the same as {@link #getFocusedStack} then the activity on the top of the focused 135 * stack has been resumed. If stacks are changing position this will hold the old stack until 136 * the new stack becomes resumed after which it will be set to current focused stack. 137 */ 138 ActivityStack mLastFocusedStack; 139 /** 140 * All of the stacks on this display. Order matters, topmost stack is in front of all other 141 * stacks, bottommost behind. Accessed directly by ActivityManager package classes. Any calls 142 * changing the list should also call {@link #onStackOrderChanged()}. 143 */ 144 private ArrayList<OnStackOrderChangedListener> mStackOrderChangedCallbacks = new ArrayList<>(); 145 146 /** 147 * The task display area is removed from the system and we are just waiting for all activities 148 * on it to be finished before removing this object. 149 */ 150 private boolean mRemoved; 151 TaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name, int displayAreaFeature)152 TaskDisplayArea(DisplayContent displayContent, WindowManagerService service, String name, 153 int displayAreaFeature) { 154 super(service, Type.ANY, name, displayAreaFeature); 155 mDisplayContent = displayContent; 156 mRootWindowContainer = service.mRoot; 157 mAtmService = service.mAtmService; 158 } 159 160 /** 161 * Returns the topmost stack on the display that is compatible with the input windowing mode 162 * and activity type. Null is no compatible stack on the display. 163 */ getStack(int windowingMode, int activityType)164 ActivityStack getStack(int windowingMode, int activityType) { 165 if (activityType == ACTIVITY_TYPE_HOME) { 166 return mRootHomeTask; 167 } else if (activityType == ACTIVITY_TYPE_RECENTS) { 168 return mRootRecentsTask; 169 } 170 if (windowingMode == WINDOWING_MODE_PINNED) { 171 return mRootPinnedTask; 172 } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { 173 return mRootSplitScreenPrimaryTask; 174 } 175 for (int i = getChildCount() - 1; i >= 0; --i) { 176 final ActivityStack stack = getChildAt(i); 177 if (activityType == ACTIVITY_TYPE_UNDEFINED 178 && windowingMode == stack.getWindowingMode()) { 179 // Passing in undefined type means we want to match the topmost stack with the 180 // windowing mode. 181 return stack; 182 } 183 if (stack.isCompatible(windowingMode, activityType)) { 184 return stack; 185 } 186 } 187 return null; 188 } 189 190 @VisibleForTesting getTopStack()191 ActivityStack getTopStack() { 192 final int count = getChildCount(); 193 return count > 0 ? getChildAt(count - 1) : null; 194 } 195 196 // TODO: Figure-out a way to remove since it might be a source of confusion. getIndexOf(ActivityStack stack)197 int getIndexOf(ActivityStack stack) { 198 return mChildren.indexOf(stack); 199 } 200 getRootHomeTask()201 @Nullable ActivityStack getRootHomeTask() { 202 return mRootHomeTask; 203 } 204 getRootRecentsTask()205 @Nullable ActivityStack getRootRecentsTask() { 206 return mRootRecentsTask; 207 } 208 getRootPinnedTask()209 ActivityStack getRootPinnedTask() { 210 return mRootPinnedTask; 211 } 212 getRootSplitScreenPrimaryTask()213 ActivityStack getRootSplitScreenPrimaryTask() { 214 return mRootSplitScreenPrimaryTask; 215 } 216 getRootSplitScreenSecondaryTask()217 ActivityStack getRootSplitScreenSecondaryTask() { 218 for (int i = mChildren.size() - 1; i >= 0; --i) { 219 if (mChildren.get(i).inSplitScreenSecondaryWindowingMode()) { 220 return mChildren.get(i); 221 } 222 } 223 return null; 224 } 225 getVisibleTasks()226 ArrayList<Task> getVisibleTasks() { 227 final ArrayList<Task> visibleTasks = new ArrayList<>(); 228 forAllTasks(task -> { 229 if (task.isLeafTask() && task.isVisible()) { 230 visibleTasks.add(task); 231 } 232 }); 233 return visibleTasks; 234 } 235 onStackWindowingModeChanged(ActivityStack stack)236 void onStackWindowingModeChanged(ActivityStack stack) { 237 removeStackReferenceIfNeeded(stack); 238 addStackReferenceIfNeeded(stack); 239 if (stack == mRootPinnedTask && getTopStack() != stack) { 240 // Looks like this stack changed windowing mode to pinned. Move it to the top. 241 positionChildAt(POSITION_TOP, stack, false /* includingParents */); 242 } 243 } 244 addStackReferenceIfNeeded(ActivityStack stack)245 void addStackReferenceIfNeeded(ActivityStack stack) { 246 if (stack.isActivityTypeHome()) { 247 if (mRootHomeTask != null) { 248 if (!stack.isDescendantOf(mRootHomeTask)) { 249 throw new IllegalArgumentException("addStackReferenceIfNeeded: home stack=" 250 + mRootHomeTask + " already exist on display=" + this 251 + " stack=" + stack); 252 } 253 } else { 254 mRootHomeTask = stack; 255 } 256 } else if (stack.isActivityTypeRecents()) { 257 if (mRootRecentsTask != null) { 258 if (!stack.isDescendantOf(mRootRecentsTask)) { 259 throw new IllegalArgumentException("addStackReferenceIfNeeded: recents stack=" 260 + mRootRecentsTask + " already exist on display=" + this 261 + " stack=" + stack); 262 } 263 } else { 264 mRootRecentsTask = stack; 265 } 266 } 267 268 if (!stack.isRootTask()) { 269 return; 270 } 271 final int windowingMode = stack.getWindowingMode(); 272 if (windowingMode == WINDOWING_MODE_PINNED) { 273 if (mRootPinnedTask != null) { 274 throw new IllegalArgumentException( 275 "addStackReferenceIfNeeded: pinned stack=" + mRootPinnedTask 276 + " already exist on display=" + this + " stack=" + stack); 277 } 278 mRootPinnedTask = stack; 279 } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { 280 if (mRootSplitScreenPrimaryTask != null) { 281 throw new IllegalArgumentException( 282 "addStackReferenceIfNeeded: split screen primary stack=" 283 + mRootSplitScreenPrimaryTask 284 + " already exist on display=" + this + " stack=" + stack); 285 } 286 mRootSplitScreenPrimaryTask = stack; 287 } 288 } 289 removeStackReferenceIfNeeded(ActivityStack stack)290 void removeStackReferenceIfNeeded(ActivityStack stack) { 291 if (stack == mRootHomeTask) { 292 mRootHomeTask = null; 293 } else if (stack == mRootRecentsTask) { 294 mRootRecentsTask = null; 295 } else if (stack == mRootPinnedTask) { 296 mRootPinnedTask = null; 297 } else if (stack == mRootSplitScreenPrimaryTask) { 298 mRootSplitScreenPrimaryTask = null; 299 } 300 } 301 302 @Override addChild(ActivityStack stack, int position)303 void addChild(ActivityStack stack, int position) { 304 if (DEBUG_STACK) Slog.d(TAG_WM, "Set stack=" + stack + " on taskDisplayArea=" + this); 305 addStackReferenceIfNeeded(stack); 306 position = findPositionForStack(position, stack, true /* adding */); 307 308 super.addChild(stack, position); 309 mAtmService.updateSleepIfNeededLocked(); 310 311 positionStackAt(stack, position); 312 } 313 314 @Override removeChild(ActivityStack stack)315 protected void removeChild(ActivityStack stack) { 316 super.removeChild(stack); 317 onStackRemoved(stack); 318 mAtmService.updateSleepIfNeededLocked(); 319 removeStackReferenceIfNeeded(stack); 320 } 321 322 @Override isOnTop()323 boolean isOnTop() { 324 // Considered always on top 325 return true; 326 } 327 328 @Override positionChildAt(int position, ActivityStack child, boolean includingParents)329 void positionChildAt(int position, ActivityStack child, boolean includingParents) { 330 final boolean moveToTop = position >= getChildCount() - 1; 331 final boolean moveToBottom = (position == POSITION_BOTTOM || position == 0); 332 333 // Reset mPreferredTopFocusableStack before positioning to top or {@link 334 // ActivityStackSupervisor#updateTopResumedActivityIfNeeded()} won't update the top 335 // resumed activity. 336 final boolean wasContained = mChildren.contains(child); 337 if (moveToTop && wasContained && child.isFocusable()) { 338 mPreferredTopFocusableStack = null; 339 } 340 341 if (child.getWindowConfiguration().isAlwaysOnTop() && !moveToTop) { 342 // This stack is always-on-top, override the default behavior. 343 Slog.w(TAG_WM, "Ignoring move of always-on-top stack=" + this + " to bottom"); 344 345 // Moving to its current position, as we must call super but we don't want to 346 // perform any meaningful action. 347 final int currentPosition = mChildren.indexOf(child); 348 super.positionChildAt(currentPosition, child, false /* includingParents */); 349 return; 350 } 351 // We don't allow untrusted display to top when task stack moves to top, 352 // until user tapping this display to change display position as top intentionally. 353 if (!mDisplayContent.isTrusted() && !getParent().isOnTop()) { 354 includingParents = false; 355 } 356 final int targetPosition = findPositionForStack(position, child, false /* adding */); 357 super.positionChildAt(targetPosition, child, false /* includingParents */); 358 359 if (includingParents && (moveToTop || moveToBottom)) { 360 // The DisplayContent children do not re-order, but we still want to move the 361 // display of this stack container because the intention of positioning is to have 362 // higher z-order to gain focus. 363 mDisplayContent.positionDisplayAt(moveToTop ? POSITION_TOP : POSITION_BOTTOM, 364 true /* includingParents */); 365 } 366 367 child.updateTaskMovement(moveToTop); 368 369 mDisplayContent.setLayoutNeeded(); 370 371 // The insert position may be adjusted to non-top when there is always-on-top stack. Since 372 // the original position is preferred to be top, the stack should have higher priority when 373 // we are looking for top focusable stack. The condition {@code wasContained} restricts the 374 // preferred stack is set only when moving an existing stack to top instead of adding a new 375 // stack that may be too early (e.g. in the middle of launching or reparenting). 376 if (moveToTop && child.isFocusableAndVisible()) { 377 mPreferredTopFocusableStack = child; 378 } else if (mPreferredTopFocusableStack == child) { 379 mPreferredTopFocusableStack = null; 380 } 381 } 382 383 /** 384 * Assigns a priority number to stack types. This priority defines an order between the types 385 * of stacks that are added to the task display area. 386 * 387 * Higher priority number indicates that the stack should have a higher z-order. 388 * 389 * @return the priority of the stack 390 */ getPriority(ActivityStack stack)391 private int getPriority(ActivityStack stack) { 392 if (mWmService.mAssistantOnTopOfDream && stack.isActivityTypeAssistant()) return 4; 393 if (stack.isActivityTypeDream()) return 3; 394 if (stack.inPinnedWindowingMode()) return 2; 395 if (stack.isAlwaysOnTop()) return 1; 396 return 0; 397 } 398 findMinPositionForStack(ActivityStack stack)399 private int findMinPositionForStack(ActivityStack stack) { 400 int minPosition = POSITION_BOTTOM; 401 for (int i = 0; i < mChildren.size(); ++i) { 402 if (getPriority(getStackAt(i)) < getPriority(stack)) { 403 minPosition = i; 404 } else { 405 break; 406 } 407 } 408 409 if (stack.isAlwaysOnTop()) { 410 // Since a stack could be repositioned while still being one of the children, we check 411 // if this always-on-top stack already exists and if so, set the minPosition to its 412 // previous position. 413 final int currentIndex = getIndexOf(stack); 414 if (currentIndex > minPosition) { 415 minPosition = currentIndex; 416 } 417 } 418 return minPosition; 419 } 420 findMaxPositionForStack(ActivityStack stack)421 private int findMaxPositionForStack(ActivityStack stack) { 422 for (int i = mChildren.size() - 1; i >= 0; --i) { 423 final ActivityStack curr = getStackAt(i); 424 // Since a stack could be repositioned while still being one of the children, we check 425 // if 'curr' is the same stack and skip it if so 426 final boolean sameStack = curr == stack; 427 if (getPriority(curr) <= getPriority(stack) && !sameStack) { 428 return i; 429 } 430 } 431 return 0; 432 } 433 434 /** 435 * When stack is added or repositioned, find a proper position for it. 436 * 437 * The order is defined as: 438 * - Dream is on top of everything 439 * - PiP is directly below the Dream 440 * - always-on-top stacks are directly below PiP; new always-on-top stacks are added above 441 * existing ones 442 * - other non-always-on-top stacks come directly below always-on-top stacks; new 443 * non-always-on-top stacks are added directly below always-on-top stacks and above existing 444 * non-always-on-top stacks 445 * - if {@link #mAssistantOnTopOfDream} is enabled, then Assistant is on top of everything 446 * (including the Dream); otherwise, it is a normal non-always-on-top stack 447 * 448 * @param requestedPosition Position requested by caller. 449 * @param stack Stack to be added or positioned. 450 * @param adding Flag indicates whether we're adding a new stack or positioning an existing. 451 * @return The proper position for the stack. 452 */ findPositionForStack(int requestedPosition, ActivityStack stack, boolean adding)453 private int findPositionForStack(int requestedPosition, ActivityStack stack, boolean adding) { 454 // The max possible position we can insert the stack at. 455 int maxPosition = findMaxPositionForStack(stack); 456 // The min possible position we can insert the stack at. 457 int minPosition = findMinPositionForStack(stack); 458 459 // Cap the requested position to something reasonable for the previous position check 460 // below. 461 if (requestedPosition == POSITION_TOP) { 462 requestedPosition = mChildren.size(); 463 } else if (requestedPosition == POSITION_BOTTOM) { 464 requestedPosition = 0; 465 } 466 467 int targetPosition = requestedPosition; 468 targetPosition = Math.min(targetPosition, maxPosition); 469 targetPosition = Math.max(targetPosition, minPosition); 470 471 int prevPosition = mChildren.indexOf(stack); 472 // The positions we calculated above (maxPosition, minPosition) do not take into 473 // consideration the following edge cases. 474 // 1) We need to adjust the position depending on the value "adding". 475 // 2) When we are moving a stack to another position, we also need to adjust the 476 // position depending on whether the stack is moving to a higher or lower position. 477 if ((targetPosition != requestedPosition) && (adding || targetPosition < prevPosition)) { 478 targetPosition++; 479 } 480 481 return targetPosition; 482 } 483 484 @Override forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)485 boolean forAllWindows(ToBooleanFunction<WindowState> callback, 486 boolean traverseTopToBottom) { 487 if (traverseTopToBottom) { 488 if (super.forAllWindows(callback, traverseTopToBottom)) { 489 return true; 490 } 491 if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) { 492 return true; 493 } 494 } else { 495 if (forAllExitingAppTokenWindows(callback, traverseTopToBottom)) { 496 return true; 497 } 498 if (super.forAllWindows(callback, traverseTopToBottom)) { 499 return true; 500 } 501 } 502 return false; 503 } 504 forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)505 private boolean forAllExitingAppTokenWindows(ToBooleanFunction<WindowState> callback, 506 boolean traverseTopToBottom) { 507 // For legacy reasons we process the TaskStack.mExitingActivities first here before the 508 // app tokens. 509 // TODO: Investigate if we need to continue to do this or if we can just process them 510 // in-order. 511 if (traverseTopToBottom) { 512 for (int i = mChildren.size() - 1; i >= 0; --i) { 513 final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities; 514 for (int j = activities.size() - 1; j >= 0; --j) { 515 if (activities.get(j).forAllWindowsUnchecked(callback, 516 traverseTopToBottom)) { 517 return true; 518 } 519 } 520 } 521 } else { 522 final int count = mChildren.size(); 523 for (int i = 0; i < count; ++i) { 524 final List<ActivityRecord> activities = mChildren.get(i).mExitingActivities; 525 final int appTokensCount = activities.size(); 526 for (int j = 0; j < appTokensCount; j++) { 527 if (activities.get(j).forAllWindowsUnchecked(callback, 528 traverseTopToBottom)) { 529 return true; 530 } 531 } 532 } 533 } 534 return false; 535 } 536 setExitingTokensHasVisible(boolean hasVisible)537 void setExitingTokensHasVisible(boolean hasVisible) { 538 for (int i = mChildren.size() - 1; i >= 0; --i) { 539 final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities; 540 for (int j = activities.size() - 1; j >= 0; --j) { 541 activities.get(j).hasVisible = hasVisible; 542 } 543 } 544 } 545 removeExistingAppTokensIfPossible()546 void removeExistingAppTokensIfPossible() { 547 for (int i = mChildren.size() - 1; i >= 0; --i) { 548 final ArrayList<ActivityRecord> activities = mChildren.get(i).mExitingActivities; 549 for (int j = activities.size() - 1; j >= 0; --j) { 550 final ActivityRecord activity = activities.get(j); 551 if (!activity.hasVisible && !mDisplayContent.mClosingApps.contains(activity) 552 && (!activity.mIsExiting || activity.isEmpty())) { 553 // Make sure there is no animation running on this activity, so any windows 554 // associated with it will be removed as soon as their animations are 555 // complete. 556 cancelAnimation(); 557 ProtoLog.v(WM_DEBUG_ADD_REMOVE, 558 "performLayout: Activity exiting now removed %s", activity); 559 activity.removeIfPossible(); 560 } 561 } 562 } 563 } 564 565 @Override getOrientation(int candidate)566 int getOrientation(int candidate) { 567 if (isStackVisible(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY)) { 568 // Apps and their containers are not allowed to specify an orientation while using 569 // root tasks...except for the home stack if it is not resizable and currently 570 // visible (top of) its root task. 571 if (mRootHomeTask != null && !mRootHomeTask.isResizeable()) { 572 // Manually nest one-level because because getOrientation() checks fillsParent() 573 // which checks that requestedOverrideBounds() is empty. However, in this case, 574 // it is not empty because it's been overridden to maintain the fullscreen size 575 // within a smaller split-root. 576 final Task topHomeTask = mRootHomeTask.getTopMostTask(); 577 final ActivityRecord topHomeActivity = topHomeTask.getTopNonFinishingActivity(); 578 // If a home activity is in the process of launching and isn't yet visible we 579 // should still respect the stack's preferred orientation to ensure rotation occurs 580 // before the home activity finishes launching. 581 final boolean isHomeActivityLaunching = topHomeActivity != null 582 && topHomeActivity.mVisibleRequested; 583 if (topHomeTask.isVisible() || isHomeActivityLaunching) { 584 final int orientation = topHomeTask.getOrientation(); 585 if (orientation != SCREEN_ORIENTATION_UNSET) { 586 return orientation; 587 } 588 } 589 } 590 return SCREEN_ORIENTATION_UNSPECIFIED; 591 } 592 593 final int orientation = super.getOrientation(candidate); 594 if (orientation != SCREEN_ORIENTATION_UNSET 595 && orientation != SCREEN_ORIENTATION_BEHIND) { 596 ProtoLog.v(WM_DEBUG_ORIENTATION, 597 "App is requesting an orientation, return %d for display id=%d", 598 orientation, mDisplayContent.mDisplayId); 599 return orientation; 600 } 601 602 ProtoLog.v(WM_DEBUG_ORIENTATION, 603 "No app is requesting an orientation, return %d for display id=%d", 604 mDisplayContent.getLastOrientation(), mDisplayContent.mDisplayId); 605 // The next app has not been requested to be visible, so we keep the current orientation 606 // to prevent freezing/unfreezing the display too early. 607 return mDisplayContent.getLastOrientation(); 608 } 609 610 @Override assignChildLayers(SurfaceControl.Transaction t)611 void assignChildLayers(SurfaceControl.Transaction t) { 612 assignStackOrdering(t); 613 614 for (int i = 0; i < mChildren.size(); i++) { 615 final ActivityStack s = mChildren.get(i); 616 s.assignChildLayers(t); 617 } 618 } 619 assignStackOrdering(SurfaceControl.Transaction t)620 void assignStackOrdering(SurfaceControl.Transaction t) { 621 if (getParent() == null) { 622 return; 623 } 624 mTmpAlwaysOnTopStacks.clear(); 625 mTmpHomeStacks.clear(); 626 mTmpNormalStacks.clear(); 627 for (int i = 0; i < mChildren.size(); ++i) { 628 final ActivityStack s = mChildren.get(i); 629 if (s.isAlwaysOnTop()) { 630 mTmpAlwaysOnTopStacks.add(s); 631 } else if (s.isActivityTypeHome()) { 632 mTmpHomeStacks.add(s); 633 } else { 634 mTmpNormalStacks.add(s); 635 } 636 } 637 638 int layer = 0; 639 // Place home stacks to the bottom. 640 layer = adjustRootTaskLayer(t, mTmpHomeStacks, layer, false /* normalStacks */); 641 // The home animation layer is between the home stacks and the normal stacks. 642 final int layerForHomeAnimationLayer = layer++; 643 mTmpLayerForSplitScreenDividerAnchor = layer++; 644 mTmpLayerForAnimationLayer = layer++; 645 layer = adjustRootTaskLayer(t, mTmpNormalStacks, layer, true /* normalStacks */); 646 647 // The boosted animation layer is between the normal stacks and the always on top 648 // stacks. 649 final int layerForBoostedAnimationLayer = layer++; 650 adjustRootTaskLayer(t, mTmpAlwaysOnTopStacks, layer, false /* normalStacks */); 651 652 t.setLayer(mHomeAppAnimationLayer, layerForHomeAnimationLayer); 653 t.setLayer(mAppAnimationLayer, mTmpLayerForAnimationLayer); 654 t.setLayer(mSplitScreenDividerAnchor, mTmpLayerForSplitScreenDividerAnchor); 655 t.setLayer(mBoostedAppAnimationLayer, layerForBoostedAnimationLayer); 656 } 657 adjustNormalStackLayer(ActivityStack s, int layer)658 private int adjustNormalStackLayer(ActivityStack s, int layer) { 659 if (s.inSplitScreenWindowingMode()) { 660 // The split screen divider anchor is located above the split screen window. 661 mTmpLayerForSplitScreenDividerAnchor = layer++; 662 } 663 if (s.isTaskAnimating() || s.isAppTransitioning()) { 664 // The animation layer is located above the highest animating stack and no 665 // higher. 666 mTmpLayerForAnimationLayer = layer++; 667 } 668 return layer; 669 } 670 671 /** 672 * Adjusts the layer of the stack which belongs to the same group. 673 * Note that there are three stack groups: home stacks, always on top stacks, and normal stacks. 674 * 675 * @param startLayer The beginning layer of this group of stacks. 676 * @param normalStacks Set {@code true} if this group is neither home nor always on top. 677 * @return The adjusted layer value. 678 */ adjustRootTaskLayer(SurfaceControl.Transaction t, ArrayList<ActivityStack> stacks, int startLayer, boolean normalStacks)679 private int adjustRootTaskLayer(SurfaceControl.Transaction t, ArrayList<ActivityStack> stacks, 680 int startLayer, boolean normalStacks) { 681 mTmpNeedsZBoostIndexes.clear(); 682 final int stackSize = stacks.size(); 683 for (int i = 0; i < stackSize; i++) { 684 final ActivityStack stack = stacks.get(i); 685 if (!stack.needsZBoost()) { 686 stack.assignLayer(t, startLayer++); 687 if (normalStacks) { 688 startLayer = adjustNormalStackLayer(stack, startLayer); 689 } 690 } else { 691 mTmpNeedsZBoostIndexes.add(i); 692 } 693 } 694 695 final int zBoostSize = mTmpNeedsZBoostIndexes.size(); 696 for (int i = 0; i < zBoostSize; i++) { 697 final ActivityStack stack = stacks.get(mTmpNeedsZBoostIndexes.get(i)); 698 stack.assignLayer(t, startLayer++); 699 if (normalStacks) { 700 startLayer = adjustNormalStackLayer(stack, startLayer); 701 } 702 } 703 return startLayer; 704 } 705 706 @Override getAppAnimationLayer(@nimationLayer int animationLayer)707 SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) { 708 switch (animationLayer) { 709 case ANIMATION_LAYER_BOOSTED: 710 return mBoostedAppAnimationLayer; 711 case ANIMATION_LAYER_HOME: 712 return mHomeAppAnimationLayer; 713 case ANIMATION_LAYER_STANDARD: 714 default: 715 return mAppAnimationLayer; 716 } 717 } 718 getSplitScreenDividerAnchor()719 SurfaceControl getSplitScreenDividerAnchor() { 720 return mSplitScreenDividerAnchor; 721 } 722 723 @Override onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent)724 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) { 725 if (getParent() != null) { 726 super.onParentChanged(newParent, oldParent, () -> { 727 mAppAnimationLayer = makeChildSurface(null) 728 .setName("animationLayer") 729 .setCallsite("TaskDisplayArea.onParentChanged") 730 .build(); 731 mBoostedAppAnimationLayer = makeChildSurface(null) 732 .setName("boostedAnimationLayer") 733 .setCallsite("TaskDisplayArea.onParentChanged") 734 .build(); 735 mHomeAppAnimationLayer = makeChildSurface(null) 736 .setName("homeAnimationLayer") 737 .setCallsite("TaskDisplayArea.onParentChanged") 738 .build(); 739 mSplitScreenDividerAnchor = makeChildSurface(null) 740 .setName("splitScreenDividerAnchor") 741 .setCallsite("TaskDisplayArea.onParentChanged") 742 .build(); 743 getSyncTransaction() 744 .show(mAppAnimationLayer) 745 .show(mBoostedAppAnimationLayer) 746 .show(mHomeAppAnimationLayer) 747 .show(mSplitScreenDividerAnchor); 748 }); 749 } else { 750 super.onParentChanged(newParent, oldParent); 751 mWmService.mTransactionFactory.get() 752 .remove(mAppAnimationLayer) 753 .remove(mBoostedAppAnimationLayer) 754 .remove(mHomeAppAnimationLayer) 755 .remove(mSplitScreenDividerAnchor) 756 .apply(); 757 mAppAnimationLayer = null; 758 mBoostedAppAnimationLayer = null; 759 mHomeAppAnimationLayer = null; 760 mSplitScreenDividerAnchor = null; 761 } 762 } 763 onStackRemoved(ActivityStack stack)764 void onStackRemoved(ActivityStack stack) { 765 if (ActivityTaskManagerDebugConfig.DEBUG_STACK) { 766 Slog.v(TAG_STACK, "removeStack: detaching " + stack + " from displayId=" 767 + mDisplayContent.mDisplayId); 768 } 769 if (mPreferredTopFocusableStack == stack) { 770 mPreferredTopFocusableStack = null; 771 } 772 mDisplayContent.releaseSelfIfNeeded(); 773 onStackOrderChanged(stack); 774 } 775 resetPreferredTopFocusableStackIfBelow(Task task)776 void resetPreferredTopFocusableStackIfBelow(Task task) { 777 if (mPreferredTopFocusableStack != null 778 && mPreferredTopFocusableStack.compareTo(task) < 0) { 779 mPreferredTopFocusableStack = null; 780 } 781 } 782 positionStackAt(int position, ActivityStack child, boolean includingParents)783 void positionStackAt(int position, ActivityStack child, boolean includingParents) { 784 positionChildAt(position, child, includingParents); 785 mDisplayContent.layoutAndAssignWindowLayersIfNeeded(); 786 } 787 positionStackAtTop(ActivityStack stack, boolean includingParents)788 void positionStackAtTop(ActivityStack stack, boolean includingParents) { 789 positionStackAtTop(stack, includingParents, null /* updateLastFocusedStackReason */); 790 } 791 positionStackAtTop(ActivityStack stack, boolean includingParents, String updateLastFocusedStackReason)792 void positionStackAtTop(ActivityStack stack, boolean includingParents, 793 String updateLastFocusedStackReason) { 794 positionStackAt(stack, getStackCount(), includingParents, 795 updateLastFocusedStackReason); 796 } 797 positionStackAtBottom(ActivityStack stack)798 void positionStackAtBottom(ActivityStack stack) { 799 positionStackAtBottom(stack, null /* updateLastFocusedStackReason */); 800 } 801 positionStackAtBottom(ActivityStack stack, String updateLastFocusedStackReason)802 void positionStackAtBottom(ActivityStack stack, String updateLastFocusedStackReason) { 803 positionStackAt(stack, 0, false /* includingParents */, 804 updateLastFocusedStackReason); 805 } 806 positionStackAt(ActivityStack stack, int position)807 void positionStackAt(ActivityStack stack, int position) { 808 positionStackAt(stack, position, false /* includingParents */, 809 null /* updateLastFocusedStackReason */); 810 } 811 positionStackAt(ActivityStack stack, int position, boolean includingParents, String updateLastFocusedStackReason)812 void positionStackAt(ActivityStack stack, int position, boolean includingParents, 813 String updateLastFocusedStackReason) { 814 // TODO: Keep in sync with WindowContainer.positionChildAt(), once we change that to adjust 815 // the position internally, also update the logic here 816 final ActivityStack prevFocusedStack = updateLastFocusedStackReason != null 817 ? getFocusedStack() : null; 818 final boolean wasContained = mChildren.contains(stack); 819 if (mDisplayContent.mSingleTaskInstance && getStackCount() == 1 && !wasContained) { 820 throw new IllegalStateException( 821 "positionStackAt: Can only have one task on display=" + this); 822 } 823 824 // Since positionChildAt() is called during the creation process of pinned stacks, 825 // ActivityStack#getStack() can be null. 826 positionStackAt(position, stack, includingParents); 827 828 if (updateLastFocusedStackReason != null) { 829 final ActivityStack currentFocusedStack = getFocusedStack(); 830 if (currentFocusedStack != prevFocusedStack) { 831 mLastFocusedStack = prevFocusedStack; 832 EventLogTags.writeWmFocusedStack(mRootWindowContainer.mCurrentUser, 833 mDisplayContent.mDisplayId, 834 currentFocusedStack == null ? -1 : currentFocusedStack.getRootTaskId(), 835 mLastFocusedStack == null ? -1 : mLastFocusedStack.getRootTaskId(), 836 updateLastFocusedStackReason); 837 } 838 } 839 840 onStackOrderChanged(stack); 841 } 842 843 /** 844 * Moves/reparents `task` to the back of whatever container the home stack is in. This is for 845 * when we just want to move a task to "the back" vs. a specific place. The primary use-case 846 * is to make sure that moved-to-back apps go into secondary split when in split-screen mode. 847 */ positionTaskBehindHome(ActivityStack task)848 void positionTaskBehindHome(ActivityStack task) { 849 final ActivityStack home = getOrCreateRootHomeTask(); 850 final WindowContainer homeParent = home.getParent(); 851 final Task homeParentTask = homeParent != null ? homeParent.asTask() : null; 852 if (homeParentTask == null) { 853 // reparent throws if parent didn't change... 854 if (task.getParent() == this) { 855 positionStackAtBottom(task); 856 } else { 857 task.reparent(this, false /* onTop */); 858 } 859 } else if (homeParentTask == task.getParent()) { 860 // Apparently reparent early-outs if same stack, so we have to explicitly reorder. 861 ((ActivityStack) homeParentTask).positionChildAtBottom(task); 862 } else { 863 task.reparent((ActivityStack) homeParentTask, false /* toTop */, 864 Task.REPARENT_LEAVE_STACK_IN_PLACE, false /* animate */, 865 false /* deferResume */, "positionTaskBehindHome"); 866 } 867 } 868 getStack(int rootTaskId)869 ActivityStack getStack(int rootTaskId) { 870 for (int i = getStackCount() - 1; i >= 0; --i) { 871 final ActivityStack stack = getStackAt(i); 872 if (stack.getRootTaskId() == rootTaskId) { 873 return stack; 874 } 875 } 876 return null; 877 } 878 879 /** 880 * Returns an existing stack compatible with the windowing mode and activity type or creates one 881 * if a compatible stack doesn't exist. 882 * @see #getOrCreateStack(int, int, boolean, Intent, Task) 883 */ getOrCreateStack(int windowingMode, int activityType, boolean onTop)884 ActivityStack getOrCreateStack(int windowingMode, int activityType, boolean onTop) { 885 return getOrCreateStack(windowingMode, activityType, onTop, null /* intent */, 886 null /* candidateTask */); 887 } 888 889 /** 890 * When two level tasks are required for given windowing mode and activity type, returns an 891 * existing compatible root task or creates a new one. 892 * For one level task, the candidate task would be reused to also be the root task or create 893 * a new root task if no candidate task. 894 * @see #getStack(int, int) 895 * @see #createStack(int, int, boolean) 896 */ getOrCreateStack(int windowingMode, int activityType, boolean onTop, Intent intent, Task candidateTask)897 ActivityStack getOrCreateStack(int windowingMode, int activityType, boolean onTop, 898 Intent intent, Task candidateTask) { 899 // Need to pass in a determined windowing mode to see if a new stack should be created, 900 // so use its parent's windowing mode if it is undefined. 901 if (!alwaysCreateStack( 902 windowingMode != WINDOWING_MODE_UNDEFINED ? windowingMode : getWindowingMode(), 903 activityType)) { 904 ActivityStack stack = getStack(windowingMode, activityType); 905 if (stack != null) { 906 return stack; 907 } 908 } else if (candidateTask != null) { 909 final ActivityStack stack = (ActivityStack) candidateTask; 910 final int position = onTop ? POSITION_TOP : POSITION_BOTTOM; 911 Task launchRootTask = updateLaunchRootTask(windowingMode); 912 913 if (launchRootTask != null) { 914 if (stack.getParent() == null) { 915 launchRootTask.addChild(stack, position); 916 } else if (stack.getParent() != launchRootTask) { 917 stack.reparent(launchRootTask, position); 918 } 919 } else if (stack.getDisplayArea() != this || !stack.isRootTask()) { 920 if (stack.getParent() == null) { 921 addChild(stack, position); 922 } else { 923 stack.reparent(this, onTop); 924 } 925 } 926 // Update windowing mode if necessary, e.g. moving a pinned task to fullscreen. 927 if (candidateTask.getWindowingMode() != windowingMode) { 928 candidateTask.setWindowingMode(windowingMode); 929 } 930 return stack; 931 } 932 return createStack(windowingMode, activityType, onTop, null /*info*/, intent, 933 false /* createdByOrganizer */); 934 } 935 936 /** 937 * Returns an existing stack compatible with the input params or creates one 938 * if a compatible stack doesn't exist. 939 * @see #getOrCreateStack(int, int, boolean) 940 */ getOrCreateStack(@ullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable Task candidateTask, int activityType, boolean onTop)941 ActivityStack getOrCreateStack(@Nullable ActivityRecord r, 942 @Nullable ActivityOptions options, @Nullable Task candidateTask, int activityType, 943 boolean onTop) { 944 // First preference is the windowing mode in the activity options if set. 945 int windowingMode = (options != null) 946 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED; 947 // Validate that our desired windowingMode will work under the current conditions. 948 // UNDEFINED windowing mode is a valid result and means that the new stack will inherit 949 // it's display's windowing mode. 950 windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType); 951 return getOrCreateStack(windowingMode, activityType, onTop, null /* intent */, 952 candidateTask); 953 } 954 955 @VisibleForTesting getNextStackId()956 int getNextStackId() { 957 return mAtmService.mStackSupervisor.getNextTaskIdForUser(); 958 } 959 createStack(int windowingMode, int activityType, boolean onTop)960 ActivityStack createStack(int windowingMode, int activityType, boolean onTop) { 961 return createStack(windowingMode, activityType, onTop, null /* info */, null /* intent */, 962 false /* createdByOrganizer */); 963 } 964 965 /** 966 * Creates a stack matching the input windowing mode and activity type on this display. 967 * @param windowingMode The windowing mode the stack should be created in. If 968 * {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will 969 * inherit its parent's windowing mode. 970 * @param activityType The activityType the stack should be created in. If 971 * {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will 972 * be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}. 973 * @param onTop If true the stack will be created at the top of the display, else at the bottom. 974 * @param info The started activity info. 975 * @param intent The intent that started this task. 976 * @param createdByOrganizer @{code true} if this is created by task organizer, @{code false} 977 * otherwise. 978 * @return The newly created stack. 979 */ createStack(int windowingMode, int activityType, boolean onTop, ActivityInfo info, Intent intent, boolean createdByOrganizer)980 ActivityStack createStack(int windowingMode, int activityType, boolean onTop, ActivityInfo info, 981 Intent intent, boolean createdByOrganizer) { 982 if (mDisplayContent.mSingleTaskInstance && getStackCount() > 0) { 983 // Create stack on default display instead since this display can only contain 1 stack. 984 // TODO: Kinda a hack, but better that having the decision at each call point. Hoping 985 // this goes away once ActivityView is no longer using virtual displays. 986 return mRootWindowContainer.getDefaultTaskDisplayArea().createStack( 987 windowingMode, activityType, onTop, info, intent, createdByOrganizer); 988 } 989 990 if (activityType == ACTIVITY_TYPE_UNDEFINED && !createdByOrganizer) { 991 // Can't have an undefined stack type yet...so re-map to standard. Anyone that wants 992 // anything else should be passing it in anyways...except for the task organizer. 993 activityType = ACTIVITY_TYPE_STANDARD; 994 } 995 996 if (activityType != ACTIVITY_TYPE_STANDARD && activityType != ACTIVITY_TYPE_UNDEFINED) { 997 // For now there can be only one stack of a particular non-standard activity type on a 998 // display. So, get that ignoring whatever windowing mode it is currently in. 999 ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType); 1000 if (stack != null) { 1001 throw new IllegalArgumentException("Stack=" + stack + " of activityType=" 1002 + activityType + " already on display=" + this + ". Can't have multiple."); 1003 } 1004 } 1005 1006 if (!isWindowingModeSupported(windowingMode, mAtmService.mSupportsMultiWindow, 1007 mAtmService.mSupportsSplitScreenMultiWindow, 1008 mAtmService.mSupportsFreeformWindowManagement, 1009 mAtmService.mSupportsPictureInPicture, activityType)) { 1010 throw new IllegalArgumentException("Can't create stack for unsupported windowingMode=" 1011 + windowingMode); 1012 } 1013 1014 if (windowingMode == WINDOWING_MODE_PINNED && getRootPinnedTask() != null) { 1015 // Only 1 stack can be PINNED at a time, so dismiss the existing one 1016 getRootPinnedTask().dismissPip(); 1017 } 1018 1019 final int stackId = getNextStackId(); 1020 return createStackUnchecked(windowingMode, activityType, stackId, onTop, info, intent, 1021 createdByOrganizer); 1022 } 1023 1024 /** @return the root task to create the next task in. */ updateLaunchRootTask(int windowingMode)1025 private Task updateLaunchRootTask(int windowingMode) { 1026 if (!isSplitScreenWindowingMode(windowingMode)) { 1027 // Only split-screen windowing modes can do this currently... 1028 return null; 1029 } 1030 for (int i = getStackCount() - 1; i >= 0; --i) { 1031 final Task t = getStackAt(i); 1032 if (!t.mCreatedByOrganizer || t.getRequestedOverrideWindowingMode() != windowingMode) { 1033 continue; 1034 } 1035 // If not already set, pick a launch root which is not the one we are launching into. 1036 if (mLaunchRootTask == null) { 1037 for (int j = 0, n = getStackCount(); j < n; ++j) { 1038 final Task tt = getStackAt(j); 1039 if (tt.mCreatedByOrganizer && tt != t) { 1040 mLaunchRootTask = tt; 1041 break; 1042 } 1043 } 1044 } 1045 return t; 1046 } 1047 return mLaunchRootTask; 1048 } 1049 1050 @VisibleForTesting createStackUnchecked(int windowingMode, int activityType, int stackId, boolean onTop, ActivityInfo info, Intent intent, boolean createdByOrganizer)1051 ActivityStack createStackUnchecked(int windowingMode, int activityType, int stackId, 1052 boolean onTop, ActivityInfo info, Intent intent, boolean createdByOrganizer) { 1053 if (windowingMode == WINDOWING_MODE_PINNED && activityType != ACTIVITY_TYPE_STANDARD) { 1054 throw new IllegalArgumentException("Stack with windowing mode cannot with non standard " 1055 + "activity type."); 1056 } 1057 if (info == null) { 1058 info = new ActivityInfo(); 1059 info.applicationInfo = new ApplicationInfo(); 1060 } 1061 1062 // Task created by organizer are added as root. 1063 Task launchRootTask = createdByOrganizer ? null : updateLaunchRootTask(windowingMode); 1064 if (launchRootTask != null) { 1065 // Since this stack will be put into a root task, its windowingMode will be inherited. 1066 windowingMode = WINDOWING_MODE_UNDEFINED; 1067 } 1068 1069 final ActivityStack stack = new ActivityStack(mAtmService, stackId, activityType, 1070 info, intent, createdByOrganizer); 1071 if (launchRootTask != null) { 1072 launchRootTask.addChild(stack, onTop ? POSITION_TOP : POSITION_BOTTOM); 1073 if (onTop) { 1074 positionStackAtTop((ActivityStack) launchRootTask, false /* includingParents */); 1075 } 1076 } else { 1077 addChild(stack, onTop ? POSITION_TOP : POSITION_BOTTOM); 1078 stack.setWindowingMode(windowingMode, true /* creating */); 1079 } 1080 return stack; 1081 } 1082 1083 /** 1084 * Get the preferred focusable stack in priority. If the preferred stack does not exist, find a 1085 * focusable and visible stack from the top of stacks in this display. 1086 */ getFocusedStack()1087 ActivityStack getFocusedStack() { 1088 if (mPreferredTopFocusableStack != null) { 1089 return mPreferredTopFocusableStack; 1090 } 1091 1092 for (int i = getStackCount() - 1; i >= 0; --i) { 1093 final ActivityStack stack = getStackAt(i); 1094 if (stack.isFocusableAndVisible()) { 1095 return stack; 1096 } 1097 } 1098 1099 return null; 1100 } 1101 getNextFocusableStack(ActivityStack currentFocus, boolean ignoreCurrent)1102 ActivityStack getNextFocusableStack(ActivityStack currentFocus, boolean ignoreCurrent) { 1103 final int currentWindowingMode = currentFocus != null 1104 ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED; 1105 1106 ActivityStack candidate = null; 1107 for (int i = getStackCount() - 1; i >= 0; --i) { 1108 final ActivityStack stack = getStackAt(i); 1109 if (ignoreCurrent && stack == currentFocus) { 1110 continue; 1111 } 1112 if (!stack.isFocusableAndVisible()) { 1113 continue; 1114 } 1115 1116 if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY 1117 && candidate == null && stack.inSplitScreenPrimaryWindowingMode()) { 1118 // If the currently focused stack is in split-screen secondary we save off the 1119 // top primary split-screen stack as a candidate for focus because we might 1120 // prefer focus to move to an other stack to avoid primary split-screen stack 1121 // overlapping with a fullscreen stack when a fullscreen stack is higher in z 1122 // than the next split-screen stack. Assistant stack, I am looking at you... 1123 // We only move the focus to the primary-split screen stack if there isn't a 1124 // better alternative. 1125 candidate = stack; 1126 continue; 1127 } 1128 if (candidate != null && stack.inSplitScreenSecondaryWindowingMode()) { 1129 // Use the candidate stack since we are now at the secondary split-screen. 1130 return candidate; 1131 } 1132 return stack; 1133 } 1134 return candidate; 1135 } 1136 getFocusedActivity()1137 ActivityRecord getFocusedActivity() { 1138 final ActivityStack focusedStack = getFocusedStack(); 1139 if (focusedStack == null) { 1140 return null; 1141 } 1142 // TODO(b/111541062): Move this into ActivityStack#getResumedActivity() 1143 // Check if the focused stack has the resumed activity 1144 ActivityRecord resumedActivity = focusedStack.getResumedActivity(); 1145 if (resumedActivity == null || resumedActivity.app == null) { 1146 // If there is no registered resumed activity in the stack or it is not running - 1147 // try to use previously resumed one. 1148 resumedActivity = focusedStack.mPausingActivity; 1149 if (resumedActivity == null || resumedActivity.app == null) { 1150 // If previously resumed activity doesn't work either - find the topmost running 1151 // activity that can be focused. 1152 resumedActivity = focusedStack.topRunningActivity(true /* focusableOnly */); 1153 } 1154 } 1155 return resumedActivity; 1156 } 1157 getLastFocusedStack()1158 ActivityStack getLastFocusedStack() { 1159 return mLastFocusedStack; 1160 } 1161 allResumedActivitiesComplete()1162 boolean allResumedActivitiesComplete() { 1163 for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) { 1164 final ActivityRecord r = getStackAt(stackNdx).getResumedActivity(); 1165 if (r != null && !r.isState(RESUMED)) { 1166 return false; 1167 } 1168 } 1169 final ActivityStack currentFocusedStack = getFocusedStack(); 1170 if (ActivityTaskManagerDebugConfig.DEBUG_STACK) { 1171 Slog.d(TAG_STACK, "allResumedActivitiesComplete: mLastFocusedStack changing from=" 1172 + mLastFocusedStack + " to=" + currentFocusedStack); 1173 } 1174 mLastFocusedStack = currentFocusedStack; 1175 return true; 1176 } 1177 1178 /** 1179 * Pause all activities in either all of the stacks or just the back stacks. This is done before 1180 * resuming a new activity and to make sure that previously active activities are 1181 * paused in stacks that are no longer visible or in pinned windowing mode. This does not 1182 * pause activities in visible stacks, so if an activity is launched within the same stack/task, 1183 * then we should explicitly pause that stack's top activity. 1184 * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving(). 1185 * @param resuming The resuming activity. 1186 * @return {@code true} if any activity was paused as a result of this call. 1187 */ pauseBackStacks(boolean userLeaving, ActivityRecord resuming)1188 boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming) { 1189 boolean someActivityPaused = false; 1190 for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) { 1191 final ActivityStack stack = getStackAt(stackNdx); 1192 final ActivityRecord resumedActivity = stack.getResumedActivity(); 1193 if (resumedActivity != null 1194 && (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE 1195 || !stack.isTopActivityFocusable())) { 1196 if (DEBUG_STATES) { 1197 Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack 1198 + " mResumedActivity=" + resumedActivity); 1199 } 1200 someActivityPaused |= stack.startPausingLocked(userLeaving, false /* uiSleeping*/, 1201 resuming); 1202 } 1203 } 1204 return someActivityPaused; 1205 } 1206 1207 /** 1208 * Find task for putting the Activity in. 1209 */ findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplayArea, RootWindowContainer.FindTaskResult result)1210 void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplayArea, 1211 RootWindowContainer.FindTaskResult result) { 1212 mTmpFindTaskResult.clear(); 1213 for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) { 1214 final ActivityStack stack = getStackAt(stackNdx); 1215 if (!r.hasCompatibleActivityType(stack) && stack.isLeafTask()) { 1216 if (DEBUG_TASKS) { 1217 Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) " + stack); 1218 } 1219 continue; 1220 } 1221 1222 mTmpFindTaskResult.process(r, stack); 1223 // It is possible to have tasks in multiple stacks with the same root affinity, so 1224 // we should keep looking after finding an affinity match to see if there is a 1225 // better match in another stack. Also, task affinity isn't a good enough reason 1226 // to target a display which isn't the source of the intent, so skip any affinity 1227 // matches not on the specified display. 1228 if (mTmpFindTaskResult.mRecord != null) { 1229 if (mTmpFindTaskResult.mIdealMatch) { 1230 result.setTo(mTmpFindTaskResult); 1231 return; 1232 } else if (isPreferredDisplayArea) { 1233 // Note: since the traversing through the stacks is top down, the floating 1234 // tasks should always have lower priority than any affinity-matching tasks 1235 // in the fullscreen stacks 1236 result.setTo(mTmpFindTaskResult); 1237 } 1238 } 1239 } 1240 } 1241 1242 /** 1243 * Removes stacks in the input windowing modes from the system if they are of activity type 1244 * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED 1245 */ removeStacksInWindowingModes(int... windowingModes)1246 void removeStacksInWindowingModes(int... windowingModes) { 1247 if (windowingModes == null || windowingModes.length == 0) { 1248 return; 1249 } 1250 1251 // Collect the stacks that are necessary to be removed instead of performing the removal 1252 // by looping mStacks, so that we don't miss any stacks after the stack size changed or 1253 // stacks reordered. 1254 final ArrayList<ActivityStack> stacks = new ArrayList<>(); 1255 for (int j = windowingModes.length - 1; j >= 0; --j) { 1256 final int windowingMode = windowingModes[j]; 1257 for (int i = getStackCount() - 1; i >= 0; --i) { 1258 final ActivityStack stack = getStackAt(i); 1259 if (!stack.isActivityTypeStandardOrUndefined()) { 1260 continue; 1261 } 1262 if (stack.getWindowingMode() != windowingMode) { 1263 continue; 1264 } 1265 stacks.add(stack); 1266 } 1267 } 1268 1269 for (int i = stacks.size() - 1; i >= 0; --i) { 1270 mRootWindowContainer.mStackSupervisor.removeStack(stacks.get(i)); 1271 } 1272 } 1273 removeStacksWithActivityTypes(int... activityTypes)1274 void removeStacksWithActivityTypes(int... activityTypes) { 1275 if (activityTypes == null || activityTypes.length == 0) { 1276 return; 1277 } 1278 1279 // Collect the stacks that are necessary to be removed instead of performing the removal 1280 // by looping mStacks, so that we don't miss any stacks after the stack size changed or 1281 // stacks reordered. 1282 final ArrayList<ActivityStack> stacks = new ArrayList<>(); 1283 for (int j = activityTypes.length - 1; j >= 0; --j) { 1284 final int activityType = activityTypes[j]; 1285 for (int i = getStackCount() - 1; i >= 0; --i) { 1286 final ActivityStack stack = getStackAt(i); 1287 // Collect the root tasks that are currently being organized. 1288 if (stack.mCreatedByOrganizer) { 1289 for (int k = stack.getChildCount() - 1; k >= 0; --k) { 1290 final ActivityStack childStack = (ActivityStack) stack.getChildAt(k); 1291 if (childStack.getActivityType() == activityType) { 1292 stacks.add(childStack); 1293 } 1294 } 1295 } else if (stack.getActivityType() == activityType) { 1296 stacks.add(stack); 1297 } 1298 } 1299 } 1300 1301 for (int i = stacks.size() - 1; i >= 0; --i) { 1302 mRootWindowContainer.mStackSupervisor.removeStack(stacks.get(i)); 1303 } 1304 } 1305 onSplitScreenModeDismissed()1306 void onSplitScreenModeDismissed() { 1307 onSplitScreenModeDismissed(null /* toTop */); 1308 } 1309 onSplitScreenModeDismissed(ActivityStack toTop)1310 void onSplitScreenModeDismissed(ActivityStack toTop) { 1311 mAtmService.deferWindowLayout(); 1312 try { 1313 mLaunchRootTask = null; 1314 moveSplitScreenTasksToFullScreen(); 1315 } finally { 1316 final ActivityStack topFullscreenStack = toTop != null 1317 ? toTop : getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN); 1318 final ActivityStack homeStack = getOrCreateRootHomeTask(); 1319 if (homeStack != null && ((topFullscreenStack != null && !isTopStack(homeStack)) 1320 || toTop != null)) { 1321 // Whenever split-screen is dismissed we want the home stack directly behind the 1322 // current top fullscreen stack so it shows up when the top stack is finished. 1323 // Or, if the caller specified a stack to be on top after split-screen is dismissed. 1324 // TODO: Would be better to use ActivityDisplay.positionChildAt() for this, however 1325 // ActivityDisplay doesn't have a direct controller to WM side yet. We can switch 1326 // once we have that. 1327 homeStack.moveToFront("onSplitScreenModeDismissed"); 1328 topFullscreenStack.moveToFront("onSplitScreenModeDismissed"); 1329 } 1330 mAtmService.continueWindowLayout(); 1331 } 1332 } 1333 moveSplitScreenTasksToFullScreen()1334 private void moveSplitScreenTasksToFullScreen() { 1335 final WindowContainerTransaction wct = new WindowContainerTransaction(); 1336 mTmpTasks.clear(); 1337 forAllTasks(task -> { 1338 if (task.mCreatedByOrganizer && task.inSplitScreenWindowingMode() && task.hasChild()) { 1339 mTmpTasks.add(task); 1340 } 1341 }); 1342 1343 for (int i = mTmpTasks.size() - 1; i >= 0; i--) { 1344 final Task root = mTmpTasks.get(i); 1345 for (int j = 0; j < root.getChildCount(); j++) { 1346 wct.reparent(root.getChildAt(j).mRemoteToken.toWindowContainerToken(), 1347 null, true /* toTop */); 1348 } 1349 } 1350 mAtmService.mWindowOrganizerController.applyTransaction(wct); 1351 } 1352 1353 /** 1354 * Returns true if the {@param windowingMode} is supported based on other parameters passed in. 1355 * @param windowingMode The windowing mode we are checking support for. 1356 * @param supportsMultiWindow If we should consider support for multi-window mode in general. 1357 * @param supportsSplitScreen If we should consider support for split-screen multi-window. 1358 * @param supportsFreeform If we should consider support for freeform multi-window. 1359 * @param supportsPip If we should consider support for picture-in-picture mutli-window. 1360 * @param activityType The activity type under consideration. 1361 * @return true if the windowing mode is supported. 1362 */ isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow, boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip, int activityType)1363 private boolean isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow, 1364 boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip, 1365 int activityType) { 1366 1367 if (windowingMode == WINDOWING_MODE_UNDEFINED 1368 || windowingMode == WINDOWING_MODE_FULLSCREEN) { 1369 return true; 1370 } 1371 if (!supportsMultiWindow) { 1372 return false; 1373 } 1374 1375 if (windowingMode == WINDOWING_MODE_MULTI_WINDOW) { 1376 return true; 1377 } 1378 1379 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY 1380 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { 1381 return supportsSplitScreen 1382 && WindowConfiguration.supportSplitScreenWindowingMode(activityType); 1383 } 1384 1385 if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) { 1386 return false; 1387 } 1388 1389 if (!supportsPip && windowingMode == WINDOWING_MODE_PINNED) { 1390 return false; 1391 } 1392 return true; 1393 } 1394 1395 /** 1396 * Resolves the windowing mode that an {@link ActivityRecord} would be in if started on this 1397 * display with the provided parameters. 1398 * 1399 * @param r The ActivityRecord in question. 1400 * @param options Options to start with. 1401 * @param task The task within-which the activity would start. 1402 * @param activityType The type of activity to start. 1403 * @return The resolved (not UNDEFINED) windowing-mode that the activity would be in. 1404 */ resolveWindowingMode(@ullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable Task task, int activityType)1405 int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options, 1406 @Nullable Task task, int activityType) { 1407 1408 // First preference if the windowing mode in the activity options if set. 1409 int windowingMode = (options != null) 1410 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED; 1411 1412 // If windowing mode is unset, then next preference is the candidate task, then the 1413 // activity record. 1414 if (windowingMode == WINDOWING_MODE_UNDEFINED) { 1415 if (task != null) { 1416 windowingMode = task.getWindowingMode(); 1417 } 1418 if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) { 1419 windowingMode = r.getWindowingMode(); 1420 } 1421 if (windowingMode == WINDOWING_MODE_UNDEFINED) { 1422 // Use the display's windowing mode. 1423 windowingMode = getWindowingMode(); 1424 } 1425 } 1426 windowingMode = validateWindowingMode(windowingMode, r, task, activityType); 1427 return windowingMode != WINDOWING_MODE_UNDEFINED 1428 ? windowingMode : WINDOWING_MODE_FULLSCREEN; 1429 } 1430 1431 /** 1432 * Check if the requested windowing-mode is appropriate for the specified task and/or activity 1433 * on this display. 1434 * 1435 * @param windowingMode The windowing-mode to validate. 1436 * @param r The {@link ActivityRecord} to check against. 1437 * @param task The {@link Task} to check against. 1438 * @param activityType An activity type. 1439 * @return {@code true} if windowingMode is valid, {@code false} otherwise. 1440 */ isValidWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task, int activityType)1441 boolean isValidWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task, 1442 int activityType) { 1443 // Make sure the windowing mode we are trying to use makes sense for what is supported. 1444 boolean supportsMultiWindow = mAtmService.mSupportsMultiWindow; 1445 boolean supportsSplitScreen = mAtmService.mSupportsSplitScreenMultiWindow; 1446 boolean supportsFreeform = mAtmService.mSupportsFreeformWindowManagement; 1447 boolean supportsPip = mAtmService.mSupportsPictureInPicture; 1448 if (supportsMultiWindow) { 1449 if (task != null) { 1450 supportsMultiWindow = task.isResizeable(); 1451 supportsSplitScreen = task.supportsSplitScreenWindowingMode(); 1452 // TODO: Do we need to check for freeform and Pip support here? 1453 } else if (r != null) { 1454 supportsMultiWindow = r.isResizeable(); 1455 supportsSplitScreen = r.supportsSplitScreenWindowingMode(); 1456 supportsFreeform = r.supportsFreeform(); 1457 supportsPip = r.supportsPictureInPicture(); 1458 } 1459 } 1460 1461 return windowingMode != WINDOWING_MODE_UNDEFINED 1462 && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen, 1463 supportsFreeform, supportsPip, activityType); 1464 } 1465 1466 /** 1467 * Check that the requested windowing-mode is appropriate for the specified task and/or activity 1468 * on this display. 1469 * 1470 * @param windowingMode The windowing-mode to validate. 1471 * @param r The {@link ActivityRecord} to check against. 1472 * @param task The {@link Task} to check against. 1473 * @param activityType An activity type. 1474 * @return The provided windowingMode or the closest valid mode which is appropriate. 1475 */ validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task, int activityType)1476 int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task, 1477 int activityType) { 1478 final boolean inSplitScreenMode = isSplitScreenModeActivated(); 1479 if (!inSplitScreenMode && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { 1480 // Switch to the display's windowing mode if we are not in split-screen mode and we are 1481 // trying to launch in split-screen secondary. 1482 windowingMode = WINDOWING_MODE_UNDEFINED; 1483 } else if (inSplitScreenMode && windowingMode == WINDOWING_MODE_UNDEFINED) { 1484 windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; 1485 } 1486 if (!isValidWindowingMode(windowingMode, r, task, activityType)) { 1487 return WINDOWING_MODE_UNDEFINED; 1488 } 1489 return windowingMode; 1490 } 1491 isTopStack(ActivityStack stack)1492 boolean isTopStack(ActivityStack stack) { 1493 return stack == getTopStack(); 1494 } 1495 isTopNotPinnedStack(ActivityStack stack)1496 boolean isTopNotPinnedStack(ActivityStack stack) { 1497 for (int i = getStackCount() - 1; i >= 0; --i) { 1498 final ActivityStack current = getStackAt(i); 1499 if (!current.inPinnedWindowingMode()) { 1500 return current == stack; 1501 } 1502 } 1503 return false; 1504 } 1505 topRunningActivity()1506 ActivityRecord topRunningActivity() { 1507 return topRunningActivity(false /* considerKeyguardState */); 1508 } 1509 1510 /** 1511 * Returns the top running activity in the focused stack. In the case the focused stack has no 1512 * such activity, the next focusable stack on this display is returned. 1513 * 1514 * @param considerKeyguardState Indicates whether the locked state should be considered. if 1515 * {@code true} and the keyguard is locked, only activities that 1516 * can be shown on top of the keyguard will be considered. 1517 * @return The top running activity. {@code null} if none is available. 1518 */ topRunningActivity(boolean considerKeyguardState)1519 ActivityRecord topRunningActivity(boolean considerKeyguardState) { 1520 ActivityRecord topRunning = null; 1521 final ActivityStack focusedStack = getFocusedStack(); 1522 if (focusedStack != null) { 1523 topRunning = focusedStack.topRunningActivity(); 1524 } 1525 1526 // Look in other focusable stacks. 1527 if (topRunning == null) { 1528 for (int i = getStackCount() - 1; i >= 0; --i) { 1529 final ActivityStack stack = getStackAt(i); 1530 // Only consider focusable stacks other than the current focused one. 1531 if (stack == focusedStack || !stack.isTopActivityFocusable()) { 1532 continue; 1533 } 1534 topRunning = stack.topRunningActivity(); 1535 if (topRunning != null) { 1536 break; 1537 } 1538 } 1539 } 1540 1541 // This activity can be considered the top running activity if we are not considering 1542 // the locked state, the keyguard isn't locked, or we can show when locked. 1543 if (topRunning != null && considerKeyguardState 1544 && mRootWindowContainer.mStackSupervisor.getKeyguardController() 1545 .isKeyguardLocked() 1546 && !topRunning.canShowWhenLocked()) { 1547 return null; 1548 } 1549 1550 return topRunning; 1551 } 1552 getStackCount()1553 protected int getStackCount() { 1554 return mChildren.size(); 1555 } 1556 getStackAt(int index)1557 protected ActivityStack getStackAt(int index) { 1558 return mChildren.get(index); 1559 } 1560 1561 @Nullable getOrCreateRootHomeTask()1562 ActivityStack getOrCreateRootHomeTask() { 1563 return getOrCreateRootHomeTask(false /* onTop */); 1564 } 1565 1566 /** 1567 * Returns the existing home stack or creates and returns a new one if it should exist for the 1568 * display. 1569 * @param onTop Only be used when there is no existing home stack. If true the home stack will 1570 * be created at the top of the display, else at the bottom. 1571 */ 1572 @Nullable getOrCreateRootHomeTask(boolean onTop)1573 ActivityStack getOrCreateRootHomeTask(boolean onTop) { 1574 ActivityStack homeTask = getRootHomeTask(); 1575 if (homeTask == null && mDisplayContent.supportsSystemDecorations()) { 1576 homeTask = createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, onTop); 1577 } 1578 return homeTask; 1579 } 1580 isSplitScreenModeActivated()1581 boolean isSplitScreenModeActivated() { 1582 Task task = getRootSplitScreenPrimaryTask(); 1583 return task != null && task.hasChild(); 1584 } 1585 1586 /** 1587 * Returns the topmost stack on the display that is compatible with the input windowing mode. 1588 * Null is no compatible stack on the display. 1589 */ getTopStackInWindowingMode(int windowingMode)1590 ActivityStack getTopStackInWindowingMode(int windowingMode) { 1591 return getStack(windowingMode, ACTIVITY_TYPE_UNDEFINED); 1592 } 1593 moveHomeStackToFront(String reason)1594 void moveHomeStackToFront(String reason) { 1595 final ActivityStack homeStack = getOrCreateRootHomeTask(); 1596 if (homeStack != null) { 1597 homeStack.moveToFront(reason); 1598 } 1599 } 1600 1601 /** 1602 * Moves the focusable home activity to top. If there is no such activity, the home stack will 1603 * still move to top. 1604 */ moveHomeActivityToTop(String reason)1605 void moveHomeActivityToTop(String reason) { 1606 final ActivityRecord top = getHomeActivity(); 1607 if (top == null) { 1608 moveHomeStackToFront(reason); 1609 return; 1610 } 1611 top.moveFocusableActivityToTop(reason); 1612 } 1613 1614 @Nullable getHomeActivity()1615 ActivityRecord getHomeActivity() { 1616 return getHomeActivityForUser(mRootWindowContainer.mCurrentUser); 1617 } 1618 1619 @Nullable getHomeActivityForUser(int userId)1620 ActivityRecord getHomeActivityForUser(int userId) { 1621 final ActivityStack homeStack = getRootHomeTask(); 1622 if (homeStack == null) { 1623 return null; 1624 } 1625 1626 final PooledPredicate p = PooledLambda.obtainPredicate( 1627 TaskDisplayArea::isHomeActivityForUser, PooledLambda.__(ActivityRecord.class), 1628 userId); 1629 final ActivityRecord r = homeStack.getActivity(p); 1630 p.recycle(); 1631 return r; 1632 } 1633 isHomeActivityForUser(ActivityRecord r, int userId)1634 private static boolean isHomeActivityForUser(ActivityRecord r, int userId) { 1635 return r.isActivityTypeHome() && (userId == UserHandle.USER_ALL || r.mUserId == userId); 1636 } 1637 1638 /** 1639 * Adjusts the {@param stack} behind the last visible stack in the display if necessary. 1640 * Generally used in conjunction with {@link #moveStackBehindStack}. 1641 */ 1642 // TODO(b/151575894): Remove special stack movement methods. moveStackBehindBottomMostVisibleStack(ActivityStack stack)1643 void moveStackBehindBottomMostVisibleStack(ActivityStack stack) { 1644 if (stack.shouldBeVisible(null)) { 1645 // Skip if the stack is already visible 1646 return; 1647 } 1648 1649 final boolean isRootTask = stack.isRootTask(); 1650 if (isRootTask) { 1651 // Move the stack to the bottom to not affect the following visibility checks 1652 positionStackAtBottom(stack); 1653 } else { 1654 stack.getParent().positionChildAt(POSITION_BOTTOM, stack, false /* includingParents */); 1655 } 1656 1657 // Find the next position where the stack should be placed 1658 final int numStacks = isRootTask ? getStackCount() : stack.getParent().getChildCount(); 1659 for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) { 1660 final ActivityStack s = isRootTask ? getStackAt(stackNdx) 1661 : (ActivityStack) stack.getParent().getChildAt(stackNdx); 1662 if (s == stack) { 1663 continue; 1664 } 1665 final int winMode = s.getWindowingMode(); 1666 final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN 1667 || winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; 1668 if (s.shouldBeVisible(null) && isValidWindowingMode) { 1669 // Move the provided stack to behind this stack 1670 final int position = Math.max(0, stackNdx - 1); 1671 if (isRootTask) { 1672 positionStackAt(stack, position); 1673 } else { 1674 stack.getParent().positionChildAt(position, stack, false /*includingParents */); 1675 } 1676 break; 1677 } 1678 } 1679 } 1680 1681 /** 1682 * Moves the {@param stack} behind the given {@param behindStack} if possible. If 1683 * {@param behindStack} is not currently in the display, then then the stack is moved to the 1684 * back. Generally used in conjunction with {@link #moveStackBehindBottomMostVisibleStack}. 1685 */ moveStackBehindStack(ActivityStack stack, ActivityStack behindStack)1686 void moveStackBehindStack(ActivityStack stack, ActivityStack behindStack) { 1687 if (behindStack == null || behindStack == stack) { 1688 return; 1689 } 1690 1691 final WindowContainer parent = stack.getParent(); 1692 if (parent == null || parent != behindStack.getParent()) { 1693 return; 1694 } 1695 1696 // Note that positionChildAt will first remove the given stack before inserting into the 1697 // list, so we need to adjust the insertion index to account for the removed index 1698 // TODO: Remove this logic when WindowContainer.positionChildAt() is updated to adjust the 1699 // position internally 1700 final int stackIndex = parent.mChildren.indexOf(stack); 1701 final int behindStackIndex = parent.mChildren.indexOf(behindStack); 1702 final int insertIndex = stackIndex <= behindStackIndex 1703 ? behindStackIndex - 1 : behindStackIndex; 1704 final int position = Math.max(0, insertIndex); 1705 if (stack.isRootTask()) { 1706 positionStackAt(stack, position); 1707 } else { 1708 parent.positionChildAt(position, stack, false /* includingParents */); 1709 } 1710 } 1711 hasPinnedTask()1712 boolean hasPinnedTask() { 1713 return getRootPinnedTask() != null; 1714 } 1715 1716 /** 1717 * @return the stack currently above the {@param stack}. Can be null if the {@param stack} is 1718 * already top-most. 1719 */ getStackAbove(ActivityStack stack)1720 static ActivityStack getStackAbove(ActivityStack stack) { 1721 final WindowContainer wc = stack.getParent(); 1722 final int index = wc.mChildren.indexOf(stack) + 1; 1723 return (index < wc.mChildren.size()) ? (ActivityStack) wc.mChildren.get(index) : null; 1724 } 1725 1726 /** Returns true if the stack in the windowing mode is visible. */ isStackVisible(int windowingMode)1727 boolean isStackVisible(int windowingMode) { 1728 final ActivityStack stack = getTopStackInWindowingMode(windowingMode); 1729 return stack != null && stack.isVisible(); 1730 } 1731 removeStack(ActivityStack stack)1732 void removeStack(ActivityStack stack) { 1733 removeChild(stack); 1734 } 1735 getDisplayId()1736 int getDisplayId() { 1737 return mDisplayContent.getDisplayId(); 1738 } 1739 isRemoved()1740 boolean isRemoved() { 1741 return mRemoved; 1742 } 1743 1744 /** 1745 * Adds a listener to be notified whenever the stack order in the display changes. Currently 1746 * only used by the {@link RecentsAnimation} to determine whether to interrupt and cancel the 1747 * current animation when the system state changes. 1748 */ registerStackOrderChangedListener(OnStackOrderChangedListener listener)1749 void registerStackOrderChangedListener(OnStackOrderChangedListener listener) { 1750 if (!mStackOrderChangedCallbacks.contains(listener)) { 1751 mStackOrderChangedCallbacks.add(listener); 1752 } 1753 } 1754 1755 /** 1756 * Removes a previously registered stack order change listener. 1757 */ unregisterStackOrderChangedListener(OnStackOrderChangedListener listener)1758 void unregisterStackOrderChangedListener(OnStackOrderChangedListener listener) { 1759 mStackOrderChangedCallbacks.remove(listener); 1760 } 1761 1762 /** 1763 * Notifies of a stack order change 1764 * @param stack The stack which triggered the order change 1765 */ onStackOrderChanged(ActivityStack stack)1766 void onStackOrderChanged(ActivityStack stack) { 1767 for (int i = mStackOrderChangedCallbacks.size() - 1; i >= 0; i--) { 1768 mStackOrderChangedCallbacks.get(i).onStackOrderChanged(stack); 1769 } 1770 } 1771 1772 @Override canCreateRemoteAnimationTarget()1773 boolean canCreateRemoteAnimationTarget() { 1774 return true; 1775 } 1776 1777 /** 1778 * Callback for when the order of the stacks in the display changes. 1779 */ 1780 interface OnStackOrderChangedListener { onStackOrderChanged(ActivityStack stack)1781 void onStackOrderChanged(ActivityStack stack); 1782 } 1783 ensureActivitiesVisible(ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients)1784 void ensureActivitiesVisible(ActivityRecord starting, int configChanges, 1785 boolean preserveWindows, boolean notifyClients) { 1786 mAtmService.mStackSupervisor.beginActivityVisibilityUpdate(); 1787 try { 1788 for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) { 1789 final ActivityStack stack = getStackAt(stackNdx); 1790 stack.ensureActivitiesVisible(starting, configChanges, preserveWindows, 1791 notifyClients); 1792 } 1793 } finally { 1794 mAtmService.mStackSupervisor.endActivityVisibilityUpdate(); 1795 } 1796 } 1797 prepareFreezingTaskBounds()1798 void prepareFreezingTaskBounds() { 1799 for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) { 1800 final ActivityStack stack = getChildAt(stackNdx); 1801 stack.prepareFreezingTaskBounds(); 1802 } 1803 } 1804 1805 /** 1806 * Removes the stacks in the node applying the content removal node from the display. 1807 * @return last reparented stack, or {@code null} if the stacks had to be destroyed. 1808 */ remove()1809 ActivityStack remove() { 1810 mPreferredTopFocusableStack = null; 1811 // TODO(b/153090332): Allow setting content removal mode per task display area 1812 final boolean destroyContentOnRemoval = mDisplayContent.shouldDestroyContentOnRemove(); 1813 final TaskDisplayArea toDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea(); 1814 ActivityStack lastReparentedStack = null; 1815 1816 // Stacks could be reparented from the removed display area to other display area. After 1817 // reparenting the last stack of the removed display area, the display area becomes ready to 1818 // be released (no more ActivityStack-s). But, we cannot release it at that moment or the 1819 // related WindowContainer will also be removed. So, we set display area as removed after 1820 // reparenting stack finished. 1821 // Keep the order from bottom to top. 1822 int numStacks = getStackCount(); 1823 1824 final boolean splitScreenActivated = toDisplayArea.isSplitScreenModeActivated(); 1825 final ActivityStack rootStack = splitScreenActivated ? toDisplayArea 1826 .getTopStackInWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) : null; 1827 for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) { 1828 final ActivityStack stack = getStackAt(stackNdx); 1829 // Always finish non-standard type stacks. 1830 if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) { 1831 stack.finishAllActivitiesImmediately(); 1832 } else { 1833 // Reparent the stack to the root task of secondary-split-screen or display area. 1834 stack.reparent(stack.supportsSplitScreenWindowingMode() && rootStack != null 1835 ? rootStack : toDisplayArea, POSITION_TOP); 1836 1837 // Set the windowing mode to undefined by default to let the stack inherited the 1838 // windowing mode. 1839 stack.setWindowingMode(WINDOWING_MODE_UNDEFINED); 1840 lastReparentedStack = stack; 1841 } 1842 // Stacks may be removed from this display. Ensure each stack will be processed 1843 // and the loop will end. 1844 stackNdx -= numStacks - getStackCount(); 1845 numStacks = getStackCount(); 1846 } 1847 if (lastReparentedStack != null && splitScreenActivated) { 1848 if (!lastReparentedStack.supportsSplitScreenWindowingMode()) { 1849 mAtmService.getTaskChangeNotificationController() 1850 .notifyActivityDismissingDockedStack(); 1851 toDisplayArea.onSplitScreenModeDismissed(lastReparentedStack); 1852 } else if (rootStack != null) { 1853 // update focus 1854 rootStack.moveToFront("display-removed"); 1855 } 1856 } 1857 1858 mRemoved = true; 1859 1860 return lastReparentedStack; 1861 } 1862 1863 1864 @Override dump(PrintWriter pw, String prefix, boolean dumpAll)1865 void dump(PrintWriter pw, String prefix, boolean dumpAll) { 1866 pw.println(prefix + "TaskDisplayArea " + getName()); 1867 final String doublePrefix = prefix + " "; 1868 super.dump(pw, doublePrefix, dumpAll); 1869 if (mPreferredTopFocusableStack != null) { 1870 pw.println(doublePrefix + "mPreferredTopFocusableStack=" + mPreferredTopFocusableStack); 1871 } 1872 if (mLastFocusedStack != null) { 1873 pw.println(doublePrefix + "mLastFocusedStack=" + mLastFocusedStack); 1874 } 1875 final String triplePrefix = doublePrefix + " "; 1876 pw.println(doublePrefix + "Application tokens in top down Z order:"); 1877 for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) { 1878 final ActivityStack stack = getChildAt(stackNdx); 1879 pw.println(doublePrefix + "* " + stack); 1880 stack.dump(pw, triplePrefix, dumpAll); 1881 } 1882 } 1883 } 1884