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