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