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