ActivityStack.java revision b1fd65c0ff5784b90d765edb7e3c3115d767dff0
1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.server.am; 18 19import static android.Manifest.permission.START_ANY_ACTIVITY; 20import static android.content.pm.PackageManager.PERMISSION_GRANTED; 21 22import com.android.internal.app.HeavyWeightSwitcherActivity; 23import com.android.internal.os.BatteryStatsImpl; 24import com.android.server.am.ActivityManagerService.PendingActivityLaunch; 25import com.android.server.am.ActivityRecord.Token; 26import com.android.server.wm.AppTransition; 27 28import android.app.Activity; 29import android.app.ActivityManager; 30import android.app.ActivityOptions; 31import android.app.AppGlobals; 32import android.app.IActivityManager; 33import android.app.IThumbnailRetriever; 34import android.app.IApplicationThread; 35import android.app.PendingIntent; 36import android.app.ResultInfo; 37import android.app.IActivityManager.WaitResult; 38import android.content.ComponentName; 39import android.content.Context; 40import android.content.IIntentSender; 41import android.content.Intent; 42import android.content.IntentSender; 43import android.content.pm.ActivityInfo; 44import android.content.pm.ApplicationInfo; 45import android.content.pm.PackageManager; 46import android.content.pm.ResolveInfo; 47import android.content.res.Configuration; 48import android.content.res.Resources; 49import android.graphics.Bitmap; 50import android.graphics.Bitmap.Config; 51import android.os.Binder; 52import android.os.Bundle; 53import android.os.Handler; 54import android.os.IBinder; 55import android.os.Looper; 56import android.os.Message; 57import android.os.ParcelFileDescriptor; 58import android.os.PowerManager; 59import android.os.RemoteException; 60import android.os.SystemClock; 61import android.os.UserHandle; 62import android.util.EventLog; 63import android.util.Log; 64import android.util.Slog; 65import android.view.Display; 66 67import java.io.IOException; 68import java.lang.ref.WeakReference; 69import java.util.ArrayList; 70import java.util.Iterator; 71import java.util.List; 72 73/** 74 * State and management of a single stack of activities. 75 */ 76final 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<TaskGroup> mValidateAppTokens = new ArrayList<TaskGroup>(); 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 int taskId = Integer.MIN_VALUE; 1964 TaskGroup task = null; 1965 for (int i=0; i<mHistory.size(); i++) { 1966 final ActivityRecord r = mHistory.get(i); 1967 if (taskId != r.task.taskId) { 1968 taskId = r.task.taskId; 1969 task = new TaskGroup(); 1970 task.taskId = taskId; 1971 mValidateAppTokens.add(task); 1972 } 1973 task.tokens.add(r.appToken); 1974 } 1975 mService.mWindowManager.validateAppTokens(mValidateAppTokens); 1976 } 1977 1978 /** 1979 * Perform a reset of the given task, if needed as part of launching it. 1980 * Returns the new HistoryRecord at the top of the task. 1981 */ 1982 private final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop, 1983 ActivityRecord newActivity) { 1984 boolean forceReset = (newActivity.info.flags 1985 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0; 1986 if (ACTIVITY_INACTIVE_RESET_TIME > 0 1987 && taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) { 1988 if ((newActivity.info.flags 1989 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) { 1990 forceReset = true; 1991 } 1992 } 1993 1994 final TaskRecord task = taskTop.task; 1995 1996 // We are going to move through the history list so that we can look 1997 // at each activity 'target' with 'below' either the interesting 1998 // activity immediately below it in the stack or null. 1999 ActivityRecord target = null; 2000 int targetI = 0; 2001 int taskTopI = -1; 2002 int replyChainEnd = -1; 2003 int lastReparentPos = -1; 2004 ActivityOptions topOptions = null; 2005 boolean canMoveOptions = true; 2006 for (int i=mHistory.size()-1; i>=-1; i--) { 2007 ActivityRecord below = i >= 0 ? mHistory.get(i) : null; 2008 2009 if (below != null && below.finishing) { 2010 continue; 2011 } 2012 // Don't check any lower in the stack if we're crossing a user boundary. 2013 if (below != null && below.userId != taskTop.userId) { 2014 break; 2015 } 2016 if (target == null) { 2017 target = below; 2018 targetI = i; 2019 // If we were in the middle of a reply chain before this 2020 // task, it doesn't appear like the root of the chain wants 2021 // anything interesting, so drop it. 2022 replyChainEnd = -1; 2023 continue; 2024 } 2025 2026 final int flags = target.info.flags; 2027 2028 final boolean finishOnTaskLaunch = 2029 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0; 2030 final boolean allowTaskReparenting = 2031 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0; 2032 2033 if (target.task == task) { 2034 // We are inside of the task being reset... we'll either 2035 // finish this activity, push it out for another task, 2036 // or leave it as-is. We only do this 2037 // for activities that are not the root of the task (since 2038 // if we finish the root, we may no longer have the task!). 2039 if (taskTopI < 0) { 2040 taskTopI = targetI; 2041 } 2042 if (below != null && below.task == task) { 2043 final boolean clearWhenTaskReset = 2044 (target.intent.getFlags() 2045 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0; 2046 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) { 2047 // If this activity is sending a reply to a previous 2048 // activity, we can't do anything with it now until 2049 // we reach the start of the reply chain. 2050 // XXX note that we are assuming the result is always 2051 // to the previous activity, which is almost always 2052 // the case but we really shouldn't count on. 2053 if (replyChainEnd < 0) { 2054 replyChainEnd = targetI; 2055 } 2056 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting 2057 && target.taskAffinity != null 2058 && !target.taskAffinity.equals(task.affinity)) { 2059 // If this activity has an affinity for another 2060 // task, then we need to move it out of here. We will 2061 // move it as far out of the way as possible, to the 2062 // bottom of the activity stack. This also keeps it 2063 // correctly ordered with any activities we previously 2064 // moved. 2065 ActivityRecord p = mHistory.get(0); 2066 if (target.taskAffinity != null 2067 && target.taskAffinity.equals(p.task.affinity)) { 2068 // If the activity currently at the bottom has the 2069 // same task affinity as the one we are moving, 2070 // then merge it into the same task. 2071 target.setTask(p.task, p.thumbHolder, false); 2072 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target 2073 + " out to bottom task " + p.task); 2074 } else { 2075 mService.mCurTask++; 2076 if (mService.mCurTask <= 0) { 2077 mService.mCurTask = 1; 2078 } 2079 target.setTask(new TaskRecord(mService.mCurTask, target.info, null), 2080 null, false); 2081 target.task.affinityIntent = target.intent; 2082 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target 2083 + " out to new task " + target.task); 2084 } 2085 mService.mWindowManager.setAppGroupId(target.appToken, task.taskId); 2086 if (replyChainEnd < 0) { 2087 replyChainEnd = targetI; 2088 } 2089 int dstPos = 0; 2090 ThumbnailHolder curThumbHolder = target.thumbHolder; 2091 boolean gotOptions = !canMoveOptions; 2092 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) { 2093 p = mHistory.get(srcPos); 2094 if (p.finishing) { 2095 continue; 2096 } 2097 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p 2098 + " out to target's task " + target.task); 2099 p.setTask(target.task, curThumbHolder, false); 2100 curThumbHolder = p.thumbHolder; 2101 canMoveOptions = false; 2102 if (!gotOptions && topOptions == null) { 2103 topOptions = p.takeOptionsLocked(); 2104 if (topOptions != null) { 2105 gotOptions = true; 2106 } 2107 } 2108 if (DEBUG_ADD_REMOVE) { 2109 RuntimeException here = new RuntimeException("here"); 2110 here.fillInStackTrace(); 2111 Slog.i(TAG, "Removing and adding activity " + p + " to stack at " 2112 + dstPos, here); 2113 } 2114 mHistory.remove(srcPos); 2115 mHistory.add(dstPos, p); 2116 mService.mWindowManager.moveAppToken(dstPos, p.appToken); 2117 mService.mWindowManager.setAppGroupId(p.appToken, p.task.taskId); 2118 dstPos++; 2119 if (VALIDATE_TOKENS) { 2120 validateAppTokensLocked(); 2121 } 2122 i++; 2123 } 2124 if (taskTop == p) { 2125 taskTop = below; 2126 } 2127 if (taskTopI == replyChainEnd) { 2128 taskTopI = -1; 2129 } 2130 replyChainEnd = -1; 2131 } else if (forceReset || finishOnTaskLaunch 2132 || clearWhenTaskReset) { 2133 // If the activity should just be removed -- either 2134 // because it asks for it, or the task should be 2135 // cleared -- then finish it and anything that is 2136 // part of its reply chain. 2137 if (clearWhenTaskReset) { 2138 // In this case, we want to finish this activity 2139 // and everything above it, so be sneaky and pretend 2140 // like these are all in the reply chain. 2141 replyChainEnd = targetI+1; 2142 while (replyChainEnd < mHistory.size() && 2143 (mHistory.get( 2144 replyChainEnd)).task == task) { 2145 replyChainEnd++; 2146 } 2147 replyChainEnd--; 2148 } else if (replyChainEnd < 0) { 2149 replyChainEnd = targetI; 2150 } 2151 ActivityRecord p = null; 2152 boolean gotOptions = !canMoveOptions; 2153 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) { 2154 p = mHistory.get(srcPos); 2155 if (p.finishing) { 2156 continue; 2157 } 2158 canMoveOptions = false; 2159 if (!gotOptions && topOptions == null) { 2160 topOptions = p.takeOptionsLocked(); 2161 if (topOptions != null) { 2162 gotOptions = true; 2163 } 2164 } 2165 if (finishActivityLocked(p, srcPos, 2166 Activity.RESULT_CANCELED, null, "reset", false)) { 2167 replyChainEnd--; 2168 srcPos--; 2169 } 2170 } 2171 if (taskTop == p) { 2172 taskTop = below; 2173 } 2174 if (taskTopI == replyChainEnd) { 2175 taskTopI = -1; 2176 } 2177 replyChainEnd = -1; 2178 } else { 2179 // If we were in the middle of a chain, well the 2180 // activity that started it all doesn't want anything 2181 // special, so leave it all as-is. 2182 replyChainEnd = -1; 2183 } 2184 } else { 2185 // Reached the bottom of the task -- any reply chain 2186 // should be left as-is. 2187 replyChainEnd = -1; 2188 } 2189 2190 } else if (target.resultTo != null && (below == null 2191 || below.task == target.task)) { 2192 // If this activity is sending a reply to a previous 2193 // activity, we can't do anything with it now until 2194 // we reach the start of the reply chain. 2195 // XXX note that we are assuming the result is always 2196 // to the previous activity, which is almost always 2197 // the case but we really shouldn't count on. 2198 if (replyChainEnd < 0) { 2199 replyChainEnd = targetI; 2200 } 2201 2202 } else if (taskTopI >= 0 && allowTaskReparenting 2203 && task.affinity != null 2204 && task.affinity.equals(target.taskAffinity)) { 2205 // We are inside of another task... if this activity has 2206 // an affinity for our task, then either remove it if we are 2207 // clearing or move it over to our task. Note that 2208 // we currently punt on the case where we are resetting a 2209 // task that is not at the top but who has activities above 2210 // with an affinity to it... this is really not a normal 2211 // case, and we will need to later pull that task to the front 2212 // and usually at that point we will do the reset and pick 2213 // up those remaining activities. (This only happens if 2214 // someone starts an activity in a new task from an activity 2215 // in a task that is not currently on top.) 2216 if (forceReset || finishOnTaskLaunch) { 2217 if (replyChainEnd < 0) { 2218 replyChainEnd = targetI; 2219 } 2220 ActivityRecord p = null; 2221 if (DEBUG_TASKS) Slog.v(TAG, "Finishing task at index " 2222 + targetI + " to " + replyChainEnd); 2223 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) { 2224 p = mHistory.get(srcPos); 2225 if (p.finishing) { 2226 continue; 2227 } 2228 if (finishActivityLocked(p, srcPos, 2229 Activity.RESULT_CANCELED, null, "reset", false)) { 2230 taskTopI--; 2231 lastReparentPos--; 2232 replyChainEnd--; 2233 srcPos--; 2234 } 2235 } 2236 replyChainEnd = -1; 2237 } else { 2238 if (replyChainEnd < 0) { 2239 replyChainEnd = targetI; 2240 } 2241 if (DEBUG_TASKS) Slog.v(TAG, "Reparenting task at index " 2242 + targetI + " to " + replyChainEnd); 2243 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) { 2244 ActivityRecord p = mHistory.get(srcPos); 2245 if (p.finishing) { 2246 continue; 2247 } 2248 if (lastReparentPos < 0) { 2249 lastReparentPos = taskTopI; 2250 taskTop = p; 2251 } else { 2252 lastReparentPos--; 2253 } 2254 if (DEBUG_ADD_REMOVE) { 2255 RuntimeException here = new RuntimeException("here"); 2256 here.fillInStackTrace(); 2257 Slog.i(TAG, "Removing and adding activity " + p + " to stack at " 2258 + lastReparentPos, here); 2259 } 2260 mHistory.remove(srcPos); 2261 p.setTask(task, null, false); 2262 mHistory.add(lastReparentPos, p); 2263 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p 2264 + " from " + srcPos + " to " + lastReparentPos 2265 + " in to resetting task " + task); 2266 mService.mWindowManager.moveAppToken(lastReparentPos, p.appToken); 2267 mService.mWindowManager.setAppGroupId(p.appToken, p.task.taskId); 2268 if (VALIDATE_TOKENS) { 2269 validateAppTokensLocked(); 2270 } 2271 } 2272 replyChainEnd = -1; 2273 2274 // Now we've moved it in to place... but what if this is 2275 // a singleTop activity and we have put it on top of another 2276 // instance of the same activity? Then we drop the instance 2277 // below so it remains singleTop. 2278 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) { 2279 for (int j=lastReparentPos-1; j>=0; j--) { 2280 ActivityRecord p = mHistory.get(j); 2281 if (p.finishing) { 2282 continue; 2283 } 2284 if (p.intent.getComponent().equals(target.intent.getComponent())) { 2285 if (finishActivityLocked(p, j, 2286 Activity.RESULT_CANCELED, null, "replace", false)) { 2287 taskTopI--; 2288 lastReparentPos--; 2289 } 2290 } 2291 } 2292 } 2293 } 2294 2295 } else if (below != null && below.task != target.task) { 2296 // We hit the botton of a task; the reply chain can't 2297 // pass through it. 2298 replyChainEnd = -1; 2299 } 2300 2301 target = below; 2302 targetI = i; 2303 } 2304 2305 if (topOptions != null) { 2306 // If we got some ActivityOptions from an activity on top that 2307 // was removed from the task, propagate them to the new real top. 2308 if (taskTop != null) { 2309 taskTop.updateOptionsLocked(topOptions); 2310 } else { 2311 topOptions.abort(); 2312 } 2313 } 2314 2315 return taskTop; 2316 } 2317 2318 /** 2319 * Perform clear operation as requested by 2320 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the 2321 * stack to the given task, then look for 2322 * an instance of that activity in the stack and, if found, finish all 2323 * activities on top of it and return the instance. 2324 * 2325 * @param newR Description of the new activity being started. 2326 * @return Returns the old activity that should be continued to be used, 2327 * or null if none was found. 2328 */ 2329 private final ActivityRecord performClearTaskLocked(int taskId, 2330 ActivityRecord newR, int launchFlags) { 2331 int i = mHistory.size(); 2332 2333 // First find the requested task. 2334 while (i > 0) { 2335 i--; 2336 ActivityRecord r = mHistory.get(i); 2337 if (r.task.taskId == taskId) { 2338 i++; 2339 break; 2340 } 2341 } 2342 2343 // Now clear it. 2344 while (i > 0) { 2345 i--; 2346 ActivityRecord r = mHistory.get(i); 2347 if (r.finishing) { 2348 continue; 2349 } 2350 if (r.task.taskId != taskId) { 2351 return null; 2352 } 2353 if (r.realActivity.equals(newR.realActivity)) { 2354 // Here it is! Now finish everything in front... 2355 ActivityRecord ret = r; 2356 while (i < (mHistory.size()-1)) { 2357 i++; 2358 r = mHistory.get(i); 2359 if (r.task.taskId != taskId) { 2360 break; 2361 } 2362 if (r.finishing) { 2363 continue; 2364 } 2365 ActivityOptions opts = r.takeOptionsLocked(); 2366 if (opts != null) { 2367 ret.updateOptionsLocked(opts); 2368 } 2369 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED, 2370 null, "clear", false)) { 2371 i--; 2372 } 2373 } 2374 2375 // Finally, if this is a normal launch mode (that is, not 2376 // expecting onNewIntent()), then we will finish the current 2377 // instance of the activity so a new fresh one can be started. 2378 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE 2379 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) { 2380 if (!ret.finishing) { 2381 int index = indexOfTokenLocked(ret.appToken); 2382 if (index >= 0) { 2383 finishActivityLocked(ret, index, Activity.RESULT_CANCELED, 2384 null, "clear", false); 2385 } 2386 return null; 2387 } 2388 } 2389 2390 return ret; 2391 } 2392 } 2393 2394 return null; 2395 } 2396 2397 /** 2398 * Completely remove all activities associated with an existing 2399 * task starting at a specified index. 2400 */ 2401 private final void performClearTaskAtIndexLocked(int taskId, int i) { 2402 while (i < mHistory.size()) { 2403 ActivityRecord r = mHistory.get(i); 2404 if (r.task.taskId != taskId) { 2405 // Whoops hit the end. 2406 return; 2407 } 2408 if (r.finishing) { 2409 i++; 2410 continue; 2411 } 2412 if (!finishActivityLocked(r, i, Activity.RESULT_CANCELED, 2413 null, "clear", false)) { 2414 i++; 2415 } 2416 } 2417 } 2418 2419 /** 2420 * Completely remove all activities associated with an existing task. 2421 */ 2422 private final void performClearTaskLocked(int taskId) { 2423 int i = mHistory.size(); 2424 2425 // First find the requested task. 2426 while (i > 0) { 2427 i--; 2428 ActivityRecord r = mHistory.get(i); 2429 if (r.task.taskId == taskId) { 2430 i++; 2431 break; 2432 } 2433 } 2434 2435 // Now find the start and clear it. 2436 while (i > 0) { 2437 i--; 2438 ActivityRecord r = mHistory.get(i); 2439 if (r.finishing) { 2440 continue; 2441 } 2442 if (r.task.taskId != taskId) { 2443 // We hit the bottom. Now finish it all... 2444 performClearTaskAtIndexLocked(taskId, i+1); 2445 return; 2446 } 2447 } 2448 } 2449 2450 /** 2451 * Find the activity in the history stack within the given task. Returns 2452 * the index within the history at which it's found, or < 0 if not found. 2453 */ 2454 private final int findActivityInHistoryLocked(ActivityRecord r, int task) { 2455 int i = mHistory.size(); 2456 while (i > 0) { 2457 i--; 2458 ActivityRecord candidate = mHistory.get(i); 2459 if (candidate.finishing) { 2460 continue; 2461 } 2462 if (candidate.task.taskId != task) { 2463 break; 2464 } 2465 if (candidate.realActivity.equals(r.realActivity)) { 2466 return i; 2467 } 2468 } 2469 2470 return -1; 2471 } 2472 2473 /** 2474 * Reorder the history stack so that the activity at the given index is 2475 * brought to the front. 2476 */ 2477 private final ActivityRecord moveActivityToFrontLocked(int where) { 2478 ActivityRecord newTop = mHistory.remove(where); 2479 int top = mHistory.size(); 2480 ActivityRecord oldTop = mHistory.get(top-1); 2481 if (DEBUG_ADD_REMOVE) { 2482 RuntimeException here = new RuntimeException("here"); 2483 here.fillInStackTrace(); 2484 Slog.i(TAG, "Removing and adding activity " + newTop + " to stack at " 2485 + top, here); 2486 } 2487 mHistory.add(top, newTop); 2488 oldTop.frontOfTask = false; 2489 newTop.frontOfTask = true; 2490 return newTop; 2491 } 2492 2493 final int startActivityLocked(IApplicationThread caller, 2494 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo, 2495 String resultWho, int requestCode, 2496 int callingPid, int callingUid, int startFlags, Bundle options, 2497 boolean componentSpecified, ActivityRecord[] outActivity) { 2498 2499 int err = ActivityManager.START_SUCCESS; 2500 2501 ProcessRecord callerApp = null; 2502 if (caller != null) { 2503 callerApp = mService.getRecordForAppLocked(caller); 2504 if (callerApp != null) { 2505 callingPid = callerApp.pid; 2506 callingUid = callerApp.info.uid; 2507 } else { 2508 Slog.w(TAG, "Unable to find app for caller " + caller 2509 + " (pid=" + callingPid + ") when starting: " 2510 + intent.toString()); 2511 err = ActivityManager.START_PERMISSION_DENIED; 2512 } 2513 } 2514 2515 if (err == ActivityManager.START_SUCCESS) { 2516 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0; 2517 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false) 2518 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid)); 2519 } 2520 2521 ActivityRecord sourceRecord = null; 2522 ActivityRecord resultRecord = null; 2523 if (resultTo != null) { 2524 int index = indexOfTokenLocked(resultTo); 2525 if (DEBUG_RESULTS) Slog.v( 2526 TAG, "Will send result to " + resultTo + " (index " + index + ")"); 2527 if (index >= 0) { 2528 sourceRecord = mHistory.get(index); 2529 if (requestCode >= 0 && !sourceRecord.finishing) { 2530 resultRecord = sourceRecord; 2531 } 2532 } 2533 } 2534 2535 int launchFlags = intent.getFlags(); 2536 2537 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 2538 && sourceRecord != null) { 2539 // Transfer the result target from the source activity to the new 2540 // one being started, including any failures. 2541 if (requestCode >= 0) { 2542 ActivityOptions.abort(options); 2543 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT; 2544 } 2545 resultRecord = sourceRecord.resultTo; 2546 resultWho = sourceRecord.resultWho; 2547 requestCode = sourceRecord.requestCode; 2548 sourceRecord.resultTo = null; 2549 if (resultRecord != null) { 2550 resultRecord.removeResultsLocked( 2551 sourceRecord, resultWho, requestCode); 2552 } 2553 } 2554 2555 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) { 2556 // We couldn't find a class that can handle the given Intent. 2557 // That's the end of that! 2558 err = ActivityManager.START_INTENT_NOT_RESOLVED; 2559 } 2560 2561 if (err == ActivityManager.START_SUCCESS && aInfo == null) { 2562 // We couldn't find the specific class specified in the Intent. 2563 // Also the end of the line. 2564 err = ActivityManager.START_CLASS_NOT_FOUND; 2565 } 2566 2567 if (err != ActivityManager.START_SUCCESS) { 2568 if (resultRecord != null) { 2569 sendActivityResultLocked(-1, 2570 resultRecord, resultWho, requestCode, 2571 Activity.RESULT_CANCELED, null); 2572 } 2573 mDismissKeyguardOnNextActivity = false; 2574 ActivityOptions.abort(options); 2575 return err; 2576 } 2577 2578 final int startAnyPerm = mService.checkPermission( 2579 START_ANY_ACTIVITY, callingPid, callingUid); 2580 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid, 2581 callingUid, aInfo.applicationInfo.uid, aInfo.exported); 2582 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) { 2583 if (resultRecord != null) { 2584 sendActivityResultLocked(-1, 2585 resultRecord, resultWho, requestCode, 2586 Activity.RESULT_CANCELED, null); 2587 } 2588 mDismissKeyguardOnNextActivity = false; 2589 String msg; 2590 if (!aInfo.exported) { 2591 msg = "Permission Denial: starting " + intent.toString() 2592 + " from " + callerApp + " (pid=" + callingPid 2593 + ", uid=" + callingUid + ")" 2594 + " not exported from uid " + aInfo.applicationInfo.uid; 2595 } else { 2596 msg = "Permission Denial: starting " + intent.toString() 2597 + " from " + callerApp + " (pid=" + callingPid 2598 + ", uid=" + callingUid + ")" 2599 + " requires " + aInfo.permission; 2600 } 2601 Slog.w(TAG, msg); 2602 throw new SecurityException(msg); 2603 } 2604 2605 if (mMainStack) { 2606 if (mService.mController != null) { 2607 boolean abort = false; 2608 try { 2609 // The Intent we give to the watcher has the extra data 2610 // stripped off, since it can contain private information. 2611 Intent watchIntent = intent.cloneFilter(); 2612 abort = !mService.mController.activityStarting(watchIntent, 2613 aInfo.applicationInfo.packageName); 2614 } catch (RemoteException e) { 2615 mService.mController = null; 2616 } 2617 2618 if (abort) { 2619 if (resultRecord != null) { 2620 sendActivityResultLocked(-1, 2621 resultRecord, resultWho, requestCode, 2622 Activity.RESULT_CANCELED, null); 2623 } 2624 // We pretend to the caller that it was really started, but 2625 // they will just get a cancel result. 2626 mDismissKeyguardOnNextActivity = false; 2627 ActivityOptions.abort(options); 2628 return ActivityManager.START_SUCCESS; 2629 } 2630 } 2631 } 2632 2633 ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid, 2634 intent, resolvedType, aInfo, mService.mConfiguration, 2635 resultRecord, resultWho, requestCode, componentSpecified); 2636 if (outActivity != null) { 2637 outActivity[0] = r; 2638 } 2639 2640 if (mMainStack) { 2641 if (mResumedActivity == null 2642 || mResumedActivity.info.applicationInfo.uid != callingUid) { 2643 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) { 2644 PendingActivityLaunch pal = new PendingActivityLaunch(); 2645 pal.r = r; 2646 pal.sourceRecord = sourceRecord; 2647 pal.startFlags = startFlags; 2648 mService.mPendingActivityLaunches.add(pal); 2649 mDismissKeyguardOnNextActivity = false; 2650 ActivityOptions.abort(options); 2651 return ActivityManager.START_SWITCHES_CANCELED; 2652 } 2653 } 2654 2655 if (mService.mDidAppSwitch) { 2656 // This is the second allowed switch since we stopped switches, 2657 // so now just generally allow switches. Use case: user presses 2658 // home (switches disabled, switch to home, mDidAppSwitch now true); 2659 // user taps a home icon (coming from home so allowed, we hit here 2660 // and now allow anyone to switch again). 2661 mService.mAppSwitchesAllowedTime = 0; 2662 } else { 2663 mService.mDidAppSwitch = true; 2664 } 2665 2666 mService.doPendingActivityLaunchesLocked(false); 2667 } 2668 2669 err = startActivityUncheckedLocked(r, sourceRecord, 2670 startFlags, true, options); 2671 if (mDismissKeyguardOnNextActivity && mPausingActivity == null) { 2672 // Someone asked to have the keyguard dismissed on the next 2673 // activity start, but we are not actually doing an activity 2674 // switch... just dismiss the keyguard now, because we 2675 // probably want to see whatever is behind it. 2676 mDismissKeyguardOnNextActivity = false; 2677 mService.mWindowManager.dismissKeyguard(); 2678 } 2679 return err; 2680 } 2681 2682 final void moveHomeToFrontFromLaunchLocked(int launchFlags) { 2683 if ((launchFlags & 2684 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) 2685 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) { 2686 // Caller wants to appear on home activity, so before starting 2687 // their own activity we will bring home to the front. 2688 moveHomeToFrontLocked(); 2689 } 2690 } 2691 2692 final int startActivityUncheckedLocked(ActivityRecord r, 2693 ActivityRecord sourceRecord, int startFlags, boolean doResume, 2694 Bundle options) { 2695 final Intent intent = r.intent; 2696 final int callingUid = r.launchedFromUid; 2697 2698 int launchFlags = intent.getFlags(); 2699 2700 // We'll invoke onUserLeaving before onPause only if the launching 2701 // activity did not explicitly state that this is an automated launch. 2702 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0; 2703 if (DEBUG_USER_LEAVING) Slog.v(TAG, 2704 "startActivity() => mUserLeaving=" + mUserLeaving); 2705 2706 // If the caller has asked not to resume at this point, we make note 2707 // of this in the record so that we can skip it when trying to find 2708 // the top running activity. 2709 if (!doResume) { 2710 r.delayedResume = true; 2711 } 2712 2713 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) 2714 != 0 ? r : null; 2715 2716 // If the onlyIfNeeded flag is set, then we can do this if the activity 2717 // being launched is the same as the one making the call... or, as 2718 // a special case, if we do not know the caller then we count the 2719 // current top activity as the caller. 2720 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { 2721 ActivityRecord checkedCaller = sourceRecord; 2722 if (checkedCaller == null) { 2723 checkedCaller = topRunningNonDelayedActivityLocked(notTop); 2724 } 2725 if (!checkedCaller.realActivity.equals(r.realActivity)) { 2726 // Caller is not the same as launcher, so always needed. 2727 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED; 2728 } 2729 } 2730 2731 if (sourceRecord == null) { 2732 // This activity is not being started from another... in this 2733 // case we -always- start a new task. 2734 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { 2735 Slog.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: " 2736 + intent); 2737 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; 2738 } 2739 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { 2740 // The original activity who is starting us is running as a single 2741 // instance... this new activity it is starting must go on its 2742 // own task. 2743 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; 2744 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE 2745 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) { 2746 // The activity being started is a single instance... it always 2747 // gets launched into its own task. 2748 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; 2749 } 2750 2751 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { 2752 // For whatever reason this activity is being launched into a new 2753 // task... yet the caller has requested a result back. Well, that 2754 // is pretty messed up, so instead immediately send back a cancel 2755 // and let the new task continue launched as normal without a 2756 // dependency on its originator. 2757 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result."); 2758 sendActivityResultLocked(-1, 2759 r.resultTo, r.resultWho, r.requestCode, 2760 Activity.RESULT_CANCELED, null); 2761 r.resultTo = null; 2762 } 2763 2764 boolean addingToTask = false; 2765 boolean movedHome = false; 2766 TaskRecord reuseTask = null; 2767 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && 2768 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0) 2769 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK 2770 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { 2771 // If bring to front is requested, and no result is requested, and 2772 // we can find a task that was started with this same 2773 // component, then instead of launching bring that one to the front. 2774 if (r.resultTo == null) { 2775 // See if there is a task to bring to the front. If this is 2776 // a SINGLE_INSTANCE activity, there can be one and only one 2777 // instance of it in the history, and it is always in its own 2778 // unique task, so we do a special search. 2779 ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE 2780 ? findTaskLocked(intent, r.info) 2781 : findActivityLocked(intent, r.info); 2782 if (taskTop != null) { 2783 if (taskTop.task.intent == null) { 2784 // This task was started because of movement of 2785 // the activity based on affinity... now that we 2786 // are actually launching it, we can assign the 2787 // base intent. 2788 taskTop.task.setIntent(intent, r.info); 2789 } 2790 // If the target task is not in the front, then we need 2791 // to bring it to the front... except... well, with 2792 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like 2793 // to have the same behavior as if a new instance was 2794 // being started, which means not bringing it to the front 2795 // if the caller is not itself in the front. 2796 ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop); 2797 if (curTop != null && curTop.task != taskTop.task) { 2798 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT); 2799 boolean callerAtFront = sourceRecord == null 2800 || curTop.task == sourceRecord.task; 2801 if (callerAtFront) { 2802 // We really do want to push this one into the 2803 // user's face, right now. 2804 movedHome = true; 2805 moveHomeToFrontFromLaunchLocked(launchFlags); 2806 moveTaskToFrontLocked(taskTop.task, r, options); 2807 options = null; 2808 } 2809 } 2810 // If the caller has requested that the target task be 2811 // reset, then do so. 2812 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { 2813 taskTop = resetTaskIfNeededLocked(taskTop, r); 2814 } 2815 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { 2816 // We don't need to start a new activity, and 2817 // the client said not to do anything if that 2818 // is the case, so this is it! And for paranoia, make 2819 // sure we have correctly resumed the top activity. 2820 if (doResume) { 2821 resumeTopActivityLocked(null, options); 2822 } else { 2823 ActivityOptions.abort(options); 2824 } 2825 return ActivityManager.START_RETURN_INTENT_TO_CALLER; 2826 } 2827 if ((launchFlags & 2828 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) 2829 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) { 2830 // The caller has requested to completely replace any 2831 // existing task with its new activity. Well that should 2832 // not be too hard... 2833 reuseTask = taskTop.task; 2834 performClearTaskLocked(taskTop.task.taskId); 2835 reuseTask.setIntent(r.intent, r.info); 2836 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0 2837 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK 2838 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { 2839 // In this situation we want to remove all activities 2840 // from the task up to the one being started. In most 2841 // cases this means we are resetting the task to its 2842 // initial state. 2843 ActivityRecord top = performClearTaskLocked( 2844 taskTop.task.taskId, r, launchFlags); 2845 if (top != null) { 2846 if (top.frontOfTask) { 2847 // Activity aliases may mean we use different 2848 // intents for the top activity, so make sure 2849 // the task now has the identity of the new 2850 // intent. 2851 top.task.setIntent(r.intent, r.info); 2852 } 2853 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); 2854 top.deliverNewIntentLocked(callingUid, r.intent); 2855 } else { 2856 // A special case: we need to 2857 // start the activity because it is not currently 2858 // running, and the caller has asked to clear the 2859 // current task to have this activity at the top. 2860 addingToTask = true; 2861 // Now pretend like this activity is being started 2862 // by the top of its task, so it is put in the 2863 // right place. 2864 sourceRecord = taskTop; 2865 } 2866 } else if (r.realActivity.equals(taskTop.task.realActivity)) { 2867 // In this case the top activity on the task is the 2868 // same as the one being launched, so we take that 2869 // as a request to bring the task to the foreground. 2870 // If the top activity in the task is the root 2871 // activity, deliver this new intent to it if it 2872 // desires. 2873 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 2874 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) 2875 && taskTop.realActivity.equals(r.realActivity)) { 2876 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task); 2877 if (taskTop.frontOfTask) { 2878 taskTop.task.setIntent(r.intent, r.info); 2879 } 2880 taskTop.deliverNewIntentLocked(callingUid, r.intent); 2881 } else if (!r.intent.filterEquals(taskTop.task.intent)) { 2882 // In this case we are launching the root activity 2883 // of the task, but with a different intent. We 2884 // should start a new instance on top. 2885 addingToTask = true; 2886 sourceRecord = taskTop; 2887 } 2888 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) { 2889 // In this case an activity is being launched in to an 2890 // existing task, without resetting that task. This 2891 // is typically the situation of launching an activity 2892 // from a notification or shortcut. We want to place 2893 // the new activity on top of the current task. 2894 addingToTask = true; 2895 sourceRecord = taskTop; 2896 } else if (!taskTop.task.rootWasReset) { 2897 // In this case we are launching in to an existing task 2898 // that has not yet been started from its front door. 2899 // The current task has been brought to the front. 2900 // Ideally, we'd probably like to place this new task 2901 // at the bottom of its stack, but that's a little hard 2902 // to do with the current organization of the code so 2903 // for now we'll just drop it. 2904 taskTop.task.setIntent(r.intent, r.info); 2905 } 2906 if (!addingToTask && reuseTask == null) { 2907 // We didn't do anything... but it was needed (a.k.a., client 2908 // don't use that intent!) And for paranoia, make 2909 // sure we have correctly resumed the top activity. 2910 if (doResume) { 2911 resumeTopActivityLocked(null, options); 2912 } else { 2913 ActivityOptions.abort(options); 2914 } 2915 return ActivityManager.START_TASK_TO_FRONT; 2916 } 2917 } 2918 } 2919 } 2920 2921 //String uri = r.intent.toURI(); 2922 //Intent intent2 = new Intent(uri); 2923 //Slog.i(TAG, "Given intent: " + r.intent); 2924 //Slog.i(TAG, "URI is: " + uri); 2925 //Slog.i(TAG, "To intent: " + intent2); 2926 2927 if (r.packageName != null) { 2928 // If the activity being launched is the same as the one currently 2929 // at the top, then we need to check if it should only be launched 2930 // once. 2931 ActivityRecord top = topRunningNonDelayedActivityLocked(notTop); 2932 if (top != null && r.resultTo == null) { 2933 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) { 2934 if (top.app != null && top.app.thread != null) { 2935 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 2936 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP 2937 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) { 2938 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task); 2939 // For paranoia, make sure we have correctly 2940 // resumed the top activity. 2941 if (doResume) { 2942 resumeTopActivityLocked(null); 2943 } 2944 ActivityOptions.abort(options); 2945 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { 2946 // We don't need to start a new activity, and 2947 // the client said not to do anything if that 2948 // is the case, so this is it! 2949 return ActivityManager.START_RETURN_INTENT_TO_CALLER; 2950 } 2951 top.deliverNewIntentLocked(callingUid, r.intent); 2952 return ActivityManager.START_DELIVERED_TO_TOP; 2953 } 2954 } 2955 } 2956 } 2957 2958 } else { 2959 if (r.resultTo != null) { 2960 sendActivityResultLocked(-1, 2961 r.resultTo, r.resultWho, r.requestCode, 2962 Activity.RESULT_CANCELED, null); 2963 } 2964 ActivityOptions.abort(options); 2965 return ActivityManager.START_CLASS_NOT_FOUND; 2966 } 2967 2968 boolean newTask = false; 2969 boolean keepCurTransition = false; 2970 2971 // Should this be considered a new task? 2972 if (r.resultTo == null && !addingToTask 2973 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { 2974 if (reuseTask == null) { 2975 // todo: should do better management of integers. 2976 mService.mCurTask++; 2977 if (mService.mCurTask <= 0) { 2978 mService.mCurTask = 1; 2979 } 2980 r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null, true); 2981 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r 2982 + " in new task " + r.task); 2983 } else { 2984 r.setTask(reuseTask, reuseTask, true); 2985 } 2986 newTask = true; 2987 if (!movedHome) { 2988 moveHomeToFrontFromLaunchLocked(launchFlags); 2989 } 2990 2991 } else if (sourceRecord != null) { 2992 if (!addingToTask && 2993 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { 2994 // In this case, we are adding the activity to an existing 2995 // task, but the caller has asked to clear that task if the 2996 // activity is already running. 2997 ActivityRecord top = performClearTaskLocked( 2998 sourceRecord.task.taskId, r, launchFlags); 2999 keepCurTransition = true; 3000 if (top != null) { 3001 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); 3002 top.deliverNewIntentLocked(callingUid, r.intent); 3003 // For paranoia, make sure we have correctly 3004 // resumed the top activity. 3005 if (doResume) { 3006 resumeTopActivityLocked(null); 3007 } 3008 ActivityOptions.abort(options); 3009 return ActivityManager.START_DELIVERED_TO_TOP; 3010 } 3011 } else if (!addingToTask && 3012 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) { 3013 // In this case, we are launching an activity in our own task 3014 // that may already be running somewhere in the history, and 3015 // we want to shuffle it to the front of the stack if so. 3016 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId); 3017 if (where >= 0) { 3018 ActivityRecord top = moveActivityToFrontLocked(where); 3019 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); 3020 top.updateOptionsLocked(options); 3021 top.deliverNewIntentLocked(callingUid, r.intent); 3022 if (doResume) { 3023 resumeTopActivityLocked(null); 3024 } 3025 return ActivityManager.START_DELIVERED_TO_TOP; 3026 } 3027 } 3028 // An existing activity is starting this new activity, so we want 3029 // to keep the new one in the same task as the one that is starting 3030 // it. 3031 r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false); 3032 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r 3033 + " in existing task " + r.task); 3034 3035 } else { 3036 // This not being started from an existing activity, and not part 3037 // of a new task... just put it in the top task, though these days 3038 // this case should never happen. 3039 final int N = mHistory.size(); 3040 ActivityRecord prev = 3041 N > 0 ? mHistory.get(N-1) : null; 3042 r.setTask(prev != null 3043 ? prev.task 3044 : new TaskRecord(mService.mCurTask, r.info, intent), null, true); 3045 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r 3046 + " in new guessed " + r.task); 3047 } 3048 3049 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName, 3050 intent, r.getUriPermissionsLocked()); 3051 3052 if (newTask) { 3053 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId); 3054 } 3055 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task); 3056 startActivityLocked(r, newTask, doResume, keepCurTransition, options); 3057 return ActivityManager.START_SUCCESS; 3058 } 3059 3060 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags, 3061 String profileFile, ParcelFileDescriptor profileFd, int userId) { 3062 // Collect information about the target of the Intent. 3063 ActivityInfo aInfo; 3064 try { 3065 ResolveInfo rInfo = 3066 AppGlobals.getPackageManager().resolveIntent( 3067 intent, resolvedType, 3068 PackageManager.MATCH_DEFAULT_ONLY 3069 | ActivityManagerService.STOCK_PM_FLAGS, userId); 3070 aInfo = rInfo != null ? rInfo.activityInfo : null; 3071 } catch (RemoteException e) { 3072 aInfo = null; 3073 } 3074 3075 if (aInfo != null) { 3076 // Store the found target back into the intent, because now that 3077 // we have it we never want to do this again. For example, if the 3078 // user navigates back to this point in the history, we should 3079 // always restart the exact same activity. 3080 intent.setComponent(new ComponentName( 3081 aInfo.applicationInfo.packageName, aInfo.name)); 3082 3083 // Don't debug things in the system process 3084 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) { 3085 if (!aInfo.processName.equals("system")) { 3086 mService.setDebugApp(aInfo.processName, true, false); 3087 } 3088 } 3089 3090 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) { 3091 if (!aInfo.processName.equals("system")) { 3092 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName); 3093 } 3094 } 3095 3096 if (profileFile != null) { 3097 if (!aInfo.processName.equals("system")) { 3098 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName, 3099 profileFile, profileFd, 3100 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0); 3101 } 3102 } 3103 } 3104 return aInfo; 3105 } 3106 3107 final int startActivityMayWait(IApplicationThread caller, int callingUid, 3108 Intent intent, String resolvedType, IBinder resultTo, 3109 String resultWho, int requestCode, int startFlags, String profileFile, 3110 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config, 3111 Bundle options, int userId) { 3112 // Refuse possible leaked file descriptors 3113 if (intent != null && intent.hasFileDescriptors()) { 3114 throw new IllegalArgumentException("File descriptors passed in Intent"); 3115 } 3116 boolean componentSpecified = intent.getComponent() != null; 3117 3118 // Don't modify the client's object! 3119 intent = new Intent(intent); 3120 3121 // Collect information about the target of the Intent. 3122 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, 3123 profileFile, profileFd, userId); 3124 3125 synchronized (mService) { 3126 int callingPid; 3127 if (callingUid >= 0) { 3128 callingPid = -1; 3129 } else if (caller == null) { 3130 callingPid = Binder.getCallingPid(); 3131 callingUid = Binder.getCallingUid(); 3132 } else { 3133 callingPid = callingUid = -1; 3134 } 3135 3136 mConfigWillChange = config != null 3137 && mService.mConfiguration.diff(config) != 0; 3138 if (DEBUG_CONFIGURATION) Slog.v(TAG, 3139 "Starting activity when config will change = " + mConfigWillChange); 3140 3141 final long origId = Binder.clearCallingIdentity(); 3142 3143 if (mMainStack && aInfo != null && 3144 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) { 3145 // This may be a heavy-weight process! Check to see if we already 3146 // have another, different heavy-weight process running. 3147 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) { 3148 if (mService.mHeavyWeightProcess != null && 3149 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid || 3150 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) { 3151 int realCallingPid = callingPid; 3152 int realCallingUid = callingUid; 3153 if (caller != null) { 3154 ProcessRecord callerApp = mService.getRecordForAppLocked(caller); 3155 if (callerApp != null) { 3156 realCallingPid = callerApp.pid; 3157 realCallingUid = callerApp.info.uid; 3158 } else { 3159 Slog.w(TAG, "Unable to find app for caller " + caller 3160 + " (pid=" + realCallingPid + ") when starting: " 3161 + intent.toString()); 3162 ActivityOptions.abort(options); 3163 return ActivityManager.START_PERMISSION_DENIED; 3164 } 3165 } 3166 3167 IIntentSender target = mService.getIntentSenderLocked( 3168 ActivityManager.INTENT_SENDER_ACTIVITY, "android", 3169 realCallingUid, userId, null, null, 0, new Intent[] { intent }, 3170 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT 3171 | PendingIntent.FLAG_ONE_SHOT, null); 3172 3173 Intent newIntent = new Intent(); 3174 if (requestCode >= 0) { 3175 // Caller is requesting a result. 3176 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true); 3177 } 3178 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT, 3179 new IntentSender(target)); 3180 if (mService.mHeavyWeightProcess.activities.size() > 0) { 3181 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0); 3182 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, 3183 hist.packageName); 3184 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, 3185 hist.task.taskId); 3186 } 3187 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP, 3188 aInfo.packageName); 3189 newIntent.setFlags(intent.getFlags()); 3190 newIntent.setClassName("android", 3191 HeavyWeightSwitcherActivity.class.getName()); 3192 intent = newIntent; 3193 resolvedType = null; 3194 caller = null; 3195 callingUid = Binder.getCallingUid(); 3196 callingPid = Binder.getCallingPid(); 3197 componentSpecified = true; 3198 try { 3199 ResolveInfo rInfo = 3200 AppGlobals.getPackageManager().resolveIntent( 3201 intent, null, 3202 PackageManager.MATCH_DEFAULT_ONLY 3203 | ActivityManagerService.STOCK_PM_FLAGS, userId); 3204 aInfo = rInfo != null ? rInfo.activityInfo : null; 3205 aInfo = mService.getActivityInfoForUser(aInfo, userId); 3206 } catch (RemoteException e) { 3207 aInfo = null; 3208 } 3209 } 3210 } 3211 } 3212 3213 int res = startActivityLocked(caller, intent, resolvedType, 3214 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid, 3215 startFlags, options, componentSpecified, null); 3216 3217 if (mConfigWillChange && mMainStack) { 3218 // If the caller also wants to switch to a new configuration, 3219 // do so now. This allows a clean switch, as we are waiting 3220 // for the current activity to pause (so we will not destroy 3221 // it), and have not yet started the next activity. 3222 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, 3223 "updateConfiguration()"); 3224 mConfigWillChange = false; 3225 if (DEBUG_CONFIGURATION) Slog.v(TAG, 3226 "Updating to new configuration after starting activity."); 3227 mService.updateConfigurationLocked(config, null, false, false); 3228 } 3229 3230 Binder.restoreCallingIdentity(origId); 3231 3232 if (outResult != null) { 3233 outResult.result = res; 3234 if (res == ActivityManager.START_SUCCESS) { 3235 mWaitingActivityLaunched.add(outResult); 3236 do { 3237 try { 3238 mService.wait(); 3239 } catch (InterruptedException e) { 3240 } 3241 } while (!outResult.timeout && outResult.who == null); 3242 } else if (res == ActivityManager.START_TASK_TO_FRONT) { 3243 ActivityRecord r = this.topRunningActivityLocked(null); 3244 if (r.nowVisible) { 3245 outResult.timeout = false; 3246 outResult.who = new ComponentName(r.info.packageName, r.info.name); 3247 outResult.totalTime = 0; 3248 outResult.thisTime = 0; 3249 } else { 3250 outResult.thisTime = SystemClock.uptimeMillis(); 3251 mWaitingActivityVisible.add(outResult); 3252 do { 3253 try { 3254 mService.wait(); 3255 } catch (InterruptedException e) { 3256 } 3257 } while (!outResult.timeout && outResult.who == null); 3258 } 3259 } 3260 } 3261 3262 return res; 3263 } 3264 } 3265 3266 final int startActivities(IApplicationThread caller, int callingUid, 3267 Intent[] intents, String[] resolvedTypes, IBinder resultTo, 3268 Bundle options, int userId) { 3269 if (intents == null) { 3270 throw new NullPointerException("intents is null"); 3271 } 3272 if (resolvedTypes == null) { 3273 throw new NullPointerException("resolvedTypes is null"); 3274 } 3275 if (intents.length != resolvedTypes.length) { 3276 throw new IllegalArgumentException("intents are length different than resolvedTypes"); 3277 } 3278 3279 ActivityRecord[] outActivity = new ActivityRecord[1]; 3280 3281 int callingPid; 3282 if (callingUid >= 0) { 3283 callingPid = -1; 3284 } else if (caller == null) { 3285 callingPid = Binder.getCallingPid(); 3286 callingUid = Binder.getCallingUid(); 3287 } else { 3288 callingPid = callingUid = -1; 3289 } 3290 final long origId = Binder.clearCallingIdentity(); 3291 try { 3292 synchronized (mService) { 3293 3294 for (int i=0; i<intents.length; i++) { 3295 Intent intent = intents[i]; 3296 if (intent == null) { 3297 continue; 3298 } 3299 3300 // Refuse possible leaked file descriptors 3301 if (intent != null && intent.hasFileDescriptors()) { 3302 throw new IllegalArgumentException("File descriptors passed in Intent"); 3303 } 3304 3305 boolean componentSpecified = intent.getComponent() != null; 3306 3307 // Don't modify the client's object! 3308 intent = new Intent(intent); 3309 3310 // Collect information about the target of the Intent. 3311 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i], 3312 0, null, null, userId); 3313 // TODO: New, check if this is correct 3314 aInfo = mService.getActivityInfoForUser(aInfo, userId); 3315 3316 if (mMainStack && aInfo != null && (aInfo.applicationInfo.flags 3317 & ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) { 3318 throw new IllegalArgumentException( 3319 "FLAG_CANT_SAVE_STATE not supported here"); 3320 } 3321 3322 Bundle theseOptions; 3323 if (options != null && i == intents.length-1) { 3324 theseOptions = options; 3325 } else { 3326 theseOptions = null; 3327 } 3328 int res = startActivityLocked(caller, intent, resolvedTypes[i], 3329 aInfo, resultTo, null, -1, callingPid, callingUid, 3330 0, theseOptions, componentSpecified, outActivity); 3331 if (res < 0) { 3332 return res; 3333 } 3334 3335 resultTo = outActivity[0] != null ? outActivity[0].appToken : null; 3336 } 3337 } 3338 } finally { 3339 Binder.restoreCallingIdentity(origId); 3340 } 3341 3342 return ActivityManager.START_SUCCESS; 3343 } 3344 3345 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r, 3346 long thisTime, long totalTime) { 3347 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) { 3348 WaitResult w = mWaitingActivityLaunched.get(i); 3349 w.timeout = timeout; 3350 if (r != null) { 3351 w.who = new ComponentName(r.info.packageName, r.info.name); 3352 } 3353 w.thisTime = thisTime; 3354 w.totalTime = totalTime; 3355 } 3356 mService.notifyAll(); 3357 } 3358 3359 void reportActivityVisibleLocked(ActivityRecord r) { 3360 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) { 3361 WaitResult w = mWaitingActivityVisible.get(i); 3362 w.timeout = false; 3363 if (r != null) { 3364 w.who = new ComponentName(r.info.packageName, r.info.name); 3365 } 3366 w.totalTime = SystemClock.uptimeMillis() - w.thisTime; 3367 w.thisTime = w.totalTime; 3368 } 3369 mService.notifyAll(); 3370 3371 if (mDismissKeyguardOnNextActivity) { 3372 mDismissKeyguardOnNextActivity = false; 3373 mService.mWindowManager.dismissKeyguard(); 3374 } 3375 } 3376 3377 void sendActivityResultLocked(int callingUid, ActivityRecord r, 3378 String resultWho, int requestCode, int resultCode, Intent data) { 3379 3380 if (callingUid > 0) { 3381 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName, 3382 data, r.getUriPermissionsLocked()); 3383 } 3384 3385 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r 3386 + " : who=" + resultWho + " req=" + requestCode 3387 + " res=" + resultCode + " data=" + data); 3388 if (mResumedActivity == r && r.app != null && r.app.thread != null) { 3389 try { 3390 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>(); 3391 list.add(new ResultInfo(resultWho, requestCode, 3392 resultCode, data)); 3393 r.app.thread.scheduleSendResult(r.appToken, list); 3394 return; 3395 } catch (Exception e) { 3396 Slog.w(TAG, "Exception thrown sending result to " + r, e); 3397 } 3398 } 3399 3400 r.addResultLocked(null, resultWho, requestCode, resultCode, data); 3401 } 3402 3403 private final void stopActivityLocked(ActivityRecord r) { 3404 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r); 3405 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 3406 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) { 3407 if (!r.finishing) { 3408 if (!mService.mSleeping) { 3409 if (DEBUG_STATES) { 3410 Slog.d(TAG, "no-history finish of " + r); 3411 } 3412 requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, 3413 "no-history", false); 3414 } else { 3415 if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r 3416 + " on stop because we're just sleeping"); 3417 } 3418 } 3419 } 3420 3421 if (r.app != null && r.app.thread != null) { 3422 if (mMainStack) { 3423 if (mService.mFocusedActivity == r) { 3424 mService.setFocusedActivityLocked(topRunningActivityLocked(null)); 3425 } 3426 } 3427 r.resumeKeyDispatchingLocked(); 3428 try { 3429 r.stopped = false; 3430 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r 3431 + " (stop requested)"); 3432 r.state = ActivityState.STOPPING; 3433 if (DEBUG_VISBILITY) Slog.v( 3434 TAG, "Stopping visible=" + r.visible + " for " + r); 3435 if (!r.visible) { 3436 mService.mWindowManager.setAppVisibility(r.appToken, false); 3437 } 3438 r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags); 3439 if (mService.isSleeping()) { 3440 r.setSleeping(true); 3441 } 3442 Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG); 3443 msg.obj = r; 3444 mHandler.sendMessageDelayed(msg, STOP_TIMEOUT); 3445 } catch (Exception e) { 3446 // Maybe just ignore exceptions here... if the process 3447 // has crashed, our death notification will clean things 3448 // up. 3449 Slog.w(TAG, "Exception thrown during pause", e); 3450 // Just in case, assume it to be stopped. 3451 r.stopped = true; 3452 if (DEBUG_STATES) Slog.v(TAG, "Stop failed; moving to STOPPED: " + r); 3453 r.state = ActivityState.STOPPED; 3454 if (r.configDestroy) { 3455 destroyActivityLocked(r, true, false, "stop-except"); 3456 } 3457 } 3458 } 3459 } 3460 3461 final ArrayList<ActivityRecord> processStoppingActivitiesLocked( 3462 boolean remove) { 3463 int N = mStoppingActivities.size(); 3464 if (N <= 0) return null; 3465 3466 ArrayList<ActivityRecord> stops = null; 3467 3468 final boolean nowVisible = mResumedActivity != null 3469 && mResumedActivity.nowVisible 3470 && !mResumedActivity.waitingVisible; 3471 for (int i=0; i<N; i++) { 3472 ActivityRecord s = mStoppingActivities.get(i); 3473 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible=" 3474 + nowVisible + " waitingVisible=" + s.waitingVisible 3475 + " finishing=" + s.finishing); 3476 if (s.waitingVisible && nowVisible) { 3477 mWaitingVisibleActivities.remove(s); 3478 s.waitingVisible = false; 3479 if (s.finishing) { 3480 // If this activity is finishing, it is sitting on top of 3481 // everyone else but we now know it is no longer needed... 3482 // so get rid of it. Otherwise, we need to go through the 3483 // normal flow and hide it once we determine that it is 3484 // hidden by the activities in front of it. 3485 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s); 3486 mService.mWindowManager.setAppVisibility(s.appToken, false); 3487 } 3488 } 3489 if ((!s.waitingVisible || mService.isSleeping()) && remove) { 3490 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s); 3491 if (stops == null) { 3492 stops = new ArrayList<ActivityRecord>(); 3493 } 3494 stops.add(s); 3495 mStoppingActivities.remove(i); 3496 N--; 3497 i--; 3498 } 3499 } 3500 3501 return stops; 3502 } 3503 3504 final void scheduleIdleLocked() { 3505 Message msg = Message.obtain(); 3506 msg.what = IDLE_NOW_MSG; 3507 mHandler.sendMessage(msg); 3508 } 3509 3510 final ActivityRecord activityIdleInternal(IBinder token, boolean fromTimeout, 3511 Configuration config) { 3512 if (localLOGV) Slog.v(TAG, "Activity idle: " + token); 3513 3514 ActivityRecord res = null; 3515 3516 ArrayList<ActivityRecord> stops = null; 3517 ArrayList<ActivityRecord> finishes = null; 3518 ArrayList<ActivityRecord> thumbnails = null; 3519 ArrayList<UserStartedState> startingUsers = null; 3520 int NS = 0; 3521 int NF = 0; 3522 int NT = 0; 3523 IApplicationThread sendThumbnail = null; 3524 boolean booting = false; 3525 boolean enableScreen = false; 3526 boolean activityRemoved = false; 3527 3528 synchronized (mService) { 3529 ActivityRecord r = ActivityRecord.forToken(token); 3530 if (r != null) { 3531 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r); 3532 r.finishLaunchTickingLocked(); 3533 } 3534 3535 // Get the activity record. 3536 int index = indexOfActivityLocked(r); 3537 if (index >= 0) { 3538 res = r; 3539 3540 if (fromTimeout) { 3541 reportActivityLaunchedLocked(fromTimeout, r, -1, -1); 3542 } 3543 3544 // This is a hack to semi-deal with a race condition 3545 // in the client where it can be constructed with a 3546 // newer configuration from when we asked it to launch. 3547 // We'll update with whatever configuration it now says 3548 // it used to launch. 3549 if (config != null) { 3550 r.configuration = config; 3551 } 3552 3553 // No longer need to keep the device awake. 3554 if (mResumedActivity == r && mLaunchingActivity.isHeld()) { 3555 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG); 3556 mLaunchingActivity.release(); 3557 } 3558 3559 // We are now idle. If someone is waiting for a thumbnail from 3560 // us, we can now deliver. 3561 r.idle = true; 3562 mService.scheduleAppGcsLocked(); 3563 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) { 3564 sendThumbnail = r.app.thread; 3565 r.thumbnailNeeded = false; 3566 } 3567 3568 // If this activity is fullscreen, set up to hide those under it. 3569 3570 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r); 3571 ensureActivitiesVisibleLocked(null, 0); 3572 3573 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout); 3574 if (mMainStack) { 3575 if (!mService.mBooted) { 3576 mService.mBooted = true; 3577 enableScreen = true; 3578 } 3579 } 3580 3581 } else if (fromTimeout) { 3582 reportActivityLaunchedLocked(fromTimeout, null, -1, -1); 3583 } 3584 3585 // Atomically retrieve all of the other things to do. 3586 stops = processStoppingActivitiesLocked(true); 3587 NS = stops != null ? stops.size() : 0; 3588 if ((NF=mFinishingActivities.size()) > 0) { 3589 finishes = new ArrayList<ActivityRecord>(mFinishingActivities); 3590 mFinishingActivities.clear(); 3591 } 3592 if ((NT=mService.mCancelledThumbnails.size()) > 0) { 3593 thumbnails = new ArrayList<ActivityRecord>(mService.mCancelledThumbnails); 3594 mService.mCancelledThumbnails.clear(); 3595 } 3596 3597 if (mMainStack) { 3598 booting = mService.mBooting; 3599 mService.mBooting = false; 3600 } 3601 if (mStartingUsers.size() > 0) { 3602 startingUsers = new ArrayList<UserStartedState>(mStartingUsers); 3603 mStartingUsers.clear(); 3604 } 3605 } 3606 3607 int i; 3608 3609 // Send thumbnail if requested. 3610 if (sendThumbnail != null) { 3611 try { 3612 sendThumbnail.requestThumbnail(token); 3613 } catch (Exception e) { 3614 Slog.w(TAG, "Exception thrown when requesting thumbnail", e); 3615 mService.sendPendingThumbnail(null, token, null, null, true); 3616 } 3617 } 3618 3619 // Stop any activities that are scheduled to do so but have been 3620 // waiting for the next one to start. 3621 for (i=0; i<NS; i++) { 3622 ActivityRecord r = (ActivityRecord)stops.get(i); 3623 synchronized (mService) { 3624 if (r.finishing) { 3625 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false); 3626 } else { 3627 stopActivityLocked(r); 3628 } 3629 } 3630 } 3631 3632 // Finish any activities that are scheduled to do so but have been 3633 // waiting for the next one to start. 3634 for (i=0; i<NF; i++) { 3635 ActivityRecord r = (ActivityRecord)finishes.get(i); 3636 synchronized (mService) { 3637 activityRemoved = destroyActivityLocked(r, true, false, "finish-idle"); 3638 } 3639 } 3640 3641 // Report back to any thumbnail receivers. 3642 for (i=0; i<NT; i++) { 3643 ActivityRecord r = (ActivityRecord)thumbnails.get(i); 3644 mService.sendPendingThumbnail(r, null, null, null, true); 3645 } 3646 3647 if (booting) { 3648 mService.finishBooting(); 3649 } else if (startingUsers != null) { 3650 for (i=0; i<startingUsers.size(); i++) { 3651 mService.finishUserSwitch(startingUsers.get(i)); 3652 } 3653 } 3654 3655 mService.trimApplications(); 3656 //dump(); 3657 //mWindowManager.dump(); 3658 3659 if (enableScreen) { 3660 mService.enableScreenAfterBoot(); 3661 } 3662 3663 if (activityRemoved) { 3664 resumeTopActivityLocked(null); 3665 } 3666 3667 return res; 3668 } 3669 3670 /** 3671 * @return Returns true if the activity is being finished, false if for 3672 * some reason it is being left as-is. 3673 */ 3674 final boolean requestFinishActivityLocked(IBinder token, int resultCode, 3675 Intent resultData, String reason, boolean oomAdj) { 3676 int index = indexOfTokenLocked(token); 3677 if (DEBUG_RESULTS || DEBUG_STATES) Slog.v( 3678 TAG, "Finishing activity @" + index + ": token=" + token 3679 + ", result=" + resultCode + ", data=" + resultData 3680 + ", reason=" + reason); 3681 if (index < 0) { 3682 return false; 3683 } 3684 ActivityRecord r = mHistory.get(index); 3685 3686 finishActivityLocked(r, index, resultCode, resultData, reason, oomAdj); 3687 return true; 3688 } 3689 3690 final void finishSubActivityLocked(IBinder token, String resultWho, int requestCode) { 3691 ActivityRecord self = isInStackLocked(token); 3692 if (self == null) { 3693 return; 3694 } 3695 3696 int i; 3697 for (i=mHistory.size()-1; i>=0; i--) { 3698 ActivityRecord r = (ActivityRecord)mHistory.get(i); 3699 if (r.resultTo == self && r.requestCode == requestCode) { 3700 if ((r.resultWho == null && resultWho == null) || 3701 (r.resultWho != null && r.resultWho.equals(resultWho))) { 3702 finishActivityLocked(r, i, 3703 Activity.RESULT_CANCELED, null, "request-sub", false); 3704 } 3705 } 3706 } 3707 mService.updateOomAdjLocked(); 3708 } 3709 3710 final boolean finishActivityAffinityLocked(IBinder token) { 3711 int index = indexOfTokenLocked(token); 3712 if (DEBUG_RESULTS) Slog.v( 3713 TAG, "Finishing activity affinity @" + index + ": token=" + token); 3714 if (index < 0) { 3715 return false; 3716 } 3717 ActivityRecord r = mHistory.get(index); 3718 3719 while (index >= 0) { 3720 ActivityRecord cur = mHistory.get(index); 3721 if (cur.task != r.task) { 3722 break; 3723 } 3724 if (cur.taskAffinity == null && r.taskAffinity != null) { 3725 break; 3726 } 3727 if (cur.taskAffinity != null && !cur.taskAffinity.equals(r.taskAffinity)) { 3728 break; 3729 } 3730 finishActivityLocked(cur, index, Activity.RESULT_CANCELED, null, 3731 "request-affinity", true); 3732 index--; 3733 } 3734 return true; 3735 } 3736 3737 final void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) { 3738 // send the result 3739 ActivityRecord resultTo = r.resultTo; 3740 if (resultTo != null) { 3741 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo 3742 + " who=" + r.resultWho + " req=" + r.requestCode 3743 + " res=" + resultCode + " data=" + resultData); 3744 if (r.info.applicationInfo.uid > 0) { 3745 mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid, 3746 resultTo.packageName, resultData, 3747 resultTo.getUriPermissionsLocked()); 3748 } 3749 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode, 3750 resultData); 3751 r.resultTo = null; 3752 } 3753 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r); 3754 3755 // Make sure this HistoryRecord is not holding on to other resources, 3756 // because clients have remote IPC references to this object so we 3757 // can't assume that will go away and want to avoid circular IPC refs. 3758 r.results = null; 3759 r.pendingResults = null; 3760 r.newIntents = null; 3761 r.icicle = null; 3762 } 3763 3764 /** 3765 * @return Returns true if this activity has been removed from the history 3766 * list, or false if it is still in the list and will be removed later. 3767 */ 3768 final boolean finishActivityLocked(ActivityRecord r, int index, 3769 int resultCode, Intent resultData, String reason, boolean oomAdj) { 3770 return finishActivityLocked(r, index, resultCode, resultData, reason, false, oomAdj); 3771 } 3772 3773 /** 3774 * @return Returns true if this activity has been removed from the history 3775 * list, or false if it is still in the list and will be removed later. 3776 */ 3777 final boolean finishActivityLocked(ActivityRecord r, int index, int resultCode, 3778 Intent resultData, String reason, boolean immediate, boolean oomAdj) { 3779 if (r.finishing) { 3780 Slog.w(TAG, "Duplicate finish request for " + r); 3781 return false; 3782 } 3783 3784 r.makeFinishing(); 3785 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY, 3786 r.userId, System.identityHashCode(r), 3787 r.task.taskId, r.shortComponentName, reason); 3788 if (index < (mHistory.size()-1)) { 3789 ActivityRecord next = mHistory.get(index+1); 3790 if (next.task == r.task) { 3791 if (r.frontOfTask) { 3792 // The next activity is now the front of the task. 3793 next.frontOfTask = true; 3794 } 3795 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) { 3796 // If the caller asked that this activity (and all above it) 3797 // be cleared when the task is reset, don't lose that information, 3798 // but propagate it up to the next activity. 3799 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 3800 } 3801 } 3802 } 3803 3804 r.pauseKeyDispatchingLocked(); 3805 if (mMainStack) { 3806 if (mService.mFocusedActivity == r) { 3807 mService.setFocusedActivityLocked(topRunningActivityLocked(null)); 3808 } 3809 } 3810 3811 finishActivityResultsLocked(r, resultCode, resultData); 3812 3813 if (mService.mPendingThumbnails.size() > 0) { 3814 // There are clients waiting to receive thumbnails so, in case 3815 // this is an activity that someone is waiting for, add it 3816 // to the pending list so we can correctly update the clients. 3817 mService.mCancelledThumbnails.add(r); 3818 } 3819 3820 if (immediate) { 3821 return finishCurrentActivityLocked(r, index, 3822 FINISH_IMMEDIATELY, oomAdj) == null; 3823 } else if (mResumedActivity == r) { 3824 boolean endTask = index <= 0 3825 || (mHistory.get(index-1)).task != r.task; 3826 if (DEBUG_TRANSITION) Slog.v(TAG, 3827 "Prepare close transition: finishing " + r); 3828 mService.mWindowManager.prepareAppTransition(endTask 3829 ? AppTransition.TRANSIT_TASK_CLOSE 3830 : AppTransition.TRANSIT_ACTIVITY_CLOSE, false); 3831 3832 // Tell window manager to prepare for this one to be removed. 3833 mService.mWindowManager.setAppVisibility(r.appToken, false); 3834 3835 if (mPausingActivity == null) { 3836 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r); 3837 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false"); 3838 startPausingLocked(false, false); 3839 } 3840 3841 } else if (r.state != ActivityState.PAUSING) { 3842 // If the activity is PAUSING, we will complete the finish once 3843 // it is done pausing; else we can just directly finish it here. 3844 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r); 3845 return finishCurrentActivityLocked(r, index, 3846 FINISH_AFTER_PAUSE, oomAdj) == null; 3847 } else { 3848 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r); 3849 } 3850 3851 return false; 3852 } 3853 3854 private static final int FINISH_IMMEDIATELY = 0; 3855 private static final int FINISH_AFTER_PAUSE = 1; 3856 private static final int FINISH_AFTER_VISIBLE = 2; 3857 3858 private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, 3859 int mode, boolean oomAdj) { 3860 final int index = indexOfActivityLocked(r); 3861 if (index < 0) { 3862 return null; 3863 } 3864 3865 return finishCurrentActivityLocked(r, index, mode, oomAdj); 3866 } 3867 3868 private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, 3869 int index, int mode, boolean oomAdj) { 3870 // First things first: if this activity is currently visible, 3871 // and the resumed activity is not yet visible, then hold off on 3872 // finishing until the resumed one becomes visible. 3873 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) { 3874 if (!mStoppingActivities.contains(r)) { 3875 mStoppingActivities.add(r); 3876 if (mStoppingActivities.size() > 3) { 3877 // If we already have a few activities waiting to stop, 3878 // then give up on things going idle and start clearing 3879 // them out. 3880 scheduleIdleLocked(); 3881 } else { 3882 checkReadyForSleepLocked(); 3883 } 3884 } 3885 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r 3886 + " (finish requested)"); 3887 r.state = ActivityState.STOPPING; 3888 if (oomAdj) { 3889 mService.updateOomAdjLocked(); 3890 } 3891 return r; 3892 } 3893 3894 // make sure the record is cleaned out of other places. 3895 mStoppingActivities.remove(r); 3896 mGoingToSleepActivities.remove(r); 3897 mWaitingVisibleActivities.remove(r); 3898 if (mResumedActivity == r) { 3899 mResumedActivity = null; 3900 } 3901 final ActivityState prevState = r.state; 3902 if (DEBUG_STATES) Slog.v(TAG, "Moving to FINISHING: " + r); 3903 r.state = ActivityState.FINISHING; 3904 3905 if (mode == FINISH_IMMEDIATELY 3906 || prevState == ActivityState.STOPPED 3907 || prevState == ActivityState.INITIALIZING) { 3908 // If this activity is already stopped, we can just finish 3909 // it right now. 3910 boolean activityRemoved = destroyActivityLocked(r, true, 3911 oomAdj, "finish-imm"); 3912 if (activityRemoved) { 3913 resumeTopActivityLocked(null); 3914 } 3915 return activityRemoved ? null : r; 3916 } else { 3917 // Need to go through the full pause cycle to get this 3918 // activity into the stopped state and then finish it. 3919 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r); 3920 mFinishingActivities.add(r); 3921 resumeTopActivityLocked(null); 3922 } 3923 return r; 3924 } 3925 3926 /** 3927 * Perform the common clean-up of an activity record. This is called both 3928 * as part of destroyActivityLocked() (when destroying the client-side 3929 * representation) and cleaning things up as a result of its hosting 3930 * processing going away, in which case there is no remaining client-side 3931 * state to destroy so only the cleanup here is needed. 3932 */ 3933 final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, 3934 boolean setState) { 3935 if (mResumedActivity == r) { 3936 mResumedActivity = null; 3937 } 3938 if (mService.mFocusedActivity == r) { 3939 mService.mFocusedActivity = null; 3940 } 3941 3942 r.configDestroy = false; 3943 r.frozenBeforeDestroy = false; 3944 3945 if (setState) { 3946 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (cleaning up)"); 3947 r.state = ActivityState.DESTROYED; 3948 if (DEBUG_APP) Slog.v(TAG, "Clearing app during cleanUp for activity " + r); 3949 r.app = null; 3950 } 3951 3952 // Make sure this record is no longer in the pending finishes list. 3953 // This could happen, for example, if we are trimming activities 3954 // down to the max limit while they are still waiting to finish. 3955 mFinishingActivities.remove(r); 3956 mWaitingVisibleActivities.remove(r); 3957 3958 // Remove any pending results. 3959 if (r.finishing && r.pendingResults != null) { 3960 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) { 3961 PendingIntentRecord rec = apr.get(); 3962 if (rec != null) { 3963 mService.cancelIntentSenderLocked(rec, false); 3964 } 3965 } 3966 r.pendingResults = null; 3967 } 3968 3969 if (cleanServices) { 3970 cleanUpActivityServicesLocked(r); 3971 } 3972 3973 if (mService.mPendingThumbnails.size() > 0) { 3974 // There are clients waiting to receive thumbnails so, in case 3975 // this is an activity that someone is waiting for, add it 3976 // to the pending list so we can correctly update the clients. 3977 mService.mCancelledThumbnails.add(r); 3978 } 3979 3980 // Get rid of any pending idle timeouts. 3981 removeTimeoutsForActivityLocked(r); 3982 } 3983 3984 private void removeTimeoutsForActivityLocked(ActivityRecord r) { 3985 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); 3986 mHandler.removeMessages(STOP_TIMEOUT_MSG, r); 3987 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r); 3988 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r); 3989 r.finishLaunchTickingLocked(); 3990 } 3991 3992 final void removeActivityFromHistoryLocked(ActivityRecord r) { 3993 finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null); 3994 r.makeFinishing(); 3995 if (DEBUG_ADD_REMOVE) { 3996 RuntimeException here = new RuntimeException("here"); 3997 here.fillInStackTrace(); 3998 Slog.i(TAG, "Removing activity " + r + " from stack"); 3999 } 4000 mHistory.remove(r); 4001 r.takeFromHistory(); 4002 removeTimeoutsForActivityLocked(r); 4003 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r 4004 + " (removed from history)"); 4005 r.state = ActivityState.DESTROYED; 4006 if (DEBUG_APP) Slog.v(TAG, "Clearing app during remove for activity " + r); 4007 r.app = null; 4008 mService.mWindowManager.removeAppToken(r.appToken); 4009 if (VALIDATE_TOKENS) { 4010 validateAppTokensLocked(); 4011 } 4012 cleanUpActivityServicesLocked(r); 4013 r.removeUriPermissionsLocked(); 4014 } 4015 4016 /** 4017 * Perform clean-up of service connections in an activity record. 4018 */ 4019 final void cleanUpActivityServicesLocked(ActivityRecord r) { 4020 // Throw away any services that have been bound by this activity. 4021 if (r.connections != null) { 4022 Iterator<ConnectionRecord> it = r.connections.iterator(); 4023 while (it.hasNext()) { 4024 ConnectionRecord c = it.next(); 4025 mService.mServices.removeConnectionLocked(c, null, r); 4026 } 4027 r.connections = null; 4028 } 4029 } 4030 4031 final void scheduleDestroyActivities(ProcessRecord owner, boolean oomAdj, String reason) { 4032 Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG); 4033 msg.obj = new ScheduleDestroyArgs(owner, oomAdj, reason); 4034 mHandler.sendMessage(msg); 4035 } 4036 4037 final void destroyActivitiesLocked(ProcessRecord owner, boolean oomAdj, String reason) { 4038 boolean lastIsOpaque = false; 4039 boolean activityRemoved = false; 4040 for (int i=mHistory.size()-1; i>=0; i--) { 4041 ActivityRecord r = mHistory.get(i); 4042 if (r.finishing) { 4043 continue; 4044 } 4045 if (r.fullscreen) { 4046 lastIsOpaque = true; 4047 } 4048 if (owner != null && r.app != owner) { 4049 continue; 4050 } 4051 if (!lastIsOpaque) { 4052 continue; 4053 } 4054 // We can destroy this one if we have its icicle saved and 4055 // it is not in the process of pausing/stopping/finishing. 4056 if (r.app != null && r != mResumedActivity && r != mPausingActivity 4057 && r.haveState && !r.visible && r.stopped 4058 && r.state != ActivityState.DESTROYING 4059 && r.state != ActivityState.DESTROYED) { 4060 if (DEBUG_SWITCH) Slog.v(TAG, "Destroying " + r + " in state " + r.state 4061 + " resumed=" + mResumedActivity 4062 + " pausing=" + mPausingActivity); 4063 if (destroyActivityLocked(r, true, oomAdj, reason)) { 4064 activityRemoved = true; 4065 } 4066 } 4067 } 4068 if (activityRemoved) { 4069 resumeTopActivityLocked(null); 4070 } 4071 } 4072 4073 /** 4074 * Destroy the current CLIENT SIDE instance of an activity. This may be 4075 * called both when actually finishing an activity, or when performing 4076 * a configuration switch where we destroy the current client-side object 4077 * but then create a new client-side object for this same HistoryRecord. 4078 */ 4079 final boolean destroyActivityLocked(ActivityRecord r, 4080 boolean removeFromApp, boolean oomAdj, String reason) { 4081 if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v( 4082 TAG, "Removing activity from " + reason + ": token=" + r 4083 + ", app=" + (r.app != null ? r.app.processName : "(null)")); 4084 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY, 4085 r.userId, System.identityHashCode(r), 4086 r.task.taskId, r.shortComponentName, reason); 4087 4088 boolean removedFromHistory = false; 4089 4090 cleanUpActivityLocked(r, false, false); 4091 4092 final boolean hadApp = r.app != null; 4093 4094 if (hadApp) { 4095 if (removeFromApp) { 4096 int idx = r.app.activities.indexOf(r); 4097 if (idx >= 0) { 4098 r.app.activities.remove(idx); 4099 } 4100 if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) { 4101 mService.mHeavyWeightProcess = null; 4102 mService.mHandler.sendEmptyMessage( 4103 ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG); 4104 } 4105 if (r.app.activities.size() == 0) { 4106 // No longer have activities, so update oom adj. 4107 mService.updateOomAdjLocked(); 4108 } 4109 } 4110 4111 boolean skipDestroy = false; 4112 4113 try { 4114 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r); 4115 r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing, 4116 r.configChangeFlags); 4117 } catch (Exception e) { 4118 // We can just ignore exceptions here... if the process 4119 // has crashed, our death notification will clean things 4120 // up. 4121 //Slog.w(TAG, "Exception thrown during finish", e); 4122 if (r.finishing) { 4123 removeActivityFromHistoryLocked(r); 4124 removedFromHistory = true; 4125 skipDestroy = true; 4126 } 4127 } 4128 4129 r.nowVisible = false; 4130 4131 // If the activity is finishing, we need to wait on removing it 4132 // from the list to give it a chance to do its cleanup. During 4133 // that time it may make calls back with its token so we need to 4134 // be able to find it on the list and so we don't want to remove 4135 // it from the list yet. Otherwise, we can just immediately put 4136 // it in the destroyed state since we are not removing it from the 4137 // list. 4138 if (r.finishing && !skipDestroy) { 4139 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYING: " + r 4140 + " (destroy requested)"); 4141 r.state = ActivityState.DESTROYING; 4142 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG); 4143 msg.obj = r; 4144 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT); 4145 } else { 4146 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r 4147 + " (destroy skipped)"); 4148 r.state = ActivityState.DESTROYED; 4149 if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r); 4150 r.app = null; 4151 } 4152 } else { 4153 // remove this record from the history. 4154 if (r.finishing) { 4155 removeActivityFromHistoryLocked(r); 4156 removedFromHistory = true; 4157 } else { 4158 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r 4159 + " (no app)"); 4160 r.state = ActivityState.DESTROYED; 4161 if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r); 4162 r.app = null; 4163 } 4164 } 4165 4166 r.configChangeFlags = 0; 4167 4168 if (!mLRUActivities.remove(r) && hadApp) { 4169 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list"); 4170 } 4171 4172 return removedFromHistory; 4173 } 4174 4175 final void activityDestroyed(IBinder token) { 4176 synchronized (mService) { 4177 final long origId = Binder.clearCallingIdentity(); 4178 try { 4179 ActivityRecord r = ActivityRecord.forToken(token); 4180 if (r != null) { 4181 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r); 4182 } 4183 4184 int index = indexOfActivityLocked(r); 4185 if (index >= 0) { 4186 if (r.state == ActivityState.DESTROYING) { 4187 cleanUpActivityLocked(r, true, false); 4188 removeActivityFromHistoryLocked(r); 4189 } 4190 } 4191 resumeTopActivityLocked(null); 4192 } finally { 4193 Binder.restoreCallingIdentity(origId); 4194 } 4195 } 4196 } 4197 4198 private void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app, 4199 String listName) { 4200 int i = list.size(); 4201 if (DEBUG_CLEANUP) Slog.v( 4202 TAG, "Removing app " + app + " from list " + listName 4203 + " with " + i + " entries"); 4204 while (i > 0) { 4205 i--; 4206 ActivityRecord r = (ActivityRecord)list.get(i); 4207 if (DEBUG_CLEANUP) Slog.v(TAG, "Record #" + i + " " + r); 4208 if (r.app == app) { 4209 if (DEBUG_CLEANUP) Slog.v(TAG, "---> REMOVING this entry!"); 4210 list.remove(i); 4211 removeTimeoutsForActivityLocked(r); 4212 } 4213 } 4214 } 4215 4216 boolean removeHistoryRecordsForAppLocked(ProcessRecord app) { 4217 removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities"); 4218 removeHistoryRecordsForAppLocked(mStoppingActivities, app, "mStoppingActivities"); 4219 removeHistoryRecordsForAppLocked(mGoingToSleepActivities, app, "mGoingToSleepActivities"); 4220 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app, 4221 "mWaitingVisibleActivities"); 4222 removeHistoryRecordsForAppLocked(mFinishingActivities, app, "mFinishingActivities"); 4223 4224 boolean hasVisibleActivities = false; 4225 4226 // Clean out the history list. 4227 int i = mHistory.size(); 4228 if (DEBUG_CLEANUP) Slog.v( 4229 TAG, "Removing app " + app + " from history with " + i + " entries"); 4230 while (i > 0) { 4231 i--; 4232 ActivityRecord r = (ActivityRecord)mHistory.get(i); 4233 if (DEBUG_CLEANUP) Slog.v( 4234 TAG, "Record #" + i + " " + r + ": app=" + r.app); 4235 if (r.app == app) { 4236 boolean remove; 4237 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) { 4238 // Don't currently have state for the activity, or 4239 // it is finishing -- always remove it. 4240 remove = true; 4241 } else if (r.launchCount > 2 && 4242 r.lastLaunchTime > (SystemClock.uptimeMillis()-60000)) { 4243 // We have launched this activity too many times since it was 4244 // able to run, so give up and remove it. 4245 remove = true; 4246 } else { 4247 // The process may be gone, but the activity lives on! 4248 remove = false; 4249 } 4250 if (remove) { 4251 if (ActivityStack.DEBUG_ADD_REMOVE || DEBUG_CLEANUP) { 4252 RuntimeException here = new RuntimeException("here"); 4253 here.fillInStackTrace(); 4254 Slog.i(TAG, "Removing activity " + r + " from stack at " + i 4255 + ": haveState=" + r.haveState 4256 + " stateNotNeeded=" + r.stateNotNeeded 4257 + " finishing=" + r.finishing 4258 + " state=" + r.state, here); 4259 } 4260 if (!r.finishing) { 4261 Slog.w(TAG, "Force removing " + r + ": app died, no saved state"); 4262 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY, 4263 r.userId, System.identityHashCode(r), 4264 r.task.taskId, r.shortComponentName, 4265 "proc died without state saved"); 4266 } 4267 removeActivityFromHistoryLocked(r); 4268 4269 } else { 4270 // We have the current state for this activity, so 4271 // it can be restarted later when needed. 4272 if (localLOGV) Slog.v( 4273 TAG, "Keeping entry, setting app to null"); 4274 if (r.visible) { 4275 hasVisibleActivities = true; 4276 } 4277 if (DEBUG_APP) Slog.v(TAG, "Clearing app during removeHistory for activity " 4278 + r); 4279 r.app = null; 4280 r.nowVisible = false; 4281 if (!r.haveState) { 4282 if (ActivityStack.DEBUG_SAVED_STATE) Slog.i(TAG, 4283 "App died, clearing saved state of " + r); 4284 r.icicle = null; 4285 } 4286 } 4287 4288 r.stack.cleanUpActivityLocked(r, true, true); 4289 } 4290 } 4291 4292 return hasVisibleActivities; 4293 } 4294 4295 /** 4296 * Move the current home activity's task (if one exists) to the front 4297 * of the stack. 4298 */ 4299 final void moveHomeToFrontLocked() { 4300 TaskRecord homeTask = null; 4301 for (int i=mHistory.size()-1; i>=0; i--) { 4302 ActivityRecord hr = mHistory.get(i); 4303 if (hr.isHomeActivity) { 4304 homeTask = hr.task; 4305 break; 4306 } 4307 } 4308 if (homeTask != null) { 4309 moveTaskToFrontLocked(homeTask, null, null); 4310 } 4311 } 4312 4313 final void updateTransitLocked(int transit, Bundle options) { 4314 if (options != null) { 4315 ActivityRecord r = topRunningActivityLocked(null); 4316 if (r != null && r.state != ActivityState.RESUMED) { 4317 r.updateOptionsLocked(options); 4318 } else { 4319 ActivityOptions.abort(options); 4320 } 4321 } 4322 mService.mWindowManager.prepareAppTransition(transit, false); 4323 } 4324 4325 final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) { 4326 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr); 4327 4328 final int task = tr.taskId; 4329 int top = mHistory.size()-1; 4330 4331 if (top < 0 || (mHistory.get(top)).task.taskId == task) { 4332 // nothing to do! 4333 if (reason != null && 4334 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) { 4335 ActivityOptions.abort(options); 4336 } else { 4337 updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options); 4338 } 4339 return; 4340 } 4341 4342 ArrayList<IBinder> moved = new ArrayList<IBinder>(); 4343 4344 // Applying the affinities may have removed entries from the history, 4345 // so get the size again. 4346 top = mHistory.size()-1; 4347 int pos = top; 4348 4349 // Shift all activities with this task up to the top 4350 // of the stack, keeping them in the same internal order. 4351 while (pos >= 0) { 4352 ActivityRecord r = mHistory.get(pos); 4353 if (localLOGV) Slog.v( 4354 TAG, "At " + pos + " ckp " + r.task + ": " + r); 4355 if (r.task.taskId == task) { 4356 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top); 4357 if (DEBUG_ADD_REMOVE) { 4358 RuntimeException here = new RuntimeException("here"); 4359 here.fillInStackTrace(); 4360 Slog.i(TAG, "Removing and adding activity " + r + " to stack at " + top, here); 4361 } 4362 mHistory.remove(pos); 4363 mHistory.add(top, r); 4364 moved.add(0, r.appToken); 4365 top--; 4366 } 4367 pos--; 4368 } 4369 4370 if (DEBUG_TRANSITION) Slog.v(TAG, 4371 "Prepare to front transition: task=" + tr); 4372 if (reason != null && 4373 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) { 4374 mService.mWindowManager.prepareAppTransition( 4375 AppTransition.TRANSIT_NONE, false); 4376 ActivityRecord r = topRunningActivityLocked(null); 4377 if (r != null) { 4378 mNoAnimActivities.add(r); 4379 } 4380 ActivityOptions.abort(options); 4381 } else { 4382 updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options); 4383 } 4384 4385 mService.mWindowManager.moveAppTokensToTop(moved); 4386 if (VALIDATE_TOKENS) { 4387 validateAppTokensLocked(); 4388 } 4389 4390 finishTaskMoveLocked(task); 4391 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, task); 4392 } 4393 4394 private final void finishTaskMoveLocked(int task) { 4395 resumeTopActivityLocked(null); 4396 } 4397 4398 /** 4399 * Worker method for rearranging history stack. Implements the function of moving all 4400 * activities for a specific task (gathering them if disjoint) into a single group at the 4401 * bottom of the stack. 4402 * 4403 * If a watcher is installed, the action is preflighted and the watcher has an opportunity 4404 * to premeptively cancel the move. 4405 * 4406 * @param task The taskId to collect and move to the bottom. 4407 * @return Returns true if the move completed, false if not. 4408 */ 4409 final boolean moveTaskToBackLocked(int task, ActivityRecord reason) { 4410 Slog.i(TAG, "moveTaskToBack: " + task); 4411 4412 // If we have a watcher, preflight the move before committing to it. First check 4413 // for *other* available tasks, but if none are available, then try again allowing the 4414 // current task to be selected. 4415 if (mMainStack && mService.mController != null) { 4416 ActivityRecord next = topRunningActivityLocked(null, task); 4417 if (next == null) { 4418 next = topRunningActivityLocked(null, 0); 4419 } 4420 if (next != null) { 4421 // ask watcher if this is allowed 4422 boolean moveOK = true; 4423 try { 4424 moveOK = mService.mController.activityResuming(next.packageName); 4425 } catch (RemoteException e) { 4426 mService.mController = null; 4427 } 4428 if (!moveOK) { 4429 return false; 4430 } 4431 } 4432 } 4433 4434 ArrayList<IBinder> moved = new ArrayList<IBinder>(); 4435 4436 if (DEBUG_TRANSITION) Slog.v(TAG, 4437 "Prepare to back transition: task=" + task); 4438 4439 final int N = mHistory.size(); 4440 int bottom = 0; 4441 int pos = 0; 4442 4443 // Shift all activities with this task down to the bottom 4444 // of the stack, keeping them in the same internal order. 4445 while (pos < N) { 4446 ActivityRecord r = mHistory.get(pos); 4447 if (localLOGV) Slog.v( 4448 TAG, "At " + pos + " ckp " + r.task + ": " + r); 4449 if (r.task.taskId == task) { 4450 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1)); 4451 if (DEBUG_ADD_REMOVE) { 4452 RuntimeException here = new RuntimeException("here"); 4453 here.fillInStackTrace(); 4454 Slog.i(TAG, "Removing and adding activity " + r + " to stack at " 4455 + bottom, here); 4456 } 4457 mHistory.remove(pos); 4458 mHistory.add(bottom, r); 4459 moved.add(r.appToken); 4460 bottom++; 4461 } 4462 pos++; 4463 } 4464 4465 if (reason != null && 4466 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) { 4467 mService.mWindowManager.prepareAppTransition( 4468 AppTransition.TRANSIT_NONE, false); 4469 ActivityRecord r = topRunningActivityLocked(null); 4470 if (r != null) { 4471 mNoAnimActivities.add(r); 4472 } 4473 } else { 4474 mService.mWindowManager.prepareAppTransition( 4475 AppTransition.TRANSIT_TASK_TO_BACK, false); 4476 } 4477 mService.mWindowManager.moveAppTokensToBottom(moved); 4478 if (VALIDATE_TOKENS) { 4479 validateAppTokensLocked(); 4480 } 4481 4482 finishTaskMoveLocked(task); 4483 return true; 4484 } 4485 4486 public ActivityManager.TaskThumbnails getTaskThumbnailsLocked(TaskRecord tr) { 4487 TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true); 4488 ActivityRecord resumed = mResumedActivity; 4489 if (resumed != null && resumed.thumbHolder == tr) { 4490 info.mainThumbnail = resumed.stack.screenshotActivities(resumed); 4491 } 4492 if (info.mainThumbnail == null) { 4493 info.mainThumbnail = tr.lastThumbnail; 4494 } 4495 return info; 4496 } 4497 4498 public Bitmap getTaskTopThumbnailLocked(TaskRecord tr) { 4499 ActivityRecord resumed = mResumedActivity; 4500 if (resumed != null && resumed.task == tr) { 4501 // This task is the current resumed task, we just need to take 4502 // a screenshot of it and return that. 4503 return resumed.stack.screenshotActivities(resumed); 4504 } 4505 // Return the information about the task, to figure out the top 4506 // thumbnail to return. 4507 TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true); 4508 if (info.numSubThumbbails <= 0) { 4509 return info.mainThumbnail != null ? info.mainThumbnail : tr.lastThumbnail; 4510 } else { 4511 return info.subtasks.get(info.numSubThumbbails-1).holder.lastThumbnail; 4512 } 4513 } 4514 4515 public ActivityRecord removeTaskActivitiesLocked(int taskId, int subTaskIndex, 4516 boolean taskRequired) { 4517 TaskAccessInfo info = getTaskAccessInfoLocked(taskId, false); 4518 if (info.root == null) { 4519 if (taskRequired) { 4520 Slog.w(TAG, "removeTaskLocked: unknown taskId " + taskId); 4521 } 4522 return null; 4523 } 4524 4525 if (subTaskIndex < 0) { 4526 // Just remove the entire task. 4527 performClearTaskAtIndexLocked(taskId, info.rootIndex); 4528 return info.root; 4529 } 4530 4531 if (subTaskIndex >= info.subtasks.size()) { 4532 if (taskRequired) { 4533 Slog.w(TAG, "removeTaskLocked: unknown subTaskIndex " + subTaskIndex); 4534 } 4535 return null; 4536 } 4537 4538 // Remove all of this task's activities starting at the sub task. 4539 TaskAccessInfo.SubTask subtask = info.subtasks.get(subTaskIndex); 4540 performClearTaskAtIndexLocked(taskId, subtask.index); 4541 return subtask.activity; 4542 } 4543 4544 public TaskAccessInfo getTaskAccessInfoLocked(int taskId, boolean inclThumbs) { 4545 final TaskAccessInfo thumbs = new TaskAccessInfo(); 4546 // How many different sub-thumbnails? 4547 final int NA = mHistory.size(); 4548 int j = 0; 4549 ThumbnailHolder holder = null; 4550 while (j < NA) { 4551 ActivityRecord ar = mHistory.get(j); 4552 if (!ar.finishing && ar.task.taskId == taskId) { 4553 thumbs.root = ar; 4554 thumbs.rootIndex = j; 4555 holder = ar.thumbHolder; 4556 if (holder != null) { 4557 thumbs.mainThumbnail = holder.lastThumbnail; 4558 } 4559 j++; 4560 break; 4561 } 4562 j++; 4563 } 4564 4565 if (j >= NA) { 4566 return thumbs; 4567 } 4568 4569 ArrayList<TaskAccessInfo.SubTask> subtasks = new ArrayList<TaskAccessInfo.SubTask>(); 4570 thumbs.subtasks = subtasks; 4571 while (j < NA) { 4572 ActivityRecord ar = mHistory.get(j); 4573 j++; 4574 if (ar.finishing) { 4575 continue; 4576 } 4577 if (ar.task.taskId != taskId) { 4578 break; 4579 } 4580 if (ar.thumbHolder != holder && holder != null) { 4581 thumbs.numSubThumbbails++; 4582 holder = ar.thumbHolder; 4583 TaskAccessInfo.SubTask sub = new TaskAccessInfo.SubTask(); 4584 sub.holder = holder; 4585 sub.activity = ar; 4586 sub.index = j-1; 4587 subtasks.add(sub); 4588 } 4589 } 4590 if (thumbs.numSubThumbbails > 0) { 4591 thumbs.retriever = new IThumbnailRetriever.Stub() { 4592 public Bitmap getThumbnail(int index) { 4593 if (index < 0 || index >= thumbs.subtasks.size()) { 4594 return null; 4595 } 4596 TaskAccessInfo.SubTask sub = thumbs.subtasks.get(index); 4597 ActivityRecord resumed = mResumedActivity; 4598 if (resumed != null && resumed.thumbHolder == sub.holder) { 4599 return resumed.stack.screenshotActivities(resumed); 4600 } 4601 return sub.holder.lastThumbnail; 4602 } 4603 }; 4604 } 4605 return thumbs; 4606 } 4607 4608 private final void logStartActivity(int tag, ActivityRecord r, 4609 TaskRecord task) { 4610 EventLog.writeEvent(tag, 4611 r.userId, System.identityHashCode(r), task.taskId, 4612 r.shortComponentName, r.intent.getAction(), 4613 r.intent.getType(), r.intent.getDataString(), 4614 r.intent.getFlags()); 4615 } 4616 4617 /** 4618 * Make sure the given activity matches the current configuration. Returns 4619 * false if the activity had to be destroyed. Returns true if the 4620 * configuration is the same, or the activity will remain running as-is 4621 * for whatever reason. Ensures the HistoryRecord is updated with the 4622 * correct configuration and all other bookkeeping is handled. 4623 */ 4624 final boolean ensureActivityConfigurationLocked(ActivityRecord r, 4625 int globalChanges) { 4626 if (mConfigWillChange) { 4627 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4628 "Skipping config check (will change): " + r); 4629 return true; 4630 } 4631 4632 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4633 "Ensuring correct configuration: " + r); 4634 4635 // Short circuit: if the two configurations are the exact same 4636 // object (the common case), then there is nothing to do. 4637 Configuration newConfig = mService.mConfiguration; 4638 if (r.configuration == newConfig && !r.forceNewConfig) { 4639 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4640 "Configuration unchanged in " + r); 4641 return true; 4642 } 4643 4644 // We don't worry about activities that are finishing. 4645 if (r.finishing) { 4646 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4647 "Configuration doesn't matter in finishing " + r); 4648 r.stopFreezingScreenLocked(false); 4649 return true; 4650 } 4651 4652 // Okay we now are going to make this activity have the new config. 4653 // But then we need to figure out how it needs to deal with that. 4654 Configuration oldConfig = r.configuration; 4655 r.configuration = newConfig; 4656 4657 // Determine what has changed. May be nothing, if this is a config 4658 // that has come back from the app after going idle. In that case 4659 // we just want to leave the official config object now in the 4660 // activity and do nothing else. 4661 final int changes = oldConfig.diff(newConfig); 4662 if (changes == 0 && !r.forceNewConfig) { 4663 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4664 "Configuration no differences in " + r); 4665 return true; 4666 } 4667 4668 // If the activity isn't currently running, just leave the new 4669 // configuration and it will pick that up next time it starts. 4670 if (r.app == null || r.app.thread == null) { 4671 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4672 "Configuration doesn't matter not running " + r); 4673 r.stopFreezingScreenLocked(false); 4674 r.forceNewConfig = false; 4675 return true; 4676 } 4677 4678 // Figure out how to handle the changes between the configurations. 4679 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) { 4680 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x" 4681 + Integer.toHexString(changes) + ", handles=0x" 4682 + Integer.toHexString(r.info.getRealConfigChanged()) 4683 + ", newConfig=" + newConfig); 4684 } 4685 if ((changes&(~r.info.getRealConfigChanged())) != 0 || r.forceNewConfig) { 4686 // Aha, the activity isn't handling the change, so DIE DIE DIE. 4687 r.configChangeFlags |= changes; 4688 r.startFreezingScreenLocked(r.app, globalChanges); 4689 r.forceNewConfig = false; 4690 if (r.app == null || r.app.thread == null) { 4691 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4692 "Config is destroying non-running " + r); 4693 destroyActivityLocked(r, true, false, "config"); 4694 } else if (r.state == ActivityState.PAUSING) { 4695 // A little annoying: we are waiting for this activity to 4696 // finish pausing. Let's not do anything now, but just 4697 // flag that it needs to be restarted when done pausing. 4698 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4699 "Config is skipping already pausing " + r); 4700 r.configDestroy = true; 4701 return true; 4702 } else if (r.state == ActivityState.RESUMED) { 4703 // Try to optimize this case: the configuration is changing 4704 // and we need to restart the top, resumed activity. 4705 // Instead of doing the normal handshaking, just say 4706 // "restart!". 4707 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4708 "Config is relaunching resumed " + r); 4709 relaunchActivityLocked(r, r.configChangeFlags, true); 4710 r.configChangeFlags = 0; 4711 } else { 4712 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4713 "Config is relaunching non-resumed " + r); 4714 relaunchActivityLocked(r, r.configChangeFlags, false); 4715 r.configChangeFlags = 0; 4716 } 4717 4718 // All done... tell the caller we weren't able to keep this 4719 // activity around. 4720 return false; 4721 } 4722 4723 // Default case: the activity can handle this new configuration, so 4724 // hand it over. Note that we don't need to give it the new 4725 // configuration, since we always send configuration changes to all 4726 // process when they happen so it can just use whatever configuration 4727 // it last got. 4728 if (r.app != null && r.app.thread != null) { 4729 try { 4730 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r); 4731 r.app.thread.scheduleActivityConfigurationChanged(r.appToken); 4732 } catch (RemoteException e) { 4733 // If process died, whatever. 4734 } 4735 } 4736 r.stopFreezingScreenLocked(false); 4737 4738 return true; 4739 } 4740 4741 private final boolean relaunchActivityLocked(ActivityRecord r, 4742 int changes, boolean andResume) { 4743 List<ResultInfo> results = null; 4744 List<Intent> newIntents = null; 4745 if (andResume) { 4746 results = r.results; 4747 newIntents = r.newIntents; 4748 } 4749 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r 4750 + " with results=" + results + " newIntents=" + newIntents 4751 + " andResume=" + andResume); 4752 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY 4753 : EventLogTags.AM_RELAUNCH_ACTIVITY, r.userId, System.identityHashCode(r), 4754 r.task.taskId, r.shortComponentName); 4755 4756 r.startFreezingScreenLocked(r.app, 0); 4757 4758 try { 4759 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, 4760 (andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ") 4761 + r); 4762 r.forceNewConfig = false; 4763 r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents, 4764 changes, !andResume, new Configuration(mService.mConfiguration)); 4765 // Note: don't need to call pauseIfSleepingLocked() here, because 4766 // the caller will only pass in 'andResume' if this activity is 4767 // currently resumed, which implies we aren't sleeping. 4768 } catch (RemoteException e) { 4769 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, "Relaunch failed", e); 4770 } 4771 4772 if (andResume) { 4773 r.results = null; 4774 r.newIntents = null; 4775 if (mMainStack) { 4776 mService.reportResumedActivityLocked(r); 4777 } 4778 r.state = ActivityState.RESUMED; 4779 } else { 4780 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); 4781 r.state = ActivityState.PAUSED; 4782 } 4783 4784 return true; 4785 } 4786 4787 public void dismissKeyguardOnNextActivityLocked() { 4788 mDismissKeyguardOnNextActivity = true; 4789 } 4790} 4791