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