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