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