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