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