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