ActivityStack.java revision 45a25bcfc9af74bc4275cc710347304e581f3c51
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.finishing) { 2351 continue; 2352 } 2353 if (candidate.task.taskId != task) { 2354 break; 2355 } 2356 if (candidate.realActivity.equals(r.realActivity)) { 2357 return i; 2358 } 2359 } 2360 2361 return -1; 2362 } 2363 2364 /** 2365 * Reorder the history stack so that the activity at the given index is 2366 * brought to the front. 2367 */ 2368 private final ActivityRecord moveActivityToFrontLocked(int where) { 2369 ActivityRecord newTop = mHistory.remove(where); 2370 int top = mHistory.size(); 2371 ActivityRecord oldTop = mHistory.get(top-1); 2372 if (DEBUG_ADD_REMOVE) { 2373 RuntimeException here = new RuntimeException("here"); 2374 here.fillInStackTrace(); 2375 Slog.i(TAG, "Removing and adding activity " + newTop + " to stack at " 2376 + top, here); 2377 } 2378 mHistory.add(top, newTop); 2379 oldTop.frontOfTask = false; 2380 newTop.frontOfTask = true; 2381 return newTop; 2382 } 2383 2384 final int startActivityLocked(IApplicationThread caller, 2385 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo, 2386 String resultWho, int requestCode, 2387 int callingPid, int callingUid, int startFlags, Bundle options, 2388 boolean componentSpecified, ActivityRecord[] outActivity) { 2389 2390 int err = ActivityManager.START_SUCCESS; 2391 2392 ProcessRecord callerApp = null; 2393 if (caller != null) { 2394 callerApp = mService.getRecordForAppLocked(caller); 2395 if (callerApp != null) { 2396 callingPid = callerApp.pid; 2397 callingUid = callerApp.info.uid; 2398 } else { 2399 Slog.w(TAG, "Unable to find app for caller " + caller 2400 + " (pid=" + callingPid + ") when starting: " 2401 + intent.toString()); 2402 err = ActivityManager.START_PERMISSION_DENIED; 2403 } 2404 } 2405 2406 if (err == ActivityManager.START_SUCCESS) { 2407 final int userId = aInfo != null ? UserId.getUserId(aInfo.applicationInfo.uid) : 0; 2408 Slog.i(TAG, "START {" + intent.toShortString(true, true, true, false) 2409 + " u=" + userId + "} from pid " + (callerApp != null ? callerApp.pid : callingPid)); 2410 } 2411 2412 ActivityRecord sourceRecord = null; 2413 ActivityRecord resultRecord = null; 2414 if (resultTo != null) { 2415 int index = indexOfTokenLocked(resultTo); 2416 if (DEBUG_RESULTS) Slog.v( 2417 TAG, "Will send result to " + resultTo + " (index " + index + ")"); 2418 if (index >= 0) { 2419 sourceRecord = mHistory.get(index); 2420 if (requestCode >= 0 && !sourceRecord.finishing) { 2421 resultRecord = sourceRecord; 2422 } 2423 } 2424 } 2425 2426 int launchFlags = intent.getFlags(); 2427 2428 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 2429 && sourceRecord != null) { 2430 // Transfer the result target from the source activity to the new 2431 // one being started, including any failures. 2432 if (requestCode >= 0) { 2433 ActivityOptions.abort(options); 2434 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT; 2435 } 2436 resultRecord = sourceRecord.resultTo; 2437 resultWho = sourceRecord.resultWho; 2438 requestCode = sourceRecord.requestCode; 2439 sourceRecord.resultTo = null; 2440 if (resultRecord != null) { 2441 resultRecord.removeResultsLocked( 2442 sourceRecord, resultWho, requestCode); 2443 } 2444 } 2445 2446 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) { 2447 // We couldn't find a class that can handle the given Intent. 2448 // That's the end of that! 2449 err = ActivityManager.START_INTENT_NOT_RESOLVED; 2450 } 2451 2452 if (err == ActivityManager.START_SUCCESS && aInfo == null) { 2453 // We couldn't find the specific class specified in the Intent. 2454 // Also the end of the line. 2455 err = ActivityManager.START_CLASS_NOT_FOUND; 2456 } 2457 2458 if (err != ActivityManager.START_SUCCESS) { 2459 if (resultRecord != null) { 2460 sendActivityResultLocked(-1, 2461 resultRecord, resultWho, requestCode, 2462 Activity.RESULT_CANCELED, null); 2463 } 2464 mDismissKeyguardOnNextActivity = false; 2465 ActivityOptions.abort(options); 2466 return err; 2467 } 2468 2469 final int startAnyPerm = mService.checkPermission( 2470 START_ANY_ACTIVITY, callingPid, callingUid); 2471 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid, 2472 callingUid, aInfo.applicationInfo.uid, aInfo.exported); 2473 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) { 2474 if (resultRecord != null) { 2475 sendActivityResultLocked(-1, 2476 resultRecord, resultWho, requestCode, 2477 Activity.RESULT_CANCELED, null); 2478 } 2479 mDismissKeyguardOnNextActivity = false; 2480 String msg; 2481 if (!aInfo.exported) { 2482 msg = "Permission Denial: starting " + intent.toString() 2483 + " from " + callerApp + " (pid=" + callingPid 2484 + ", uid=" + callingUid + ")" 2485 + " not exported from uid " + aInfo.applicationInfo.uid; 2486 } else { 2487 msg = "Permission Denial: starting " + intent.toString() 2488 + " from " + callerApp + " (pid=" + callingPid 2489 + ", uid=" + callingUid + ")" 2490 + " requires " + aInfo.permission; 2491 } 2492 Slog.w(TAG, msg); 2493 throw new SecurityException(msg); 2494 } 2495 2496 if (mMainStack) { 2497 if (mService.mController != null) { 2498 boolean abort = false; 2499 try { 2500 // The Intent we give to the watcher has the extra data 2501 // stripped off, since it can contain private information. 2502 Intent watchIntent = intent.cloneFilter(); 2503 abort = !mService.mController.activityStarting(watchIntent, 2504 aInfo.applicationInfo.packageName); 2505 } catch (RemoteException e) { 2506 mService.mController = null; 2507 } 2508 2509 if (abort) { 2510 if (resultRecord != null) { 2511 sendActivityResultLocked(-1, 2512 resultRecord, resultWho, requestCode, 2513 Activity.RESULT_CANCELED, null); 2514 } 2515 // We pretend to the caller that it was really started, but 2516 // they will just get a cancel result. 2517 mDismissKeyguardOnNextActivity = false; 2518 ActivityOptions.abort(options); 2519 return ActivityManager.START_SUCCESS; 2520 } 2521 } 2522 } 2523 2524 ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid, 2525 intent, resolvedType, aInfo, mService.mConfiguration, 2526 resultRecord, resultWho, requestCode, componentSpecified); 2527 if (outActivity != null) { 2528 outActivity[0] = r; 2529 } 2530 2531 if (mMainStack) { 2532 if (mResumedActivity == null 2533 || mResumedActivity.info.applicationInfo.uid != callingUid) { 2534 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) { 2535 PendingActivityLaunch pal = new PendingActivityLaunch(); 2536 pal.r = r; 2537 pal.sourceRecord = sourceRecord; 2538 pal.startFlags = startFlags; 2539 mService.mPendingActivityLaunches.add(pal); 2540 mDismissKeyguardOnNextActivity = false; 2541 ActivityOptions.abort(options); 2542 return ActivityManager.START_SWITCHES_CANCELED; 2543 } 2544 } 2545 2546 if (mService.mDidAppSwitch) { 2547 // This is the second allowed switch since we stopped switches, 2548 // so now just generally allow switches. Use case: user presses 2549 // home (switches disabled, switch to home, mDidAppSwitch now true); 2550 // user taps a home icon (coming from home so allowed, we hit here 2551 // and now allow anyone to switch again). 2552 mService.mAppSwitchesAllowedTime = 0; 2553 } else { 2554 mService.mDidAppSwitch = true; 2555 } 2556 2557 mService.doPendingActivityLaunchesLocked(false); 2558 } 2559 2560 err = startActivityUncheckedLocked(r, sourceRecord, 2561 startFlags, true, options); 2562 if (mDismissKeyguardOnNextActivity && mPausingActivity == null) { 2563 // Someone asked to have the keyguard dismissed on the next 2564 // activity start, but we are not actually doing an activity 2565 // switch... just dismiss the keyguard now, because we 2566 // probably want to see whatever is behind it. 2567 mDismissKeyguardOnNextActivity = false; 2568 mService.mWindowManager.dismissKeyguard(); 2569 } 2570 return err; 2571 } 2572 2573 final void moveHomeToFrontFromLaunchLocked(int launchFlags) { 2574 if ((launchFlags & 2575 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) 2576 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) { 2577 // Caller wants to appear on home activity, so before starting 2578 // their own activity we will bring home to the front. 2579 moveHomeToFrontLocked(); 2580 } 2581 } 2582 2583 final int startActivityUncheckedLocked(ActivityRecord r, 2584 ActivityRecord sourceRecord, int startFlags, boolean doResume, 2585 Bundle options) { 2586 final Intent intent = r.intent; 2587 final int callingUid = r.launchedFromUid; 2588 final int userId = r.userId; 2589 2590 int launchFlags = intent.getFlags(); 2591 2592 // We'll invoke onUserLeaving before onPause only if the launching 2593 // activity did not explicitly state that this is an automated launch. 2594 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0; 2595 if (DEBUG_USER_LEAVING) Slog.v(TAG, 2596 "startActivity() => mUserLeaving=" + mUserLeaving); 2597 2598 // If the caller has asked not to resume at this point, we make note 2599 // of this in the record so that we can skip it when trying to find 2600 // the top running activity. 2601 if (!doResume) { 2602 r.delayedResume = true; 2603 } 2604 2605 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) 2606 != 0 ? r : null; 2607 2608 // If the onlyIfNeeded flag is set, then we can do this if the activity 2609 // being launched is the same as the one making the call... or, as 2610 // a special case, if we do not know the caller then we count the 2611 // current top activity as the caller. 2612 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { 2613 ActivityRecord checkedCaller = sourceRecord; 2614 if (checkedCaller == null) { 2615 checkedCaller = topRunningNonDelayedActivityLocked(notTop); 2616 } 2617 if (!checkedCaller.realActivity.equals(r.realActivity)) { 2618 // Caller is not the same as launcher, so always needed. 2619 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED; 2620 } 2621 } 2622 2623 if (sourceRecord == null) { 2624 // This activity is not being started from another... in this 2625 // case we -always- start a new task. 2626 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) { 2627 Slog.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: " 2628 + intent); 2629 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; 2630 } 2631 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { 2632 // The original activity who is starting us is running as a single 2633 // instance... this new activity it is starting must go on its 2634 // own task. 2635 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; 2636 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE 2637 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) { 2638 // The activity being started is a single instance... it always 2639 // gets launched into its own task. 2640 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK; 2641 } 2642 2643 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { 2644 // For whatever reason this activity is being launched into a new 2645 // task... yet the caller has requested a result back. Well, that 2646 // is pretty messed up, so instead immediately send back a cancel 2647 // and let the new task continue launched as normal without a 2648 // dependency on its originator. 2649 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result."); 2650 sendActivityResultLocked(-1, 2651 r.resultTo, r.resultWho, r.requestCode, 2652 Activity.RESULT_CANCELED, null); 2653 r.resultTo = null; 2654 } 2655 2656 boolean addingToTask = false; 2657 boolean movedHome = false; 2658 TaskRecord reuseTask = null; 2659 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && 2660 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0) 2661 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK 2662 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { 2663 // If bring to front is requested, and no result is requested, and 2664 // we can find a task that was started with this same 2665 // component, then instead of launching bring that one to the front. 2666 if (r.resultTo == null) { 2667 // See if there is a task to bring to the front. If this is 2668 // a SINGLE_INSTANCE activity, there can be one and only one 2669 // instance of it in the history, and it is always in its own 2670 // unique task, so we do a special search. 2671 ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE 2672 ? findTaskLocked(intent, r.info) 2673 : findActivityLocked(intent, r.info); 2674 if (taskTop != null) { 2675 if (taskTop.task.intent == null) { 2676 // This task was started because of movement of 2677 // the activity based on affinity... now that we 2678 // are actually launching it, we can assign the 2679 // base intent. 2680 taskTop.task.setIntent(intent, r.info); 2681 } 2682 // If the target task is not in the front, then we need 2683 // to bring it to the front... except... well, with 2684 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like 2685 // to have the same behavior as if a new instance was 2686 // being started, which means not bringing it to the front 2687 // if the caller is not itself in the front. 2688 ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop); 2689 if (curTop != null && curTop.task != taskTop.task) { 2690 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT); 2691 boolean callerAtFront = sourceRecord == null 2692 || curTop.task == sourceRecord.task; 2693 if (callerAtFront) { 2694 // We really do want to push this one into the 2695 // user's face, right now. 2696 movedHome = true; 2697 moveHomeToFrontFromLaunchLocked(launchFlags); 2698 moveTaskToFrontLocked(taskTop.task, r, options); 2699 options = null; 2700 } 2701 } 2702 // If the caller has requested that the target task be 2703 // reset, then do so. 2704 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) { 2705 taskTop = resetTaskIfNeededLocked(taskTop, r); 2706 } 2707 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { 2708 // We don't need to start a new activity, and 2709 // the client said not to do anything if that 2710 // is the case, so this is it! And for paranoia, make 2711 // sure we have correctly resumed the top activity. 2712 if (doResume) { 2713 resumeTopActivityLocked(null, options); 2714 } else { 2715 ActivityOptions.abort(options); 2716 } 2717 return ActivityManager.START_RETURN_INTENT_TO_CALLER; 2718 } 2719 if ((launchFlags & 2720 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) 2721 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) { 2722 // The caller has requested to completely replace any 2723 // existing task with its new activity. Well that should 2724 // not be too hard... 2725 reuseTask = taskTop.task; 2726 performClearTaskLocked(taskTop.task.taskId); 2727 reuseTask.setIntent(r.intent, r.info); 2728 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0 2729 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK 2730 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) { 2731 // In this situation we want to remove all activities 2732 // from the task up to the one being started. In most 2733 // cases this means we are resetting the task to its 2734 // initial state. 2735 ActivityRecord top = performClearTaskLocked( 2736 taskTop.task.taskId, r, launchFlags); 2737 if (top != null) { 2738 if (top.frontOfTask) { 2739 // Activity aliases may mean we use different 2740 // intents for the top activity, so make sure 2741 // the task now has the identity of the new 2742 // intent. 2743 top.task.setIntent(r.intent, r.info); 2744 } 2745 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); 2746 top.deliverNewIntentLocked(callingUid, r.intent); 2747 } else { 2748 // A special case: we need to 2749 // start the activity because it is not currently 2750 // running, and the caller has asked to clear the 2751 // current task to have this activity at the top. 2752 addingToTask = true; 2753 // Now pretend like this activity is being started 2754 // by the top of its task, so it is put in the 2755 // right place. 2756 sourceRecord = taskTop; 2757 } 2758 } else if (r.realActivity.equals(taskTop.task.realActivity)) { 2759 // In this case the top activity on the task is the 2760 // same as the one being launched, so we take that 2761 // as a request to bring the task to the foreground. 2762 // If the top activity in the task is the root 2763 // activity, deliver this new intent to it if it 2764 // desires. 2765 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 2766 && taskTop.realActivity.equals(r.realActivity)) { 2767 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task); 2768 if (taskTop.frontOfTask) { 2769 taskTop.task.setIntent(r.intent, r.info); 2770 } 2771 taskTop.deliverNewIntentLocked(callingUid, r.intent); 2772 } else if (!r.intent.filterEquals(taskTop.task.intent)) { 2773 // In this case we are launching the root activity 2774 // of the task, but with a different intent. We 2775 // should start a new instance on top. 2776 addingToTask = true; 2777 sourceRecord = taskTop; 2778 } 2779 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) { 2780 // In this case an activity is being launched in to an 2781 // existing task, without resetting that task. This 2782 // is typically the situation of launching an activity 2783 // from a notification or shortcut. We want to place 2784 // the new activity on top of the current task. 2785 addingToTask = true; 2786 sourceRecord = taskTop; 2787 } else if (!taskTop.task.rootWasReset) { 2788 // In this case we are launching in to an existing task 2789 // that has not yet been started from its front door. 2790 // The current task has been brought to the front. 2791 // Ideally, we'd probably like to place this new task 2792 // at the bottom of its stack, but that's a little hard 2793 // to do with the current organization of the code so 2794 // for now we'll just drop it. 2795 taskTop.task.setIntent(r.intent, r.info); 2796 } 2797 if (!addingToTask && reuseTask == null) { 2798 // We didn't do anything... but it was needed (a.k.a., client 2799 // don't use that intent!) And for paranoia, make 2800 // sure we have correctly resumed the top activity. 2801 if (doResume) { 2802 resumeTopActivityLocked(null, options); 2803 } else { 2804 ActivityOptions.abort(options); 2805 } 2806 return ActivityManager.START_TASK_TO_FRONT; 2807 } 2808 } 2809 } 2810 } 2811 2812 //String uri = r.intent.toURI(); 2813 //Intent intent2 = new Intent(uri); 2814 //Slog.i(TAG, "Given intent: " + r.intent); 2815 //Slog.i(TAG, "URI is: " + uri); 2816 //Slog.i(TAG, "To intent: " + intent2); 2817 2818 if (r.packageName != null) { 2819 // If the activity being launched is the same as the one currently 2820 // at the top, then we need to check if it should only be launched 2821 // once. 2822 ActivityRecord top = topRunningNonDelayedActivityLocked(notTop); 2823 if (top != null && r.resultTo == null) { 2824 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) { 2825 if (top.app != null && top.app.thread != null) { 2826 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0 2827 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP 2828 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) { 2829 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task); 2830 // For paranoia, make sure we have correctly 2831 // resumed the top activity. 2832 if (doResume) { 2833 resumeTopActivityLocked(null); 2834 } 2835 ActivityOptions.abort(options); 2836 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) { 2837 // We don't need to start a new activity, and 2838 // the client said not to do anything if that 2839 // is the case, so this is it! 2840 return ActivityManager.START_RETURN_INTENT_TO_CALLER; 2841 } 2842 top.deliverNewIntentLocked(callingUid, r.intent); 2843 return ActivityManager.START_DELIVERED_TO_TOP; 2844 } 2845 } 2846 } 2847 } 2848 2849 } else { 2850 if (r.resultTo != null) { 2851 sendActivityResultLocked(-1, 2852 r.resultTo, r.resultWho, r.requestCode, 2853 Activity.RESULT_CANCELED, null); 2854 } 2855 ActivityOptions.abort(options); 2856 return ActivityManager.START_CLASS_NOT_FOUND; 2857 } 2858 2859 boolean newTask = false; 2860 boolean keepCurTransition = false; 2861 2862 // Should this be considered a new task? 2863 if (r.resultTo == null && !addingToTask 2864 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) { 2865 if (reuseTask == null) { 2866 // todo: should do better management of integers. 2867 mService.mCurTask++; 2868 if (mService.mCurTask <= 0) { 2869 mService.mCurTask = 1; 2870 } 2871 r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null, true); 2872 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r 2873 + " in new task " + r.task); 2874 } else { 2875 r.setTask(reuseTask, reuseTask, true); 2876 } 2877 newTask = true; 2878 if (!movedHome) { 2879 moveHomeToFrontFromLaunchLocked(launchFlags); 2880 } 2881 2882 } else if (sourceRecord != null) { 2883 if (!addingToTask && 2884 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) { 2885 // In this case, we are adding the activity to an existing 2886 // task, but the caller has asked to clear that task if the 2887 // activity is already running. 2888 ActivityRecord top = performClearTaskLocked( 2889 sourceRecord.task.taskId, r, launchFlags); 2890 keepCurTransition = true; 2891 if (top != null) { 2892 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); 2893 top.deliverNewIntentLocked(callingUid, r.intent); 2894 // For paranoia, make sure we have correctly 2895 // resumed the top activity. 2896 if (doResume) { 2897 resumeTopActivityLocked(null); 2898 } 2899 ActivityOptions.abort(options); 2900 return ActivityManager.START_DELIVERED_TO_TOP; 2901 } 2902 } else if (!addingToTask && 2903 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) { 2904 // In this case, we are launching an activity in our own task 2905 // that may already be running somewhere in the history, and 2906 // we want to shuffle it to the front of the stack if so. 2907 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId); 2908 if (where >= 0) { 2909 ActivityRecord top = moveActivityToFrontLocked(where); 2910 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task); 2911 top.updateOptionsLocked(options); 2912 top.deliverNewIntentLocked(callingUid, r.intent); 2913 if (doResume) { 2914 resumeTopActivityLocked(null); 2915 } 2916 return ActivityManager.START_DELIVERED_TO_TOP; 2917 } 2918 } 2919 // An existing activity is starting this new activity, so we want 2920 // to keep the new one in the same task as the one that is starting 2921 // it. 2922 r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false); 2923 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r 2924 + " in existing task " + r.task); 2925 2926 } else { 2927 // This not being started from an existing activity, and not part 2928 // of a new task... just put it in the top task, though these days 2929 // this case should never happen. 2930 final int N = mHistory.size(); 2931 ActivityRecord prev = 2932 N > 0 ? mHistory.get(N-1) : null; 2933 r.setTask(prev != null 2934 ? prev.task 2935 : new TaskRecord(mService.mCurTask, r.info, intent), null, true); 2936 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r 2937 + " in new guessed " + r.task); 2938 } 2939 2940 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName, 2941 intent, r.getUriPermissionsLocked()); 2942 2943 if (newTask) { 2944 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.task.taskId); 2945 } 2946 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task); 2947 startActivityLocked(r, newTask, doResume, keepCurTransition, options); 2948 return ActivityManager.START_SUCCESS; 2949 } 2950 2951 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags, 2952 String profileFile, ParcelFileDescriptor profileFd, int userId) { 2953 // Collect information about the target of the Intent. 2954 ActivityInfo aInfo; 2955 try { 2956 ResolveInfo rInfo = 2957 AppGlobals.getPackageManager().resolveIntent( 2958 intent, resolvedType, 2959 PackageManager.MATCH_DEFAULT_ONLY 2960 | ActivityManagerService.STOCK_PM_FLAGS, userId); 2961 aInfo = rInfo != null ? rInfo.activityInfo : null; 2962 } catch (RemoteException e) { 2963 aInfo = null; 2964 } 2965 2966 if (aInfo != null) { 2967 // Store the found target back into the intent, because now that 2968 // we have it we never want to do this again. For example, if the 2969 // user navigates back to this point in the history, we should 2970 // always restart the exact same activity. 2971 intent.setComponent(new ComponentName( 2972 aInfo.applicationInfo.packageName, aInfo.name)); 2973 2974 // Don't debug things in the system process 2975 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) { 2976 if (!aInfo.processName.equals("system")) { 2977 mService.setDebugApp(aInfo.processName, true, false); 2978 } 2979 } 2980 2981 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) { 2982 if (!aInfo.processName.equals("system")) { 2983 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName); 2984 } 2985 } 2986 2987 if (profileFile != null) { 2988 if (!aInfo.processName.equals("system")) { 2989 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName, 2990 profileFile, profileFd, 2991 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0); 2992 } 2993 } 2994 } 2995 return aInfo; 2996 } 2997 2998 final int startActivityMayWait(IApplicationThread caller, int callingUid, 2999 Intent intent, String resolvedType, IBinder resultTo, 3000 String resultWho, int requestCode, int startFlags, String profileFile, 3001 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config, 3002 Bundle options, int userId) { 3003 // Refuse possible leaked file descriptors 3004 if (intent != null && intent.hasFileDescriptors()) { 3005 throw new IllegalArgumentException("File descriptors passed in Intent"); 3006 } 3007 boolean componentSpecified = intent.getComponent() != null; 3008 3009 // Don't modify the client's object! 3010 intent = new Intent(intent); 3011 3012 // Collect information about the target of the Intent. 3013 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, 3014 profileFile, profileFd, userId); 3015 if (aInfo != null && mService.isSingleton(aInfo.processName, aInfo.applicationInfo)) { 3016 userId = 0; 3017 } 3018 aInfo = mService.getActivityInfoForUser(aInfo, userId); 3019 3020 synchronized (mService) { 3021 int callingPid; 3022 if (callingUid >= 0) { 3023 callingPid = -1; 3024 } else if (caller == null) { 3025 callingPid = Binder.getCallingPid(); 3026 callingUid = Binder.getCallingUid(); 3027 } else { 3028 callingPid = callingUid = -1; 3029 } 3030 3031 mConfigWillChange = config != null 3032 && mService.mConfiguration.diff(config) != 0; 3033 if (DEBUG_CONFIGURATION) Slog.v(TAG, 3034 "Starting activity when config will change = " + mConfigWillChange); 3035 3036 final long origId = Binder.clearCallingIdentity(); 3037 3038 if (mMainStack && aInfo != null && 3039 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) { 3040 // This may be a heavy-weight process! Check to see if we already 3041 // have another, different heavy-weight process running. 3042 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) { 3043 if (mService.mHeavyWeightProcess != null && 3044 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid || 3045 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) { 3046 int realCallingPid = callingPid; 3047 int realCallingUid = callingUid; 3048 if (caller != null) { 3049 ProcessRecord callerApp = mService.getRecordForAppLocked(caller); 3050 if (callerApp != null) { 3051 realCallingPid = callerApp.pid; 3052 realCallingUid = callerApp.info.uid; 3053 } else { 3054 Slog.w(TAG, "Unable to find app for caller " + caller 3055 + " (pid=" + realCallingPid + ") when starting: " 3056 + intent.toString()); 3057 ActivityOptions.abort(options); 3058 return ActivityManager.START_PERMISSION_DENIED; 3059 } 3060 } 3061 3062 IIntentSender target = mService.getIntentSenderLocked( 3063 ActivityManager.INTENT_SENDER_ACTIVITY, "android", 3064 realCallingUid, null, null, 0, new Intent[] { intent }, 3065 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT 3066 | PendingIntent.FLAG_ONE_SHOT, null); 3067 3068 Intent newIntent = new Intent(); 3069 if (requestCode >= 0) { 3070 // Caller is requesting a result. 3071 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true); 3072 } 3073 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT, 3074 new IntentSender(target)); 3075 if (mService.mHeavyWeightProcess.activities.size() > 0) { 3076 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0); 3077 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP, 3078 hist.packageName); 3079 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK, 3080 hist.task.taskId); 3081 } 3082 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP, 3083 aInfo.packageName); 3084 newIntent.setFlags(intent.getFlags()); 3085 newIntent.setClassName("android", 3086 HeavyWeightSwitcherActivity.class.getName()); 3087 intent = newIntent; 3088 resolvedType = null; 3089 caller = null; 3090 callingUid = Binder.getCallingUid(); 3091 callingPid = Binder.getCallingPid(); 3092 componentSpecified = true; 3093 try { 3094 ResolveInfo rInfo = 3095 AppGlobals.getPackageManager().resolveIntent( 3096 intent, null, 3097 PackageManager.MATCH_DEFAULT_ONLY 3098 | ActivityManagerService.STOCK_PM_FLAGS, userId); 3099 aInfo = rInfo != null ? rInfo.activityInfo : null; 3100 aInfo = mService.getActivityInfoForUser(aInfo, userId); 3101 } catch (RemoteException e) { 3102 aInfo = null; 3103 } 3104 } 3105 } 3106 } 3107 3108 int res = startActivityLocked(caller, intent, resolvedType, 3109 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid, 3110 startFlags, options, componentSpecified, null); 3111 3112 if (mConfigWillChange && mMainStack) { 3113 // If the caller also wants to switch to a new configuration, 3114 // do so now. This allows a clean switch, as we are waiting 3115 // for the current activity to pause (so we will not destroy 3116 // it), and have not yet started the next activity. 3117 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION, 3118 "updateConfiguration()"); 3119 mConfigWillChange = false; 3120 if (DEBUG_CONFIGURATION) Slog.v(TAG, 3121 "Updating to new configuration after starting activity."); 3122 mService.updateConfigurationLocked(config, null, false, false); 3123 } 3124 3125 Binder.restoreCallingIdentity(origId); 3126 3127 if (outResult != null) { 3128 outResult.result = res; 3129 if (res == ActivityManager.START_SUCCESS) { 3130 mWaitingActivityLaunched.add(outResult); 3131 do { 3132 try { 3133 mService.wait(); 3134 } catch (InterruptedException e) { 3135 } 3136 } while (!outResult.timeout && outResult.who == null); 3137 } else if (res == ActivityManager.START_TASK_TO_FRONT) { 3138 ActivityRecord r = this.topRunningActivityLocked(null); 3139 if (r.nowVisible) { 3140 outResult.timeout = false; 3141 outResult.who = new ComponentName(r.info.packageName, r.info.name); 3142 outResult.totalTime = 0; 3143 outResult.thisTime = 0; 3144 } else { 3145 outResult.thisTime = SystemClock.uptimeMillis(); 3146 mWaitingActivityVisible.add(outResult); 3147 do { 3148 try { 3149 mService.wait(); 3150 } catch (InterruptedException e) { 3151 } 3152 } while (!outResult.timeout && outResult.who == null); 3153 } 3154 } 3155 } 3156 3157 return res; 3158 } 3159 } 3160 3161 final int startActivities(IApplicationThread caller, int callingUid, 3162 Intent[] intents, String[] resolvedTypes, IBinder resultTo, 3163 Bundle options, int userId) { 3164 if (intents == null) { 3165 throw new NullPointerException("intents is null"); 3166 } 3167 if (resolvedTypes == null) { 3168 throw new NullPointerException("resolvedTypes is null"); 3169 } 3170 if (intents.length != resolvedTypes.length) { 3171 throw new IllegalArgumentException("intents are length different than resolvedTypes"); 3172 } 3173 3174 ActivityRecord[] outActivity = new ActivityRecord[1]; 3175 3176 int callingPid; 3177 if (callingUid >= 0) { 3178 callingPid = -1; 3179 } else if (caller == null) { 3180 callingPid = Binder.getCallingPid(); 3181 callingUid = Binder.getCallingUid(); 3182 } else { 3183 callingPid = callingUid = -1; 3184 } 3185 final long origId = Binder.clearCallingIdentity(); 3186 try { 3187 synchronized (mService) { 3188 3189 for (int i=0; i<intents.length; i++) { 3190 Intent intent = intents[i]; 3191 if (intent == null) { 3192 continue; 3193 } 3194 3195 // Refuse possible leaked file descriptors 3196 if (intent != null && intent.hasFileDescriptors()) { 3197 throw new IllegalArgumentException("File descriptors passed in Intent"); 3198 } 3199 3200 boolean componentSpecified = intent.getComponent() != null; 3201 3202 // Don't modify the client's object! 3203 intent = new Intent(intent); 3204 3205 // Collect information about the target of the Intent. 3206 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i], 3207 0, null, null, userId); 3208 // TODO: New, check if this is correct 3209 aInfo = mService.getActivityInfoForUser(aInfo, userId); 3210 3211 if (mMainStack && aInfo != null && (aInfo.applicationInfo.flags 3212 & ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) { 3213 throw new IllegalArgumentException( 3214 "FLAG_CANT_SAVE_STATE not supported here"); 3215 } 3216 3217 Bundle theseOptions; 3218 if (options != null && i == intents.length-1) { 3219 theseOptions = options; 3220 } else { 3221 theseOptions = null; 3222 } 3223 int res = startActivityLocked(caller, intent, resolvedTypes[i], 3224 aInfo, resultTo, null, -1, callingPid, callingUid, 3225 0, theseOptions, componentSpecified, outActivity); 3226 if (res < 0) { 3227 return res; 3228 } 3229 3230 resultTo = outActivity[0] != null ? outActivity[0].appToken : null; 3231 } 3232 } 3233 } finally { 3234 Binder.restoreCallingIdentity(origId); 3235 } 3236 3237 return ActivityManager.START_SUCCESS; 3238 } 3239 3240 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r, 3241 long thisTime, long totalTime) { 3242 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) { 3243 WaitResult w = mWaitingActivityLaunched.get(i); 3244 w.timeout = timeout; 3245 if (r != null) { 3246 w.who = new ComponentName(r.info.packageName, r.info.name); 3247 } 3248 w.thisTime = thisTime; 3249 w.totalTime = totalTime; 3250 } 3251 mService.notifyAll(); 3252 } 3253 3254 void reportActivityVisibleLocked(ActivityRecord r) { 3255 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) { 3256 WaitResult w = mWaitingActivityVisible.get(i); 3257 w.timeout = false; 3258 if (r != null) { 3259 w.who = new ComponentName(r.info.packageName, r.info.name); 3260 } 3261 w.totalTime = SystemClock.uptimeMillis() - w.thisTime; 3262 w.thisTime = w.totalTime; 3263 } 3264 mService.notifyAll(); 3265 3266 if (mDismissKeyguardOnNextActivity) { 3267 mDismissKeyguardOnNextActivity = false; 3268 mService.mWindowManager.dismissKeyguard(); 3269 } 3270 } 3271 3272 void sendActivityResultLocked(int callingUid, ActivityRecord r, 3273 String resultWho, int requestCode, int resultCode, Intent data) { 3274 3275 if (callingUid > 0) { 3276 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName, 3277 data, r.getUriPermissionsLocked()); 3278 } 3279 3280 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r 3281 + " : who=" + resultWho + " req=" + requestCode 3282 + " res=" + resultCode + " data=" + data); 3283 if (mResumedActivity == r && r.app != null && r.app.thread != null) { 3284 try { 3285 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>(); 3286 list.add(new ResultInfo(resultWho, requestCode, 3287 resultCode, data)); 3288 r.app.thread.scheduleSendResult(r.appToken, list); 3289 return; 3290 } catch (Exception e) { 3291 Slog.w(TAG, "Exception thrown sending result to " + r, e); 3292 } 3293 } 3294 3295 r.addResultLocked(null, resultWho, requestCode, resultCode, data); 3296 } 3297 3298 private final void stopActivityLocked(ActivityRecord r) { 3299 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r); 3300 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0 3301 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) { 3302 if (!r.finishing) { 3303 if (!mService.mSleeping) { 3304 if (DEBUG_STATES) { 3305 Slog.d(TAG, "no-history finish of " + r); 3306 } 3307 requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null, 3308 "no-history"); 3309 } else { 3310 if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r 3311 + " on stop because we're just sleeping"); 3312 } 3313 } 3314 } 3315 3316 if (r.app != null && r.app.thread != null) { 3317 if (mMainStack) { 3318 if (mService.mFocusedActivity == r) { 3319 mService.setFocusedActivityLocked(topRunningActivityLocked(null)); 3320 } 3321 } 3322 r.resumeKeyDispatchingLocked(); 3323 try { 3324 r.stopped = false; 3325 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r 3326 + " (stop requested)"); 3327 r.state = ActivityState.STOPPING; 3328 if (DEBUG_VISBILITY) Slog.v( 3329 TAG, "Stopping visible=" + r.visible + " for " + r); 3330 if (!r.visible) { 3331 mService.mWindowManager.setAppVisibility(r.appToken, false); 3332 } 3333 r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags); 3334 if (mService.isSleeping()) { 3335 r.setSleeping(true); 3336 } 3337 Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG); 3338 msg.obj = r; 3339 mHandler.sendMessageDelayed(msg, STOP_TIMEOUT); 3340 } catch (Exception e) { 3341 // Maybe just ignore exceptions here... if the process 3342 // has crashed, our death notification will clean things 3343 // up. 3344 Slog.w(TAG, "Exception thrown during pause", e); 3345 // Just in case, assume it to be stopped. 3346 r.stopped = true; 3347 if (DEBUG_STATES) Slog.v(TAG, "Stop failed; moving to STOPPED: " + r); 3348 r.state = ActivityState.STOPPED; 3349 if (r.configDestroy) { 3350 destroyActivityLocked(r, true, false, "stop-except"); 3351 } 3352 } 3353 } 3354 } 3355 3356 final ArrayList<ActivityRecord> processStoppingActivitiesLocked( 3357 boolean remove) { 3358 int N = mStoppingActivities.size(); 3359 if (N <= 0) return null; 3360 3361 ArrayList<ActivityRecord> stops = null; 3362 3363 final boolean nowVisible = mResumedActivity != null 3364 && mResumedActivity.nowVisible 3365 && !mResumedActivity.waitingVisible; 3366 for (int i=0; i<N; i++) { 3367 ActivityRecord s = mStoppingActivities.get(i); 3368 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible=" 3369 + nowVisible + " waitingVisible=" + s.waitingVisible 3370 + " finishing=" + s.finishing); 3371 if (s.waitingVisible && nowVisible) { 3372 mWaitingVisibleActivities.remove(s); 3373 s.waitingVisible = false; 3374 if (s.finishing) { 3375 // If this activity is finishing, it is sitting on top of 3376 // everyone else but we now know it is no longer needed... 3377 // so get rid of it. Otherwise, we need to go through the 3378 // normal flow and hide it once we determine that it is 3379 // hidden by the activities in front of it. 3380 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s); 3381 mService.mWindowManager.setAppVisibility(s.appToken, false); 3382 } 3383 } 3384 if ((!s.waitingVisible || mService.isSleeping()) && remove) { 3385 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s); 3386 if (stops == null) { 3387 stops = new ArrayList<ActivityRecord>(); 3388 } 3389 stops.add(s); 3390 mStoppingActivities.remove(i); 3391 N--; 3392 i--; 3393 } 3394 } 3395 3396 return stops; 3397 } 3398 3399 final void scheduleIdleLocked() { 3400 Message msg = Message.obtain(); 3401 msg.what = IDLE_NOW_MSG; 3402 mHandler.sendMessage(msg); 3403 } 3404 3405 final ActivityRecord activityIdleInternal(IBinder token, boolean fromTimeout, 3406 Configuration config) { 3407 if (localLOGV) Slog.v(TAG, "Activity idle: " + token); 3408 3409 ActivityRecord res = null; 3410 3411 ArrayList<ActivityRecord> stops = null; 3412 ArrayList<ActivityRecord> finishes = null; 3413 ArrayList<ActivityRecord> thumbnails = null; 3414 int NS = 0; 3415 int NF = 0; 3416 int NT = 0; 3417 IApplicationThread sendThumbnail = null; 3418 boolean booting = false; 3419 boolean enableScreen = false; 3420 boolean activityRemoved = false; 3421 3422 synchronized (mService) { 3423 ActivityRecord r = ActivityRecord.forToken(token); 3424 if (r != null) { 3425 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r); 3426 r.finishLaunchTickingLocked(); 3427 } 3428 3429 // Get the activity record. 3430 int index = indexOfActivityLocked(r); 3431 if (index >= 0) { 3432 res = r; 3433 3434 if (fromTimeout) { 3435 reportActivityLaunchedLocked(fromTimeout, r, -1, -1); 3436 } 3437 3438 // This is a hack to semi-deal with a race condition 3439 // in the client where it can be constructed with a 3440 // newer configuration from when we asked it to launch. 3441 // We'll update with whatever configuration it now says 3442 // it used to launch. 3443 if (config != null) { 3444 r.configuration = config; 3445 } 3446 3447 // No longer need to keep the device awake. 3448 if (mResumedActivity == r && mLaunchingActivity.isHeld()) { 3449 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG); 3450 mLaunchingActivity.release(); 3451 } 3452 3453 // We are now idle. If someone is waiting for a thumbnail from 3454 // us, we can now deliver. 3455 r.idle = true; 3456 mService.scheduleAppGcsLocked(); 3457 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) { 3458 sendThumbnail = r.app.thread; 3459 r.thumbnailNeeded = false; 3460 } 3461 3462 // If this activity is fullscreen, set up to hide those under it. 3463 3464 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r); 3465 ensureActivitiesVisibleLocked(null, 0); 3466 3467 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout); 3468 if (mMainStack) { 3469 if (!mService.mBooted) { 3470 mService.mBooted = true; 3471 enableScreen = true; 3472 } 3473 } 3474 3475 } else if (fromTimeout) { 3476 reportActivityLaunchedLocked(fromTimeout, null, -1, -1); 3477 } 3478 3479 // Atomically retrieve all of the other things to do. 3480 stops = processStoppingActivitiesLocked(true); 3481 NS = stops != null ? stops.size() : 0; 3482 if ((NF=mFinishingActivities.size()) > 0) { 3483 finishes = new ArrayList<ActivityRecord>(mFinishingActivities); 3484 mFinishingActivities.clear(); 3485 } 3486 if ((NT=mService.mCancelledThumbnails.size()) > 0) { 3487 thumbnails = new ArrayList<ActivityRecord>(mService.mCancelledThumbnails); 3488 mService.mCancelledThumbnails.clear(); 3489 } 3490 3491 if (mMainStack) { 3492 booting = mService.mBooting; 3493 mService.mBooting = false; 3494 } 3495 } 3496 3497 int i; 3498 3499 // Send thumbnail if requested. 3500 if (sendThumbnail != null) { 3501 try { 3502 sendThumbnail.requestThumbnail(token); 3503 } catch (Exception e) { 3504 Slog.w(TAG, "Exception thrown when requesting thumbnail", e); 3505 mService.sendPendingThumbnail(null, token, null, null, true); 3506 } 3507 } 3508 3509 // Stop any activities that are scheduled to do so but have been 3510 // waiting for the next one to start. 3511 for (i=0; i<NS; i++) { 3512 ActivityRecord r = (ActivityRecord)stops.get(i); 3513 synchronized (mService) { 3514 if (r.finishing) { 3515 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY); 3516 } else { 3517 stopActivityLocked(r); 3518 } 3519 } 3520 } 3521 3522 // Finish any activities that are scheduled to do so but have been 3523 // waiting for the next one to start. 3524 for (i=0; i<NF; i++) { 3525 ActivityRecord r = (ActivityRecord)finishes.get(i); 3526 synchronized (mService) { 3527 activityRemoved = destroyActivityLocked(r, true, false, "finish-idle"); 3528 } 3529 } 3530 3531 // Report back to any thumbnail receivers. 3532 for (i=0; i<NT; i++) { 3533 ActivityRecord r = (ActivityRecord)thumbnails.get(i); 3534 mService.sendPendingThumbnail(r, null, null, null, true); 3535 } 3536 3537 if (booting) { 3538 mService.finishBooting(); 3539 } 3540 3541 mService.trimApplications(); 3542 //dump(); 3543 //mWindowManager.dump(); 3544 3545 if (enableScreen) { 3546 mService.enableScreenAfterBoot(); 3547 } 3548 3549 if (activityRemoved) { 3550 resumeTopActivityLocked(null); 3551 } 3552 3553 return res; 3554 } 3555 3556 /** 3557 * @return Returns true if the activity is being finished, false if for 3558 * some reason it is being left as-is. 3559 */ 3560 final boolean requestFinishActivityLocked(IBinder token, int resultCode, 3561 Intent resultData, String reason) { 3562 int index = indexOfTokenLocked(token); 3563 if (DEBUG_RESULTS || DEBUG_STATES) Slog.v( 3564 TAG, "Finishing activity @" + index + ": token=" + token 3565 + ", result=" + resultCode + ", data=" + resultData 3566 + ", reason=" + reason); 3567 if (index < 0) { 3568 return false; 3569 } 3570 ActivityRecord r = mHistory.get(index); 3571 3572 finishActivityLocked(r, index, resultCode, resultData, reason); 3573 return true; 3574 } 3575 3576 final void finishSubActivityLocked(IBinder token, String resultWho, int requestCode) { 3577 ActivityRecord self = isInStackLocked(token); 3578 if (self == null) { 3579 return; 3580 } 3581 3582 int i; 3583 for (i=mHistory.size()-1; i>=0; i--) { 3584 ActivityRecord r = (ActivityRecord)mHistory.get(i); 3585 if (r.resultTo == self && r.requestCode == requestCode) { 3586 if ((r.resultWho == null && resultWho == null) || 3587 (r.resultWho != null && r.resultWho.equals(resultWho))) { 3588 finishActivityLocked(r, i, 3589 Activity.RESULT_CANCELED, null, "request-sub"); 3590 } 3591 } 3592 } 3593 } 3594 3595 final boolean finishActivityAffinityLocked(IBinder token) { 3596 int index = indexOfTokenLocked(token); 3597 if (DEBUG_RESULTS) Slog.v( 3598 TAG, "Finishing activity affinity @" + index + ": token=" + token); 3599 if (index < 0) { 3600 return false; 3601 } 3602 ActivityRecord r = mHistory.get(index); 3603 3604 while (index >= 0) { 3605 ActivityRecord cur = mHistory.get(index); 3606 if (cur.task != r.task) { 3607 break; 3608 } 3609 if (cur.taskAffinity == null && r.taskAffinity != null) { 3610 break; 3611 } 3612 if (cur.taskAffinity != null && !cur.taskAffinity.equals(r.taskAffinity)) { 3613 break; 3614 } 3615 finishActivityLocked(cur, index, Activity.RESULT_CANCELED, null, "request-affinity"); 3616 index--; 3617 } 3618 return true; 3619 } 3620 3621 final void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) { 3622 // send the result 3623 ActivityRecord resultTo = r.resultTo; 3624 if (resultTo != null) { 3625 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo 3626 + " who=" + r.resultWho + " req=" + r.requestCode 3627 + " res=" + resultCode + " data=" + resultData); 3628 if (r.info.applicationInfo.uid > 0) { 3629 mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid, 3630 resultTo.packageName, resultData, 3631 resultTo.getUriPermissionsLocked()); 3632 } 3633 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode, 3634 resultData); 3635 r.resultTo = null; 3636 } 3637 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r); 3638 3639 // Make sure this HistoryRecord is not holding on to other resources, 3640 // because clients have remote IPC references to this object so we 3641 // can't assume that will go away and want to avoid circular IPC refs. 3642 r.results = null; 3643 r.pendingResults = null; 3644 r.newIntents = null; 3645 r.icicle = null; 3646 } 3647 3648 /** 3649 * @return Returns true if this activity has been removed from the history 3650 * list, or false if it is still in the list and will be removed later. 3651 */ 3652 final boolean finishActivityLocked(ActivityRecord r, int index, 3653 int resultCode, Intent resultData, String reason) { 3654 return finishActivityLocked(r, index, resultCode, resultData, reason, false); 3655 } 3656 3657 /** 3658 * @return Returns true if this activity has been removed from the history 3659 * list, or false if it is still in the list and will be removed later. 3660 */ 3661 final boolean finishActivityLocked(ActivityRecord r, int index, 3662 int resultCode, Intent resultData, String reason, boolean immediate) { 3663 if (r.finishing) { 3664 Slog.w(TAG, "Duplicate finish request for " + r); 3665 return false; 3666 } 3667 3668 r.makeFinishing(); 3669 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY, 3670 System.identityHashCode(r), 3671 r.task.taskId, r.shortComponentName, reason); 3672 if (index < (mHistory.size()-1)) { 3673 ActivityRecord next = mHistory.get(index+1); 3674 if (next.task == r.task) { 3675 if (r.frontOfTask) { 3676 // The next activity is now the front of the task. 3677 next.frontOfTask = true; 3678 } 3679 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) { 3680 // If the caller asked that this activity (and all above it) 3681 // be cleared when the task is reset, don't lose that information, 3682 // but propagate it up to the next activity. 3683 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 3684 } 3685 } 3686 } 3687 3688 r.pauseKeyDispatchingLocked(); 3689 if (mMainStack) { 3690 if (mService.mFocusedActivity == r) { 3691 mService.setFocusedActivityLocked(topRunningActivityLocked(null)); 3692 } 3693 } 3694 3695 finishActivityResultsLocked(r, resultCode, resultData); 3696 3697 if (mService.mPendingThumbnails.size() > 0) { 3698 // There are clients waiting to receive thumbnails so, in case 3699 // this is an activity that someone is waiting for, add it 3700 // to the pending list so we can correctly update the clients. 3701 mService.mCancelledThumbnails.add(r); 3702 } 3703 3704 if (immediate) { 3705 return finishCurrentActivityLocked(r, index, 3706 FINISH_IMMEDIATELY) == null; 3707 } else if (mResumedActivity == r) { 3708 boolean endTask = index <= 0 3709 || (mHistory.get(index-1)).task != r.task; 3710 if (DEBUG_TRANSITION) Slog.v(TAG, 3711 "Prepare close transition: finishing " + r); 3712 mService.mWindowManager.prepareAppTransition(endTask 3713 ? WindowManagerPolicy.TRANSIT_TASK_CLOSE 3714 : WindowManagerPolicy.TRANSIT_ACTIVITY_CLOSE, false); 3715 3716 // Tell window manager to prepare for this one to be removed. 3717 mService.mWindowManager.setAppVisibility(r.appToken, false); 3718 3719 if (mPausingActivity == null) { 3720 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r); 3721 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false"); 3722 startPausingLocked(false, false); 3723 } 3724 3725 } else if (r.state != ActivityState.PAUSING) { 3726 // If the activity is PAUSING, we will complete the finish once 3727 // it is done pausing; else we can just directly finish it here. 3728 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r); 3729 return finishCurrentActivityLocked(r, index, 3730 FINISH_AFTER_PAUSE) == null; 3731 } else { 3732 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r); 3733 } 3734 3735 return false; 3736 } 3737 3738 private static final int FINISH_IMMEDIATELY = 0; 3739 private static final int FINISH_AFTER_PAUSE = 1; 3740 private static final int FINISH_AFTER_VISIBLE = 2; 3741 3742 private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, 3743 int mode) { 3744 final int index = indexOfActivityLocked(r); 3745 if (index < 0) { 3746 return null; 3747 } 3748 3749 return finishCurrentActivityLocked(r, index, mode); 3750 } 3751 3752 private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, 3753 int index, int mode) { 3754 // First things first: if this activity is currently visible, 3755 // and the resumed activity is not yet visible, then hold off on 3756 // finishing until the resumed one becomes visible. 3757 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) { 3758 if (!mStoppingActivities.contains(r)) { 3759 mStoppingActivities.add(r); 3760 if (mStoppingActivities.size() > 3) { 3761 // If we already have a few activities waiting to stop, 3762 // then give up on things going idle and start clearing 3763 // them out. 3764 scheduleIdleLocked(); 3765 } else { 3766 checkReadyForSleepLocked(); 3767 } 3768 } 3769 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r 3770 + " (finish requested)"); 3771 r.state = ActivityState.STOPPING; 3772 mService.updateOomAdjLocked(); 3773 return r; 3774 } 3775 3776 // make sure the record is cleaned out of other places. 3777 mStoppingActivities.remove(r); 3778 mGoingToSleepActivities.remove(r); 3779 mWaitingVisibleActivities.remove(r); 3780 if (mResumedActivity == r) { 3781 mResumedActivity = null; 3782 } 3783 final ActivityState prevState = r.state; 3784 if (DEBUG_STATES) Slog.v(TAG, "Moving to FINISHING: " + r); 3785 r.state = ActivityState.FINISHING; 3786 3787 if (mode == FINISH_IMMEDIATELY 3788 || prevState == ActivityState.STOPPED 3789 || prevState == ActivityState.INITIALIZING) { 3790 // If this activity is already stopped, we can just finish 3791 // it right now. 3792 boolean activityRemoved = destroyActivityLocked(r, true, true, "finish-imm"); 3793 if (activityRemoved) { 3794 resumeTopActivityLocked(null); 3795 } 3796 return activityRemoved ? null : r; 3797 } else { 3798 // Need to go through the full pause cycle to get this 3799 // activity into the stopped state and then finish it. 3800 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r); 3801 mFinishingActivities.add(r); 3802 resumeTopActivityLocked(null); 3803 } 3804 return r; 3805 } 3806 3807 /** 3808 * Perform the common clean-up of an activity record. This is called both 3809 * as part of destroyActivityLocked() (when destroying the client-side 3810 * representation) and cleaning things up as a result of its hosting 3811 * processing going away, in which case there is no remaining client-side 3812 * state to destroy so only the cleanup here is needed. 3813 */ 3814 final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices, 3815 boolean setState) { 3816 if (mResumedActivity == r) { 3817 mResumedActivity = null; 3818 } 3819 if (mService.mFocusedActivity == r) { 3820 mService.mFocusedActivity = null; 3821 } 3822 3823 r.configDestroy = false; 3824 r.frozenBeforeDestroy = false; 3825 3826 if (setState) { 3827 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (cleaning up)"); 3828 r.state = ActivityState.DESTROYED; 3829 } 3830 3831 // Make sure this record is no longer in the pending finishes list. 3832 // This could happen, for example, if we are trimming activities 3833 // down to the max limit while they are still waiting to finish. 3834 mFinishingActivities.remove(r); 3835 mWaitingVisibleActivities.remove(r); 3836 3837 // Remove any pending results. 3838 if (r.finishing && r.pendingResults != null) { 3839 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) { 3840 PendingIntentRecord rec = apr.get(); 3841 if (rec != null) { 3842 mService.cancelIntentSenderLocked(rec, false); 3843 } 3844 } 3845 r.pendingResults = null; 3846 } 3847 3848 if (cleanServices) { 3849 cleanUpActivityServicesLocked(r); 3850 } 3851 3852 if (mService.mPendingThumbnails.size() > 0) { 3853 // There are clients waiting to receive thumbnails so, in case 3854 // this is an activity that someone is waiting for, add it 3855 // to the pending list so we can correctly update the clients. 3856 mService.mCancelledThumbnails.add(r); 3857 } 3858 3859 // Get rid of any pending idle timeouts. 3860 removeTimeoutsForActivityLocked(r); 3861 } 3862 3863 private void removeTimeoutsForActivityLocked(ActivityRecord r) { 3864 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); 3865 mHandler.removeMessages(STOP_TIMEOUT_MSG, r); 3866 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r); 3867 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r); 3868 r.finishLaunchTickingLocked(); 3869 } 3870 3871 final void removeActivityFromHistoryLocked(ActivityRecord r) { 3872 if (r.state != ActivityState.DESTROYED) { 3873 finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null); 3874 r.makeFinishing(); 3875 if (DEBUG_ADD_REMOVE) { 3876 RuntimeException here = new RuntimeException("here"); 3877 here.fillInStackTrace(); 3878 Slog.i(TAG, "Removing activity " + r + " from stack"); 3879 } 3880 mHistory.remove(r); 3881 r.takeFromHistory(); 3882 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r 3883 + " (removed from history)"); 3884 r.state = ActivityState.DESTROYED; 3885 mService.mWindowManager.removeAppToken(r.appToken); 3886 if (VALIDATE_TOKENS) { 3887 validateAppTokensLocked(); 3888 } 3889 cleanUpActivityServicesLocked(r); 3890 r.removeUriPermissionsLocked(); 3891 } 3892 } 3893 3894 /** 3895 * Perform clean-up of service connections in an activity record. 3896 */ 3897 final void cleanUpActivityServicesLocked(ActivityRecord r) { 3898 // Throw away any services that have been bound by this activity. 3899 if (r.connections != null) { 3900 Iterator<ConnectionRecord> it = r.connections.iterator(); 3901 while (it.hasNext()) { 3902 ConnectionRecord c = it.next(); 3903 mService.removeConnectionLocked(c, null, r); 3904 } 3905 r.connections = null; 3906 } 3907 } 3908 3909 final void scheduleDestroyActivities(ProcessRecord owner, boolean oomAdj, String reason) { 3910 Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG); 3911 msg.obj = new ScheduleDestroyArgs(owner, oomAdj, reason); 3912 mHandler.sendMessage(msg); 3913 } 3914 3915 final void destroyActivitiesLocked(ProcessRecord owner, boolean oomAdj, String reason) { 3916 boolean lastIsOpaque = false; 3917 boolean activityRemoved = false; 3918 for (int i=mHistory.size()-1; i>=0; i--) { 3919 ActivityRecord r = mHistory.get(i); 3920 if (r.finishing) { 3921 continue; 3922 } 3923 if (r.fullscreen) { 3924 lastIsOpaque = true; 3925 } 3926 if (owner != null && r.app != owner) { 3927 continue; 3928 } 3929 if (!lastIsOpaque) { 3930 continue; 3931 } 3932 // We can destroy this one if we have its icicle saved and 3933 // it is not in the process of pausing/stopping/finishing. 3934 if (r.app != null && r != mResumedActivity && r != mPausingActivity 3935 && r.haveState && !r.visible && r.stopped 3936 && r.state != ActivityState.DESTROYING 3937 && r.state != ActivityState.DESTROYED) { 3938 if (DEBUG_SWITCH) Slog.v(TAG, "Destroying " + r + " in state " + r.state 3939 + " resumed=" + mResumedActivity 3940 + " pausing=" + mPausingActivity); 3941 if (destroyActivityLocked(r, true, oomAdj, reason)) { 3942 activityRemoved = true; 3943 } 3944 } 3945 } 3946 if (activityRemoved) { 3947 resumeTopActivityLocked(null); 3948 } 3949 } 3950 3951 /** 3952 * Destroy the current CLIENT SIDE instance of an activity. This may be 3953 * called both when actually finishing an activity, or when performing 3954 * a configuration switch where we destroy the current client-side object 3955 * but then create a new client-side object for this same HistoryRecord. 3956 */ 3957 final boolean destroyActivityLocked(ActivityRecord r, 3958 boolean removeFromApp, boolean oomAdj, String reason) { 3959 if (DEBUG_SWITCH) Slog.v( 3960 TAG, "Removing activity from " + reason + ": token=" + r 3961 + ", app=" + (r.app != null ? r.app.processName : "(null)")); 3962 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY, 3963 System.identityHashCode(r), 3964 r.task.taskId, r.shortComponentName, reason); 3965 3966 boolean removedFromHistory = false; 3967 3968 cleanUpActivityLocked(r, false, false); 3969 3970 final boolean hadApp = r.app != null; 3971 3972 if (hadApp) { 3973 if (removeFromApp) { 3974 int idx = r.app.activities.indexOf(r); 3975 if (idx >= 0) { 3976 r.app.activities.remove(idx); 3977 } 3978 if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) { 3979 mService.mHeavyWeightProcess = null; 3980 mService.mHandler.sendEmptyMessage( 3981 ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG); 3982 } 3983 if (r.app.activities.size() == 0) { 3984 // No longer have activities, so update location in 3985 // LRU list. 3986 mService.updateLruProcessLocked(r.app, oomAdj, false); 3987 } 3988 } 3989 3990 boolean skipDestroy = false; 3991 3992 try { 3993 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r); 3994 r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing, 3995 r.configChangeFlags); 3996 } catch (Exception e) { 3997 // We can just ignore exceptions here... if the process 3998 // has crashed, our death notification will clean things 3999 // up. 4000 //Slog.w(TAG, "Exception thrown during finish", e); 4001 if (r.finishing) { 4002 removeActivityFromHistoryLocked(r); 4003 removedFromHistory = true; 4004 skipDestroy = true; 4005 } 4006 } 4007 4008 r.app = null; 4009 r.nowVisible = false; 4010 4011 // If the activity is finishing, we need to wait on removing it 4012 // from the list to give it a chance to do its cleanup. During 4013 // that time it may make calls back with its token so we need to 4014 // be able to find it on the list and so we don't want to remove 4015 // it from the list yet. Otherwise, we can just immediately put 4016 // it in the destroyed state since we are not removing it from the 4017 // list. 4018 if (r.finishing && !skipDestroy) { 4019 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYING: " + r 4020 + " (destroy requested)"); 4021 r.state = ActivityState.DESTROYING; 4022 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG); 4023 msg.obj = r; 4024 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT); 4025 } else { 4026 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r 4027 + " (destroy skipped)"); 4028 r.state = ActivityState.DESTROYED; 4029 } 4030 } else { 4031 // remove this record from the history. 4032 if (r.finishing) { 4033 removeActivityFromHistoryLocked(r); 4034 removedFromHistory = true; 4035 } else { 4036 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r 4037 + " (no app)"); 4038 r.state = ActivityState.DESTROYED; 4039 } 4040 } 4041 4042 r.configChangeFlags = 0; 4043 4044 if (!mLRUActivities.remove(r) && hadApp) { 4045 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list"); 4046 } 4047 4048 return removedFromHistory; 4049 } 4050 4051 final void activityDestroyed(IBinder token) { 4052 synchronized (mService) { 4053 final long origId = Binder.clearCallingIdentity(); 4054 try { 4055 ActivityRecord r = ActivityRecord.forToken(token); 4056 if (r != null) { 4057 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r); 4058 } 4059 4060 int index = indexOfActivityLocked(r); 4061 if (index >= 0) { 4062 if (r.state == ActivityState.DESTROYING) { 4063 cleanUpActivityLocked(r, true, false); 4064 removeActivityFromHistoryLocked(r); 4065 } 4066 } 4067 resumeTopActivityLocked(null); 4068 } finally { 4069 Binder.restoreCallingIdentity(origId); 4070 } 4071 } 4072 } 4073 4074 private void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app) { 4075 int i = list.size(); 4076 if (localLOGV) Slog.v( 4077 TAG, "Removing app " + app + " from list " + list 4078 + " with " + i + " entries"); 4079 while (i > 0) { 4080 i--; 4081 ActivityRecord r = (ActivityRecord)list.get(i); 4082 if (localLOGV) Slog.v( 4083 TAG, "Record #" + i + " " + r + ": app=" + r.app); 4084 if (r.app == app) { 4085 if (localLOGV) Slog.v(TAG, "Removing this entry!"); 4086 list.remove(i); 4087 removeTimeoutsForActivityLocked(r); 4088 } 4089 } 4090 } 4091 4092 void removeHistoryRecordsForAppLocked(ProcessRecord app) { 4093 removeHistoryRecordsForAppLocked(mLRUActivities, app); 4094 removeHistoryRecordsForAppLocked(mStoppingActivities, app); 4095 removeHistoryRecordsForAppLocked(mGoingToSleepActivities, app); 4096 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app); 4097 removeHistoryRecordsForAppLocked(mFinishingActivities, app); 4098 } 4099 4100 /** 4101 * Move the current home activity's task (if one exists) to the front 4102 * of the stack. 4103 */ 4104 final void moveHomeToFrontLocked() { 4105 TaskRecord homeTask = null; 4106 for (int i=mHistory.size()-1; i>=0; i--) { 4107 ActivityRecord hr = mHistory.get(i); 4108 if (hr.isHomeActivity) { 4109 homeTask = hr.task; 4110 break; 4111 } 4112 } 4113 if (homeTask != null) { 4114 moveTaskToFrontLocked(homeTask, null, null); 4115 } 4116 } 4117 4118 final void updateTransitLocked(int transit, Bundle options) { 4119 if (options != null) { 4120 ActivityRecord r = topRunningActivityLocked(null); 4121 if (r != null && r.state != ActivityState.RESUMED) { 4122 r.updateOptionsLocked(options); 4123 } else { 4124 ActivityOptions.abort(options); 4125 } 4126 } 4127 mService.mWindowManager.prepareAppTransition(transit, false); 4128 } 4129 4130 final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) { 4131 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr); 4132 4133 final int task = tr.taskId; 4134 int top = mHistory.size()-1; 4135 4136 if (top < 0 || (mHistory.get(top)).task.taskId == task) { 4137 // nothing to do! 4138 if (reason != null && 4139 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) { 4140 ActivityOptions.abort(options); 4141 } else { 4142 updateTransitLocked(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT, options); 4143 } 4144 return; 4145 } 4146 4147 ArrayList<IBinder> moved = new ArrayList<IBinder>(); 4148 4149 // Applying the affinities may have removed entries from the history, 4150 // so get the size again. 4151 top = mHistory.size()-1; 4152 int pos = top; 4153 4154 // Shift all activities with this task up to the top 4155 // of the stack, keeping them in the same internal order. 4156 while (pos >= 0) { 4157 ActivityRecord r = mHistory.get(pos); 4158 if (localLOGV) Slog.v( 4159 TAG, "At " + pos + " ckp " + r.task + ": " + r); 4160 if (r.task.taskId == task) { 4161 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top); 4162 if (DEBUG_ADD_REMOVE) { 4163 RuntimeException here = new RuntimeException("here"); 4164 here.fillInStackTrace(); 4165 Slog.i(TAG, "Removing and adding activity " + r + " to stack at " + top, here); 4166 } 4167 mHistory.remove(pos); 4168 mHistory.add(top, r); 4169 moved.add(0, r.appToken); 4170 top--; 4171 } 4172 pos--; 4173 } 4174 4175 if (DEBUG_TRANSITION) Slog.v(TAG, 4176 "Prepare to front transition: task=" + tr); 4177 if (reason != null && 4178 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) { 4179 mService.mWindowManager.prepareAppTransition( 4180 WindowManagerPolicy.TRANSIT_NONE, false); 4181 ActivityRecord r = topRunningActivityLocked(null); 4182 if (r != null) { 4183 mNoAnimActivities.add(r); 4184 } 4185 ActivityOptions.abort(options); 4186 } else { 4187 updateTransitLocked(WindowManagerPolicy.TRANSIT_TASK_TO_FRONT, options); 4188 } 4189 4190 mService.mWindowManager.moveAppTokensToTop(moved); 4191 if (VALIDATE_TOKENS) { 4192 validateAppTokensLocked(); 4193 } 4194 4195 finishTaskMoveLocked(task); 4196 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, task); 4197 } 4198 4199 private final void finishTaskMoveLocked(int task) { 4200 resumeTopActivityLocked(null); 4201 } 4202 4203 /** 4204 * Worker method for rearranging history stack. Implements the function of moving all 4205 * activities for a specific task (gathering them if disjoint) into a single group at the 4206 * bottom of the stack. 4207 * 4208 * If a watcher is installed, the action is preflighted and the watcher has an opportunity 4209 * to premeptively cancel the move. 4210 * 4211 * @param task The taskId to collect and move to the bottom. 4212 * @return Returns true if the move completed, false if not. 4213 */ 4214 final boolean moveTaskToBackLocked(int task, ActivityRecord reason) { 4215 Slog.i(TAG, "moveTaskToBack: " + task); 4216 4217 // If we have a watcher, preflight the move before committing to it. First check 4218 // for *other* available tasks, but if none are available, then try again allowing the 4219 // current task to be selected. 4220 if (mMainStack && mService.mController != null) { 4221 ActivityRecord next = topRunningActivityLocked(null, task); 4222 if (next == null) { 4223 next = topRunningActivityLocked(null, 0); 4224 } 4225 if (next != null) { 4226 // ask watcher if this is allowed 4227 boolean moveOK = true; 4228 try { 4229 moveOK = mService.mController.activityResuming(next.packageName); 4230 } catch (RemoteException e) { 4231 mService.mController = null; 4232 } 4233 if (!moveOK) { 4234 return false; 4235 } 4236 } 4237 } 4238 4239 ArrayList<IBinder> moved = new ArrayList<IBinder>(); 4240 4241 if (DEBUG_TRANSITION) Slog.v(TAG, 4242 "Prepare to back transition: task=" + task); 4243 4244 final int N = mHistory.size(); 4245 int bottom = 0; 4246 int pos = 0; 4247 4248 // Shift all activities with this task down to the bottom 4249 // of the stack, keeping them in the same internal order. 4250 while (pos < N) { 4251 ActivityRecord r = mHistory.get(pos); 4252 if (localLOGV) Slog.v( 4253 TAG, "At " + pos + " ckp " + r.task + ": " + r); 4254 if (r.task.taskId == task) { 4255 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1)); 4256 if (DEBUG_ADD_REMOVE) { 4257 RuntimeException here = new RuntimeException("here"); 4258 here.fillInStackTrace(); 4259 Slog.i(TAG, "Removing and adding activity " + r + " to stack at " 4260 + bottom, here); 4261 } 4262 mHistory.remove(pos); 4263 mHistory.add(bottom, r); 4264 moved.add(r.appToken); 4265 bottom++; 4266 } 4267 pos++; 4268 } 4269 4270 if (reason != null && 4271 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) { 4272 mService.mWindowManager.prepareAppTransition( 4273 WindowManagerPolicy.TRANSIT_NONE, false); 4274 ActivityRecord r = topRunningActivityLocked(null); 4275 if (r != null) { 4276 mNoAnimActivities.add(r); 4277 } 4278 } else { 4279 mService.mWindowManager.prepareAppTransition( 4280 WindowManagerPolicy.TRANSIT_TASK_TO_BACK, false); 4281 } 4282 mService.mWindowManager.moveAppTokensToBottom(moved); 4283 if (VALIDATE_TOKENS) { 4284 validateAppTokensLocked(); 4285 } 4286 4287 finishTaskMoveLocked(task); 4288 return true; 4289 } 4290 4291 public ActivityManager.TaskThumbnails getTaskThumbnailsLocked(TaskRecord tr) { 4292 TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true); 4293 ActivityRecord resumed = mResumedActivity; 4294 if (resumed != null && resumed.thumbHolder == tr) { 4295 info.mainThumbnail = resumed.stack.screenshotActivities(resumed); 4296 } else { 4297 info.mainThumbnail = tr.lastThumbnail; 4298 } 4299 return info; 4300 } 4301 4302 public ActivityRecord removeTaskActivitiesLocked(int taskId, int subTaskIndex, 4303 boolean taskRequired) { 4304 TaskAccessInfo info = getTaskAccessInfoLocked(taskId, false); 4305 if (info.root == null) { 4306 if (taskRequired) { 4307 Slog.w(TAG, "removeTaskLocked: unknown taskId " + taskId); 4308 } 4309 return null; 4310 } 4311 4312 if (subTaskIndex < 0) { 4313 // Just remove the entire task. 4314 performClearTaskAtIndexLocked(taskId, info.rootIndex); 4315 return info.root; 4316 } 4317 4318 if (subTaskIndex >= info.subtasks.size()) { 4319 if (taskRequired) { 4320 Slog.w(TAG, "removeTaskLocked: unknown subTaskIndex " + subTaskIndex); 4321 } 4322 return null; 4323 } 4324 4325 // Remove all of this task's activies starting at the sub task. 4326 TaskAccessInfo.SubTask subtask = info.subtasks.get(subTaskIndex); 4327 performClearTaskAtIndexLocked(taskId, subtask.index); 4328 return subtask.activity; 4329 } 4330 4331 public TaskAccessInfo getTaskAccessInfoLocked(int taskId, boolean inclThumbs) { 4332 ActivityRecord resumed = mResumedActivity; 4333 final TaskAccessInfo thumbs = new TaskAccessInfo(); 4334 // How many different sub-thumbnails? 4335 final int NA = mHistory.size(); 4336 int j = 0; 4337 ThumbnailHolder holder = null; 4338 while (j < NA) { 4339 ActivityRecord ar = mHistory.get(j); 4340 if (!ar.finishing && ar.task.taskId == taskId) { 4341 holder = ar.thumbHolder; 4342 break; 4343 } 4344 j++; 4345 } 4346 4347 if (j >= NA) { 4348 return thumbs; 4349 } 4350 4351 thumbs.root = mHistory.get(j); 4352 thumbs.rootIndex = j; 4353 4354 ArrayList<TaskAccessInfo.SubTask> subtasks = new ArrayList<TaskAccessInfo.SubTask>(); 4355 thumbs.subtasks = subtasks; 4356 ActivityRecord lastActivity = null; 4357 while (j < NA) { 4358 ActivityRecord ar = mHistory.get(j); 4359 j++; 4360 if (ar.finishing) { 4361 continue; 4362 } 4363 if (ar.task.taskId != taskId) { 4364 break; 4365 } 4366 lastActivity = ar; 4367 if (ar.thumbHolder != holder && holder != null) { 4368 thumbs.numSubThumbbails++; 4369 holder = ar.thumbHolder; 4370 TaskAccessInfo.SubTask sub = new TaskAccessInfo.SubTask(); 4371 sub.thumbnail = holder.lastThumbnail; 4372 sub.activity = ar; 4373 sub.index = j-1; 4374 subtasks.add(sub); 4375 } 4376 } 4377 if (lastActivity != null && subtasks.size() > 0) { 4378 if (resumed == lastActivity) { 4379 TaskAccessInfo.SubTask sub = subtasks.get(subtasks.size()-1); 4380 sub.thumbnail = lastActivity.stack.screenshotActivities(lastActivity); 4381 } 4382 } 4383 if (thumbs.numSubThumbbails > 0) { 4384 thumbs.retriever = new IThumbnailRetriever.Stub() { 4385 public Bitmap getThumbnail(int index) { 4386 if (index < 0 || index >= thumbs.subtasks.size()) { 4387 return null; 4388 } 4389 return thumbs.subtasks.get(index).thumbnail; 4390 } 4391 }; 4392 } 4393 return thumbs; 4394 } 4395 4396 private final void logStartActivity(int tag, ActivityRecord r, 4397 TaskRecord task) { 4398 EventLog.writeEvent(tag, 4399 System.identityHashCode(r), task.taskId, 4400 r.shortComponentName, r.intent.getAction(), 4401 r.intent.getType(), r.intent.getDataString(), 4402 r.intent.getFlags()); 4403 } 4404 4405 /** 4406 * Make sure the given activity matches the current configuration. Returns 4407 * false if the activity had to be destroyed. Returns true if the 4408 * configuration is the same, or the activity will remain running as-is 4409 * for whatever reason. Ensures the HistoryRecord is updated with the 4410 * correct configuration and all other bookkeeping is handled. 4411 */ 4412 final boolean ensureActivityConfigurationLocked(ActivityRecord r, 4413 int globalChanges) { 4414 if (mConfigWillChange) { 4415 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4416 "Skipping config check (will change): " + r); 4417 return true; 4418 } 4419 4420 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4421 "Ensuring correct configuration: " + r); 4422 4423 // Short circuit: if the two configurations are the exact same 4424 // object (the common case), then there is nothing to do. 4425 Configuration newConfig = mService.mConfiguration; 4426 if (r.configuration == newConfig && !r.forceNewConfig) { 4427 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4428 "Configuration unchanged in " + r); 4429 return true; 4430 } 4431 4432 // We don't worry about activities that are finishing. 4433 if (r.finishing) { 4434 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4435 "Configuration doesn't matter in finishing " + r); 4436 r.stopFreezingScreenLocked(false); 4437 return true; 4438 } 4439 4440 // Okay we now are going to make this activity have the new config. 4441 // But then we need to figure out how it needs to deal with that. 4442 Configuration oldConfig = r.configuration; 4443 r.configuration = newConfig; 4444 4445 // Determine what has changed. May be nothing, if this is a config 4446 // that has come back from the app after going idle. In that case 4447 // we just want to leave the official config object now in the 4448 // activity and do nothing else. 4449 final int changes = oldConfig.diff(newConfig); 4450 if (changes == 0 && !r.forceNewConfig) { 4451 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4452 "Configuration no differences in " + r); 4453 return true; 4454 } 4455 4456 // If the activity isn't currently running, just leave the new 4457 // configuration and it will pick that up next time it starts. 4458 if (r.app == null || r.app.thread == null) { 4459 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4460 "Configuration doesn't matter not running " + r); 4461 r.stopFreezingScreenLocked(false); 4462 r.forceNewConfig = false; 4463 return true; 4464 } 4465 4466 // Figure out how to handle the changes between the configurations. 4467 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) { 4468 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x" 4469 + Integer.toHexString(changes) + ", handles=0x" 4470 + Integer.toHexString(r.info.getRealConfigChanged()) 4471 + ", newConfig=" + newConfig); 4472 } 4473 if ((changes&(~r.info.getRealConfigChanged())) != 0 || r.forceNewConfig) { 4474 // Aha, the activity isn't handling the change, so DIE DIE DIE. 4475 r.configChangeFlags |= changes; 4476 r.startFreezingScreenLocked(r.app, globalChanges); 4477 r.forceNewConfig = false; 4478 if (r.app == null || r.app.thread == null) { 4479 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4480 "Config is destroying non-running " + r); 4481 destroyActivityLocked(r, true, false, "config"); 4482 } else if (r.state == ActivityState.PAUSING) { 4483 // A little annoying: we are waiting for this activity to 4484 // finish pausing. Let's not do anything now, but just 4485 // flag that it needs to be restarted when done pausing. 4486 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4487 "Config is skipping already pausing " + r); 4488 r.configDestroy = true; 4489 return true; 4490 } else if (r.state == ActivityState.RESUMED) { 4491 // Try to optimize this case: the configuration is changing 4492 // and we need to restart the top, resumed activity. 4493 // Instead of doing the normal handshaking, just say 4494 // "restart!". 4495 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4496 "Config is relaunching resumed " + r); 4497 relaunchActivityLocked(r, r.configChangeFlags, true); 4498 r.configChangeFlags = 0; 4499 } else { 4500 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG, 4501 "Config is relaunching non-resumed " + r); 4502 relaunchActivityLocked(r, r.configChangeFlags, false); 4503 r.configChangeFlags = 0; 4504 } 4505 4506 // All done... tell the caller we weren't able to keep this 4507 // activity around. 4508 return false; 4509 } 4510 4511 // Default case: the activity can handle this new configuration, so 4512 // hand it over. Note that we don't need to give it the new 4513 // configuration, since we always send configuration changes to all 4514 // process when they happen so it can just use whatever configuration 4515 // it last got. 4516 if (r.app != null && r.app.thread != null) { 4517 try { 4518 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r); 4519 r.app.thread.scheduleActivityConfigurationChanged(r.appToken); 4520 } catch (RemoteException e) { 4521 // If process died, whatever. 4522 } 4523 } 4524 r.stopFreezingScreenLocked(false); 4525 4526 return true; 4527 } 4528 4529 private final boolean relaunchActivityLocked(ActivityRecord r, 4530 int changes, boolean andResume) { 4531 List<ResultInfo> results = null; 4532 List<Intent> newIntents = null; 4533 if (andResume) { 4534 results = r.results; 4535 newIntents = r.newIntents; 4536 } 4537 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r 4538 + " with results=" + results + " newIntents=" + newIntents 4539 + " andResume=" + andResume); 4540 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY 4541 : EventLogTags.AM_RELAUNCH_ACTIVITY, System.identityHashCode(r), 4542 r.task.taskId, r.shortComponentName); 4543 4544 r.startFreezingScreenLocked(r.app, 0); 4545 4546 try { 4547 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, 4548 (andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ") 4549 + r); 4550 r.forceNewConfig = false; 4551 r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents, 4552 changes, !andResume, new Configuration(mService.mConfiguration)); 4553 // Note: don't need to call pauseIfSleepingLocked() here, because 4554 // the caller will only pass in 'andResume' if this activity is 4555 // currently resumed, which implies we aren't sleeping. 4556 } catch (RemoteException e) { 4557 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, "Relaunch failed", e); 4558 } 4559 4560 if (andResume) { 4561 r.results = null; 4562 r.newIntents = null; 4563 if (mMainStack) { 4564 mService.reportResumedActivityLocked(r); 4565 } 4566 r.state = ActivityState.RESUMED; 4567 } else { 4568 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r); 4569 r.state = ActivityState.PAUSED; 4570 } 4571 4572 return true; 4573 } 4574 4575 public void dismissKeyguardOnNextActivityLocked() { 4576 mDismissKeyguardOnNextActivity = true; 4577 } 4578} 4579