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