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