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