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