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