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