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