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