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