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