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