1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.server.wm; 18 19 import static android.app.ActivityTaskManager.INVALID_TASK_ID; 20 import static android.app.KeyguardManager.ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER; 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_PINNED; 24 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; 25 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_INSTANCE; 26 import static android.content.pm.ActivityInfo.LAUNCH_SINGLE_TASK; 27 import static android.content.res.Configuration.EMPTY; 28 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 29 import static android.view.Display.DEFAULT_DISPLAY; 30 import static android.view.Display.INVALID_DISPLAY; 31 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE; 32 import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG; 33 import static android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE; 34 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_OCCLUDING; 35 import static android.view.WindowManager.TRANSIT_NONE; 36 import static android.view.WindowManager.TRANSIT_PIP; 37 import static android.view.WindowManager.TRANSIT_SLEEP; 38 import static android.view.WindowManager.TRANSIT_WAKE; 39 import static android.window.DesktopExperienceFlags.ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT; 40 41 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_FOCUS_LIGHT; 42 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_KEEP_SCREEN_ON; 43 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_ORIENTATION; 44 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_SLEEP_TOKEN; 45 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_STATES; 46 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_TASKS; 47 import static com.android.internal.protolog.WmProtoLogGroups.WM_DEBUG_WALLPAPER; 48 import static com.android.internal.protolog.WmProtoLogGroups.WM_SHOW_SURFACE_ALLOC; 49 import static com.android.server.policy.PhoneWindowManager.SYSTEM_DIALOG_REASON_ASSIST; 50 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT; 51 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 52 import static com.android.server.wm.ActivityRecord.State.FINISHING; 53 import static com.android.server.wm.ActivityRecord.State.PAUSED; 54 import static com.android.server.wm.ActivityRecord.State.RESUMED; 55 import static com.android.server.wm.ActivityRecord.State.STOPPED; 56 import static com.android.server.wm.ActivityRecord.State.STOPPING; 57 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RECENTS; 58 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ROOT_TASK; 59 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; 60 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RECENTS; 61 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES; 62 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS; 63 import static com.android.server.wm.ActivityTaskManagerService.ANIMATE; 64 import static com.android.server.wm.ActivityTaskManagerService.TAG_SWITCH; 65 import static com.android.server.wm.ActivityTaskManagerService.isPip2ExperimentEnabled; 66 import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME; 67 import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP; 68 import static com.android.server.wm.ActivityTaskSupervisor.dumpHistoryList; 69 import static com.android.server.wm.ActivityTaskSupervisor.printThisActivity; 70 import static com.android.server.wm.RootWindowContainerProto.IS_HOME_RECENTS_COMPONENT; 71 import static com.android.server.wm.RootWindowContainerProto.KEYGUARD_CONTROLLER; 72 import static com.android.server.wm.RootWindowContainerProto.WINDOW_CONTAINER; 73 import static com.android.server.wm.Task.REPARENT_LEAVE_ROOT_TASK_IN_PLACE; 74 import static com.android.server.wm.Task.REPARENT_MOVE_ROOT_TASK_TO_FRONT; 75 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS; 76 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE; 77 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 78 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 79 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_NORMAL; 80 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES; 81 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES; 82 83 import static java.lang.Integer.MAX_VALUE; 84 85 import android.annotation.IntDef; 86 import android.annotation.NonNull; 87 import android.annotation.Nullable; 88 import android.annotation.UserIdInt; 89 import android.app.ActivityManager; 90 import android.app.ActivityOptions; 91 import android.app.ActivityTaskManager.RootTaskInfo; 92 import android.app.AppGlobals; 93 import android.app.WindowConfiguration; 94 import android.content.ComponentName; 95 import android.content.Context; 96 import android.content.Intent; 97 import android.content.pm.ActivityInfo; 98 import android.content.pm.ApplicationInfo; 99 import android.content.pm.ResolveInfo; 100 import android.content.pm.UserProperties; 101 import android.content.res.Configuration; 102 import android.graphics.Rect; 103 import android.graphics.Region; 104 import android.hardware.display.DisplayManager; 105 import android.hardware.display.DisplayManagerInternal; 106 import android.hardware.display.DisplayManagerInternal.DisplayBrightnessOverrideRequest; 107 import android.hardware.power.Mode; 108 import android.net.Uri; 109 import android.os.Binder; 110 import android.os.Debug; 111 import android.os.FactoryTest; 112 import android.os.Handler; 113 import android.os.IBinder; 114 import android.os.Looper; 115 import android.os.Message; 116 import android.os.PowerManager; 117 import android.os.RemoteException; 118 import android.os.SystemClock; 119 import android.os.Trace; 120 import android.os.UserHandle; 121 import android.os.storage.StorageManager; 122 import android.provider.Settings; 123 import android.service.voice.IVoiceInteractionSession; 124 import android.util.ArrayMap; 125 import android.util.ArraySet; 126 import android.util.IntArray; 127 import android.util.Pair; 128 import android.util.Slog; 129 import android.util.SparseArray; 130 import android.util.SparseIntArray; 131 import android.util.TimeUtils; 132 import android.util.proto.ProtoOutputStream; 133 import android.view.Display; 134 import android.view.DisplayInfo; 135 import android.view.SurfaceControl; 136 import android.view.WindowManager; 137 import android.window.DesktopModeFlags; 138 import android.window.TaskFragmentAnimationParams; 139 import android.window.WindowContainerToken; 140 141 import com.android.internal.annotations.VisibleForTesting; 142 import com.android.internal.app.ResolverActivity; 143 import com.android.internal.protolog.ProtoLog; 144 import com.android.internal.util.function.pooled.PooledLambda; 145 import com.android.internal.util.function.pooled.PooledPredicate; 146 import com.android.server.LocalServices; 147 import com.android.server.am.ActivityManagerService; 148 import com.android.server.am.AppTimeTracker; 149 import com.android.server.am.UserState; 150 import com.android.server.pm.UserManagerInternal; 151 import com.android.server.policy.PermissionPolicyInternal; 152 import com.android.server.policy.WindowManagerPolicy; 153 import com.android.server.utils.Slogf; 154 import com.android.server.wm.utils.RegionUtils; 155 import com.android.window.flags.Flags; 156 157 import java.io.FileDescriptor; 158 import java.io.PrintWriter; 159 import java.lang.annotation.Retention; 160 import java.lang.annotation.RetentionPolicy; 161 import java.util.ArrayList; 162 import java.util.Collections; 163 import java.util.List; 164 import java.util.Objects; 165 import java.util.Set; 166 import java.util.function.Consumer; 167 import java.util.function.Predicate; 168 169 /** Root {@link WindowContainer} for the device. */ 170 class RootWindowContainer extends WindowContainer<DisplayContent> 171 implements DisplayManager.DisplayListener { 172 private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM; 173 174 private static final int SET_SCREEN_BRIGHTNESS_OVERRIDE = 1; 175 private static final int SET_USER_ACTIVITY_TIMEOUT = 2; 176 private static final int MSG_SEND_SLEEP_TRANSITION = 3; 177 private static final int PINNED_TASK_ABORT_TIMEOUT = 1000; 178 179 static final String TAG_TASKS = TAG + POSTFIX_TASKS; 180 static final String TAG_STATES = TAG + POSTFIX_STATES; 181 private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS; 182 183 private static final long SLEEP_TRANSITION_WAIT_MILLIS = 1000L; 184 185 private Object mLastWindowFreezeSource = null; 186 // Per-display WindowManager overrides that are passed on. 187 private final SparseArray<DisplayBrightnessOverrideRequest> mDisplayBrightnessOverrides = 188 new SparseArray<>(); 189 private long mUserActivityTimeout = -1; 190 private boolean mUpdateRotation = false; 191 // Only set while traversing the default display based on its content. 192 // Affects the behavior of mirroring on secondary displays. 193 private boolean mObscureApplicationContentOnSecondaryDisplays = false; 194 195 private boolean mSustainedPerformanceModeEnabled = false; 196 private boolean mSustainedPerformanceModeCurrent = false; 197 198 private final Handler mHandler; 199 200 private String mCloseSystemDialogsReason; 201 202 // The ID of the display which is responsible for receiving display-unspecified key and pointer 203 // events. 204 private int mTopFocusedDisplayId = INVALID_DISPLAY; 205 206 // Map from the PID to the top most app which has a focused window of the process. 207 final ArrayMap<Integer, ActivityRecord> mTopFocusedAppByProcess = new ArrayMap<>(); 208 209 // The tag for the token to put root tasks on the displays to sleep. 210 private static final String DISPLAY_OFF_SLEEP_TOKEN_TAG = "Display-off"; 211 212 /** The token acquirer to put root tasks on the displays to sleep */ 213 final ActivityTaskManagerService.SleepTokenAcquirer mDisplayOffTokenAcquirer; 214 215 /** 216 * The modes which affect which tasks are returned when calling 217 * {@link RootWindowContainer#anyTaskForId(int)}. 218 */ 219 @Retention(RetentionPolicy.SOURCE) 220 @IntDef({ 221 MATCH_ATTACHED_TASK_ONLY, 222 MATCH_ATTACHED_TASK_OR_RECENT_TASKS, 223 MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE 224 }) 225 public @interface AnyTaskForIdMatchTaskMode { 226 } 227 228 // Match only tasks that are attached to the hierarchy 229 static final int MATCH_ATTACHED_TASK_ONLY = 0; 230 // Match either attached tasks, or in the recent tasks if the tasks are detached 231 static final int MATCH_ATTACHED_TASK_OR_RECENT_TASKS = 1; 232 // Match either attached tasks, or in the recent tasks, restoring it to the provided task id 233 static final int MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE = 2; 234 235 ActivityTaskManagerService mService; 236 ActivityTaskSupervisor mTaskSupervisor; 237 WindowManagerService mWindowManager; 238 DisplayManager mDisplayManager; 239 private DisplayManagerInternal mDisplayManagerInternal; 240 @NonNull 241 private final DeviceStateController mDeviceStateController; 242 @NonNull 243 private final DisplayRotationCoordinator mDisplayRotationCoordinator; 244 245 /** Reference to default display so we can quickly look it up. */ 246 private DisplayContent mDefaultDisplay; 247 private final SparseArray<IntArray> mDisplayAccessUIDs = new SparseArray<>(); 248 private final SparseArray<SurfaceControl.Transaction> mDisplayTransactions = 249 new SparseArray<>(); 250 251 /** The current user */ 252 int mCurrentUser; 253 /** Root task id of the front root task when user switched, indexed by userId. */ 254 SparseIntArray mUserRootTaskInFront = new SparseIntArray(2); 255 SparseArray<IntArray> mUserVisibleRootTasks = new SparseArray<>(); 256 257 /** 258 * A list of tokens that cause the top activity to be put to sleep. 259 * They are used by components that may hide and block interaction with underlying 260 * activities. 261 */ 262 final SparseArray<SleepToken> mSleepTokens = new SparseArray<>(); 263 264 // Whether tasks have moved and we need to rank the tasks before next OOM scoring 265 private boolean mTaskLayersChanged = true; 266 private int mTmpTaskLayerRank; 267 private final RankTaskLayersRunnable mRankTaskLayersRunnable = new RankTaskLayersRunnable(); 268 private Region mTmpOccludingRegion; 269 private Region mTmpTaskRegion; 270 271 private String mDestroyAllActivitiesReason; 272 private final Runnable mDestroyAllActivitiesRunnable = new Runnable() { 273 @Override 274 public void run() { 275 synchronized (mService.mGlobalLock) { 276 try { 277 mTaskSupervisor.beginDeferResume(); 278 forAllActivities(r -> { 279 if (r.finishing || !r.isDestroyable()) return; 280 if (DEBUG_SWITCH) { 281 Slog.v(TAG_SWITCH, "Destroying " + r + " in state " + r.getState() 282 + " resumed=" + r.getTask().getTopResumedActivity() 283 + " pausing=" + r.getTask().getTopPausingActivity() 284 + " for reason " + mDestroyAllActivitiesReason); 285 } 286 r.destroyImmediately(mDestroyAllActivitiesReason); 287 }); 288 } finally { 289 mTaskSupervisor.endDeferResume(); 290 resumeFocusedTasksTopActivities(); 291 } 292 } 293 } 294 295 }; 296 297 // TODO: b/335866033 Remove the abort PiP on timeout once PiP2 flag is on. 298 @Nullable private Runnable mMaybeAbortPipEnterRunnable = null; 299 300 private final FindTaskResult mTmpFindTaskResult = new FindTaskResult(); 301 302 static class FindTaskResult implements Predicate<Task> { 303 ActivityRecord mIdealRecord; 304 ActivityRecord mCandidateRecord; 305 306 private int mActivityType; 307 private String mTaskAffinity; 308 private Intent mIntent; 309 private ActivityInfo mInfo; 310 private ComponentName cls; 311 private int userId; 312 private boolean isDocument; 313 private Uri documentData; 314 315 // determines whether to include bubbled tasks. defaults to true to preserve previous 316 // behavior. 317 private boolean mIncludeLaunchedFromBubble = true; 318 init(int activityType, String taskAffinity, Intent intent, ActivityInfo info, boolean includeLaunchedFromBubble)319 void init(int activityType, String taskAffinity, Intent intent, ActivityInfo info, 320 boolean includeLaunchedFromBubble) { 321 mActivityType = activityType; 322 mTaskAffinity = taskAffinity; 323 mIntent = intent; 324 mInfo = info; 325 mIdealRecord = null; 326 mCandidateRecord = null; 327 mIncludeLaunchedFromBubble = includeLaunchedFromBubble; 328 } 329 330 /** 331 * Returns the top activity in any existing task matching the given Intent in the input 332 * result. Returns null if no such task is found. 333 */ process(WindowContainer parent)334 void process(WindowContainer parent) { 335 cls = mIntent.getComponent(); 336 if (mInfo.targetActivity != null) { 337 cls = new ComponentName(mInfo.packageName, mInfo.targetActivity); 338 } 339 userId = UserHandle.getUserId(mInfo.applicationInfo.uid); 340 isDocument = mIntent != null & mIntent.isDocument(); 341 // If documentData is non-null then it must match the existing task data. 342 documentData = isDocument ? mIntent.getData() : null; 343 344 ProtoLog.d(WM_DEBUG_TASKS, "Looking for task of %s in %s", mInfo, 345 parent); 346 parent.forAllLeafTasks(this); 347 } 348 349 @Override test(Task task)350 public boolean test(Task task) { 351 if (!ConfigurationContainer.isCompatibleActivityType(mActivityType, 352 task.getActivityType())) { 353 ProtoLog.d(WM_DEBUG_TASKS, "Skipping task: (mismatch activity/task) %s", task); 354 return false; 355 } 356 357 if (task.voiceSession != null) { 358 // We never match voice sessions; those always run independently. 359 ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: voice session", task); 360 return false; 361 } 362 if (task.mUserId != userId) { 363 // Looking for a different task. 364 ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: different user", task); 365 return false; 366 } 367 368 // Overlays should not be considered as the task's logical top activity. 369 final ActivityRecord r = task.getTopNonFinishingActivity( 370 false /* includeOverlays */, mIncludeLaunchedFromBubble); 371 372 if (r == null || r.finishing || r.mUserId != userId 373 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { 374 ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: mismatch root %s", task, r); 375 return false; 376 } 377 if (!ConfigurationContainer.isCompatibleActivityType(r.getActivityType(), 378 mActivityType)) { 379 ProtoLog.d(WM_DEBUG_TASKS, "Skipping %s: mismatch activity type", task); 380 return false; 381 } 382 383 final Intent taskIntent = task.intent; 384 final Intent affinityIntent = task.affinityIntent; 385 final boolean taskIsDocument; 386 final Uri taskDocumentData; 387 if (taskIntent != null && taskIntent.isDocument()) { 388 taskIsDocument = true; 389 taskDocumentData = taskIntent.getData(); 390 } else if (affinityIntent != null && affinityIntent.isDocument()) { 391 taskIsDocument = true; 392 taskDocumentData = affinityIntent.getData(); 393 } else { 394 taskIsDocument = false; 395 taskDocumentData = null; 396 } 397 398 ProtoLog.d(WM_DEBUG_TASKS, "Comparing existing cls=%s /aff=%s to new cls=%s /aff=%s", 399 (task.realActivity != null ? task.realActivity.flattenToShortString() : ""), 400 task.rootAffinity, mIntent.getComponent().flattenToShortString(), 401 mTaskAffinity); 402 // TODO Refactor to remove duplications. Check if logic can be simplified. 403 if (task.realActivity != null && task.realActivity.compareTo(cls) == 0 404 && Objects.equals(documentData, taskDocumentData)) { 405 ProtoLog.d(WM_DEBUG_TASKS, "Found matching class!"); 406 //dump(); 407 ProtoLog.d(WM_DEBUG_TASKS, "For Intent %s bringing to top: %s", mIntent, r.intent); 408 mIdealRecord = r; 409 return true; 410 } else if (affinityIntent != null && affinityIntent.getComponent() != null 411 && affinityIntent.getComponent().compareTo(cls) == 0 && 412 Objects.equals(documentData, taskDocumentData)) { 413 ProtoLog.d(WM_DEBUG_TASKS, "Found matching class!"); 414 ProtoLog.d(WM_DEBUG_TASKS, "For Intent %s bringing to top: %s", mIntent, r.intent); 415 mIdealRecord = r; 416 return true; 417 } else if (!isDocument && !taskIsDocument 418 && mIdealRecord == null && mCandidateRecord == null 419 && task.rootAffinity != null) { 420 if (task.rootAffinity.equals(mTaskAffinity) 421 && task.isSameRequiredDisplayCategory(mInfo)) { 422 ProtoLog.d(WM_DEBUG_TASKS, "Found matching affinity candidate!"); 423 // It is possible for multiple tasks to have the same root affinity especially 424 // if they are in separate root tasks. We save off this candidate, but keep 425 // looking to see if there is a better candidate. 426 mCandidateRecord = r; 427 } 428 } else { 429 ProtoLog.d(WM_DEBUG_TASKS, "Not a match: %s", task); 430 } 431 432 return false; 433 } 434 } 435 436 private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> { 437 if (w.mHasSurface) { 438 try { 439 w.mClient.closeSystemDialogs(mCloseSystemDialogsReason); 440 } catch (RemoteException e) { 441 } 442 } 443 }; 444 RootWindowContainer(WindowManagerService service)445 RootWindowContainer(WindowManagerService service) { 446 super(service); 447 mHandler = new MyHandler(service.mH.getLooper()); 448 mService = service.mAtmService; 449 mTaskSupervisor = mService.mTaskSupervisor; 450 mTaskSupervisor.mRootWindowContainer = this; 451 mDisplayOffTokenAcquirer = mService.new SleepTokenAcquirer(DISPLAY_OFF_SLEEP_TOKEN_TAG); 452 mDeviceStateController = new DeviceStateController(service.mContext, service.mGlobalLock); 453 mDisplayRotationCoordinator = new DisplayRotationCoordinator(); 454 } 455 456 /** 457 * Updates the children's focused window and the top focused display if needed. 458 */ updateFocusedWindowLocked(int mode, boolean updateInputWindows)459 boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) { 460 mTopFocusedAppByProcess.clear(); 461 boolean changed = false; 462 int topFocusedDisplayId = INVALID_DISPLAY; 463 // Go through the children in z-order starting at the top-most 464 for (int i = mChildren.size() - 1; i >= 0; --i) { 465 final DisplayContent dc = mChildren.get(i); 466 changed |= dc.updateFocusedWindowLocked(mode, updateInputWindows, topFocusedDisplayId); 467 final WindowState newFocus = dc.mCurrentFocus; 468 if (newFocus != null) { 469 final int pidOfNewFocus = newFocus.mSession.mPid; 470 if (mTopFocusedAppByProcess.get(pidOfNewFocus) == null) { 471 mTopFocusedAppByProcess.put(pidOfNewFocus, newFocus.mActivityRecord); 472 } 473 if (topFocusedDisplayId == INVALID_DISPLAY) { 474 topFocusedDisplayId = dc.getDisplayId(); 475 } 476 } else if (topFocusedDisplayId == INVALID_DISPLAY && dc.mFocusedApp != null) { 477 // The top-most display that has a focused app should still be the top focused 478 // display even when the app window is not ready yet (process not attached or 479 // window not added yet). 480 topFocusedDisplayId = dc.getDisplayId(); 481 } 482 } 483 if (topFocusedDisplayId == INVALID_DISPLAY) { 484 topFocusedDisplayId = DEFAULT_DISPLAY; 485 } 486 if (mTopFocusedDisplayId != topFocusedDisplayId) { 487 mTopFocusedDisplayId = topFocusedDisplayId; 488 mWmService.mInputManager.setFocusedDisplay(topFocusedDisplayId); 489 mWmService.mPolicy.setTopFocusedDisplay(topFocusedDisplayId); 490 mWmService.mAccessibilityController.setFocusedDisplay(topFocusedDisplayId); 491 ProtoLog.d(WM_DEBUG_FOCUS_LIGHT, "New topFocusedDisplayId=%d", topFocusedDisplayId); 492 } 493 return changed; 494 } 495 getTopFocusedDisplayContent()496 DisplayContent getTopFocusedDisplayContent() { 497 final DisplayContent dc = getDisplayContent(mTopFocusedDisplayId); 498 return dc != null ? dc : getDisplayContent(DEFAULT_DISPLAY); 499 } 500 501 @Override isOnTop()502 boolean isOnTop() { 503 // Considered always on top 504 return true; 505 } 506 507 @Override onChildPositionChanged(WindowContainer child)508 void onChildPositionChanged(WindowContainer child) { 509 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, 510 !mWmService.mPerDisplayFocusEnabled /* updateInputWindows */); 511 mTaskSupervisor.updateTopResumedActivityIfNeeded("onChildPositionChanged"); 512 } 513 514 @Override isAttached()515 boolean isAttached() { 516 return true; 517 } 518 519 /** 520 * Called when DisplayWindowSettings values may change. 521 */ onSettingsRetrieved()522 void onSettingsRetrieved() { 523 final int numDisplays = mChildren.size(); 524 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 525 final DisplayContent displayContent = mChildren.get(displayNdx); 526 final boolean changed = mWmService.mDisplayWindowSettings.updateSettingsForDisplay( 527 displayContent); 528 if (!changed) { 529 continue; 530 } 531 532 displayContent.reconfigureDisplayLocked(); 533 534 // We need to update global configuration as well if config of default display has 535 // changed. Do it inline because ATMS#retrieveSettings() will soon update the 536 // configuration inline, which will overwrite the new windowing mode. 537 if (displayContent.isDefaultDisplay) { 538 final Configuration newConfig = mWmService.computeNewConfiguration( 539 displayContent.getDisplayId()); 540 mWmService.mAtmService.updateConfigurationLocked(newConfig, null /* starting */, 541 false /* initLocale */); 542 } 543 } 544 } 545 isLayoutNeeded()546 boolean isLayoutNeeded() { 547 final int numDisplays = mChildren.size(); 548 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 549 final DisplayContent displayContent = mChildren.get(displayNdx); 550 if (displayContent.isLayoutNeeded()) { 551 return true; 552 } 553 } 554 return false; 555 } 556 getWindowsByName(ArrayList<WindowState> output, String name)557 void getWindowsByName(ArrayList<WindowState> output, String name) { 558 int objectId = 0; 559 // See if this is an object ID. 560 try { 561 objectId = Integer.parseInt(name, 16); 562 name = null; 563 } catch (RuntimeException e) { 564 } 565 566 getWindowsByName(output, name, objectId); 567 } 568 getWindowsByName(ArrayList<WindowState> output, String name, int objectId)569 private void getWindowsByName(ArrayList<WindowState> output, String name, int objectId) { 570 forAllWindows((w) -> { 571 if (name != null) { 572 if (w.mAttrs.getTitle().toString().contains(name)) { 573 output.add(w); 574 } 575 } else if (System.identityHashCode(w) == objectId) { 576 output.add(w); 577 } 578 }, true /* traverseTopToBottom */); 579 } 580 581 /** Returns the window token for the input binder if it exist in the system. */ getWindowToken(IBinder binder)582 WindowToken getWindowToken(IBinder binder) { 583 for (int i = mChildren.size() - 1; i >= 0; --i) { 584 final DisplayContent dc = mChildren.get(i); 585 final WindowToken wtoken = dc.getWindowToken(binder); 586 if (wtoken != null) { 587 return wtoken; 588 } 589 } 590 return null; 591 } 592 593 /** Returns the display object the input window token is currently mapped on. */ getWindowTokenDisplay(WindowToken token)594 DisplayContent getWindowTokenDisplay(WindowToken token) { 595 if (token == null) { 596 return null; 597 } 598 599 for (int i = mChildren.size() - 1; i >= 0; --i) { 600 final DisplayContent dc = mChildren.get(i); 601 final WindowToken current = dc.getWindowToken(token.token); 602 if (current == token) { 603 return dc; 604 } 605 } 606 607 return null; 608 } 609 610 @Override dispatchConfigurationToChild(DisplayContent child, Configuration config)611 void dispatchConfigurationToChild(DisplayContent child, Configuration config) { 612 if (child.isDefaultDisplay) { 613 // The global configuration is also the override configuration of default display. 614 child.performDisplayOverrideConfigUpdate(config); 615 } else { 616 child.onConfigurationChanged(config); 617 } 618 } 619 refreshSecureSurfaceState()620 void refreshSecureSurfaceState() { 621 forAllWindows(w -> { 622 w.setSecureLocked(w.isSecureLocked()); 623 }, true /* traverseTopToBottom */); 624 } 625 updateHiddenWhileSuspendedState(final ArraySet<String> packages, final boolean suspended)626 void updateHiddenWhileSuspendedState(final ArraySet<String> packages, final boolean suspended) { 627 forAllWindows((w) -> { 628 if (packages.contains(w.getOwningPackage())) { 629 w.setHiddenWhileSuspended(suspended); 630 } 631 }, false); 632 } 633 updateAppOpsState()634 void updateAppOpsState() { 635 forAllWindows((w) -> { 636 w.updateAppOpsState(); 637 }, false /* traverseTopToBottom */); 638 } 639 canShowStrictModeViolation(int pid)640 boolean canShowStrictModeViolation(int pid) { 641 final WindowState win = getWindow((w) -> w.mSession.mPid == pid && w.isVisible()); 642 return win != null; 643 } 644 closeSystemDialogs(String reason)645 void closeSystemDialogs(String reason) { 646 mCloseSystemDialogsReason = reason; 647 forAllWindows(mCloseSystemDialogsConsumer, false /* traverseTopToBottom */); 648 } 649 hasPendingLayoutChanges(WindowAnimator animator)650 boolean hasPendingLayoutChanges(WindowAnimator animator) { 651 boolean hasChanges = false; 652 653 final int count = mChildren.size(); 654 for (int i = 0; i < count; ++i) { 655 final int pendingChanges = mChildren.get(i).pendingLayoutChanges; 656 if (pendingChanges != 0) { 657 hasChanges = true; 658 } 659 } 660 661 return hasChanges; 662 } 663 reclaimSomeSurfaceMemory(WindowStateAnimator winAnimator, String operation, boolean secure)664 boolean reclaimSomeSurfaceMemory(WindowStateAnimator winAnimator, String operation, 665 boolean secure) { 666 final SurfaceControl surfaceControl = winAnimator.mSurfaceControl; 667 boolean leakedSurface = false; 668 boolean killedApps = false; 669 EventLogTags.writeWmNoSurfaceMemory(winAnimator.mWin.toString(), 670 winAnimator.mSession.mPid, operation); 671 final long callingIdentity = Binder.clearCallingIdentity(); 672 try { 673 // There was some problem...first, do a validity check of the window list to make sure 674 // we haven't left any dangling surfaces around. 675 676 Slog.i(TAG_WM, "Out of memory for surface! Looking for leaks..."); 677 final int numDisplays = mChildren.size(); 678 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 679 leakedSurface |= mChildren.get(displayNdx).destroyLeakedSurfaces(); 680 } 681 682 if (!leakedSurface) { 683 Slog.w(TAG_WM, "No leaked surfaces; killing applications!"); 684 final SparseIntArray pidCandidates = new SparseIntArray(); 685 for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) { 686 mChildren.get(displayNdx).forAllWindows((w) -> { 687 if (mWmService.mForceRemoves.contains(w)) { 688 return; 689 } 690 final WindowStateAnimator wsa = w.mWinAnimator; 691 if (wsa.mSurfaceControl != null) { 692 pidCandidates.append(wsa.mSession.mPid, wsa.mSession.mPid); 693 } 694 }, false /* traverseTopToBottom */); 695 696 if (pidCandidates.size() > 0) { 697 int[] pids = new int[pidCandidates.size()]; 698 for (int i = 0; i < pids.length; i++) { 699 pids[i] = pidCandidates.keyAt(i); 700 } 701 try { 702 if (mWmService.mActivityManager.killPids(pids, "Free memory", secure)) { 703 killedApps = true; 704 } 705 } catch (RemoteException e) { 706 } 707 } 708 } 709 } 710 711 if (leakedSurface || killedApps) { 712 // We managed to reclaim some memory, so get rid of the trouble surface and ask the 713 // app to request another one. 714 Slog.w(TAG_WM, 715 "Looks like we have reclaimed some memory, clearing surface for retry."); 716 if (surfaceControl != null) { 717 ProtoLog.i(WM_SHOW_SURFACE_ALLOC, 718 "SURFACE RECOVER DESTROY: %s", winAnimator.mWin); 719 SurfaceControl.Transaction t = mWmService.mTransactionFactory.get(); 720 winAnimator.destroySurface(t); 721 t.apply(); 722 if (winAnimator.mWin.mActivityRecord != null) { 723 winAnimator.mWin.mActivityRecord.removeStartingWindow(); 724 } 725 } 726 727 try { 728 winAnimator.mWin.mClient.dispatchGetNewSurface(); 729 } catch (RemoteException e) { 730 } 731 } 732 } finally { 733 Binder.restoreCallingIdentity(callingIdentity); 734 } 735 736 return leakedSurface || killedApps; 737 } 738 739 /** 740 * This method should only be called from {@link WindowSurfacePlacer}. Otherwise the recursion 741 * check and {@link WindowSurfacePlacer#isInLayout()} won't take effect. 742 */ performSurfacePlacement()743 void performSurfacePlacement() { 744 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "performSurfacePlacement"); 745 try { 746 performSurfacePlacementNoTrace(); 747 } finally { 748 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 749 } 750 } 751 752 // "Something has changed! Let's make it correct now." 753 // TODO: Super long method that should be broken down... performSurfacePlacementNoTrace()754 void performSurfacePlacementNoTrace() { 755 if (DEBUG_WINDOW_TRACE) { 756 Slog.v(TAG, "performSurfacePlacementInner: entry. Called by " 757 + Debug.getCallers(3)); 758 } 759 760 int i; 761 762 if (mWmService.mFocusMayChange) { 763 mWmService.mFocusMayChange = false; 764 mWmService.updateFocusedWindowLocked( 765 UPDATE_FOCUS_WILL_PLACE_SURFACES, false /*updateInputWindows*/); 766 } 767 768 mDisplayBrightnessOverrides.clear(); 769 mUserActivityTimeout = -1; 770 mObscureApplicationContentOnSecondaryDisplays = false; 771 mSustainedPerformanceModeCurrent = false; 772 mWmService.mTransactionSequence++; 773 774 // TODO(multi-display): recents animation & wallpaper need support multi-display. 775 final DisplayContent defaultDisplay = mWmService.getDefaultDisplayContentLocked(); 776 final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked; 777 778 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "applySurfaceChanges"); 779 try { 780 applySurfaceChangesTransaction(); 781 } catch (RuntimeException e) { 782 Slog.wtf(TAG, "Unhandled exception in Window Manager", e); 783 } finally { 784 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 785 } 786 787 // mWmService.mResizingWindows is populated in #applySurfaceChangesTransaction() 788 handleResizingWindows(); 789 clearFrameChangingWindows(); 790 791 // Called after #handleResizingWindows to include WindowStateResizeItem if any. 792 mWmService.mAtmService.getLifecycleManager().dispatchPendingTransactions(); 793 794 // Send any pending task-info changes that were queued-up during a layout deferment 795 mWmService.mAtmService.mTaskOrganizerController.dispatchPendingEvents(); 796 mWmService.mAtmService.mTaskFragmentOrganizerController.dispatchPendingEvents(); 797 mWmService.mSyncEngine.onSurfacePlacement(); 798 799 mWmService.mAtmService.mBackNavigationController 800 .checkAnimationReady(defaultDisplay.mWallpaperController); 801 802 for (int displayNdx = 0; displayNdx < mChildren.size(); ++displayNdx) { 803 final DisplayContent displayContent = mChildren.get(displayNdx); 804 if (displayContent.mWallpaperMayChange) { 805 ProtoLog.v(WM_DEBUG_WALLPAPER, "Wallpaper may change! Adjusting"); 806 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 807 if (DEBUG_LAYOUT_REPEATS) { 808 surfacePlacer.debugLayoutRepeats("WallpaperMayChange", 809 displayContent.pendingLayoutChanges); 810 } 811 } 812 } 813 814 if (mWmService.mFocusMayChange) { 815 mWmService.mFocusMayChange = false; 816 mWmService.updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES, 817 false /*updateInputWindows*/); 818 } 819 820 if (isLayoutNeeded()) { 821 defaultDisplay.pendingLayoutChanges |= FINISH_LAYOUT_REDO_LAYOUT; 822 if (DEBUG_LAYOUT_REPEATS) { 823 surfacePlacer.debugLayoutRepeats("mLayoutNeeded", 824 defaultDisplay.pendingLayoutChanges); 825 } 826 } 827 828 // Destroy the surface of any windows that are no longer visible. 829 i = mWmService.mDestroySurface.size(); 830 if (i > 0) { 831 do { 832 i--; 833 WindowState win = mWmService.mDestroySurface.get(i); 834 win.mDestroying = false; 835 final DisplayContent displayContent = win.getDisplayContent(); 836 if (displayContent.mInputMethodWindow == win) { 837 displayContent.setInputMethodWindowLocked(null); 838 } 839 if (displayContent.mWallpaperController.isWallpaperTarget(win)) { 840 displayContent.pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 841 } 842 win.destroySurfaceUnchecked(); 843 } while (i > 0); 844 mWmService.mDestroySurface.clear(); 845 } 846 847 for (int displayNdx = 0; displayNdx < mChildren.size(); ++displayNdx) { 848 final DisplayContent displayContent = mChildren.get(displayNdx); 849 if (displayContent.pendingLayoutChanges != 0) { 850 displayContent.setLayoutNeeded(); 851 } 852 } 853 854 // Post these on a handler such that we don't call into power manager service while 855 // holding the window manager lock to avoid lock contention with power manager lock. 856 // Send a copy of the brightness overrides as they may be cleared before being sent out. 857 mHandler.obtainMessage(SET_SCREEN_BRIGHTNESS_OVERRIDE, mDisplayBrightnessOverrides.clone()) 858 .sendToTarget(); 859 mHandler.obtainMessage(SET_USER_ACTIVITY_TIMEOUT, mUserActivityTimeout).sendToTarget(); 860 861 if (mSustainedPerformanceModeCurrent != mSustainedPerformanceModeEnabled) { 862 mSustainedPerformanceModeEnabled = mSustainedPerformanceModeCurrent; 863 mWmService.mPowerManagerInternal.setPowerMode( 864 Mode.SUSTAINED_PERFORMANCE, 865 mSustainedPerformanceModeEnabled); 866 } 867 868 if (mUpdateRotation) { 869 ProtoLog.d(WM_DEBUG_ORIENTATION, "Performing post-rotate rotation"); 870 mUpdateRotation = updateRotationUnchecked(); 871 } 872 873 if (!mWmService.mWaitingForDrawnCallbacks.isEmpty() 874 || (!isLayoutNeeded() && !mUpdateRotation)) { 875 mWmService.checkDrawnWindowsLocked(); 876 } 877 878 forAllDisplays(dc -> { 879 dc.getInputMonitor().updateInputWindowsLw(true /*force*/); 880 dc.updateSystemGestureExclusion(); 881 dc.updateKeepClearAreas(); 882 }); 883 884 // Check to see if we are now in a state where the screen should 885 // be enabled, because the window obscured flags have changed. 886 mWmService.enableScreenIfNeededLocked(); 887 888 mWmService.scheduleAnimationLocked(); 889 890 if (DEBUG_WINDOW_TRACE) Slog.e(TAG, "performSurfacePlacementInner exit"); 891 } 892 applySurfaceChangesTransaction()893 private void applySurfaceChangesTransaction() { 894 // TODO(multi-display): Support these features on secondary screens. 895 final DisplayContent defaultDc = mDefaultDisplay; 896 final DisplayInfo defaultInfo = defaultDc.getDisplayInfo(); 897 final int defaultDw = defaultInfo.logicalWidth; 898 final int defaultDh = defaultInfo.logicalHeight; 899 final SurfaceControl.Transaction t = defaultDc.getSyncTransaction(); 900 if (mWmService.mWatermark != null) { 901 mWmService.mWatermark.positionSurface(defaultDw, defaultDh, t); 902 } 903 if (mWmService.mStrictModeFlash != null) { 904 mWmService.mStrictModeFlash.positionSurface(defaultDw, defaultDh, t); 905 } 906 if (mWmService.mEmulatorDisplayOverlay != null) { 907 mWmService.mEmulatorDisplayOverlay.positionSurface(defaultDw, defaultDh, 908 defaultDc.getRotation(), t); 909 } 910 911 final int count = mChildren.size(); 912 for (int j = 0; j < count; ++j) { 913 final DisplayContent dc = mChildren.get(j); 914 dc.applySurfaceChangesTransaction(); 915 mDisplayTransactions.append(dc.mDisplayId, dc.getSyncTransaction()); 916 } 917 918 // Give the display manager a chance to adjust properties like display rotation if it needs 919 // to. 920 mWmService.mDisplayManagerInternal.performTraversal(t, mDisplayTransactions); 921 mDisplayTransactions.clear(); 922 } 923 924 /** 925 * Handles resizing windows during surface placement. 926 */ handleResizingWindows()927 private void handleResizingWindows() { 928 for (int i = mWmService.mResizingWindows.size() - 1; i >= 0; i--) { 929 WindowState win = mWmService.mResizingWindows.get(i); 930 if (win.getDisplayContent().mWaitingForConfig) { 931 // Don't remove this window until rotation has completed and is not waiting for the 932 // complete configuration. 933 continue; 934 } 935 win.updateSurfacePositionIfNeeded(); 936 win.reportResized(); 937 mWmService.mResizingWindows.remove(i); 938 } 939 } 940 941 /** 942 * Clears frame changing windows after handling moving and resizing windows. 943 */ clearFrameChangingWindows()944 private void clearFrameChangingWindows() { 945 final ArrayList<WindowState> frameChangingWindows = mWmService.mFrameChangingWindows; 946 for (int i = frameChangingWindows.size() - 1; i >= 0; i--) { 947 frameChangingWindows.get(i).updateLastFrames(); 948 } 949 frameChangingWindows.clear(); 950 } 951 952 /** 953 * @param w WindowState this method is applied to. 954 * @param obscured True if there is a window on top of this obscuring the display. 955 * @param syswin System window? 956 * @return True when the display contains content to show the user. When false, the display 957 * manager may choose to mirror or blank the display. 958 */ handleNotObscuredLocked(WindowState w, boolean obscured, boolean syswin)959 boolean handleNotObscuredLocked(WindowState w, boolean obscured, boolean syswin) { 960 final boolean onScreen = w.isOnScreen(); 961 boolean displayHasContent = false; 962 963 ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON, 964 "handleNotObscuredLocked w: %s, w.mHasSurface: %b, w.isOnScreen(): %b, w" 965 + ".isDisplayedLw(): %b, w.mAttrs.userActivityTimeout: %d", 966 w, w.mHasSurface, onScreen, w.isDisplayed(), w.mAttrs.userActivityTimeout); 967 if (!onScreen) { 968 return false; 969 } 970 if (!syswin && w.mAttrs.userActivityTimeout >= 0 && mUserActivityTimeout < 0) { 971 mUserActivityTimeout = w.mAttrs.userActivityTimeout; 972 ProtoLog.d(WM_DEBUG_KEEP_SCREEN_ON, "mUserActivityTimeout set to %d", 973 mUserActivityTimeout); 974 } 975 if (w.isDrawn() || (w.mActivityRecord != null && w.mActivityRecord.firstWindowDrawn 976 && w.mActivityRecord.isVisibleRequested())) { 977 if (!syswin && w.mAttrs.screenBrightness >= PowerManager.BRIGHTNESS_MIN 978 && w.mAttrs.screenBrightness <= PowerManager.BRIGHTNESS_MAX 979 && !mDisplayBrightnessOverrides.contains(w.getDisplayId())) { 980 var brightnessOverride = new DisplayBrightnessOverrideRequest(); 981 brightnessOverride.brightness = w.mAttrs.screenBrightness; 982 brightnessOverride.tag = w.getWindowTag(); 983 mDisplayBrightnessOverrides.put(w.getDisplayId(), brightnessOverride); 984 } 985 986 // This function assumes that the contents of the default display are processed first 987 // before secondary displays. 988 final DisplayContent displayContent = w.getDisplayContent(); 989 if (displayContent != null && displayContent.isDefaultDisplay) { 990 // While a dream or keyguard is showing, obscure ordinary application content on 991 // secondary displays (by forcibly enabling mirroring unless there is other content 992 // we want to show) but still allow opaque keyguard dialogs to be shown. 993 if (w.isDreamWindow() || mWmService.mPolicy.isKeyguardShowing()) { 994 mObscureApplicationContentOnSecondaryDisplays = true; 995 } 996 displayHasContent = true; 997 } else if (displayContent != null && 998 (!mObscureApplicationContentOnSecondaryDisplays 999 || displayContent.isKeyguardAlwaysUnlocked() 1000 || (obscured && w.mAttrs.type == TYPE_KEYGUARD_DIALOG))) { 1001 // Allow full screen keyguard presentation dialogs to be seen, or simply ignore the 1002 // keyguard if this display is always unlocked. 1003 displayHasContent = true; 1004 } 1005 if ((w.mAttrs.privateFlags & PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE) != 0) { 1006 mSustainedPerformanceModeCurrent = true; 1007 } 1008 } 1009 1010 return displayHasContent; 1011 } 1012 updateRotationUnchecked()1013 boolean updateRotationUnchecked() { 1014 boolean changed = false; 1015 for (int i = mChildren.size() - 1; i >= 0; i--) { 1016 if (mChildren.get(i).getDisplayRotation().updateRotationAndSendNewConfigIfChanged()) { 1017 changed = true; 1018 } 1019 } 1020 return changed; 1021 } 1022 1023 private final class MyHandler extends Handler { 1024 MyHandler(Looper looper)1025 public MyHandler(Looper looper) { 1026 super(looper); 1027 } 1028 1029 @Override handleMessage(Message msg)1030 public void handleMessage(Message msg) { 1031 switch (msg.what) { 1032 case SET_SCREEN_BRIGHTNESS_OVERRIDE: 1033 var brightnessOverrides = 1034 (SparseArray<DisplayBrightnessOverrideRequest>) msg.obj; 1035 mWmService.mDisplayManagerInternal.setScreenBrightnessOverrideFromWindowManager( 1036 brightnessOverrides); 1037 break; 1038 case SET_USER_ACTIVITY_TIMEOUT: 1039 mWmService.mPowerManagerInternal. 1040 setUserActivityTimeoutOverrideFromWindowManager((Long) msg.obj); 1041 break; 1042 case MSG_SEND_SLEEP_TRANSITION: 1043 synchronized (mService.mGlobalLock) { 1044 sendSleepTransition((DisplayContent) msg.obj); 1045 } 1046 break; 1047 default: 1048 break; 1049 } 1050 } 1051 } 1052 dumpDisplayContents(PrintWriter pw)1053 void dumpDisplayContents(PrintWriter pw) { 1054 pw.println("WINDOW MANAGER DISPLAY CONTENTS (dumpsys window displays)"); 1055 if (mWmService.mDisplayReady) { 1056 final int count = mChildren.size(); 1057 for (int i = 0; i < count; ++i) { 1058 final DisplayContent displayContent = mChildren.get(i); 1059 displayContent.dump(pw, " ", true /* dumpAll */); 1060 } 1061 } else { 1062 pw.println(" NO DISPLAY"); 1063 } 1064 } 1065 dumpTopFocusedDisplayId(PrintWriter pw)1066 void dumpTopFocusedDisplayId(PrintWriter pw) { 1067 pw.print(" mTopFocusedDisplayId="); 1068 pw.println(mTopFocusedDisplayId); 1069 } 1070 dumpLayoutNeededDisplayIds(PrintWriter pw)1071 void dumpLayoutNeededDisplayIds(PrintWriter pw) { 1072 if (!isLayoutNeeded()) { 1073 return; 1074 } 1075 pw.print(" mLayoutNeeded on displays="); 1076 final int count = mChildren.size(); 1077 for (int displayNdx = 0; displayNdx < count; ++displayNdx) { 1078 final DisplayContent displayContent = mChildren.get(displayNdx); 1079 if (displayContent.isLayoutNeeded()) { 1080 pw.print(displayContent.getDisplayId()); 1081 } 1082 } 1083 pw.println(); 1084 } 1085 dumpWindowsNoHeader(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows)1086 void dumpWindowsNoHeader(PrintWriter pw, boolean dumpAll, ArrayList<WindowState> windows) { 1087 final int[] index = new int[1]; 1088 forAllWindows((w) -> { 1089 if (windows == null || windows.contains(w)) { 1090 pw.println(" Window #" + index[0] + " " + w + ":"); 1091 w.dump(pw, " ", dumpAll || windows != null); 1092 index[0] = index[0] + 1; 1093 } 1094 }, true /* traverseTopToBottom */); 1095 } 1096 dumpTokens(PrintWriter pw, boolean dumpAll)1097 void dumpTokens(PrintWriter pw, boolean dumpAll) { 1098 pw.println(" All tokens:"); 1099 for (int i = mChildren.size() - 1; i >= 0; --i) { 1100 mChildren.get(i).dumpTokens(pw, dumpAll); 1101 } 1102 } 1103 1104 @Override dumpDebug(ProtoOutputStream proto, long fieldId, @WindowTracingLogLevel int logLevel)1105 public void dumpDebug(ProtoOutputStream proto, long fieldId, 1106 @WindowTracingLogLevel int logLevel) { 1107 if (logLevel == WindowTracingLogLevel.CRITICAL && !isVisible()) { 1108 return; 1109 } 1110 1111 final long token = proto.start(fieldId); 1112 super.dumpDebug(proto, WINDOW_CONTAINER, logLevel); 1113 1114 mTaskSupervisor.getKeyguardController().dumpDebug(proto, KEYGUARD_CONTROLLER); 1115 proto.write(IS_HOME_RECENTS_COMPONENT, 1116 mTaskSupervisor.mRecentTasks.isRecentsComponentHomeActivity(mCurrentUser)); 1117 proto.end(token); 1118 } 1119 1120 @Override getName()1121 String getName() { 1122 return "ROOT"; 1123 } 1124 1125 @Override removeChild(DisplayContent dc)1126 protected void removeChild(DisplayContent dc) { 1127 super.removeChild(dc); 1128 if (mTopFocusedDisplayId == dc.getDisplayId()) { 1129 mWmService.updateFocusedWindowLocked( 1130 UPDATE_FOCUS_NORMAL, true /* updateInputWindows */); 1131 } 1132 } 1133 1134 /** 1135 * For all display at or below this call the callback. 1136 * 1137 * @param callback Callback to be called for every display. 1138 */ forAllDisplays(Consumer<DisplayContent> callback)1139 void forAllDisplays(Consumer<DisplayContent> callback) { 1140 for (int i = mChildren.size() - 1; i >= 0; --i) { 1141 callback.accept(mChildren.get(i)); 1142 } 1143 } 1144 forAllDisplayPolicies(Consumer<DisplayPolicy> callback)1145 void forAllDisplayPolicies(Consumer<DisplayPolicy> callback) { 1146 for (int i = mChildren.size() - 1; i >= 0; --i) { 1147 callback.accept(mChildren.get(i).getDisplayPolicy()); 1148 } 1149 } 1150 1151 /** 1152 * Get current topmost focused IME window in system. 1153 * Will look on all displays in current Z-order. 1154 */ getCurrentInputMethodWindow()1155 WindowState getCurrentInputMethodWindow() { 1156 for (int i = mChildren.size() - 1; i >= 0; --i) { 1157 final DisplayContent displayContent = mChildren.get(i); 1158 if (displayContent.mInputMethodWindow != null) { 1159 return displayContent.mInputMethodWindow; 1160 } 1161 } 1162 return null; 1163 } 1164 getDisplayContextsWithNonToastVisibleWindows(int pid, List<Context> outContexts)1165 void getDisplayContextsWithNonToastVisibleWindows(int pid, List<Context> outContexts) { 1166 if (outContexts == null) { 1167 return; 1168 } 1169 for (int i = mChildren.size() - 1; i >= 0; --i) { 1170 DisplayContent dc = mChildren.get(i); 1171 if (dc.getWindow(w -> pid == w.mSession.mPid && w.isVisibleNow() 1172 && w.mAttrs.type != WindowManager.LayoutParams.TYPE_TOAST) != null) { 1173 outContexts.add(dc.getDisplayUiContext()); 1174 } 1175 } 1176 } 1177 1178 @Nullable getDisplayUiContext(int displayId)1179 Context getDisplayUiContext(int displayId) { 1180 return getDisplayContent(displayId) != null 1181 ? getDisplayContent(displayId).getDisplayUiContext() : null; 1182 } 1183 setWindowManager(WindowManagerService wm)1184 void setWindowManager(WindowManagerService wm) { 1185 mWindowManager = wm; 1186 mDisplayManager = mService.mContext.getSystemService(DisplayManager.class); 1187 mDisplayManager.registerDisplayListener(this, mService.mUiHandler); 1188 mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class); 1189 1190 final Display[] displays = mDisplayManager.getDisplays(); 1191 for (int displayNdx = 0; displayNdx < displays.length; ++displayNdx) { 1192 final Display display = displays[displayNdx]; 1193 final DisplayContent displayContent = 1194 new DisplayContent(display, this, mDeviceStateController); 1195 addChild(displayContent, POSITION_BOTTOM); 1196 if (displayContent.mDisplayId == DEFAULT_DISPLAY) { 1197 mDefaultDisplay = displayContent; 1198 } 1199 } 1200 1201 final TaskDisplayArea defaultTaskDisplayArea = getDefaultTaskDisplayArea(); 1202 defaultTaskDisplayArea.getOrCreateRootHomeTask(ON_TOP); 1203 positionChildAt(POSITION_TOP, defaultTaskDisplayArea.mDisplayContent, 1204 false /* includingParents */); 1205 } 1206 1207 /** 1208 * Called just before display manager has applied the device state to the displays 1209 * @param deviceState device state as defined by 1210 * {@link android.hardware.devicestate.DeviceStateManager} 1211 */ onDisplayManagerReceivedDeviceState(int deviceState)1212 void onDisplayManagerReceivedDeviceState(int deviceState) { 1213 mDeviceStateController.onDeviceStateReceivedByDisplayManager(deviceState); 1214 } 1215 1216 // TODO(multi-display): Look at all callpoints to make sure they make sense in multi-display. getDefaultDisplay()1217 DisplayContent getDefaultDisplay() { 1218 return mDefaultDisplay; 1219 } 1220 1221 @NonNull getDisplayRotationCoordinator()1222 DisplayRotationCoordinator getDisplayRotationCoordinator() { 1223 return mDisplayRotationCoordinator; 1224 } 1225 1226 /** 1227 * Get the default display area on the device dedicated to app windows. This one should be used 1228 * only as a fallback location for activity launches when no target display area is specified, 1229 * or for cases when multi-instance is not supported yet (like Split-screen, Freeform, PiP or 1230 * Recents). 1231 */ getDefaultTaskDisplayArea()1232 TaskDisplayArea getDefaultTaskDisplayArea() { 1233 return mDefaultDisplay.getDefaultTaskDisplayArea(); 1234 } 1235 1236 /** 1237 * Get an existing instance of {@link DisplayContent} that has the given uniqueId. Unique ID is 1238 * defined in {@link DisplayInfo#uniqueId}. 1239 * 1240 * @param uniqueId the unique ID of the display 1241 * @return the {@link DisplayContent} or {@code null} if nothing is found. 1242 */ getDisplayContent(String uniqueId)1243 DisplayContent getDisplayContent(String uniqueId) { 1244 for (int i = getChildCount() - 1; i >= 0; --i) { 1245 final DisplayContent display = getChildAt(i); 1246 final boolean isValid = display.mDisplay.isValid(); 1247 if (isValid && display.mDisplay.getUniqueId().equals(uniqueId)) { 1248 return display; 1249 } 1250 } 1251 1252 return null; 1253 } 1254 1255 // TODO: Look into consolidating with getDisplayContentOrCreate() getDisplayContent(int displayId)1256 DisplayContent getDisplayContent(int displayId) { 1257 for (int i = getChildCount() - 1; i >= 0; --i) { 1258 final DisplayContent displayContent = getChildAt(i); 1259 if (displayContent.mDisplayId == displayId) { 1260 return displayContent; 1261 } 1262 } 1263 return null; 1264 } 1265 1266 /** 1267 * Get an existing instance of {@link DisplayContent} or create new if there is a 1268 * corresponding record in display manager. 1269 */ 1270 // TODO: Look into consolidating with getDisplayContent() 1271 @Nullable getDisplayContentOrCreate(int displayId)1272 DisplayContent getDisplayContentOrCreate(int displayId) { 1273 DisplayContent displayContent = getDisplayContent(displayId); 1274 if (displayContent != null) { 1275 return displayContent; 1276 } 1277 if (mDisplayManager == null) { 1278 // The system isn't fully initialized yet. 1279 return null; 1280 } 1281 final Display display = mDisplayManager.getDisplay(displayId); 1282 if (display == null) { 1283 // The display is not registered in DisplayManager. 1284 return null; 1285 } 1286 // The display hasn't been added to ActivityManager yet, create a new record now. 1287 displayContent = new DisplayContent(display, this, mDeviceStateController); 1288 addChild(displayContent, POSITION_BOTTOM); 1289 return displayContent; 1290 } 1291 getDefaultDisplayHomeActivityForUser(int userId)1292 ActivityRecord getDefaultDisplayHomeActivityForUser(int userId) { 1293 return getDefaultTaskDisplayArea().getHomeActivityForUser(userId); 1294 } 1295 startHomeOnAllDisplays(int userId, String reason)1296 boolean startHomeOnAllDisplays(int userId, String reason) { 1297 boolean homeStarted = false; 1298 for (int i = getChildCount() - 1; i >= 0; i--) { 1299 final int displayId = getChildAt(i).mDisplayId; 1300 homeStarted |= startHomeOnDisplay(userId, reason, displayId); 1301 } 1302 return homeStarted; 1303 } 1304 startHomeOnEmptyDisplays(String reason)1305 void startHomeOnEmptyDisplays(String reason) { 1306 forAllTaskDisplayAreas(taskDisplayArea -> { 1307 if (taskDisplayArea.topRunningActivity() == null) { 1308 int userId = mWmService.getUserAssignedToDisplay(taskDisplayArea.getDisplayId()); 1309 startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea, 1310 false /* allowInstrumenting */, false /* fromHomeKey */); 1311 } 1312 }); 1313 } 1314 startHomeOnDisplay(int userId, String reason, int displayId)1315 boolean startHomeOnDisplay(int userId, String reason, int displayId) { 1316 return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */, 1317 false /* fromHomeKey */); 1318 } 1319 startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting, boolean fromHomeKey)1320 boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting, 1321 boolean fromHomeKey) { 1322 // Fallback to top focused display or default display if the displayId is invalid. 1323 if (displayId == INVALID_DISPLAY) { 1324 final Task rootTask = getTopDisplayFocusedRootTask(); 1325 displayId = rootTask != null ? rootTask.getDisplayId() : DEFAULT_DISPLAY; 1326 } 1327 1328 final DisplayContent display = getDisplayContentOrCreate(displayId); 1329 return display.reduceOnAllTaskDisplayAreas((taskDisplayArea, result) -> 1330 result | startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea, 1331 allowInstrumenting, fromHomeKey), 1332 false /* initValue */); 1333 } 1334 1335 /** 1336 * This starts home activity on display areas that can have system decorations based on 1337 * displayId - default display area always uses primary home component. 1338 * For secondary display areas, the home activity must have category SECONDARY_HOME and then 1339 * resolves according to the priorities listed below. 1340 * - If default home is not set, always use the secondary home defined in the config. 1341 * - Use currently selected primary home activity. 1342 * - Use the activity in the same package as currently selected primary home activity. 1343 * If there are multiple activities matched, use first one. 1344 * - Use the secondary home defined in the config. 1345 */ startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea, boolean allowInstrumenting, boolean fromHomeKey)1346 boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea, 1347 boolean allowInstrumenting, boolean fromHomeKey) { 1348 // Fallback to top focused display area if the provided one is invalid. 1349 if (taskDisplayArea == null) { 1350 final Task rootTask = getTopDisplayFocusedRootTask(); 1351 taskDisplayArea = rootTask != null ? rootTask.getDisplayArea() 1352 : getDefaultTaskDisplayArea(); 1353 } 1354 1355 // When display content mode management flag is enabled, the task display area is marked as 1356 // removed when switching from extended display to mirroring display. We need to restart the 1357 // task display area before starting the home. 1358 if (ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT.isTrue() 1359 && taskDisplayArea.shouldKeepNoTask()) { 1360 taskDisplayArea.setShouldKeepNoTask(false); 1361 } 1362 1363 Intent homeIntent = null; 1364 ActivityInfo aInfo = null; 1365 if (taskDisplayArea == getDefaultTaskDisplayArea() 1366 || mWmService.shouldPlacePrimaryHomeOnDisplay( 1367 taskDisplayArea.getDisplayId(), userId)) { 1368 homeIntent = mService.getHomeIntent(); 1369 aInfo = resolveHomeActivity(userId, homeIntent); 1370 } else if (shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) { 1371 Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, taskDisplayArea); 1372 aInfo = info.first; 1373 homeIntent = info.second; 1374 } 1375 1376 if (aInfo == null || homeIntent == null) { 1377 return false; 1378 } 1379 1380 if (!canStartHomeOnDisplayArea(aInfo, taskDisplayArea, allowInstrumenting)) { 1381 return false; 1382 } 1383 1384 if (mService.mAmInternal.shouldDelayHomeLaunch(userId)) { 1385 Slog.d(TAG, "ThemeHomeDelay: Home launch was deferred with user " + userId); 1386 return false; 1387 } 1388 1389 // Updates the home component of the intent. 1390 homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name)); 1391 homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK); 1392 // Updates the extra information of the intent. 1393 if (fromHomeKey) { 1394 homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true); 1395 } 1396 homeIntent.putExtra(WindowManagerPolicy.EXTRA_START_REASON, reason); 1397 1398 // Update the reason for ANR debugging to verify if the user activity is the one that 1399 // actually launched. 1400 final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId( 1401 aInfo.applicationInfo.uid) + ":" + taskDisplayArea.getDisplayId(); 1402 mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason, 1403 taskDisplayArea); 1404 return true; 1405 } 1406 1407 /** 1408 * This resolves the home activity info. 1409 * 1410 * @return the home activity info if any. 1411 */ 1412 @VisibleForTesting resolveHomeActivity(int userId, Intent homeIntent)1413 ActivityInfo resolveHomeActivity(int userId, Intent homeIntent) { 1414 final int flags = ActivityManagerService.STOCK_PM_FLAGS; 1415 final ComponentName comp = homeIntent.getComponent(); 1416 ActivityInfo aInfo = null; 1417 try { 1418 if (comp != null) { 1419 // Factory test. 1420 aInfo = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId); 1421 } else { 1422 final String resolvedType = 1423 homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver()); 1424 final ResolveInfo info = mTaskSupervisor.resolveIntent(homeIntent, resolvedType, 1425 userId, flags, Binder.getCallingUid(), Binder.getCallingPid()); 1426 if (info != null) { 1427 aInfo = info.activityInfo; 1428 } 1429 } 1430 } catch (RemoteException e) { 1431 // ignore 1432 } 1433 1434 if (aInfo == null) { 1435 Slogf.wtf(TAG, new Exception(), "No home screen found for %s and user %d", homeIntent, 1436 userId); 1437 return null; 1438 } 1439 1440 aInfo = new ActivityInfo(aInfo); 1441 aInfo.applicationInfo = mService.getAppInfoForUser(aInfo.applicationInfo, userId); 1442 return aInfo; 1443 } 1444 1445 @VisibleForTesting resolveSecondaryHomeActivity(int userId, @NonNull TaskDisplayArea taskDisplayArea)1446 Pair<ActivityInfo, Intent> resolveSecondaryHomeActivity(int userId, 1447 @NonNull TaskDisplayArea taskDisplayArea) { 1448 if (taskDisplayArea == getDefaultTaskDisplayArea()) { 1449 throw new IllegalArgumentException( 1450 "resolveSecondaryHomeActivity: Should not be default task container"); 1451 } 1452 1453 Intent homeIntent = mService.getHomeIntent(); 1454 ActivityInfo aInfo = resolveHomeActivity(userId, homeIntent); 1455 boolean lookForSecondaryHomeActivityInPrimaryHomePackage = aInfo != null; 1456 1457 // Resolve the externally set home activity for this display, if any. If it is unset or 1458 // we fail to resolve it, fallback to the default secondary home activity. 1459 final ComponentName customHomeComponent = 1460 taskDisplayArea.getDisplayContent() != null 1461 ? taskDisplayArea.getDisplayContent().getCustomHomeComponent() 1462 : null; 1463 if (customHomeComponent != null) { 1464 homeIntent.setComponent(customHomeComponent); 1465 ActivityInfo customHomeActivityInfo = resolveHomeActivity(userId, homeIntent); 1466 if (customHomeActivityInfo != null) { 1467 aInfo = customHomeActivityInfo; 1468 lookForSecondaryHomeActivityInPrimaryHomePackage = false; 1469 } 1470 } 1471 1472 if (lookForSecondaryHomeActivityInPrimaryHomePackage) { 1473 // Resolve activities in the same package as currently selected primary home activity. 1474 if (ResolverActivity.class.getName().equals(aInfo.name)) { 1475 // Always fallback to secondary home component if default home is not set. 1476 aInfo = null; 1477 } else { 1478 // Look for secondary home activities in the currently selected default home 1479 // package. 1480 homeIntent = mService.getSecondaryHomeIntent(aInfo.applicationInfo.packageName); 1481 final List<ResolveInfo> resolutions = resolveActivities(userId, homeIntent); 1482 final int size = resolutions.size(); 1483 final String targetName = aInfo.name; 1484 aInfo = null; 1485 for (int i = 0; i < size; i++) { 1486 ResolveInfo resolveInfo = resolutions.get(i); 1487 // We need to traverse all resolutions to check if the currently selected 1488 // default home activity is present. 1489 if (resolveInfo.activityInfo.name.equals(targetName)) { 1490 aInfo = resolveInfo.activityInfo; 1491 break; 1492 } 1493 } 1494 if (aInfo == null && size > 0) { 1495 // First one is the best. 1496 aInfo = resolutions.get(0).activityInfo; 1497 } 1498 } 1499 } 1500 1501 if (aInfo != null) { 1502 if (!canStartHomeOnDisplayArea(aInfo, taskDisplayArea, 1503 false /* allowInstrumenting */)) { 1504 aInfo = null; 1505 } 1506 } 1507 1508 // Fallback to secondary home component. 1509 if (aInfo == null) { 1510 homeIntent = mService.getSecondaryHomeIntent(null); 1511 aInfo = resolveHomeActivity(userId, homeIntent); 1512 } 1513 return Pair.create(aInfo, homeIntent); 1514 } 1515 1516 /** 1517 * Retrieve all activities that match the given intent. 1518 * The list should already ordered from best to worst matched. 1519 * {@link android.content.pm.PackageManager#queryIntentActivities} 1520 */ 1521 @VisibleForTesting resolveActivities(int userId, Intent homeIntent)1522 List<ResolveInfo> resolveActivities(int userId, Intent homeIntent) { 1523 List<ResolveInfo> resolutions; 1524 try { 1525 final String resolvedType = 1526 homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver()); 1527 resolutions = AppGlobals.getPackageManager().queryIntentActivities(homeIntent, 1528 resolvedType, ActivityManagerService.STOCK_PM_FLAGS, userId).getList(); 1529 1530 } catch (RemoteException e) { 1531 resolutions = new ArrayList<>(); 1532 } 1533 return resolutions; 1534 } 1535 resumeHomeActivity(ActivityRecord prev, String reason, TaskDisplayArea taskDisplayArea)1536 boolean resumeHomeActivity(ActivityRecord prev, String reason, 1537 TaskDisplayArea taskDisplayArea) { 1538 if (!mService.isBooting() && !mService.isBooted()) { 1539 // Not ready yet! 1540 return false; 1541 } 1542 1543 if (taskDisplayArea == null) { 1544 taskDisplayArea = getDefaultTaskDisplayArea(); 1545 } 1546 1547 final ActivityRecord r = taskDisplayArea.getHomeActivity(); 1548 final String myReason = reason + " resumeHomeActivity"; 1549 1550 // Only resume home activity if isn't finishing. 1551 if (r != null && !r.finishing) { 1552 r.moveFocusableActivityToTop(myReason); 1553 return resumeFocusedTasksTopActivities(r.getRootTask(), prev); 1554 } 1555 int userId = mWmService.getUserAssignedToDisplay(taskDisplayArea.getDisplayId()); 1556 return startHomeOnTaskDisplayArea(userId, myReason, taskDisplayArea, 1557 false /* allowInstrumenting */, false /* fromHomeKey */); 1558 } 1559 1560 /** 1561 * Check if the display is valid for primary home activity. 1562 * 1563 * @param displayId The target display ID 1564 * @return {@code true} if allowed to launch, {@code false} otherwise. 1565 */ shouldPlacePrimaryHomeOnDisplay(int displayId)1566 boolean shouldPlacePrimaryHomeOnDisplay(int displayId) { 1567 // No restrictions to default display, vr 2d display or main display for visible users. 1568 return displayId == DEFAULT_DISPLAY || (displayId != INVALID_DISPLAY 1569 && (displayId == mService.mVr2dDisplayId 1570 || mWmService.shouldPlacePrimaryHomeOnDisplay(displayId))); 1571 } 1572 1573 /** 1574 * Check if the display area is valid for secondary home activity. 1575 * 1576 * @param taskDisplayArea The target display area. 1577 * @return {@code true} if allow to launch, {@code false} otherwise. 1578 */ shouldPlaceSecondaryHomeOnDisplayArea(TaskDisplayArea taskDisplayArea)1579 boolean shouldPlaceSecondaryHomeOnDisplayArea(TaskDisplayArea taskDisplayArea) { 1580 if (getDefaultTaskDisplayArea() == taskDisplayArea) { 1581 throw new IllegalArgumentException( 1582 "shouldPlaceSecondaryHomeOnDisplay: Should not be on default task container"); 1583 } else if (taskDisplayArea == null) { 1584 return false; 1585 } 1586 1587 if (!taskDisplayArea.canHostHomeTask()) { 1588 // Can't launch home on a TaskDisplayArea that does not support root home task 1589 return false; 1590 } 1591 1592 if (taskDisplayArea.getDisplayId() != DEFAULT_DISPLAY && !mService.mSupportsMultiDisplay) { 1593 // Can't launch home on secondary display if device does not support multi-display. 1594 return false; 1595 } 1596 1597 final boolean deviceProvisioned = Settings.Global.getInt( 1598 mService.mContext.getContentResolver(), 1599 Settings.Global.DEVICE_PROVISIONED, 0) != 0; 1600 if (!deviceProvisioned) { 1601 // Can't launch home on secondary display areas before device is provisioned. 1602 return false; 1603 } 1604 1605 if (!StorageManager.isCeStorageUnlocked(mCurrentUser)) { 1606 // Can't launch home on secondary display areas if CE storage is still locked. 1607 return false; 1608 } 1609 1610 final DisplayContent display = taskDisplayArea.getDisplayContent(); 1611 if (display == null || display.isRemoved() || !display.isHomeSupported()) { 1612 // Can't launch home on display that doesn't support home. 1613 return false; 1614 } 1615 1616 return true; 1617 } 1618 1619 /** 1620 * Check if home activity start should be allowed on a {@link TaskDisplayArea}. 1621 * 1622 * @param homeInfo {@code ActivityInfo} of the home activity that is going to be 1623 * launched. 1624 * @param taskDisplayArea The target display area. 1625 * @param allowInstrumenting Whether launching home should be allowed if being instrumented. 1626 * @return {@code true} if allow to launch, {@code false} otherwise. 1627 */ canStartHomeOnDisplayArea(ActivityInfo homeInfo, TaskDisplayArea taskDisplayArea, boolean allowInstrumenting)1628 boolean canStartHomeOnDisplayArea(ActivityInfo homeInfo, TaskDisplayArea taskDisplayArea, 1629 boolean allowInstrumenting) { 1630 if (mService.mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL 1631 && mService.mTopAction == null) { 1632 // We are running in factory test mode, but unable to find the factory test app, so 1633 // just sit around displaying the error message and don't try to start anything. 1634 return false; 1635 } 1636 1637 final WindowProcessController app = 1638 mService.getProcessController(homeInfo.processName, homeInfo.applicationInfo.uid); 1639 if (!allowInstrumenting && app != null && app.isInstrumenting()) { 1640 // Don't do this if the home app is currently being instrumented. 1641 return false; 1642 } 1643 1644 if (taskDisplayArea != null && !taskDisplayArea.canHostHomeTask()) { 1645 return false; 1646 } 1647 1648 final int displayId = taskDisplayArea != null ? taskDisplayArea.getDisplayId() 1649 : INVALID_DISPLAY; 1650 if (shouldPlacePrimaryHomeOnDisplay(displayId)) { 1651 return true; 1652 } 1653 1654 if (!shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) { 1655 return false; 1656 } 1657 1658 final boolean supportMultipleInstance = homeInfo.launchMode != LAUNCH_SINGLE_TASK 1659 && homeInfo.launchMode != LAUNCH_SINGLE_INSTANCE; 1660 if (!supportMultipleInstance) { 1661 // Can't launch home on secondary displays if it requested to be single instance. 1662 return false; 1663 } 1664 1665 return true; 1666 } 1667 1668 /** 1669 * Ensure all activities visibility, update orientation and configuration. 1670 * 1671 * @param starting The currently starting activity or {@code null} if there is 1672 * none. 1673 * @param displayContent The display where the operation is executed. 1674 * @param deferResume Whether to defer resume while updating config. 1675 */ ensureVisibilityAndConfig(@ullable ActivityRecord starting, @NonNull DisplayContent displayContent, boolean deferResume)1676 void ensureVisibilityAndConfig(@Nullable ActivityRecord starting, 1677 @NonNull DisplayContent displayContent, boolean deferResume) { 1678 // First ensure visibility without updating the config just yet. We need this to know what 1679 // activities are affecting configuration now. 1680 // Passing null here for 'starting' param value, so that visibility of actual starting 1681 // activity will be properly updated. 1682 ensureActivitiesVisible(null /* starting */, false /* notifyClients */); 1683 1684 // Force-update the orientation from the WindowManager, since we need the true configuration 1685 // to send to the client now. 1686 final Configuration config = 1687 displayContent.updateOrientationAndComputeConfig(true /* forceUpdate */); 1688 // Visibilities may change so let the starting activity have a chance to report. Can't do it 1689 // when visibility is changed in each AppWindowToken because it may trigger wrong 1690 // configuration push because the visibility of some activities may not be updated yet. 1691 if (starting != null) { 1692 starting.reportDescendantOrientationChangeIfNeeded(); 1693 } 1694 1695 // Update the configuration of the activities on the display. 1696 displayContent.updateDisplayOverrideConfigurationLocked(config, starting, deferResume); 1697 } 1698 1699 /** 1700 * @return a list of pairs, containing activities and their task id which are the top ones in 1701 * each visible root task. The first entry will be the focused activity. 1702 * 1703 * <p>NOTE: If the top activity is in the split screen, the other activities in the same split 1704 * screen will also be returned. 1705 */ getTopVisibleActivities()1706 List<ActivityAssistInfo> getTopVisibleActivities() { 1707 final ArrayList<ActivityAssistInfo> topVisibleActivities = new ArrayList<>(); 1708 final ArrayList<ActivityAssistInfo> activityAssistInfos = new ArrayList<>(); 1709 final Task topFocusedRootTask = getTopDisplayFocusedRootTask(); 1710 // Traverse all displays. 1711 forAllRootTasks(rootTask -> { 1712 // Get top activity from a visible root task and add it to the list. 1713 if (rootTask.shouldBeVisible(null /* starting */)) { 1714 final ActivityRecord top = rootTask.getTopNonFinishingActivity(); 1715 if (top != null) { 1716 activityAssistInfos.clear(); 1717 activityAssistInfos.add(new ActivityAssistInfo(top)); 1718 // Check if the activity on the split screen. 1719 top.getTask().forOtherAdjacentTasks(task -> { 1720 final ActivityRecord adjacentActivityRecord = 1721 task.getTopNonFinishingActivity(); 1722 if (adjacentActivityRecord != null) { 1723 activityAssistInfos.add( 1724 new ActivityAssistInfo(adjacentActivityRecord)); 1725 } 1726 }); 1727 if (rootTask == topFocusedRootTask) { 1728 topVisibleActivities.addAll(0, activityAssistInfos); 1729 } else { 1730 topVisibleActivities.addAll(activityAssistInfos); 1731 } 1732 } 1733 } 1734 }); 1735 return topVisibleActivities; 1736 } 1737 1738 @Nullable getTopDisplayFocusedRootTask()1739 Task getTopDisplayFocusedRootTask() { 1740 for (int i = getChildCount() - 1; i >= 0; --i) { 1741 final Task focusedRootTask = getChildAt(i).getFocusedRootTask(); 1742 if (focusedRootTask != null) { 1743 return focusedRootTask; 1744 } 1745 } 1746 return null; 1747 } 1748 1749 @Nullable getTopResumedActivity()1750 ActivityRecord getTopResumedActivity() { 1751 final Task focusedRootTask = getTopDisplayFocusedRootTask(); 1752 if (focusedRootTask == null) { 1753 return null; 1754 } 1755 final ActivityRecord resumedActivity = focusedRootTask.getTopResumedActivity(); 1756 if (resumedActivity != null && resumedActivity.app != null) { 1757 return resumedActivity; 1758 } 1759 // The top focused root task might not have a resumed activity yet - look on all displays in 1760 // focus order. 1761 return getItemFromTaskDisplayAreas(TaskDisplayArea::getFocusedActivity); 1762 } 1763 isTopDisplayFocusedRootTask(Task task)1764 boolean isTopDisplayFocusedRootTask(Task task) { 1765 return task != null && task == getTopDisplayFocusedRootTask(); 1766 } 1767 attachApplication(WindowProcessController app)1768 boolean attachApplication(WindowProcessController app) throws RemoteException { 1769 app.mHasEverAttached = true; 1770 final ArrayList<ActivityRecord> activities = mService.mStartingProcessActivities; 1771 RemoteException remoteException = null; 1772 boolean hasActivityStarted = false; 1773 for (int i = activities.size() - 1; i >= 0; i--) { 1774 final ActivityRecord r = activities.get(i); 1775 if (app.mUid != r.info.applicationInfo.uid || !app.mName.equals(r.processName)) { 1776 // The attaching process does not match the starting activity. 1777 continue; 1778 } 1779 // Consume the pending record. 1780 activities.remove(i); 1781 final TaskFragment tf = r.getTaskFragment(); 1782 if (tf == null || r.finishing || r.app != null 1783 // Ignore keyguard because the app may use show-when-locked when creating. 1784 || !r.shouldBeVisible(true /* ignoringKeyguard */) 1785 || !r.showToCurrentUser()) { 1786 continue; 1787 } 1788 try { 1789 final boolean canResume = r.isFocusable() && r == tf.topRunningActivity(); 1790 if (mTaskSupervisor.realStartActivityLocked(r, app, canResume, 1791 true /* checkConfig */)) { 1792 hasActivityStarted = true; 1793 } 1794 } catch (RemoteException e) { 1795 Slog.w(TAG, "Exception in new process when starting " + r, e); 1796 remoteException = e; 1797 } 1798 } 1799 if (remoteException != null) { 1800 throw remoteException; 1801 } 1802 return hasActivityStarted; 1803 } 1804 1805 /** 1806 * Make sure that all activities that need to be visible in the system actually are and update 1807 * their configuration. 1808 */ ensureActivitiesVisible()1809 void ensureActivitiesVisible() { 1810 ensureActivitiesVisible(null /* starting */); 1811 } 1812 ensureActivitiesVisible(ActivityRecord starting)1813 void ensureActivitiesVisible(ActivityRecord starting) { 1814 ensureActivitiesVisible(starting, true /* notifyClients */); 1815 } 1816 1817 /** 1818 * @see #ensureActivitiesVisible() 1819 */ ensureActivitiesVisible(ActivityRecord starting, boolean notifyClients)1820 void ensureActivitiesVisible(ActivityRecord starting, boolean notifyClients) { 1821 if (mTaskSupervisor.inActivityVisibilityUpdate() 1822 || mTaskSupervisor.isRootVisibilityUpdateDeferred()) { 1823 // Don't do recursive work. 1824 return; 1825 } 1826 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "RWC_ensureActivitiesVisible"); 1827 mTaskSupervisor.beginActivityVisibilityUpdate(); 1828 try { 1829 // First the front root tasks. In case any are not fullscreen and are in front of home. 1830 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { 1831 final DisplayContent display = getChildAt(displayNdx); 1832 display.ensureActivitiesVisible(starting, notifyClients); 1833 } 1834 } finally { 1835 mTaskSupervisor.endActivityVisibilityUpdate(); 1836 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 1837 } 1838 } 1839 switchUser(int userId, UserState uss)1840 boolean switchUser(int userId, UserState uss) { 1841 final Task topFocusedRootTask = getTopDisplayFocusedRootTask(); 1842 final int focusRootTaskId = topFocusedRootTask != null 1843 ? topFocusedRootTask.getRootTaskId() : INVALID_TASK_ID; 1844 // Also dismiss the pinned root task whenever we switch users. Removing the pinned root task 1845 // will also cause all tasks to be moved to the fullscreen root task at a position that is 1846 // appropriate. 1847 removeRootTasksInWindowingModes(WINDOWING_MODE_PINNED); 1848 1849 if (DesktopModeFlags.ENABLE_TOP_VISIBLE_ROOT_TASK_PER_USER_TRACKING.isTrue()) { 1850 final IntArray visibleRootTasks = new IntArray(); 1851 forAllRootTasks(rootTask -> { 1852 if ((mCurrentUser == rootTask.mUserId || rootTask.showForAllUsers()) 1853 && rootTask.isVisible()) { 1854 visibleRootTasks.add(rootTask.getRootTaskId()); 1855 } 1856 }, /* traverseTopToBottom */ false); 1857 mUserVisibleRootTasks.put(mCurrentUser, visibleRootTasks); 1858 } else { 1859 mUserRootTaskInFront.put(mCurrentUser, focusRootTaskId); 1860 } 1861 1862 mCurrentUser = userId; 1863 1864 mTaskSupervisor.mStartingUsers.add(uss); 1865 forAllRootTasks(rootTask -> { 1866 rootTask.switchUser(userId); 1867 }); 1868 1869 1870 if (topFocusedRootTask != null && isAlwaysVisibleUser(topFocusedRootTask.mUserId)) { 1871 Slog.i(TAG, "Persisting top task because it belongs to an always-visible user"); 1872 // For a normal user-switch, we will restore the new user's task. But if the pre-switch 1873 // top task is an always-visible (Communal) one, keep it even after the switch. 1874 if (Flags.enableTopVisibleRootTaskPerUserTracking()) { 1875 final IntArray rootTasks = mUserVisibleRootTasks.get(mCurrentUser); 1876 rootTasks.add(focusRootTaskId); 1877 mUserVisibleRootTasks.put(mCurrentUser, rootTasks); 1878 } else { 1879 mUserRootTaskInFront.put(mCurrentUser, focusRootTaskId); 1880 } 1881 1882 } 1883 1884 final int restoreRootTaskId = mUserRootTaskInFront.get(userId); 1885 final IntArray rootTaskIdsToRestore = mUserVisibleRootTasks.get(userId); 1886 boolean homeInFront = false; 1887 if (Flags.enableTopVisibleRootTaskPerUserTracking()) { 1888 if (rootTaskIdsToRestore == null || rootTaskIdsToRestore.size() == 0) { 1889 // If there are no root tasks saved, try restore id 0 which should create and launch 1890 // the home task. 1891 handleRootTaskLaunchOnUserSwitch(/* restoreRootTaskId */INVALID_TASK_ID); 1892 homeInFront = true; 1893 } else { 1894 for (int i = 0; i < rootTaskIdsToRestore.size(); i++) { 1895 handleRootTaskLaunchOnUserSwitch(rootTaskIdsToRestore.get(i)); 1896 } 1897 // Check if the top task is type home 1898 final int topRootTaskId = rootTaskIdsToRestore.get(rootTaskIdsToRestore.size() - 1); 1899 homeInFront = isHomeTask(topRootTaskId); 1900 } 1901 } else { 1902 handleRootTaskLaunchOnUserSwitch(restoreRootTaskId); 1903 // Check if the top task is type home 1904 homeInFront = isHomeTask(restoreRootTaskId); 1905 } 1906 return homeInFront; 1907 } 1908 isHomeTask(int taskId)1909 private boolean isHomeTask(int taskId) { 1910 final Task rootTask = getRootTask(taskId); 1911 return rootTask != null && rootTask.isActivityTypeHome(); 1912 } 1913 handleRootTaskLaunchOnUserSwitch(int restoreRootTaskId)1914 private void handleRootTaskLaunchOnUserSwitch(int restoreRootTaskId) { 1915 Task rootTask = getRootTask(restoreRootTaskId); 1916 if (rootTask == null) { 1917 rootTask = getDefaultTaskDisplayArea().getOrCreateRootHomeTask(); 1918 } 1919 if (rootTask.isOnHomeDisplay()) { 1920 rootTask.moveToFront("switchUserOnHomeDisplay"); 1921 } else { 1922 // Root task was moved to another display while user was swapped out. 1923 resumeHomeActivity(null, "switchUserOnOtherDisplay", getDefaultTaskDisplayArea()); 1924 } 1925 } 1926 1927 /** Returns whether the given user is to be always-visible (e.g. a communal profile). */ isAlwaysVisibleUser(@serIdInt int userId)1928 private boolean isAlwaysVisibleUser(@UserIdInt int userId) { 1929 final UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class); 1930 final UserProperties properties = umi.getUserProperties(userId); 1931 return properties != null && properties.getAlwaysVisible(); 1932 } 1933 removeUser(int userId)1934 void removeUser(int userId) { 1935 if (Flags.enableTopVisibleRootTaskPerUserTracking()) { 1936 mUserVisibleRootTasks.delete(userId); 1937 } else { 1938 mUserRootTaskInFront.delete(userId); 1939 } 1940 } 1941 1942 /** 1943 * Update the last used root task id for non-current user (current user's last 1944 * used root task is the focused root task) 1945 */ updateUserRootTask(int userId, Task rootTask)1946 void updateUserRootTask(int userId, Task rootTask) { 1947 if (userId != mCurrentUser) { 1948 if (rootTask == null) { 1949 rootTask = getDefaultTaskDisplayArea().getOrCreateRootHomeTask(); 1950 } 1951 1952 if (Flags.enableTopVisibleRootTaskPerUserTracking()) { 1953 final IntArray rootTasks = mUserVisibleRootTasks.get(userId, new IntArray()); 1954 // If root task already exists in the list, move it to the top instead. 1955 final int rootTaskIndex = rootTasks.indexOf(rootTask.getRootTaskId()); 1956 if (rootTaskIndex != -1) { 1957 rootTasks.remove(rootTaskIndex); 1958 } 1959 rootTasks.add(rootTask.getRootTaskId()); 1960 mUserVisibleRootTasks.put(userId, rootTasks); 1961 } else { 1962 mUserRootTaskInFront.put(userId, rootTask.getRootTaskId()); 1963 } 1964 } 1965 } 1966 1967 /** 1968 * Move root task with all its existing content to specified task display area. 1969 * 1970 * @param rootTaskId Id of root task to move. 1971 * @param taskDisplayArea The task display area to move root task to. 1972 * @param onTop Indicates whether container should be place on top or on bottom. 1973 */ moveRootTaskToTaskDisplayArea(int rootTaskId, TaskDisplayArea taskDisplayArea, boolean onTop)1974 void moveRootTaskToTaskDisplayArea(int rootTaskId, TaskDisplayArea taskDisplayArea, 1975 boolean onTop) { 1976 final Task rootTask = getRootTask(rootTaskId); 1977 if (rootTask == null) { 1978 throw new IllegalArgumentException("moveRootTaskToTaskDisplayArea: Unknown rootTaskId=" 1979 + rootTaskId); 1980 } 1981 1982 final TaskDisplayArea currentTaskDisplayArea = rootTask.getDisplayArea(); 1983 if (currentTaskDisplayArea == null) { 1984 throw new IllegalStateException("moveRootTaskToTaskDisplayArea: rootTask=" + rootTask 1985 + " is not attached to any task display area."); 1986 } 1987 1988 if (taskDisplayArea == null) { 1989 throw new IllegalArgumentException( 1990 "moveRootTaskToTaskDisplayArea: Unknown taskDisplayArea=" + taskDisplayArea); 1991 } 1992 1993 if (currentTaskDisplayArea == taskDisplayArea) { 1994 throw new IllegalArgumentException("Trying to move rootTask=" + rootTask 1995 + " to its current taskDisplayArea=" + taskDisplayArea); 1996 } 1997 rootTask.reparent(taskDisplayArea, onTop); 1998 1999 // Resume focusable root task after reparenting to another display area. 2000 rootTask.resumeNextFocusAfterReparent(); 2001 2002 // TODO(multi-display): resize rootTasks properly if moved from split-screen. 2003 } 2004 2005 /** 2006 * Move root task with all its existing content to specified display. 2007 * 2008 * @param rootTaskId Id of root task to move. 2009 * @param displayId Id of display to move root task to. 2010 * @param onTop Indicates whether container should be place on top or on bottom. 2011 */ moveRootTaskToDisplay(int rootTaskId, int displayId, boolean onTop)2012 void moveRootTaskToDisplay(int rootTaskId, int displayId, boolean onTop) { 2013 final DisplayContent displayContent = getDisplayContentOrCreate(displayId); 2014 if (displayContent == null) { 2015 throw new IllegalArgumentException("moveRootTaskToDisplay: Unknown displayId=" 2016 + displayId); 2017 } 2018 2019 moveRootTaskToTaskDisplayArea(rootTaskId, displayContent.getDefaultTaskDisplayArea(), 2020 onTop); 2021 } 2022 2023 /** Wrapper/Helper for tests */ moveActivityToPinnedRootTask(@onNull ActivityRecord r, String reason)2024 void moveActivityToPinnedRootTask(@NonNull ActivityRecord r, String reason) { 2025 Transition newTransit = (r.mTransitionController.isCollecting() 2026 || !r.mTransitionController.isShellTransitionsEnabled()) 2027 ? null : r.mTransitionController.createTransition(TRANSIT_PIP); 2028 moveActivityToPinnedRootTaskInner(r, null /* launchIntoPipHostActivity */, reason, 2029 null /* bounds */, newTransit != null); 2030 } 2031 moveActivityToPinnedRootTask(@onNull ActivityRecord r, @Nullable ActivityRecord launchIntoPipHostActivity, String reason, @Nullable Rect bounds)2032 void moveActivityToPinnedRootTask(@NonNull ActivityRecord r, 2033 @Nullable ActivityRecord launchIntoPipHostActivity, String reason, 2034 @Nullable Rect bounds) { 2035 moveActivityToPinnedRootTaskInner(r, launchIntoPipHostActivity, reason, bounds, 2036 false /* requestStart */); 2037 } 2038 2039 /** 2040 * Moves activity to pinned in the provided transition and also requests start on that 2041 * Transition at an appropriate time. 2042 */ moveActivityToPinnedRootTaskAndRequestStart(@onNull ActivityRecord r, String reason)2043 void moveActivityToPinnedRootTaskAndRequestStart(@NonNull ActivityRecord r, String reason) { 2044 moveActivityToPinnedRootTaskInner(r, null /* launchIntoPipHostActivity */, reason, 2045 null /* bounds */, true /* requestStart */); 2046 } 2047 moveActivityToPinnedRootTaskInner(@onNull ActivityRecord r, @Nullable ActivityRecord launchIntoPipHostActivity, String reason, @Nullable Rect bounds, boolean requestStart)2048 private void moveActivityToPinnedRootTaskInner(@NonNull ActivityRecord r, 2049 @Nullable ActivityRecord launchIntoPipHostActivity, String reason, 2050 @Nullable Rect bounds, boolean requestStart) { 2051 final TaskDisplayArea taskDisplayArea = r.getDisplayArea(); 2052 final Task task = r.getTask(); 2053 final Task rootTask; 2054 2055 final TransitionController transitionController = task.mTransitionController; 2056 2057 transitionController.deferTransitionReady(); 2058 Transition.ReadyCondition pipChangesApplied = new Transition.ReadyCondition("movedToPip"); 2059 transitionController.waitFor(pipChangesApplied); 2060 mService.deferWindowLayout(); 2061 boolean localVisibilityDeferred = false; 2062 // If the caller is from WindowOrganizerController, it should be already deferred. 2063 if (!mTaskSupervisor.isRootVisibilityUpdateDeferred()) { 2064 mTaskSupervisor.setDeferRootVisibilityUpdate(true); 2065 localVisibilityDeferred = true; 2066 } 2067 try { 2068 // This will change the root pinned task's windowing mode to its original mode, ensuring 2069 // we only have one root task that is in pinned mode. 2070 final Task rootPinnedTask = taskDisplayArea.getRootPinnedTask(); 2071 if (rootPinnedTask != null) { 2072 transitionController.collect(rootPinnedTask); 2073 // The new ActivityRecord should replace the existing PiP, so it's more desirable 2074 // that the old PiP disappears instead of turning to full-screen at the same time, 2075 // as the Task#dismissPip is trying to do. 2076 removeRootTasksInWindowingModes(WINDOWING_MODE_PINNED); 2077 } 2078 2079 transitionController.collect(task); 2080 2081 // Defer the windowing mode change until after the transition to prevent the activity 2082 // from doing work and changing the activity visuals while animating 2083 // TODO(task-org): Figure-out more structured way to do this long term. 2084 if (!isPip2ExperimentEnabled()) { 2085 r.setWindowingMode(r.getWindowingMode()); 2086 } 2087 2088 final TaskFragment organizedTf = r.getOrganizedTaskFragment(); 2089 final TaskFragment taskFragment = r.getTaskFragment(); 2090 final boolean singleActivity = task.getNonFinishingActivityCount() == 1; 2091 if (singleActivity) { 2092 rootTask = task; 2093 2094 // Apply the last recents animation leash transform to the task entering PIP 2095 rootTask.maybeApplyLastRecentsAnimationTransaction(); 2096 2097 if (rootTask.getParent() != taskDisplayArea) { 2098 // root task is nested, but pinned tasks need to be direct children of their 2099 // display area, so reparent. 2100 rootTask.reparent(taskDisplayArea, true /* onTop */); 2101 } 2102 2103 rootTask.forAllTaskFragments(tf -> { 2104 if (!tf.isOrganizedTaskFragment()) { 2105 return; 2106 } 2107 tf.clearAdjacentTaskFragments(); 2108 tf.setCompanionTaskFragment(null /* companionTaskFragment */); 2109 tf.setAnimationParams(TaskFragmentAnimationParams.DEFAULT); 2110 if (tf.getTopNonFinishingActivity() != null) { 2111 // When the Task is entering picture-in-picture, we should clear all 2112 // override from the client organizer, so the PIP activity can get the 2113 // correct config from the Task, and prevent conflict with the 2114 // PipTaskOrganizer. TaskFragmentOrganizer may have requested relative 2115 // bounds, so reset the relative bounds before update configuration. 2116 tf.setRelativeEmbeddedBounds(new Rect()); 2117 tf.updateRequestedOverrideConfiguration(EMPTY); 2118 } 2119 }); 2120 } else { 2121 // In the case of multiple activities, we will create a new task for it and then 2122 // move the PIP activity into the task. Note that we explicitly defer the task 2123 // appear being sent in this case and mark this newly created task to been visible. 2124 rootTask = new Task.Builder(mService) 2125 .setActivityType(r.getActivityType()) 2126 .setOnTop(true) 2127 .setActivityInfo(r.info) 2128 .setParent(taskDisplayArea) 2129 .setIntent(r.intent) 2130 .setDeferTaskAppear(true) 2131 .setHasBeenVisible(true) 2132 // In case the activity is in system split screen, or Activity Embedding 2133 // split, we need to animate the PIP Task from the original TaskFragment 2134 // bounds, so also setting the windowing mode, otherwise the bounds may 2135 // be reset to fullscreen. 2136 .setWindowingMode(taskFragment.getWindowingMode()) 2137 .build(); 2138 // Establish bi-directional link between the original and pinned task. 2139 r.setLastParentBeforePip(launchIntoPipHostActivity); 2140 // It's possible the task entering PIP is in freeform, so save the last 2141 // non-fullscreen bounds. Then when this new PIP task exits PIP, it can restore 2142 // to its previous freeform bounds. 2143 rootTask.setLastNonFullscreenBounds(task.mLastNonFullscreenBounds); 2144 // When creating a new Task for PiP, set its initial bounds as the TaskFragment in 2145 // case the activity is embedded, so that it can be animated to PiP window from the 2146 // current bounds. 2147 // Use Task#setBoundsUnchecked to skip checking windowing mode as the windowing mode 2148 // will be updated later after this is collected in transition. 2149 rootTask.setBoundsUnchecked(taskFragment.getBounds()); 2150 // The exit-PIP activity resumes early for seamless transition. In certain 2151 // scenarios, this introduces unintended addition to recents. To address this, 2152 // we mark the root task for automatic removal from recents. This ensures that 2153 // after the pinned activity reparents to its original task, the root task is 2154 // automatically removed from the recents list. 2155 rootTask.autoRemoveRecents = true; 2156 2157 // Move the last recents animation transaction from original task to the new one. 2158 if (task.mLastRecentsAnimationTransaction != null) { 2159 rootTask.setLastRecentsAnimationTransaction( 2160 task.mLastRecentsAnimationTransaction, 2161 task.mLastRecentsAnimationOverlay); 2162 task.clearLastRecentsAnimationTransaction(false /* forceRemoveOverlay */); 2163 } else { 2164 // Reset the original task surface 2165 task.resetSurfaceControlTransforms(); 2166 } 2167 2168 // The organized TaskFragment is becoming empty because this activity is reparented 2169 // to a new PIP Task. In this case, we should notify the organizer about why the 2170 // TaskFragment becomes empty. 2171 if (organizedTf != null && organizedTf.getNonFinishingActivityCount() == 1 2172 && organizedTf.getTopNonFinishingActivity() == r) { 2173 organizedTf.mClearedTaskFragmentForPip = true; 2174 } 2175 2176 if (isPip2ExperimentEnabled()) { 2177 transitionController.collectExistenceChange(rootTask); 2178 } else { 2179 transitionController.collect(rootTask); 2180 } 2181 2182 if (transitionController.isShellTransitionsEnabled()) { 2183 // set mode NOW so that when we reparent the activity, it won't be resumed. 2184 // During recents animations, the original task is "occluded" by launcher but 2185 // it wasn't paused (due to transient-launch). If we reparent to the (top) task 2186 // now, it will take focus briefly which confuses the RecentTasks tracker. 2187 rootTask.setRootTaskWindowingMode(WINDOWING_MODE_PINNED); 2188 } 2189 // Temporarily disable focus when reparenting to avoid intermediate focus change 2190 // (because the task is on top and the activity is resumed), which could cause the 2191 // task to be added in recents task list unexpectedly. 2192 rootTask.setFocusable(false); 2193 // There are multiple activities in the task and moving the top activity should 2194 // reveal/leave the other activities in their original task. 2195 // On the other hand, ActivityRecord#onParentChanged takes care of setting the 2196 // up-to-dated root pinned task information on this newly created root task. 2197 r.reparent(rootTask, MAX_VALUE, reason); 2198 rootTask.setFocusable(true); 2199 2200 // Ensure the leash of new task is in sync with its current bounds after reparent. 2201 rootTask.maybeApplyLastRecentsAnimationTransaction(); 2202 } 2203 2204 // TODO(remove-legacy-transit): Move this to the `singleActivity` case when removing 2205 // legacy transit. 2206 rootTask.setRootTaskWindowingMode(WINDOWING_MODE_PINNED); 2207 if (isPip2ExperimentEnabled() && bounds != null) { 2208 // set the final pip bounds in advance if pip2 is enabled 2209 rootTask.setBounds(bounds); 2210 } 2211 2212 // Set the launch bounds for launch-into-pip Activity on the root task. 2213 if (r.getOptions() != null && r.getOptions().isLaunchIntoPip()) { 2214 // Record the snapshot now, it will be later fetched for content-pip animation. 2215 // We do this early in the process to make sure the right snapshot is used for 2216 // entering content-pip animation. 2217 mWindowManager.mTaskSnapshotController.recordSnapshot(task); 2218 rootTask.setBounds(r.pictureInPictureArgs.getSourceRectHint()); 2219 } 2220 rootTask.setDeferTaskAppear(false); 2221 2222 if (!isPip2ExperimentEnabled()) { 2223 // After setting this, it is not expected to change activity configuration until the 2224 // transition animation is finished. So the activity can keep consistent appearance 2225 // when animating. 2226 r.mWaitForEnteringPinnedMode = true; 2227 } 2228 // Reset the state that indicates it can enter PiP while pausing after we've moved it 2229 // to the root pinned task 2230 r.supportsEnterPipOnTaskSwitch = false; 2231 2232 if (organizedTf != null && organizedTf.mClearedTaskFragmentForPip 2233 && organizedTf.isTaskVisibleRequested()) { 2234 // Dispatch the pending info to TaskFragmentOrganizer before PIP animation. 2235 // Otherwise, it will keep waiting for the empty TaskFragment to be non-empty. 2236 mService.mTaskFragmentOrganizerController.dispatchPendingInfoChangedEvent( 2237 organizedTf); 2238 } 2239 } finally { 2240 mService.continueWindowLayout(); 2241 try { 2242 if (localVisibilityDeferred) { 2243 mTaskSupervisor.setDeferRootVisibilityUpdate(false); 2244 ensureActivitiesVisible(); 2245 } 2246 } finally { 2247 transitionController.continueTransitionReady(); 2248 pipChangesApplied.meet(); 2249 } 2250 } 2251 2252 // can be null (for now) if shell transitions are disabled or inactive at this time 2253 final Transition transit = transitionController.getCollectingTransition(); 2254 if (requestStart && transit != null) { 2255 // Request at end since we want task-organizer events from ensureActivitiesVisible 2256 // to be recognized. 2257 transitionController.requestStartTransition(transit, rootTask, 2258 null /* remoteTransition */, null /* displayChange */); 2259 // A new transition was created just for this operations. Since the operation is 2260 // complete, mark it as ready. 2261 transit.setReady(rootTask, true /* ready */); 2262 } 2263 2264 resumeFocusedTasksTopActivities(); 2265 2266 notifyActivityPipModeChanged(r.getTask(), r); 2267 2268 if (!isPip2ExperimentEnabled()) { 2269 // TODO: b/335866033 Remove the abort PiP on timeout once PiP2 flag is on. 2270 // Set up a timeout callback to potentially abort PiP enter if in an inconsistent state. 2271 scheduleTimeoutAbortPipEnter(rootTask); 2272 } 2273 } 2274 scheduleTimeoutAbortPipEnter(Task rootTask)2275 private void scheduleTimeoutAbortPipEnter(Task rootTask) { 2276 if (mMaybeAbortPipEnterRunnable != null) { 2277 // If there is an abort enter PiP check pending already remove it and abort 2278 // immediately since we are trying to enter PiP in an inconsistent state 2279 mHandler.removeCallbacks(mMaybeAbortPipEnterRunnable); 2280 mMaybeAbortPipEnterRunnable.run(); 2281 } 2282 // Snapshot a throwable early on to display the callstack upon abort later on timeout. 2283 final Throwable enterPipThrowable = new Throwable(); 2284 // Set up a timeout to potentially roll back the task change to PINNED mode 2285 // by aborting PiP. 2286 mMaybeAbortPipEnterRunnable = new Runnable() { 2287 @Override 2288 public void run() { 2289 synchronized (mService.mGlobalLock) { 2290 if (mTransitionController.inTransition()) { 2291 // If this task is a part an active transition aborting PiP might break 2292 // it; so run the timeout callback directly once idle. 2293 2294 final Runnable expectedMaybeAbortAtTimeout = mMaybeAbortPipEnterRunnable; 2295 mTransitionController.mStateValidators.add(() -> { 2296 // If a second PiP transition comes in, it runs the abort runnable for 2297 // the first transition pre-emptively, so we need to avoid calling 2298 // the same runnable twice when validating states. 2299 if (expectedMaybeAbortAtTimeout != mMaybeAbortPipEnterRunnable) return; 2300 mMaybeAbortPipEnterRunnable = null; 2301 run(); 2302 }); 2303 return; 2304 } else { 2305 mMaybeAbortPipEnterRunnable = null; 2306 } 2307 mService.deferWindowLayout(); 2308 final ActivityRecord top = rootTask.getTopMostActivity(); 2309 final ActivityManager.RunningTaskInfo beforeTaskInfo = 2310 rootTask.getTaskInfo(); 2311 if (top != null && !top.inPinnedWindowingMode() 2312 && rootTask.abortPipEnter(top)) { 2313 Slog.wtf(TAG, "Enter PiP was aborted via a scheduled timeout" 2314 + "task_state_before=" + beforeTaskInfo 2315 + "task_state_after=" + rootTask.getTaskInfo(), 2316 enterPipThrowable); 2317 } 2318 mService.continueWindowLayout(); 2319 } 2320 } 2321 }; 2322 mHandler.postDelayed(mMaybeAbortPipEnterRunnable, PINNED_TASK_ABORT_TIMEOUT); 2323 Slog.d(TAG, "a delayed check for potentially aborting PiP if " 2324 + "in a wrong state is scheduled."); 2325 } 2326 2327 2328 /** 2329 * Notifies when an activity enters or leaves PIP mode. 2330 * 2331 * @param task the task of {@param r} 2332 * @param r indicates the activity currently in PIP, can be null to indicate no activity is 2333 * currently in PIP mode. 2334 */ notifyActivityPipModeChanged(@onNull Task task, @Nullable ActivityRecord r)2335 void notifyActivityPipModeChanged(@NonNull Task task, @Nullable ActivityRecord r) { 2336 final boolean inPip = r != null; 2337 if (inPip) { 2338 mService.getTaskChangeNotificationController().notifyActivityPinned(r); 2339 } else { 2340 mService.getTaskChangeNotificationController().notifyActivityUnpinned(); 2341 } 2342 mWindowManager.mPolicy.setPipVisibilityLw(inPip); 2343 if (task.getSurfaceControl() != null) { 2344 mWmService.mTransactionFactory.get() 2345 .setTrustedOverlay(task.getSurfaceControl(), inPip) 2346 .apply(); 2347 } 2348 } 2349 executeAppTransitionForAllDisplay()2350 void executeAppTransitionForAllDisplay() { 2351 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { 2352 final DisplayContent display = getChildAt(displayNdx); 2353 display.mDisplayContent.executeAppTransition(); 2354 } 2355 } 2356 2357 @Nullable findTask(ActivityRecord r, TaskDisplayArea preferredTaskDisplayArea, boolean includeLaunchedFromBubble)2358 ActivityRecord findTask(ActivityRecord r, TaskDisplayArea preferredTaskDisplayArea, 2359 boolean includeLaunchedFromBubble) { 2360 return findTask(r.getActivityType(), r.taskAffinity, r.intent, r.info, 2361 preferredTaskDisplayArea, includeLaunchedFromBubble); 2362 } 2363 2364 @Nullable findTask(int activityType, String taskAffinity, Intent intent, ActivityInfo info, TaskDisplayArea preferredTaskDisplayArea, boolean includeLaunchedFromBubble)2365 ActivityRecord findTask(int activityType, String taskAffinity, Intent intent, ActivityInfo info, 2366 TaskDisplayArea preferredTaskDisplayArea, boolean includeLaunchedFromBubble) { 2367 ProtoLog.d(WM_DEBUG_TASKS, "Looking for task of type=%s, taskAffinity=%s, intent=%s" 2368 + ", info=%s, preferredTDA=%s, includeLaunchedFromBubble=%b", activityType, 2369 taskAffinity, intent, info, preferredTaskDisplayArea, includeLaunchedFromBubble); 2370 mTmpFindTaskResult.init(activityType, taskAffinity, intent, info, 2371 includeLaunchedFromBubble); 2372 2373 // Looking up task on preferred display area first 2374 ActivityRecord candidateActivity = null; 2375 if (preferredTaskDisplayArea != null) { 2376 mTmpFindTaskResult.process(preferredTaskDisplayArea); 2377 if (mTmpFindTaskResult.mIdealRecord != null) { 2378 return mTmpFindTaskResult.mIdealRecord; 2379 } else if (mTmpFindTaskResult.mCandidateRecord != null) { 2380 candidateActivity = mTmpFindTaskResult.mCandidateRecord; 2381 } 2382 } 2383 2384 final ActivityRecord idealMatchActivity = getItemFromTaskDisplayAreas(taskDisplayArea -> { 2385 if (taskDisplayArea == preferredTaskDisplayArea) { 2386 return null; 2387 } 2388 2389 mTmpFindTaskResult.process(taskDisplayArea); 2390 if (mTmpFindTaskResult.mIdealRecord != null) { 2391 return mTmpFindTaskResult.mIdealRecord; 2392 } 2393 return null; 2394 }); 2395 if (idealMatchActivity != null) { 2396 return idealMatchActivity; 2397 } 2398 2399 if (WM_DEBUG_TASKS.isEnabled() && candidateActivity == null) { 2400 ProtoLog.d(WM_DEBUG_TASKS, "No task found"); 2401 } 2402 return candidateActivity; 2403 } 2404 2405 /** 2406 * Finish the topmost activities in all leaf tasks that belong to the crashed app. 2407 * 2408 * @param app The app that crashed. 2409 * @param reason Reason to perform this action. 2410 * @return The finished task which was on top or visible, otherwise {@code null} if the crashed 2411 * app doesn't have activity in visible task. 2412 */ 2413 @Nullable finishTopCrashedActivities(WindowProcessController app, String reason)2414 Task finishTopCrashedActivities(WindowProcessController app, String reason) { 2415 Task focusedRootTask = getTopDisplayFocusedRootTask(); 2416 final Task[] finishedTask = new Task[1]; 2417 forAllLeafTasks(leafTask -> { 2418 final boolean recordTopOrVisible = finishedTask[0] == null 2419 && (focusedRootTask == leafTask.getRootTask() || leafTask.isVisibleRequested()); 2420 final Task t = leafTask.finishTopCrashedActivityLocked(app, reason); 2421 if (recordTopOrVisible) { 2422 finishedTask[0] = t; 2423 } 2424 }, true); 2425 return finishedTask[0]; 2426 } 2427 ensureVisibilityOnVisibleActivityDiedOrCrashed(String reason)2428 void ensureVisibilityOnVisibleActivityDiedOrCrashed(String reason) { 2429 final Task topTask = getTopDisplayFocusedRootTask(); 2430 if (topTask != null && topTask.topRunningActivity(true /* focusableOnly */) == null) { 2431 // Move the next focusable task to front. 2432 topTask.adjustFocusToNextFocusableTask(reason); 2433 } 2434 if (!resumeFocusedTasksTopActivities()) { 2435 // It may be nothing to resume because there are pausing activities or all the top 2436 // activities are resumed. Then it still needs to make sure all visible activities are 2437 // running in case the tasks were reordered or there are non-top visible activities. 2438 ensureActivitiesVisible(); 2439 } 2440 } 2441 resumeFocusedTasksTopActivities()2442 boolean resumeFocusedTasksTopActivities() { 2443 return resumeFocusedTasksTopActivities(null, null, null, false /* deferPause */); 2444 } 2445 resumeFocusedTasksTopActivities( Task targetRootTask, ActivityRecord target)2446 boolean resumeFocusedTasksTopActivities( 2447 Task targetRootTask, ActivityRecord target) { 2448 return resumeFocusedTasksTopActivities(targetRootTask, target, null /* targetOptions */, 2449 false /* deferPause */); 2450 } 2451 resumeFocusedTasksTopActivities( Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions, boolean deferPause)2452 boolean resumeFocusedTasksTopActivities( 2453 Task targetRootTask, ActivityRecord target, ActivityOptions targetOptions, 2454 boolean deferPause) { 2455 if (!mTaskSupervisor.readyToResume()) { 2456 return false; 2457 } 2458 2459 boolean result = false; 2460 if (targetRootTask != null && (targetRootTask.isTopRootTaskInDisplayArea() 2461 || getTopDisplayFocusedRootTask() == targetRootTask)) { 2462 result = targetRootTask.resumeTopActivityUncheckedLocked(target, targetOptions, 2463 deferPause); 2464 } 2465 2466 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { 2467 final DisplayContent display = getChildAt(displayNdx); 2468 final boolean curResult = result; 2469 boolean[] resumedOnDisplay = new boolean[1]; 2470 final ActivityRecord topOfDisplay = display.topRunningActivity(); 2471 display.forAllRootTasks(rootTask -> { 2472 final ActivityRecord topRunningActivity = rootTask.topRunningActivity(); 2473 if (!rootTask.isFocusableAndVisible() || topRunningActivity == null) { 2474 return; 2475 } 2476 if (rootTask == targetRootTask) { 2477 // Simply update the result for targetRootTask because the targetRootTask 2478 // had already resumed in above. We don't want to resume it again, 2479 // especially in some cases, it would cause a second launch failure 2480 // if app process was dead. 2481 resumedOnDisplay[0] |= curResult; 2482 return; 2483 } 2484 if (topRunningActivity.isState(RESUMED) && topRunningActivity == topOfDisplay) { 2485 // Kick off any lingering app transitions form the MoveTaskToFront operation, 2486 // but only consider the top activity on that display. 2487 rootTask.executeAppTransition(targetOptions); 2488 } else { 2489 resumedOnDisplay[0] |= topRunningActivity.makeActiveIfNeeded(target); 2490 } 2491 }); 2492 result |= resumedOnDisplay[0]; 2493 if (!resumedOnDisplay[0]) { 2494 // In cases when there are no valid activities (e.g. device just booted or launcher 2495 // crashed) it's possible that nothing was resumed on a display. Requesting resume 2496 // of top activity in focused root task explicitly will make sure that at least home 2497 // activity is started and resumed, and no recursion occurs. 2498 final Task focusedRoot = display.getFocusedRootTask(); 2499 if (focusedRoot != null) { 2500 result |= focusedRoot.resumeTopActivityUncheckedLocked( 2501 target, targetOptions, false /* skipPause */); 2502 } else if (targetRootTask == null) { 2503 result |= resumeHomeActivity(null /* prev */, "no-focusable-task", 2504 display.getDefaultTaskDisplayArea()); 2505 } 2506 } 2507 } 2508 2509 return result; 2510 } 2511 sendSleepTransition(final DisplayContent display)2512 void sendSleepTransition(final DisplayContent display) { 2513 // We don't actually care about collecting anything here. We really just want 2514 // this as a signal to the transition-player. 2515 final Transition transition = new Transition(TRANSIT_SLEEP, 0 /* flags */, 2516 display.mTransitionController, mWmService.mSyncEngine); 2517 final TransitionController.OnStartCollect sendSleepTransition = (deferred) -> { 2518 if (deferred && !display.shouldSleep()) { 2519 transition.abort(); 2520 } else { 2521 display.mTransitionController.requestStartTransition(transition, 2522 null /* trigger */, null /* remote */, null /* display */); 2523 // Force playing immediately so that unrelated ops can't be collected. 2524 transition.playNow(); 2525 } 2526 }; 2527 if (!display.mTransitionController.isCollecting()) { 2528 // Since this bypasses sync, submit directly ignoring whether sync-engine 2529 // is active. 2530 if (mWindowManager.mSyncEngine.hasActiveSync()) { 2531 Slog.w(TAG, "Ongoing sync outside of a transition."); 2532 } 2533 display.mTransitionController.moveToCollecting(transition); 2534 sendSleepTransition.onCollectStarted(false /* deferred */); 2535 } else { 2536 display.mTransitionController.startCollectOrQueue(transition, 2537 sendSleepTransition); 2538 } 2539 } 2540 applySleepTokens(boolean applyToRootTasks)2541 void applySleepTokens(boolean applyToRootTasks) { 2542 boolean scheduledSleepTransition = false; 2543 2544 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { 2545 // Set the sleeping state of the display. 2546 final DisplayContent display = getChildAt(displayNdx); 2547 final boolean displayShouldSleep = display.shouldSleep(); 2548 if (displayShouldSleep == display.isSleeping()) { 2549 continue; 2550 } 2551 final boolean wasSleeping = display.isSleeping(); 2552 display.setIsSleeping(displayShouldSleep); 2553 2554 if (display.mTransitionController.isShellTransitionsEnabled() 2555 && !scheduledSleepTransition 2556 // Only care if there are actual sleep tokens. 2557 && displayShouldSleep && !display.mAllSleepTokens.isEmpty()) { 2558 scheduledSleepTransition = true; 2559 2560 if (!mHandler.hasMessages(MSG_SEND_SLEEP_TRANSITION)) { 2561 mHandler.sendMessageDelayed( 2562 mHandler.obtainMessage(MSG_SEND_SLEEP_TRANSITION, display), 2563 SLEEP_TRANSITION_WAIT_MILLIS); 2564 } 2565 } 2566 2567 if (!applyToRootTasks) { 2568 continue; 2569 } 2570 2571 // Prepare transition before resume top activity, so it can be collected. 2572 if (!displayShouldSleep && display.mTransitionController.isShellTransitionsEnabled() 2573 && !display.mTransitionController.isCollecting()) { 2574 // Use NONE if keyguard is not showing. 2575 int transit = TRANSIT_NONE; 2576 Task startTask = null; 2577 int flags = 0; 2578 if (display.isKeyguardOccluded()) { 2579 startTask = display.getTaskOccludingKeyguard(); 2580 flags = TRANSIT_FLAG_KEYGUARD_OCCLUDING; 2581 transit = WindowManager.TRANSIT_KEYGUARD_OCCLUDE; 2582 } 2583 if (wasSleeping) { 2584 transit = TRANSIT_WAKE; 2585 } 2586 display.mTransitionController.requestStartTransition( 2587 display.mTransitionController.createTransition(transit, flags), 2588 startTask, null /* remoteTransition */, null /* displayChange */); 2589 } 2590 // Set the sleeping state of the root tasks on the display. 2591 display.forAllRootTasks(rootTask -> { 2592 if (displayShouldSleep) { 2593 rootTask.goToSleepIfPossible(false /* shuttingDown */); 2594 } else { 2595 rootTask.forAllLeafTasksAndLeafTaskFragments( 2596 taskFragment -> taskFragment.awakeFromSleeping(), 2597 true /* traverseTopToBottom */); 2598 if (rootTask.isFocusedRootTaskOnDisplay() 2599 && !mTaskSupervisor.getKeyguardController() 2600 .isKeyguardOrAodShowing(display.mDisplayId)) { 2601 // If the keyguard is unlocked - resume immediately. 2602 // It is possible that the display will not be awake at the time we 2603 // process the keyguard going away, which can happen before the sleep 2604 // token is released. As a result, it is important we resume the 2605 // activity here. 2606 rootTask.resumeTopActivityUncheckedLocked(); 2607 } 2608 // The visibility update must not be called before resuming the top, so the 2609 // display orientation can be updated first if needed. Otherwise there may 2610 // have redundant configuration changes due to apply outdated display 2611 // orientation (from keyguard) to activity. 2612 rootTask.ensureActivitiesVisible(null /* starting */); 2613 } 2614 }); 2615 } 2616 2617 if (!scheduledSleepTransition) { 2618 mHandler.removeMessages(MSG_SEND_SLEEP_TRANSITION); 2619 } 2620 } 2621 getRootTask(int rooTaskId)2622 protected Task getRootTask(int rooTaskId) { 2623 for (int i = getChildCount() - 1; i >= 0; --i) { 2624 final Task rootTask = getChildAt(i).getRootTask(rooTaskId); 2625 if (rootTask != null) { 2626 return rootTask; 2627 } 2628 } 2629 return null; 2630 } 2631 2632 /** @see DisplayContent#getRootTask(int, int) */ getRootTask(int windowingMode, int activityType)2633 Task getRootTask(int windowingMode, int activityType) { 2634 for (int i = getChildCount() - 1; i >= 0; --i) { 2635 final Task rootTask = getChildAt(i).getRootTask(windowingMode, activityType); 2636 if (rootTask != null) { 2637 return rootTask; 2638 } 2639 } 2640 return null; 2641 } 2642 getRootTask(int windowingMode, int activityType, int displayId)2643 private Task getRootTask(int windowingMode, int activityType, 2644 int displayId) { 2645 DisplayContent display = getDisplayContent(displayId); 2646 if (display == null) { 2647 return null; 2648 } 2649 return display.getRootTask(windowingMode, activityType); 2650 } 2651 getRootTaskInfo(Task task)2652 private RootTaskInfo getRootTaskInfo(Task task) { 2653 RootTaskInfo info = new RootTaskInfo(); 2654 task.fillTaskInfo(info); 2655 2656 final DisplayContent displayContent = task.getDisplayContent(); 2657 if (displayContent == null) { 2658 // A task might be not attached to a display. 2659 info.position = -1; 2660 } else { 2661 // Find the task z-order among all root tasks on the display from bottom to top. 2662 final int[] taskIndex = new int[1]; 2663 final boolean[] hasFound = new boolean[1]; 2664 displayContent.forAllRootTasks(rootTask -> { 2665 if (task == rootTask) { 2666 hasFound[0] = true; 2667 return true; 2668 } 2669 taskIndex[0]++; 2670 return false; 2671 }, false /* traverseTopToBottom */); 2672 info.position = hasFound[0] ? taskIndex[0] : -1; 2673 } 2674 info.visible = task.shouldBeVisible(null); 2675 task.getBounds(info.bounds); 2676 2677 final int numTasks = task.getDescendantTaskCount(); 2678 info.childTaskIds = new int[numTasks]; 2679 info.childTaskNames = new String[numTasks]; 2680 info.childTaskBounds = new Rect[numTasks]; 2681 info.childTaskUserIds = new int[numTasks]; 2682 final int[] currentIndex = {0}; 2683 2684 task.forAllLeafTasks(t -> { 2685 int i = currentIndex[0]; 2686 info.childTaskIds[i] = t.mTaskId; 2687 info.childTaskNames[i] = t.origActivity != null ? t.origActivity.flattenToString() 2688 : t.realActivity != null ? t.realActivity.flattenToString() 2689 : t.getTopNonFinishingActivity() != null 2690 ? t.getTopNonFinishingActivity().packageName : "unknown"; 2691 info.childTaskBounds[i] = t.mAtmService.getTaskBounds(t.mTaskId); 2692 info.childTaskUserIds[i] = t.mUserId; 2693 currentIndex[0] = ++i; 2694 }, false /* traverseTopToBottom */); 2695 2696 final ActivityRecord top = task.topRunningActivity(); 2697 info.topActivity = top != null ? top.intent.getComponent() : null; 2698 return info; 2699 } 2700 getRootTaskInfo(int taskId)2701 RootTaskInfo getRootTaskInfo(int taskId) { 2702 Task task = getRootTask(taskId); 2703 if (task != null) { 2704 return getRootTaskInfo(task); 2705 } 2706 return null; 2707 } 2708 getRootTaskInfo(int windowingMode, int activityType)2709 RootTaskInfo getRootTaskInfo(int windowingMode, int activityType) { 2710 final Task rootTask = getRootTask(windowingMode, activityType); 2711 return (rootTask != null) ? getRootTaskInfo(rootTask) : null; 2712 } 2713 getRootTaskInfo(int windowingMode, int activityType, int displayId)2714 RootTaskInfo getRootTaskInfo(int windowingMode, int activityType, int displayId) { 2715 final Task rootTask = getRootTask(windowingMode, activityType, displayId); 2716 return (rootTask != null) ? getRootTaskInfo(rootTask) : null; 2717 } 2718 2719 /** If displayId == INVALID_DISPLAY, this will get root task infos on all displays */ getAllRootTaskInfos(int displayId)2720 ArrayList<RootTaskInfo> getAllRootTaskInfos(int displayId) { 2721 final ArrayList<RootTaskInfo> list = new ArrayList<>(); 2722 if (displayId == INVALID_DISPLAY) { 2723 forAllRootTasks(rootTask -> { 2724 list.add(getRootTaskInfo(rootTask)); 2725 }); 2726 return list; 2727 } 2728 final DisplayContent display = getDisplayContent(displayId); 2729 if (display == null) { 2730 return list; 2731 } 2732 display.forAllRootTasks(rootTask -> { 2733 list.add(getRootTaskInfo(rootTask)); 2734 }); 2735 return list; 2736 } 2737 2738 @Override onDisplayAdded(int displayId)2739 public void onDisplayAdded(int displayId) { 2740 if (DEBUG_ROOT_TASK) Slog.v(TAG, "Display added displayId=" + displayId); 2741 synchronized (mService.mGlobalLock) { 2742 final DisplayContent display = getDisplayContentOrCreate(displayId); 2743 if (display == null) { 2744 return; 2745 } 2746 2747 if (ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT.isTrue()) { 2748 if (display.allowContentModeSwitch()) { 2749 mWindowManager.mDisplayWindowSettings 2750 .setShouldShowSystemDecorsInternalLocked(display, 2751 display.mDisplay.canHostTasks()); 2752 } 2753 2754 final boolean inTopology = mWindowManager.mDisplayWindowSettings 2755 .shouldShowSystemDecorsLocked(display); 2756 mWmService.mDisplayManagerInternal.onDisplayBelongToTopologyChanged(displayId, 2757 inTopology); 2758 } 2759 2760 startSystemDecorations(display, "displayAdded"); 2761 2762 // Drop any cached DisplayInfos associated with this display id - the values are now 2763 // out of date given this display added event. 2764 mWmService.mPossibleDisplayInfoMapper.removePossibleDisplayInfos(displayId); 2765 } 2766 } 2767 startSystemDecorations(final DisplayContent displayContent, String reason)2768 void startSystemDecorations(final DisplayContent displayContent, String reason) { 2769 // Do not start home before booting, or it may accidentally finish booting before it 2770 // starts. Instead, we expect home activities to be launched when the system is ready 2771 // (ActivityManagerService#systemReady). 2772 if (!mService.isBooted() && !mService.isBooting()) { 2773 return; 2774 } 2775 2776 startHomeOnDisplay(mCurrentUser, reason, displayContent.getDisplayId()); 2777 displayContent.getDisplayPolicy().notifyDisplayAddSystemDecorations(); 2778 } 2779 2780 @Override onDisplayRemoved(int displayId)2781 public void onDisplayRemoved(int displayId) { 2782 if (DEBUG_ROOT_TASK) Slog.v(TAG, "Display removed displayId=" + displayId); 2783 if (displayId == DEFAULT_DISPLAY) { 2784 throw new IllegalArgumentException("Can't remove the primary display."); 2785 } 2786 2787 synchronized (mService.mGlobalLock) { 2788 final DisplayContent displayContent = getDisplayContent(displayId); 2789 if (displayContent == null) { 2790 return; 2791 } 2792 displayContent.remove(); 2793 mWmService.mPossibleDisplayInfoMapper.removePossibleDisplayInfos(displayId); 2794 } 2795 } 2796 2797 @Override onDisplayChanged(int displayId)2798 public void onDisplayChanged(int displayId) { 2799 if (DEBUG_ROOT_TASK) Slog.v(TAG, "Display changed displayId=" + displayId); 2800 synchronized (mService.mGlobalLock) { 2801 final DisplayContent displayContent = getDisplayContent(displayId); 2802 if (displayContent != null) { 2803 displayContent.requestDisplayUpdate( 2804 () -> { 2805 clearDisplayInfoCaches(displayId); 2806 if (ENABLE_DISPLAY_CONTENT_MODE_MANAGEMENT.isTrue()) { 2807 displayContent.onDisplayInfoChangeApplied(); 2808 } 2809 }); 2810 } else { 2811 clearDisplayInfoCaches(displayId); 2812 } 2813 } 2814 } 2815 clearDisplayInfoCaches(int displayId)2816 private void clearDisplayInfoCaches(int displayId) { 2817 // Drop any cached DisplayInfos associated with this display id - the values are now 2818 // out of date given this display changed event. 2819 mWmService.mPossibleDisplayInfoMapper.removePossibleDisplayInfos(displayId); 2820 updateDisplayImePolicyCache(); 2821 } 2822 updateDisplayImePolicyCache()2823 void updateDisplayImePolicyCache() { 2824 ArrayMap<Integer, Integer> displayImePolicyMap = new ArrayMap<>(); 2825 forAllDisplays(dc -> displayImePolicyMap.put(dc.getDisplayId(), dc.getImePolicy())); 2826 mWmService.mDisplayImePolicyCache = Collections.unmodifiableMap(displayImePolicyMap); 2827 } 2828 2829 /** Update lists of UIDs that are present on displays and have access to them. */ updateUIDsPresentOnDisplay()2830 void updateUIDsPresentOnDisplay() { 2831 mDisplayAccessUIDs.clear(); 2832 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { 2833 final DisplayContent displayContent = getChildAt(displayNdx); 2834 // Only bother calculating the allowlist for private displays 2835 if (displayContent.isPrivate()) { 2836 mDisplayAccessUIDs.append( 2837 displayContent.mDisplayId, displayContent.getPresentUIDs()); 2838 } 2839 } 2840 // Store updated lists in DisplayManager. Callers from outside of AM should get them there. 2841 mDisplayManagerInternal.setDisplayAccessUIDs(mDisplayAccessUIDs); 2842 } 2843 prepareForShutdown()2844 void prepareForShutdown() { 2845 for (int i = 0; i < getChildCount(); i++) { 2846 createSleepToken("shutdown", getChildAt(i).mDisplayId); 2847 } 2848 } 2849 createSleepToken(String tag, int displayId)2850 SleepToken createSleepToken(String tag, int displayId) { 2851 final DisplayContent display = getDisplayContent(displayId); 2852 if (display == null) { 2853 throw new IllegalArgumentException("Invalid display: " + displayId); 2854 } 2855 2856 final int tokenKey = makeSleepTokenKey(tag, displayId); 2857 SleepToken token = mSleepTokens.get(tokenKey); 2858 if (token == null) { 2859 token = new SleepToken(tag, displayId); 2860 mSleepTokens.put(tokenKey, token); 2861 display.mAllSleepTokens.add(token); 2862 ProtoLog.d(WM_DEBUG_SLEEP_TOKEN, "Create SleepToken: tag=%s, displayId=%d", 2863 tag, displayId); 2864 } else { 2865 throw new RuntimeException("Create the same sleep token twice: " + token); 2866 } 2867 return token; 2868 } 2869 removeSleepToken(SleepToken token)2870 void removeSleepToken(SleepToken token) { 2871 if (!mSleepTokens.contains(token.mHashKey)) { 2872 Slog.d(TAG, "Remove non-exist sleep token: " + token + " from " + Debug.getCallers(6)); 2873 } 2874 mSleepTokens.remove(token.mHashKey); 2875 final DisplayContent display = getDisplayContent(token.mDisplayId); 2876 if (display == null) { 2877 Slog.d(TAG, "Remove sleep token for non-existing display: " + token + " from " 2878 + Debug.getCallers(6)); 2879 return; 2880 } 2881 2882 ProtoLog.d(WM_DEBUG_SLEEP_TOKEN, "Remove SleepToken: tag=%s, displayId=%d", 2883 token.mTag, token.mDisplayId); 2884 display.mAllSleepTokens.remove(token); 2885 if (display.mAllSleepTokens.isEmpty()) { 2886 mService.updateSleepIfNeededLocked(); 2887 } 2888 } 2889 addStartingWindowsForVisibleActivities()2890 void addStartingWindowsForVisibleActivities() { 2891 final ArrayList<Task> addedTasks = new ArrayList<>(); 2892 forAllActivities((r) -> { 2893 final Task task = r.getTask(); 2894 if (r.isVisibleRequested() && r.mStartingData == null && !addedTasks.contains(task)) { 2895 r.showStartingWindow(true /*taskSwitch*/); 2896 addedTasks.add(task); 2897 } 2898 }); 2899 } 2900 invalidateTaskLayersAndUpdateOomAdjIfNeeded()2901 void invalidateTaskLayersAndUpdateOomAdjIfNeeded() { 2902 mRankTaskLayersRunnable.mCheckUpdateOomAdj = true; 2903 invalidateTaskLayers(); 2904 } 2905 invalidateTaskLayers()2906 void invalidateTaskLayers() { 2907 if (!mTaskLayersChanged) { 2908 mTaskLayersChanged = true; 2909 mService.mH.post(mRankTaskLayersRunnable); 2910 } 2911 } 2912 2913 /** Generate oom-score-adjustment rank for all tasks in the system based on z-order. */ rankTaskLayers()2914 void rankTaskLayers() { 2915 if (mTaskLayersChanged) { 2916 mTaskLayersChanged = false; 2917 mService.mH.removeCallbacks(mRankTaskLayersRunnable); 2918 } 2919 mTmpTaskLayerRank = 0; 2920 // Only rank for leaf tasks because the score of activity is based on immediate parent. 2921 forAllLeafTasks(task -> { 2922 final int oldRank = task.mLayerRank; 2923 final int oldRatio = task.mNonOccludedFreeformAreaRatio; 2924 task.mNonOccludedFreeformAreaRatio = 0; 2925 if (task.isVisibleRequested()) { 2926 task.mLayerRank = ++mTmpTaskLayerRank; 2927 if (task.inFreeformWindowingMode()) { 2928 computeNonOccludedFreeformAreaRatio(task); 2929 } 2930 } else { 2931 task.mLayerRank = Task.LAYER_RANK_INVISIBLE; 2932 } 2933 if (task.mLayerRank != oldRank 2934 || task.mNonOccludedFreeformAreaRatio != oldRatio) { 2935 task.forAllActivities(activity -> { 2936 if (activity.hasProcess()) { 2937 mTaskSupervisor.onProcessActivityStateChanged(activity.app, 2938 true /* forceBatch */); 2939 } 2940 }); 2941 } 2942 }, true /* traverseTopToBottom */); 2943 if (mTmpOccludingRegion != null) { 2944 mTmpOccludingRegion.setEmpty(); 2945 } 2946 boolean changed = false; 2947 if (!mTaskSupervisor.inActivityVisibilityUpdate()) { 2948 changed = mTaskSupervisor.computeProcessActivityStateBatch(); 2949 } 2950 if (mRankTaskLayersRunnable.mCheckUpdateOomAdj) { 2951 mRankTaskLayersRunnable.mCheckUpdateOomAdj = false; 2952 if (changed) { 2953 mService.updateOomAdj(); 2954 } 2955 } 2956 } 2957 2958 /** This method is called for visible freeform task from top to bottom. */ computeNonOccludedFreeformAreaRatio(@onNull Task task)2959 private void computeNonOccludedFreeformAreaRatio(@NonNull Task task) { 2960 if (!com.android.window.flags.Flags.processPriorityPolicyForMultiWindowMode()) { 2961 return; 2962 } 2963 if (mTmpOccludingRegion == null) { 2964 mTmpOccludingRegion = new Region(); 2965 mTmpTaskRegion = new Region(); 2966 } 2967 final Rect taskBounds = task.getBounds(); 2968 mTmpTaskRegion.set(taskBounds); 2969 // Exclude the area outside the display. 2970 mTmpTaskRegion.op(task.mDisplayContent.getBounds(), Region.Op.INTERSECT); 2971 // Exclude the area covered by the above tasks. 2972 mTmpTaskRegion.op(mTmpOccludingRegion, Region.Op.DIFFERENCE); 2973 task.mNonOccludedFreeformAreaRatio = 100 * RegionUtils.getAreaSize(mTmpTaskRegion) 2974 / (taskBounds.width() * taskBounds.height()); 2975 // Accumulate the occluding region for other visible tasks behind. 2976 mTmpOccludingRegion.op(taskBounds, Region.Op.UNION); 2977 } 2978 clearOtherAppTimeTrackers(AppTimeTracker except)2979 void clearOtherAppTimeTrackers(AppTimeTracker except) { 2980 forAllActivities(r -> { 2981 if (r.appTimeTracker != except) { 2982 r.appTimeTracker = null; 2983 } 2984 }); 2985 } 2986 scheduleDestroyAllActivities(String reason)2987 void scheduleDestroyAllActivities(String reason) { 2988 mDestroyAllActivitiesReason = reason; 2989 mService.mH.post(mDestroyAllActivitiesRunnable); 2990 } 2991 removeAllMaybeAbortPipEnterRunnable()2992 void removeAllMaybeAbortPipEnterRunnable() { 2993 if (mMaybeAbortPipEnterRunnable == null) { 2994 return; 2995 } 2996 mHandler.removeCallbacks(mMaybeAbortPipEnterRunnable); 2997 mMaybeAbortPipEnterRunnable = null; 2998 } 2999 3000 // Tries to put all activity tasks to sleep. Returns true if all tasks were 3001 // successfully put to sleep. putTasksToSleep(boolean allowDelay, boolean shuttingDown)3002 boolean putTasksToSleep(boolean allowDelay, boolean shuttingDown) { 3003 final boolean[] result = {true}; 3004 forAllRootTasks(task -> { 3005 if (allowDelay) { 3006 result[0] &= task.goToSleepIfPossible(shuttingDown); 3007 } else { 3008 task.ensureActivitiesVisible(null /* starting */); 3009 } 3010 }); 3011 return result[0]; 3012 } 3013 findActivity(Intent intent, ActivityInfo info, boolean compareIntentFilters)3014 ActivityRecord findActivity(Intent intent, ActivityInfo info, boolean compareIntentFilters) { 3015 ComponentName cls = intent.getComponent(); 3016 if (info.targetActivity != null) { 3017 cls = new ComponentName(info.packageName, info.targetActivity); 3018 } 3019 final int userId = UserHandle.getUserId(info.applicationInfo.uid); 3020 3021 final PooledPredicate p = PooledLambda.obtainPredicate( 3022 RootWindowContainer::matchesActivity, PooledLambda.__(ActivityRecord.class), 3023 userId, compareIntentFilters, intent, cls); 3024 final ActivityRecord r = getActivity(p); 3025 p.recycle(); 3026 return r; 3027 } 3028 matchesActivity(ActivityRecord r, int userId, boolean compareIntentFilters, Intent intent, ComponentName cls)3029 private static boolean matchesActivity(ActivityRecord r, int userId, 3030 boolean compareIntentFilters, Intent intent, ComponentName cls) { 3031 if (!r.canBeTopRunning() || r.mUserId != userId) return false; 3032 3033 if (compareIntentFilters) { 3034 if (r.intent.filterEquals(intent)) { 3035 return true; 3036 } 3037 } else { 3038 // Compare the target component instead of intent component so we don't miss if the 3039 // activity uses alias. 3040 if (r.mActivityComponent.equals(cls)) { 3041 return true; 3042 } 3043 } 3044 return false; 3045 } 3046 hasAwakeDisplay()3047 boolean hasAwakeDisplay() { 3048 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { 3049 final DisplayContent display = getChildAt(displayNdx); 3050 if (!display.shouldSleep()) { 3051 return true; 3052 } 3053 } 3054 return false; 3055 } 3056 getOrCreateRootTask(@ullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable Task candidateTask, boolean onTop)3057 Task getOrCreateRootTask(@Nullable ActivityRecord r, @Nullable ActivityOptions options, 3058 @Nullable Task candidateTask, boolean onTop) { 3059 return getOrCreateRootTask(r, options, candidateTask, null /* sourceTask */, onTop, 3060 null /* launchParams */, 0 /* launchFlags */); 3061 } 3062 3063 /** 3064 * Returns the right root task to use for launching factoring in all the input parameters. 3065 * 3066 * @param r The activity we are trying to launch. Can be null. 3067 * @param options The activity options used to the launch. Can be null. 3068 * @param candidateTask The possible task the activity might be launched in. Can be null. 3069 * @param sourceTask The task requesting to start activity. Can be null. 3070 * @param launchParams The resolved launch params to use. 3071 * @param launchFlags The launch flags for this launch. 3072 * @param realCallingPid The pid from {@link ActivityStarter#setRealCallingPid} 3073 * @param realCallingUid The uid from {@link ActivityStarter#setRealCallingUid} 3074 * @return The root task to use for the launch. 3075 */ getOrCreateRootTask(@ullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable Task candidateTask, @Nullable Task sourceTask, boolean onTop, @Nullable LaunchParamsController.LaunchParams launchParams, int launchFlags)3076 Task getOrCreateRootTask(@Nullable ActivityRecord r, 3077 @Nullable ActivityOptions options, @Nullable Task candidateTask, 3078 @Nullable Task sourceTask, boolean onTop, 3079 @Nullable LaunchParamsController.LaunchParams launchParams, int launchFlags) { 3080 // First preference goes to the launch root task set in the activity options. 3081 if (options != null) { 3082 final Task candidateRoot = Task.fromWindowContainerToken(options.getLaunchRootTask()); 3083 if (candidateRoot != null && canLaunchOnDisplay(r, candidateRoot)) { 3084 return candidateRoot; 3085 } 3086 } 3087 3088 // Next preference goes to the task id set in the activity options. 3089 if (options != null) { 3090 final int candidateTaskId = options.getLaunchTaskId(); 3091 if (candidateTaskId != INVALID_TASK_ID) { 3092 // Temporarily set the task id to invalid in case in re-entry. 3093 options.setLaunchTaskId(INVALID_TASK_ID); 3094 final Task task = anyTaskForId(candidateTaskId, 3095 MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE, options, onTop); 3096 options.setLaunchTaskId(candidateTaskId); 3097 if (canLaunchOnDisplay(r, task)) { 3098 return task.getRootTask(); 3099 } 3100 } 3101 } 3102 3103 // Next preference goes to the TaskDisplayArea candidate from launchParams 3104 // or activity options. 3105 TaskDisplayArea taskDisplayArea = null; 3106 if (launchParams != null && launchParams.mPreferredTaskDisplayArea != null) { 3107 taskDisplayArea = launchParams.mPreferredTaskDisplayArea; 3108 } else if (options != null) { 3109 final WindowContainerToken daToken = options.getLaunchTaskDisplayArea(); 3110 taskDisplayArea = daToken != null 3111 ? (TaskDisplayArea) WindowContainer.fromBinder(daToken.asBinder()) : null; 3112 if (taskDisplayArea == null) { 3113 final int launchDisplayId = options.getLaunchDisplayId(); 3114 if (launchDisplayId != INVALID_DISPLAY) { 3115 final DisplayContent displayContent = getDisplayContent(launchDisplayId); 3116 if (displayContent != null) { 3117 taskDisplayArea = displayContent.getDefaultTaskDisplayArea(); 3118 } 3119 } 3120 } 3121 } 3122 3123 final int activityType = resolveActivityType(r, options, candidateTask); 3124 if (taskDisplayArea != null) { 3125 if (canLaunchOnDisplay(r, taskDisplayArea.getDisplayId())) { 3126 return taskDisplayArea.getOrCreateRootTask(r, options, candidateTask, 3127 sourceTask, launchParams, launchFlags, activityType, onTop); 3128 } else { 3129 taskDisplayArea = null; 3130 } 3131 } 3132 3133 // Give preference to the root task and display of the input task and activity if they 3134 // match the mode we want to launch into. 3135 Task rootTask = null; 3136 if (candidateTask != null) { 3137 rootTask = candidateTask.getRootTask(); 3138 } 3139 if (rootTask == null && r != null) { 3140 rootTask = r.getRootTask(); 3141 } 3142 int windowingMode = launchParams != null ? launchParams.mWindowingMode 3143 : WindowConfiguration.WINDOWING_MODE_UNDEFINED; 3144 if (rootTask != null) { 3145 taskDisplayArea = rootTask.getDisplayArea(); 3146 if (taskDisplayArea != null 3147 && canLaunchOnDisplay(r, taskDisplayArea.mDisplayContent.mDisplayId)) { 3148 if (windowingMode == WindowConfiguration.WINDOWING_MODE_UNDEFINED) { 3149 windowingMode = taskDisplayArea.resolveWindowingMode(r, options, candidateTask); 3150 } 3151 // Always allow organized tasks that created by organizer since the activity type 3152 // of an organized task is decided by the activity type of its top child, which 3153 // could be incompatible with the given windowing mode and activity type. 3154 if (rootTask.isCompatible(windowingMode, activityType) 3155 || rootTask.mCreatedByOrganizer) { 3156 return rootTask; 3157 } 3158 } else { 3159 taskDisplayArea = null; 3160 } 3161 3162 } 3163 3164 // Falling back to default task container 3165 if (taskDisplayArea == null) { 3166 taskDisplayArea = getDefaultTaskDisplayArea(); 3167 } 3168 return taskDisplayArea.getOrCreateRootTask(r, options, candidateTask, sourceTask, 3169 launchParams, launchFlags, activityType, onTop); 3170 } 3171 canLaunchOnDisplay(ActivityRecord r, Task task)3172 private boolean canLaunchOnDisplay(ActivityRecord r, Task task) { 3173 if (task == null) { 3174 Slog.w(TAG, "canLaunchOnDisplay(), invalid task: " + task); 3175 return false; 3176 } 3177 3178 if (!task.isAttached()) { 3179 Slog.w(TAG, "canLaunchOnDisplay(), Task is not attached: " + task); 3180 return false; 3181 } 3182 3183 return canLaunchOnDisplay(r, task.getTaskDisplayArea().getDisplayId()); 3184 } 3185 3186 /** @return true if activity record is null or can be launched on provided display. */ canLaunchOnDisplay(ActivityRecord r, int displayId)3187 private boolean canLaunchOnDisplay(ActivityRecord r, int displayId) { 3188 if (r == null) { 3189 return true; 3190 } 3191 if (!r.canBeLaunchedOnDisplay(displayId)) { 3192 Slog.w(TAG, "Not allow to launch " + r + " on display " + displayId); 3193 return false; 3194 } 3195 return true; 3196 } 3197 resolveActivityType(@ullable ActivityRecord r, @Nullable ActivityOptions options, @Nullable Task task)3198 int resolveActivityType(@Nullable ActivityRecord r, @Nullable ActivityOptions options, 3199 @Nullable Task task) { 3200 // Preference is given to the activity type for the activity then the task since the type 3201 // once set shouldn't change. 3202 int activityType = r != null ? r.getActivityType() : ACTIVITY_TYPE_UNDEFINED; 3203 if (activityType == ACTIVITY_TYPE_UNDEFINED && task != null) { 3204 activityType = task.getActivityType(); 3205 } 3206 if (activityType != ACTIVITY_TYPE_UNDEFINED) { 3207 return activityType; 3208 } 3209 if (options != null) { 3210 activityType = options.getLaunchActivityType(); 3211 } 3212 return activityType != ACTIVITY_TYPE_UNDEFINED ? activityType : ACTIVITY_TYPE_STANDARD; 3213 } 3214 3215 /** 3216 * Get next focusable root task in the system. This will search through the root task on the 3217 * same display as the current focused root task, looking for a focusable and visible root task, 3218 * different from the target root task. If no valid candidates will be found, it will then go 3219 * through all displays and root tasks in last-focused order. 3220 * 3221 * @param currentFocus The root task that previously had focus. 3222 * @param ignoreCurrent If we should ignore {@param currentFocus} when searching for next 3223 * candidate. 3224 * @return Next focusable {@link Task}, {@code null} if not found. 3225 */ getNextFocusableRootTask(@onNull Task currentFocus, boolean ignoreCurrent)3226 Task getNextFocusableRootTask(@NonNull Task currentFocus, boolean ignoreCurrent) { 3227 // First look for next focusable root task on the same display 3228 TaskDisplayArea preferredDisplayArea = currentFocus.getDisplayArea(); 3229 if (preferredDisplayArea == null) { 3230 // Root task is currently detached because it is being removed. Use the previous 3231 // display it was on. 3232 preferredDisplayArea = getDisplayContent(currentFocus.mPrevDisplayId) 3233 .getDefaultTaskDisplayArea(); 3234 } 3235 final Task preferredFocusableRootTask = preferredDisplayArea.getNextFocusableRootTask( 3236 currentFocus, ignoreCurrent); 3237 if (preferredFocusableRootTask != null) { 3238 return preferredFocusableRootTask; 3239 } 3240 3241 if (preferredDisplayArea.mDisplayContent.isHomeSupported()) { 3242 // Stop looking for focusable root task on other displays because the preferred display 3243 // supports home. Home activity would be launched on the same display if no focusable 3244 // root task found. 3245 return null; 3246 } 3247 3248 // Now look through all displays 3249 for (int i = getChildCount() - 1; i >= 0; --i) { 3250 final DisplayContent display = getChildAt(i); 3251 if (display == preferredDisplayArea.mDisplayContent) { 3252 // We've already checked this one 3253 continue; 3254 } 3255 final Task nextFocusableRootTask = display.getDefaultTaskDisplayArea() 3256 .getNextFocusableRootTask(currentFocus, ignoreCurrent); 3257 if (nextFocusableRootTask != null) { 3258 return nextFocusableRootTask; 3259 } 3260 } 3261 3262 return null; 3263 } 3264 closeSystemDialogActivities(String reason)3265 void closeSystemDialogActivities(String reason) { 3266 forAllActivities((r) -> { 3267 if ((r.info.flags & ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0 3268 || shouldCloseAssistant(r, reason)) { 3269 r.finishIfPossible(reason, true /* oomAdj */); 3270 } 3271 }); 3272 } 3273 3274 /** 3275 * Returns {@code true} if {@code uid} has a visible window that's above the window of type 3276 * {@link WindowManager.LayoutParams#TYPE_NOTIFICATION_SHADE} and {@code uid} is not owner of 3277 * the window of type {@link WindowManager.LayoutParams#TYPE_NOTIFICATION_SHADE}. 3278 * 3279 * If there is no window with type {@link WindowManager.LayoutParams#TYPE_NOTIFICATION_SHADE}, 3280 * it returns {@code false}. 3281 */ hasVisibleWindowAboveButDoesNotOwnNotificationShade(int uid)3282 boolean hasVisibleWindowAboveButDoesNotOwnNotificationShade(int uid) { 3283 boolean[] visibleWindowFound = {false}; 3284 // We only return true if we found the notification shade (ie. window of type 3285 // TYPE_NOTIFICATION_SHADE). Usually, it should always be there, but if for some reason 3286 // it isn't, we should better be on the safe side and return false for this. 3287 return forAllWindows(w -> { 3288 if (w.mOwnerUid == uid && w.isVisible()) { 3289 visibleWindowFound[0] = true; 3290 } 3291 if (w.mAttrs.type == TYPE_NOTIFICATION_SHADE) { 3292 return visibleWindowFound[0] && w.mOwnerUid != uid; 3293 } 3294 return false; 3295 }, true /* traverseTopToBottom */); 3296 } 3297 3298 private boolean shouldCloseAssistant(ActivityRecord r, String reason) { 3299 if (!r.isActivityTypeAssistant()) return false; 3300 if (reason == SYSTEM_DIALOG_REASON_ASSIST) return false; 3301 // When the assistant is configured to be on top of the dream, it will have higher z-order 3302 // than other activities. If it is also opaque, it will prevent other activities from 3303 // starting. We want to close the assistant on closeSystemDialogs to allow other activities 3304 // to start, e.g. on home button press. 3305 return mWmService.mAssistantOnTopOfDream; 3306 } 3307 3308 FinishDisabledPackageActivitiesHelper mFinishDisabledPackageActivitiesHelper = 3309 new FinishDisabledPackageActivitiesHelper(); 3310 3311 class FinishDisabledPackageActivitiesHelper implements Predicate<ActivityRecord> { 3312 private String mPackageName; 3313 private Set<String> mFilterByClasses; 3314 private boolean mDoit; 3315 private boolean mEvenPersistent; 3316 private int mUserId; 3317 private boolean mOnlyRemoveNoProcess; 3318 private Task mLastTask; 3319 private final ArrayList<ActivityRecord> mCollectedActivities = new ArrayList<>(); 3320 3321 private void reset(String packageName, Set<String> filterByClasses, 3322 boolean doit, boolean evenPersistent, int userId, boolean onlyRemoveNoProcess) { 3323 mPackageName = packageName; 3324 mFilterByClasses = filterByClasses; 3325 mDoit = doit; 3326 mEvenPersistent = evenPersistent; 3327 mUserId = userId; 3328 mOnlyRemoveNoProcess = onlyRemoveNoProcess; 3329 mLastTask = null; 3330 } 3331 3332 boolean process(String packageName, Set<String> filterByClasses, 3333 boolean doit, boolean evenPersistent, int userId, boolean onlyRemoveNoProcess) { 3334 reset(packageName, filterByClasses, doit, evenPersistent, userId, onlyRemoveNoProcess); 3335 forAllActivities(this); 3336 3337 boolean didSomething = false; 3338 final int size = mCollectedActivities.size(); 3339 // Keep the finishing order from top to bottom. 3340 for (int i = 0; i < size; i++) { 3341 final ActivityRecord r = mCollectedActivities.get(i); 3342 if (mOnlyRemoveNoProcess) { 3343 if (!r.hasProcess()) { 3344 didSomething = true; 3345 Slog.i(TAG, " Force removing " + r); 3346 r.cleanUp(false /* cleanServices */, false /* setState */); 3347 r.removeFromHistory("force-stop"); 3348 } 3349 } else { 3350 didSomething = true; 3351 Slog.i(TAG, " Force finishing " + r); 3352 r.finishIfPossible("force-stop", true /* oomAdj */); 3353 } 3354 } 3355 mCollectedActivities.clear(); 3356 3357 return didSomething; 3358 } 3359 3360 @Override 3361 public boolean test(ActivityRecord r) { 3362 final boolean sameComponent = 3363 (r.packageName.equals(mPackageName) && (mFilterByClasses == null 3364 || mFilterByClasses.contains(r.mActivityComponent.getClassName()))) 3365 || (mPackageName == null && r.mUserId == mUserId); 3366 final boolean noProcess = !r.hasProcess(); 3367 if ((mUserId == UserHandle.USER_ALL || r.mUserId == mUserId) 3368 && (sameComponent || r.getTask() == mLastTask) 3369 && (noProcess || mEvenPersistent || !r.app.isPersistent())) { 3370 if (!mDoit) { 3371 if (r.finishing) { 3372 // If this activity is just finishing, then it is not 3373 // interesting as far as something to stop. 3374 return false; 3375 } 3376 return true; 3377 } 3378 mCollectedActivities.add(r); 3379 mLastTask = r.getTask(); 3380 } 3381 3382 return false; 3383 } 3384 } 3385 3386 /** @return true if some activity was finished (or would have finished if doit were true). */ 3387 boolean finishDisabledPackageActivities(String packageName, Set<String> filterByClasses, 3388 boolean doit, boolean evenPersistent, int userId, boolean onlyRemoveNoProcess) { 3389 return mFinishDisabledPackageActivitiesHelper.process(packageName, filterByClasses, doit, 3390 evenPersistent, userId, onlyRemoveNoProcess); 3391 } 3392 3393 void updateActivityApplicationInfo(ApplicationInfo aInfo) { 3394 final String packageName = aInfo.packageName; 3395 final int userId = UserHandle.getUserId(aInfo.uid); 3396 forAllActivities(r -> { 3397 if (r.mUserId == userId && packageName.equals(r.packageName)) { 3398 r.updateApplicationInfo(aInfo); 3399 } 3400 }); 3401 } 3402 3403 void updateActivityApplicationInfo(int userId, 3404 ArrayMap<String, ApplicationInfo> applicationInfoByPackage) { 3405 forAllActivities(r -> { 3406 if (r.mUserId != userId) { 3407 return; 3408 } 3409 3410 final ApplicationInfo aInfo = applicationInfoByPackage.get(r.packageName); 3411 if (aInfo != null) { 3412 r.updateApplicationInfo(aInfo); 3413 } 3414 }); 3415 } 3416 3417 void finishVoiceTask(IVoiceInteractionSession session) { 3418 final IBinder binder = session.asBinder(); 3419 forAllLeafTasks(t -> t.finishIfVoiceTask(binder), true /* traverseTopToBottom */); 3420 } 3421 3422 /** 3423 * Removes root tasks in the input windowing modes from the system if they are of activity type 3424 * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED 3425 */ 3426 void removeRootTasksInWindowingModes(int... windowingModes) { 3427 for (int i = getChildCount() - 1; i >= 0; --i) { 3428 getChildAt(i).removeRootTasksInWindowingModes(windowingModes); 3429 } 3430 } 3431 3432 void removeRootTasksWithActivityTypes(int... activityTypes) { 3433 for (int i = getChildCount() - 1; i >= 0; --i) { 3434 getChildAt(i).removeRootTasksWithActivityTypes(activityTypes); 3435 } 3436 } 3437 3438 ActivityRecord topRunningActivity() { 3439 for (int i = getChildCount() - 1; i >= 0; --i) { 3440 final ActivityRecord topActivity = getChildAt(i).topRunningActivity(); 3441 if (topActivity != null) { 3442 return topActivity; 3443 } 3444 } 3445 return null; 3446 } 3447 3448 /** Returns the top direct activity if it should be idle but has not yet been reported. */ 3449 @Nullable 3450 private static ActivityRecord getNotYetIdleActivity(@NonNull TaskFragment visibleTf) { 3451 for (int i = visibleTf.getChildCount() - 1; i >= 0; i--) { 3452 final ActivityRecord r = visibleTf.getChildAt(i).asActivityRecord(); 3453 if (r == null || r.finishing) { 3454 continue; 3455 } 3456 if (!r.idle && (r.isState(RESUMED) 3457 // Its process is not attached yet and it may resume later. 3458 || (r.app == null && r.isFocusable()))) { 3459 return r; 3460 } 3461 // Only check the top running activity. 3462 break; 3463 } 3464 return null; 3465 } 3466 3467 boolean allResumedActivitiesIdle() { 3468 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { 3469 final DisplayContent display = getChildAt(displayNdx); 3470 if (display.isSleeping()) { 3471 // No resumed activities while display is sleeping. 3472 continue; 3473 } 3474 3475 final boolean foundNotIdle = display.forAllLeafTasks(task -> { 3476 if (!task.isVisibleRequested()) { 3477 return false; 3478 } 3479 final ActivityRecord notIdle = getNotYetIdleActivity(task); 3480 if (notIdle != null) { 3481 ProtoLog.d(WM_DEBUG_STATES, "allResumedActivitiesIdle: %s not idle", notIdle); 3482 return true; 3483 } 3484 if (task.isLeafTaskFragment()) { 3485 // The task doesn't contain child TaskFragment. 3486 return false; 3487 } 3488 return task.forAllLeafTaskFragments(tf -> { 3489 if (!tf.isVisibleRequested()) { 3490 return false; 3491 } 3492 final ActivityRecord tfNotIdle = getNotYetIdleActivity(tf); 3493 if (tfNotIdle != null) { 3494 ProtoLog.d(WM_DEBUG_STATES, "allResumedActivitiesIdle: %s not idle", 3495 tfNotIdle); 3496 return true; 3497 } 3498 return false; 3499 }); 3500 }); 3501 if (foundNotIdle) { 3502 return false; 3503 } 3504 if (mTransitionController.hasTransientLaunch(display)) { 3505 // Not idle if the transient transition animation is running. 3506 return false; 3507 } 3508 } 3509 // End power mode launch when idle. 3510 mService.endPowerMode(ActivityTaskManagerService.POWER_MODE_REASON_START_ACTIVITY); 3511 return true; 3512 } 3513 3514 boolean allResumedActivitiesVisible() { 3515 boolean[] foundResumed = {false}; 3516 final boolean foundInvisibleResumedActivity = forAllRootTasks(rootTask -> { 3517 final ActivityRecord r = rootTask.getTopResumedActivity(); 3518 if (r != null) { 3519 if (!r.nowVisible) { 3520 return true; 3521 } 3522 foundResumed[0] = true; 3523 } 3524 return false; 3525 }); 3526 if (foundInvisibleResumedActivity) { 3527 return false; 3528 } 3529 return foundResumed[0]; 3530 } 3531 3532 boolean allPausedActivitiesComplete() { 3533 boolean[] pausing = {true}; 3534 final boolean hasActivityNotCompleted = forAllLeafTasks(task -> { 3535 final ActivityRecord r = task.getTopPausingActivity(); 3536 if (r != null && !r.isState(PAUSED, STOPPED, STOPPING, FINISHING)) { 3537 ProtoLog.d(WM_DEBUG_STATES, "allPausedActivitiesComplete: " 3538 + "r=%s state=%s", r, r.getState()); 3539 if (WM_DEBUG_STATES.isEnabled()) { 3540 pausing[0] = false; 3541 } else { 3542 return true; 3543 } 3544 } 3545 return false; 3546 }); 3547 if (hasActivityNotCompleted) { 3548 return false; 3549 } 3550 return pausing[0]; 3551 } 3552 3553 /** 3554 * Find all tasks containing {@param userId} and intercept them with an activity 3555 * to block out the contents and possibly start a credential-confirming intent. 3556 * 3557 * @param userId user handle for the locked managed profile. 3558 */ 3559 void lockAllProfileTasks(@UserIdInt int userId) { 3560 forAllLeafTasks(task -> { 3561 final ActivityRecord top = task.topRunningActivity(); 3562 if (top != null && !top.finishing 3563 && ACTION_CONFIRM_DEVICE_CREDENTIAL_WITH_USER.equals(top.intent.getAction()) 3564 && top.packageName.equals( 3565 mService.getSysUiServiceComponentLocked().getPackageName())) { 3566 // Do nothing since the task is already secure by sysui. 3567 return; 3568 } 3569 3570 if (task.getActivity(activity -> !activity.finishing && activity.mUserId == userId) 3571 != null) { 3572 mService.getTaskChangeNotificationController().notifyTaskProfileLocked( 3573 task.getTaskInfo(), userId); 3574 } 3575 }, true /* traverseTopToBottom */); 3576 } 3577 3578 Task anyTaskForId(int id) { 3579 return anyTaskForId(id, MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE); 3580 } 3581 3582 Task anyTaskForId(int id, @RootWindowContainer.AnyTaskForIdMatchTaskMode int matchMode) { 3583 return anyTaskForId(id, matchMode, null, !ON_TOP); 3584 } 3585 3586 /** 3587 * Returns a {@link Task} for the input id if available. {@code null} otherwise. 3588 * 3589 * @param id Id of the task we would like returned. 3590 * @param matchMode The mode to match the given task id in. 3591 * @param aOptions The activity options to use for restoration. Can be null. 3592 * @param onTop If the root task for the task should be the topmost on the display. 3593 */ 3594 Task anyTaskForId(int id, @RootWindowContainer.AnyTaskForIdMatchTaskMode int matchMode, 3595 @Nullable ActivityOptions aOptions, boolean onTop) { 3596 // If options are set, ensure that we are attempting to actually restore a task 3597 if (matchMode != MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE && aOptions != null) { 3598 throw new IllegalArgumentException("Should not specify activity options for non-restore" 3599 + " lookup"); 3600 } 3601 3602 final PooledPredicate p = PooledLambda.obtainPredicate( 3603 Task::isTaskId, PooledLambda.__(Task.class), id); 3604 Task task = getTask(p); 3605 p.recycle(); 3606 3607 if (task != null) { 3608 if (aOptions != null) { 3609 // Resolve the root task the task should be placed in now based on options 3610 // and reparent if needed. 3611 // TODO(b/229927851) For split-screen, setLaunchRootTask is no longer the "root" 3612 // task, consider to rename methods like "parentTask" instead of "rootTask". 3613 final Task targetRootTask = 3614 getOrCreateRootTask(null, aOptions, task, onTop); 3615 // When launch with ActivityOptions#getLaunchRootTask, the "root task" just mean the 3616 // parent of current launch, not the "root task" in hierarchy. 3617 if (targetRootTask != null && task.getRootTask() != targetRootTask 3618 && task.getParent() != targetRootTask) { 3619 final int reparentMode = onTop 3620 ? REPARENT_MOVE_ROOT_TASK_TO_FRONT : REPARENT_LEAVE_ROOT_TASK_IN_PLACE; 3621 task.reparent(targetRootTask, onTop, reparentMode, ANIMATE, DEFER_RESUME, 3622 "anyTaskForId"); 3623 } 3624 } 3625 return task; 3626 } 3627 3628 // If we are matching root task tasks only, return now 3629 if (matchMode == MATCH_ATTACHED_TASK_ONLY) { 3630 return null; 3631 } 3632 3633 // Otherwise, check the recent tasks and return if we find it there and we are not restoring 3634 // the task from recents 3635 if (DEBUG_RECENTS) Slog.v(TAG_RECENTS, "Looking for task id=" + id + " in recents"); 3636 task = mTaskSupervisor.mRecentTasks.getTask(id); 3637 3638 if (task == null) { 3639 if (DEBUG_RECENTS) { 3640 Slog.d(TAG_RECENTS, "\tDidn't find task id=" + id + " in recents"); 3641 } 3642 3643 return null; 3644 } 3645 3646 if (matchMode == MATCH_ATTACHED_TASK_OR_RECENT_TASKS) { 3647 return task; 3648 } 3649 3650 // Implicitly, this case is MATCH_ATTACHED_TASK_OR_RECENT_TASKS_AND_RESTORE 3651 if (!mTaskSupervisor.restoreRecentTaskLocked(task, aOptions, onTop)) { 3652 if (DEBUG_RECENTS) { 3653 Slog.w(TAG_RECENTS, 3654 "Couldn't restore task id=" + id + " found in recents"); 3655 } 3656 return null; 3657 } 3658 if (DEBUG_RECENTS) Slog.w(TAG_RECENTS, "Restored task id=" + id + " from in recents"); 3659 return task; 3660 } 3661 3662 @VisibleForTesting 3663 void getRunningTasks(int maxNum, List<ActivityManager.RunningTaskInfo> list, 3664 int flags, int callingUid, ArraySet<Integer> profileIds, int displayId) { 3665 WindowContainer root = this; 3666 if (displayId != INVALID_DISPLAY) { 3667 root = getDisplayContent(displayId); 3668 if (root == null) { 3669 return; 3670 } 3671 } 3672 mTaskSupervisor.getRunningTasks().getTasks(maxNum, list, flags, mService.getRecentTasks(), 3673 root, callingUid, profileIds); 3674 } 3675 3676 void startPowerModeLaunchIfNeeded(boolean forceSend, ActivityRecord targetActivity) { 3677 if (!forceSend && targetActivity != null && targetActivity.app != null) { 3678 // Set power mode when the activity's process is different than the current top resumed 3679 // activity on all display areas, or if there are no resumed activities in the system. 3680 boolean[] noResumedActivities = {true}; 3681 boolean[] allFocusedProcessesDiffer = {true}; 3682 forAllTaskDisplayAreas(taskDisplayArea -> { 3683 final ActivityRecord resumedActivity = taskDisplayArea.getFocusedActivity(); 3684 final WindowProcessController resumedActivityProcess = 3685 resumedActivity == null ? null : resumedActivity.app; 3686 3687 noResumedActivities[0] &= resumedActivityProcess == null; 3688 if (resumedActivityProcess != null) { 3689 allFocusedProcessesDiffer[0] &= 3690 !resumedActivityProcess.equals(targetActivity.app); 3691 } 3692 }); 3693 if (!noResumedActivities[0] && !allFocusedProcessesDiffer[0]) { 3694 // All focused activities are resumed and the process of the target activity is 3695 // the same as them, e.g. delivering new intent to the current top. 3696 return; 3697 } 3698 } 3699 3700 int reason = ActivityTaskManagerService.POWER_MODE_REASON_START_ACTIVITY; 3701 // If the activity is launching while keyguard is locked (including occluded), the activity 3702 // may be visible until its first relayout is done (e.g. apply show-when-lock flag). To 3703 // avoid power mode from being cleared before that, add a special reason to consider whether 3704 // the unknown visibility is resolved. The case from SystemUI is excluded because it should 3705 // rely on keyguard-going-away. 3706 final boolean isKeyguardLocked = (targetActivity != null) 3707 ? targetActivity.isKeyguardLocked() : mDefaultDisplay.isKeyguardLocked(); 3708 if (isKeyguardLocked && targetActivity != null 3709 && !targetActivity.isLaunchSourceType(ActivityRecord.LAUNCH_SOURCE_TYPE_SYSTEMUI)) { 3710 final ActivityOptions opts = targetActivity.getOptions(); 3711 if (opts == null || opts.getSourceInfo() == null 3712 || opts.getSourceInfo().type != ActivityOptions.SourceInfo.TYPE_LOCKSCREEN) { 3713 reason |= ActivityTaskManagerService.POWER_MODE_REASON_UNKNOWN_VISIBILITY; 3714 } 3715 } 3716 mService.startPowerMode(reason); 3717 } 3718 3719 /** 3720 * Iterate over all task fragments, to see if there exists one that meets the 3721 * PermissionPolicyService's criteria to show a permission dialog. 3722 */ 3723 public int getTaskToShowPermissionDialogOn(String pkgName, int uid) { 3724 PermissionPolicyInternal pPi = mService.getPermissionPolicyInternal(); 3725 if (pPi == null) { 3726 return INVALID_TASK_ID; 3727 } 3728 3729 final int[] validTaskId = {INVALID_TASK_ID}; 3730 forAllLeafTaskFragments(fragment -> { 3731 ActivityRecord record = fragment.getActivity((r) -> { 3732 // skip hidden (or about to hide) apps, or the permission dialog 3733 return r.canBeTopRunning() && r.isVisibleRequested() 3734 && !pPi.isIntentToPermissionDialog(r.intent); 3735 }); 3736 if (record != null && record.isUid(uid) 3737 && Objects.equals(pkgName, record.packageName) 3738 && pPi.shouldShowNotificationDialogForTask(record.getTask().getTaskInfo(), 3739 pkgName, record.launchedFromPackage, record.intent, record.getName())) { 3740 validTaskId[0] = record.getTask().mTaskId; 3741 return true; 3742 } 3743 return false; 3744 }); 3745 3746 return validTaskId[0]; 3747 } 3748 3749 /** 3750 * Dumps the activities matching the given {@param name} in the either the focused root task 3751 * or all visible root tasks if {@param dumpVisibleRootTasksOnly} is true. 3752 */ 3753 ArrayList<ActivityRecord> getDumpActivities(String name, boolean dumpVisibleRootTasksOnly, 3754 boolean dumpFocusedRootTaskOnly, @UserIdInt int userId) { 3755 if (dumpFocusedRootTaskOnly) { 3756 final Task topFocusedRootTask = getTopDisplayFocusedRootTask(); 3757 if (topFocusedRootTask != null) { 3758 return topFocusedRootTask.getDumpActivitiesLocked(name, userId); 3759 } else { 3760 return new ArrayList<>(); 3761 } 3762 } else { 3763 final RecentTasks recentTasks = mWindowManager.mAtmService.getRecentTasks(); 3764 final int recentsComponentUid = recentTasks != null 3765 ? recentTasks.getRecentsComponentUid() 3766 : -1; 3767 final ArrayList<ActivityRecord> activities = new ArrayList<>(); 3768 forAllLeafTasks(task -> { 3769 final boolean isRecents = (task.effectiveUid == recentsComponentUid); 3770 if (!dumpVisibleRootTasksOnly || task.shouldBeVisible(null) || isRecents) { 3771 activities.addAll(task.getDumpActivitiesLocked(name, userId)); 3772 } 3773 return false; 3774 }); 3775 return activities; 3776 } 3777 } 3778 3779 @Override 3780 public void dump(PrintWriter pw, String prefix, boolean dumpAll) { 3781 super.dump(pw, prefix, dumpAll); 3782 pw.print(prefix); 3783 pw.println("topDisplayFocusedRootTask=" + getTopDisplayFocusedRootTask()); 3784 for (int i = getChildCount() - 1; i >= 0; --i) { 3785 final DisplayContent display = getChildAt(i); 3786 display.dump(pw, prefix, dumpAll); 3787 } 3788 } 3789 3790 /** 3791 * Dump all connected displays' configurations. 3792 * 3793 * @param prefix Prefix to apply to each line of the dump. 3794 */ 3795 void dumpDisplayConfigs(PrintWriter pw, String prefix) { 3796 pw.print(prefix); 3797 pw.println("Display override configurations:"); 3798 final int displayCount = getChildCount(); 3799 for (int i = 0; i < displayCount; i++) { 3800 final DisplayContent displayContent = getChildAt(i); 3801 pw.print(prefix); 3802 pw.print(" "); 3803 pw.print(displayContent.mDisplayId); 3804 pw.print(": "); 3805 pw.println(displayContent.getRequestedOverrideConfiguration()); 3806 } 3807 } 3808 3809 boolean dumpActivities(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient, 3810 String dumpPackage, int displayIdFilter) { 3811 boolean[] printed = {false}; 3812 boolean[] needSep = {false}; 3813 for (int displayNdx = getChildCount() - 1; displayNdx >= 0; --displayNdx) { 3814 DisplayContent displayContent = getChildAt(displayNdx); 3815 if (printed[0]) { 3816 pw.println(); 3817 } 3818 if (displayIdFilter != Display.INVALID_DISPLAY 3819 && displayContent.mDisplayId != displayIdFilter) { 3820 continue; 3821 } 3822 pw.print("Display #"); 3823 pw.print(displayContent.mDisplayId); 3824 pw.println(" (activities from top to bottom):"); 3825 displayContent.forAllRootTasks(rootTask -> { 3826 if (needSep[0]) { 3827 pw.println(); 3828 } 3829 needSep[0] = rootTask.dump(fd, pw, dumpAll, dumpClient, dumpPackage, false); 3830 printed[0] |= needSep[0]; 3831 }); 3832 displayContent.forAllTaskDisplayAreas(taskDisplayArea -> { 3833 printed[0] |= printThisActivity(pw, taskDisplayArea.getFocusedActivity(), 3834 dumpPackage, needSep[0], " Resumed: ", () -> 3835 pw.println(" Resumed activities in task display areas" 3836 + " (from top to bottom):")); 3837 }); 3838 } 3839 3840 printed[0] |= dumpHistoryList(fd, pw, mTaskSupervisor.mFinishingActivities, " ", 3841 "Fin", false, !dumpAll, 3842 false, dumpPackage, true, 3843 () -> pw.println(" Activities waiting to finish:"), null); 3844 printed[0] |= dumpHistoryList(fd, pw, mTaskSupervisor.mStoppingActivities, " ", 3845 "Stop", false, !dumpAll, 3846 false, dumpPackage, true, 3847 () -> pw.println(" Activities waiting to stop:"), null); 3848 3849 return printed[0]; 3850 } 3851 3852 private static int makeSleepTokenKey(String tag, int displayId) { 3853 final String tokenKey = tag + displayId; 3854 return tokenKey.hashCode(); 3855 } 3856 3857 static final class SleepToken { 3858 private final String mTag; 3859 private final long mAcquireTime; 3860 private final int mDisplayId; 3861 final int mHashKey; 3862 3863 SleepToken(String tag, int displayId) { 3864 mTag = tag; 3865 mDisplayId = displayId; 3866 mAcquireTime = SystemClock.uptimeMillis(); 3867 mHashKey = makeSleepTokenKey(mTag, mDisplayId); 3868 } 3869 3870 @Override 3871 public String toString() { 3872 return "{\"" + mTag + "\", display " + mDisplayId 3873 + ", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}"; 3874 } 3875 3876 void writeTagToProto(ProtoOutputStream proto, long fieldId) { 3877 proto.write(fieldId, mTag); 3878 } 3879 } 3880 3881 private class RankTaskLayersRunnable implements Runnable { 3882 boolean mCheckUpdateOomAdj; 3883 3884 @Override 3885 public void run() { 3886 synchronized (mService.mGlobalLock) { 3887 if (mTaskLayersChanged) { 3888 mTaskLayersChanged = false; 3889 rankTaskLayers(); 3890 } 3891 } 3892 } 3893 } 3894 } 3895