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