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