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