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