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