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