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