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