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