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