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