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