1 /* 2 * Copyright (C) 2010 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.ITaskStackListener.FORCED_RESIZEABLE_REASON_SPLIT_SCREEN; 20 import static android.app.WindowConfiguration.ACTIVITY_TYPE_ASSISTANT; 21 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME; 22 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS; 23 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD; 24 import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED; 25 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; 26 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; 27 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED; 28 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY; 29 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; 30 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED; 31 import static android.app.WindowConfiguration.activityTypeToString; 32 import static android.app.WindowConfiguration.windowingModeToString; 33 import static android.content.pm.ActivityInfo.CONFIG_SCREEN_LAYOUT; 34 import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING; 35 import static android.content.pm.ActivityInfo.FLAG_SHOW_FOR_ALL_USERS; 36 import static android.view.Display.DEFAULT_DISPLAY; 37 import static android.view.Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD; 38 import static android.view.Display.INVALID_DISPLAY; 39 import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE; 40 import static android.view.WindowManager.TRANSIT_ACTIVITY_OPEN; 41 import static android.view.WindowManager.TRANSIT_CRASHING_ACTIVITY_CLOSE; 42 import static android.view.WindowManager.TRANSIT_NONE; 43 import static android.view.WindowManager.TRANSIT_TASK_CLOSE; 44 import static android.view.WindowManager.TRANSIT_TASK_OPEN; 45 import static android.view.WindowManager.TRANSIT_TASK_OPEN_BEHIND; 46 import static android.view.WindowManager.TRANSIT_TASK_TO_BACK; 47 import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT; 48 49 import static com.android.server.am.ActivityStackProto.BOUNDS; 50 import static com.android.server.am.ActivityStackProto.CONFIGURATION_CONTAINER; 51 import static com.android.server.am.ActivityStackProto.DISPLAY_ID; 52 import static com.android.server.am.ActivityStackProto.FULLSCREEN; 53 import static com.android.server.am.ActivityStackProto.ID; 54 import static com.android.server.am.ActivityStackProto.RESUMED_ACTIVITY; 55 import static com.android.server.am.ActivityStackProto.TASKS; 56 import static com.android.server.wm.ActivityDisplay.POSITION_BOTTOM; 57 import static com.android.server.wm.ActivityDisplay.POSITION_TOP; 58 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYED; 59 import static com.android.server.wm.ActivityStack.ActivityState.DESTROYING; 60 import static com.android.server.wm.ActivityStack.ActivityState.FINISHING; 61 import static com.android.server.wm.ActivityStack.ActivityState.PAUSED; 62 import static com.android.server.wm.ActivityStack.ActivityState.PAUSING; 63 import static com.android.server.wm.ActivityStack.ActivityState.RESUMED; 64 import static com.android.server.wm.ActivityStack.ActivityState.STOPPED; 65 import static com.android.server.wm.ActivityStack.ActivityState.STOPPING; 66 import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY; 67 import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS; 68 import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS; 69 import static com.android.server.wm.ActivityStackSupervisor.dumpHistoryList; 70 import static com.android.server.wm.ActivityStackSupervisor.printThisActivity; 71 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE; 72 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL; 73 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_APP; 74 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP; 75 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CONTAINERS; 76 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_PAUSE; 77 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RELEASE; 78 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_RESULTS; 79 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SAVED_STATE; 80 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STACK; 81 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_STATES; 82 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH; 83 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TASKS; 84 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_TRANSITION; 85 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_USER_LEAVING; 86 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_VISIBILITY; 87 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_ADD_REMOVE; 88 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_APP; 89 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CLEANUP; 90 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONTAINERS; 91 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_PAUSE; 92 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RELEASE; 93 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_RESULTS; 94 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SAVED_STATE; 95 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STACK; 96 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_STATES; 97 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_SWITCH; 98 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TASKS; 99 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_TRANSITION; 100 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_USER_LEAVING; 101 import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_VISIBILITY; 102 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM; 103 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME; 104 import static com.android.server.wm.ActivityTaskManagerService.H.FIRST_ACTIVITY_STACK_MSG; 105 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_FREE_RESIZE; 106 import static com.android.server.wm.ActivityTaskManagerService.RELAUNCH_REASON_WINDOWING_MODE_RESIZE; 107 import static com.android.server.wm.RootActivityContainer.FindTaskResult; 108 109 import static java.lang.Integer.MAX_VALUE; 110 111 import android.annotation.IntDef; 112 import android.app.Activity; 113 import android.app.ActivityManager; 114 import android.app.ActivityManagerInternal; 115 import android.app.ActivityOptions; 116 import android.app.AppGlobals; 117 import android.app.IActivityController; 118 import android.app.RemoteAction; 119 import android.app.ResultInfo; 120 import android.app.WindowConfiguration.ActivityType; 121 import android.app.WindowConfiguration.WindowingMode; 122 import android.app.servertransaction.ActivityResultItem; 123 import android.app.servertransaction.ClientTransaction; 124 import android.app.servertransaction.DestroyActivityItem; 125 import android.app.servertransaction.NewIntentItem; 126 import android.app.servertransaction.PauseActivityItem; 127 import android.app.servertransaction.ResumeActivityItem; 128 import android.app.servertransaction.StopActivityItem; 129 import android.app.servertransaction.WindowVisibilityItem; 130 import android.content.ComponentName; 131 import android.content.Intent; 132 import android.content.pm.ActivityInfo; 133 import android.content.pm.ApplicationInfo; 134 import android.content.res.Configuration; 135 import android.graphics.Rect; 136 import android.net.Uri; 137 import android.os.Binder; 138 import android.os.Debug; 139 import android.os.Handler; 140 import android.os.IBinder; 141 import android.os.Looper; 142 import android.os.Message; 143 import android.os.RemoteException; 144 import android.os.SystemClock; 145 import android.os.UserHandle; 146 import android.service.voice.IVoiceInteractionSession; 147 import android.util.ArraySet; 148 import android.util.EventLog; 149 import android.util.IntArray; 150 import android.util.Log; 151 import android.util.Slog; 152 import android.util.proto.ProtoOutputStream; 153 import android.view.Display; 154 155 import com.android.internal.annotations.GuardedBy; 156 import com.android.internal.annotations.VisibleForTesting; 157 import com.android.internal.app.IVoiceInteractor; 158 import com.android.internal.util.function.pooled.PooledLambda; 159 import com.android.server.Watchdog; 160 import com.android.server.am.ActivityManagerService; 161 import com.android.server.am.ActivityManagerService.ItemMatcher; 162 import com.android.server.am.AppTimeTracker; 163 import com.android.server.am.EventLogTags; 164 import com.android.server.am.PendingIntentRecord; 165 166 import java.io.FileDescriptor; 167 import java.io.PrintWriter; 168 import java.lang.ref.WeakReference; 169 import java.util.ArrayList; 170 import java.util.List; 171 import java.util.Objects; 172 import java.util.Set; 173 174 /** 175 * State and management of a single stack of activities. 176 */ 177 class ActivityStack extends ConfigurationContainer { 178 private static final String TAG = TAG_WITH_CLASS_NAME ? "ActivityStack" : TAG_ATM; 179 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE; 180 private static final String TAG_APP = TAG + POSTFIX_APP; 181 private static final String TAG_CLEANUP = TAG + POSTFIX_CLEANUP; 182 private static final String TAG_CONTAINERS = TAG + POSTFIX_CONTAINERS; 183 private static final String TAG_PAUSE = TAG + POSTFIX_PAUSE; 184 private static final String TAG_RELEASE = TAG + POSTFIX_RELEASE; 185 private static final String TAG_RESULTS = TAG + POSTFIX_RESULTS; 186 private static final String TAG_SAVED_STATE = TAG + POSTFIX_SAVED_STATE; 187 private static final String TAG_STACK = TAG + POSTFIX_STACK; 188 private static final String TAG_STATES = TAG + POSTFIX_STATES; 189 private static final String TAG_SWITCH = TAG + POSTFIX_SWITCH; 190 private static final String TAG_TASKS = TAG + POSTFIX_TASKS; 191 private static final String TAG_TRANSITION = TAG + POSTFIX_TRANSITION; 192 private static final String TAG_USER_LEAVING = TAG + POSTFIX_USER_LEAVING; 193 private static final String TAG_VISIBILITY = TAG + POSTFIX_VISIBILITY; 194 195 // Ticks during which we check progress while waiting for an app to launch. 196 static final int LAUNCH_TICK = 500; 197 198 // How long we wait until giving up on the last activity to pause. This 199 // is short because it directly impacts the responsiveness of starting the 200 // next activity. 201 private static final int PAUSE_TIMEOUT = 500; 202 203 // How long we wait for the activity to tell us it has stopped before 204 // giving up. This is a good amount of time because we really need this 205 // from the application in order to get its saved state. Once the stop 206 // is complete we may start destroying client resources triggering 207 // crashes if the UI thread was hung. We put this timeout one second behind 208 // the ANR timeout so these situations will generate ANR instead of 209 // Surface lost or other errors. 210 private static final int STOP_TIMEOUT = 11 * 1000; 211 212 // How long we wait until giving up on an activity telling us it has 213 // finished destroying itself. 214 private static final int DESTROY_TIMEOUT = 10 * 1000; 215 216 // Set to false to disable the preview that is shown while a new activity 217 // is being started. 218 private static final boolean SHOW_APP_STARTING_PREVIEW = true; 219 220 // How long to wait for all background Activities to redraw following a call to 221 // convertToTranslucent(). 222 private static final long TRANSLUCENT_CONVERSION_TIMEOUT = 2000; 223 224 // How many activities have to be scheduled to stop to force a stop pass. 225 private static final int MAX_STOPPING_TO_FORCE = 3; 226 227 @IntDef(prefix = {"STACK_VISIBILITY"}, value = { 228 STACK_VISIBILITY_VISIBLE, 229 STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT, 230 STACK_VISIBILITY_INVISIBLE, 231 }) 232 @interface StackVisibility {} 233 234 /** Stack is visible. No other stacks on top that fully or partially occlude it. */ 235 static final int STACK_VISIBILITY_VISIBLE = 0; 236 237 /** Stack is partially occluded by other translucent stack(s) on top of it. */ 238 static final int STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT = 1; 239 240 /** Stack is completely invisible. */ 241 static final int STACK_VISIBILITY_INVISIBLE = 2; 242 243 @Override getChildCount()244 protected int getChildCount() { 245 return mTaskHistory.size(); 246 } 247 248 @Override getChildAt(int index)249 protected TaskRecord getChildAt(int index) { 250 return mTaskHistory.get(index); 251 } 252 253 @Override getParent()254 protected ActivityDisplay getParent() { 255 return getDisplay(); 256 } 257 setParent(ActivityDisplay parent)258 void setParent(ActivityDisplay parent) { 259 ActivityDisplay current = getParent(); 260 if (current != parent) { 261 mDisplayId = parent.mDisplayId; 262 onParentChanged(); 263 } 264 } 265 266 @Override onParentChanged()267 protected void onParentChanged() { 268 ActivityDisplay display = getParent(); 269 if (display != null) { 270 // Rotations are relative to the display. This means if there are 2 displays rotated 271 // differently (eg. 2 monitors with one landscape and one portrait), moving a stack 272 // from one to the other could look like a rotation change. To prevent this 273 // apparent rotation change (and corresponding bounds rotation), pretend like our 274 // current rotation is already the same as the new display. 275 // Note, if ActivityStack or related logic ever gets nested, this logic will need 276 // to move to onConfigurationChanged. 277 getConfiguration().windowConfiguration.setRotation( 278 display.getWindowConfiguration().getRotation()); 279 } 280 super.onParentChanged(); 281 if (display != null && inSplitScreenPrimaryWindowingMode()) { 282 // If we created a docked stack we want to resize it so it resizes all other stacks 283 // in the system. 284 getStackDockedModeBounds(null /* dockedBounds */, null /* currentTempTaskBounds */, 285 mTmpRect /* outStackBounds */, mTmpRect2 /* outTempTaskBounds */); 286 mStackSupervisor.resizeDockedStackLocked(getRequestedOverrideBounds(), mTmpRect, 287 mTmpRect2, null, null, PRESERVE_WINDOWS); 288 } 289 mRootActivityContainer.updateUIDsPresentOnDisplay(); 290 } 291 292 enum ActivityState { 293 INITIALIZING, 294 RESUMED, 295 PAUSING, 296 PAUSED, 297 STOPPING, 298 STOPPED, 299 FINISHING, 300 DESTROYING, 301 DESTROYED, 302 RESTARTING_PROCESS 303 } 304 305 @VisibleForTesting 306 /* The various modes for the method {@link #removeTask}. */ 307 // Task is being completely removed from all stacks in the system. 308 protected static final int REMOVE_TASK_MODE_DESTROYING = 0; 309 // Task is being removed from this stack so we can add it to another stack. In the case we are 310 // moving we don't want to perform some operations on the task like removing it from window 311 // manager or recents. 312 static final int REMOVE_TASK_MODE_MOVING = 1; 313 // Similar to {@link #REMOVE_TASK_MODE_MOVING} and the task will be added to the top of its new 314 // stack and the new stack will be on top of all stacks. 315 static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2; 316 317 final ActivityTaskManagerService mService; 318 final WindowManagerService mWindowManager; 319 320 /** 321 * The back history of all previous (and possibly still 322 * running) activities. It contains #TaskRecord objects. 323 */ 324 private final ArrayList<TaskRecord> mTaskHistory = new ArrayList<>(); 325 326 /** 327 * List of running activities, sorted by recent usage. 328 * The first entry in the list is the least recently used. 329 * It contains HistoryRecord objects. 330 */ 331 private final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<>(); 332 333 /** 334 * When we are in the process of pausing an activity, before starting the 335 * next one, this variable holds the activity that is currently being paused. 336 */ 337 ActivityRecord mPausingActivity = null; 338 339 /** 340 * This is the last activity that we put into the paused state. This is 341 * used to determine if we need to do an activity transition while sleeping, 342 * when we normally hold the top activity paused. 343 */ 344 ActivityRecord mLastPausedActivity = null; 345 346 /** 347 * Activities that specify No History must be removed once the user navigates away from them. 348 * If the device goes to sleep with such an activity in the paused state then we save it here 349 * and finish it later if another activity replaces it on wakeup. 350 */ 351 ActivityRecord mLastNoHistoryActivity = null; 352 353 /** 354 * Current activity that is resumed, or null if there is none. 355 */ 356 ActivityRecord mResumedActivity = null; 357 358 // The topmost Activity passed to convertToTranslucent(). When non-null it means we are 359 // waiting for all Activities in mUndrawnActivitiesBelowTopTranslucent to be removed as they 360 // are drawn. When the last member of mUndrawnActivitiesBelowTopTranslucent is removed the 361 // Activity in mTranslucentActivityWaiting is notified via 362 // Activity.onTranslucentConversionComplete(false). If a timeout occurs prior to the last 363 // background activity being drawn then the same call will be made with a true value. 364 ActivityRecord mTranslucentActivityWaiting = null; 365 ArrayList<ActivityRecord> mUndrawnActivitiesBelowTopTranslucent = new ArrayList<>(); 366 367 /** 368 * Set when we know we are going to be calling updateConfiguration() 369 * soon, so want to skip intermediate config checks. 370 */ 371 boolean mConfigWillChange; 372 373 /** 374 * When set, will force the stack to report as invisible. 375 */ 376 boolean mForceHidden = false; 377 378 /** 379 * Used to keep resumeTopActivityUncheckedLocked() from being entered recursively 380 */ 381 boolean mInResumeTopActivity = false; 382 383 private boolean mUpdateBoundsDeferred; 384 private boolean mUpdateBoundsDeferredCalled; 385 private boolean mUpdateDisplayedBoundsDeferredCalled; 386 private final Rect mDeferredBounds = new Rect(); 387 private final Rect mDeferredDisplayedBounds = new Rect(); 388 389 int mCurrentUser; 390 391 final int mStackId; 392 /** The attached Display's unique identifier, or -1 if detached */ 393 int mDisplayId; 394 395 /** Stores the override windowing-mode from before a transient mode change (eg. split) */ 396 private int mRestoreOverrideWindowingMode = WINDOWING_MODE_UNDEFINED; 397 398 private final Rect mTmpRect = new Rect(); 399 private final Rect mTmpRect2 = new Rect(); 400 private final ActivityOptions mTmpOptions = ActivityOptions.makeBasic(); 401 402 /** List for processing through a set of activities */ 403 private final ArrayList<ActivityRecord> mTmpActivities = new ArrayList<>(); 404 405 /** Run all ActivityStacks through this */ 406 protected final ActivityStackSupervisor mStackSupervisor; 407 protected final RootActivityContainer mRootActivityContainer; 408 409 private boolean mTopActivityOccludesKeyguard; 410 private ActivityRecord mTopDismissingKeyguardActivity; 411 412 static final int PAUSE_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 1; 413 static final int DESTROY_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 2; 414 static final int LAUNCH_TICK_MSG = FIRST_ACTIVITY_STACK_MSG + 3; 415 static final int STOP_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 4; 416 static final int DESTROY_ACTIVITIES_MSG = FIRST_ACTIVITY_STACK_MSG + 5; 417 static final int TRANSLUCENT_TIMEOUT_MSG = FIRST_ACTIVITY_STACK_MSG + 6; 418 419 // TODO: remove after unification. 420 TaskStack mTaskStack; 421 422 private static class ScheduleDestroyArgs { 423 final WindowProcessController mOwner; 424 final String mReason; ScheduleDestroyArgs(WindowProcessController owner, String reason)425 ScheduleDestroyArgs(WindowProcessController owner, String reason) { 426 mOwner = owner; 427 mReason = reason; 428 } 429 } 430 431 final Handler mHandler; 432 433 private class ActivityStackHandler extends Handler { 434 ActivityStackHandler(Looper looper)435 ActivityStackHandler(Looper looper) { 436 super(looper); 437 } 438 439 @Override handleMessage(Message msg)440 public void handleMessage(Message msg) { 441 switch (msg.what) { 442 case PAUSE_TIMEOUT_MSG: { 443 ActivityRecord r = (ActivityRecord)msg.obj; 444 // We don't at this point know if the activity is fullscreen, 445 // so we need to be conservative and assume it isn't. 446 Slog.w(TAG, "Activity pause timeout for " + r); 447 synchronized (mService.mGlobalLock) { 448 if (r.hasProcess()) { 449 mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r); 450 } 451 activityPausedLocked(r.appToken, true); 452 } 453 } break; 454 case LAUNCH_TICK_MSG: { 455 ActivityRecord r = (ActivityRecord)msg.obj; 456 synchronized (mService.mGlobalLock) { 457 if (r.continueLaunchTickingLocked()) { 458 mService.logAppTooSlow(r.app, r.launchTickTime, "launching " + r); 459 } 460 } 461 } break; 462 case DESTROY_TIMEOUT_MSG: { 463 ActivityRecord r = (ActivityRecord)msg.obj; 464 // We don't at this point know if the activity is fullscreen, 465 // so we need to be conservative and assume it isn't. 466 Slog.w(TAG, "Activity destroy timeout for " + r); 467 synchronized (mService.mGlobalLock) { 468 activityDestroyedLocked(r != null ? r.appToken : null, "destroyTimeout"); 469 } 470 } break; 471 case STOP_TIMEOUT_MSG: { 472 ActivityRecord r = (ActivityRecord)msg.obj; 473 // We don't at this point know if the activity is fullscreen, 474 // so we need to be conservative and assume it isn't. 475 Slog.w(TAG, "Activity stop timeout for " + r); 476 synchronized (mService.mGlobalLock) { 477 if (r.isInHistory()) { 478 r.activityStoppedLocked(null /* icicle */, 479 null /* persistentState */, null /* description */); 480 } 481 } 482 } break; 483 case DESTROY_ACTIVITIES_MSG: { 484 ScheduleDestroyArgs args = (ScheduleDestroyArgs)msg.obj; 485 synchronized (mService.mGlobalLock) { 486 destroyActivitiesLocked(args.mOwner, args.mReason); 487 } 488 } break; 489 case TRANSLUCENT_TIMEOUT_MSG: { 490 synchronized (mService.mGlobalLock) { 491 notifyActivityDrawnLocked(null); 492 } 493 } break; 494 } 495 } 496 } 497 numActivities()498 int numActivities() { 499 int count = 0; 500 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 501 count += mTaskHistory.get(taskNdx).mActivities.size(); 502 } 503 return count; 504 } 505 ActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor, int windowingMode, int activityType, boolean onTop)506 ActivityStack(ActivityDisplay display, int stackId, ActivityStackSupervisor supervisor, 507 int windowingMode, int activityType, boolean onTop) { 508 mStackSupervisor = supervisor; 509 mService = supervisor.mService; 510 mRootActivityContainer = mService.mRootActivityContainer; 511 mHandler = new ActivityStackHandler(supervisor.mLooper); 512 mWindowManager = mService.mWindowManager; 513 mStackId = stackId; 514 mCurrentUser = mService.mAmInternal.getCurrentUserId(); 515 // Set display id before setting activity and window type to make sure it won't affect 516 // stacks on a wrong display. 517 mDisplayId = display.mDisplayId; 518 setActivityType(activityType); 519 createTaskStack(display.mDisplayId, onTop, mTmpRect2); 520 setWindowingMode(windowingMode, false /* animate */, false /* showRecents */, 521 false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */, 522 true /* creating */); 523 display.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM); 524 } 525 createTaskStack(int displayId, boolean onTop, Rect outBounds)526 void createTaskStack(int displayId, boolean onTop, Rect outBounds) { 527 final DisplayContent dc = mWindowManager.mRoot.getDisplayContent(displayId); 528 if (dc == null) { 529 throw new IllegalArgumentException("Trying to add stackId=" + mStackId 530 + " to unknown displayId=" + displayId); 531 } 532 mTaskStack = new TaskStack(mWindowManager, mStackId, this); 533 dc.setStackOnDisplay(mStackId, onTop, mTaskStack); 534 if (mTaskStack.matchParentBounds()) { 535 outBounds.setEmpty(); 536 } else { 537 mTaskStack.getRawBounds(outBounds); 538 } 539 } 540 getTaskStack()541 TaskStack getTaskStack() { 542 return mTaskStack; 543 } 544 545 /** 546 * This should be called when an activity in a child task changes state. This should only 547 * be called from 548 * {@link TaskRecord#onActivityStateChanged(ActivityRecord, ActivityState, String)}. 549 * @param record The {@link ActivityRecord} whose state has changed. 550 * @param state The new state. 551 * @param reason The reason for the change. 552 */ onActivityStateChanged(ActivityRecord record, ActivityState state, String reason)553 void onActivityStateChanged(ActivityRecord record, ActivityState state, String reason) { 554 if (record == mResumedActivity && state != RESUMED) { 555 setResumedActivity(null, reason + " - onActivityStateChanged"); 556 } 557 558 if (state == RESUMED) { 559 if (DEBUG_STACK) Slog.v(TAG_STACK, "set resumed activity to:" + record + " reason:" 560 + reason); 561 setResumedActivity(record, reason + " - onActivityStateChanged"); 562 if (record == mRootActivityContainer.getTopResumedActivity()) { 563 // TODO(b/111361570): Support multiple focused apps in WM 564 mService.setResumedActivityUncheckLocked(record, reason); 565 } 566 mStackSupervisor.mRecentTasks.add(record.getTaskRecord()); 567 } 568 } 569 570 @Override onConfigurationChanged(Configuration newParentConfig)571 public void onConfigurationChanged(Configuration newParentConfig) { 572 final int prevWindowingMode = getWindowingMode(); 573 final boolean prevIsAlwaysOnTop = isAlwaysOnTop(); 574 final int prevRotation = getWindowConfiguration().getRotation(); 575 final int prevDensity = getConfiguration().densityDpi; 576 final int prevScreenW = getConfiguration().screenWidthDp; 577 final int prevScreenH = getConfiguration().screenHeightDp; 578 final Rect newBounds = mTmpRect; 579 // Initialize the new bounds by previous bounds as the input and output for calculating 580 // override bounds in pinned (pip) or split-screen mode. 581 getBounds(newBounds); 582 583 super.onConfigurationChanged(newParentConfig); 584 final ActivityDisplay display = getDisplay(); 585 if (display == null || getTaskStack() == null) { 586 return; 587 } 588 589 final boolean windowingModeChanged = prevWindowingMode != getWindowingMode(); 590 final int overrideWindowingMode = getRequestedOverrideWindowingMode(); 591 // Update bounds if applicable 592 boolean hasNewOverrideBounds = false; 593 // Use override windowing mode to prevent extra bounds changes if inheriting the mode. 594 if (overrideWindowingMode == WINDOWING_MODE_PINNED) { 595 // Pinned calculation already includes rotation 596 hasNewOverrideBounds = getTaskStack().calculatePinnedBoundsForConfigChange(newBounds); 597 } else if (!matchParentBounds()) { 598 // If the parent (display) has rotated, rotate our bounds to best-fit where their 599 // bounds were on the pre-rotated display. 600 final int newRotation = getWindowConfiguration().getRotation(); 601 final boolean rotationChanged = prevRotation != newRotation; 602 if (rotationChanged) { 603 display.mDisplayContent.rotateBounds( 604 newParentConfig.windowConfiguration.getBounds(), prevRotation, newRotation, 605 newBounds); 606 hasNewOverrideBounds = true; 607 } 608 609 // Use override windowing mode to prevent extra bounds changes if inheriting the mode. 610 if (overrideWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY 611 || overrideWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { 612 // If entering split screen or if something about the available split area changes, 613 // recalculate the split windows to match the new configuration. 614 if (rotationChanged || windowingModeChanged 615 || prevDensity != getConfiguration().densityDpi 616 || prevScreenW != getConfiguration().screenWidthDp 617 || prevScreenH != getConfiguration().screenHeightDp) { 618 getTaskStack().calculateDockedBoundsForConfigChange(newParentConfig, newBounds); 619 hasNewOverrideBounds = true; 620 } 621 } 622 } 623 624 if (windowingModeChanged) { 625 // Use override windowing mode to prevent extra bounds changes if inheriting the mode. 626 if (overrideWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { 627 getStackDockedModeBounds(null /* dockedBounds */, null /* currentTempTaskBounds */, 628 newBounds /* outStackBounds */, mTmpRect2 /* outTempTaskBounds */); 629 // immediately resize so docked bounds are available in onSplitScreenModeActivated 630 setTaskDisplayedBounds(null); 631 setTaskBounds(newBounds); 632 setBounds(newBounds); 633 newBounds.set(newBounds); 634 } else if (overrideWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { 635 Rect dockedBounds = display.getSplitScreenPrimaryStack().getBounds(); 636 final boolean isMinimizedDock = 637 display.mDisplayContent.getDockedDividerController().isMinimizedDock(); 638 if (isMinimizedDock) { 639 TaskRecord topTask = display.getSplitScreenPrimaryStack().topTask(); 640 if (topTask != null) { 641 dockedBounds = topTask.getBounds(); 642 } 643 } 644 getStackDockedModeBounds(dockedBounds, null /* currentTempTaskBounds */, 645 newBounds /* outStackBounds */, mTmpRect2 /* outTempTaskBounds */); 646 hasNewOverrideBounds = true; 647 } 648 display.onStackWindowingModeChanged(this); 649 } 650 if (hasNewOverrideBounds) { 651 // Note the resizeStack may enter onConfigurationChanged recursively, so we make a copy 652 // of the temporary bounds (newBounds is mTmpRect) to avoid it being modified. 653 mRootActivityContainer.resizeStack(this, new Rect(newBounds), null /* tempTaskBounds */, 654 null /* tempTaskInsetBounds */, PRESERVE_WINDOWS, 655 true /* allowResizeInDockedMode */, true /* deferResume */); 656 } 657 if (prevIsAlwaysOnTop != isAlwaysOnTop()) { 658 // Since always on top is only on when the stack is freeform or pinned, the state 659 // can be toggled when the windowing mode changes. We must make sure the stack is 660 // placed properly when always on top state changes. 661 display.positionChildAtTop(this, false /* includingParents */); 662 } 663 } 664 665 @Override setWindowingMode(int windowingMode)666 public void setWindowingMode(int windowingMode) { 667 setWindowingMode(windowingMode, false /* animate */, false /* showRecents */, 668 false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */, 669 false /* creating */); 670 } 671 672 /** 673 * A transient windowing mode is one which activities enter into temporarily. Examples of this 674 * are Split window modes and pip. Non-transient modes are modes that displays can adopt. 675 * 676 * @param windowingMode the windowingMode to test for transient-ness. 677 * @return {@code true} if the windowing mode is transient, {@code false} otherwise. 678 */ isTransientWindowingMode(int windowingMode)679 private static boolean isTransientWindowingMode(int windowingMode) { 680 // TODO(b/114842032): add PIP if/when it uses mode transitions instead of task reparenting 681 return windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY 682 || windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; 683 } 684 685 /** 686 * Specialization of {@link #setWindowingMode(int)} for this subclass. 687 * 688 * @param preferredWindowingMode the preferred windowing mode. This may not be honored depending 689 * on the state of things. For example, WINDOWING_MODE_UNDEFINED will resolve to the 690 * previous non-transient mode if this stack is currently in a transient mode. 691 * @param animate Can be used to prevent animation. 692 * @param showRecents Controls whether recents is shown on the other side of a split while 693 * entering split mode. 694 * @param enteringSplitScreenMode {@code true} if entering split mode. 695 * @param deferEnsuringVisibility Whether visibility updates are deferred. This is set when 696 * many operations (which can effect visibility) are being performed in bulk. 697 * @param creating {@code true} if this is being run during ActivityStack construction. 698 */ setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents, boolean enteringSplitScreenMode, boolean deferEnsuringVisibility, boolean creating)699 void setWindowingMode(int preferredWindowingMode, boolean animate, boolean showRecents, 700 boolean enteringSplitScreenMode, boolean deferEnsuringVisibility, boolean creating) { 701 mWindowManager.inSurfaceTransaction(() -> setWindowingModeInSurfaceTransaction( 702 preferredWindowingMode, animate, showRecents, enteringSplitScreenMode, 703 deferEnsuringVisibility, creating)); 704 } 705 setWindowingModeInSurfaceTransaction(int preferredWindowingMode, boolean animate, boolean showRecents, boolean enteringSplitScreenMode, boolean deferEnsuringVisibility, boolean creating)706 private void setWindowingModeInSurfaceTransaction(int preferredWindowingMode, boolean animate, 707 boolean showRecents, boolean enteringSplitScreenMode, boolean deferEnsuringVisibility, 708 boolean creating) { 709 final int currentMode = getWindowingMode(); 710 final int currentOverrideMode = getRequestedOverrideWindowingMode(); 711 final ActivityDisplay display = getDisplay(); 712 final TaskRecord topTask = topTask(); 713 final ActivityStack splitScreenStack = display.getSplitScreenPrimaryStack(); 714 int windowingMode = preferredWindowingMode; 715 if (preferredWindowingMode == WINDOWING_MODE_UNDEFINED 716 && isTransientWindowingMode(currentMode)) { 717 // Leaving a transient mode. Interpret UNDEFINED as "restore" 718 windowingMode = mRestoreOverrideWindowingMode; 719 } 720 mTmpOptions.setLaunchWindowingMode(windowingMode); 721 722 // Need to make sure windowing mode is supported. If we in the process of creating the stack 723 // no need to resolve the windowing mode again as it is already resolved to the right mode. 724 if (!creating) { 725 windowingMode = display.validateWindowingMode(windowingMode, 726 null /* ActivityRecord */, topTask, getActivityType()); 727 } 728 if (splitScreenStack == this 729 && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) { 730 // Resolution to split-screen secondary for the primary split-screen stack means 731 // we want to leave split-screen mode. 732 windowingMode = mRestoreOverrideWindowingMode; 733 } 734 735 final boolean alreadyInSplitScreenMode = display.hasSplitScreenPrimaryStack(); 736 737 // Don't send non-resizeable notifications if the windowing mode changed was a side effect 738 // of us entering split-screen mode. 739 final boolean sendNonResizeableNotification = !enteringSplitScreenMode; 740 // Take any required action due to us not supporting the preferred windowing mode. 741 if (alreadyInSplitScreenMode && windowingMode == WINDOWING_MODE_FULLSCREEN 742 && sendNonResizeableNotification && isActivityTypeStandardOrUndefined()) { 743 final boolean preferredSplitScreen = 744 preferredWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY 745 || preferredWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY; 746 if (preferredSplitScreen || creating) { 747 // Looks like we can't launch in split screen mode or the stack we are launching 748 // doesn't support split-screen mode, go ahead an dismiss split-screen and display a 749 // warning toast about it. 750 mService.getTaskChangeNotificationController().notifyActivityDismissingDockedStack(); 751 final ActivityStack primarySplitStack = display.getSplitScreenPrimaryStack(); 752 primarySplitStack.setWindowingModeInSurfaceTransaction(WINDOWING_MODE_UNDEFINED, 753 false /* animate */, false /* showRecents */, 754 false /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */, 755 primarySplitStack == this ? creating : false); 756 } 757 } 758 759 if (currentMode == windowingMode) { 760 // You are already in the window mode, so we can skip most of the work below. However, 761 // it's possible that we have inherited the current windowing mode from a parent. So, 762 // fulfill this method's contract by setting the override mode directly. 763 getRequestedOverrideConfiguration().windowConfiguration.setWindowingMode(windowingMode); 764 return; 765 } 766 767 final WindowManagerService wm = mService.mWindowManager; 768 final ActivityRecord topActivity = getTopActivity(); 769 770 // For now, assume that the Stack's windowing mode is what will actually be used 771 // by it's activities. In the future, there may be situations where this doesn't 772 // happen; so at that point, this message will need to handle that. 773 int likelyResolvedMode = windowingMode; 774 if (windowingMode == WINDOWING_MODE_UNDEFINED) { 775 final ConfigurationContainer parent = getParent(); 776 likelyResolvedMode = parent != null ? parent.getWindowingMode() 777 : WINDOWING_MODE_FULLSCREEN; 778 } 779 if (sendNonResizeableNotification && likelyResolvedMode != WINDOWING_MODE_FULLSCREEN 780 && topActivity != null && topActivity.isNonResizableOrForcedResizable() 781 && !topActivity.noDisplay) { 782 // Inform the user that they are starting an app that may not work correctly in 783 // multi-window mode. 784 final String packageName = topActivity.appInfo.packageName; 785 mService.getTaskChangeNotificationController().notifyActivityForcedResizable( 786 topTask.taskId, FORCED_RESIZEABLE_REASON_SPLIT_SCREEN, packageName); 787 } 788 789 wm.deferSurfaceLayout(); 790 try { 791 if (!animate && topActivity != null) { 792 mStackSupervisor.mNoAnimActivities.add(topActivity); 793 } 794 super.setWindowingMode(windowingMode); 795 // setWindowingMode triggers an onConfigurationChanged cascade which can result in a 796 // different resolved windowing mode (usually when preferredWindowingMode is UNDEFINED). 797 windowingMode = getWindowingMode(); 798 799 if (creating) { 800 // Nothing else to do if we don't have a window container yet. E.g. call from ctor. 801 return; 802 } 803 804 if (windowingMode == WINDOWING_MODE_PINNED || currentMode == WINDOWING_MODE_PINNED) { 805 // TODO: Need to remove use of PinnedActivityStack for this to be supported. 806 // NOTE: Need to ASS.scheduleUpdatePictureInPictureModeIfNeeded() in 807 // setWindowModeUnchecked() when this support is added. See TaskRecord.reparent() 808 throw new IllegalArgumentException( 809 "Changing pinned windowing mode not currently supported"); 810 } 811 812 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY && splitScreenStack != null) { 813 // We already have a split-screen stack in this display, so just move the tasks over. 814 // TODO: Figure-out how to do all the stuff in 815 // AMS.setTaskWindowingModeSplitScreenPrimary 816 throw new IllegalArgumentException("Setting primary split-screen windowing mode" 817 + " while there is already one isn't currently supported"); 818 //return; 819 } 820 if (isTransientWindowingMode(windowingMode) && !isTransientWindowingMode(currentMode)) { 821 mRestoreOverrideWindowingMode = currentOverrideMode; 822 } 823 824 mTmpRect2.setEmpty(); 825 if (windowingMode != WINDOWING_MODE_FULLSCREEN) { 826 if (mTaskStack.matchParentBounds()) { 827 mTmpRect2.setEmpty(); 828 } else { 829 mTaskStack.getRawBounds(mTmpRect2); 830 } 831 } 832 833 if (!Objects.equals(getRequestedOverrideBounds(), mTmpRect2)) { 834 resize(mTmpRect2, null /* tempTaskBounds */, null /* tempTaskInsetBounds */); 835 } 836 } finally { 837 if (showRecents && !alreadyInSplitScreenMode && mDisplayId == DEFAULT_DISPLAY 838 && windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { 839 // Make sure recents stack exist when creating a dock stack as it normally needs to 840 // be on the other side of the docked stack and we make visibility decisions based 841 // on that. 842 // TODO: This is only here to help out with the case where recents stack doesn't 843 // exist yet. For that case the initial size of the split-screen stack will be the 844 // the one where the home stack is visible since recents isn't visible yet, but the 845 // divider will be off. I think we should just make the initial bounds that of home 846 // so that the divider matches and remove this logic. 847 // TODO: This is currently only called when entering split-screen while in another 848 // task, and from the tests 849 // TODO (b/78247419): Check if launcher and overview are same then move home stack 850 // instead of recents stack. Then fix the rotation animation from fullscreen to 851 // minimized mode 852 final ActivityStack recentStack = display.getOrCreateStack( 853 WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_RECENTS, 854 true /* onTop */); 855 recentStack.moveToFront("setWindowingMode"); 856 // If task moved to docked stack - show recents if needed. 857 mService.mWindowManager.showRecentApps(); 858 } 859 wm.continueSurfaceLayout(); 860 } 861 862 if (!deferEnsuringVisibility) { 863 mRootActivityContainer.ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS); 864 mRootActivityContainer.resumeFocusedStacksTopActivities(); 865 } 866 } 867 868 @Override isCompatible(int windowingMode, int activityType)869 public boolean isCompatible(int windowingMode, int activityType) { 870 // TODO: Should we just move this to ConfigurationContainer? 871 if (activityType == ACTIVITY_TYPE_UNDEFINED) { 872 // Undefined activity types end up in a standard stack once the stack is created on a 873 // display, so they should be considered compatible. 874 activityType = ACTIVITY_TYPE_STANDARD; 875 } 876 return super.isCompatible(windowingMode, activityType); 877 } 878 879 /** Adds the stack to specified display and calls WindowManager to do the same. */ reparent(ActivityDisplay activityDisplay, boolean onTop, boolean displayRemoved)880 void reparent(ActivityDisplay activityDisplay, boolean onTop, boolean displayRemoved) { 881 // TODO: We should probably resolve the windowing mode for the stack on the new display here 882 // so that it end up in a compatible mode in the new display. e.g. split-screen secondary. 883 removeFromDisplay(); 884 // Reparent the window container before we try to update the position when adding it to 885 // the new display below 886 mTmpRect2.setEmpty(); 887 if (mTaskStack == null) { 888 // TODO: Remove after unification. 889 Log.w(TAG, "Task stack is not valid when reparenting."); 890 } else { 891 mTaskStack.reparent(activityDisplay.mDisplayId, mTmpRect2, onTop); 892 } 893 setBounds(mTmpRect2.isEmpty() ? null : mTmpRect2); 894 activityDisplay.addChild(this, onTop ? POSITION_TOP : POSITION_BOTTOM); 895 if (!displayRemoved) { 896 postReparent(); 897 } 898 } 899 900 /** Resume next focusable stack after reparenting to another display. */ postReparent()901 void postReparent() { 902 adjustFocusToNextFocusableStack("reparent", true /* allowFocusSelf */); 903 mRootActivityContainer.resumeFocusedStacksTopActivities(); 904 // Update visibility of activities before notifying WM. This way it won't try to resize 905 // windows that are no longer visible. 906 mRootActivityContainer.ensureActivitiesVisible(null /* starting */, 0 /* configChanges */, 907 !PRESERVE_WINDOWS); 908 } 909 910 /** 911 * Updates the inner state of the stack to remove it from its current parent, so it can be 912 * either destroyed completely or re-parented. 913 */ removeFromDisplay()914 private void removeFromDisplay() { 915 final ActivityDisplay display = getDisplay(); 916 if (display != null) { 917 display.removeChild(this); 918 } 919 mDisplayId = INVALID_DISPLAY; 920 } 921 922 /** Removes the stack completely. Also calls WindowManager to do the same on its side. */ remove()923 void remove() { 924 removeFromDisplay(); 925 if (mTaskStack != null) { 926 mTaskStack.removeIfPossible(); 927 mTaskStack = null; 928 } 929 onParentChanged(); 930 } 931 getDisplay()932 ActivityDisplay getDisplay() { 933 return mRootActivityContainer.getActivityDisplay(mDisplayId); 934 } 935 936 /** 937 * @see #getStackDockedModeBounds(Rect, Rect, Rect, Rect) 938 */ getStackDockedModeBounds(Rect dockedBounds, Rect currentTempTaskBounds, Rect outStackBounds, Rect outTempTaskBounds)939 void getStackDockedModeBounds(Rect dockedBounds, Rect currentTempTaskBounds, 940 Rect outStackBounds, Rect outTempTaskBounds) { 941 if (mTaskStack != null) { 942 mTaskStack.getStackDockedModeBoundsLocked(getParent().getConfiguration(), dockedBounds, 943 currentTempTaskBounds, outStackBounds, outTempTaskBounds); 944 } else { 945 outStackBounds.setEmpty(); 946 outTempTaskBounds.setEmpty(); 947 } 948 } 949 prepareFreezingTaskBounds()950 void prepareFreezingTaskBounds() { 951 if (mTaskStack != null) { 952 // TODO: This cannot be false after unification. 953 mTaskStack.prepareFreezingTaskBounds(); 954 } 955 } 956 getWindowContainerBounds(Rect outBounds)957 void getWindowContainerBounds(Rect outBounds) { 958 if (mTaskStack != null) { 959 mTaskStack.getBounds(outBounds); 960 return; 961 } 962 outBounds.setEmpty(); 963 } 964 positionChildWindowContainerAtTop(TaskRecord child)965 void positionChildWindowContainerAtTop(TaskRecord child) { 966 if (mTaskStack != null) { 967 // TODO: Remove after unification. This cannot be false after that. 968 mTaskStack.positionChildAtTop(child.getTask(), true /* includingParents */); 969 } 970 } 971 positionChildWindowContainerAtBottom(TaskRecord child)972 void positionChildWindowContainerAtBottom(TaskRecord child) { 973 // If there are other focusable stacks on the display, the z-order of the display should not 974 // be changed just because a task was placed at the bottom. E.g. if it is moving the topmost 975 // task to bottom, the next focusable stack on the same display should be focused. 976 final ActivityStack nextFocusableStack = getDisplay().getNextFocusableStack( 977 child.getStack(), true /* ignoreCurrent */); 978 if (mTaskStack != null) { 979 // TODO: Remove after unification. This cannot be false after that. 980 mTaskStack.positionChildAtBottom(child.getTask(), 981 nextFocusableStack == null /* includingParents */); 982 } 983 } 984 985 /** 986 * Returns whether to defer the scheduling of the multi-window mode. 987 */ deferScheduleMultiWindowModeChanged()988 boolean deferScheduleMultiWindowModeChanged() { 989 if (inPinnedWindowingMode()) { 990 // For the pinned stack, the deferring of the multi-window mode changed is tied to the 991 // transition animation into picture-in-picture, and is called once the animation 992 // completes, or is interrupted in a way that would leave the stack in a non-fullscreen 993 // state. 994 // @see BoundsAnimationController 995 // @see BoundsAnimationControllerTests 996 if (getTaskStack() == null) return false; 997 return getTaskStack().deferScheduleMultiWindowModeChanged(); 998 } 999 return false; 1000 } 1001 1002 /** 1003 * Defers updating the bounds of the stack. If the stack was resized/repositioned while 1004 * deferring, the bounds will update in {@link #continueUpdateBounds()}. 1005 */ deferUpdateBounds()1006 void deferUpdateBounds() { 1007 if (!mUpdateBoundsDeferred) { 1008 mUpdateBoundsDeferred = true; 1009 mUpdateBoundsDeferredCalled = false; 1010 } 1011 } 1012 1013 /** 1014 * Continues updating bounds after updates have been deferred. If there was a resize attempt 1015 * between {@link #deferUpdateBounds()} and {@link #continueUpdateBounds()}, the stack will 1016 * be resized to that bounds. 1017 */ continueUpdateBounds()1018 void continueUpdateBounds() { 1019 if (mUpdateBoundsDeferred) { 1020 mUpdateBoundsDeferred = false; 1021 if (mUpdateBoundsDeferredCalled) { 1022 setTaskBounds(mDeferredBounds); 1023 setBounds(mDeferredBounds); 1024 } 1025 if (mUpdateDisplayedBoundsDeferredCalled) { 1026 setTaskDisplayedBounds(mDeferredDisplayedBounds); 1027 } 1028 } 1029 } 1030 updateBoundsAllowed(Rect bounds)1031 boolean updateBoundsAllowed(Rect bounds) { 1032 if (!mUpdateBoundsDeferred) { 1033 return true; 1034 } 1035 if (bounds != null) { 1036 mDeferredBounds.set(bounds); 1037 } else { 1038 mDeferredBounds.setEmpty(); 1039 } 1040 mUpdateBoundsDeferredCalled = true; 1041 return false; 1042 } 1043 updateDisplayedBoundsAllowed(Rect bounds)1044 boolean updateDisplayedBoundsAllowed(Rect bounds) { 1045 if (!mUpdateBoundsDeferred) { 1046 return true; 1047 } 1048 if (bounds != null) { 1049 mDeferredDisplayedBounds.set(bounds); 1050 } else { 1051 mDeferredDisplayedBounds.setEmpty(); 1052 } 1053 mUpdateDisplayedBoundsDeferredCalled = true; 1054 return false; 1055 } 1056 1057 @Override setBounds(Rect bounds)1058 public int setBounds(Rect bounds) { 1059 return super.setBounds(!inMultiWindowMode() ? null : bounds); 1060 } 1061 topRunningActivityLocked()1062 ActivityRecord topRunningActivityLocked() { 1063 return topRunningActivityLocked(false /* focusableOnly */); 1064 } 1065 getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities)1066 void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) { 1067 outActivities.clear(); 1068 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1069 mTaskHistory.get(taskNdx).getAllRunningVisibleActivitiesLocked(outActivities); 1070 } 1071 } 1072 topRunningActivityLocked(boolean focusableOnly)1073 ActivityRecord topRunningActivityLocked(boolean focusableOnly) { 1074 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1075 ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked(); 1076 if (r != null && (!focusableOnly || r.isFocusable())) { 1077 return r; 1078 } 1079 } 1080 return null; 1081 } 1082 topRunningNonOverlayTaskActivity()1083 ActivityRecord topRunningNonOverlayTaskActivity() { 1084 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1085 final TaskRecord task = mTaskHistory.get(taskNdx); 1086 final ArrayList<ActivityRecord> activities = task.mActivities; 1087 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1088 final ActivityRecord r = activities.get(activityNdx); 1089 if (!r.finishing && !r.mTaskOverlay) { 1090 return r; 1091 } 1092 } 1093 } 1094 return null; 1095 } 1096 topRunningNonDelayedActivityLocked(ActivityRecord notTop)1097 ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) { 1098 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1099 final TaskRecord task = mTaskHistory.get(taskNdx); 1100 final ArrayList<ActivityRecord> activities = task.mActivities; 1101 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1102 ActivityRecord r = activities.get(activityNdx); 1103 if (!r.finishing && !r.delayedResume && r != notTop && r.okToShowLocked()) { 1104 return r; 1105 } 1106 } 1107 } 1108 return null; 1109 } 1110 1111 /** 1112 * This is a simplified version of topRunningActivity that provides a number of 1113 * optional skip-over modes. It is intended for use with the ActivityController hook only. 1114 * 1115 * @param token If non-null, any history records matching this token will be skipped. 1116 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID. 1117 * 1118 * @return Returns the HistoryRecord of the next activity on the stack. 1119 */ topRunningActivityLocked(IBinder token, int taskId)1120 final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) { 1121 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1122 TaskRecord task = mTaskHistory.get(taskNdx); 1123 if (task.taskId == taskId) { 1124 continue; 1125 } 1126 ArrayList<ActivityRecord> activities = task.mActivities; 1127 for (int i = activities.size() - 1; i >= 0; --i) { 1128 final ActivityRecord r = activities.get(i); 1129 // Note: the taskId check depends on real taskId fields being non-zero 1130 if (!r.finishing && (token != r.appToken) && r.okToShowLocked()) { 1131 return r; 1132 } 1133 } 1134 } 1135 return null; 1136 } 1137 getTopActivity()1138 ActivityRecord getTopActivity() { 1139 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1140 final ActivityRecord r = mTaskHistory.get(taskNdx).getTopActivity(); 1141 if (r != null) { 1142 return r; 1143 } 1144 } 1145 return null; 1146 } 1147 topTask()1148 final TaskRecord topTask() { 1149 final int size = mTaskHistory.size(); 1150 if (size > 0) { 1151 return mTaskHistory.get(size - 1); 1152 } 1153 return null; 1154 } 1155 bottomTask()1156 private TaskRecord bottomTask() { 1157 if (mTaskHistory.isEmpty()) { 1158 return null; 1159 } 1160 return mTaskHistory.get(0); 1161 } 1162 taskForIdLocked(int id)1163 TaskRecord taskForIdLocked(int id) { 1164 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1165 final TaskRecord task = mTaskHistory.get(taskNdx); 1166 if (task.taskId == id) { 1167 return task; 1168 } 1169 } 1170 return null; 1171 } 1172 isInStackLocked(IBinder token)1173 ActivityRecord isInStackLocked(IBinder token) { 1174 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 1175 return isInStackLocked(r); 1176 } 1177 isInStackLocked(ActivityRecord r)1178 ActivityRecord isInStackLocked(ActivityRecord r) { 1179 if (r == null) { 1180 return null; 1181 } 1182 final TaskRecord task = r.getTaskRecord(); 1183 final ActivityStack stack = r.getActivityStack(); 1184 if (stack != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) { 1185 if (stack != this) Slog.w(TAG, 1186 "Illegal state! task does not point to stack it is in."); 1187 return r; 1188 } 1189 return null; 1190 } 1191 isInStackLocked(TaskRecord task)1192 boolean isInStackLocked(TaskRecord task) { 1193 return mTaskHistory.contains(task); 1194 } 1195 1196 /** Checks if there are tasks with specific UID in the stack. */ isUidPresent(int uid)1197 boolean isUidPresent(int uid) { 1198 for (TaskRecord task : mTaskHistory) { 1199 for (ActivityRecord r : task.mActivities) { 1200 if (r.getUid() == uid) { 1201 return true; 1202 } 1203 } 1204 } 1205 return false; 1206 } 1207 1208 /** Get all UIDs that are present in the stack. */ getPresentUIDs(IntArray presentUIDs)1209 void getPresentUIDs(IntArray presentUIDs) { 1210 for (TaskRecord task : mTaskHistory) { 1211 for (ActivityRecord r : task.mActivities) { 1212 presentUIDs.add(r.getUid()); 1213 } 1214 } 1215 } 1216 1217 /** @return true if the stack can only contain one task */ isSingleTaskInstance()1218 boolean isSingleTaskInstance() { 1219 final ActivityDisplay display = getDisplay(); 1220 return display != null && display.isSingleTaskInstance(); 1221 } 1222 removeActivitiesFromLRUListLocked(TaskRecord task)1223 final void removeActivitiesFromLRUListLocked(TaskRecord task) { 1224 for (ActivityRecord r : task.mActivities) { 1225 mLRUActivities.remove(r); 1226 } 1227 } 1228 updateLRUListLocked(ActivityRecord r)1229 final boolean updateLRUListLocked(ActivityRecord r) { 1230 final boolean hadit = mLRUActivities.remove(r); 1231 mLRUActivities.add(r); 1232 return hadit; 1233 } 1234 isHomeOrRecentsStack()1235 final boolean isHomeOrRecentsStack() { 1236 return isActivityTypeHome() || isActivityTypeRecents(); 1237 } 1238 isOnHomeDisplay()1239 final boolean isOnHomeDisplay() { 1240 return mDisplayId == DEFAULT_DISPLAY; 1241 } 1242 returnsToHomeStack()1243 private boolean returnsToHomeStack() { 1244 return !inMultiWindowMode() 1245 && !mTaskHistory.isEmpty() 1246 && mTaskHistory.get(0).returnsToHomeStack(); 1247 } 1248 moveToFront(String reason)1249 void moveToFront(String reason) { 1250 moveToFront(reason, null); 1251 } 1252 1253 /** 1254 * @param reason The reason for moving the stack to the front. 1255 * @param task If non-null, the task will be moved to the top of the stack. 1256 * */ moveToFront(String reason, TaskRecord task)1257 void moveToFront(String reason, TaskRecord task) { 1258 if (!isAttached()) { 1259 return; 1260 } 1261 1262 final ActivityDisplay display = getDisplay(); 1263 1264 if (inSplitScreenSecondaryWindowingMode()) { 1265 // If the stack is in split-screen seconardy mode, we need to make sure we move the 1266 // primary split-screen stack forward in the case it is currently behind a fullscreen 1267 // stack so both halves of the split-screen appear on-top and the fullscreen stack isn't 1268 // cutting between them. 1269 // TODO(b/70677280): This is a workaround until we can fix as part of b/70677280. 1270 final ActivityStack topFullScreenStack = 1271 display.getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN); 1272 if (topFullScreenStack != null) { 1273 final ActivityStack primarySplitScreenStack = display.getSplitScreenPrimaryStack(); 1274 if (display.getIndexOf(topFullScreenStack) 1275 > display.getIndexOf(primarySplitScreenStack)) { 1276 primarySplitScreenStack.moveToFront(reason + " splitScreenToTop"); 1277 } 1278 } 1279 } 1280 1281 if (!isActivityTypeHome() && returnsToHomeStack()) { 1282 // Make sure the home stack is behind this stack since that is where we should return to 1283 // when this stack is no longer visible. 1284 display.moveHomeStackToFront(reason + " returnToHome"); 1285 } 1286 1287 final boolean movingTask = task != null; 1288 display.positionChildAtTop(this, !movingTask /* includingParents */, reason); 1289 if (movingTask) { 1290 // This also moves the entire hierarchy branch to top, including parents 1291 insertTaskAtTop(task, null /* starting */); 1292 } 1293 } 1294 1295 /** 1296 * @param reason The reason for moving the stack to the back. 1297 * @param task If non-null, the task will be moved to the bottom of the stack. 1298 **/ moveToBack(String reason, TaskRecord task)1299 void moveToBack(String reason, TaskRecord task) { 1300 if (!isAttached()) { 1301 return; 1302 } 1303 1304 /** 1305 * The intent behind moving a primary split screen stack to the back is usually to hide 1306 * behind the home stack. Exit split screen in this case. 1307 */ 1308 if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { 1309 setWindowingMode(WINDOWING_MODE_UNDEFINED); 1310 } 1311 1312 getDisplay().positionChildAtBottom(this, reason); 1313 if (task != null) { 1314 insertTaskAtBottom(task); 1315 } 1316 } 1317 isFocusable()1318 boolean isFocusable() { 1319 final ActivityRecord r = topRunningActivityLocked(); 1320 return mRootActivityContainer.isFocusable(this, r != null && r.isFocusable()); 1321 } 1322 isFocusableAndVisible()1323 boolean isFocusableAndVisible() { 1324 return isFocusable() && shouldBeVisible(null /* starting */); 1325 } 1326 isAttached()1327 final boolean isAttached() { 1328 final ActivityDisplay display = getDisplay(); 1329 return display != null && !display.isRemoved(); 1330 } 1331 1332 /** 1333 * Returns the top activity in any existing task matching the given Intent in the input result. 1334 * Returns null if no such task is found. 1335 */ findTaskLocked(ActivityRecord target, FindTaskResult result)1336 void findTaskLocked(ActivityRecord target, FindTaskResult result) { 1337 Intent intent = target.intent; 1338 ActivityInfo info = target.info; 1339 ComponentName cls = intent.getComponent(); 1340 if (info.targetActivity != null) { 1341 cls = new ComponentName(info.packageName, info.targetActivity); 1342 } 1343 final int userId = UserHandle.getUserId(info.applicationInfo.uid); 1344 boolean isDocument = intent != null & intent.isDocument(); 1345 // If documentData is non-null then it must match the existing task data. 1346 Uri documentData = isDocument ? intent.getData() : null; 1347 1348 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Looking for task of " + target + " in " + this); 1349 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1350 final TaskRecord task = mTaskHistory.get(taskNdx); 1351 if (task.voiceSession != null) { 1352 // We never match voice sessions; those always run independently. 1353 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": voice session"); 1354 continue; 1355 } 1356 if (task.userId != userId) { 1357 // Looking for a different task. 1358 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": different user"); 1359 continue; 1360 } 1361 1362 // Overlays should not be considered as the task's logical top activity. 1363 final ActivityRecord r = task.getTopActivity(false /* includeOverlays */); 1364 if (r == null || r.finishing || r.mUserId != userId || 1365 r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { 1366 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch root " + r); 1367 continue; 1368 } 1369 if (!r.hasCompatibleActivityType(target)) { 1370 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Skipping " + task + ": mismatch activity type"); 1371 continue; 1372 } 1373 1374 final Intent taskIntent = task.intent; 1375 final Intent affinityIntent = task.affinityIntent; 1376 final boolean taskIsDocument; 1377 final Uri taskDocumentData; 1378 if (taskIntent != null && taskIntent.isDocument()) { 1379 taskIsDocument = true; 1380 taskDocumentData = taskIntent.getData(); 1381 } else if (affinityIntent != null && affinityIntent.isDocument()) { 1382 taskIsDocument = true; 1383 taskDocumentData = affinityIntent.getData(); 1384 } else { 1385 taskIsDocument = false; 1386 taskDocumentData = null; 1387 } 1388 1389 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls=" 1390 + (task.realActivity != null ? task.realActivity.flattenToShortString() : "") 1391 + "/aff=" + r.getTaskRecord().rootAffinity + " to new cls=" 1392 + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity); 1393 // TODO Refactor to remove duplications. Check if logic can be simplified. 1394 if (task.realActivity != null && task.realActivity.compareTo(cls) == 0 1395 && Objects.equals(documentData, taskDocumentData)) { 1396 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!"); 1397 //dump(); 1398 if (DEBUG_TASKS) Slog.d(TAG_TASKS, 1399 "For Intent " + intent + " bringing to top: " + r.intent); 1400 result.mRecord = r; 1401 result.mIdealMatch = true; 1402 break; 1403 } else if (affinityIntent != null && affinityIntent.getComponent() != null && 1404 affinityIntent.getComponent().compareTo(cls) == 0 && 1405 Objects.equals(documentData, taskDocumentData)) { 1406 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!"); 1407 //dump(); 1408 if (DEBUG_TASKS) Slog.d(TAG_TASKS, 1409 "For Intent " + intent + " bringing to top: " + r.intent); 1410 result.mRecord = r; 1411 result.mIdealMatch = true; 1412 break; 1413 } else if (!isDocument && !taskIsDocument 1414 && result.mRecord == null && task.rootAffinity != null) { 1415 if (task.rootAffinity.equals(target.taskAffinity)) { 1416 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching affinity candidate!"); 1417 // It is possible for multiple tasks to have the same root affinity especially 1418 // if they are in separate stacks. We save off this candidate, but keep looking 1419 // to see if there is a better candidate. 1420 result.mRecord = r; 1421 result.mIdealMatch = false; 1422 } 1423 } else if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Not a match: " + task); 1424 } 1425 } 1426 1427 /** 1428 * Returns the first activity (starting from the top of the stack) that 1429 * is the same as the given activity. Returns null if no such activity 1430 * is found. 1431 */ findActivityLocked(Intent intent, ActivityInfo info, boolean compareIntentFilters)1432 ActivityRecord findActivityLocked(Intent intent, ActivityInfo info, 1433 boolean compareIntentFilters) { 1434 ComponentName cls = intent.getComponent(); 1435 if (info.targetActivity != null) { 1436 cls = new ComponentName(info.packageName, info.targetActivity); 1437 } 1438 final int userId = UserHandle.getUserId(info.applicationInfo.uid); 1439 1440 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1441 final TaskRecord task = mTaskHistory.get(taskNdx); 1442 final ArrayList<ActivityRecord> activities = task.mActivities; 1443 1444 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1445 ActivityRecord r = activities.get(activityNdx); 1446 if (!r.okToShowLocked()) { 1447 continue; 1448 } 1449 if (!r.finishing && r.mUserId == userId) { 1450 if (compareIntentFilters) { 1451 if (r.intent.filterEquals(intent)) { 1452 return r; 1453 } 1454 } else { 1455 if (r.intent.getComponent().equals(cls)) { 1456 return r; 1457 } 1458 } 1459 } 1460 } 1461 } 1462 1463 return null; 1464 } 1465 1466 /* 1467 * Move the activities around in the stack to bring a user to the foreground. 1468 */ switchUserLocked(int userId)1469 final void switchUserLocked(int userId) { 1470 if (mCurrentUser == userId) { 1471 return; 1472 } 1473 mCurrentUser = userId; 1474 1475 // Move userId's tasks to the top. 1476 int index = mTaskHistory.size(); 1477 for (int i = 0; i < index; ) { 1478 final TaskRecord task = mTaskHistory.get(i); 1479 1480 if (task.okToShowLocked()) { 1481 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "switchUser: stack=" + getStackId() + 1482 " moving " + task + " to top"); 1483 mTaskHistory.remove(i); 1484 mTaskHistory.add(task); 1485 --index; 1486 // Use same value for i. 1487 } else { 1488 ++i; 1489 } 1490 } 1491 } 1492 minimalResumeActivityLocked(ActivityRecord r)1493 void minimalResumeActivityLocked(ActivityRecord r) { 1494 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + r + " (starting new instance)" 1495 + " callers=" + Debug.getCallers(5)); 1496 r.setState(RESUMED, "minimalResumeActivityLocked"); 1497 r.completeResumeLocked(); 1498 if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, 1499 "Launch completed; removing icicle of " + r.icicle); 1500 } 1501 clearLaunchTime(ActivityRecord r)1502 private void clearLaunchTime(ActivityRecord r) { 1503 // Make sure that there is no activity waiting for this to launch. 1504 if (!mStackSupervisor.mWaitingActivityLaunched.isEmpty()) { 1505 mStackSupervisor.removeTimeoutsForActivityLocked(r); 1506 mStackSupervisor.scheduleIdleTimeoutLocked(r); 1507 } 1508 } 1509 awakeFromSleepingLocked()1510 void awakeFromSleepingLocked() { 1511 // Ensure activities are no longer sleeping. 1512 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1513 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 1514 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1515 activities.get(activityNdx).setSleeping(false); 1516 } 1517 } 1518 if (mPausingActivity != null) { 1519 Slog.d(TAG, "awakeFromSleepingLocked: previously pausing activity didn't pause"); 1520 activityPausedLocked(mPausingActivity.appToken, true); 1521 } 1522 } 1523 updateActivityApplicationInfoLocked(ApplicationInfo aInfo)1524 void updateActivityApplicationInfoLocked(ApplicationInfo aInfo) { 1525 final String packageName = aInfo.packageName; 1526 final int userId = UserHandle.getUserId(aInfo.uid); 1527 1528 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1529 final List<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 1530 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1531 final ActivityRecord ar = activities.get(activityNdx); 1532 1533 if ((userId == ar.mUserId) && packageName.equals(ar.packageName)) { 1534 ar.updateApplicationInfo(aInfo); 1535 } 1536 } 1537 } 1538 } 1539 checkReadyForSleep()1540 void checkReadyForSleep() { 1541 if (shouldSleepActivities() && goToSleepIfPossible(false /* shuttingDown */)) { 1542 mStackSupervisor.checkReadyForSleepLocked(true /* allowDelay */); 1543 } 1544 } 1545 1546 /** 1547 * Tries to put the activities in the stack to sleep. 1548 * 1549 * If the stack is not in a state where its activities can be put to sleep, this function will 1550 * start any necessary actions to move the stack into such a state. It is expected that this 1551 * function get called again when those actions complete. 1552 * 1553 * @param shuttingDown true when the called because the device is shutting down. 1554 * @return true if the stack finished going to sleep, false if the stack only started the 1555 * process of going to sleep (checkReadyForSleep will be called when that process finishes). 1556 */ goToSleepIfPossible(boolean shuttingDown)1557 boolean goToSleepIfPossible(boolean shuttingDown) { 1558 boolean shouldSleep = true; 1559 1560 if (mResumedActivity != null) { 1561 // Still have something resumed; can't sleep until it is paused. 1562 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep needs to pause " + mResumedActivity); 1563 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING, 1564 "Sleep => pause with userLeaving=false"); 1565 1566 startPausingLocked(false, true, null, false); 1567 shouldSleep = false ; 1568 } else if (mPausingActivity != null) { 1569 // Still waiting for something to pause; can't sleep yet. 1570 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still waiting to pause " + mPausingActivity); 1571 shouldSleep = false; 1572 } 1573 1574 if (!shuttingDown) { 1575 if (containsActivityFromStack(mStackSupervisor.mStoppingActivities)) { 1576 // Still need to tell some activities to stop; can't sleep yet. 1577 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to stop " 1578 + mStackSupervisor.mStoppingActivities.size() + " activities"); 1579 1580 mStackSupervisor.scheduleIdleLocked(); 1581 shouldSleep = false; 1582 } 1583 1584 if (containsActivityFromStack(mStackSupervisor.mGoingToSleepActivities)) { 1585 // Still need to tell some activities to sleep; can't sleep yet. 1586 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Sleep still need to sleep " 1587 + mStackSupervisor.mGoingToSleepActivities.size() + " activities"); 1588 shouldSleep = false; 1589 } 1590 } 1591 1592 if (shouldSleep) { 1593 goToSleep(); 1594 } 1595 1596 return shouldSleep; 1597 } 1598 goToSleep()1599 void goToSleep() { 1600 // Ensure visibility without updating configuration, as activities are about to sleep. 1601 ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */, 1602 !PRESERVE_WINDOWS); 1603 1604 // Make sure any paused or stopped but visible activities are now sleeping. 1605 // This ensures that the activity's onStop() is called. 1606 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1607 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 1608 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1609 final ActivityRecord r = activities.get(activityNdx); 1610 if (r.isState(STOPPING, STOPPED, PAUSED, PAUSING)) { 1611 r.setSleeping(true); 1612 } 1613 } 1614 } 1615 } 1616 containsActivityFromStack(List<ActivityRecord> rs)1617 private boolean containsActivityFromStack(List<ActivityRecord> rs) { 1618 for (ActivityRecord r : rs) { 1619 if (r.getActivityStack() == this) { 1620 return true; 1621 } 1622 } 1623 return false; 1624 } 1625 1626 /** 1627 * Schedule a pause timeout in case the app doesn't respond. We don't give it much time because 1628 * this directly impacts the responsiveness seen by the user. 1629 */ schedulePauseTimeout(ActivityRecord r)1630 private void schedulePauseTimeout(ActivityRecord r) { 1631 final Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG); 1632 msg.obj = r; 1633 r.pauseTime = SystemClock.uptimeMillis(); 1634 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT); 1635 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Waiting for pause to complete..."); 1636 } 1637 1638 /** 1639 * Start pausing the currently resumed activity. It is an error to call this if there 1640 * is already an activity being paused or there is no resumed activity. 1641 * 1642 * @param userLeaving True if this should result in an onUserLeaving to the current activity. 1643 * @param uiSleeping True if this is happening with the user interface going to sleep (the 1644 * screen turning off). 1645 * @param resuming The activity we are currently trying to resume or null if this is not being 1646 * called as part of resuming the top activity, so we shouldn't try to instigate 1647 * a resume here if not null. 1648 * @param pauseImmediately True if the caller does not want to wait for the activity callback to 1649 * complete pausing. 1650 * @return Returns true if an activity now is in the PAUSING state, and we are waiting for 1651 * it to tell us when it is done. 1652 */ startPausingLocked(boolean userLeaving, boolean uiSleeping, ActivityRecord resuming, boolean pauseImmediately)1653 final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, 1654 ActivityRecord resuming, boolean pauseImmediately) { 1655 if (mPausingActivity != null) { 1656 Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity 1657 + " state=" + mPausingActivity.getState()); 1658 if (!shouldSleepActivities()) { 1659 // Avoid recursion among check for sleep and complete pause during sleeping. 1660 // Because activity will be paused immediately after resume, just let pause 1661 // be completed by the order of activity paused from clients. 1662 completePauseLocked(false, resuming); 1663 } 1664 } 1665 ActivityRecord prev = mResumedActivity; 1666 1667 if (prev == null) { 1668 if (resuming == null) { 1669 Slog.wtf(TAG, "Trying to pause when nothing is resumed"); 1670 mRootActivityContainer.resumeFocusedStacksTopActivities(); 1671 } 1672 return false; 1673 } 1674 1675 if (prev == resuming) { 1676 Slog.wtf(TAG, "Trying to pause activity that is in process of being resumed"); 1677 return false; 1678 } 1679 1680 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSING: " + prev); 1681 else if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Start pausing: " + prev); 1682 mPausingActivity = prev; 1683 mLastPausedActivity = prev; 1684 mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 1685 || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null; 1686 prev.setState(PAUSING, "startPausingLocked"); 1687 prev.getTaskRecord().touchActiveTime(); 1688 clearLaunchTime(prev); 1689 1690 mService.updateCpuStats(); 1691 1692 if (prev.attachedToProcess()) { 1693 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev); 1694 try { 1695 EventLogTags.writeAmPauseActivity(prev.mUserId, System.identityHashCode(prev), 1696 prev.shortComponentName, "userLeaving=" + userLeaving); 1697 1698 mService.getLifecycleManager().scheduleTransaction(prev.app.getThread(), 1699 prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving, 1700 prev.configChangeFlags, pauseImmediately)); 1701 } catch (Exception e) { 1702 // Ignore exception, if process died other code will cleanup. 1703 Slog.w(TAG, "Exception thrown during pause", e); 1704 mPausingActivity = null; 1705 mLastPausedActivity = null; 1706 mLastNoHistoryActivity = null; 1707 } 1708 } else { 1709 mPausingActivity = null; 1710 mLastPausedActivity = null; 1711 mLastNoHistoryActivity = null; 1712 } 1713 1714 // If we are not going to sleep, we want to ensure the device is 1715 // awake until the next activity is started. 1716 if (!uiSleeping && !mService.isSleepingOrShuttingDownLocked()) { 1717 mStackSupervisor.acquireLaunchWakelock(); 1718 } 1719 1720 if (mPausingActivity != null) { 1721 // Have the window manager pause its key dispatching until the new 1722 // activity has started. If we're pausing the activity just because 1723 // the screen is being turned off and the UI is sleeping, don't interrupt 1724 // key dispatch; the same activity will pick it up again on wakeup. 1725 if (!uiSleeping) { 1726 prev.pauseKeyDispatchingLocked(); 1727 } else if (DEBUG_PAUSE) { 1728 Slog.v(TAG_PAUSE, "Key dispatch not paused for screen off"); 1729 } 1730 1731 if (pauseImmediately) { 1732 // If the caller said they don't want to wait for the pause, then complete 1733 // the pause now. 1734 completePauseLocked(false, resuming); 1735 return false; 1736 1737 } else { 1738 schedulePauseTimeout(prev); 1739 return true; 1740 } 1741 1742 } else { 1743 // This activity failed to schedule the 1744 // pause, so just treat it as being paused now. 1745 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Activity not running, resuming next."); 1746 if (resuming == null) { 1747 mRootActivityContainer.resumeFocusedStacksTopActivities(); 1748 } 1749 return false; 1750 } 1751 } 1752 activityPausedLocked(IBinder token, boolean timeout)1753 final void activityPausedLocked(IBinder token, boolean timeout) { 1754 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, 1755 "Activity paused: token=" + token + ", timeout=" + timeout); 1756 1757 final ActivityRecord r = isInStackLocked(token); 1758 1759 if (r != null) { 1760 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); 1761 if (mPausingActivity == r) { 1762 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to PAUSED: " + r 1763 + (timeout ? " (due to timeout)" : " (pause complete)")); 1764 mService.mWindowManager.deferSurfaceLayout(); 1765 try { 1766 completePauseLocked(true /* resumeNext */, null /* resumingActivity */); 1767 } finally { 1768 mService.mWindowManager.continueSurfaceLayout(); 1769 } 1770 return; 1771 } else { 1772 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE, 1773 r.mUserId, System.identityHashCode(r), r.shortComponentName, 1774 mPausingActivity != null 1775 ? mPausingActivity.shortComponentName : "(none)"); 1776 if (r.isState(PAUSING)) { 1777 r.setState(PAUSED, "activityPausedLocked"); 1778 if (r.finishing) { 1779 if (DEBUG_PAUSE) Slog.v(TAG, 1780 "Executing finish of failed to pause activity: " + r); 1781 finishCurrentActivityLocked(r, FINISH_AFTER_VISIBLE, false, 1782 "activityPausedLocked"); 1783 } 1784 } 1785 } 1786 } 1787 mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS); 1788 } 1789 completePauseLocked(boolean resumeNext, ActivityRecord resuming)1790 private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) { 1791 ActivityRecord prev = mPausingActivity; 1792 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev); 1793 1794 if (prev != null) { 1795 prev.setWillCloseOrEnterPip(false); 1796 final boolean wasStopping = prev.isState(STOPPING); 1797 prev.setState(PAUSED, "completePausedLocked"); 1798 if (prev.finishing) { 1799 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Executing finish of activity: " + prev); 1800 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false, 1801 "completePausedLocked"); 1802 } else if (prev.hasProcess()) { 1803 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueue pending stop if needed: " + prev 1804 + " wasStopping=" + wasStopping + " visible=" + prev.visible); 1805 if (prev.deferRelaunchUntilPaused) { 1806 // Complete the deferred relaunch that was waiting for pause to complete. 1807 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Re-launching after pause: " + prev); 1808 prev.relaunchActivityLocked(false /* andResume */, 1809 prev.preserveWindowOnDeferredRelaunch); 1810 } else if (wasStopping) { 1811 // We are also stopping, the stop request must have gone soon after the pause. 1812 // We can't clobber it, because the stop confirmation will not be handled. 1813 // We don't need to schedule another stop, we only need to let it happen. 1814 prev.setState(STOPPING, "completePausedLocked"); 1815 } else if (!prev.visible || shouldSleepOrShutDownActivities()) { 1816 // Clear out any deferred client hide we might currently have. 1817 prev.setDeferHidingClient(false); 1818 // If we were visible then resumeTopActivities will release resources before 1819 // stopping. 1820 addToStopping(prev, true /* scheduleIdle */, false /* idleDelayed */, 1821 "completePauseLocked"); 1822 } 1823 } else { 1824 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "App died during pause, not stopping: " + prev); 1825 prev = null; 1826 } 1827 // It is possible the activity was freezing the screen before it was paused. 1828 // In that case go ahead and remove the freeze this activity has on the screen 1829 // since it is no longer visible. 1830 if (prev != null) { 1831 prev.stopFreezingScreenLocked(true /*force*/); 1832 } 1833 mPausingActivity = null; 1834 } 1835 1836 if (resumeNext) { 1837 final ActivityStack topStack = mRootActivityContainer.getTopDisplayFocusedStack(); 1838 if (!topStack.shouldSleepOrShutDownActivities()) { 1839 mRootActivityContainer.resumeFocusedStacksTopActivities(topStack, prev, null); 1840 } else { 1841 checkReadyForSleep(); 1842 ActivityRecord top = topStack.topRunningActivityLocked(); 1843 if (top == null || (prev != null && top != prev)) { 1844 // If there are no more activities available to run, do resume anyway to start 1845 // something. Also if the top activity on the stack is not the just paused 1846 // activity, we need to go ahead and resume it to ensure we complete an 1847 // in-flight app switch. 1848 mRootActivityContainer.resumeFocusedStacksTopActivities(); 1849 } 1850 } 1851 } 1852 1853 if (prev != null) { 1854 prev.resumeKeyDispatchingLocked(); 1855 1856 if (prev.hasProcess() && prev.cpuTimeAtResume > 0) { 1857 final long diff = prev.app.getCpuTime() - prev.cpuTimeAtResume; 1858 if (diff > 0) { 1859 final Runnable r = PooledLambda.obtainRunnable( 1860 ActivityManagerInternal::updateForegroundTimeIfOnBattery, 1861 mService.mAmInternal, prev.info.packageName, 1862 prev.info.applicationInfo.uid, 1863 diff); 1864 mService.mH.post(r); 1865 } 1866 } 1867 prev.cpuTimeAtResume = 0; // reset it 1868 } 1869 1870 // Notify when the task stack has changed, but only if visibilities changed (not just 1871 // focus). Also if there is an active pinned stack - we always want to notify it about 1872 // task stack changes, because its positioning may depend on it. 1873 if (mStackSupervisor.mAppVisibilitiesChangedSinceLastPause 1874 || (getDisplay() != null && getDisplay().hasPinnedStack())) { 1875 mService.getTaskChangeNotificationController().notifyTaskStackChanged(); 1876 mStackSupervisor.mAppVisibilitiesChangedSinceLastPause = false; 1877 } 1878 1879 mRootActivityContainer.ensureActivitiesVisible(resuming, 0, !PRESERVE_WINDOWS); 1880 } 1881 addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed, String reason)1882 private void addToStopping(ActivityRecord r, boolean scheduleIdle, boolean idleDelayed, 1883 String reason) { 1884 if (!mStackSupervisor.mStoppingActivities.contains(r)) { 1885 EventLog.writeEvent(EventLogTags.AM_ADD_TO_STOPPING, r.mUserId, 1886 System.identityHashCode(r), r.shortComponentName, reason); 1887 mStackSupervisor.mStoppingActivities.add(r); 1888 } 1889 1890 // If we already have a few activities waiting to stop, then give up 1891 // on things going idle and start clearing them out. Or if r is the 1892 // last of activity of the last task the stack will be empty and must 1893 // be cleared immediately. 1894 boolean forceIdle = mStackSupervisor.mStoppingActivities.size() > MAX_STOPPING_TO_FORCE 1895 || (r.frontOfTask && mTaskHistory.size() <= 1); 1896 if (scheduleIdle || forceIdle) { 1897 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Scheduling idle now: forceIdle=" 1898 + forceIdle + "immediate=" + !idleDelayed); 1899 if (!idleDelayed) { 1900 mStackSupervisor.scheduleIdleLocked(); 1901 } else { 1902 mStackSupervisor.scheduleIdleTimeoutLocked(r); 1903 } 1904 } else { 1905 checkReadyForSleep(); 1906 } 1907 } 1908 1909 /** 1910 * Returns true if the stack is translucent and can have other contents visible behind it if 1911 * needed. A stack is considered translucent if it don't contain a visible or 1912 * starting (about to be visible) activity that is fullscreen (opaque). 1913 * @param starting The currently starting activity or null if there is none. 1914 */ 1915 @VisibleForTesting isStackTranslucent(ActivityRecord starting)1916 boolean isStackTranslucent(ActivityRecord starting) { 1917 if (!isAttached() || mForceHidden) { 1918 return true; 1919 } 1920 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 1921 final TaskRecord task = mTaskHistory.get(taskNdx); 1922 final ArrayList<ActivityRecord> activities = task.mActivities; 1923 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 1924 final ActivityRecord r = activities.get(activityNdx); 1925 1926 if (r.finishing) { 1927 // We don't factor in finishing activities when determining translucency since 1928 // they will be gone soon. 1929 continue; 1930 } 1931 1932 if (!r.visibleIgnoringKeyguard && r != starting) { 1933 // Also ignore invisible activities that are not the currently starting 1934 // activity (about to be visible). 1935 continue; 1936 } 1937 1938 if (r.fullscreen || r.hasWallpaper) { 1939 // Stack isn't translucent if it has at least one fullscreen activity 1940 // that is visible. 1941 return false; 1942 } 1943 } 1944 } 1945 return true; 1946 } 1947 isTopStackOnDisplay()1948 boolean isTopStackOnDisplay() { 1949 final ActivityDisplay display = getDisplay(); 1950 return display != null && display.isTopStack(this); 1951 } 1952 1953 /** 1954 * @return {@code true} if this is the focused stack on its current display, {@code false} 1955 * otherwise. 1956 */ isFocusedStackOnDisplay()1957 boolean isFocusedStackOnDisplay() { 1958 final ActivityDisplay display = getDisplay(); 1959 return display != null && this == display.getFocusedStack(); 1960 } 1961 isTopActivityVisible()1962 boolean isTopActivityVisible() { 1963 final ActivityRecord topActivity = getTopActivity(); 1964 return topActivity != null && topActivity.visible; 1965 } 1966 1967 /** 1968 * Returns true if the stack should be visible. 1969 * 1970 * @param starting The currently starting activity or null if there is none. 1971 */ shouldBeVisible(ActivityRecord starting)1972 boolean shouldBeVisible(ActivityRecord starting) { 1973 return getVisibility(starting) != STACK_VISIBILITY_INVISIBLE; 1974 } 1975 1976 /** 1977 * Returns true if the stack should be visible. 1978 * 1979 * @param starting The currently starting activity or null if there is none. 1980 */ 1981 @StackVisibility getVisibility(ActivityRecord starting)1982 int getVisibility(ActivityRecord starting) { 1983 if (!isAttached() || mForceHidden) { 1984 return STACK_VISIBILITY_INVISIBLE; 1985 } 1986 1987 final ActivityDisplay display = getDisplay(); 1988 boolean gotSplitScreenStack = false; 1989 boolean gotOpaqueSplitScreenPrimary = false; 1990 boolean gotOpaqueSplitScreenSecondary = false; 1991 boolean gotTranslucentFullscreen = false; 1992 boolean gotTranslucentSplitScreenPrimary = false; 1993 boolean gotTranslucentSplitScreenSecondary = false; 1994 boolean shouldBeVisible = true; 1995 final int windowingMode = getWindowingMode(); 1996 final boolean isAssistantType = isActivityTypeAssistant(); 1997 for (int i = display.getChildCount() - 1; i >= 0; --i) { 1998 final ActivityStack other = display.getChildAt(i); 1999 final boolean hasRunningActivities = other.topRunningActivityLocked() != null; 2000 if (other == this) { 2001 // Should be visible if there is no other stack occluding it, unless it doesn't 2002 // have any running activities, not starting one and not home stack. 2003 shouldBeVisible = hasRunningActivities || isInStackLocked(starting) != null 2004 || isActivityTypeHome(); 2005 break; 2006 } 2007 2008 if (!hasRunningActivities) { 2009 continue; 2010 } 2011 2012 final int otherWindowingMode = other.getWindowingMode(); 2013 2014 if (otherWindowingMode == WINDOWING_MODE_FULLSCREEN) { 2015 // In this case the home stack isn't resizeable even though we are in split-screen 2016 // mode. We still want the primary splitscreen stack to be visible as there will be 2017 // a slight hint of it in the status bar area above the non-resizeable home 2018 // activity. In addition, if the fullscreen assistant is over primary splitscreen 2019 // stack, the stack should still be visible in the background as long as the recents 2020 // animation is running. 2021 final int activityType = other.getActivityType(); 2022 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) { 2023 if (activityType == ACTIVITY_TYPE_HOME 2024 || (activityType == ACTIVITY_TYPE_ASSISTANT 2025 && mWindowManager.getRecentsAnimationController() != null)) { 2026 break; 2027 } 2028 } 2029 if (other.isStackTranslucent(starting)) { 2030 // Can be visible behind a translucent fullscreen stack. 2031 gotTranslucentFullscreen = true; 2032 continue; 2033 } 2034 return STACK_VISIBILITY_INVISIBLE; 2035 } else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY 2036 && !gotOpaqueSplitScreenPrimary) { 2037 gotSplitScreenStack = true; 2038 gotTranslucentSplitScreenPrimary = other.isStackTranslucent(starting); 2039 gotOpaqueSplitScreenPrimary = !gotTranslucentSplitScreenPrimary; 2040 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY 2041 && gotOpaqueSplitScreenPrimary) { 2042 // Can not be visible behind another opaque stack in split-screen-primary mode. 2043 return STACK_VISIBILITY_INVISIBLE; 2044 } 2045 } else if (otherWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY 2046 && !gotOpaqueSplitScreenSecondary) { 2047 gotSplitScreenStack = true; 2048 gotTranslucentSplitScreenSecondary = other.isStackTranslucent(starting); 2049 gotOpaqueSplitScreenSecondary = !gotTranslucentSplitScreenSecondary; 2050 if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY 2051 && gotOpaqueSplitScreenSecondary) { 2052 // Can not be visible behind another opaque stack in split-screen-secondary mode. 2053 return STACK_VISIBILITY_INVISIBLE; 2054 } 2055 } 2056 if (gotOpaqueSplitScreenPrimary && gotOpaqueSplitScreenSecondary) { 2057 // Can not be visible if we are in split-screen windowing mode and both halves of 2058 // the screen are opaque. 2059 return STACK_VISIBILITY_INVISIBLE; 2060 } 2061 if (isAssistantType && gotSplitScreenStack) { 2062 // Assistant stack can't be visible behind split-screen. In addition to this not 2063 // making sense, it also works around an issue here we boost the z-order of the 2064 // assistant window surfaces in window manager whenever it is visible. 2065 return STACK_VISIBILITY_INVISIBLE; 2066 } 2067 } 2068 2069 if (!shouldBeVisible) { 2070 return STACK_VISIBILITY_INVISIBLE; 2071 } 2072 2073 // Handle cases when there can be a translucent split-screen stack on top. 2074 switch (windowingMode) { 2075 case WINDOWING_MODE_FULLSCREEN: 2076 if (gotTranslucentSplitScreenPrimary || gotTranslucentSplitScreenSecondary) { 2077 // At least one of the split-screen stacks that covers this one is translucent. 2078 return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT; 2079 } 2080 break; 2081 case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY: 2082 if (gotTranslucentSplitScreenPrimary) { 2083 // Covered by translucent primary split-screen on top. 2084 return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT; 2085 } 2086 break; 2087 case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY: 2088 if (gotTranslucentSplitScreenSecondary) { 2089 // Covered by translucent secondary split-screen on top. 2090 return STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT; 2091 } 2092 break; 2093 } 2094 2095 // Lastly - check if there is a translucent fullscreen stack on top. 2096 return gotTranslucentFullscreen ? STACK_VISIBILITY_VISIBLE_BEHIND_TRANSLUCENT 2097 : STACK_VISIBILITY_VISIBLE; 2098 } 2099 rankTaskLayers(int baseLayer)2100 final int rankTaskLayers(int baseLayer) { 2101 int layer = 0; 2102 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 2103 final TaskRecord task = mTaskHistory.get(taskNdx); 2104 ActivityRecord r = task.topRunningActivityLocked(); 2105 if (r == null || r.finishing || !r.visible) { 2106 task.mLayerRank = -1; 2107 } else { 2108 task.mLayerRank = baseLayer + layer++; 2109 } 2110 } 2111 return layer; 2112 } 2113 2114 /** 2115 * Make sure that all activities that need to be visible in the stack (that is, they 2116 * currently can be seen by the user) actually are and update their configuration. 2117 */ ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, boolean preserveWindows)2118 final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, 2119 boolean preserveWindows) { 2120 ensureActivitiesVisibleLocked(starting, configChanges, preserveWindows, 2121 true /* notifyClients */); 2122 } 2123 2124 /** 2125 * Ensure visibility with an option to also update the configuration of visible activities. 2126 * @see #ensureActivitiesVisibleLocked(ActivityRecord, int, boolean) 2127 * @see RootActivityContainer#ensureActivitiesVisible(ActivityRecord, int, boolean) 2128 */ 2129 // TODO: Should be re-worked based on the fact that each task as a stack in most cases. ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, boolean preserveWindows, boolean notifyClients)2130 final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges, 2131 boolean preserveWindows, boolean notifyClients) { 2132 mTopActivityOccludesKeyguard = false; 2133 mTopDismissingKeyguardActivity = null; 2134 mStackSupervisor.getKeyguardController().beginActivityVisibilityUpdate(); 2135 try { 2136 ActivityRecord top = topRunningActivityLocked(); 2137 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "ensureActivitiesVisible behind " + top 2138 + " configChanges=0x" + Integer.toHexString(configChanges)); 2139 if (top != null) { 2140 checkTranslucentActivityWaiting(top); 2141 } 2142 2143 // If the top activity is not fullscreen, then we need to 2144 // make sure any activities under it are now visible. 2145 boolean aboveTop = top != null; 2146 final boolean stackShouldBeVisible = shouldBeVisible(starting); 2147 boolean behindFullscreenActivity = !stackShouldBeVisible; 2148 boolean resumeNextActivity = isFocusable() && isInStackLocked(starting) == null; 2149 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 2150 final TaskRecord task = mTaskHistory.get(taskNdx); 2151 final ArrayList<ActivityRecord> activities = task.mActivities; 2152 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 2153 final ActivityRecord r = activities.get(activityNdx); 2154 if (r.finishing) { 2155 continue; 2156 } 2157 final boolean isTop = r == top; 2158 if (aboveTop && !isTop) { 2159 continue; 2160 } 2161 aboveTop = false; 2162 2163 // Check whether activity should be visible without Keyguard influence 2164 final boolean visibleIgnoringKeyguard = r.shouldBeVisibleIgnoringKeyguard( 2165 behindFullscreenActivity); 2166 final boolean reallyVisible = r.shouldBeVisible(behindFullscreenActivity); 2167 if (visibleIgnoringKeyguard) { 2168 behindFullscreenActivity = updateBehindFullscreen(!stackShouldBeVisible, 2169 behindFullscreenActivity, r); 2170 } 2171 if (reallyVisible) { 2172 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make visible? " + r 2173 + " finishing=" + r.finishing + " state=" + r.getState()); 2174 // First: if this is not the current activity being started, make 2175 // sure it matches the current configuration. 2176 if (r != starting && notifyClients) { 2177 r.ensureActivityConfiguration(0 /* globalChanges */, preserveWindows, 2178 true /* ignoreStopState */); 2179 } 2180 2181 if (!r.attachedToProcess()) { 2182 if (makeVisibleAndRestartIfNeeded(starting, configChanges, isTop, 2183 resumeNextActivity, r)) { 2184 if (activityNdx >= activities.size()) { 2185 // Record may be removed if its process needs to restart. 2186 activityNdx = activities.size() - 1; 2187 } else { 2188 resumeNextActivity = false; 2189 } 2190 } 2191 } else if (r.visible) { 2192 // If this activity is already visible, then there is nothing to do here. 2193 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, 2194 "Skipping: already visible at " + r); 2195 2196 if (r.mClientVisibilityDeferred && notifyClients) { 2197 r.makeClientVisible(); 2198 } 2199 2200 if (r.handleAlreadyVisible()) { 2201 resumeNextActivity = false; 2202 } 2203 2204 if (notifyClients) { 2205 r.makeActiveIfNeeded(starting); 2206 } 2207 } else { 2208 r.makeVisibleIfNeeded(starting, notifyClients); 2209 } 2210 // Aggregate current change flags. 2211 configChanges |= r.configChangeFlags; 2212 } else { 2213 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Make invisible? " + r 2214 + " finishing=" + r.finishing + " state=" + r.getState() 2215 + " stackShouldBeVisible=" + stackShouldBeVisible 2216 + " behindFullscreenActivity=" + behindFullscreenActivity 2217 + " mLaunchTaskBehind=" + r.mLaunchTaskBehind); 2218 makeInvisible(r); 2219 } 2220 } 2221 final int windowingMode = getWindowingMode(); 2222 if (windowingMode == WINDOWING_MODE_FREEFORM) { 2223 // The visibility of tasks and the activities they contain in freeform stack are 2224 // determined individually unlike other stacks where the visibility or fullscreen 2225 // status of an activity in a previous task affects other. 2226 behindFullscreenActivity = !stackShouldBeVisible; 2227 } else if (isActivityTypeHome()) { 2228 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Home task: at " + task 2229 + " stackShouldBeVisible=" + stackShouldBeVisible 2230 + " behindFullscreenActivity=" + behindFullscreenActivity); 2231 // No other task in the home stack should be visible behind the home activity. 2232 // Home activities is usually a translucent activity with the wallpaper behind 2233 // them. However, when they don't have the wallpaper behind them, we want to 2234 // show activities in the next application stack behind them vs. another 2235 // task in the home stack like recents. 2236 behindFullscreenActivity = true; 2237 } 2238 } 2239 2240 if (mTranslucentActivityWaiting != null && 2241 mUndrawnActivitiesBelowTopTranslucent.isEmpty()) { 2242 // Nothing is getting drawn or everything was already visible, don't wait for timeout. 2243 notifyActivityDrawnLocked(null); 2244 } 2245 } finally { 2246 mStackSupervisor.getKeyguardController().endActivityVisibilityUpdate(); 2247 } 2248 } 2249 addStartingWindowsForVisibleActivities(boolean taskSwitch)2250 void addStartingWindowsForVisibleActivities(boolean taskSwitch) { 2251 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 2252 mTaskHistory.get(taskNdx).addStartingWindowsForVisibleActivities(taskSwitch); 2253 } 2254 } 2255 2256 /** 2257 * @return true if the top visible activity wants to occlude the Keyguard, false otherwise 2258 */ topActivityOccludesKeyguard()2259 boolean topActivityOccludesKeyguard() { 2260 return mTopActivityOccludesKeyguard; 2261 } 2262 2263 /** 2264 * Returns true if this stack should be resized to match the bounds specified by 2265 * {@link ActivityOptions#setLaunchBounds} when launching an activity into the stack. 2266 */ resizeStackWithLaunchBounds()2267 boolean resizeStackWithLaunchBounds() { 2268 return inPinnedWindowingMode(); 2269 } 2270 2271 @Override supportsSplitScreenWindowingMode()2272 public boolean supportsSplitScreenWindowingMode() { 2273 final TaskRecord topTask = topTask(); 2274 return super.supportsSplitScreenWindowingMode() 2275 && (topTask == null || topTask.supportsSplitScreenWindowingMode()); 2276 } 2277 2278 /** @return True if the resizing of the primary-split-screen stack affects this stack size. */ affectedBySplitScreenResize()2279 boolean affectedBySplitScreenResize() { 2280 if (!supportsSplitScreenWindowingMode()) { 2281 return false; 2282 } 2283 final int windowingMode = getWindowingMode(); 2284 return windowingMode != WINDOWING_MODE_FREEFORM && windowingMode != WINDOWING_MODE_PINNED; 2285 } 2286 2287 /** 2288 * @return the top most visible activity that wants to dismiss Keyguard 2289 */ getTopDismissingKeyguardActivity()2290 ActivityRecord getTopDismissingKeyguardActivity() { 2291 return mTopDismissingKeyguardActivity; 2292 } 2293 2294 /** 2295 * Checks whether {@param r} should be visible depending on Keyguard state and updates 2296 * {@link #mTopActivityOccludesKeyguard} and {@link #mTopDismissingKeyguardActivity} if 2297 * necessary. 2298 * 2299 * @return true if {@param r} is visible taken Keyguard state into account, false otherwise 2300 */ checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible, boolean isTop)2301 boolean checkKeyguardVisibility(ActivityRecord r, boolean shouldBeVisible, boolean isTop) { 2302 final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY; 2303 final boolean keyguardOrAodShowing = mStackSupervisor.getKeyguardController() 2304 .isKeyguardOrAodShowing(displayId); 2305 final boolean keyguardLocked = mStackSupervisor.getKeyguardController().isKeyguardLocked(); 2306 final boolean showWhenLocked = r.canShowWhenLocked(); 2307 final boolean dismissKeyguard = r.mAppWindowToken != null 2308 && r.mAppWindowToken.containsDismissKeyguardWindow(); 2309 if (shouldBeVisible) { 2310 if (dismissKeyguard && mTopDismissingKeyguardActivity == null) { 2311 mTopDismissingKeyguardActivity = r; 2312 } 2313 2314 // Only the top activity may control occluded, as we can't occlude the Keyguard if the 2315 // top app doesn't want to occlude it. 2316 if (isTop) { 2317 mTopActivityOccludesKeyguard |= showWhenLocked; 2318 } 2319 2320 final boolean canShowWithKeyguard = canShowWithInsecureKeyguard() 2321 && mStackSupervisor.getKeyguardController().canDismissKeyguard(); 2322 if (canShowWithKeyguard) { 2323 return true; 2324 } 2325 } 2326 if (keyguardOrAodShowing) { 2327 // If keyguard is showing, nothing is visible, except if we are able to dismiss Keyguard 2328 // right away and AOD isn't visible. 2329 return shouldBeVisible && mStackSupervisor.getKeyguardController() 2330 .canShowActivityWhileKeyguardShowing(r, dismissKeyguard); 2331 } else if (keyguardLocked) { 2332 return shouldBeVisible && mStackSupervisor.getKeyguardController().canShowWhileOccluded( 2333 dismissKeyguard, showWhenLocked); 2334 } else { 2335 return shouldBeVisible; 2336 } 2337 } 2338 2339 /** 2340 * Check if the display to which this stack is attached has 2341 * {@link Display#FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD} applied. 2342 */ canShowWithInsecureKeyguard()2343 boolean canShowWithInsecureKeyguard() { 2344 final ActivityDisplay activityDisplay = getDisplay(); 2345 if (activityDisplay == null) { 2346 throw new IllegalStateException("Stack is not attached to any display, stackId=" 2347 + mStackId); 2348 } 2349 2350 final int flags = activityDisplay.mDisplay.getFlags(); 2351 return (flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0; 2352 } 2353 checkTranslucentActivityWaiting(ActivityRecord top)2354 private void checkTranslucentActivityWaiting(ActivityRecord top) { 2355 if (mTranslucentActivityWaiting != top) { 2356 mUndrawnActivitiesBelowTopTranslucent.clear(); 2357 if (mTranslucentActivityWaiting != null) { 2358 // Call the callback with a timeout indication. 2359 notifyActivityDrawnLocked(null); 2360 mTranslucentActivityWaiting = null; 2361 } 2362 mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG); 2363 } 2364 } 2365 makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges, boolean isTop, boolean andResume, ActivityRecord r)2366 private boolean makeVisibleAndRestartIfNeeded(ActivityRecord starting, int configChanges, 2367 boolean isTop, boolean andResume, ActivityRecord r) { 2368 // We need to make sure the app is running if it's the top, or it is just made visible from 2369 // invisible. If the app is already visible, it must have died while it was visible. In this 2370 // case, we'll show the dead window but will not restart the app. Otherwise we could end up 2371 // thrashing. 2372 if (isTop || !r.visible) { 2373 // This activity needs to be visible, but isn't even running... 2374 // get it started and resume if no other stack in this stack is resumed. 2375 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Start and freeze screen for " + r); 2376 if (r != starting) { 2377 r.startFreezingScreenLocked(r.app, configChanges); 2378 } 2379 if (!r.visible || r.mLaunchTaskBehind) { 2380 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Starting and making visible: " + r); 2381 r.setVisible(true); 2382 } 2383 if (r != starting) { 2384 // We should not resume activities that being launched behind because these 2385 // activities are actually behind other fullscreen activities, but still required 2386 // to be visible (such as performing Recents animation). 2387 mStackSupervisor.startSpecificActivityLocked(r, andResume && !r.mLaunchTaskBehind, 2388 true /* checkConfig */); 2389 return true; 2390 } 2391 } 2392 return false; 2393 } 2394 2395 // TODO: Should probably be moved into ActivityRecord. makeInvisible(ActivityRecord r)2396 private void makeInvisible(ActivityRecord r) { 2397 if (!r.visible) { 2398 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Already invisible: " + r); 2399 return; 2400 } 2401 // Now for any activities that aren't visible to the user, make sure they no longer are 2402 // keeping the screen frozen. 2403 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Making invisible: " + r + " " + r.getState()); 2404 try { 2405 final boolean canEnterPictureInPicture = r.checkEnterPictureInPictureState( 2406 "makeInvisible", true /* beforeStopping */); 2407 // Defer telling the client it is hidden if it can enter Pip and isn't current paused, 2408 // stopped or stopping. This gives it a chance to enter Pip in onPause(). 2409 // TODO: There is still a question surrounding activities in multi-window mode that want 2410 // to enter Pip after they are paused, but are still visible. I they should be okay to 2411 // enter Pip in those cases, but not "auto-Pip" which is what this condition covers and 2412 // the current contract for "auto-Pip" is that the app should enter it before onPause 2413 // returns. Just need to confirm this reasoning makes sense. 2414 final boolean deferHidingClient = canEnterPictureInPicture 2415 && !r.isState(STOPPING, STOPPED, PAUSED); 2416 r.setDeferHidingClient(deferHidingClient); 2417 r.setVisible(false); 2418 2419 switch (r.getState()) { 2420 case STOPPING: 2421 case STOPPED: 2422 if (r.attachedToProcess()) { 2423 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, 2424 "Scheduling invisibility: " + r); 2425 mService.getLifecycleManager().scheduleTransaction(r.app.getThread(), 2426 r.appToken, WindowVisibilityItem.obtain(false /* showWindow */)); 2427 } 2428 2429 // Reset the flag indicating that an app can enter picture-in-picture once the 2430 // activity is hidden 2431 r.supportsEnterPipOnTaskSwitch = false; 2432 break; 2433 2434 case INITIALIZING: 2435 case RESUMED: 2436 case PAUSING: 2437 case PAUSED: 2438 addToStopping(r, true /* scheduleIdle */, 2439 canEnterPictureInPicture /* idleDelayed */, "makeInvisible"); 2440 break; 2441 2442 default: 2443 break; 2444 } 2445 } catch (Exception e) { 2446 // Just skip on any failure; we'll make it visible when it next restarts. 2447 Slog.w(TAG, "Exception thrown making hidden: " + r.intent.getComponent(), e); 2448 } 2449 } 2450 updateBehindFullscreen(boolean stackInvisible, boolean behindFullscreenActivity, ActivityRecord r)2451 private boolean updateBehindFullscreen(boolean stackInvisible, boolean behindFullscreenActivity, 2452 ActivityRecord r) { 2453 if (r.fullscreen) { 2454 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, "Fullscreen: at " + r 2455 + " stackInvisible=" + stackInvisible 2456 + " behindFullscreenActivity=" + behindFullscreenActivity); 2457 // At this point, nothing else needs to be shown in this task. 2458 behindFullscreenActivity = true; 2459 } 2460 return behindFullscreenActivity; 2461 } 2462 convertActivityToTranslucent(ActivityRecord r)2463 void convertActivityToTranslucent(ActivityRecord r) { 2464 mTranslucentActivityWaiting = r; 2465 mUndrawnActivitiesBelowTopTranslucent.clear(); 2466 mHandler.sendEmptyMessageDelayed(TRANSLUCENT_TIMEOUT_MSG, TRANSLUCENT_CONVERSION_TIMEOUT); 2467 } 2468 clearOtherAppTimeTrackers(AppTimeTracker except)2469 void clearOtherAppTimeTrackers(AppTimeTracker except) { 2470 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 2471 final TaskRecord task = mTaskHistory.get(taskNdx); 2472 final ArrayList<ActivityRecord> activities = task.mActivities; 2473 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 2474 final ActivityRecord r = activities.get(activityNdx); 2475 if ( r.appTimeTracker != except) { 2476 r.appTimeTracker = null; 2477 } 2478 } 2479 } 2480 } 2481 2482 /** 2483 * Called as activities below the top translucent activity are redrawn. When the last one is 2484 * redrawn notify the top activity by calling 2485 * {@link Activity#onTranslucentConversionComplete}. 2486 * 2487 * @param r The most recent background activity to be drawn. Or, if r is null then a timeout 2488 * occurred and the activity will be notified immediately. 2489 */ notifyActivityDrawnLocked(ActivityRecord r)2490 void notifyActivityDrawnLocked(ActivityRecord r) { 2491 if ((r == null) 2492 || (mUndrawnActivitiesBelowTopTranslucent.remove(r) && 2493 mUndrawnActivitiesBelowTopTranslucent.isEmpty())) { 2494 // The last undrawn activity below the top has just been drawn. If there is an 2495 // opaque activity at the top, notify it that it can become translucent safely now. 2496 final ActivityRecord waitingActivity = mTranslucentActivityWaiting; 2497 mTranslucentActivityWaiting = null; 2498 mUndrawnActivitiesBelowTopTranslucent.clear(); 2499 mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG); 2500 2501 if (waitingActivity != null) { 2502 mWindowManager.setWindowOpaque(waitingActivity.appToken, false); 2503 if (waitingActivity.attachedToProcess()) { 2504 try { 2505 waitingActivity.app.getThread().scheduleTranslucentConversionComplete( 2506 waitingActivity.appToken, r != null); 2507 } catch (RemoteException e) { 2508 } 2509 } 2510 } 2511 } 2512 } 2513 2514 /** If any activities below the top running one are in the INITIALIZING state and they have a 2515 * starting window displayed then remove that starting window. It is possible that the activity 2516 * in this state will never resumed in which case that starting window will be orphaned. */ cancelInitializingActivities()2517 void cancelInitializingActivities() { 2518 final ActivityRecord topActivity = topRunningActivityLocked(); 2519 boolean aboveTop = true; 2520 // We don't want to clear starting window for activities that aren't behind fullscreen 2521 // activities as we need to display their starting window until they are done initializing. 2522 boolean behindFullscreenActivity = false; 2523 2524 if (!shouldBeVisible(null)) { 2525 // The stack is not visible, so no activity in it should be displaying a starting 2526 // window. Mark all activities below top and behind fullscreen. 2527 aboveTop = false; 2528 behindFullscreenActivity = true; 2529 } 2530 2531 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 2532 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 2533 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 2534 final ActivityRecord r = activities.get(activityNdx); 2535 if (aboveTop) { 2536 if (r == topActivity) { 2537 aboveTop = false; 2538 } 2539 behindFullscreenActivity |= r.fullscreen; 2540 continue; 2541 } 2542 2543 r.removeOrphanedStartingWindow(behindFullscreenActivity); 2544 behindFullscreenActivity |= r.fullscreen; 2545 } 2546 } 2547 } 2548 2549 /** 2550 * Ensure that the top activity in the stack is resumed. 2551 * 2552 * @param prev The previously resumed activity, for when in the process 2553 * of pausing; can be null to call from elsewhere. 2554 * @param options Activity options. 2555 * 2556 * @return Returns true if something is being resumed, or false if 2557 * nothing happened. 2558 * 2559 * NOTE: It is not safe to call this method directly as it can cause an activity in a 2560 * non-focused stack to be resumed. 2561 * Use {@link RootActivityContainer#resumeFocusedStacksTopActivities} to resume the 2562 * right activity for the current system state. 2563 */ 2564 @GuardedBy("mService") resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options)2565 boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) { 2566 if (mInResumeTopActivity) { 2567 // Don't even start recursing. 2568 return false; 2569 } 2570 2571 boolean result = false; 2572 try { 2573 // Protect against recursion. 2574 mInResumeTopActivity = true; 2575 result = resumeTopActivityInnerLocked(prev, options); 2576 2577 // When resuming the top activity, it may be necessary to pause the top activity (for 2578 // example, returning to the lock screen. We suppress the normal pause logic in 2579 // {@link #resumeTopActivityUncheckedLocked}, since the top activity is resumed at the 2580 // end. We call the {@link ActivityStackSupervisor#checkReadyForSleepLocked} again here 2581 // to ensure any necessary pause logic occurs. In the case where the Activity will be 2582 // shown regardless of the lock screen, the call to 2583 // {@link ActivityStackSupervisor#checkReadyForSleepLocked} is skipped. 2584 final ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */); 2585 if (next == null || !next.canTurnScreenOn()) { 2586 checkReadyForSleep(); 2587 } 2588 } finally { 2589 mInResumeTopActivity = false; 2590 } 2591 2592 return result; 2593 } 2594 2595 /** 2596 * Returns the currently resumed activity. 2597 */ getResumedActivity()2598 protected ActivityRecord getResumedActivity() { 2599 return mResumedActivity; 2600 } 2601 setResumedActivity(ActivityRecord r, String reason)2602 private void setResumedActivity(ActivityRecord r, String reason) { 2603 if (mResumedActivity == r) { 2604 return; 2605 } 2606 2607 if (DEBUG_STACK) Slog.d(TAG_STACK, "setResumedActivity stack:" + this + " + from: " 2608 + mResumedActivity + " to:" + r + " reason:" + reason); 2609 mResumedActivity = r; 2610 mStackSupervisor.updateTopResumedActivityIfNeeded(); 2611 } 2612 2613 @GuardedBy("mService") resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options)2614 private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) { 2615 if (!mService.isBooting() && !mService.isBooted()) { 2616 // Not ready yet! 2617 return false; 2618 } 2619 2620 // Find the next top-most activity to resume in this stack that is not finishing and is 2621 // focusable. If it is not focusable, we will fall into the case below to resume the 2622 // top activity in the next focusable task. 2623 ActivityRecord next = topRunningActivityLocked(true /* focusableOnly */); 2624 2625 final boolean hasRunningActivity = next != null; 2626 2627 // TODO: Maybe this entire condition can get removed? 2628 if (hasRunningActivity && !isAttached()) { 2629 return false; 2630 } 2631 2632 mRootActivityContainer.cancelInitializingActivities(); 2633 2634 // Remember how we'll process this pause/resume situation, and ensure 2635 // that the state is reset however we wind up proceeding. 2636 boolean userLeaving = mStackSupervisor.mUserLeaving; 2637 mStackSupervisor.mUserLeaving = false; 2638 2639 if (!hasRunningActivity) { 2640 // There are no activities left in the stack, let's look somewhere else. 2641 return resumeNextFocusableActivityWhenStackIsEmpty(prev, options); 2642 } 2643 2644 next.delayedResume = false; 2645 final ActivityDisplay display = getDisplay(); 2646 2647 // If the top activity is the resumed one, nothing to do. 2648 if (mResumedActivity == next && next.isState(RESUMED) 2649 && display.allResumedActivitiesComplete()) { 2650 // Make sure we have executed any pending transitions, since there 2651 // should be nothing left to do at this point. 2652 executeAppTransition(options); 2653 if (DEBUG_STATES) Slog.d(TAG_STATES, 2654 "resumeTopActivityLocked: Top activity resumed " + next); 2655 return false; 2656 } 2657 2658 if (!next.canResumeByCompat()) { 2659 return false; 2660 } 2661 2662 // If we are sleeping, and there is no resumed activity, and the top 2663 // activity is paused, well that is the state we want. 2664 if (shouldSleepOrShutDownActivities() 2665 && mLastPausedActivity == next 2666 && mRootActivityContainer.allPausedActivitiesComplete()) { 2667 // If the current top activity may be able to occlude keyguard but the occluded state 2668 // has not been set, update visibility and check again if we should continue to resume. 2669 boolean nothingToResume = true; 2670 if (!mService.mShuttingDown) { 2671 final boolean canShowWhenLocked = !mTopActivityOccludesKeyguard 2672 && next.canShowWhenLocked(); 2673 final boolean mayDismissKeyguard = mTopDismissingKeyguardActivity != next 2674 && next.mAppWindowToken != null 2675 && next.mAppWindowToken.containsDismissKeyguardWindow(); 2676 2677 if (canShowWhenLocked || mayDismissKeyguard) { 2678 ensureActivitiesVisibleLocked(null /* starting */, 0 /* configChanges */, 2679 !PRESERVE_WINDOWS); 2680 nothingToResume = shouldSleepActivities(); 2681 } 2682 } 2683 if (nothingToResume) { 2684 // Make sure we have executed any pending transitions, since there 2685 // should be nothing left to do at this point. 2686 executeAppTransition(options); 2687 if (DEBUG_STATES) Slog.d(TAG_STATES, 2688 "resumeTopActivityLocked: Going to sleep and all paused"); 2689 return false; 2690 } 2691 } 2692 2693 // Make sure that the user who owns this activity is started. If not, 2694 // we will just leave it as is because someone should be bringing 2695 // another user's activities to the top of the stack. 2696 if (!mService.mAmInternal.hasStartedUserState(next.mUserId)) { 2697 Slog.w(TAG, "Skipping resume of top activity " + next 2698 + ": user " + next.mUserId + " is stopped"); 2699 return false; 2700 } 2701 2702 // The activity may be waiting for stop, but that is no longer 2703 // appropriate for it. 2704 mStackSupervisor.mStoppingActivities.remove(next); 2705 mStackSupervisor.mGoingToSleepActivities.remove(next); 2706 next.sleeping = false; 2707 2708 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resuming " + next); 2709 2710 // If we are currently pausing an activity, then don't do anything until that is done. 2711 if (!mRootActivityContainer.allPausedActivitiesComplete()) { 2712 if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG_PAUSE, 2713 "resumeTopActivityLocked: Skip resume: some activity pausing."); 2714 2715 return false; 2716 } 2717 2718 mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid); 2719 2720 boolean lastResumedCanPip = false; 2721 ActivityRecord lastResumed = null; 2722 final ActivityStack lastFocusedStack = display.getLastFocusedStack(); 2723 if (lastFocusedStack != null && lastFocusedStack != this) { 2724 // So, why aren't we using prev here??? See the param comment on the method. prev doesn't 2725 // represent the last resumed activity. However, the last focus stack does if it isn't null. 2726 lastResumed = lastFocusedStack.mResumedActivity; 2727 if (userLeaving && inMultiWindowMode() && lastFocusedStack.shouldBeVisible(next)) { 2728 // The user isn't leaving if this stack is the multi-window mode and the last 2729 // focused stack should still be visible. 2730 if(DEBUG_USER_LEAVING) Slog.i(TAG_USER_LEAVING, "Overriding userLeaving to false" 2731 + " next=" + next + " lastResumed=" + lastResumed); 2732 userLeaving = false; 2733 } 2734 lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState( 2735 "resumeTopActivity", userLeaving /* beforeStopping */); 2736 } 2737 // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity 2738 // to be paused, while at the same time resuming the new resume activity only if the 2739 // previous activity can't go into Pip since we want to give Pip activities a chance to 2740 // enter Pip before resuming the next activity. 2741 final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0 2742 && !lastResumedCanPip; 2743 2744 boolean pausing = getDisplay().pauseBackStacks(userLeaving, next, false); 2745 if (mResumedActivity != null) { 2746 if (DEBUG_STATES) Slog.d(TAG_STATES, 2747 "resumeTopActivityLocked: Pausing " + mResumedActivity); 2748 pausing |= startPausingLocked(userLeaving, false, next, false); 2749 } 2750 if (pausing && !resumeWhilePausing) { 2751 if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES, 2752 "resumeTopActivityLocked: Skip resume: need to start pausing"); 2753 // At this point we want to put the upcoming activity's process 2754 // at the top of the LRU list, since we know we will be needing it 2755 // very soon and it would be a waste to let it get killed if it 2756 // happens to be sitting towards the end. 2757 if (next.attachedToProcess()) { 2758 next.app.updateProcessInfo(false /* updateServiceConnectionActivities */, 2759 true /* activityChange */, false /* updateOomAdj */); 2760 } 2761 if (lastResumed != null) { 2762 lastResumed.setWillCloseOrEnterPip(true); 2763 } 2764 return true; 2765 } else if (mResumedActivity == next && next.isState(RESUMED) 2766 && display.allResumedActivitiesComplete()) { 2767 // It is possible for the activity to be resumed when we paused back stacks above if the 2768 // next activity doesn't have to wait for pause to complete. 2769 // So, nothing else to-do except: 2770 // Make sure we have executed any pending transitions, since there 2771 // should be nothing left to do at this point. 2772 executeAppTransition(options); 2773 if (DEBUG_STATES) Slog.d(TAG_STATES, 2774 "resumeTopActivityLocked: Top activity resumed (dontWaitForPause) " + next); 2775 return true; 2776 } 2777 2778 // If the most recent activity was noHistory but was only stopped rather 2779 // than stopped+finished because the device went to sleep, we need to make 2780 // sure to finish it as we're making a new activity topmost. 2781 if (shouldSleepActivities() && mLastNoHistoryActivity != null && 2782 !mLastNoHistoryActivity.finishing) { 2783 if (DEBUG_STATES) Slog.d(TAG_STATES, 2784 "no-history finish of " + mLastNoHistoryActivity + " on new resume"); 2785 requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED, 2786 null, "resume-no-history", false); 2787 mLastNoHistoryActivity = null; 2788 } 2789 2790 if (prev != null && prev != next && next.nowVisible) { 2791 2792 // The next activity is already visible, so hide the previous 2793 // activity's windows right now so we can show the new one ASAP. 2794 // We only do this if the previous is finishing, which should mean 2795 // it is on top of the one being resumed so hiding it quickly 2796 // is good. Otherwise, we want to do the normal route of allowing 2797 // the resumed activity to be shown so we can decide if the 2798 // previous should actually be hidden depending on whether the 2799 // new one is found to be full-screen or not. 2800 if (prev.finishing) { 2801 prev.setVisibility(false); 2802 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, 2803 "Not waiting for visible to hide: " + prev 2804 + ", nowVisible=" + next.nowVisible); 2805 } else { 2806 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, 2807 "Previous already visible but still waiting to hide: " + prev 2808 + ", nowVisible=" + next.nowVisible); 2809 } 2810 2811 } 2812 2813 // Launching this app's activity, make sure the app is no longer 2814 // considered stopped. 2815 try { 2816 AppGlobals.getPackageManager().setPackageStoppedState( 2817 next.packageName, false, next.mUserId); /* TODO: Verify if correct userid */ 2818 } catch (RemoteException e1) { 2819 } catch (IllegalArgumentException e) { 2820 Slog.w(TAG, "Failed trying to unstop package " 2821 + next.packageName + ": " + e); 2822 } 2823 2824 // We are starting up the next activity, so tell the window manager 2825 // that the previous one will be hidden soon. This way it can know 2826 // to ignore it when computing the desired screen orientation. 2827 boolean anim = true; 2828 final DisplayContent dc = getDisplay().mDisplayContent; 2829 if (prev != null) { 2830 if (prev.finishing) { 2831 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, 2832 "Prepare close transition: prev=" + prev); 2833 if (mStackSupervisor.mNoAnimActivities.contains(prev)) { 2834 anim = false; 2835 dc.prepareAppTransition(TRANSIT_NONE, false); 2836 } else { 2837 dc.prepareAppTransition( 2838 prev.getTaskRecord() == next.getTaskRecord() ? TRANSIT_ACTIVITY_CLOSE 2839 : TRANSIT_TASK_CLOSE, false); 2840 } 2841 prev.setVisibility(false); 2842 } else { 2843 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, 2844 "Prepare open transition: prev=" + prev); 2845 if (mStackSupervisor.mNoAnimActivities.contains(next)) { 2846 anim = false; 2847 dc.prepareAppTransition(TRANSIT_NONE, false); 2848 } else { 2849 dc.prepareAppTransition( 2850 prev.getTaskRecord() == next.getTaskRecord() ? TRANSIT_ACTIVITY_OPEN 2851 : next.mLaunchTaskBehind ? TRANSIT_TASK_OPEN_BEHIND 2852 : TRANSIT_TASK_OPEN, false); 2853 } 2854 } 2855 } else { 2856 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare open transition: no previous"); 2857 if (mStackSupervisor.mNoAnimActivities.contains(next)) { 2858 anim = false; 2859 dc.prepareAppTransition(TRANSIT_NONE, false); 2860 } else { 2861 dc.prepareAppTransition(TRANSIT_ACTIVITY_OPEN, false); 2862 } 2863 } 2864 2865 if (anim) { 2866 next.applyOptionsLocked(); 2867 } else { 2868 next.clearOptionsLocked(); 2869 } 2870 2871 mStackSupervisor.mNoAnimActivities.clear(); 2872 2873 if (next.attachedToProcess()) { 2874 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Resume running: " + next 2875 + " stopped=" + next.stopped + " visible=" + next.visible); 2876 2877 // If the previous activity is translucent, force a visibility update of 2878 // the next activity, so that it's added to WM's opening app list, and 2879 // transition animation can be set up properly. 2880 // For example, pressing Home button with a translucent activity in focus. 2881 // Launcher is already visible in this case. If we don't add it to opening 2882 // apps, maybeUpdateTransitToWallpaper() will fail to identify this as a 2883 // TRANSIT_WALLPAPER_OPEN animation, and run some funny animation. 2884 final boolean lastActivityTranslucent = lastFocusedStack != null 2885 && (lastFocusedStack.inMultiWindowMode() 2886 || (lastFocusedStack.mLastPausedActivity != null 2887 && !lastFocusedStack.mLastPausedActivity.fullscreen)); 2888 2889 // This activity is now becoming visible. 2890 if (!next.visible || next.stopped || lastActivityTranslucent) { 2891 next.setVisibility(true); 2892 } 2893 2894 // schedule launch ticks to collect information about slow apps. 2895 next.startLaunchTickingLocked(); 2896 2897 ActivityRecord lastResumedActivity = 2898 lastFocusedStack == null ? null : lastFocusedStack.mResumedActivity; 2899 final ActivityState lastState = next.getState(); 2900 2901 mService.updateCpuStats(); 2902 2903 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to RESUMED: " + next 2904 + " (in existing)"); 2905 2906 next.setState(RESUMED, "resumeTopActivityInnerLocked"); 2907 2908 next.app.updateProcessInfo(false /* updateServiceConnectionActivities */, 2909 true /* activityChange */, true /* updateOomAdj */); 2910 updateLRUListLocked(next); 2911 2912 // Have the window manager re-evaluate the orientation of 2913 // the screen based on the new activity order. 2914 boolean notUpdated = true; 2915 2916 // Activity should also be visible if set mLaunchTaskBehind to true (see 2917 // ActivityRecord#shouldBeVisibleIgnoringKeyguard()). 2918 if (shouldBeVisible(next)) { 2919 // We have special rotation behavior when here is some active activity that 2920 // requests specific orientation or Keyguard is locked. Make sure all activity 2921 // visibilities are set correctly as well as the transition is updated if needed 2922 // to get the correct rotation behavior. Otherwise the following call to update 2923 // the orientation may cause incorrect configurations delivered to client as a 2924 // result of invisible window resize. 2925 // TODO: Remove this once visibilities are set correctly immediately when 2926 // starting an activity. 2927 notUpdated = !mRootActivityContainer.ensureVisibilityAndConfig(next, mDisplayId, 2928 true /* markFrozenIfConfigChanged */, false /* deferResume */); 2929 } 2930 2931 if (notUpdated) { 2932 // The configuration update wasn't able to keep the existing 2933 // instance of the activity, and instead started a new one. 2934 // We should be all done, but let's just make sure our activity 2935 // is still at the top and schedule another run if something 2936 // weird happened. 2937 ActivityRecord nextNext = topRunningActivityLocked(); 2938 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG_STATES, 2939 "Activity config changed during resume: " + next 2940 + ", new next: " + nextNext); 2941 if (nextNext != next) { 2942 // Do over! 2943 mStackSupervisor.scheduleResumeTopActivities(); 2944 } 2945 if (!next.visible || next.stopped) { 2946 next.setVisibility(true); 2947 } 2948 next.completeResumeLocked(); 2949 return true; 2950 } 2951 2952 try { 2953 final ClientTransaction transaction = 2954 ClientTransaction.obtain(next.app.getThread(), next.appToken); 2955 // Deliver all pending results. 2956 ArrayList<ResultInfo> a = next.results; 2957 if (a != null) { 2958 final int N = a.size(); 2959 if (!next.finishing && N > 0) { 2960 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, 2961 "Delivering results to " + next + ": " + a); 2962 transaction.addCallback(ActivityResultItem.obtain(a)); 2963 } 2964 } 2965 2966 if (next.newIntents != null) { 2967 transaction.addCallback( 2968 NewIntentItem.obtain(next.newIntents, true /* resume */)); 2969 } 2970 2971 // Well the app will no longer be stopped. 2972 // Clear app token stopped state in window manager if needed. 2973 next.notifyAppResumed(next.stopped); 2974 2975 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY, next.mUserId, 2976 System.identityHashCode(next), next.getTaskRecord().taskId, 2977 next.shortComponentName); 2978 2979 next.sleeping = false; 2980 mService.getAppWarningsLocked().onResumeActivity(next); 2981 next.app.setPendingUiCleanAndForceProcessStateUpTo(mService.mTopProcessState); 2982 next.clearOptionsLocked(); 2983 transaction.setLifecycleStateRequest( 2984 ResumeActivityItem.obtain(next.app.getReportedProcState(), 2985 getDisplay().mDisplayContent.isNextTransitionForward())); 2986 mService.getLifecycleManager().scheduleTransaction(transaction); 2987 2988 if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Resumed " 2989 + next); 2990 } catch (Exception e) { 2991 // Whoops, need to restart this activity! 2992 if (DEBUG_STATES) Slog.v(TAG_STATES, "Resume failed; resetting state to " 2993 + lastState + ": " + next); 2994 next.setState(lastState, "resumeTopActivityInnerLocked"); 2995 2996 // lastResumedActivity being non-null implies there is a lastStack present. 2997 if (lastResumedActivity != null) { 2998 lastResumedActivity.setState(RESUMED, "resumeTopActivityInnerLocked"); 2999 } 3000 3001 Slog.i(TAG, "Restarting because process died: " + next); 3002 if (!next.hasBeenLaunched) { 3003 next.hasBeenLaunched = true; 3004 } else if (SHOW_APP_STARTING_PREVIEW && lastFocusedStack != null 3005 && lastFocusedStack.isTopStackOnDisplay()) { 3006 next.showStartingWindow(null /* prev */, false /* newTask */, 3007 false /* taskSwitch */); 3008 } 3009 mStackSupervisor.startSpecificActivityLocked(next, true, false); 3010 return true; 3011 } 3012 3013 // From this point on, if something goes wrong there is no way 3014 // to recover the activity. 3015 try { 3016 next.completeResumeLocked(); 3017 } catch (Exception e) { 3018 // If any exception gets thrown, toss away this 3019 // activity and try the next one. 3020 Slog.w(TAG, "Exception thrown during resume of " + next, e); 3021 requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null, 3022 "resume-exception", true); 3023 return true; 3024 } 3025 } else { 3026 // Whoops, need to restart this activity! 3027 if (!next.hasBeenLaunched) { 3028 next.hasBeenLaunched = true; 3029 } else { 3030 if (SHOW_APP_STARTING_PREVIEW) { 3031 next.showStartingWindow(null /* prev */, false /* newTask */, 3032 false /* taskSwich */); 3033 } 3034 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next); 3035 } 3036 if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next); 3037 mStackSupervisor.startSpecificActivityLocked(next, true, true); 3038 } 3039 3040 return true; 3041 } 3042 3043 /** 3044 * Resume the next eligible activity in a focusable stack when this one does not have any 3045 * running activities left. The focus will be adjusted to the next focusable stack and 3046 * top running activities will be resumed in all focusable stacks. However, if the current stack 3047 * is a home stack - we have to keep it focused, start and resume a home activity on the current 3048 * display instead to make sure that the display is not empty. 3049 */ resumeNextFocusableActivityWhenStackIsEmpty(ActivityRecord prev, ActivityOptions options)3050 private boolean resumeNextFocusableActivityWhenStackIsEmpty(ActivityRecord prev, 3051 ActivityOptions options) { 3052 final String reason = "noMoreActivities"; 3053 3054 if (!isActivityTypeHome()) { 3055 final ActivityStack nextFocusedStack = adjustFocusToNextFocusableStack(reason); 3056 if (nextFocusedStack != null) { 3057 // Try to move focus to the next visible stack with a running activity if this 3058 // stack is not covering the entire screen or is on a secondary display with no home 3059 // stack. 3060 return mRootActivityContainer.resumeFocusedStacksTopActivities(nextFocusedStack, 3061 prev, null /* targetOptions */); 3062 } 3063 } 3064 3065 // If the current stack is a home stack, or if focus didn't switch to a different stack - 3066 // just start up the Launcher... 3067 ActivityOptions.abort(options); 3068 if (DEBUG_STATES) Slog.d(TAG_STATES, 3069 "resumeNextFocusableActivityWhenStackIsEmpty: " + reason + ", go home"); 3070 return mRootActivityContainer.resumeHomeActivity(prev, reason, mDisplayId); 3071 } 3072 3073 /** Returns the position the input task should be placed in this stack. */ getAdjustedPositionForTask(TaskRecord task, int suggestedPosition, ActivityRecord starting)3074 int getAdjustedPositionForTask(TaskRecord task, int suggestedPosition, 3075 ActivityRecord starting) { 3076 3077 int maxPosition = mTaskHistory.size(); 3078 if ((starting != null && starting.okToShowLocked()) 3079 || (starting == null && task.okToShowLocked())) { 3080 // If the task or starting activity can be shown, then whatever position is okay. 3081 return Math.min(suggestedPosition, maxPosition); 3082 } 3083 3084 // The task can't be shown, put non-current user tasks below current user tasks. 3085 while (maxPosition > 0) { 3086 final TaskRecord tmpTask = mTaskHistory.get(maxPosition - 1); 3087 if (!mStackSupervisor.isCurrentProfileLocked(tmpTask.userId) 3088 || tmpTask.topRunningActivityLocked() == null) { 3089 break; 3090 } 3091 maxPosition--; 3092 } 3093 3094 return Math.min(suggestedPosition, maxPosition); 3095 } 3096 3097 /** 3098 * Used from {@link ActivityStack#positionTask(TaskRecord, int)}. 3099 * @see ActivityTaskManagerService#positionTaskInStack(int, int, int). 3100 */ insertTaskAtPosition(TaskRecord task, int position)3101 private void insertTaskAtPosition(TaskRecord task, int position) { 3102 if (position >= mTaskHistory.size()) { 3103 insertTaskAtTop(task, null); 3104 return; 3105 } else if (position <= 0) { 3106 insertTaskAtBottom(task); 3107 return; 3108 } 3109 position = getAdjustedPositionForTask(task, position, null /* starting */); 3110 mTaskHistory.remove(task); 3111 mTaskHistory.add(position, task); 3112 if (mTaskStack != null) { 3113 // TODO: this could not be false after unification. 3114 mTaskStack.positionChildAt(task.getTask(), position); 3115 } 3116 updateTaskMovement(task, true); 3117 } 3118 insertTaskAtTop(TaskRecord task, ActivityRecord starting)3119 private void insertTaskAtTop(TaskRecord task, ActivityRecord starting) { 3120 // TODO: Better place to put all the code below...may be addTask... 3121 mTaskHistory.remove(task); 3122 // Now put task at top. 3123 final int position = getAdjustedPositionForTask(task, mTaskHistory.size(), starting); 3124 mTaskHistory.add(position, task); 3125 updateTaskMovement(task, true); 3126 positionChildWindowContainerAtTop(task); 3127 } 3128 insertTaskAtBottom(TaskRecord task)3129 private void insertTaskAtBottom(TaskRecord task) { 3130 mTaskHistory.remove(task); 3131 final int position = getAdjustedPositionForTask(task, 0, null); 3132 mTaskHistory.add(position, task); 3133 updateTaskMovement(task, true); 3134 positionChildWindowContainerAtBottom(task); 3135 } 3136 startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity, boolean newTask, boolean keepCurTransition, ActivityOptions options)3137 void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity, 3138 boolean newTask, boolean keepCurTransition, ActivityOptions options) { 3139 TaskRecord rTask = r.getTaskRecord(); 3140 final int taskId = rTask.taskId; 3141 // mLaunchTaskBehind tasks get placed at the back of the task stack. 3142 if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) { 3143 // Last activity in task had been removed or ActivityManagerService is reusing task. 3144 // Insert or replace. 3145 // Might not even be in. 3146 insertTaskAtTop(rTask, r); 3147 } 3148 TaskRecord task = null; 3149 if (!newTask) { 3150 // If starting in an existing task, find where that is... 3151 boolean startIt = true; 3152 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 3153 task = mTaskHistory.get(taskNdx); 3154 if (task.getTopActivity() == null) { 3155 // All activities in task are finishing. 3156 continue; 3157 } 3158 if (task == rTask) { 3159 // Here it is! Now, if this is not yet visible to the 3160 // user, then just add it without starting; it will 3161 // get started when the user navigates back to it. 3162 if (!startIt) { 3163 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task " 3164 + task, new RuntimeException("here").fillInStackTrace()); 3165 r.createAppWindowToken(); 3166 ActivityOptions.abort(options); 3167 return; 3168 } 3169 break; 3170 } else if (task.numFullscreen > 0) { 3171 startIt = false; 3172 } 3173 } 3174 } 3175 3176 // Place a new activity at top of stack, so it is next to interact with the user. 3177 3178 // If we are not placing the new activity frontmost, we do not want to deliver the 3179 // onUserLeaving callback to the actual frontmost activity 3180 final TaskRecord activityTask = r.getTaskRecord(); 3181 if (task == activityTask && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) { 3182 mStackSupervisor.mUserLeaving = false; 3183 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING, 3184 "startActivity() behind front, mUserLeaving=false"); 3185 } 3186 3187 task = activityTask; 3188 3189 // Slot the activity into the history stack and proceed 3190 if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task, 3191 new RuntimeException("here").fillInStackTrace()); 3192 // TODO: Need to investigate if it is okay for the controller to already be created by the 3193 // time we get to this point. I think it is, but need to double check. 3194 // Use test in b/34179495 to trace the call path. 3195 if (r.mAppWindowToken == null) { 3196 r.createAppWindowToken(); 3197 } 3198 3199 task.setFrontOfTask(); 3200 3201 if (!isHomeOrRecentsStack() || numActivities() > 0) { 3202 final DisplayContent dc = getDisplay().mDisplayContent; 3203 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, 3204 "Prepare open transition: starting " + r); 3205 if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) { 3206 dc.prepareAppTransition(TRANSIT_NONE, keepCurTransition); 3207 mStackSupervisor.mNoAnimActivities.add(r); 3208 } else { 3209 int transit = TRANSIT_ACTIVITY_OPEN; 3210 if (newTask) { 3211 if (r.mLaunchTaskBehind) { 3212 transit = TRANSIT_TASK_OPEN_BEHIND; 3213 } else { 3214 // If a new task is being launched, then mark the existing top activity as 3215 // supporting picture-in-picture while pausing only if the starting activity 3216 // would not be considered an overlay on top of the current activity 3217 // (eg. not fullscreen, or the assistant) 3218 if (canEnterPipOnTaskSwitch(focusedTopActivity, 3219 null /* toFrontTask */, r, options)) { 3220 focusedTopActivity.supportsEnterPipOnTaskSwitch = true; 3221 } 3222 transit = TRANSIT_TASK_OPEN; 3223 } 3224 } 3225 dc.prepareAppTransition(transit, keepCurTransition); 3226 mStackSupervisor.mNoAnimActivities.remove(r); 3227 } 3228 boolean doShow = true; 3229 if (newTask) { 3230 // Even though this activity is starting fresh, we still need 3231 // to reset it to make sure we apply affinities to move any 3232 // existing activities from other tasks in to it. 3233 // If the caller has requested that the target task be 3234 // reset, then do so. 3235 if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { 3236 resetTaskIfNeededLocked(r, r); 3237 doShow = topRunningNonDelayedActivityLocked(null) == r; 3238 } 3239 } else if (options != null && options.getAnimationType() 3240 == ActivityOptions.ANIM_SCENE_TRANSITION) { 3241 doShow = false; 3242 } 3243 if (r.mLaunchTaskBehind) { 3244 // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we 3245 // tell WindowManager that r is visible even though it is at the back of the stack. 3246 r.setVisibility(true); 3247 ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); 3248 } else if (SHOW_APP_STARTING_PREVIEW && doShow) { 3249 // Figure out if we are transitioning from another activity that is 3250 // "has the same starting icon" as the next one. This allows the 3251 // window manager to keep the previous window it had previously 3252 // created, if it still had one. 3253 TaskRecord prevTask = r.getTaskRecord(); 3254 ActivityRecord prev = prevTask.topRunningActivityWithStartingWindowLocked(); 3255 if (prev != null) { 3256 // We don't want to reuse the previous starting preview if: 3257 // (1) The current activity is in a different task. 3258 if (prev.getTaskRecord() != prevTask) { 3259 prev = null; 3260 } 3261 // (2) The current activity is already displayed. 3262 else if (prev.nowVisible) { 3263 prev = null; 3264 } 3265 } 3266 r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity)); 3267 } 3268 } else { 3269 // If this is the first activity, don't do any fancy animations, 3270 // because there is nothing for it to animate on top of. 3271 ActivityOptions.abort(options); 3272 } 3273 } 3274 3275 /** 3276 * @return Whether the switch to another task can trigger the currently running activity to 3277 * enter PiP while it is pausing (if supported). Only one of {@param toFrontTask} or 3278 * {@param toFrontActivity} should be set. 3279 */ canEnterPipOnTaskSwitch(ActivityRecord pipCandidate, TaskRecord toFrontTask, ActivityRecord toFrontActivity, ActivityOptions opts)3280 private boolean canEnterPipOnTaskSwitch(ActivityRecord pipCandidate, 3281 TaskRecord toFrontTask, ActivityRecord toFrontActivity, ActivityOptions opts) { 3282 if (opts != null && opts.disallowEnterPictureInPictureWhileLaunching()) { 3283 // Ensure the caller has requested not to trigger auto-enter PiP 3284 return false; 3285 } 3286 if (pipCandidate == null || pipCandidate.inPinnedWindowingMode()) { 3287 // Ensure that we do not trigger entering PiP an activity on the pinned stack 3288 return false; 3289 } 3290 final ActivityStack targetStack = toFrontTask != null 3291 ? toFrontTask.getStack() : toFrontActivity.getActivityStack(); 3292 if (targetStack != null && targetStack.isActivityTypeAssistant()) { 3293 // Ensure the task/activity being brought forward is not the assistant 3294 return false; 3295 } 3296 return true; 3297 } 3298 isTaskSwitch(ActivityRecord r, ActivityRecord topFocusedActivity)3299 private boolean isTaskSwitch(ActivityRecord r, 3300 ActivityRecord topFocusedActivity) { 3301 return topFocusedActivity != null && r.getTaskRecord() != topFocusedActivity.getTaskRecord(); 3302 } 3303 3304 /** 3305 * Perform a reset of the given task, if needed as part of launching it. 3306 * Returns the new HistoryRecord at the top of the task. 3307 */ 3308 /** 3309 * Helper method for #resetTaskIfNeededLocked. 3310 * We are inside of the task being reset... we'll either finish this activity, push it out 3311 * for another task, or leave it as-is. 3312 * @param task The task containing the Activity (taskTop) that might be reset. 3313 * @param forceReset 3314 * @return An ActivityOptions that needs to be processed. 3315 */ resetTargetTaskIfNeededLocked(TaskRecord task, boolean forceReset)3316 private ActivityOptions resetTargetTaskIfNeededLocked(TaskRecord task, boolean forceReset) { 3317 ActivityOptions topOptions = null; 3318 3319 int replyChainEnd = -1; 3320 boolean canMoveOptions = true; 3321 3322 // We only do this for activities that are not the root of the task (since if we finish 3323 // the root, we may no longer have the task!). 3324 final ArrayList<ActivityRecord> activities = task.mActivities; 3325 final int numActivities = activities.size(); 3326 final int rootActivityNdx = task.findEffectiveRootIndex(); 3327 for (int i = numActivities - 1; i > rootActivityNdx; --i ) { 3328 ActivityRecord target = activities.get(i); 3329 if (target.frontOfTask) 3330 break; 3331 3332 final int flags = target.info.flags; 3333 final boolean finishOnTaskLaunch = 3334 (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0; 3335 final boolean allowTaskReparenting = 3336 (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0; 3337 final boolean clearWhenTaskReset = 3338 (target.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0; 3339 3340 if (!finishOnTaskLaunch 3341 && !clearWhenTaskReset 3342 && target.resultTo != null) { 3343 // If this activity is sending a reply to a previous 3344 // activity, we can't do anything with it now until 3345 // we reach the start of the reply chain. 3346 // XXX note that we are assuming the result is always 3347 // to the previous activity, which is almost always 3348 // the case but we really shouldn't count on. 3349 if (replyChainEnd < 0) { 3350 replyChainEnd = i; 3351 } 3352 } else if (!finishOnTaskLaunch 3353 && !clearWhenTaskReset 3354 && allowTaskReparenting 3355 && target.taskAffinity != null 3356 && !target.taskAffinity.equals(task.affinity)) { 3357 // If this activity has an affinity for another 3358 // task, then we need to move it out of here. We will 3359 // move it as far out of the way as possible, to the 3360 // bottom of the activity stack. This also keeps it 3361 // correctly ordered with any activities we previously 3362 // moved. 3363 final TaskRecord targetTask; 3364 final ActivityRecord bottom = 3365 !mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ? 3366 mTaskHistory.get(0).mActivities.get(0) : null; 3367 if (bottom != null && target.taskAffinity != null 3368 && target.taskAffinity.equals(bottom.getTaskRecord().affinity)) { 3369 // If the activity currently at the bottom has the 3370 // same task affinity as the one we are moving, 3371 // then merge it into the same task. 3372 targetTask = bottom.getTaskRecord(); 3373 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target 3374 + " out to bottom task " + targetTask); 3375 } else { 3376 targetTask = createTaskRecord( 3377 mStackSupervisor.getNextTaskIdForUserLocked(target.mUserId), 3378 target.info, null, null, null, false); 3379 targetTask.affinityIntent = target.intent; 3380 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity " + target 3381 + " out to new task " + targetTask); 3382 } 3383 3384 boolean noOptions = canMoveOptions; 3385 final int start = replyChainEnd < 0 ? i : replyChainEnd; 3386 for (int srcPos = start; srcPos >= i; --srcPos) { 3387 final ActivityRecord p = activities.get(srcPos); 3388 if (p.finishing) { 3389 continue; 3390 } 3391 3392 canMoveOptions = false; 3393 if (noOptions && topOptions == null) { 3394 topOptions = p.takeOptionsLocked(false /* fromClient */); 3395 if (topOptions != null) { 3396 noOptions = false; 3397 } 3398 } 3399 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, 3400 "Removing activity " + p + " from task=" + task + " adding to task=" 3401 + targetTask + " Callers=" + Debug.getCallers(4)); 3402 if (DEBUG_TASKS) Slog.v(TAG_TASKS, 3403 "Pushing next activity " + p + " out to target's task " + target); 3404 p.reparent(targetTask, 0 /* position - bottom */, "resetTargetTaskIfNeeded"); 3405 } 3406 3407 positionChildWindowContainerAtBottom(targetTask); 3408 replyChainEnd = -1; 3409 } else if (forceReset || finishOnTaskLaunch || clearWhenTaskReset) { 3410 // If the activity should just be removed -- either 3411 // because it asks for it, or the task should be 3412 // cleared -- then finish it and anything that is 3413 // part of its reply chain. 3414 int end; 3415 if (clearWhenTaskReset) { 3416 // In this case, we want to finish this activity 3417 // and everything above it, so be sneaky and pretend 3418 // like these are all in the reply chain. 3419 end = activities.size() - 1; 3420 } else if (replyChainEnd < 0) { 3421 end = i; 3422 } else { 3423 end = replyChainEnd; 3424 } 3425 boolean noOptions = canMoveOptions; 3426 for (int srcPos = i; srcPos <= end; srcPos++) { 3427 ActivityRecord p = activities.get(srcPos); 3428 if (p.finishing) { 3429 continue; 3430 } 3431 canMoveOptions = false; 3432 if (noOptions && topOptions == null) { 3433 topOptions = p.takeOptionsLocked(false /* fromClient */); 3434 if (topOptions != null) { 3435 noOptions = false; 3436 } 3437 } 3438 if (DEBUG_TASKS) Slog.w(TAG_TASKS, 3439 "resetTaskIntendedTask: calling finishActivity on " + p); 3440 if (finishActivityLocked( 3441 p, Activity.RESULT_CANCELED, null, "reset-task", false)) { 3442 end--; 3443 srcPos--; 3444 } 3445 } 3446 replyChainEnd = -1; 3447 } else { 3448 // If we were in the middle of a chain, well the 3449 // activity that started it all doesn't want anything 3450 // special, so leave it all as-is. 3451 replyChainEnd = -1; 3452 } 3453 } 3454 3455 return topOptions; 3456 } 3457 3458 /** 3459 * Helper method for #resetTaskIfNeededLocked. Processes all of the activities in a given 3460 * TaskRecord looking for an affinity with the task of resetTaskIfNeededLocked.taskTop. 3461 * @param affinityTask The task we are looking for an affinity to. 3462 * @param task Task that resetTaskIfNeededLocked.taskTop belongs to. 3463 * @param topTaskIsHigher True if #task has already been processed by resetTaskIfNeededLocked. 3464 * @param forceReset Flag passed in to resetTaskIfNeededLocked. 3465 */ resetAffinityTaskIfNeededLocked(TaskRecord affinityTask, TaskRecord task, boolean topTaskIsHigher, boolean forceReset, int taskInsertionPoint)3466 private int resetAffinityTaskIfNeededLocked(TaskRecord affinityTask, TaskRecord task, 3467 boolean topTaskIsHigher, boolean forceReset, int taskInsertionPoint) { 3468 int replyChainEnd = -1; 3469 final int taskId = task.taskId; 3470 final String taskAffinity = task.affinity; 3471 3472 final ArrayList<ActivityRecord> activities = affinityTask.mActivities; 3473 final int numActivities = activities.size(); 3474 final int rootActivityNdx = affinityTask.findEffectiveRootIndex(); 3475 3476 // Do not operate on or below the effective root Activity. 3477 for (int i = numActivities - 1; i > rootActivityNdx; --i) { 3478 ActivityRecord target = activities.get(i); 3479 if (target.frontOfTask) 3480 break; 3481 3482 final int flags = target.info.flags; 3483 boolean finishOnTaskLaunch = (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0; 3484 boolean allowTaskReparenting = (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0; 3485 3486 if (target.resultTo != null) { 3487 // If this activity is sending a reply to a previous 3488 // activity, we can't do anything with it now until 3489 // we reach the start of the reply chain. 3490 // XXX note that we are assuming the result is always 3491 // to the previous activity, which is almost always 3492 // the case but we really shouldn't count on. 3493 if (replyChainEnd < 0) { 3494 replyChainEnd = i; 3495 } 3496 } else if (topTaskIsHigher 3497 && allowTaskReparenting 3498 && taskAffinity != null 3499 && taskAffinity.equals(target.taskAffinity)) { 3500 // This activity has an affinity for our task. Either remove it if we are 3501 // clearing or move it over to our task. Note that 3502 // we currently punt on the case where we are resetting a 3503 // task that is not at the top but who has activities above 3504 // with an affinity to it... this is really not a normal 3505 // case, and we will need to later pull that task to the front 3506 // and usually at that point we will do the reset and pick 3507 // up those remaining activities. (This only happens if 3508 // someone starts an activity in a new task from an activity 3509 // in a task that is not currently on top.) 3510 if (forceReset || finishOnTaskLaunch) { 3511 final int start = replyChainEnd >= 0 ? replyChainEnd : i; 3512 if (DEBUG_TASKS) Slog.v(TAG_TASKS, 3513 "Finishing task at index " + start + " to " + i); 3514 for (int srcPos = start; srcPos >= i; --srcPos) { 3515 final ActivityRecord p = activities.get(srcPos); 3516 if (p.finishing) { 3517 continue; 3518 } 3519 finishActivityLocked( 3520 p, Activity.RESULT_CANCELED, null, "move-affinity", false); 3521 } 3522 } else { 3523 if (taskInsertionPoint < 0) { 3524 taskInsertionPoint = task.mActivities.size(); 3525 3526 } 3527 3528 final int start = replyChainEnd >= 0 ? replyChainEnd : i; 3529 if (DEBUG_TASKS) Slog.v(TAG_TASKS, 3530 "Reparenting from task=" + affinityTask + ":" + start + "-" + i 3531 + " to task=" + task + ":" + taskInsertionPoint); 3532 for (int srcPos = start; srcPos >= i; --srcPos) { 3533 final ActivityRecord p = activities.get(srcPos); 3534 p.reparent(task, taskInsertionPoint, "resetAffinityTaskIfNeededLocked"); 3535 3536 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, 3537 "Removing and adding activity " + p + " to stack at " + task 3538 + " callers=" + Debug.getCallers(3)); 3539 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Pulling activity " + p 3540 + " from " + srcPos + " in to resetting task " + task); 3541 } 3542 positionChildWindowContainerAtTop(task); 3543 3544 // Now we've moved it in to place... but what if this is 3545 // a singleTop activity and we have put it on top of another 3546 // instance of the same activity? Then we drop the instance 3547 // below so it remains singleTop. 3548 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) { 3549 ArrayList<ActivityRecord> taskActivities = task.mActivities; 3550 int targetNdx = taskActivities.indexOf(target); 3551 if (targetNdx > 0) { 3552 ActivityRecord p = taskActivities.get(targetNdx - 1); 3553 if (p.intent.getComponent().equals(target.intent.getComponent())) { 3554 finishActivityLocked(p, Activity.RESULT_CANCELED, null, "replace", 3555 false); 3556 } 3557 } 3558 } 3559 } 3560 3561 replyChainEnd = -1; 3562 } 3563 } 3564 return taskInsertionPoint; 3565 } 3566 resetTaskIfNeededLocked(ActivityRecord taskTop, ActivityRecord newActivity)3567 final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop, 3568 ActivityRecord newActivity) { 3569 final boolean forceReset = 3570 (newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0; 3571 final TaskRecord task = taskTop.getTaskRecord(); 3572 3573 /** False until we evaluate the TaskRecord associated with taskTop. Switches to true 3574 * for remaining tasks. Used for later tasks to reparent to task. */ 3575 boolean taskFound = false; 3576 3577 /** If ActivityOptions are moved out and need to be aborted or moved to taskTop. */ 3578 ActivityOptions topOptions = null; 3579 3580 // Preserve the location for reparenting in the new task. 3581 int reparentInsertionPoint = -1; 3582 3583 for (int i = mTaskHistory.size() - 1; i >= 0; --i) { 3584 final TaskRecord targetTask = mTaskHistory.get(i); 3585 3586 if (targetTask == task) { 3587 topOptions = resetTargetTaskIfNeededLocked(task, forceReset); 3588 taskFound = true; 3589 } else { 3590 reparentInsertionPoint = resetAffinityTaskIfNeededLocked(targetTask, task, 3591 taskFound, forceReset, reparentInsertionPoint); 3592 } 3593 } 3594 3595 int taskNdx = mTaskHistory.indexOf(task); 3596 if (taskNdx >= 0) { 3597 do { 3598 taskTop = mTaskHistory.get(taskNdx--).getTopActivity(); 3599 } while (taskTop == null && taskNdx >= 0); 3600 } 3601 3602 if (topOptions != null) { 3603 // If we got some ActivityOptions from an activity on top that 3604 // was removed from the task, propagate them to the new real top. 3605 if (taskTop != null) { 3606 taskTop.updateOptionsLocked(topOptions); 3607 } else { 3608 topOptions.abort(); 3609 } 3610 } 3611 3612 return taskTop; 3613 } 3614 sendActivityResultLocked(int callingUid, ActivityRecord r, String resultWho, int requestCode, int resultCode, Intent data)3615 void sendActivityResultLocked(int callingUid, ActivityRecord r, 3616 String resultWho, int requestCode, int resultCode, Intent data) { 3617 3618 if (callingUid > 0) { 3619 mService.mUgmInternal.grantUriPermissionFromIntent(callingUid, r.packageName, 3620 data, r.getUriPermissionsLocked(), r.mUserId); 3621 } 3622 3623 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r 3624 + " : who=" + resultWho + " req=" + requestCode 3625 + " res=" + resultCode + " data=" + data); 3626 if (mResumedActivity == r && r.attachedToProcess()) { 3627 try { 3628 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>(); 3629 list.add(new ResultInfo(resultWho, requestCode, 3630 resultCode, data)); 3631 mService.getLifecycleManager().scheduleTransaction(r.app.getThread(), r.appToken, 3632 ActivityResultItem.obtain(list)); 3633 return; 3634 } catch (Exception e) { 3635 Slog.w(TAG, "Exception thrown sending result to " + r, e); 3636 } 3637 } 3638 3639 r.addResultLocked(null, resultWho, requestCode, resultCode, data); 3640 } 3641 3642 /** Returns true if the task is one of the task finishing on-top of the top running task. */ isATopFinishingTask(TaskRecord task)3643 private boolean isATopFinishingTask(TaskRecord task) { 3644 for (int i = mTaskHistory.size() - 1; i >= 0; --i) { 3645 final TaskRecord current = mTaskHistory.get(i); 3646 final ActivityRecord r = current.topRunningActivityLocked(); 3647 if (r != null) { 3648 // We got a top running activity, so there isn't a top finishing task... 3649 return false; 3650 } 3651 if (current == task) { 3652 return true; 3653 } 3654 } 3655 return false; 3656 } 3657 adjustFocusedActivityStack(ActivityRecord r, String reason)3658 private void adjustFocusedActivityStack(ActivityRecord r, String reason) { 3659 if (!mRootActivityContainer.isTopDisplayFocusedStack(this) || 3660 ((mResumedActivity != r) && (mResumedActivity != null))) { 3661 return; 3662 } 3663 3664 final ActivityRecord next = topRunningActivityLocked(); 3665 final String myReason = reason + " adjustFocus"; 3666 3667 if (next == r) { 3668 final ActivityRecord top = mRootActivityContainer.topRunningActivity(); 3669 if (top != null) { 3670 top.moveFocusableActivityToTop(myReason); 3671 } 3672 return; 3673 } 3674 3675 if (next != null && isFocusable()) { 3676 // Keep focus in stack if we have a top running activity and are focusable. 3677 return; 3678 } 3679 3680 // Task is not guaranteed to be non-null. For example, destroying the 3681 // {@link ActivityRecord} will disassociate the task from the activity. 3682 final TaskRecord task = r.getTaskRecord(); 3683 3684 if (task == null) { 3685 throw new IllegalStateException("activity no longer associated with task:" + r); 3686 } 3687 3688 // Move focus to next focusable stack if possible. 3689 final ActivityStack nextFocusableStack = adjustFocusToNextFocusableStack(myReason); 3690 if (nextFocusableStack != null) { 3691 final ActivityRecord top = nextFocusableStack.topRunningActivityLocked(); 3692 if (top != null && top == mRootActivityContainer.getTopResumedActivity()) { 3693 // TODO(b/111361570): Remove this and update focused app per-display in 3694 // WindowManager every time an activity becomes resumed in 3695 // ActivityTaskManagerService#setResumedActivityUncheckLocked(). 3696 mService.setResumedActivityUncheckLocked(top, reason); 3697 } 3698 return; 3699 } 3700 3701 // Whatever...go home. 3702 getDisplay().moveHomeActivityToTop(myReason); 3703 } 3704 3705 /** 3706 * Find next proper focusable stack and make it focused. 3707 * @return The stack that now got the focus, {@code null} if none found. 3708 */ adjustFocusToNextFocusableStack(String reason)3709 ActivityStack adjustFocusToNextFocusableStack(String reason) { 3710 return adjustFocusToNextFocusableStack(reason, false /* allowFocusSelf */); 3711 } 3712 3713 /** 3714 * Find next proper focusable stack and make it focused. 3715 * @param allowFocusSelf Is the focus allowed to remain on the same stack. 3716 * @return The stack that now got the focus, {@code null} if none found. 3717 */ adjustFocusToNextFocusableStack(String reason, boolean allowFocusSelf)3718 private ActivityStack adjustFocusToNextFocusableStack(String reason, boolean allowFocusSelf) { 3719 final ActivityStack stack = 3720 mRootActivityContainer.getNextFocusableStack(this, !allowFocusSelf); 3721 final String myReason = reason + " adjustFocusToNextFocusableStack"; 3722 if (stack == null) { 3723 return null; 3724 } 3725 3726 final ActivityRecord top = stack.topRunningActivityLocked(); 3727 3728 if (stack.isActivityTypeHome() && (top == null || !top.visible)) { 3729 // If we will be focusing on the home stack next and its current top activity isn't 3730 // visible, then use the move the home stack task to top to make the activity visible. 3731 stack.getDisplay().moveHomeActivityToTop(reason); 3732 return stack; 3733 } 3734 3735 stack.moveToFront(myReason); 3736 return stack; 3737 } 3738 stopActivityLocked(ActivityRecord r)3739 final void stopActivityLocked(ActivityRecord r) { 3740 if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Stopping: " + r); 3741 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 3742 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) { 3743 if (!r.finishing) { 3744 if (!shouldSleepActivities()) { 3745 if (DEBUG_STATES) Slog.d(TAG_STATES, "no-history finish of " + r); 3746 if (requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, 3747 "stop-no-history", false)) { 3748 // If {@link requestFinishActivityLocked} returns {@code true}, 3749 // {@link adjustFocusedActivityStack} would have been already called. 3750 r.resumeKeyDispatchingLocked(); 3751 return; 3752 } 3753 } else { 3754 if (DEBUG_STATES) Slog.d(TAG_STATES, "Not finishing noHistory " + r 3755 + " on stop because we're just sleeping"); 3756 } 3757 } 3758 } 3759 3760 if (r.attachedToProcess()) { 3761 adjustFocusedActivityStack(r, "stopActivity"); 3762 r.resumeKeyDispatchingLocked(); 3763 try { 3764 r.stopped = false; 3765 if (DEBUG_STATES) Slog.v(TAG_STATES, 3766 "Moving to STOPPING: " + r + " (stop requested)"); 3767 r.setState(STOPPING, "stopActivityLocked"); 3768 if (DEBUG_VISIBILITY) Slog.v(TAG_VISIBILITY, 3769 "Stopping visible=" + r.visible + " for " + r); 3770 if (!r.visible) { 3771 r.setVisible(false); 3772 } 3773 EventLogTags.writeAmStopActivity( 3774 r.mUserId, System.identityHashCode(r), r.shortComponentName); 3775 mService.getLifecycleManager().scheduleTransaction(r.app.getThread(), r.appToken, 3776 StopActivityItem.obtain(r.visible, r.configChangeFlags)); 3777 if (shouldSleepOrShutDownActivities()) { 3778 r.setSleeping(true); 3779 } 3780 Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r); 3781 mHandler.sendMessageDelayed(msg, STOP_TIMEOUT); 3782 } catch (Exception e) { 3783 // Maybe just ignore exceptions here... if the process 3784 // has crashed, our death notification will clean things 3785 // up. 3786 Slog.w(TAG, "Exception thrown during pause", e); 3787 // Just in case, assume it to be stopped. 3788 r.stopped = true; 3789 if (DEBUG_STATES) Slog.v(TAG_STATES, "Stop failed; moving to STOPPED: " + r); 3790 r.setState(STOPPED, "stopActivityLocked"); 3791 if (r.deferRelaunchUntilPaused) { 3792 destroyActivityLocked(r, true, "stop-except"); 3793 } 3794 } 3795 } 3796 } 3797 3798 /** 3799 * @return Returns true if the activity is being finished, false if for 3800 * some reason it is being left as-is. 3801 */ requestFinishActivityLocked(IBinder token, int resultCode, Intent resultData, String reason, boolean oomAdj)3802 final boolean requestFinishActivityLocked(IBinder token, int resultCode, 3803 Intent resultData, String reason, boolean oomAdj) { 3804 ActivityRecord r = isInStackLocked(token); 3805 if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(TAG_STATES, 3806 "Finishing activity token=" + token + " r=" 3807 + ", result=" + resultCode + ", data=" + resultData 3808 + ", reason=" + reason); 3809 if (r == null) { 3810 return false; 3811 } 3812 3813 finishActivityLocked(r, resultCode, resultData, reason, oomAdj); 3814 return true; 3815 } 3816 finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode)3817 final void finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode) { 3818 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 3819 ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 3820 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 3821 ActivityRecord r = activities.get(activityNdx); 3822 if (r.resultTo == self && r.requestCode == requestCode) { 3823 if ((r.resultWho == null && resultWho == null) || 3824 (r.resultWho != null && r.resultWho.equals(resultWho))) { 3825 finishActivityLocked(r, Activity.RESULT_CANCELED, null, "request-sub", 3826 false); 3827 } 3828 } 3829 } 3830 } 3831 mService.updateOomAdj(); 3832 } 3833 3834 /** 3835 * Finish the topmost activity that belongs to the crashed app. We may also finish the activity 3836 * that requested launch of the crashed one to prevent launch-crash loop. 3837 * @param app The app that crashed. 3838 * @param reason Reason to perform this action. 3839 * @return The task that was finished in this stack, {@code null} if top running activity does 3840 * not belong to the crashed app. 3841 */ finishTopCrashedActivityLocked(WindowProcessController app, String reason)3842 final TaskRecord finishTopCrashedActivityLocked(WindowProcessController app, String reason) { 3843 ActivityRecord r = topRunningActivityLocked(); 3844 TaskRecord finishedTask = null; 3845 if (r == null || r.app != app) { 3846 return null; 3847 } 3848 Slog.w(TAG, " Force finishing activity " 3849 + r.intent.getComponent().flattenToShortString()); 3850 finishedTask = r.getTaskRecord(); 3851 int taskNdx = mTaskHistory.indexOf(finishedTask); 3852 final TaskRecord task = finishedTask; 3853 int activityNdx = task.mActivities.indexOf(r); 3854 getDisplay().mDisplayContent.prepareAppTransition( 3855 TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */); 3856 finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false); 3857 finishedTask = task; 3858 // Also terminate any activities below it that aren't yet 3859 // stopped, to avoid a situation where one will get 3860 // re-start our crashing activity once it gets resumed again. 3861 --activityNdx; 3862 if (activityNdx < 0) { 3863 do { 3864 --taskNdx; 3865 if (taskNdx < 0) { 3866 break; 3867 } 3868 activityNdx = mTaskHistory.get(taskNdx).mActivities.size() - 1; 3869 } while (activityNdx < 0); 3870 } 3871 if (activityNdx >= 0) { 3872 r = mTaskHistory.get(taskNdx).mActivities.get(activityNdx); 3873 if (r.isState(RESUMED, PAUSING, PAUSED)) { 3874 if (!r.isActivityTypeHome() || mService.mHomeProcess != r.app) { 3875 Slog.w(TAG, " Force finishing activity " 3876 + r.intent.getComponent().flattenToShortString()); 3877 finishActivityLocked(r, Activity.RESULT_CANCELED, null, reason, false); 3878 } 3879 } 3880 } 3881 return finishedTask; 3882 } 3883 finishVoiceTask(IVoiceInteractionSession session)3884 final void finishVoiceTask(IVoiceInteractionSession session) { 3885 IBinder sessionBinder = session.asBinder(); 3886 boolean didOne = false; 3887 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 3888 TaskRecord tr = mTaskHistory.get(taskNdx); 3889 if (tr.voiceSession != null && tr.voiceSession.asBinder() == sessionBinder) { 3890 for (int activityNdx = tr.mActivities.size() - 1; activityNdx >= 0; --activityNdx) { 3891 ActivityRecord r = tr.mActivities.get(activityNdx); 3892 if (!r.finishing) { 3893 finishActivityLocked(r, Activity.RESULT_CANCELED, null, "finish-voice", 3894 false); 3895 didOne = true; 3896 } 3897 } 3898 } else { 3899 // Check if any of the activities are using voice 3900 for (int activityNdx = tr.mActivities.size() - 1; activityNdx >= 0; --activityNdx) { 3901 ActivityRecord r = tr.mActivities.get(activityNdx); 3902 if (r.voiceSession != null && r.voiceSession.asBinder() == sessionBinder) { 3903 // Inform of cancellation 3904 r.clearVoiceSessionLocked(); 3905 try { 3906 r.app.getThread().scheduleLocalVoiceInteractionStarted( 3907 r.appToken, null); 3908 } catch (RemoteException re) { 3909 // Ok 3910 } 3911 mService.finishRunningVoiceLocked(); 3912 break; 3913 } 3914 } 3915 } 3916 } 3917 3918 if (didOne) { 3919 mService.updateOomAdj(); 3920 } 3921 } 3922 finishActivityAffinityLocked(ActivityRecord r)3923 final boolean finishActivityAffinityLocked(ActivityRecord r) { 3924 ArrayList<ActivityRecord> activities = r.getTaskRecord().mActivities; 3925 for (int index = activities.indexOf(r); index >= 0; --index) { 3926 ActivityRecord cur = activities.get(index); 3927 if (!Objects.equals(cur.taskAffinity, r.taskAffinity)) { 3928 break; 3929 } 3930 finishActivityLocked(cur, Activity.RESULT_CANCELED, null, "request-affinity", true); 3931 } 3932 return true; 3933 } 3934 finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData)3935 private void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) { 3936 // send the result 3937 ActivityRecord resultTo = r.resultTo; 3938 if (resultTo != null) { 3939 if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "Adding result to " + resultTo 3940 + " who=" + r.resultWho + " req=" + r.requestCode 3941 + " res=" + resultCode + " data=" + resultData); 3942 if (resultTo.mUserId != r.mUserId) { 3943 if (resultData != null) { 3944 resultData.prepareToLeaveUser(r.mUserId); 3945 } 3946 } 3947 if (r.info.applicationInfo.uid > 0) { 3948 mService.mUgmInternal.grantUriPermissionFromIntent(r.info.applicationInfo.uid, 3949 resultTo.packageName, resultData, 3950 resultTo.getUriPermissionsLocked(), resultTo.mUserId); 3951 } 3952 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode, resultData); 3953 r.resultTo = null; 3954 } 3955 else if (DEBUG_RESULTS) Slog.v(TAG_RESULTS, "No result destination from " + r); 3956 3957 // Make sure this HistoryRecord is not holding on to other resources, 3958 // because clients have remote IPC references to this object so we 3959 // can't assume that will go away and want to avoid circular IPC refs. 3960 r.results = null; 3961 r.pendingResults = null; 3962 r.newIntents = null; 3963 r.icicle = null; 3964 } 3965 3966 /** 3967 * See {@link #finishActivityLocked(ActivityRecord, int, Intent, String, boolean, boolean)} 3968 */ finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData, String reason, boolean oomAdj)3969 final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData, 3970 String reason, boolean oomAdj) { 3971 return finishActivityLocked(r, resultCode, resultData, reason, oomAdj, !PAUSE_IMMEDIATELY); 3972 } 3973 3974 /** 3975 * @return Returns true if this activity has been removed from the history 3976 * list, or false if it is still in the list and will be removed later. 3977 */ finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData, String reason, boolean oomAdj, boolean pauseImmediately)3978 final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData, 3979 String reason, boolean oomAdj, boolean pauseImmediately) { 3980 if (r.finishing) { 3981 Slog.w(TAG, "Duplicate finish request for " + r); 3982 return false; 3983 } 3984 3985 mWindowManager.deferSurfaceLayout(); 3986 try { 3987 r.makeFinishingLocked(); 3988 final TaskRecord task = r.getTaskRecord(); 3989 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY, 3990 r.mUserId, System.identityHashCode(r), 3991 task.taskId, r.shortComponentName, reason); 3992 final ArrayList<ActivityRecord> activities = task.mActivities; 3993 final int index = activities.indexOf(r); 3994 if (index < (activities.size() - 1)) { 3995 task.setFrontOfTask(); 3996 if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) { 3997 // If the caller asked that this activity (and all above it) 3998 // be cleared when the task is reset, don't lose that information, 3999 // but propagate it up to the next activity. 4000 ActivityRecord next = activities.get(index+1); 4001 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 4002 } 4003 } 4004 4005 r.pauseKeyDispatchingLocked(); 4006 4007 adjustFocusedActivityStack(r, "finishActivity"); 4008 4009 finishActivityResultsLocked(r, resultCode, resultData); 4010 4011 final boolean endTask = index <= 0 && !task.isClearingToReuseTask(); 4012 final int transit = endTask ? TRANSIT_TASK_CLOSE : TRANSIT_ACTIVITY_CLOSE; 4013 if (mResumedActivity == r) { 4014 if (DEBUG_VISIBILITY || DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, 4015 "Prepare close transition: finishing " + r); 4016 if (endTask) { 4017 mService.getTaskChangeNotificationController().notifyTaskRemovalStarted( 4018 task.getTaskInfo()); 4019 } 4020 getDisplay().mDisplayContent.prepareAppTransition(transit, false); 4021 4022 // Tell window manager to prepare for this one to be removed. 4023 r.setVisibility(false); 4024 4025 if (mPausingActivity == null) { 4026 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish needs to pause: " + r); 4027 if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING, 4028 "finish() => pause with userLeaving=false"); 4029 startPausingLocked(false, false, null, pauseImmediately); 4030 } 4031 4032 if (endTask) { 4033 mService.getLockTaskController().clearLockedTask(task); 4034 } 4035 } else if (!r.isState(PAUSING)) { 4036 // If the activity is PAUSING, we will complete the finish once 4037 // it is done pausing; else we can just directly finish it here. 4038 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish not pausing: " + r); 4039 if (r.visible) { 4040 prepareActivityHideTransitionAnimation(r, transit); 4041 } 4042 4043 final int finishMode = (r.visible || r.nowVisible) ? FINISH_AFTER_VISIBLE 4044 : FINISH_AFTER_PAUSE; 4045 final boolean removedActivity = finishCurrentActivityLocked(r, finishMode, oomAdj, 4046 "finishActivityLocked") == null; 4047 4048 // The following code is an optimization. When the last non-task overlay activity 4049 // is removed from the task, we remove the entire task from the stack. However, 4050 // since that is done after the scheduled destroy callback from the activity, that 4051 // call to change the visibility of the task overlay activities would be out of 4052 // sync with the activitiy visibility being set for this finishing activity above. 4053 // In this case, we can set the visibility of all the task overlay activities when 4054 // we detect the last one is finishing to keep them in sync. 4055 if (task.onlyHasTaskOverlayActivities(true /* excludeFinishing */)) { 4056 for (ActivityRecord taskOverlay : task.mActivities) { 4057 if (!taskOverlay.mTaskOverlay) { 4058 continue; 4059 } 4060 prepareActivityHideTransitionAnimation(taskOverlay, transit); 4061 } 4062 } 4063 return removedActivity; 4064 } else { 4065 if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Finish waiting for pause of: " + r); 4066 } 4067 4068 return false; 4069 } finally { 4070 mWindowManager.continueSurfaceLayout(); 4071 } 4072 } 4073 prepareActivityHideTransitionAnimation(ActivityRecord r, int transit)4074 private void prepareActivityHideTransitionAnimation(ActivityRecord r, int transit) { 4075 final DisplayContent dc = getDisplay().mDisplayContent; 4076 dc.prepareAppTransition(transit, false); 4077 r.setVisibility(false); 4078 dc.executeAppTransition(); 4079 } 4080 4081 static final int FINISH_IMMEDIATELY = 0; 4082 static final int FINISH_AFTER_PAUSE = 1; 4083 static final int FINISH_AFTER_VISIBLE = 2; 4084 finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj, String reason)4085 final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj, 4086 String reason) { 4087 // First things first: if this activity is currently visible, 4088 // and the resumed activity is not yet visible, then hold off on 4089 // finishing until the resumed one becomes visible. 4090 4091 // The activity that we are finishing may be over the lock screen. In this case, we do not 4092 // want to consider activities that cannot be shown on the lock screen as running and should 4093 // proceed with finishing the activity if there is no valid next top running activity. 4094 // Note that if this finishing activity is floating task, we don't need to wait the 4095 // next activity resume and can destroy it directly. 4096 final ActivityDisplay display = getDisplay(); 4097 final ActivityRecord next = display.topRunningActivity(true /* considerKeyguardState */); 4098 final boolean isFloating = r.getConfiguration().windowConfiguration.tasksAreFloating(); 4099 4100 if (mode == FINISH_AFTER_VISIBLE && (r.visible || r.nowVisible) 4101 && next != null && !next.nowVisible && !isFloating) { 4102 if (!mStackSupervisor.mStoppingActivities.contains(r)) { 4103 addToStopping(r, false /* scheduleIdle */, false /* idleDelayed */, 4104 "finishCurrentActivityLocked"); 4105 } 4106 if (DEBUG_STATES) Slog.v(TAG_STATES, 4107 "Moving to STOPPING: "+ r + " (finish requested)"); 4108 r.setState(STOPPING, "finishCurrentActivityLocked"); 4109 if (oomAdj) { 4110 mService.updateOomAdj(); 4111 } 4112 return r; 4113 } 4114 4115 // make sure the record is cleaned out of other places. 4116 mStackSupervisor.mStoppingActivities.remove(r); 4117 mStackSupervisor.mGoingToSleepActivities.remove(r); 4118 final ActivityState prevState = r.getState(); 4119 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to FINISHING: " + r); 4120 4121 r.setState(FINISHING, "finishCurrentActivityLocked"); 4122 4123 // Don't destroy activity immediately if the display contains home stack, although there is 4124 // no next activity at the moment but another home activity should be started later. Keep 4125 // this activity alive until next home activity is resumed then user won't see a temporary 4126 // black screen. 4127 final boolean noRunningStack = next == null && display.topRunningActivity() == null 4128 && display.getHomeStack() == null; 4129 final boolean noFocusedStack = r.getActivityStack() != display.getFocusedStack(); 4130 final boolean finishingInNonFocusedStackOrNoRunning = mode == FINISH_AFTER_VISIBLE 4131 && prevState == PAUSED && (noFocusedStack || noRunningStack); 4132 4133 if (mode == FINISH_IMMEDIATELY 4134 || (prevState == PAUSED 4135 && (mode == FINISH_AFTER_PAUSE || inPinnedWindowingMode())) 4136 || finishingInNonFocusedStackOrNoRunning 4137 || prevState == STOPPING 4138 || prevState == STOPPED 4139 || prevState == ActivityState.INITIALIZING) { 4140 r.makeFinishingLocked(); 4141 boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm:" + reason); 4142 4143 if (finishingInNonFocusedStackOrNoRunning) { 4144 // Finishing activity that was in paused state and it was in not currently focused 4145 // stack, need to make something visible in its place. Also if the display does not 4146 // have running activity, the configuration may need to be updated for restoring 4147 // original orientation of the display. 4148 mRootActivityContainer.ensureVisibilityAndConfig(next, mDisplayId, 4149 false /* markFrozenIfConfigChanged */, true /* deferResume */); 4150 } 4151 if (activityRemoved) { 4152 mRootActivityContainer.resumeFocusedStacksTopActivities(); 4153 } 4154 if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, 4155 "destroyActivityLocked: finishCurrentActivityLocked r=" + r + 4156 " destroy returned removed=" + activityRemoved); 4157 return activityRemoved ? null : r; 4158 } 4159 4160 // Need to go through the full pause cycle to get this 4161 // activity into the stopped state and then finish it. 4162 if (DEBUG_ALL) Slog.v(TAG, "Enqueueing pending finish: " + r); 4163 mStackSupervisor.mFinishingActivities.add(r); 4164 r.resumeKeyDispatchingLocked(); 4165 mRootActivityContainer.resumeFocusedStacksTopActivities(); 4166 // If activity was not paused at this point - explicitly pause it to start finishing 4167 // process. Finishing will be completed once it reports pause back. 4168 if (r.isState(RESUMED) && mPausingActivity != null) { 4169 startPausingLocked(false /* userLeaving */, false /* uiSleeping */, next /* resuming */, 4170 false /* dontWait */); 4171 } 4172 return r; 4173 } 4174 finishAllActivitiesLocked(boolean immediately)4175 void finishAllActivitiesLocked(boolean immediately) { 4176 boolean noActivitiesInStack = true; 4177 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 4178 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 4179 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 4180 final ActivityRecord r = activities.get(activityNdx); 4181 noActivitiesInStack = false; 4182 if (r.finishing && !immediately) { 4183 continue; 4184 } 4185 Slog.d(TAG, "finishAllActivitiesLocked: finishing " + r + " immediately"); 4186 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false, 4187 "finishAllActivitiesLocked"); 4188 } 4189 } 4190 if (noActivitiesInStack) { 4191 remove(); 4192 } 4193 } 4194 4195 /** @return true if the stack behind this one is a standard activity type. */ inFrontOfStandardStack()4196 boolean inFrontOfStandardStack() { 4197 final ActivityDisplay display = getDisplay(); 4198 if (display == null) { 4199 return false; 4200 } 4201 final int index = display.getIndexOf(this); 4202 if (index == 0) { 4203 return false; 4204 } 4205 final ActivityStack stackBehind = display.getChildAt(index - 1); 4206 return stackBehind.isActivityTypeStandard(); 4207 } 4208 shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity)4209 boolean shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity) { 4210 // Basic case: for simple app-centric recents, we need to recreate 4211 // the task if the affinity has changed. 4212 if (srec == null || srec.getTaskRecord().affinity == null || 4213 !srec.getTaskRecord().affinity.equals(destAffinity)) { 4214 return true; 4215 } 4216 // Document-centric case: an app may be split in to multiple documents; 4217 // they need to re-create their task if this current activity is the root 4218 // of a document, unless simply finishing it will return them to the the 4219 // correct app behind. 4220 final TaskRecord task = srec.getTaskRecord(); 4221 if (srec.frontOfTask && task.getBaseIntent() != null && task.getBaseIntent().isDocument()) { 4222 // Okay, this activity is at the root of its task. What to do, what to do... 4223 if (!inFrontOfStandardStack()) { 4224 // Finishing won't return to an application, so we need to recreate. 4225 return true; 4226 } 4227 // We now need to get the task below it to determine what to do. 4228 int taskIdx = mTaskHistory.indexOf(task); 4229 if (taskIdx <= 0) { 4230 Slog.w(TAG, "shouldUpRecreateTask: task not in history for " + srec); 4231 return false; 4232 } 4233 final TaskRecord prevTask = mTaskHistory.get(taskIdx); 4234 if (!task.affinity.equals(prevTask.affinity)) { 4235 // These are different apps, so need to recreate. 4236 return true; 4237 } 4238 } 4239 return false; 4240 } 4241 navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode, Intent resultData)4242 final boolean navigateUpToLocked(ActivityRecord srec, Intent destIntent, int resultCode, 4243 Intent resultData) { 4244 final TaskRecord task = srec.getTaskRecord(); 4245 final ArrayList<ActivityRecord> activities = task.mActivities; 4246 final int start = activities.indexOf(srec); 4247 if (!mTaskHistory.contains(task) || (start < 0)) { 4248 return false; 4249 } 4250 int finishTo = start - 1; 4251 ActivityRecord parent = finishTo < 0 ? null : activities.get(finishTo); 4252 boolean foundParentInTask = false; 4253 final ComponentName dest = destIntent.getComponent(); 4254 if (start > 0 && dest != null) { 4255 for (int i = finishTo; i >= 0; i--) { 4256 ActivityRecord r = activities.get(i); 4257 if (r.info.packageName.equals(dest.getPackageName()) && 4258 r.info.name.equals(dest.getClassName())) { 4259 finishTo = i; 4260 parent = r; 4261 foundParentInTask = true; 4262 break; 4263 } 4264 } 4265 } 4266 4267 // TODO: There is a dup. of this block of code in ActivityTaskManagerService.finishActivity 4268 // We should consolidate. 4269 IActivityController controller = mService.mController; 4270 if (controller != null) { 4271 ActivityRecord next = topRunningActivityLocked(srec.appToken, 0); 4272 if (next != null) { 4273 // ask watcher if this is allowed 4274 boolean resumeOK = true; 4275 try { 4276 resumeOK = controller.activityResuming(next.packageName); 4277 } catch (RemoteException e) { 4278 mService.mController = null; 4279 Watchdog.getInstance().setActivityController(null); 4280 } 4281 4282 if (!resumeOK) { 4283 return false; 4284 } 4285 } 4286 } 4287 final long origId = Binder.clearCallingIdentity(); 4288 for (int i = start; i > finishTo; i--) { 4289 ActivityRecord r = activities.get(i); 4290 requestFinishActivityLocked(r.appToken, resultCode, resultData, "navigate-up", true); 4291 // Only return the supplied result for the first activity finished 4292 resultCode = Activity.RESULT_CANCELED; 4293 resultData = null; 4294 } 4295 4296 if (parent != null && foundParentInTask) { 4297 final int parentLaunchMode = parent.info.launchMode; 4298 final int destIntentFlags = destIntent.getFlags(); 4299 if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE || 4300 parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK || 4301 parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP || 4302 (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { 4303 parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent, 4304 srec.packageName); 4305 } else { 4306 try { 4307 ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo( 4308 destIntent.getComponent(), ActivityManagerService.STOCK_PM_FLAGS, 4309 srec.mUserId); 4310 // TODO(b/64750076): Check if calling pid should really be -1. 4311 final int res = mService.getActivityStartController() 4312 .obtainStarter(destIntent, "navigateUpTo") 4313 .setCaller(srec.app.getThread()) 4314 .setActivityInfo(aInfo) 4315 .setResultTo(parent.appToken) 4316 .setCallingPid(-1) 4317 .setCallingUid(parent.launchedFromUid) 4318 .setCallingPackage(parent.launchedFromPackage) 4319 .setRealCallingPid(-1) 4320 .setRealCallingUid(parent.launchedFromUid) 4321 .setComponentSpecified(true) 4322 .execute(); 4323 foundParentInTask = res == ActivityManager.START_SUCCESS; 4324 } catch (RemoteException e) { 4325 foundParentInTask = false; 4326 } 4327 requestFinishActivityLocked(parent.appToken, resultCode, 4328 resultData, "navigate-top", true); 4329 } 4330 } 4331 Binder.restoreCallingIdentity(origId); 4332 return foundParentInTask; 4333 } 4334 4335 /** 4336 * Remove any state associated with the {@link ActivityRecord}. This should be called whenever 4337 * an activity moves away from the stack. 4338 */ onActivityRemovedFromStack(ActivityRecord r)4339 void onActivityRemovedFromStack(ActivityRecord r) { 4340 removeTimeoutsForActivityLocked(r); 4341 4342 if (mResumedActivity != null && mResumedActivity == r) { 4343 setResumedActivity(null, "onActivityRemovedFromStack"); 4344 } 4345 if (mPausingActivity != null && mPausingActivity == r) { 4346 mPausingActivity = null; 4347 } 4348 } 4349 onActivityAddedToStack(ActivityRecord r)4350 void onActivityAddedToStack(ActivityRecord r) { 4351 if(r.getState() == RESUMED) { 4352 setResumedActivity(r, "onActivityAddedToStack"); 4353 } 4354 } 4355 4356 /** 4357 * Perform the common clean-up of an activity record. This is called both 4358 * as part of destroyActivityLocked() (when destroying the client-side 4359 * representation) and cleaning things up as a result of its hosting 4360 * processing going away, in which case there is no remaining client-side 4361 * state to destroy so only the cleanup here is needed. 4362 * 4363 * Note: Call before #removeActivityFromHistoryLocked. 4364 */ cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState)4365 private void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, boolean setState) { 4366 onActivityRemovedFromStack(r); 4367 4368 r.deferRelaunchUntilPaused = false; 4369 r.frozenBeforeDestroy = false; 4370 4371 if (setState) { 4372 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (cleaning up)"); 4373 r.setState(DESTROYED, "cleanupActivityLocked"); 4374 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during cleanUp for activity " + r); 4375 r.app = null; 4376 } 4377 4378 // Inform supervisor the activity has been removed. 4379 mStackSupervisor.cleanupActivity(r); 4380 4381 4382 // Remove any pending results. 4383 if (r.finishing && r.pendingResults != null) { 4384 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) { 4385 PendingIntentRecord rec = apr.get(); 4386 if (rec != null) { 4387 mService.mPendingIntentController.cancelIntentSender(rec, false); 4388 } 4389 } 4390 r.pendingResults = null; 4391 } 4392 4393 if (cleanServices) { 4394 cleanUpActivityServicesLocked(r); 4395 } 4396 4397 // Get rid of any pending idle timeouts. 4398 removeTimeoutsForActivityLocked(r); 4399 // Clean-up activities are no longer relaunching (e.g. app process died). Notify window 4400 // manager so it can update its bookkeeping. 4401 mWindowManager.notifyAppRelaunchesCleared(r.appToken); 4402 } 4403 removeTimeoutsForActivityLocked(ActivityRecord r)4404 private void removeTimeoutsForActivityLocked(ActivityRecord r) { 4405 mStackSupervisor.removeTimeoutsForActivityLocked(r); 4406 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); 4407 mHandler.removeMessages(STOP_TIMEOUT_MSG, r); 4408 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r); 4409 r.finishLaunchTickingLocked(); 4410 } 4411 removeActivityFromHistoryLocked(ActivityRecord r, String reason)4412 private void removeActivityFromHistoryLocked(ActivityRecord r, String reason) { 4413 finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null); 4414 r.makeFinishingLocked(); 4415 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE, 4416 "Removing activity " + r + " from stack callers=" + Debug.getCallers(5)); 4417 4418 r.takeFromHistory(); 4419 removeTimeoutsForActivityLocked(r); 4420 if (DEBUG_STATES) Slog.v(TAG_STATES, 4421 "Moving to DESTROYED: " + r + " (removed from history)"); 4422 r.setState(DESTROYED, "removeActivityFromHistoryLocked"); 4423 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during remove for activity " + r); 4424 r.app = null; 4425 r.removeWindowContainer(); 4426 final TaskRecord task = r.getTaskRecord(); 4427 final boolean lastActivity = task != null ? task.removeActivity(r) : false; 4428 // If we are removing the last activity in the task, not including task overlay activities, 4429 // then fall through into the block below to remove the entire task itself 4430 final boolean onlyHasTaskOverlays = task != null 4431 ? task.onlyHasTaskOverlayActivities(false /* excludingFinishing */) : false; 4432 4433 if (lastActivity || onlyHasTaskOverlays) { 4434 if (DEBUG_STACK) { 4435 Slog.i(TAG_STACK, 4436 "removeActivityFromHistoryLocked: last activity removed from " + this 4437 + " onlyHasTaskOverlays=" + onlyHasTaskOverlays); 4438 } 4439 4440 // The following block can be executed multiple times if there is more than one overlay. 4441 // {@link ActivityStackSupervisor#removeTaskByIdLocked} handles this by reverse lookup 4442 // of the task by id and exiting early if not found. 4443 if (onlyHasTaskOverlays) { 4444 // When destroying a task, tell the supervisor to remove it so that any activity it 4445 // has can be cleaned up correctly. This is currently the only place where we remove 4446 // a task with the DESTROYING mode, so instead of passing the onlyHasTaskOverlays 4447 // state into removeTask(), we just clear the task here before the other residual 4448 // work. 4449 // TODO: If the callers to removeTask() changes such that we have multiple places 4450 // where we are destroying the task, move this back into removeTask() 4451 mStackSupervisor.removeTaskByIdLocked(task.taskId, false /* killProcess */, 4452 !REMOVE_FROM_RECENTS, PAUSE_IMMEDIATELY, reason); 4453 } 4454 4455 // We must keep the task around until all activities are destroyed. The following 4456 // statement will only execute once since overlays are also considered activities. 4457 if (lastActivity) { 4458 removeTask(task, reason, REMOVE_TASK_MODE_DESTROYING); 4459 } 4460 } 4461 cleanUpActivityServicesLocked(r); 4462 r.removeUriPermissionsLocked(); 4463 } 4464 4465 /** 4466 * Perform clean-up of service connections in an activity record. 4467 */ cleanUpActivityServicesLocked(ActivityRecord r)4468 private void cleanUpActivityServicesLocked(ActivityRecord r) { 4469 if (r.mServiceConnectionsHolder == null) { 4470 return; 4471 } 4472 // Throw away any services that have been bound by this activity. 4473 r.mServiceConnectionsHolder.disconnectActivityFromServices(); 4474 } 4475 scheduleDestroyActivities(WindowProcessController owner, String reason)4476 final void scheduleDestroyActivities(WindowProcessController owner, String reason) { 4477 Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG); 4478 msg.obj = new ScheduleDestroyArgs(owner, reason); 4479 mHandler.sendMessage(msg); 4480 } 4481 destroyActivitiesLocked(WindowProcessController owner, String reason)4482 private void destroyActivitiesLocked(WindowProcessController owner, String reason) { 4483 boolean lastIsOpaque = false; 4484 boolean activityRemoved = false; 4485 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 4486 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 4487 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 4488 final ActivityRecord r = activities.get(activityNdx); 4489 if (r.finishing) { 4490 continue; 4491 } 4492 if (r.fullscreen) { 4493 lastIsOpaque = true; 4494 } 4495 if (owner != null && r.app != owner) { 4496 continue; 4497 } 4498 if (!lastIsOpaque) { 4499 continue; 4500 } 4501 if (r.isDestroyable()) { 4502 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Destroying " + r 4503 + " in state " + r.getState() 4504 + " resumed=" + mResumedActivity 4505 + " pausing=" + mPausingActivity + " for reason " + reason); 4506 if (destroyActivityLocked(r, true, reason)) { 4507 activityRemoved = true; 4508 } 4509 } 4510 } 4511 } 4512 if (activityRemoved) { 4513 mRootActivityContainer.resumeFocusedStacksTopActivities(); 4514 } 4515 } 4516 safelyDestroyActivityLocked(ActivityRecord r, String reason)4517 final boolean safelyDestroyActivityLocked(ActivityRecord r, String reason) { 4518 if (r.isDestroyable()) { 4519 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, 4520 "Destroying " + r + " in state " + r.getState() + " resumed=" + mResumedActivity 4521 + " pausing=" + mPausingActivity + " for reason " + reason); 4522 return destroyActivityLocked(r, true, reason); 4523 } 4524 return false; 4525 } 4526 releaseSomeActivitiesLocked(WindowProcessController app, ArraySet<TaskRecord> tasks, String reason)4527 final int releaseSomeActivitiesLocked(WindowProcessController app, ArraySet<TaskRecord> tasks, 4528 String reason) { 4529 // Iterate over tasks starting at the back (oldest) first. 4530 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Trying to release some activities in " + app); 4531 int maxTasks = tasks.size() / 4; 4532 if (maxTasks < 1) { 4533 maxTasks = 1; 4534 } 4535 int numReleased = 0; 4536 for (int taskNdx = 0; taskNdx < mTaskHistory.size() && maxTasks > 0; taskNdx++) { 4537 final TaskRecord task = mTaskHistory.get(taskNdx); 4538 if (!tasks.contains(task)) { 4539 continue; 4540 } 4541 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, "Looking for activities to release in " + task); 4542 int curNum = 0; 4543 final ArrayList<ActivityRecord> activities = task.mActivities; 4544 for (int actNdx = 0; actNdx < activities.size(); actNdx++) { 4545 final ActivityRecord activity = activities.get(actNdx); 4546 if (activity.app == app && activity.isDestroyable()) { 4547 if (DEBUG_RELEASE) Slog.v(TAG_RELEASE, "Destroying " + activity 4548 + " in state " + activity.getState() + " resumed=" + mResumedActivity 4549 + " pausing=" + mPausingActivity + " for reason " + reason); 4550 destroyActivityLocked(activity, true, reason); 4551 if (activities.get(actNdx) != activity) { 4552 // Was removed from list, back up so we don't miss the next one. 4553 actNdx--; 4554 } 4555 curNum++; 4556 } 4557 } 4558 if (curNum > 0) { 4559 numReleased += curNum; 4560 maxTasks--; 4561 if (mTaskHistory.get(taskNdx) != task) { 4562 // The entire task got removed, back up so we don't miss the next one. 4563 taskNdx--; 4564 } 4565 } 4566 } 4567 if (DEBUG_RELEASE) Slog.d(TAG_RELEASE, 4568 "Done releasing: did " + numReleased + " activities"); 4569 return numReleased; 4570 } 4571 4572 /** 4573 * Destroy the current CLIENT SIDE instance of an activity. This may be 4574 * called both when actually finishing an activity, or when performing 4575 * a configuration switch where we destroy the current client-side object 4576 * but then create a new client-side object for this same HistoryRecord. 4577 */ destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason)4578 final boolean destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason) { 4579 if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(TAG_SWITCH, 4580 "Removing activity from " + reason + ": token=" + r 4581 + ", app=" + (r.hasProcess() ? r.app.mName : "(null)")); 4582 4583 if (r.isState(DESTROYING, DESTROYED)) { 4584 if (DEBUG_STATES) Slog.v(TAG_STATES, "activity " + r + " already destroying." 4585 + "skipping request with reason:" + reason); 4586 return false; 4587 } 4588 4589 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY, 4590 r.mUserId, System.identityHashCode(r), 4591 r.getTaskRecord().taskId, r.shortComponentName, reason); 4592 4593 boolean removedFromHistory = false; 4594 4595 cleanUpActivityLocked(r, false, false); 4596 4597 final boolean hadApp = r.hasProcess(); 4598 4599 if (hadApp) { 4600 if (removeFromApp) { 4601 r.app.removeActivity(r); 4602 if (!r.app.hasActivities()) { 4603 mService.clearHeavyWeightProcessIfEquals(r.app); 4604 } 4605 if (!r.app.hasActivities()) { 4606 // Update any services we are bound to that might care about whether 4607 // their client may have activities. 4608 // No longer have activities, so update LRU list and oom adj. 4609 r.app.updateProcessInfo(true /* updateServiceConnectionActivities */, 4610 false /* activityChange */, true /* updateOomAdj */); 4611 } 4612 } 4613 4614 boolean skipDestroy = false; 4615 4616 try { 4617 if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + r); 4618 mService.getLifecycleManager().scheduleTransaction(r.app.getThread(), r.appToken, 4619 DestroyActivityItem.obtain(r.finishing, r.configChangeFlags)); 4620 } catch (Exception e) { 4621 // We can just ignore exceptions here... if the process 4622 // has crashed, our death notification will clean things 4623 // up. 4624 //Slog.w(TAG, "Exception thrown during finish", e); 4625 if (r.finishing) { 4626 removeActivityFromHistoryLocked(r, reason + " exceptionInScheduleDestroy"); 4627 removedFromHistory = true; 4628 skipDestroy = true; 4629 } 4630 } 4631 4632 r.nowVisible = false; 4633 4634 // If the activity is finishing, we need to wait on removing it 4635 // from the list to give it a chance to do its cleanup. During 4636 // that time it may make calls back with its token so we need to 4637 // be able to find it on the list and so we don't want to remove 4638 // it from the list yet. Otherwise, we can just immediately put 4639 // it in the destroyed state since we are not removing it from the 4640 // list. 4641 if (r.finishing && !skipDestroy) { 4642 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYING: " + r 4643 + " (destroy requested)"); 4644 r.setState(DESTROYING, 4645 "destroyActivityLocked. finishing and not skipping destroy"); 4646 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG, r); 4647 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT); 4648 } else { 4649 if (DEBUG_STATES) Slog.v(TAG_STATES, 4650 "Moving to DESTROYED: " + r + " (destroy skipped)"); 4651 r.setState(DESTROYED, 4652 "destroyActivityLocked. not finishing or skipping destroy"); 4653 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + r); 4654 r.app = null; 4655 } 4656 } else { 4657 // remove this record from the history. 4658 if (r.finishing) { 4659 removeActivityFromHistoryLocked(r, reason + " hadNoApp"); 4660 removedFromHistory = true; 4661 } else { 4662 if (DEBUG_STATES) Slog.v(TAG_STATES, "Moving to DESTROYED: " + r + " (no app)"); 4663 r.setState(DESTROYED, "destroyActivityLocked. not finishing and had no app"); 4664 if (DEBUG_APP) Slog.v(TAG_APP, "Clearing app during destroy for activity " + r); 4665 r.app = null; 4666 } 4667 } 4668 4669 r.configChangeFlags = 0; 4670 4671 if (!mLRUActivities.remove(r) && hadApp) { 4672 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list"); 4673 } 4674 4675 return removedFromHistory; 4676 } 4677 activityDestroyedLocked(IBinder token, String reason)4678 final void activityDestroyedLocked(IBinder token, String reason) { 4679 final long origId = Binder.clearCallingIdentity(); 4680 try { 4681 activityDestroyedLocked(ActivityRecord.forTokenLocked(token), reason); 4682 } finally { 4683 Binder.restoreCallingIdentity(origId); 4684 } 4685 } 4686 4687 /** 4688 * This method is to only be called from the client via binder when the activity is destroyed 4689 * AND finished. 4690 */ activityDestroyedLocked(ActivityRecord record, String reason)4691 final void activityDestroyedLocked(ActivityRecord record, String reason) { 4692 if (record != null) { 4693 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, record); 4694 } 4695 4696 if (DEBUG_CONTAINERS) Slog.d(TAG_CONTAINERS, "activityDestroyedLocked: r=" + record); 4697 4698 if (isInStackLocked(record) != null) { 4699 if (record.isState(DESTROYING, DESTROYED)) { 4700 cleanUpActivityLocked(record, true, false); 4701 removeActivityFromHistoryLocked(record, reason); 4702 } 4703 } 4704 4705 mRootActivityContainer.resumeFocusedStacksTopActivities(); 4706 } 4707 removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list, WindowProcessController app, String listName)4708 private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list, 4709 WindowProcessController app, String listName) { 4710 int i = list.size(); 4711 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, 4712 "Removing app " + app + " from list " + listName + " with " + i + " entries"); 4713 while (i > 0) { 4714 i--; 4715 ActivityRecord r = list.get(i); 4716 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "Record #" + i + " " + r); 4717 if (r.app == app) { 4718 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, "---> REMOVING this entry!"); 4719 list.remove(i); 4720 removeTimeoutsForActivityLocked(r); 4721 } 4722 } 4723 } 4724 removeHistoryRecordsForAppLocked(WindowProcessController app)4725 private boolean removeHistoryRecordsForAppLocked(WindowProcessController app) { 4726 removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities"); 4727 removeHistoryRecordsForAppLocked(mStackSupervisor.mStoppingActivities, app, 4728 "mStoppingActivities"); 4729 removeHistoryRecordsForAppLocked(mStackSupervisor.mGoingToSleepActivities, app, 4730 "mGoingToSleepActivities"); 4731 removeHistoryRecordsForAppLocked(mStackSupervisor.mFinishingActivities, app, 4732 "mFinishingActivities"); 4733 4734 final boolean isProcessRemoved = app.isRemoved(); 4735 if (isProcessRemoved) { 4736 // The package of the died process should be force-stopped, so make its activities as 4737 // finishing to prevent the process from being started again if the next top (or being 4738 // visible) activity also resides in the same process. 4739 app.makeFinishingForProcessRemoved(); 4740 } 4741 4742 boolean hasVisibleActivities = false; 4743 4744 // Clean out the history list. 4745 int i = numActivities(); 4746 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, 4747 "Removing app " + app + " from history with " + i + " entries"); 4748 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 4749 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 4750 mTmpActivities.clear(); 4751 mTmpActivities.addAll(activities); 4752 4753 while (!mTmpActivities.isEmpty()) { 4754 final int targetIndex = mTmpActivities.size() - 1; 4755 final ActivityRecord r = mTmpActivities.remove(targetIndex); 4756 if (DEBUG_CLEANUP) Slog.v(TAG_CLEANUP, 4757 "Record #" + targetIndex + " " + r + ": app=" + r.app); 4758 4759 if (r.app == app) { 4760 if (r.visible) { 4761 hasVisibleActivities = true; 4762 } 4763 final boolean remove; 4764 if ((r.mRelaunchReason == RELAUNCH_REASON_WINDOWING_MODE_RESIZE 4765 || r.mRelaunchReason == RELAUNCH_REASON_FREE_RESIZE) 4766 && r.launchCount < 3 && !r.finishing) { 4767 // If the process crashed during a resize, always try to relaunch it, unless 4768 // it has failed more than twice. Skip activities that's already finishing 4769 // cleanly by itself. 4770 remove = false; 4771 } else if ((!r.haveState && !r.stateNotNeeded 4772 && !r.isState(ActivityState.RESTARTING_PROCESS)) || r.finishing) { 4773 // Don't currently have state for the activity, or 4774 // it is finishing -- always remove it. 4775 remove = true; 4776 } else if (!r.visible && r.launchCount > 2 && 4777 r.lastLaunchTime > (SystemClock.uptimeMillis() - 60000)) { 4778 // We have launched this activity too many times since it was 4779 // able to run, so give up and remove it. 4780 // (Note if the activity is visible, we don't remove the record. 4781 // We leave the dead window on the screen but the process will 4782 // not be restarted unless user explicitly tap on it.) 4783 remove = true; 4784 } else { 4785 // The process may be gone, but the activity lives on! 4786 remove = false; 4787 } 4788 if (remove) { 4789 if (DEBUG_ADD_REMOVE || DEBUG_CLEANUP) Slog.i(TAG_ADD_REMOVE, 4790 "Removing activity " + r + " from stack at " + i 4791 + ": haveState=" + r.haveState 4792 + " stateNotNeeded=" + r.stateNotNeeded 4793 + " finishing=" + r.finishing 4794 + " state=" + r.getState() + " callers=" + Debug.getCallers(5)); 4795 if (!r.finishing || isProcessRemoved) { 4796 Slog.w(TAG, "Force removing " + r + ": app died, no saved state"); 4797 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY, 4798 r.mUserId, System.identityHashCode(r), 4799 r.getTaskRecord().taskId, r.shortComponentName, 4800 "proc died without state saved"); 4801 } 4802 } else { 4803 // We have the current state for this activity, so 4804 // it can be restarted later when needed. 4805 if (DEBUG_ALL) Slog.v(TAG, "Keeping entry, setting app to null"); 4806 if (DEBUG_APP) Slog.v(TAG_APP, 4807 "Clearing app during removeHistory for activity " + r); 4808 r.app = null; 4809 // Set nowVisible to previous visible state. If the app was visible while 4810 // it died, we leave the dead window on screen so it's basically visible. 4811 // This is needed when user later tap on the dead window, we need to stop 4812 // other apps when user transfers focus to the restarted activity. 4813 r.nowVisible = r.visible; 4814 if (!r.haveState) { 4815 if (DEBUG_SAVED_STATE) Slog.i(TAG_SAVED_STATE, 4816 "App died, clearing saved state of " + r); 4817 r.icicle = null; 4818 } 4819 } 4820 cleanUpActivityLocked(r, true, true); 4821 if (remove) { 4822 removeActivityFromHistoryLocked(r, "appDied"); 4823 } 4824 } 4825 } 4826 } 4827 4828 return hasVisibleActivities; 4829 } 4830 updateTransitLocked(int transit, ActivityOptions options)4831 private void updateTransitLocked(int transit, ActivityOptions options) { 4832 if (options != null) { 4833 ActivityRecord r = topRunningActivityLocked(); 4834 if (r != null && !r.isState(RESUMED)) { 4835 r.updateOptionsLocked(options); 4836 } else { 4837 ActivityOptions.abort(options); 4838 } 4839 } 4840 getDisplay().mDisplayContent.prepareAppTransition(transit, false); 4841 } 4842 updateTaskMovement(TaskRecord task, boolean toFront)4843 private void updateTaskMovement(TaskRecord task, boolean toFront) { 4844 if (task.isPersistable) { 4845 task.mLastTimeMoved = System.currentTimeMillis(); 4846 // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most 4847 // recently will be most negative, tasks sent to the bottom before that will be less 4848 // negative. Similarly for recent tasks moved to the top which will be most positive. 4849 if (!toFront) { 4850 task.mLastTimeMoved *= -1; 4851 } 4852 } 4853 mRootActivityContainer.invalidateTaskLayers(); 4854 } 4855 moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options, AppTimeTracker timeTracker, String reason)4856 final void moveTaskToFrontLocked(TaskRecord tr, boolean noAnimation, ActivityOptions options, 4857 AppTimeTracker timeTracker, String reason) { 4858 if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr); 4859 4860 final ActivityStack topStack = getDisplay().getTopStack(); 4861 final ActivityRecord topActivity = topStack != null ? topStack.getTopActivity() : null; 4862 final int numTasks = mTaskHistory.size(); 4863 final int index = mTaskHistory.indexOf(tr); 4864 if (numTasks == 0 || index < 0) { 4865 // nothing to do! 4866 if (noAnimation) { 4867 ActivityOptions.abort(options); 4868 } else { 4869 updateTransitLocked(TRANSIT_TASK_TO_FRONT, options); 4870 } 4871 return; 4872 } 4873 4874 if (timeTracker != null) { 4875 // The caller wants a time tracker associated with this task. 4876 for (int i = tr.mActivities.size() - 1; i >= 0; i--) { 4877 tr.mActivities.get(i).appTimeTracker = timeTracker; 4878 } 4879 } 4880 4881 try { 4882 // Defer updating the IME target since the new IME target will try to get computed 4883 // before updating all closing and opening apps, which can cause the ime target to 4884 // get calculated incorrectly. 4885 getDisplay().deferUpdateImeTarget(); 4886 4887 // Shift all activities with this task up to the top 4888 // of the stack, keeping them in the same internal order. 4889 insertTaskAtTop(tr, null); 4890 4891 // Don't refocus if invisible to current user 4892 final ActivityRecord top = tr.getTopActivity(); 4893 if (top == null || !top.okToShowLocked()) { 4894 if (top != null) { 4895 mStackSupervisor.mRecentTasks.add(top.getTaskRecord()); 4896 } 4897 ActivityOptions.abort(options); 4898 return; 4899 } 4900 4901 // Set focus to the top running activity of this stack. 4902 final ActivityRecord r = topRunningActivityLocked(); 4903 if (r != null) { 4904 r.moveFocusableActivityToTop(reason); 4905 } 4906 4907 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to front transition: task=" + tr); 4908 if (noAnimation) { 4909 getDisplay().mDisplayContent.prepareAppTransition(TRANSIT_NONE, false); 4910 if (r != null) { 4911 mStackSupervisor.mNoAnimActivities.add(r); 4912 } 4913 ActivityOptions.abort(options); 4914 } else { 4915 updateTransitLocked(TRANSIT_TASK_TO_FRONT, options); 4916 } 4917 // If a new task is moved to the front, then mark the existing top activity as 4918 // supporting 4919 4920 // picture-in-picture while paused only if the task would not be considered an oerlay 4921 // on top 4922 // of the current activity (eg. not fullscreen, or the assistant) 4923 if (canEnterPipOnTaskSwitch(topActivity, tr, null /* toFrontActivity */, 4924 options)) { 4925 topActivity.supportsEnterPipOnTaskSwitch = true; 4926 } 4927 4928 mRootActivityContainer.resumeFocusedStacksTopActivities(); 4929 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId); 4930 mService.getTaskChangeNotificationController().notifyTaskMovedToFront(tr.getTaskInfo()); 4931 } finally { 4932 getDisplay().continueUpdateImeTarget(); 4933 } 4934 } 4935 4936 /** 4937 * Worker method for rearranging history stack. Implements the function of moving all 4938 * activities for a specific task (gathering them if disjoint) into a single group at the 4939 * bottom of the stack. 4940 * 4941 * If a watcher is installed, the action is preflighted and the watcher has an opportunity 4942 * to premeptively cancel the move. 4943 * 4944 * @param taskId The taskId to collect and move to the bottom. 4945 * @return Returns true if the move completed, false if not. 4946 */ moveTaskToBackLocked(int taskId)4947 final boolean moveTaskToBackLocked(int taskId) { 4948 final TaskRecord tr = taskForIdLocked(taskId); 4949 if (tr == null) { 4950 Slog.i(TAG, "moveTaskToBack: bad taskId=" + taskId); 4951 return false; 4952 } 4953 Slog.i(TAG, "moveTaskToBack: " + tr); 4954 4955 // In LockTask mode, moving a locked task to the back of the stack may expose unlocked 4956 // ones. Therefore we need to check if this operation is allowed. 4957 if (!mService.getLockTaskController().canMoveTaskToBack(tr)) { 4958 return false; 4959 } 4960 4961 // If we have a watcher, preflight the move before committing to it. First check 4962 // for *other* available tasks, but if none are available, then try again allowing the 4963 // current task to be selected. 4964 if (isTopStackOnDisplay() && mService.mController != null) { 4965 ActivityRecord next = topRunningActivityLocked(null, taskId); 4966 if (next == null) { 4967 next = topRunningActivityLocked(null, 0); 4968 } 4969 if (next != null) { 4970 // ask watcher if this is allowed 4971 boolean moveOK = true; 4972 try { 4973 moveOK = mService.mController.activityResuming(next.packageName); 4974 } catch (RemoteException e) { 4975 mService.mController = null; 4976 Watchdog.getInstance().setActivityController(null); 4977 } 4978 if (!moveOK) { 4979 return false; 4980 } 4981 } 4982 } 4983 4984 if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION, "Prepare to back transition: task=" + taskId); 4985 4986 mTaskHistory.remove(tr); 4987 mTaskHistory.add(0, tr); 4988 updateTaskMovement(tr, false); 4989 4990 getDisplay().mDisplayContent.prepareAppTransition(TRANSIT_TASK_TO_BACK, false); 4991 moveToBack("moveTaskToBackLocked", tr); 4992 4993 if (inPinnedWindowingMode()) { 4994 mStackSupervisor.removeStack(this); 4995 return true; 4996 } 4997 4998 ActivityRecord topActivity = getDisplay().topRunningActivity(); 4999 ActivityStack topStack = topActivity.getActivityStack(); 5000 if (topStack != null && topStack != this && topActivity.isState(RESUMED)) { 5001 // The new top activity is already resumed, so there's a good chance that nothing will 5002 // get resumed below. So, update visibility now in case the transition is closed 5003 // prematurely. 5004 mRootActivityContainer.ensureVisibilityAndConfig(null /* starting */, 5005 getDisplay().mDisplayId, false /* markFrozenIfConfigChanged */, 5006 false /* deferResume */); 5007 } 5008 5009 mRootActivityContainer.resumeFocusedStacksTopActivities(); 5010 return true; 5011 } 5012 logStartActivity(int tag, ActivityRecord r, TaskRecord task)5013 static void logStartActivity(int tag, ActivityRecord r, TaskRecord task) { 5014 final Uri data = r.intent.getData(); 5015 final String strData = data != null ? data.toSafeString() : null; 5016 5017 EventLog.writeEvent(tag, 5018 r.mUserId, System.identityHashCode(r), task.taskId, 5019 r.shortComponentName, r.intent.getAction(), 5020 r.intent.getType(), strData, r.intent.getFlags()); 5021 } 5022 5023 /** 5024 * Ensures all visible activities at or below the input activity have the right configuration. 5025 */ ensureVisibleActivitiesConfigurationLocked(ActivityRecord start, boolean preserveWindow)5026 void ensureVisibleActivitiesConfigurationLocked(ActivityRecord start, boolean preserveWindow) { 5027 if (start == null || !start.visible) { 5028 return; 5029 } 5030 5031 final TaskRecord startTask = start.getTaskRecord(); 5032 boolean behindFullscreen = false; 5033 boolean updatedConfig = false; 5034 5035 for (int taskIndex = mTaskHistory.indexOf(startTask); taskIndex >= 0; --taskIndex) { 5036 final TaskRecord task = mTaskHistory.get(taskIndex); 5037 final ArrayList<ActivityRecord> activities = task.mActivities; 5038 int activityIndex = (start.getTaskRecord() == task) 5039 ? activities.indexOf(start) : activities.size() - 1; 5040 for (; activityIndex >= 0; --activityIndex) { 5041 final ActivityRecord r = activities.get(activityIndex); 5042 updatedConfig |= r.ensureActivityConfiguration(0 /* globalChanges */, 5043 preserveWindow); 5044 if (r.fullscreen) { 5045 behindFullscreen = true; 5046 break; 5047 } 5048 } 5049 if (behindFullscreen) { 5050 break; 5051 } 5052 } 5053 if (updatedConfig) { 5054 // Ensure the resumed state of the focus activity if we updated the configuration of 5055 // any activity. 5056 mRootActivityContainer.resumeFocusedStacksTopActivities(); 5057 } 5058 } 5059 5060 // TODO: Figure-out a way to consolidate with resize() method below. requestResize(Rect bounds)5061 void requestResize(Rect bounds) { 5062 mService.resizeStack(mStackId, bounds, 5063 true /* allowResizeInDockedMode */, false /* preserveWindows */, 5064 false /* animate */, -1 /* animationDuration */); 5065 } 5066 5067 // TODO: Can only be called from special methods in ActivityStackSupervisor. 5068 // Need to consolidate those calls points into this resize method so anyone can call directly. resize(Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds)5069 void resize(Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds) { 5070 if (!updateBoundsAllowed(bounds)) { 5071 return; 5072 } 5073 5074 // Update override configurations of all tasks in the stack. 5075 final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : bounds; 5076 5077 for (int i = mTaskHistory.size() - 1; i >= 0; i--) { 5078 final TaskRecord task = mTaskHistory.get(i); 5079 if (task.isResizeable()) { 5080 task.updateOverrideConfiguration(taskBounds, tempTaskInsetBounds); 5081 } 5082 } 5083 5084 setBounds(bounds); 5085 } 5086 onPipAnimationEndResize()5087 void onPipAnimationEndResize() { 5088 if (mTaskStack == null) return; 5089 mTaskStack.onPipAnimationEndResize(); 5090 } 5091 5092 5093 /** 5094 * Until we can break this "set task bounds to same as stack bounds" behavior, this 5095 * basically resizes both stack and task bounds to the same bounds. 5096 */ setTaskBounds(Rect bounds)5097 void setTaskBounds(Rect bounds) { 5098 if (!updateBoundsAllowed(bounds)) { 5099 return; 5100 } 5101 5102 for (int i = mTaskHistory.size() - 1; i >= 0; i--) { 5103 final TaskRecord task = mTaskHistory.get(i); 5104 if (task.isResizeable()) { 5105 task.setBounds(bounds); 5106 } else { 5107 task.setBounds(null); 5108 } 5109 } 5110 } 5111 5112 /** Helper to setDisplayedBounds on all child tasks */ setTaskDisplayedBounds(Rect bounds)5113 void setTaskDisplayedBounds(Rect bounds) { 5114 if (!updateDisplayedBoundsAllowed(bounds)) { 5115 return; 5116 } 5117 5118 for (int i = mTaskHistory.size() - 1; i >= 0; i--) { 5119 final TaskRecord task = mTaskHistory.get(i); 5120 if (bounds == null || bounds.isEmpty()) { 5121 task.setDisplayedBounds(null); 5122 } else if (task.isResizeable()) { 5123 task.setDisplayedBounds(bounds); 5124 } 5125 } 5126 } 5127 willActivityBeVisibleLocked(IBinder token)5128 boolean willActivityBeVisibleLocked(IBinder token) { 5129 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5130 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 5131 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 5132 final ActivityRecord r = activities.get(activityNdx); 5133 if (r.appToken == token) { 5134 return true; 5135 } 5136 if (r.fullscreen && !r.finishing) { 5137 return false; 5138 } 5139 } 5140 } 5141 final ActivityRecord r = ActivityRecord.forTokenLocked(token); 5142 if (r == null) { 5143 return false; 5144 } 5145 if (r.finishing) Slog.e(TAG, "willActivityBeVisibleLocked: Returning false," 5146 + " would have returned true for r=" + r); 5147 return !r.finishing; 5148 } 5149 closeSystemDialogsLocked()5150 void closeSystemDialogsLocked() { 5151 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5152 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 5153 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 5154 final ActivityRecord r = activities.get(activityNdx); 5155 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) { 5156 finishActivityLocked(r, Activity.RESULT_CANCELED, null, "close-sys", true); 5157 } 5158 } 5159 } 5160 } 5161 finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses, boolean doit, boolean evenPersistent, int userId)5162 boolean finishDisabledPackageActivitiesLocked(String packageName, Set<String> filterByClasses, 5163 boolean doit, boolean evenPersistent, int userId) { 5164 boolean didSomething = false; 5165 TaskRecord lastTask = null; 5166 ComponentName homeActivity = null; 5167 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5168 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 5169 mTmpActivities.clear(); 5170 mTmpActivities.addAll(activities); 5171 5172 while (!mTmpActivities.isEmpty()) { 5173 ActivityRecord r = mTmpActivities.remove(0); 5174 final boolean sameComponent = 5175 (r.packageName.equals(packageName) && (filterByClasses == null 5176 || filterByClasses.contains(r.mActivityComponent.getClassName()))) 5177 || (packageName == null && r.mUserId == userId); 5178 if ((userId == UserHandle.USER_ALL || r.mUserId == userId) 5179 && (sameComponent || r.getTaskRecord() == lastTask) 5180 && (r.app == null || evenPersistent || !r.app.isPersistent())) { 5181 if (!doit) { 5182 if (r.finishing) { 5183 // If this activity is just finishing, then it is not 5184 // interesting as far as something to stop. 5185 continue; 5186 } 5187 return true; 5188 } 5189 if (r.isActivityTypeHome()) { 5190 if (homeActivity != null && homeActivity.equals(r.mActivityComponent)) { 5191 Slog.i(TAG, "Skip force-stop again " + r); 5192 continue; 5193 } else { 5194 homeActivity = r.mActivityComponent; 5195 } 5196 } 5197 didSomething = true; 5198 Slog.i(TAG, " Force finishing activity " + r); 5199 lastTask = r.getTaskRecord(); 5200 finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop", 5201 true); 5202 } 5203 } 5204 } 5205 return didSomething; 5206 } 5207 5208 /** 5209 * @return The set of running tasks through {@param tasksOut} that are available to the caller. 5210 * If {@param ignoreActivityType} or {@param ignoreWindowingMode} are not undefined, 5211 * then skip running tasks that match those types. 5212 */ getRunningTasks(List<TaskRecord> tasksOut, @ActivityType int ignoreActivityType, @WindowingMode int ignoreWindowingMode, int callingUid, boolean allowed)5213 void getRunningTasks(List<TaskRecord> tasksOut, @ActivityType int ignoreActivityType, 5214 @WindowingMode int ignoreWindowingMode, int callingUid, boolean allowed) { 5215 boolean focusedStack = mRootActivityContainer.getTopDisplayFocusedStack() == this; 5216 boolean topTask = true; 5217 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5218 final TaskRecord task = mTaskHistory.get(taskNdx); 5219 if (task.getTopActivity() == null) { 5220 // Skip if there are no activities in the task 5221 continue; 5222 } 5223 if (!allowed && !task.isActivityTypeHome() && task.effectiveUid != callingUid) { 5224 // Skip if the caller can't fetch this task 5225 continue; 5226 } 5227 if (ignoreActivityType != ACTIVITY_TYPE_UNDEFINED 5228 && task.getActivityType() == ignoreActivityType) { 5229 // Skip ignored activity type 5230 continue; 5231 } 5232 if (ignoreWindowingMode != WINDOWING_MODE_UNDEFINED 5233 && task.getWindowingMode() == ignoreWindowingMode) { 5234 // Skip ignored windowing mode 5235 continue; 5236 } 5237 if (focusedStack && topTask) { 5238 // For the focused stack top task, update the last stack active time so that it can 5239 // be used to determine the order of the tasks (it may not be set for newly created 5240 // tasks) 5241 task.lastActiveTime = SystemClock.elapsedRealtime(); 5242 topTask = false; 5243 } 5244 tasksOut.add(task); 5245 } 5246 } 5247 unhandledBackLocked()5248 void unhandledBackLocked() { 5249 final int top = mTaskHistory.size() - 1; 5250 if (DEBUG_SWITCH) Slog.d(TAG_SWITCH, "Performing unhandledBack(): top activity at " + top); 5251 if (top >= 0) { 5252 final ArrayList<ActivityRecord> activities = mTaskHistory.get(top).mActivities; 5253 int activityTop = activities.size() - 1; 5254 if (activityTop >= 0) { 5255 finishActivityLocked(activities.get(activityTop), Activity.RESULT_CANCELED, null, 5256 "unhandled-back", true); 5257 } 5258 } 5259 } 5260 5261 /** 5262 * Reset local parameters because an app's activity died. 5263 * @param app The app of the activity that died. 5264 * @return result from removeHistoryRecordsForAppLocked. 5265 */ handleAppDiedLocked(WindowProcessController app)5266 boolean handleAppDiedLocked(WindowProcessController app) { 5267 if (mPausingActivity != null && mPausingActivity.app == app) { 5268 if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG_PAUSE, 5269 "App died while pausing: " + mPausingActivity); 5270 mPausingActivity = null; 5271 } 5272 if (mLastPausedActivity != null && mLastPausedActivity.app == app) { 5273 mLastPausedActivity = null; 5274 mLastNoHistoryActivity = null; 5275 } 5276 5277 return removeHistoryRecordsForAppLocked(app); 5278 } 5279 handleAppCrash(WindowProcessController app)5280 void handleAppCrash(WindowProcessController app) { 5281 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5282 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 5283 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 5284 final ActivityRecord r = activities.get(activityNdx); 5285 if (r.app == app) { 5286 Slog.w(TAG, " Force finishing activity " 5287 + r.intent.getComponent().flattenToShortString()); 5288 // Force the destroy to skip right to removal. 5289 r.app = null; 5290 getDisplay().mDisplayContent.prepareAppTransition( 5291 TRANSIT_CRASHING_ACTIVITY_CLOSE, false /* alwaysKeepCurrent */); 5292 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false, 5293 "handleAppCrashedLocked"); 5294 } 5295 } 5296 } 5297 } 5298 dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient, String dumpPackage, boolean needSep)5299 boolean dump(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient, 5300 String dumpPackage, boolean needSep) { 5301 pw.println(" Stack #" + mStackId 5302 + ": type=" + activityTypeToString(getActivityType()) 5303 + " mode=" + windowingModeToString(getWindowingMode())); 5304 pw.println(" isSleeping=" + shouldSleepActivities()); 5305 pw.println(" mBounds=" + getRequestedOverrideBounds()); 5306 5307 boolean printed = dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage, 5308 needSep); 5309 5310 printed |= dumpHistoryList(fd, pw, mLRUActivities, " ", "Run", false, 5311 !dumpAll, false, dumpPackage, true, 5312 " Running activities (most recent first):", null); 5313 5314 needSep = printed; 5315 boolean pr = printThisActivity(pw, mPausingActivity, dumpPackage, needSep, 5316 " mPausingActivity: "); 5317 if (pr) { 5318 printed = true; 5319 needSep = false; 5320 } 5321 pr = printThisActivity(pw, getResumedActivity(), dumpPackage, needSep, 5322 " mResumedActivity: "); 5323 if (pr) { 5324 printed = true; 5325 needSep = false; 5326 } 5327 if (dumpAll) { 5328 pr = printThisActivity(pw, mLastPausedActivity, dumpPackage, needSep, 5329 " mLastPausedActivity: "); 5330 if (pr) { 5331 printed = true; 5332 needSep = true; 5333 } 5334 printed |= printThisActivity(pw, mLastNoHistoryActivity, dumpPackage, 5335 needSep, " mLastNoHistoryActivity: "); 5336 } 5337 return printed; 5338 } 5339 dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll, boolean dumpClient, String dumpPackage, boolean needSep)5340 boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll, 5341 boolean dumpClient, String dumpPackage, boolean needSep) { 5342 5343 if (mTaskHistory.isEmpty()) { 5344 return false; 5345 } 5346 final String prefix = " "; 5347 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5348 final TaskRecord task = mTaskHistory.get(taskNdx); 5349 if (needSep) { 5350 pw.println(""); 5351 } 5352 pw.println(prefix + "Task id #" + task.taskId); 5353 pw.println(prefix + "mBounds=" + task.getRequestedOverrideBounds()); 5354 pw.println(prefix + "mMinWidth=" + task.mMinWidth); 5355 pw.println(prefix + "mMinHeight=" + task.mMinHeight); 5356 pw.println(prefix + "mLastNonFullscreenBounds=" + task.mLastNonFullscreenBounds); 5357 pw.println(prefix + "* " + task); 5358 task.dump(pw, prefix + " "); 5359 dumpHistoryList(fd, pw, mTaskHistory.get(taskNdx).mActivities, 5360 prefix, "Hist", true, !dumpAll, dumpClient, dumpPackage, false, null, task); 5361 } 5362 return true; 5363 } 5364 getDumpActivitiesLocked(String name)5365 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) { 5366 ArrayList<ActivityRecord> activities = new ArrayList<>(); 5367 5368 if ("all".equals(name)) { 5369 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5370 activities.addAll(mTaskHistory.get(taskNdx).mActivities); 5371 } 5372 } else if ("top".equals(name)) { 5373 final int top = mTaskHistory.size() - 1; 5374 if (top >= 0) { 5375 final ArrayList<ActivityRecord> list = mTaskHistory.get(top).mActivities; 5376 int listTop = list.size() - 1; 5377 if (listTop >= 0) { 5378 activities.add(list.get(listTop)); 5379 } 5380 } 5381 } else { 5382 ItemMatcher matcher = new ItemMatcher(); 5383 matcher.build(name); 5384 5385 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5386 for (ActivityRecord r1 : mTaskHistory.get(taskNdx).mActivities) { 5387 if (matcher.match(r1, r1.intent.getComponent())) { 5388 activities.add(r1); 5389 } 5390 } 5391 } 5392 } 5393 5394 return activities; 5395 } 5396 restartPackage(String packageName)5397 ActivityRecord restartPackage(String packageName) { 5398 ActivityRecord starting = topRunningActivityLocked(); 5399 5400 // All activities that came from the package must be 5401 // restarted as if there was a config change. 5402 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5403 final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities; 5404 for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) { 5405 final ActivityRecord a = activities.get(activityNdx); 5406 if (a.info.packageName.equals(packageName)) { 5407 a.forceNewConfig = true; 5408 if (starting != null && a == starting && a.visible) { 5409 a.startFreezingScreenLocked(starting.app, 5410 CONFIG_SCREEN_LAYOUT); 5411 } 5412 } 5413 } 5414 } 5415 5416 return starting; 5417 } 5418 5419 /** 5420 * Removes the input task from this stack. 5421 * 5422 * @param task to remove. 5423 * @param reason for removal. 5424 * @param mode task removal mode. Either {@link #REMOVE_TASK_MODE_DESTROYING}, 5425 * {@link #REMOVE_TASK_MODE_MOVING}, {@link #REMOVE_TASK_MODE_MOVING_TO_TOP}. 5426 */ removeTask(TaskRecord task, String reason, int mode)5427 void removeTask(TaskRecord task, String reason, int mode) { 5428 final boolean removed = mTaskHistory.remove(task); 5429 5430 if (removed) { 5431 EventLog.writeEvent(EventLogTags.AM_REMOVE_TASK, task.taskId, getStackId()); 5432 } 5433 5434 removeActivitiesFromLRUListLocked(task); 5435 updateTaskMovement(task, true); 5436 5437 if (mode == REMOVE_TASK_MODE_DESTROYING) { 5438 task.cleanUpResourcesForDestroy(); 5439 } 5440 5441 if (mTaskHistory.isEmpty()) { 5442 if (DEBUG_STACK) Slog.i(TAG_STACK, "removeTask: removing stack=" + this); 5443 // We only need to adjust focused stack if this stack is in focus and we are not in the 5444 // process of moving the task to the top of the stack that will be focused. 5445 if (mode != REMOVE_TASK_MODE_MOVING_TO_TOP 5446 && mRootActivityContainer.isTopDisplayFocusedStack(this)) { 5447 String myReason = reason + " leftTaskHistoryEmpty"; 5448 if (!inMultiWindowMode() || adjustFocusToNextFocusableStack(myReason) == null) { 5449 getDisplay().moveHomeStackToFront(myReason); 5450 } 5451 } 5452 if (isAttached()) { 5453 getDisplay().positionChildAtBottom(this); 5454 } 5455 if (!isActivityTypeHome() || !isAttached()) { 5456 remove(); 5457 } 5458 } 5459 5460 task.setStack(null); 5461 5462 // Notify if a task from the pinned stack is being removed (or moved depending on the mode) 5463 if (inPinnedWindowingMode()) { 5464 mService.getTaskChangeNotificationController().notifyActivityUnpinned(); 5465 } 5466 } 5467 createTaskRecord(int taskId, ActivityInfo info, Intent intent, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, boolean toTop)5468 TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent, 5469 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, 5470 boolean toTop) { 5471 return createTaskRecord(taskId, info, intent, voiceSession, voiceInteractor, toTop, 5472 null /*activity*/, null /*source*/, null /*options*/); 5473 } 5474 createTaskRecord(int taskId, ActivityInfo info, Intent intent, IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, boolean toTop, ActivityRecord activity, ActivityRecord source, ActivityOptions options)5475 TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent, 5476 IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, 5477 boolean toTop, ActivityRecord activity, ActivityRecord source, 5478 ActivityOptions options) { 5479 final TaskRecord task = TaskRecord.create( 5480 mService, taskId, info, intent, voiceSession, voiceInteractor); 5481 // add the task to stack first, mTaskPositioner might need the stack association 5482 addTask(task, toTop, "createTaskRecord"); 5483 final int displayId = mDisplayId != INVALID_DISPLAY ? mDisplayId : DEFAULT_DISPLAY; 5484 final boolean isLockscreenShown = mService.mStackSupervisor.getKeyguardController() 5485 .isKeyguardOrAodShowing(displayId); 5486 if (!mStackSupervisor.getLaunchParamsController() 5487 .layoutTask(task, info.windowLayout, activity, source, options) 5488 && !matchParentBounds() && task.isResizeable() && !isLockscreenShown) { 5489 task.updateOverrideConfiguration(getRequestedOverrideBounds()); 5490 } 5491 task.createTask(toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0); 5492 return task; 5493 } 5494 getAllTasks()5495 ArrayList<TaskRecord> getAllTasks() { 5496 return new ArrayList<>(mTaskHistory); 5497 } 5498 addTask(final TaskRecord task, final boolean toTop, String reason)5499 void addTask(final TaskRecord task, final boolean toTop, String reason) { 5500 addTask(task, toTop ? MAX_VALUE : 0, true /* schedulePictureInPictureModeChange */, reason); 5501 if (toTop) { 5502 // TODO: figure-out a way to remove this call. 5503 positionChildWindowContainerAtTop(task); 5504 } 5505 } 5506 5507 // TODO: This shouldn't allow automatic reparenting. Remove the call to preAddTask and deal 5508 // with the fall-out... addTask(final TaskRecord task, int position, boolean schedulePictureInPictureModeChange, String reason)5509 void addTask(final TaskRecord task, int position, boolean schedulePictureInPictureModeChange, 5510 String reason) { 5511 // TODO: Is this remove really needed? Need to look into the call path for the other addTask 5512 mTaskHistory.remove(task); 5513 if (isSingleTaskInstance() && !mTaskHistory.isEmpty()) { 5514 throw new IllegalStateException("Can only have one child on stack=" + this); 5515 } 5516 5517 position = getAdjustedPositionForTask(task, position, null /* starting */); 5518 final boolean toTop = position >= mTaskHistory.size(); 5519 final ActivityStack prevStack = preAddTask(task, reason, toTop); 5520 5521 mTaskHistory.add(position, task); 5522 task.setStack(this); 5523 5524 updateTaskMovement(task, toTop); 5525 5526 postAddTask(task, prevStack, schedulePictureInPictureModeChange); 5527 } 5528 positionChildAt(TaskRecord task, int index)5529 void positionChildAt(TaskRecord task, int index) { 5530 5531 if (task.getStack() != this) { 5532 throw new IllegalArgumentException("AS.positionChildAt: task=" + task 5533 + " is not a child of stack=" + this + " current parent=" + task.getStack()); 5534 } 5535 5536 task.updateOverrideConfigurationForStack(this); 5537 5538 final ActivityRecord topRunningActivity = task.topRunningActivityLocked(); 5539 final boolean wasResumed = topRunningActivity == task.getStack().mResumedActivity; 5540 insertTaskAtPosition(task, index); 5541 task.setStack(this); 5542 postAddTask(task, null /* prevStack */, true /* schedulePictureInPictureModeChange */); 5543 5544 if (wasResumed) { 5545 if (mResumedActivity != null) { 5546 Log.wtf(TAG, "mResumedActivity was already set when moving mResumedActivity from" 5547 + " other stack to this stack mResumedActivity=" + mResumedActivity 5548 + " other mResumedActivity=" + topRunningActivity); 5549 } 5550 topRunningActivity.setState(RESUMED, "positionChildAt"); 5551 } 5552 5553 // The task might have already been running and its visibility needs to be synchronized with 5554 // the visibility of the stack / windows. 5555 ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS); 5556 mRootActivityContainer.resumeFocusedStacksTopActivities(); 5557 } 5558 preAddTask(TaskRecord task, String reason, boolean toTop)5559 private ActivityStack preAddTask(TaskRecord task, String reason, boolean toTop) { 5560 final ActivityStack prevStack = task.getStack(); 5561 if (prevStack != null && prevStack != this) { 5562 prevStack.removeTask(task, reason, 5563 toTop ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING); 5564 } 5565 return prevStack; 5566 } 5567 5568 /** 5569 * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode 5570 * change. Callers may set this to false if they are explicitly scheduling PiP mode 5571 * changes themselves, like during the PiP animation 5572 */ postAddTask(TaskRecord task, ActivityStack prevStack, boolean schedulePictureInPictureModeChange)5573 private void postAddTask(TaskRecord task, ActivityStack prevStack, 5574 boolean schedulePictureInPictureModeChange) { 5575 if (schedulePictureInPictureModeChange && prevStack != null) { 5576 mStackSupervisor.scheduleUpdatePictureInPictureModeIfNeeded(task, prevStack); 5577 } else if (task.voiceSession != null) { 5578 try { 5579 task.voiceSession.taskStarted(task.intent, task.taskId); 5580 } catch (RemoteException e) { 5581 } 5582 } 5583 } 5584 setAlwaysOnTop(boolean alwaysOnTop)5585 public void setAlwaysOnTop(boolean alwaysOnTop) { 5586 if (isAlwaysOnTop() == alwaysOnTop) { 5587 return; 5588 } 5589 super.setAlwaysOnTop(alwaysOnTop); 5590 final ActivityDisplay display = getDisplay(); 5591 // positionChildAtTop() must be called even when always on top gets turned off because we 5592 // need to make sure that the stack is moved from among always on top windows to below other 5593 // always on top windows. Since the position the stack should be inserted into is calculated 5594 // properly in {@link ActivityDisplay#getTopInsertPosition()} in both cases, we can just 5595 // request that the stack is put at top here. 5596 display.positionChildAtTop(this, false /* includingParents */); 5597 } 5598 5599 /** NOTE: Should only be called from {@link TaskRecord#reparent}. */ moveToFrontAndResumeStateIfNeeded(ActivityRecord r, boolean moveToFront, boolean setResume, boolean setPause, String reason)5600 void moveToFrontAndResumeStateIfNeeded(ActivityRecord r, boolean moveToFront, boolean setResume, 5601 boolean setPause, String reason) { 5602 if (!moveToFront) { 5603 return; 5604 } 5605 5606 final ActivityState origState = r.getState(); 5607 // If the activity owns the last resumed activity, transfer that together, 5608 // so that we don't resume the same activity again in the new stack. 5609 // Apps may depend on onResume()/onPause() being called in pairs. 5610 if (setResume) { 5611 r.setState(RESUMED, "moveToFrontAndResumeStateIfNeeded"); 5612 updateLRUListLocked(r); 5613 } 5614 // If the activity was previously pausing, then ensure we transfer that as well 5615 if (setPause) { 5616 mPausingActivity = r; 5617 schedulePauseTimeout(r); 5618 } 5619 // Move the stack in which we are placing the activity to the front. 5620 moveToFront(reason); 5621 // If the original state is resumed, there is no state change to update focused app. 5622 // So here makes sure the activity focus is set if it is the top. 5623 if (origState == RESUMED && r == mRootActivityContainer.getTopResumedActivity()) { 5624 // TODO(b/111361570): Support multiple focused apps in WM 5625 mService.setResumedActivityUncheckLocked(r, reason); 5626 } 5627 } 5628 5629 getDefaultPictureInPictureBounds(float aspectRatio)5630 Rect getDefaultPictureInPictureBounds(float aspectRatio) { 5631 if (getTaskStack() == null) return null; 5632 return getTaskStack().getPictureInPictureBounds(aspectRatio, null /* currentStackBounds */); 5633 } 5634 animateResizePinnedStack(Rect sourceHintBounds, Rect toBounds, int animationDuration, boolean fromFullscreen)5635 void animateResizePinnedStack(Rect sourceHintBounds, Rect toBounds, int animationDuration, 5636 boolean fromFullscreen) { 5637 if (!inPinnedWindowingMode()) return; 5638 if (skipResizeAnimation(toBounds == null /* toFullscreen */)) { 5639 mService.moveTasksToFullscreenStack(mStackId, true /* onTop */); 5640 } else { 5641 if (getTaskStack() == null) return; 5642 getTaskStack().animateResizePinnedStack(toBounds, sourceHintBounds, 5643 animationDuration, fromFullscreen); 5644 } 5645 } 5646 5647 /** 5648 * Get current bounds of this stack, return empty when it is unavailable. 5649 * @see TaskStack#getAnimationOrCurrentBounds(Rect) 5650 */ getAnimationOrCurrentBounds(Rect outBounds)5651 void getAnimationOrCurrentBounds(Rect outBounds) { 5652 final TaskStack stack = getTaskStack(); 5653 if (stack == null) { 5654 outBounds.setEmpty(); 5655 return; 5656 } 5657 stack.getAnimationOrCurrentBounds(outBounds); 5658 } 5659 skipResizeAnimation(boolean toFullscreen)5660 private boolean skipResizeAnimation(boolean toFullscreen) { 5661 if (!toFullscreen) { 5662 return false; 5663 } 5664 final Configuration parentConfig = getParent().getConfiguration(); 5665 final ActivityRecord top = topRunningNonOverlayTaskActivity(); 5666 return top != null && !top.isConfigurationCompatible(parentConfig); 5667 } 5668 setPictureInPictureAspectRatio(float aspectRatio)5669 void setPictureInPictureAspectRatio(float aspectRatio) { 5670 if (getTaskStack() == null) return; 5671 getTaskStack().setPictureInPictureAspectRatio(aspectRatio); 5672 } 5673 setPictureInPictureActions(List<RemoteAction> actions)5674 void setPictureInPictureActions(List<RemoteAction> actions) { 5675 if (getTaskStack() == null) return; 5676 getTaskStack().setPictureInPictureActions(actions); 5677 } 5678 isAnimatingBoundsToFullscreen()5679 boolean isAnimatingBoundsToFullscreen() { 5680 if (getTaskStack() == null) return false; 5681 return getTaskStack().isAnimatingBoundsToFullscreen(); 5682 } 5683 updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds, boolean forceUpdate)5684 public void updatePictureInPictureModeForPinnedStackAnimation(Rect targetStackBounds, 5685 boolean forceUpdate) { 5686 // It is guaranteed that the activities requiring the update will be in the pinned stack at 5687 // this point (either reparented before the animation into PiP, or before reparenting after 5688 // the animation out of PiP) 5689 synchronized (mService.mGlobalLock) { 5690 if (!isAttached()) { 5691 return; 5692 } 5693 ArrayList<TaskRecord> tasks = getAllTasks(); 5694 for (int i = 0; i < tasks.size(); i++) { 5695 mStackSupervisor.updatePictureInPictureMode(tasks.get(i), targetStackBounds, 5696 forceUpdate); 5697 } 5698 } 5699 } 5700 getStackId()5701 public int getStackId() { 5702 return mStackId; 5703 } 5704 5705 @Override toString()5706 public String toString() { 5707 return "ActivityStack{" + Integer.toHexString(System.identityHashCode(this)) 5708 + " stackId=" + mStackId + " type=" + activityTypeToString(getActivityType()) 5709 + " mode=" + windowingModeToString(getWindowingMode()) 5710 + " visible=" + shouldBeVisible(null /* starting */) 5711 + " translucent=" + isStackTranslucent(null /* starting */) 5712 + ", " 5713 + mTaskHistory.size() + " tasks}"; 5714 } 5715 onLockTaskPackagesUpdated()5716 void onLockTaskPackagesUpdated() { 5717 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5718 mTaskHistory.get(taskNdx).setLockTaskAuth(); 5719 } 5720 } 5721 executeAppTransition(ActivityOptions options)5722 void executeAppTransition(ActivityOptions options) { 5723 getDisplay().mDisplayContent.executeAppTransition(); 5724 ActivityOptions.abort(options); 5725 } 5726 shouldSleepActivities()5727 boolean shouldSleepActivities() { 5728 final ActivityDisplay display = getDisplay(); 5729 5730 // Do not sleep activities in this stack if we're marked as focused and the keyguard 5731 // is in the process of going away. 5732 if (isFocusedStackOnDisplay() 5733 && mStackSupervisor.getKeyguardController().isKeyguardGoingAway()) { 5734 return false; 5735 } 5736 5737 return display != null ? display.isSleeping() : mService.isSleepingLocked(); 5738 } 5739 shouldSleepOrShutDownActivities()5740 boolean shouldSleepOrShutDownActivities() { 5741 return shouldSleepActivities() || mService.mShuttingDown; 5742 } 5743 writeToProto(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel)5744 public void writeToProto(ProtoOutputStream proto, long fieldId, 5745 @WindowTraceLogLevel int logLevel) { 5746 final long token = proto.start(fieldId); 5747 super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel); 5748 proto.write(ID, mStackId); 5749 for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { 5750 final TaskRecord task = mTaskHistory.get(taskNdx); 5751 task.writeToProto(proto, TASKS, logLevel); 5752 } 5753 if (mResumedActivity != null) { 5754 mResumedActivity.writeIdentifierToProto(proto, RESUMED_ACTIVITY); 5755 } 5756 proto.write(DISPLAY_ID, mDisplayId); 5757 if (!matchParentBounds()) { 5758 final Rect bounds = getRequestedOverrideBounds(); 5759 bounds.writeToProto(proto, BOUNDS); 5760 } 5761 5762 // TODO: Remove, no longer needed with windowingMode. 5763 proto.write(FULLSCREEN, matchParentBounds()); 5764 proto.end(token); 5765 } 5766 } 5767