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