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