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