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 776 /** Reset the mPreferredTopFocusableRootTask if it is or below the given task. */ resetPreferredTopFocusableRootTaskIfNeeded(Task task)777 void resetPreferredTopFocusableRootTaskIfNeeded(Task task) { 778 if (mPreferredTopFocusableStack != null 779 && mPreferredTopFocusableStack.compareTo(task) <= 0) { 780 mPreferredTopFocusableStack = null; 781 } 782 } 783 positionStackAt(int position, ActivityStack child, boolean includingParents)784 void positionStackAt(int position, ActivityStack child, boolean includingParents) { 785 positionChildAt(position, child, includingParents); 786 mDisplayContent.layoutAndAssignWindowLayersIfNeeded(); 787 } 788 positionStackAtTop(ActivityStack stack, boolean includingParents)789 void positionStackAtTop(ActivityStack stack, boolean includingParents) { 790 positionStackAtTop(stack, includingParents, null /* updateLastFocusedStackReason */); 791 } 792 positionStackAtTop(ActivityStack stack, boolean includingParents, String updateLastFocusedStackReason)793 void positionStackAtTop(ActivityStack stack, boolean includingParents, 794 String updateLastFocusedStackReason) { 795 positionStackAt(stack, getStackCount(), includingParents, 796 updateLastFocusedStackReason); 797 } 798 positionStackAtBottom(ActivityStack stack)799 void positionStackAtBottom(ActivityStack stack) { 800 positionStackAtBottom(stack, null /* updateLastFocusedStackReason */); 801 } 802 positionStackAtBottom(ActivityStack stack, String updateLastFocusedStackReason)803 void positionStackAtBottom(ActivityStack stack, String updateLastFocusedStackReason) { 804 positionStackAt(stack, 0, false /* includingParents */, 805 updateLastFocusedStackReason); 806 } 807 positionStackAt(ActivityStack stack, int position)808 void positionStackAt(ActivityStack stack, int position) { 809 positionStackAt(stack, position, false /* includingParents */, 810 null /* updateLastFocusedStackReason */); 811 } 812 positionStackAt(ActivityStack stack, int position, boolean includingParents, String updateLastFocusedStackReason)813 void positionStackAt(ActivityStack stack, int position, boolean includingParents, 814 String updateLastFocusedStackReason) { 815 // TODO: Keep in sync with WindowContainer.positionChildAt(), once we change that to adjust 816 // the position internally, also update the logic here 817 final ActivityStack prevFocusedStack = updateLastFocusedStackReason != null 818 ? getFocusedStack() : null; 819 final boolean wasContained = mChildren.contains(stack); 820 if (mDisplayContent.mSingleTaskInstance && getStackCount() == 1 && !wasContained) { 821 throw new IllegalStateException( 822 "positionStackAt: Can only have one task on display=" + this); 823 } 824 825 // Since positionChildAt() is called during the creation process of pinned stacks, 826 // ActivityStack#getStack() can be null. 827 positionStackAt(position, stack, includingParents); 828 829 if (updateLastFocusedStackReason != null) { 830 final ActivityStack currentFocusedStack = getFocusedStack(); 831 if (currentFocusedStack != prevFocusedStack) { 832 mLastFocusedStack = prevFocusedStack; 833 EventLogTags.writeWmFocusedStack(mRootWindowContainer.mCurrentUser, 834 mDisplayContent.mDisplayId, 835 currentFocusedStack == null ? -1 : currentFocusedStack.getRootTaskId(), 836 mLastFocusedStack == null ? -1 : mLastFocusedStack.getRootTaskId(), 837 updateLastFocusedStackReason); 838 } 839 } 840 841 onStackOrderChanged(stack); 842 } 843 844 /** 845 * Moves/reparents `task` to the back of whatever container the home stack is in. This is for 846 * when we just want to move a task to "the back" vs. a specific place. The primary use-case 847 * is to make sure that moved-to-back apps go into secondary split when in split-screen mode. 848 */ positionTaskBehindHome(ActivityStack task)849 void positionTaskBehindHome(ActivityStack task) { 850 final ActivityStack home = getOrCreateRootHomeTask(); 851 final WindowContainer homeParent = home.getParent(); 852 final Task homeParentTask = homeParent != null ? homeParent.asTask() : null; 853 if (homeParentTask == null) { 854 // reparent throws if parent didn't change... 855 if (task.getParent() == this) { 856 positionStackAtBottom(task); 857 } else { 858 task.reparent(this, false /* onTop */); 859 } 860 } else if (homeParentTask == task.getParent()) { 861 // Apparently reparent early-outs if same stack, so we have to explicitly reorder. 862 ((ActivityStack) homeParentTask).positionChildAtBottom(task); 863 } else { 864 task.reparent((ActivityStack) homeParentTask, false /* toTop */, 865 Task.REPARENT_LEAVE_STACK_IN_PLACE, false /* animate */, 866 false /* deferResume */, "positionTaskBehindHome"); 867 } 868 } 869 getStack(int rootTaskId)870 ActivityStack getStack(int rootTaskId) { 871 for (int i = getStackCount() - 1; i >= 0; --i) { 872 final ActivityStack stack = getStackAt(i); 873 if (stack.getRootTaskId() == rootTaskId) { 874 return stack; 875 } 876 } 877 return null; 878 } 879 880 /** 881 * Returns an existing stack compatible with the windowing mode and activity type or creates one 882 * if a compatible stack doesn't exist. 883 * @see #getOrCreateStack(int, int, boolean, Intent, Task) 884 */ getOrCreateStack(int windowingMode, int activityType, boolean onTop)885 ActivityStack getOrCreateStack(int windowingMode, int activityType, boolean onTop) { 886 return getOrCreateStack(windowingMode, activityType, onTop, null /* intent */, 887 null /* candidateTask */); 888 } 889 890 /** 891 * When two level tasks are required for given windowing mode and activity type, returns an 892 * existing compatible root task or creates a new one. 893 * For one level task, the candidate task would be reused to also be the root task or create 894 * a new root task if no candidate task. 895 * @see #getStack(int, int) 896 * @see #createStack(int, int, boolean) 897 */ getOrCreateStack(int windowingMode, int activityType, boolean onTop, Intent intent, Task candidateTask)898 ActivityStack getOrCreateStack(int windowingMode, int activityType, boolean onTop, 899 Intent intent, Task candidateTask) { 900 // Need to pass in a determined windowing mode to see if a new stack should be created, 901 // so use its parent's windowing mode if it is undefined. 902 if (!alwaysCreateStack( 903 windowingMode != WINDOWING_MODE_UNDEFINED ? windowingMode : getWindowingMode(), 904 activityType)) { 905 ActivityStack stack = getStack(windowingMode, activityType); 906 if (stack != null) { 907 return stack; 908 } 909 } else if (candidateTask != null) { 910 final ActivityStack stack = (ActivityStack) candidateTask; 911 final int position = onTop ? POSITION_TOP : POSITION_BOTTOM; 912 Task launchRootTask = updateLaunchRootTask(windowingMode); 913 914 if (launchRootTask != null) { 915 if (stack.getParent() == null) { 916 launchRootTask.addChild(stack, position); 917 } else if (stack.getParent() != launchRootTask) { 918 stack.reparent(launchRootTask, position); 919 } 920 } else if (stack.getDisplayArea() != this || !stack.isRootTask()) { 921 if (stack.getParent() == null) { 922 addChild(stack, position); 923 } else { 924 stack.reparent(this, onTop); 925 } 926 } 927 // Update windowing mode if necessary, e.g. moving a pinned task to fullscreen. 928 if (candidateTask.getWindowingMode() != windowingMode) { 929 candidateTask.setWindowingMode(windowingMode); 930 } 931 return stack; 932 } 933 return createStack(windowingMode, activityType, onTop, null /*info*/, intent, 934 false /* createdByOrganizer */); 935 } 936 937 /** 938 * Returns an existing stack compatible with the input params or creates one 939 * if a compatible stack doesn't exist. 940 * @see #getOrCreateStack(int, int, boolean) 941 */ getOrCreateStack(@ullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable Task candidateTask, int activityType, boolean onTop)942 ActivityStack getOrCreateStack(@Nullable ActivityRecord r, 943 @Nullable ActivityOptions options, @Nullable Task candidateTask, int activityType, 944 boolean onTop) { 945 // First preference is the windowing mode in the activity options if set. 946 int windowingMode = (options != null) 947 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED; 948 // Validate that our desired windowingMode will work under the current conditions. 949 // UNDEFINED windowing mode is a valid result and means that the new stack will inherit 950 // it's display's windowing mode. 951 windowingMode = validateWindowingMode(windowingMode, r, candidateTask, activityType); 952 return getOrCreateStack(windowingMode, activityType, onTop, null /* intent */, 953 candidateTask); 954 } 955 956 @VisibleForTesting getNextStackId()957 int getNextStackId() { 958 return mAtmService.mStackSupervisor.getNextTaskIdForUser(); 959 } 960 createStack(int windowingMode, int activityType, boolean onTop)961 ActivityStack createStack(int windowingMode, int activityType, boolean onTop) { 962 return createStack(windowingMode, activityType, onTop, null /* info */, null /* intent */, 963 false /* createdByOrganizer */); 964 } 965 966 /** 967 * Creates a stack matching the input windowing mode and activity type on this display. 968 * @param windowingMode The windowing mode the stack should be created in. If 969 * {@link WindowConfiguration#WINDOWING_MODE_UNDEFINED} then the stack will 970 * inherit its parent's windowing mode. 971 * @param activityType The activityType the stack should be created in. If 972 * {@link WindowConfiguration#ACTIVITY_TYPE_UNDEFINED} then the stack will 973 * be created in {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD}. 974 * @param onTop If true the stack will be created at the top of the display, else at the bottom. 975 * @param info The started activity info. 976 * @param intent The intent that started this task. 977 * @param createdByOrganizer @{code true} if this is created by task organizer, @{code false} 978 * otherwise. 979 * @return The newly created stack. 980 */ createStack(int windowingMode, int activityType, boolean onTop, ActivityInfo info, Intent intent, boolean createdByOrganizer)981 ActivityStack createStack(int windowingMode, int activityType, boolean onTop, ActivityInfo info, 982 Intent intent, boolean createdByOrganizer) { 983 if (mDisplayContent.mSingleTaskInstance && getStackCount() > 0) { 984 // Create stack on default display instead since this display can only contain 1 stack. 985 // TODO: Kinda a hack, but better that having the decision at each call point. Hoping 986 // this goes away once ActivityView is no longer using virtual displays. 987 return mRootWindowContainer.getDefaultTaskDisplayArea().createStack( 988 windowingMode, activityType, onTop, info, intent, createdByOrganizer); 989 } 990 991 if (activityType == ACTIVITY_TYPE_UNDEFINED && !createdByOrganizer) { 992 // Can't have an undefined stack type yet...so re-map to standard. Anyone that wants 993 // anything else should be passing it in anyways...except for the task organizer. 994 activityType = ACTIVITY_TYPE_STANDARD; 995 } 996 997 if (activityType != ACTIVITY_TYPE_STANDARD && activityType != ACTIVITY_TYPE_UNDEFINED) { 998 // For now there can be only one stack of a particular non-standard activity type on a 999 // display. So, get that ignoring whatever windowing mode it is currently in. 1000 ActivityStack stack = getStack(WINDOWING_MODE_UNDEFINED, activityType); 1001 if (stack != null) { 1002 throw new IllegalArgumentException("Stack=" + stack + " of activityType=" 1003 + activityType + " already on display=" + this + ". Can't have multiple."); 1004 } 1005 } 1006 1007 if (!isWindowingModeSupported(windowingMode, mAtmService.mSupportsMultiWindow, 1008 mAtmService.mSupportsSplitScreenMultiWindow, 1009 mAtmService.mSupportsFreeformWindowManagement, 1010 mAtmService.mSupportsPictureInPicture, activityType)) { 1011 throw new IllegalArgumentException("Can't create stack for unsupported windowingMode=" 1012 + windowingMode); 1013 } 1014 1015 if (windowingMode == WINDOWING_MODE_PINNED && getRootPinnedTask() != null) { 1016 // Only 1 stack can be PINNED at a time, so dismiss the existing one 1017 getRootPinnedTask().dismissPip(); 1018 } 1019 1020 final int stackId = getNextStackId(); 1021 return createStackUnchecked(windowingMode, activityType, stackId, onTop, info, intent, 1022 createdByOrganizer); 1023 } 1024 1025 /** @return the root task to create the next task in. */ updateLaunchRootTask(int windowingMode)1026 private Task updateLaunchRootTask(int windowingMode) { 1027 if (!isSplitScreenWindowingMode(windowingMode)) { 1028 // Only split-screen windowing modes can do this currently... 1029 return null; 1030 } 1031 for (int i = getStackCount() - 1; i >= 0; --i) { 1032 final Task t = getStackAt(i); 1033 if (!t.mCreatedByOrganizer || t.getRequestedOverrideWindowingMode() != windowingMode) { 1034 continue; 1035 } 1036 // If not already set, pick a launch root which is not the one we are launching into. 1037 if (mLaunchRootTask == null) { 1038 for (int j = 0, n = getStackCount(); j < n; ++j) { 1039 final Task tt = getStackAt(j); 1040 if (tt.mCreatedByOrganizer && tt != t) { 1041 mLaunchRootTask = tt; 1042 break; 1043 } 1044 } 1045 } 1046 return t; 1047 } 1048 return mLaunchRootTask; 1049 } 1050 1051 @VisibleForTesting createStackUnchecked(int windowingMode, int activityType, int stackId, boolean onTop, ActivityInfo info, Intent intent, boolean createdByOrganizer)1052 ActivityStack createStackUnchecked(int windowingMode, int activityType, int stackId, 1053 boolean onTop, ActivityInfo info, Intent intent, boolean createdByOrganizer) { 1054 if (windowingMode == WINDOWING_MODE_PINNED && activityType != ACTIVITY_TYPE_STANDARD) { 1055 throw new IllegalArgumentException("Stack with windowing mode cannot with non standard " 1056 + "activity type."); 1057 } 1058 if (info == null) { 1059 info = new ActivityInfo(); 1060 info.applicationInfo = new ApplicationInfo(); 1061 } 1062 1063 // Task created by organizer are added as root. 1064 Task launchRootTask = createdByOrganizer ? null : updateLaunchRootTask(windowingMode); 1065 if (launchRootTask != null) { 1066 // Since this stack will be put into a root task, its windowingMode will be inherited. 1067 windowingMode = WINDOWING_MODE_UNDEFINED; 1068 } 1069 1070 final ActivityStack stack = new ActivityStack(mAtmService, stackId, activityType, 1071 info, intent, createdByOrganizer); 1072 if (launchRootTask != null) { 1073 launchRootTask.addChild(stack, onTop ? POSITION_TOP : POSITION_BOTTOM); 1074 if (onTop) { 1075 positionStackAtTop((ActivityStack) launchRootTask, false /* includingParents */); 1076 } 1077 } else { 1078 addChild(stack, onTop ? POSITION_TOP : POSITION_BOTTOM); 1079 stack.setWindowingMode(windowingMode, true /* creating */); 1080 } 1081 return stack; 1082 } 1083 1084 /** 1085 * Get the preferred focusable stack in priority. If the preferred stack does not exist, find a 1086 * focusable and visible stack from the top of stacks in this display. 1087 */ getFocusedStack()1088 ActivityStack getFocusedStack() { 1089 if (mPreferredTopFocusableStack != null) { 1090 return mPreferredTopFocusableStack; 1091 } 1092 1093 for (int i = getStackCount() - 1; i >= 0; --i) { 1094 final ActivityStack stack = getStackAt(i); 1095 if (stack.isFocusableAndVisible()) { 1096 return stack; 1097 } 1098 } 1099 1100 return null; 1101 } 1102 getNextFocusableStack(ActivityStack currentFocus, boolean ignoreCurrent)1103 ActivityStack getNextFocusableStack(ActivityStack currentFocus, boolean ignoreCurrent) { 1104 final int currentWindowingMode = currentFocus != null 1105 ? currentFocus.getWindowingMode() : WINDOWING_MODE_UNDEFINED; 1106 1107 ActivityStack candidate = null; 1108 for (int i = getStackCount() - 1; i >= 0; --i) { 1109 final ActivityStack stack = getStackAt(i); 1110 if (ignoreCurrent && stack == currentFocus) { 1111 continue; 1112 } 1113 if (!stack.isFocusableAndVisible()) { 1114 continue; 1115 } 1116 1117 if (currentWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY 1118 && candidate == null && stack.inSplitScreenPrimaryWindowingMode()) { 1119 // If the currently focused stack is in split-screen secondary we save off the 1120 // top primary split-screen stack as a candidate for focus because we might 1121 // prefer focus to move to an other stack to avoid primary split-screen stack 1122 // overlapping with a fullscreen stack when a fullscreen stack is higher in z 1123 // than the next split-screen stack. Assistant stack, I am looking at you... 1124 // We only move the focus to the primary-split screen stack if there isn't a 1125 // better alternative. 1126 candidate = stack; 1127 continue; 1128 } 1129 if (candidate != null && stack.inSplitScreenSecondaryWindowingMode()) { 1130 // Use the candidate stack since we are now at the secondary split-screen. 1131 return candidate; 1132 } 1133 return stack; 1134 } 1135 return candidate; 1136 } 1137 getFocusedActivity()1138 ActivityRecord getFocusedActivity() { 1139 final ActivityStack focusedStack = getFocusedStack(); 1140 if (focusedStack == null) { 1141 return null; 1142 } 1143 // TODO(b/111541062): Move this into ActivityStack#getResumedActivity() 1144 // Check if the focused stack has the resumed activity 1145 ActivityRecord resumedActivity = focusedStack.getResumedActivity(); 1146 if (resumedActivity == null || resumedActivity.app == null) { 1147 // If there is no registered resumed activity in the stack or it is not running - 1148 // try to use previously resumed one. 1149 resumedActivity = focusedStack.mPausingActivity; 1150 if (resumedActivity == null || resumedActivity.app == null) { 1151 // If previously resumed activity doesn't work either - find the topmost running 1152 // activity that can be focused. 1153 resumedActivity = focusedStack.topRunningActivity(true /* focusableOnly */); 1154 } 1155 } 1156 return resumedActivity; 1157 } 1158 getLastFocusedStack()1159 ActivityStack getLastFocusedStack() { 1160 return mLastFocusedStack; 1161 } 1162 allResumedActivitiesComplete()1163 boolean allResumedActivitiesComplete() { 1164 for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) { 1165 final ActivityRecord r = getStackAt(stackNdx).getResumedActivity(); 1166 if (r != null && !r.isState(RESUMED)) { 1167 return false; 1168 } 1169 } 1170 final ActivityStack currentFocusedStack = getFocusedStack(); 1171 if (ActivityTaskManagerDebugConfig.DEBUG_STACK) { 1172 Slog.d(TAG_STACK, "allResumedActivitiesComplete: mLastFocusedStack changing from=" 1173 + mLastFocusedStack + " to=" + currentFocusedStack); 1174 } 1175 mLastFocusedStack = currentFocusedStack; 1176 return true; 1177 } 1178 1179 /** 1180 * Pause all activities in either all of the stacks or just the back stacks. This is done before 1181 * resuming a new activity and to make sure that previously active activities are 1182 * paused in stacks that are no longer visible or in pinned windowing mode. This does not 1183 * pause activities in visible stacks, so if an activity is launched within the same stack/task, 1184 * then we should explicitly pause that stack's top activity. 1185 * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving(). 1186 * @param resuming The resuming activity. 1187 * @return {@code true} if any activity was paused as a result of this call. 1188 */ pauseBackStacks(boolean userLeaving, ActivityRecord resuming)1189 boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming) { 1190 boolean someActivityPaused = false; 1191 for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) { 1192 final ActivityStack stack = getStackAt(stackNdx); 1193 final ActivityRecord resumedActivity = stack.getResumedActivity(); 1194 if (resumedActivity != null 1195 && (stack.getVisibility(resuming) != STACK_VISIBILITY_VISIBLE 1196 || !stack.isTopActivityFocusable())) { 1197 if (DEBUG_STATES) { 1198 Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack 1199 + " mResumedActivity=" + resumedActivity); 1200 } 1201 someActivityPaused |= stack.startPausingLocked(userLeaving, false /* uiSleeping*/, 1202 resuming); 1203 } 1204 } 1205 return someActivityPaused; 1206 } 1207 1208 /** 1209 * Find task for putting the Activity in. 1210 */ findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplayArea, RootWindowContainer.FindTaskResult result)1211 void findTaskLocked(final ActivityRecord r, final boolean isPreferredDisplayArea, 1212 RootWindowContainer.FindTaskResult result) { 1213 mTmpFindTaskResult.clear(); 1214 for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) { 1215 final ActivityStack stack = getStackAt(stackNdx); 1216 if (!r.hasCompatibleActivityType(stack) && stack.isLeafTask()) { 1217 if (DEBUG_TASKS) { 1218 Slog.d(TAG_TASKS, "Skipping stack: (mismatch activity/stack) " + stack); 1219 } 1220 continue; 1221 } 1222 1223 mTmpFindTaskResult.process(r, stack); 1224 // It is possible to have tasks in multiple stacks with the same root affinity, so 1225 // we should keep looking after finding an affinity match to see if there is a 1226 // better match in another stack. Also, task affinity isn't a good enough reason 1227 // to target a display which isn't the source of the intent, so skip any affinity 1228 // matches not on the specified display. 1229 if (mTmpFindTaskResult.mRecord != null) { 1230 if (mTmpFindTaskResult.mIdealMatch) { 1231 result.setTo(mTmpFindTaskResult); 1232 return; 1233 } else if (isPreferredDisplayArea) { 1234 // Note: since the traversing through the stacks is top down, the floating 1235 // tasks should always have lower priority than any affinity-matching tasks 1236 // in the fullscreen stacks 1237 result.setTo(mTmpFindTaskResult); 1238 } 1239 } 1240 } 1241 } 1242 1243 /** 1244 * Removes stacks in the input windowing modes from the system if they are of activity type 1245 * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED 1246 */ removeStacksInWindowingModes(int... windowingModes)1247 void removeStacksInWindowingModes(int... windowingModes) { 1248 if (windowingModes == null || windowingModes.length == 0) { 1249 return; 1250 } 1251 1252 // Collect the stacks that are necessary to be removed instead of performing the removal 1253 // by looping mStacks, so that we don't miss any stacks after the stack size changed or 1254 // stacks reordered. 1255 final ArrayList<ActivityStack> stacks = new ArrayList<>(); 1256 for (int j = windowingModes.length - 1; j >= 0; --j) { 1257 final int windowingMode = windowingModes[j]; 1258 for (int i = getStackCount() - 1; i >= 0; --i) { 1259 final ActivityStack stack = getStackAt(i); 1260 if (!stack.isActivityTypeStandardOrUndefined()) { 1261 continue; 1262 } 1263 if (stack.getWindowingMode() != windowingMode) { 1264 continue; 1265 } 1266 stacks.add(stack); 1267 } 1268 } 1269 1270 for (int i = stacks.size() - 1; i >= 0; --i) { 1271 mRootWindowContainer.mStackSupervisor.removeStack(stacks.get(i)); 1272 } 1273 } 1274 removeStacksWithActivityTypes(int... activityTypes)1275 void removeStacksWithActivityTypes(int... activityTypes) { 1276 if (activityTypes == null || activityTypes.length == 0) { 1277 return; 1278 } 1279 1280 // Collect the stacks that are necessary to be removed instead of performing the removal 1281 // by looping mStacks, so that we don't miss any stacks after the stack size changed or 1282 // stacks reordered. 1283 final ArrayList<ActivityStack> stacks = new ArrayList<>(); 1284 for (int j = activityTypes.length - 1; j >= 0; --j) { 1285 final int activityType = activityTypes[j]; 1286 for (int i = getStackCount() - 1; i >= 0; --i) { 1287 final ActivityStack stack = getStackAt(i); 1288 // Collect the root tasks that are currently being organized. 1289 if (stack.mCreatedByOrganizer) { 1290 for (int k = stack.getChildCount() - 1; k >= 0; --k) { 1291 final ActivityStack childStack = (ActivityStack) stack.getChildAt(k); 1292 if (childStack.getActivityType() == activityType) { 1293 stacks.add(childStack); 1294 } 1295 } 1296 } else if (stack.getActivityType() == activityType) { 1297 stacks.add(stack); 1298 } 1299 } 1300 } 1301 1302 for (int i = stacks.size() - 1; i >= 0; --i) { 1303 mRootWindowContainer.mStackSupervisor.removeStack(stacks.get(i)); 1304 } 1305 } 1306 onSplitScreenModeDismissed()1307 void onSplitScreenModeDismissed() { 1308 onSplitScreenModeDismissed(null /* toTop */); 1309 } 1310 onSplitScreenModeDismissed(ActivityStack toTop)1311 void onSplitScreenModeDismissed(ActivityStack toTop) { 1312 mAtmService.deferWindowLayout(); 1313 try { 1314 mLaunchRootTask = null; 1315 moveSplitScreenTasksToFullScreen(); 1316 } finally { 1317 final ActivityStack topFullscreenStack = toTop != null 1318 ? toTop : getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN); 1319 final ActivityStack homeStack = getOrCreateRootHomeTask(); 1320 if (homeStack != null && ((topFullscreenStack != null && !isTopStack(homeStack)) 1321 || toTop != null)) { 1322 // Whenever split-screen is dismissed we want the home stack directly behind the 1323 // current top fullscreen stack so it shows up when the top stack is finished. 1324 // Or, if the caller specified a stack to be on top after split-screen is dismissed. 1325 // TODO: Would be better to use ActivityDisplay.positionChildAt() for this, however 1326 // ActivityDisplay doesn't have a direct controller to WM side yet. We can switch 1327 // once we have that. 1328 homeStack.moveToFront("onSplitScreenModeDismissed"); 1329 topFullscreenStack.moveToFront("onSplitScreenModeDismissed"); 1330 } 1331 mAtmService.continueWindowLayout(); 1332 } 1333 } 1334 moveSplitScreenTasksToFullScreen()1335 private void moveSplitScreenTasksToFullScreen() { 1336 final WindowContainerTransaction wct = new WindowContainerTransaction(); 1337 mTmpTasks.clear(); 1338 forAllTasks(task -> { 1339 if (task.mCreatedByOrganizer && task.inSplitScreenWindowingMode() && task.hasChild()) { 1340 mTmpTasks.add(task); 1341 } 1342 }); 1343 1344 for (int i = mTmpTasks.size() - 1; i >= 0; i--) { 1345 final Task root = mTmpTasks.get(i); 1346 for (int j = 0; j < root.getChildCount(); j++) { 1347 wct.reparent(root.getChildAt(j).mRemoteToken.toWindowContainerToken(), 1348 null, true /* toTop */); 1349 } 1350 } 1351 mAtmService.mWindowOrganizerController.applyTransaction(wct); 1352 } 1353 1354 /** 1355 * Returns true if the {@param windowingMode} is supported based on other parameters passed in. 1356 * @param windowingMode The windowing mode we are checking support for. 1357 * @param supportsMultiWindow If we should consider support for multi-window mode in general. 1358 * @param supportsSplitScreen If we should consider support for split-screen multi-window. 1359 * @param supportsFreeform If we should consider support for freeform multi-window. 1360 * @param supportsPip If we should consider support for picture-in-picture mutli-window. 1361 * @param activityType The activity type under consideration. 1362 * @return true if the windowing mode is supported. 1363 */ isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow, boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip, int activityType)1364 private boolean isWindowingModeSupported(int windowingMode, boolean supportsMultiWindow, 1365 boolean supportsSplitScreen, boolean supportsFreeform, boolean supportsPip, 1366 int activityType) { 1367 1368 if (windowingMode == WINDOWING_MODE_UNDEFINED 1369 || windowingMode == WINDOWING_MODE_FULLSCREEN) { 1370 return true; 1371 } 1372 if (!supportsMultiWindow) { 1373 return false; 1374 } 1375 1376 if (windowingMode == WINDOWING_MODE_MULTI_WINDOW) { 1377 return true; 1378 } 1379 1380 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY 1381 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { 1382 return supportsSplitScreen 1383 && WindowConfiguration.supportSplitScreenWindowingMode(activityType); 1384 } 1385 1386 if (!supportsFreeform && windowingMode == WINDOWING_MODE_FREEFORM) { 1387 return false; 1388 } 1389 1390 if (!supportsPip && windowingMode == WINDOWING_MODE_PINNED) { 1391 return false; 1392 } 1393 return true; 1394 } 1395 1396 /** 1397 * Resolves the windowing mode that an {@link ActivityRecord} would be in if started on this 1398 * display with the provided parameters. 1399 * 1400 * @param r The ActivityRecord in question. 1401 * @param options Options to start with. 1402 * @param task The task within-which the activity would start. 1403 * @param activityType The type of activity to start. 1404 * @return The resolved (not UNDEFINED) windowing-mode that the activity would be in. 1405 */ resolveWindowingMode(@ullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable Task task, int activityType)1406 int resolveWindowingMode(@Nullable ActivityRecord r, @Nullable ActivityOptions options, 1407 @Nullable Task task, int activityType) { 1408 1409 // First preference if the windowing mode in the activity options if set. 1410 int windowingMode = (options != null) 1411 ? options.getLaunchWindowingMode() : WINDOWING_MODE_UNDEFINED; 1412 1413 // If windowing mode is unset, then next preference is the candidate task, then the 1414 // activity record. 1415 if (windowingMode == WINDOWING_MODE_UNDEFINED) { 1416 if (task != null) { 1417 windowingMode = task.getWindowingMode(); 1418 } 1419 if (windowingMode == WINDOWING_MODE_UNDEFINED && r != null) { 1420 windowingMode = r.getWindowingMode(); 1421 } 1422 if (windowingMode == WINDOWING_MODE_UNDEFINED) { 1423 // Use the display's windowing mode. 1424 windowingMode = getWindowingMode(); 1425 } 1426 } 1427 windowingMode = validateWindowingMode(windowingMode, r, task, activityType); 1428 return windowingMode != WINDOWING_MODE_UNDEFINED 1429 ? windowingMode : WINDOWING_MODE_FULLSCREEN; 1430 } 1431 1432 /** 1433 * Check if the requested windowing-mode is appropriate for the specified task and/or activity 1434 * on this display. 1435 * 1436 * @param windowingMode The windowing-mode to validate. 1437 * @param r The {@link ActivityRecord} to check against. 1438 * @param task The {@link Task} to check against. 1439 * @param activityType An activity type. 1440 * @return {@code true} if windowingMode is valid, {@code false} otherwise. 1441 */ isValidWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task, int activityType)1442 boolean isValidWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task, 1443 int activityType) { 1444 // Make sure the windowing mode we are trying to use makes sense for what is supported. 1445 boolean supportsMultiWindow = mAtmService.mSupportsMultiWindow; 1446 boolean supportsSplitScreen = mAtmService.mSupportsSplitScreenMultiWindow; 1447 boolean supportsFreeform = mAtmService.mSupportsFreeformWindowManagement; 1448 boolean supportsPip = mAtmService.mSupportsPictureInPicture; 1449 if (supportsMultiWindow) { 1450 if (task != null) { 1451 supportsMultiWindow = task.isResizeable(); 1452 supportsSplitScreen = task.supportsSplitScreenWindowingMode(); 1453 // TODO: Do we need to check for freeform and Pip support here? 1454 } else if (r != null) { 1455 supportsMultiWindow = r.isResizeable(); 1456 supportsSplitScreen = r.supportsSplitScreenWindowingMode(); 1457 supportsFreeform = r.supportsFreeform(); 1458 supportsPip = r.supportsPictureInPicture(); 1459 } 1460 } 1461 1462 return windowingMode != WINDOWING_MODE_UNDEFINED 1463 && isWindowingModeSupported(windowingMode, supportsMultiWindow, supportsSplitScreen, 1464 supportsFreeform, supportsPip, activityType); 1465 } 1466 1467 /** 1468 * Check that the requested windowing-mode is appropriate for the specified task and/or activity 1469 * on this display. 1470 * 1471 * @param windowingMode The windowing-mode to validate. 1472 * @param r The {@link ActivityRecord} to check against. 1473 * @param task The {@link Task} to check against. 1474 * @param activityType An activity type. 1475 * @return The provided windowingMode or the closest valid mode which is appropriate. 1476 */ validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task, int activityType)1477 int validateWindowingMode(int windowingMode, @Nullable ActivityRecord r, @Nullable Task task, 1478 int activityType) { 1479 final boolean inSplitScreenMode = isSplitScreenModeActivated(); 1480 if (!inSplitScreenMode && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { 1481 // Switch to the display's windowing mode if we are not in split-screen mode and we are 1482 // trying to launch in split-screen secondary. 1483 windowingMode = WINDOWING_MODE_UNDEFINED; 1484 } else if (inSplitScreenMode && windowingMode == WINDOWING_MODE_UNDEFINED) { 1485 windowingMode = WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; 1486 } 1487 if (!isValidWindowingMode(windowingMode, r, task, activityType)) { 1488 return WINDOWING_MODE_UNDEFINED; 1489 } 1490 return windowingMode; 1491 } 1492 isTopStack(ActivityStack stack)1493 boolean isTopStack(ActivityStack stack) { 1494 return stack == getTopStack(); 1495 } 1496 isTopNotPinnedStack(ActivityStack stack)1497 boolean isTopNotPinnedStack(ActivityStack stack) { 1498 for (int i = getStackCount() - 1; i >= 0; --i) { 1499 final ActivityStack current = getStackAt(i); 1500 if (!current.inPinnedWindowingMode()) { 1501 return current == stack; 1502 } 1503 } 1504 return false; 1505 } 1506 topRunningActivity()1507 ActivityRecord topRunningActivity() { 1508 return topRunningActivity(false /* considerKeyguardState */); 1509 } 1510 1511 /** 1512 * Returns the top running activity in the focused stack. In the case the focused stack has no 1513 * such activity, the next focusable stack on this display is returned. 1514 * 1515 * @param considerKeyguardState Indicates whether the locked state should be considered. if 1516 * {@code true} and the keyguard is locked, only activities that 1517 * can be shown on top of the keyguard will be considered. 1518 * @return The top running activity. {@code null} if none is available. 1519 */ topRunningActivity(boolean considerKeyguardState)1520 ActivityRecord topRunningActivity(boolean considerKeyguardState) { 1521 ActivityRecord topRunning = null; 1522 final ActivityStack focusedStack = getFocusedStack(); 1523 if (focusedStack != null) { 1524 topRunning = focusedStack.topRunningActivity(); 1525 } 1526 1527 // Look in other focusable stacks. 1528 if (topRunning == null) { 1529 for (int i = getStackCount() - 1; i >= 0; --i) { 1530 final ActivityStack stack = getStackAt(i); 1531 // Only consider focusable stacks other than the current focused one. 1532 if (stack == focusedStack || !stack.isTopActivityFocusable()) { 1533 continue; 1534 } 1535 topRunning = stack.topRunningActivity(); 1536 if (topRunning != null) { 1537 break; 1538 } 1539 } 1540 } 1541 1542 // This activity can be considered the top running activity if we are not considering 1543 // the locked state, the keyguard isn't locked, or we can show when locked. 1544 if (topRunning != null && considerKeyguardState 1545 && mRootWindowContainer.mStackSupervisor.getKeyguardController() 1546 .isKeyguardLocked() 1547 && !topRunning.canShowWhenLocked()) { 1548 return null; 1549 } 1550 1551 return topRunning; 1552 } 1553 getStackCount()1554 protected int getStackCount() { 1555 return mChildren.size(); 1556 } 1557 getStackAt(int index)1558 protected ActivityStack getStackAt(int index) { 1559 return mChildren.get(index); 1560 } 1561 1562 @Nullable getOrCreateRootHomeTask()1563 ActivityStack getOrCreateRootHomeTask() { 1564 return getOrCreateRootHomeTask(false /* onTop */); 1565 } 1566 1567 /** 1568 * Returns the existing home stack or creates and returns a new one if it should exist for the 1569 * display. 1570 * @param onTop Only be used when there is no existing home stack. If true the home stack will 1571 * be created at the top of the display, else at the bottom. 1572 */ 1573 @Nullable getOrCreateRootHomeTask(boolean onTop)1574 ActivityStack getOrCreateRootHomeTask(boolean onTop) { 1575 ActivityStack homeTask = getRootHomeTask(); 1576 if (homeTask == null && mDisplayContent.supportsSystemDecorations()) { 1577 homeTask = createStack(WINDOWING_MODE_UNDEFINED, ACTIVITY_TYPE_HOME, onTop); 1578 } 1579 return homeTask; 1580 } 1581 isSplitScreenModeActivated()1582 boolean isSplitScreenModeActivated() { 1583 Task task = getRootSplitScreenPrimaryTask(); 1584 return task != null && task.hasChild(); 1585 } 1586 1587 /** 1588 * Returns the topmost stack on the display that is compatible with the input windowing mode. 1589 * Null is no compatible stack on the display. 1590 */ getTopStackInWindowingMode(int windowingMode)1591 ActivityStack getTopStackInWindowingMode(int windowingMode) { 1592 return getStack(windowingMode, ACTIVITY_TYPE_UNDEFINED); 1593 } 1594 moveHomeStackToFront(String reason)1595 void moveHomeStackToFront(String reason) { 1596 final ActivityStack homeStack = getOrCreateRootHomeTask(); 1597 if (homeStack != null) { 1598 homeStack.moveToFront(reason); 1599 } 1600 } 1601 1602 /** 1603 * Moves the focusable home activity to top. If there is no such activity, the home stack will 1604 * still move to top. 1605 */ moveHomeActivityToTop(String reason)1606 void moveHomeActivityToTop(String reason) { 1607 final ActivityRecord top = getHomeActivity(); 1608 if (top == null) { 1609 moveHomeStackToFront(reason); 1610 return; 1611 } 1612 top.moveFocusableActivityToTop(reason); 1613 } 1614 1615 @Nullable getHomeActivity()1616 ActivityRecord getHomeActivity() { 1617 return getHomeActivityForUser(mRootWindowContainer.mCurrentUser); 1618 } 1619 1620 @Nullable getHomeActivityForUser(int userId)1621 ActivityRecord getHomeActivityForUser(int userId) { 1622 final ActivityStack homeStack = getRootHomeTask(); 1623 if (homeStack == null) { 1624 return null; 1625 } 1626 1627 final PooledPredicate p = PooledLambda.obtainPredicate( 1628 TaskDisplayArea::isHomeActivityForUser, PooledLambda.__(ActivityRecord.class), 1629 userId); 1630 final ActivityRecord r = homeStack.getActivity(p); 1631 p.recycle(); 1632 return r; 1633 } 1634 isHomeActivityForUser(ActivityRecord r, int userId)1635 private static boolean isHomeActivityForUser(ActivityRecord r, int userId) { 1636 return r.isActivityTypeHome() && (userId == UserHandle.USER_ALL || r.mUserId == userId); 1637 } 1638 1639 /** 1640 * Adjusts the {@param stack} behind the last visible stack in the display if necessary. 1641 * Generally used in conjunction with {@link #moveStackBehindStack}. 1642 */ 1643 // TODO(b/151575894): Remove special stack movement methods. moveStackBehindBottomMostVisibleStack(ActivityStack stack)1644 void moveStackBehindBottomMostVisibleStack(ActivityStack stack) { 1645 if (stack.shouldBeVisible(null)) { 1646 // Skip if the stack is already visible 1647 return; 1648 } 1649 1650 final boolean isRootTask = stack.isRootTask(); 1651 if (isRootTask) { 1652 // Move the stack to the bottom to not affect the following visibility checks 1653 positionStackAtBottom(stack); 1654 } else { 1655 stack.getParent().positionChildAt(POSITION_BOTTOM, stack, false /* includingParents */); 1656 } 1657 1658 // Find the next position where the stack should be placed 1659 final int numStacks = isRootTask ? getStackCount() : stack.getParent().getChildCount(); 1660 for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) { 1661 final ActivityStack s = isRootTask ? getStackAt(stackNdx) 1662 : (ActivityStack) stack.getParent().getChildAt(stackNdx); 1663 if (s == stack) { 1664 continue; 1665 } 1666 final int winMode = s.getWindowingMode(); 1667 final boolean isValidWindowingMode = winMode == WINDOWING_MODE_FULLSCREEN 1668 || winMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; 1669 if (s.shouldBeVisible(null) && isValidWindowingMode) { 1670 // Move the provided stack to behind this stack 1671 final int position = Math.max(0, stackNdx - 1); 1672 if (isRootTask) { 1673 positionStackAt(stack, position); 1674 } else { 1675 stack.getParent().positionChildAt(position, stack, false /*includingParents */); 1676 } 1677 break; 1678 } 1679 } 1680 } 1681 1682 /** 1683 * Moves the {@param stack} behind the given {@param behindStack} if possible. If 1684 * {@param behindStack} is not currently in the display, then then the stack is moved to the 1685 * back. Generally used in conjunction with {@link #moveStackBehindBottomMostVisibleStack}. 1686 */ moveStackBehindStack(ActivityStack stack, ActivityStack behindStack)1687 void moveStackBehindStack(ActivityStack stack, ActivityStack behindStack) { 1688 if (behindStack == null || behindStack == stack) { 1689 return; 1690 } 1691 1692 final WindowContainer parent = stack.getParent(); 1693 if (parent == null || parent != behindStack.getParent()) { 1694 return; 1695 } 1696 1697 // Note that positionChildAt will first remove the given stack before inserting into the 1698 // list, so we need to adjust the insertion index to account for the removed index 1699 // TODO: Remove this logic when WindowContainer.positionChildAt() is updated to adjust the 1700 // position internally 1701 final int stackIndex = parent.mChildren.indexOf(stack); 1702 final int behindStackIndex = parent.mChildren.indexOf(behindStack); 1703 final int insertIndex = stackIndex <= behindStackIndex 1704 ? behindStackIndex - 1 : behindStackIndex; 1705 final int position = Math.max(0, insertIndex); 1706 if (stack.isRootTask()) { 1707 positionStackAt(stack, position); 1708 } else { 1709 parent.positionChildAt(position, stack, false /* includingParents */); 1710 } 1711 } 1712 hasPinnedTask()1713 boolean hasPinnedTask() { 1714 return getRootPinnedTask() != null; 1715 } 1716 1717 /** 1718 * @return the stack currently above the {@param stack}. Can be null if the {@param stack} is 1719 * already top-most. 1720 */ getStackAbove(ActivityStack stack)1721 static ActivityStack getStackAbove(ActivityStack stack) { 1722 final WindowContainer wc = stack.getParent(); 1723 final int index = wc.mChildren.indexOf(stack) + 1; 1724 return (index < wc.mChildren.size()) ? (ActivityStack) wc.mChildren.get(index) : null; 1725 } 1726 1727 /** Returns true if the stack in the windowing mode is visible. */ isStackVisible(int windowingMode)1728 boolean isStackVisible(int windowingMode) { 1729 final ActivityStack stack = getTopStackInWindowingMode(windowingMode); 1730 return stack != null && stack.isVisible(); 1731 } 1732 removeStack(ActivityStack stack)1733 void removeStack(ActivityStack stack) { 1734 removeChild(stack); 1735 } 1736 getDisplayId()1737 int getDisplayId() { 1738 return mDisplayContent.getDisplayId(); 1739 } 1740 isRemoved()1741 boolean isRemoved() { 1742 return mRemoved; 1743 } 1744 1745 /** 1746 * Adds a listener to be notified whenever the stack order in the display changes. Currently 1747 * only used by the {@link RecentsAnimation} to determine whether to interrupt and cancel the 1748 * current animation when the system state changes. 1749 */ registerStackOrderChangedListener(OnStackOrderChangedListener listener)1750 void registerStackOrderChangedListener(OnStackOrderChangedListener listener) { 1751 if (!mStackOrderChangedCallbacks.contains(listener)) { 1752 mStackOrderChangedCallbacks.add(listener); 1753 } 1754 } 1755 1756 /** 1757 * Removes a previously registered stack order change listener. 1758 */ unregisterStackOrderChangedListener(OnStackOrderChangedListener listener)1759 void unregisterStackOrderChangedListener(OnStackOrderChangedListener listener) { 1760 mStackOrderChangedCallbacks.remove(listener); 1761 } 1762 1763 /** 1764 * Notifies of a stack order change 1765 * @param stack The stack which triggered the order change 1766 */ onStackOrderChanged(ActivityStack stack)1767 void onStackOrderChanged(ActivityStack stack) { 1768 for (int i = mStackOrderChangedCallbacks.size() - 1; i >= 0; i--) { 1769 mStackOrderChangedCallbacks.get(i).onStackOrderChanged(stack); 1770 } 1771 } 1772 1773 @Override canCreateRemoteAnimationTarget()1774 boolean canCreateRemoteAnimationTarget() { 1775 return true; 1776 } 1777 1778 /** 1779 * Callback for when the order of the stacks in the display changes. 1780 */ 1781 interface OnStackOrderChangedListener { onStackOrderChanged(ActivityStack stack)1782 void onStackOrderChanged(ActivityStack stack); 1783 } 1784 ensureActivitiesVisible(ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients)1785 void ensureActivitiesVisible(ActivityRecord starting, int configChanges, 1786 boolean preserveWindows, boolean notifyClients) { 1787 mAtmService.mStackSupervisor.beginActivityVisibilityUpdate(); 1788 try { 1789 for (int stackNdx = getStackCount() - 1; stackNdx >= 0; --stackNdx) { 1790 final ActivityStack stack = getStackAt(stackNdx); 1791 stack.ensureActivitiesVisible(starting, configChanges, preserveWindows, 1792 notifyClients); 1793 } 1794 } finally { 1795 mAtmService.mStackSupervisor.endActivityVisibilityUpdate(); 1796 } 1797 } 1798 prepareFreezingTaskBounds()1799 void prepareFreezingTaskBounds() { 1800 for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) { 1801 final ActivityStack stack = getChildAt(stackNdx); 1802 stack.prepareFreezingTaskBounds(); 1803 } 1804 } 1805 1806 /** 1807 * Removes the stacks in the node applying the content removal node from the display. 1808 * @return last reparented stack, or {@code null} if the stacks had to be destroyed. 1809 */ remove()1810 ActivityStack remove() { 1811 mPreferredTopFocusableStack = null; 1812 // TODO(b/153090332): Allow setting content removal mode per task display area 1813 final boolean destroyContentOnRemoval = mDisplayContent.shouldDestroyContentOnRemove(); 1814 final TaskDisplayArea toDisplayArea = mRootWindowContainer.getDefaultTaskDisplayArea(); 1815 ActivityStack lastReparentedStack = null; 1816 1817 // Stacks could be reparented from the removed display area to other display area. After 1818 // reparenting the last stack of the removed display area, the display area becomes ready to 1819 // be released (no more ActivityStack-s). But, we cannot release it at that moment or the 1820 // related WindowContainer will also be removed. So, we set display area as removed after 1821 // reparenting stack finished. 1822 // Keep the order from bottom to top. 1823 int numStacks = getStackCount(); 1824 1825 final boolean splitScreenActivated = toDisplayArea.isSplitScreenModeActivated(); 1826 final ActivityStack rootStack = splitScreenActivated ? toDisplayArea 1827 .getTopStackInWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) : null; 1828 for (int stackNdx = 0; stackNdx < numStacks; stackNdx++) { 1829 final ActivityStack stack = getStackAt(stackNdx); 1830 // Always finish non-standard type stacks. 1831 if (destroyContentOnRemoval || !stack.isActivityTypeStandardOrUndefined()) { 1832 stack.finishAllActivitiesImmediately(); 1833 } else { 1834 // Reparent the stack to the root task of secondary-split-screen or display area. 1835 stack.reparent(stack.supportsSplitScreenWindowingMode() && rootStack != null 1836 ? rootStack : toDisplayArea, POSITION_TOP); 1837 1838 // Set the windowing mode to undefined by default to let the stack inherited the 1839 // windowing mode. 1840 stack.setWindowingMode(WINDOWING_MODE_UNDEFINED); 1841 lastReparentedStack = stack; 1842 } 1843 // Stacks may be removed from this display. Ensure each stack will be processed 1844 // and the loop will end. 1845 stackNdx -= numStacks - getStackCount(); 1846 numStacks = getStackCount(); 1847 } 1848 if (lastReparentedStack != null && splitScreenActivated) { 1849 if (!lastReparentedStack.supportsSplitScreenWindowingMode()) { 1850 mAtmService.getTaskChangeNotificationController() 1851 .notifyActivityDismissingDockedStack(); 1852 toDisplayArea.onSplitScreenModeDismissed(lastReparentedStack); 1853 } else if (rootStack != null) { 1854 // update focus 1855 rootStack.moveToFront("display-removed"); 1856 } 1857 } 1858 1859 mRemoved = true; 1860 1861 return lastReparentedStack; 1862 } 1863 1864 1865 @Override dump(PrintWriter pw, String prefix, boolean dumpAll)1866 void dump(PrintWriter pw, String prefix, boolean dumpAll) { 1867 pw.println(prefix + "TaskDisplayArea " + getName()); 1868 final String doublePrefix = prefix + " "; 1869 super.dump(pw, doublePrefix, dumpAll); 1870 if (mPreferredTopFocusableStack != null) { 1871 pw.println(doublePrefix + "mPreferredTopFocusableStack=" + mPreferredTopFocusableStack); 1872 } 1873 if (mLastFocusedStack != null) { 1874 pw.println(doublePrefix + "mLastFocusedStack=" + mLastFocusedStack); 1875 } 1876 final String triplePrefix = doublePrefix + " "; 1877 pw.println(doublePrefix + "Application tokens in top down Z order:"); 1878 for (int stackNdx = getChildCount() - 1; stackNdx >= 0; --stackNdx) { 1879 final ActivityStack stack = getChildAt(stackNdx); 1880 pw.println(doublePrefix + "* " + stack); 1881 stack.dump(pw, triplePrefix, dumpAll); 1882 } 1883 } 1884 } 1885