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