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