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