2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.server.am;
19 import static android.Manifest.permission.START_ANY_ACTIVITY;
20 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
22 import com.android.internal.app.HeavyWeightSwitcherActivity;
23 import com.android.internal.os.BatteryStatsImpl;
24 import com.android.server.am.ActivityManagerService.ItemMatcher;
25 import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
26 import com.android.server.wm.AppTransition;
28 import android.app.Activity;
29 import android.app.ActivityManager;
30 import android.app.ActivityOptions;
31 import android.app.AppGlobals;
32 import android.app.IActivityManager;
33 import android.app.IThumbnailReceiver;
34 import android.app.IThumbnailRetriever;
35 import android.app.IApplicationThread;
36 import android.app.PendingIntent;
37 import android.app.ResultInfo;
38 import android.app.ActivityManager.RunningTaskInfo;
39 import android.app.IActivityManager.WaitResult;
40 import android.content.ComponentName;
41 import android.content.Context;
42 import android.content.IIntentSender;
43 import android.content.Intent;
44 import android.content.IntentSender;
45 import android.content.pm.ActivityInfo;
46 import android.content.pm.ApplicationInfo;
47 import android.content.pm.PackageManager;
48 import android.content.pm.ResolveInfo;
49 import android.content.res.Configuration;
50 import android.content.res.Resources;
51 import android.graphics.Bitmap;
52 import android.graphics.Bitmap.Config;
53 import android.os.Binder;
54 import android.os.Bundle;
55 import android.os.Handler;
56 import android.os.IBinder;
57 import android.os.Looper;
58 import android.os.Message;
59 import android.os.ParcelFileDescriptor;
60 import android.os.PowerManager;
61 import android.os.RemoteException;
62 import android.os.SystemClock;
63 import android.os.UserHandle;
64 import android.util.EventLog;
65 import android.util.Log;
66 import android.util.Slog;
67 import android.view.Display;
69 import java.io.FileDescriptor;
70 import java.io.IOException;
71 import java.io.PrintWriter;
72 import java.lang.ref.WeakReference;
73 import java.util.ArrayList;
74 import java.util.Iterator;
75 import java.util.List;
78 * State and management of a single stack of activities.
80 final class ActivityStack {
81 static final String TAG = ActivityManagerService.TAG;
82 static final boolean localLOGV = ActivityManagerService.localLOGV;
83 static final boolean DEBUG_SWITCH = ActivityManagerService.DEBUG_SWITCH;
84 static final boolean DEBUG_PAUSE = ActivityManagerService.DEBUG_PAUSE;
85 static final boolean DEBUG_VISBILITY = ActivityManagerService.DEBUG_VISBILITY;
86 static final boolean DEBUG_USER_LEAVING = ActivityManagerService.DEBUG_USER_LEAVING;
87 static final boolean DEBUG_TRANSITION = ActivityManagerService.DEBUG_TRANSITION;
88 static final boolean DEBUG_RESULTS = ActivityManagerService.DEBUG_RESULTS;
89 static final boolean DEBUG_CONFIGURATION = ActivityManagerService.DEBUG_CONFIGURATION;
90 static final boolean DEBUG_TASKS = ActivityManagerService.DEBUG_TASKS;
91 static final boolean DEBUG_CLEANUP = ActivityManagerService.DEBUG_CLEANUP;
93 static final boolean DEBUG_STATES = false;
94 static final boolean DEBUG_ADD_REMOVE = false;
95 static final boolean DEBUG_SAVED_STATE = false;
96 static final boolean DEBUG_APP = false;
98 static final boolean VALIDATE_TOKENS = ActivityManagerService.VALIDATE_TOKENS;
100 // How long we wait until giving up on the last activity telling us it
102 static final int IDLE_TIMEOUT = 10*1000;
104 // Ticks during which we check progress while waiting for an app to launch.
105 static final int LAUNCH_TICK = 500;
107 // How long we wait until giving up on the last activity to pause. This
108 // is short because it directly impacts the responsiveness of starting the
110 static final int PAUSE_TIMEOUT = 500;
112 // How long we wait for the activity to tell us it has stopped before
113 // giving up. This is a good amount of time because we really need this
114 // from the application in order to get its saved state.
115 static final int STOP_TIMEOUT = 10*1000;
117 // How long we can hold the sleep wake lock before giving up.
118 static final int SLEEP_TIMEOUT = 5*1000;
120 // How long we can hold the launch wake lock before giving up.
121 static final int LAUNCH_TIMEOUT = 10*1000;
123 // How long we wait until giving up on an activity telling us it has
124 // finished destroying itself.
125 static final int DESTROY_TIMEOUT = 10*1000;
127 // How long until we reset a task when the user returns to it. Currently
129 static final long ACTIVITY_INACTIVE_RESET_TIME = 0;
131 // How long between activity launches that we consider safe to not warn
132 // the user about an unexpected activity being launched on top.
133 static final long START_WARN_TIME = 5*1000;
135 // Set to false to disable the preview that is shown while a new activity
137 static final boolean SHOW_APP_STARTING_PREVIEW = true;
151 final ActivityManagerService mService;
152 final boolean mMainStack;
154 final Context mContext;
157 * The back history of all previous (and possibly still
158 * running) activities. It contains #ActivityRecord objects.
160 private final ArrayList<ActivityRecord> mHistory = new ArrayList<ActivityRecord>();
163 * Used for validating app tokens with window manager.
165 final ArrayList<TaskGroup> mValidateAppTokens = new ArrayList<TaskGroup>();
168 * List of running activities, sorted by recent usage.
169 * The first entry in the list is the least recently used.
170 * It contains HistoryRecord objects.
172 final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<ActivityRecord>();
175 * List of activities that are waiting for a new activity
176 * to become visible before completing whatever operation they are
179 final ArrayList<ActivityRecord> mWaitingVisibleActivities
180 = new ArrayList<ActivityRecord>();
183 * List of activities that are ready to be stopped, but waiting
184 * for the next activity to settle down before doing so. It contains
185 * HistoryRecord objects.
187 final ArrayList<ActivityRecord> mStoppingActivities
188 = new ArrayList<ActivityRecord>();
191 * List of activities that are in the process of going to sleep.
193 final ArrayList<ActivityRecord> mGoingToSleepActivities
194 = new ArrayList<ActivityRecord>();
197 * Animations that for the current transition have requested not to
198 * be considered for the transition animation.
200 final ArrayList<ActivityRecord> mNoAnimActivities
201 = new ArrayList<ActivityRecord>();
204 * List of activities that are ready to be finished, but waiting
205 * for the previous activity to settle down before doing so. It contains
206 * HistoryRecord objects.
208 final ArrayList<ActivityRecord> mFinishingActivities
209 = new ArrayList<ActivityRecord>();
212 * List of people waiting to find out about the next launched activity.
214 final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
215 = new ArrayList<IActivityManager.WaitResult>();
218 * List of people waiting to find out about the next visible activity.
220 final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
221 = new ArrayList<IActivityManager.WaitResult>();
223 final ArrayList<UserStartedState> mStartingUsers
224 = new ArrayList<UserStartedState>();
227 * Set when the system is going to sleep, until we have
228 * successfully paused the current activity and released our wake lock.
229 * At that point the system is allowed to actually sleep.
231 final PowerManager.WakeLock mGoingToSleep;
234 * We don't want to allow the device to go to sleep while in the process
235 * of launching an activity. This is primarily to allow alarm intent
236 * receivers to launch an activity and get that to run before the device
237 * goes back to sleep.
239 final PowerManager.WakeLock mLaunchingActivity;
242 * When we are in the process of pausing an activity, before starting the
243 * next one, this variable holds the activity that is currently being paused.
245 ActivityRecord mPausingActivity = null;
248 * This is the last activity that we put into the paused state. This is
249 * used to determine if we need to do an activity transition while sleeping,
250 * when we normally hold the top activity paused.
252 ActivityRecord mLastPausedActivity = null;
255 * Current activity that is resumed, or null if there is none.
257 ActivityRecord mResumedActivity = null;
260 * This is the last activity that has been started. It is only used to
261 * identify when multiple activities are started at once so that the user
262 * can be warned they may not be in the activity they think they are.
264 ActivityRecord mLastStartedActivity = null;
267 * Set when we know we are going to be calling updateConfiguration()
268 * soon, so want to skip intermediate config checks.
270 boolean mConfigWillChange;
273 * Set to indicate whether to issue an onUserLeaving callback when a
274 * newly launched activity is being brought in front of us.
276 boolean mUserLeaving = false;
278 long mInitialStartTime = 0;
281 * Set when we have taken too long waiting to go to sleep.
283 boolean mSleepTimeout = false;
286 * Dismiss the keyguard after the next activity is displayed?
288 boolean mDismissKeyguardOnNextActivity = false;
291 * Save the most recent screenshot for reuse. This keeps Recents from taking two identical
292 * screenshots, one for the Recents thumbnail and one for the pauseActivity thumbnail.
294 private ActivityRecord mLastScreenshotActivity = null;
295 private Bitmap mLastScreenshotBitmap = null;
298 * List of ActivityRecord objects that have been finished and must
299 * still report back to a pending thumbnail receiver.
301 private final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
303 int mThumbnailWidth = -1;
304 int mThumbnailHeight = -1;
306 private int mCurrentUser;
308 static final int SLEEP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG;
309 static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
310 static final int IDLE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
311 static final int IDLE_NOW_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
312 static final int LAUNCH_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4;
313 static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5;
314 static final int RESUME_TOP_ACTIVITY_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6;
315 static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 7;
316 static final int STOP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 8;
317 static final int DESTROY_ACTIVITIES_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 9;
319 static class ScheduleDestroyArgs {
320 final ProcessRecord mOwner;
321 final boolean mOomAdj;
322 final String mReason;
323 ScheduleDestroyArgs(ProcessRecord owner, boolean oomAdj, String reason) {
330 final Handler mHandler;
332 final class ActivityStackHandler extends Handler {
334 // if (localLOGV) Slog.v(TAG, "Handler started!");
336 public ActivityStackHandler(Looper looper) {
341 public void handleMessage(Message msg) {
343 case SLEEP_TIMEOUT_MSG: {
344 synchronized (mService) {
345 if (mService.isSleeping()) {
346 Slog.w(TAG, "Sleep timeout! Sleeping now.");
347 mSleepTimeout = true;
348 checkReadyForSleepLocked();
352 case PAUSE_TIMEOUT_MSG: {
353 ActivityRecord r = (ActivityRecord)msg.obj;
354 // We don't at this point know if the activity is fullscreen,
355 // so we need to be conservative and assume it isn't.
356 Slog.w(TAG, "Activity pause timeout for " + r);
357 synchronized (mService) {
359 mService.logAppTooSlow(r.app, r.pauseTime,
364 activityPaused(r != null ? r.appToken : null, true);
366 case IDLE_TIMEOUT_MSG: {
367 if (mService.mDidDexOpt) {
368 mService.mDidDexOpt = false;
369 Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
371 mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
374 // We don't at this point know if the activity is fullscreen,
375 // so we need to be conservative and assume it isn't.
376 ActivityRecord r = (ActivityRecord)msg.obj;
377 Slog.w(TAG, "Activity idle timeout for " + r);
378 activityIdleInternal(r != null ? r.appToken : null, true, null);
380 case LAUNCH_TICK_MSG: {
381 ActivityRecord r = (ActivityRecord)msg.obj;
382 synchronized (mService) {
383 if (r.continueLaunchTickingLocked()) {
384 mService.logAppTooSlow(r.app, r.launchTickTime,
389 case DESTROY_TIMEOUT_MSG: {
390 ActivityRecord r = (ActivityRecord)msg.obj;
391 // We don't at this point know if the activity is fullscreen,
392 // so we need to be conservative and assume it isn't.
393 Slog.w(TAG, "Activity destroy timeout for " + r);
394 activityDestroyed(r != null ? r.appToken : null);
397 ActivityRecord r = (ActivityRecord)msg.obj;
398 activityIdleInternal(r != null ? r.appToken : null, false, null);
400 case LAUNCH_TIMEOUT_MSG: {
401 if (mService.mDidDexOpt) {
402 mService.mDidDexOpt = false;
403 Message nmsg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
404 mHandler.sendMessageDelayed(nmsg, LAUNCH_TIMEOUT);
407 synchronized (mService) {
408 if (mLaunchingActivity.isHeld()) {
409 Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
410 mLaunchingActivity.release();
414 case RESUME_TOP_ACTIVITY_MSG: {
415 synchronized (mService) {
416 resumeTopActivityLocked(null);
419 case STOP_TIMEOUT_MSG: {
420 ActivityRecord r = (ActivityRecord)msg.obj;
421 // We don't at this point know if the activity is fullscreen,
422 // so we need to be conservative and assume it isn't.
423 Slog.w(TAG, "Activity stop timeout for " + r);
424 synchronized (mService) {
425 if (r.isInHistory()) {
426 activityStoppedLocked(r, null, null, null);
430 case DESTROY_ACTIVITIES_MSG: {
431 ScheduleDestroyArgs args = (ScheduleDestroyArgs)msg.obj;
432 synchronized (mService) {
433 destroyActivitiesLocked(args.mOwner, args.mOomAdj, args.mReason);
440 ActivityStack(ActivityManagerService service, Context context, boolean mainStack, Looper looper) {
441 mHandler = new ActivityStackHandler(looper);
444 mMainStack = mainStack;
446 (PowerManager)context.getSystemService(Context.POWER_SERVICE);
447 mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
448 mLaunchingActivity = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
449 mLaunchingActivity.setReferenceCounted(false);
452 private boolean okToShow(ActivityRecord r) {
453 return r.userId == mCurrentUser
454 || (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0;
457 final ActivityRecord topRunningActivityLocked(ActivityRecord notTop) {
458 int i = mHistory.size()-1;
460 ActivityRecord r = mHistory.get(i);
461 if (!r.finishing && r != notTop && okToShow(r)) {
469 final ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
470 int i = mHistory.size()-1;
472 ActivityRecord r = mHistory.get(i);
473 if (!r.finishing && !r.delayedResume && r != notTop && okToShow(r)) {
482 * This is a simplified version of topRunningActivityLocked that provides a number of
483 * optional skip-over modes. It is intended for use with the ActivityController hook only.
485 * @param token If non-null, any history records matching this token will be skipped.
486 * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
488 * @return Returns the HistoryRecord of the next activity on the stack.
490 final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
491 int i = mHistory.size()-1;
493 ActivityRecord r = mHistory.get(i);
494 // Note: the taskId check depends on real taskId fields being non-zero
495 if (!r.finishing && (token != r.appToken) && (taskId != r.task.taskId)
504 final int indexOfTokenLocked(IBinder token) {
505 return mHistory.indexOf(ActivityRecord.forToken(token));
508 final int indexOfActivityLocked(ActivityRecord r) {
509 return mHistory.indexOf(r);
512 final ActivityRecord isInStackLocked(IBinder token) {
513 ActivityRecord r = ActivityRecord.forToken(token);
514 if (mHistory.contains(r)) {
520 // TODO: This exposes mHistory too much, replace usage with ActivityStack methods.
521 final ActivityRecord getActivityAtIndex(int index) {
522 if (index >= 0 && index < mHistory.size()) {
523 return mHistory.get(index);
528 int getTaskForActivityLocked(IBinder token, boolean onlyRoot) {
529 TaskRecord lastTask = null;
530 final int N = mHistory.size();
531 for (int i = 0; i < N; i++) {
532 ActivityRecord r = mHistory.get(i);
533 if (r.appToken == token) {
534 if (!onlyRoot || lastTask != r.task) {
535 return r.task.taskId;
545 private final boolean updateLRUListLocked(ActivityRecord r) {
546 final boolean hadit = mLRUActivities.remove(r);
547 mLRUActivities.add(r);
552 * Returns the top activity in any existing task matching the given
553 * Intent. Returns null if no such task is found.
555 private ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
556 ComponentName cls = intent.getComponent();
557 if (info.targetActivity != null) {
558 cls = new ComponentName(info.packageName, info.targetActivity);
561 TaskRecord cp = null;
563 final int userId = UserHandle.getUserId(info.applicationInfo.uid);
564 final int N = mHistory.size();
565 for (int i=(N-1); i>=0; i--) {
566 ActivityRecord r = mHistory.get(i);
567 if (!r.finishing && r.task != cp && r.userId == userId
568 && r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
570 //Slog.i(TAG, "Comparing existing cls=" + r.task.intent.getComponent().flattenToShortString()
571 // + "/aff=" + r.task.affinity + " to new cls="
572 // + intent.getComponent().flattenToShortString() + "/aff=" + taskAffinity);
573 if (r.task.affinity != null) {
574 if (r.task.affinity.equals(info.taskAffinity)) {
575 //Slog.i(TAG, "Found matching affinity!");
578 } else if (r.task.intent != null
579 && r.task.intent.getComponent().equals(cls)) {
580 //Slog.i(TAG, "Found matching class!");
582 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
584 } else if (r.task.affinityIntent != null
585 && r.task.affinityIntent.getComponent().equals(cls)) {
586 //Slog.i(TAG, "Found matching class!");
588 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
598 * Returns the first activity (starting from the top of the stack) that
599 * is the same as the given activity. Returns null if no such activity
602 private ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
603 ComponentName cls = intent.getComponent();
604 if (info.targetActivity != null) {
605 cls = new ComponentName(info.packageName, info.targetActivity);
607 final int userId = UserHandle.getUserId(info.applicationInfo.uid);
609 final int N = mHistory.size();
610 for (int i=(N-1); i>=0; i--) {
611 ActivityRecord r = mHistory.get(i);
613 if (r.intent.getComponent().equals(cls) && r.userId == userId) {
614 //Slog.i(TAG, "Found matching class!");
616 //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
625 final void showAskCompatModeDialogLocked(ActivityRecord r) {
626 Message msg = Message.obtain();
627 msg.what = ActivityManagerService.SHOW_COMPAT_MODE_DIALOG_MSG;
628 msg.obj = r.task.askedCompatMode ? null : r;
629 mService.mHandler.sendMessage(msg);
633 * Move the activities around in the stack to bring a user to the foreground.
634 * @return whether there are any activities for the specified user.
636 final boolean switchUserLocked(int userId, UserStartedState uss) {
637 mCurrentUser = userId;
638 mStartingUsers.add(uss);
640 // Only one activity? Nothing to do...
641 if (mHistory.size() < 2)
644 boolean haveActivities = false;
645 // Check if the top activity is from the new user.
646 ActivityRecord top = mHistory.get(mHistory.size() - 1);
647 if (top.userId == userId) return true;
648 // Otherwise, move the user's activities to the top.
649 int N = mHistory.size();
652 ActivityRecord r = mHistory.get(i);
653 if (r.userId == userId) {
654 ActivityRecord moveToTop = mHistory.remove(i);
655 mHistory.add(moveToTop);
656 // No need to check the top one now
658 haveActivities = true;
663 // Transition from the old top to the new top
664 resumeTopActivityLocked(top);
665 return haveActivities;
668 final boolean realStartActivityLocked(ActivityRecord r,
669 ProcessRecord app, boolean andResume, boolean checkConfig)
670 throws RemoteException {
672 r.startFreezingScreenLocked(app, 0);
673 mService.mWindowManager.setAppVisibility(r.appToken, true);
675 // schedule launch ticks to collect information about slow apps.
676 r.startLaunchTickingLocked();
678 // Have the window manager re-evaluate the orientation of
679 // the screen based on the new activity order. Note that
680 // as a result of this, it can call back into the activity
681 // manager with a new orientation. We don't care about that,
682 // because the activity is not currently running so we are
683 // just restarting it anyway.
685 Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
686 mService.mConfiguration,
687 r.mayFreezeScreenLocked(app) ? r.appToken : null);
688 mService.updateConfigurationLocked(config, r, false, false);
692 app.waitingToKill = null;
694 r.lastLaunchTime = SystemClock.uptimeMillis();
696 if (localLOGV) Slog.v(TAG, "Launching: " + r);
698 int idx = app.activities.indexOf(r);
700 app.activities.add(r);
702 mService.updateLruProcessLocked(app, true);
705 if (app.thread == null) {
706 throw new RemoteException();
708 List<ResultInfo> results = null;
709 List<Intent> newIntents = null;
712 newIntents = r.newIntents;
714 if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
715 + " icicle=" + r.icicle
716 + " with results=" + results + " newIntents=" + newIntents
717 + " andResume=" + andResume);
719 EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
720 r.userId, System.identityHashCode(r),
721 r.task.taskId, r.shortComponentName);
723 if (r.isHomeActivity) {
724 mService.mHomeProcess = app;
726 mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
728 r.forceNewConfig = false;
729 showAskCompatModeDialogLocked(r);
730 r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
731 String profileFile = null;
732 ParcelFileDescriptor profileFd = null;
733 boolean profileAutoStop = false;
734 if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
735 if (mService.mProfileProc == null || mService.mProfileProc == app) {
736 mService.mProfileProc = app;
737 profileFile = mService.mProfileFile;
738 profileFd = mService.mProfileFd;
739 profileAutoStop = mService.mAutoStopProfiler;
742 app.hasShownUi = true;
743 app.pendingUiClean = true;
744 if (profileFd != null) {
746 profileFd = profileFd.dup();
747 } catch (IOException e) {
751 app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
752 System.identityHashCode(r), r.info,
753 new Configuration(mService.mConfiguration),
754 r.compat, r.icicle, results, newIntents, !andResume,
755 mService.isNextTransitionForward(), profileFile, profileFd,
758 if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
759 // This may be a heavy-weight process! Note that the package
760 // manager will ensure that only activity can run in the main
761 // process of the .apk, which is the only thing that will be
762 // considered heavy-weight.
763 if (app.processName.equals(app.info.packageName)) {
764 if (mService.mHeavyWeightProcess != null
765 && mService.mHeavyWeightProcess != app) {
766 Log.w(TAG, "Starting new heavy weight process " + app
767 + " when already running "
768 + mService.mHeavyWeightProcess);
770 mService.mHeavyWeightProcess = app;
771 Message msg = mService.mHandler.obtainMessage(
772 ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
774 mService.mHandler.sendMessage(msg);
778 } catch (RemoteException e) {
779 if (r.launchFailed) {
780 // This is the second time we failed -- finish activity
782 Slog.e(TAG, "Second failure launching "
783 + r.intent.getComponent().flattenToShortString()
785 mService.appDiedLocked(app, app.pid, app.thread);
786 requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
791 // This is the first time we failed -- restart process and
793 app.activities.remove(r);
797 r.launchFailed = false;
798 if (updateLRUListLocked(r)) {
799 Slog.w(TAG, "Activity " + r
800 + " being launched, but already in LRU list");
804 // As part of the process of launching, ActivityThread also performs
806 r.state = ActivityState.RESUMED;
807 if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + r
808 + " (starting new instance)");
810 mResumedActivity = r;
811 r.task.touchActiveTime();
813 mService.addRecentTaskLocked(r.task);
815 completeResumeLocked(r);
816 checkReadyForSleepLocked();
817 if (DEBUG_SAVED_STATE) Slog.i(TAG, "Launch completed; removing icicle of " + r.icicle);
819 // This activity is not starting in the resumed state... which
820 // should look like we asked it to pause+stop (but remain visible),
821 // and it has done so and reported back the current icicle and
823 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
824 + " (starting in stopped state)");
825 r.state = ActivityState.STOPPED;
829 // Launch the new version setup screen if needed. We do this -after-
830 // launching the initial activity (that is, home), so that it can have
831 // a chance to initialize itself while in the background, making the
832 // switch back to it faster and look better.
834 mService.startSetupActivityLocked();
840 private final void startSpecificActivityLocked(ActivityRecord r,
841 boolean andResume, boolean checkConfig) {
842 // Is this activity's application already running?
843 ProcessRecord app = mService.getProcessRecordLocked(r.processName,
844 r.info.applicationInfo.uid);
846 if (r.launchTime == 0) {
847 r.launchTime = SystemClock.uptimeMillis();
848 if (mInitialStartTime == 0) {
849 mInitialStartTime = r.launchTime;
851 } else if (mInitialStartTime == 0) {
852 mInitialStartTime = SystemClock.uptimeMillis();
855 if (app != null && app.thread != null) {
857 app.addPackage(r.info.packageName);
858 realStartActivityLocked(r, app, andResume, checkConfig);
860 } catch (RemoteException e) {
861 Slog.w(TAG, "Exception when starting activity "
862 + r.intent.getComponent().flattenToShortString(), e);
865 // If a dead object exception was thrown -- fall through to
866 // restart the application.
869 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
870 "activity", r.intent.getComponent(), false, false);
873 void stopIfSleepingLocked() {
874 if (mService.isSleeping()) {
875 if (!mGoingToSleep.isHeld()) {
876 mGoingToSleep.acquire();
877 if (mLaunchingActivity.isHeld()) {
878 mLaunchingActivity.release();
879 mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
882 mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
883 Message msg = mHandler.obtainMessage(SLEEP_TIMEOUT_MSG);
884 mHandler.sendMessageDelayed(msg, SLEEP_TIMEOUT);
885 checkReadyForSleepLocked();
889 void awakeFromSleepingLocked() {
890 mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
891 mSleepTimeout = false;
892 if (mGoingToSleep.isHeld()) {
893 mGoingToSleep.release();
895 // Ensure activities are no longer sleeping.
896 for (int i=mHistory.size()-1; i>=0; i--) {
897 ActivityRecord r = mHistory.get(i);
898 r.setSleeping(false);
900 mGoingToSleepActivities.clear();
903 void activitySleptLocked(ActivityRecord r) {
904 mGoingToSleepActivities.remove(r);
905 checkReadyForSleepLocked();
908 void checkReadyForSleepLocked() {
909 if (!mService.isSleeping()) {
914 if (!mSleepTimeout) {
915 if (mResumedActivity != null) {
916 // Still have something resumed; can't sleep until it is paused.
917 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause " + mResumedActivity);
918 if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
919 startPausingLocked(false, true);
922 if (mPausingActivity != null) {
923 // Still waiting for something to pause; can't sleep yet.
924 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still waiting to pause " + mPausingActivity);
928 if (mStoppingActivities.size() > 0) {
929 // Still need to tell some activities to stop; can't sleep yet.
930 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
931 + mStoppingActivities.size() + " activities");
932 scheduleIdleLocked();
936 ensureActivitiesVisibleLocked(null, 0);
938 // Make sure any stopped but visible activities are now sleeping.
939 // This ensures that the activity's onStop() is called.
940 for (int i=mHistory.size()-1; i>=0; i--) {
941 ActivityRecord r = mHistory.get(i);
942 if (r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED) {
947 if (mGoingToSleepActivities.size() > 0) {
948 // Still need to tell some activities to sleep; can't sleep yet.
949 if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
950 + mGoingToSleepActivities.size() + " activities");
955 mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
957 if (mGoingToSleep.isHeld()) {
958 mGoingToSleep.release();
960 if (mService.mShuttingDown) {
961 mService.notifyAll();
965 public final Bitmap screenshotActivities(ActivityRecord who) {
970 Resources res = mService.mContext.getResources();
971 int w = mThumbnailWidth;
972 int h = mThumbnailHeight;
974 mThumbnailWidth = w =
975 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_width);
976 mThumbnailHeight = h =
977 res.getDimensionPixelSize(com.android.internal.R.dimen.thumbnail_height);
981 if (who != mLastScreenshotActivity || mLastScreenshotBitmap == null
982 || mLastScreenshotBitmap.getWidth() != w
983 || mLastScreenshotBitmap.getHeight() != h) {
984 mLastScreenshotActivity = who;
985 mLastScreenshotBitmap = mService.mWindowManager.screenshotApplications(
986 who.appToken, Display.DEFAULT_DISPLAY, w, h);
988 if (mLastScreenshotBitmap != null) {
989 return mLastScreenshotBitmap.copy(Config.ARGB_8888, true);
995 private final void startPausingLocked(boolean userLeaving, boolean uiSleeping) {
996 if (mPausingActivity != null) {
997 RuntimeException e = new RuntimeException();
998 Slog.e(TAG, "Trying to pause when pause is already pending for "
999 + mPausingActivity, e);
1001 ActivityRecord prev = mResumedActivity;
1003 RuntimeException e = new RuntimeException();
1004 Slog.e(TAG, "Trying to pause when nothing is resumed", e);
1005 resumeTopActivityLocked(null);
1008 if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev);
1009 else if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
1010 mResumedActivity = null;
1011 mPausingActivity = prev;
1012 mLastPausedActivity = prev;
1013 prev.state = ActivityState.PAUSING;
1014 prev.task.touchActiveTime();
1015 prev.updateThumbnail(screenshotActivities(prev), null);
1017 mService.updateCpuStats();
1019 if (prev.app != null && prev.app.thread != null) {
1020 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
1022 EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
1023 prev.userId, System.identityHashCode(prev),
1024 prev.shortComponentName);
1025 prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
1026 userLeaving, prev.configChangeFlags);
1028 mService.updateUsageStats(prev, false);
1030 } catch (Exception e) {
1031 // Ignore exception, if process died other code will cleanup.
1032 Slog.w(TAG, "Exception thrown during pause", e);
1033 mPausingActivity = null;
1034 mLastPausedActivity = null;
1037 mPausingActivity = null;
1038 mLastPausedActivity = null;
1041 // If we are not going to sleep, we want to ensure the device is
1042 // awake until the next activity is started.
1043 if (!mService.mSleeping && !mService.mShuttingDown) {
1044 mLaunchingActivity.acquire();
1045 if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
1046 // To be safe, don't allow the wake lock to be held for too long.
1047 Message msg = mHandler.obtainMessage(LAUNCH_TIMEOUT_MSG);
1048 mHandler.sendMessageDelayed(msg, LAUNCH_TIMEOUT);
1053 if (mPausingActivity != null) {
1054 // Have the window manager pause its key dispatching until the new
1055 // activity has started. If we're pausing the activity just because
1056 // the screen is being turned off and the UI is sleeping, don't interrupt
1057 // key dispatch; the same activity will pick it up again on wakeup.
1059 prev.pauseKeyDispatchingLocked();
1061 if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
1064 // Schedule a pause timeout in case the app doesn't respond.
1065 // We don't give it much time because this directly impacts the
1066 // responsiveness seen by the user.
1067 Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
1069 prev.pauseTime = SystemClock.uptimeMillis();
1070 mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
1071 if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
1073 // This activity failed to schedule the
1074 // pause, so just treat it as being paused now.
1075 if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
1076 resumeTopActivityLocked(null);
1080 final void activityResumed(IBinder token) {
1081 ActivityRecord r = null;
1083 synchronized (mService) {
1084 int index = indexOfTokenLocked(token);
1086 r = mHistory.get(index);
1087 if (DEBUG_SAVED_STATE) Slog.i(TAG, "Resumed activity; dropping state of: " + r);
1089 r.haveState = false;
1094 final void activityPaused(IBinder token, boolean timeout) {
1095 if (DEBUG_PAUSE) Slog.v(
1096 TAG, "Activity paused: token=" + token + ", timeout=" + timeout);
1098 ActivityRecord r = null;
1100 synchronized (mService) {
1101 int index = indexOfTokenLocked(token);
1103 r = mHistory.get(index);
1104 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
1105 if (mPausingActivity == r) {
1106 if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r
1107 + (timeout ? " (due to timeout)" : " (pause complete)"));
1108 r.state = ActivityState.PAUSED;
1109 completePauseLocked();
1111 EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
1112 r.userId, System.identityHashCode(r), r.shortComponentName,
1113 mPausingActivity != null
1114 ? mPausingActivity.shortComponentName : "(none)");
1120 final void activityStoppedLocked(ActivityRecord r, Bundle icicle, Bitmap thumbnail,
1121 CharSequence description) {
1122 if (r.state != ActivityState.STOPPING) {
1123 Slog.i(TAG, "Activity reported stop, but no longer stopping: " + r);
1124 mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
1127 if (DEBUG_SAVED_STATE) Slog.i(TAG, "Saving icicle of " + r + ": " + icicle);
1128 if (icicle != null) {
1129 // If icicle is null, this is happening due to a timeout, so we
1130 // haven't really saved the state.
1134 r.updateThumbnail(thumbnail, description);
1137 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (stop complete)");
1138 mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
1140 r.state = ActivityState.STOPPED;
1142 r.clearOptionsLocked();
1144 if (r.configDestroy) {
1145 destroyActivityLocked(r, true, false, "stop-config");
1146 resumeTopActivityLocked(null);
1148 // Now that this process has stopped, we may want to consider
1149 // it to be the previous app to try to keep around in case
1150 // the user wants to return to it.
1151 ProcessRecord fgApp = null;
1152 if (mResumedActivity != null) {
1153 fgApp = mResumedActivity.app;
1154 } else if (mPausingActivity != null) {
1155 fgApp = mPausingActivity.app;
1157 if (r.app != null && fgApp != null && r.app != fgApp
1158 && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
1159 && r.app != mService.mHomeProcess) {
1160 mService.mPreviousProcess = r.app;
1161 mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
1168 private final void completePauseLocked() {
1169 ActivityRecord prev = mPausingActivity;
1170 if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
1173 if (prev.finishing) {
1174 if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
1175 prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
1176 } else if (prev.app != null) {
1177 if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
1178 if (prev.waitingVisible) {
1179 prev.waitingVisible = false;
1180 mWaitingVisibleActivities.remove(prev);
1181 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
1182 TAG, "Complete pause, no longer waiting: " + prev);
1184 if (prev.configDestroy) {
1185 // The previous is being paused because the configuration
1186 // is changing, which means it is actually stopping...
1187 // To juggle the fact that we are also starting a new
1188 // instance right now, we need to first completely stop
1189 // the current instance before starting the new one.
1190 if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
1191 destroyActivityLocked(prev, true, false, "pause-config");
1193 mStoppingActivities.add(prev);
1194 if (mStoppingActivities.size() > 3) {
1195 // If we already have a few activities waiting to stop,
1196 // then give up on things going idle and start clearing
1198 if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
1199 scheduleIdleLocked();
1201 checkReadyForSleepLocked();
1205 if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
1208 mPausingActivity = null;
1211 if (!mService.isSleeping()) {
1212 resumeTopActivityLocked(prev);
1214 checkReadyForSleepLocked();
1215 ActivityRecord top = topRunningActivityLocked(null);
1216 if (top == null || (prev != null && top != prev)) {
1217 // If there are no more activities available to run,
1218 // do resume anyway to start something. Also if the top
1219 // activity on the stack is not the just paused activity,
1220 // we need to go ahead and resume it to ensure we complete
1221 // an in-flight app switch.
1222 resumeTopActivityLocked(null);
1227 prev.resumeKeyDispatchingLocked();
1230 if (prev.app != null && prev.cpuTimeAtResume > 0
1231 && mService.mBatteryStatsService.isOnBattery()) {
1233 synchronized (mService.mProcessStatsThread) {
1234 diff = mService.mProcessStats.getCpuTimeForPid(prev.app.pid)
1235 - prev.cpuTimeAtResume;
1238 BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();
1239 synchronized (bsi) {
1240 BatteryStatsImpl.Uid.Proc ps =
1241 bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
1242 prev.info.packageName);
1244 ps.addForegroundTimeLocked(diff);
1249 prev.cpuTimeAtResume = 0; // reset it
1253 * Once we know that we have asked an application to put an activity in
1254 * the resumed state (either by launching it or explicitly telling it),
1255 * this function updates the rest of our state to match that fact.
1257 private final void completeResumeLocked(ActivityRecord next) {
1259 next.results = null;
1260 next.newIntents = null;
1262 // schedule an idle timeout in case the app doesn't do it for us.
1263 Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1265 mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
1268 // The activity was never told to pause, so just keep
1269 // things going as-is. To maintain our own state,
1270 // we need to emulate it coming back and saying it is
1272 msg = mHandler.obtainMessage(IDLE_NOW_MSG);
1274 mHandler.sendMessage(msg);
1278 mService.reportResumedActivityLocked(next);
1282 mService.setFocusedActivityLocked(next);
1284 next.resumeKeyDispatchingLocked();
1285 ensureActivitiesVisibleLocked(null, 0);
1286 mService.mWindowManager.executeAppTransition();
1287 mNoAnimActivities.clear();
1289 // Mark the point when the activity is resuming
1290 // TODO: To be more accurate, the mark should be before the onCreate,
1291 // not after the onResume. But for subsequent starts, onResume is fine.
1292 if (next.app != null) {
1293 synchronized (mService.mProcessStatsThread) {
1294 next.cpuTimeAtResume = mService.mProcessStats.getCpuTimeForPid(next.app.pid);
1297 next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
1302 * Make sure that all activities that need to be visible (that is, they
1303 * currently can be seen by the user) actually are.
1305 final void ensureActivitiesVisibleLocked(ActivityRecord top,
1306 ActivityRecord starting, String onlyThisProcess, int configChanges) {
1307 if (DEBUG_VISBILITY) Slog.v(
1308 TAG, "ensureActivitiesVisible behind " + top
1309 + " configChanges=0x" + Integer.toHexString(configChanges));
1311 // If the top activity is not fullscreen, then we need to
1312 // make sure any activities under it are now visible.
1313 final int count = mHistory.size();
1315 while (mHistory.get(i) != top) {
1319 boolean behindFullscreen = false;
1321 r = mHistory.get(i);
1322 if (DEBUG_VISBILITY) Slog.v(
1323 TAG, "Make visible? " + r + " finishing=" + r.finishing
1324 + " state=" + r.state);
1329 final boolean doThisProcess = onlyThisProcess == null
1330 || onlyThisProcess.equals(r.processName);
1332 // First: if this is not the current activity being started, make
1333 // sure it matches the current configuration.
1334 if (r != starting && doThisProcess) {
1335 ensureActivityConfigurationLocked(r, 0);
1338 if (r.app == null || r.app.thread == null) {
1339 if (onlyThisProcess == null
1340 || onlyThisProcess.equals(r.processName)) {
1341 // This activity needs to be visible, but isn't even
1342 // running... get it started, but don't resume it
1344 if (DEBUG_VISBILITY) Slog.v(
1345 TAG, "Start and freeze screen for " + r);
1346 if (r != starting) {
1347 r.startFreezingScreenLocked(r.app, configChanges);
1350 if (DEBUG_VISBILITY) Slog.v(
1351 TAG, "Starting and making visible: " + r);
1352 mService.mWindowManager.setAppVisibility(r.appToken, true);
1354 if (r != starting) {
1355 startSpecificActivityLocked(r, false, false);
1359 } else if (r.visible) {
1360 // If this activity is already visible, then there is nothing
1362 if (DEBUG_VISBILITY) Slog.v(
1363 TAG, "Skipping: already visible at " + r);
1364 r.stopFreezingScreenLocked(false);
1366 } else if (onlyThisProcess == null) {
1367 // This activity is not currently visible, but is running.
1368 // Tell it to become visible.
1370 if (r.state != ActivityState.RESUMED && r != starting) {
1371 // If this activity is paused, tell it
1372 // to now show its window.
1373 if (DEBUG_VISBILITY) Slog.v(
1374 TAG, "Making visible and scheduling visibility: " + r);
1376 mService.mWindowManager.setAppVisibility(r.appToken, true);
1378 r.app.pendingUiClean = true;
1379 r.app.thread.scheduleWindowVisibility(r.appToken, true);
1380 r.stopFreezingScreenLocked(false);
1381 } catch (Exception e) {
1382 // Just skip on any failure; we'll make it
1383 // visible when it next restarts.
1384 Slog.w(TAG, "Exception thrown making visibile: "
1385 + r.intent.getComponent(), e);
1390 // Aggregate current change flags.
1391 configChanges |= r.configChangeFlags;
1394 // At this point, nothing else needs to be shown
1395 if (DEBUG_VISBILITY) Slog.v(
1396 TAG, "Stopping: fullscreen at " + r);
1397 behindFullscreen = true;
1403 // Now for any activities that aren't visible to the user, make
1404 // sure they no longer are keeping the screen frozen.
1406 r = mHistory.get(i);
1407 if (DEBUG_VISBILITY) Slog.v(
1408 TAG, "Make invisible? " + r + " finishing=" + r.finishing
1409 + " state=" + r.state
1410 + " behindFullscreen=" + behindFullscreen);
1412 if (behindFullscreen) {
1414 if (DEBUG_VISBILITY) Slog.v(
1415 TAG, "Making invisible: " + r);
1418 mService.mWindowManager.setAppVisibility(r.appToken, false);
1419 if ((r.state == ActivityState.STOPPING
1420 || r.state == ActivityState.STOPPED)
1421 && r.app != null && r.app.thread != null) {
1422 if (DEBUG_VISBILITY) Slog.v(
1423 TAG, "Scheduling invisibility: " + r);
1424 r.app.thread.scheduleWindowVisibility(r.appToken, false);
1426 } catch (Exception e) {
1427 // Just skip on any failure; we'll make it
1428 // visible when it next restarts.
1429 Slog.w(TAG, "Exception thrown making hidden: "
1430 + r.intent.getComponent(), e);
1433 if (DEBUG_VISBILITY) Slog.v(
1434 TAG, "Already invisible: " + r);
1436 } else if (r.fullscreen) {
1437 if (DEBUG_VISBILITY) Slog.v(
1438 TAG, "Now behindFullscreen: " + r);
1439 behindFullscreen = true;
1447 * Version of ensureActivitiesVisible that can easily be called anywhere.
1449 final void ensureActivitiesVisibleLocked(ActivityRecord starting,
1450 int configChanges) {
1451 ActivityRecord r = topRunningActivityLocked(null);
1453 ensureActivitiesVisibleLocked(r, starting, null, configChanges);
1458 * Ensure that the top activity in the stack is resumed.
1460 * @param prev The previously resumed activity, for when in the process
1461 * of pausing; can be null to call from elsewhere.
1463 * @return Returns true if something is being resumed, or false if
1466 final boolean resumeTopActivityLocked(ActivityRecord prev) {
1467 return resumeTopActivityLocked(prev, null);
1470 final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
1471 // Find the first activity that is not finishing.
1472 ActivityRecord next = topRunningActivityLocked(null);
1474 // Remember how we'll process this pause/resume situation, and ensure
1475 // that the state is reset however we wind up proceeding.
1476 final boolean userLeaving = mUserLeaving;
1477 mUserLeaving = false;
1480 // There are no more activities! Let's just start up the
1483 ActivityOptions.abort(options);
1484 return mService.startHomeActivityLocked(mCurrentUser);
1488 next.delayedResume = false;
1490 // If the top activity is the resumed one, nothing to do.
1491 if (mResumedActivity == next && next.state == ActivityState.RESUMED) {
1492 // Make sure we have executed any pending transitions, since there
1493 // should be nothing left to do at this point.
1494 mService.mWindowManager.executeAppTransition();
1495 mNoAnimActivities.clear();
1496 ActivityOptions.abort(options);
1500 // If we are sleeping, and there is no resumed activity, and the top
1501 // activity is paused, well that is the state we want.
1502 if ((mService.mSleeping || mService.mShuttingDown)
1503 && mLastPausedActivity == next
1504 && (next.state == ActivityState.PAUSED
1505 || next.state == ActivityState.STOPPED
1506 || next.state == ActivityState.STOPPING)) {
1507 // Make sure we have executed any pending transitions, since there
1508 // should be nothing left to do at this point.
1509 mService.mWindowManager.executeAppTransition();
1510 mNoAnimActivities.clear();
1511 ActivityOptions.abort(options);
1515 // Make sure that the user who owns this activity is started. If not,
1516 // we will just leave it as is because someone should be bringing
1517 // another user's activities to the top of the stack.
1518 if (mService.mStartedUsers.get(next.userId) == null) {
1519 Slog.w(TAG, "Skipping resume of top activity " + next
1520 + ": user " + next.userId + " is stopped");
1524 // The activity may be waiting for stop, but that is no longer
1525 // appropriate for it.
1526 mStoppingActivities.remove(next);
1527 mGoingToSleepActivities.remove(next);
1528 next.sleeping = false;
1529 mWaitingVisibleActivities.remove(next);
1531 next.updateOptionsLocked(options);
1533 if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
1535 // If we are currently pausing an activity, then don't do anything
1536 // until that is done.
1537 if (mPausingActivity != null) {
1538 if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(TAG,
1539 "Skip resume: pausing=" + mPausingActivity);
1543 // Okay we are now going to start a switch, to 'next'. We may first
1544 // have to pause the current activity, but this is an important point
1545 // where we have decided to go to 'next' so keep track of that.
1546 // XXX "App Redirected" dialog is getting too many false positives
1547 // at this point, so turn off for now.
1549 if (mLastStartedActivity != null && !mLastStartedActivity.finishing) {
1550 long now = SystemClock.uptimeMillis();
1551 final boolean inTime = mLastStartedActivity.startTime != 0
1552 && (mLastStartedActivity.startTime + START_WARN_TIME) >= now;
1553 final int lastUid = mLastStartedActivity.info.applicationInfo.uid;
1554 final int nextUid = next.info.applicationInfo.uid;
1555 if (inTime && lastUid != nextUid
1556 && lastUid != next.launchedFromUid
1557 && mService.checkPermission(
1558 android.Manifest.permission.STOP_APP_SWITCHES,
1559 -1, next.launchedFromUid)
1560 != PackageManager.PERMISSION_GRANTED) {
1561 mService.showLaunchWarningLocked(mLastStartedActivity, next);
1563 next.startTime = now;
1564 mLastStartedActivity = next;
1567 next.startTime = SystemClock.uptimeMillis();
1568 mLastStartedActivity = next;
1572 // We need to start pausing the current activity so the top one
1573 // can be resumed...
1574 if (mResumedActivity != null) {
1575 if (DEBUG_SWITCH) Slog.v(TAG, "Skip resume: need to start pausing");
1576 // At this point we want to put the upcoming activity's process
1577 // at the top of the LRU list, since we know we will be needing it
1578 // very soon and it would be a waste to let it get killed if it
1579 // happens to be sitting towards the end.
1580 if (next.app != null && next.app.thread != null) {
1581 // No reason to do full oom adj update here; we'll let that
1582 // happen whenever it needs to later.
1583 mService.updateLruProcessLocked(next.app, false);
1585 startPausingLocked(userLeaving, false);
1589 // If the most recent activity was noHistory but was only stopped rather
1590 // than stopped+finished because the device went to sleep, we need to make
1591 // sure to finish it as we're making a new activity topmost.
1592 final ActivityRecord last = mLastPausedActivity;
1593 if (mService.mSleeping && last != null && !last.finishing) {
1594 if ((last.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
1595 || (last.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
1597 Slog.d(TAG, "no-history finish of " + last + " on new resume");
1599 requestFinishActivityLocked(last.appToken, Activity.RESULT_CANCELED, null,
1600 "no-history", false);
1604 if (prev != null && prev != next) {
1605 if (!prev.waitingVisible && next != null && !next.nowVisible) {
1606 prev.waitingVisible = true;
1607 mWaitingVisibleActivities.add(prev);
1608 if (DEBUG_SWITCH) Slog.v(
1609 TAG, "Resuming top, waiting visible to hide: " + prev);
1611 // The next activity is already visible, so hide the previous
1612 // activity's windows right now so we can show the new one ASAP.
1613 // We only do this if the previous is finishing, which should mean
1614 // it is on top of the one being resumed so hiding it quickly
1615 // is good. Otherwise, we want to do the normal route of allowing
1616 // the resumed activity to be shown so we can decide if the
1617 // previous should actually be hidden depending on whether the
1618 // new one is found to be full-screen or not.
1619 if (prev.finishing) {
1620 mService.mWindowManager.setAppVisibility(prev.appToken, false);
1621 if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
1622 + prev + ", waitingVisible="
1623 + (prev != null ? prev.waitingVisible : null)
1624 + ", nowVisible=" + next.nowVisible);
1626 if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
1627 + prev + ", waitingVisible="
1628 + (prev != null ? prev.waitingVisible : null)
1629 + ", nowVisible=" + next.nowVisible);
1634 // Launching this app's activity, make sure the app is no longer
1635 // considered stopped.
1637 AppGlobals.getPackageManager().setPackageStoppedState(
1638 next.packageName, false, next.userId); /* TODO: Verify if correct userid */
1639 } catch (RemoteException e1) {
1640 } catch (IllegalArgumentException e) {
1641 Slog.w(TAG, "Failed trying to unstop package "
1642 + next.packageName + ": " + e);
1645 // We are starting up the next activity, so tell the window manager
1646 // that the previous one will be hidden soon. This way it can know
1647 // to ignore it when computing the desired screen orientation.
1648 boolean noAnim = false;
1650 if (prev.finishing) {
1651 if (DEBUG_TRANSITION) Slog.v(TAG,
1652 "Prepare close transition: prev=" + prev);
1653 if (mNoAnimActivities.contains(prev)) {
1654 mService.mWindowManager.prepareAppTransition(
1655 AppTransition.TRANSIT_NONE, false);
1657 mService.mWindowManager.prepareAppTransition(prev.task == next.task
1658 ? AppTransition.TRANSIT_ACTIVITY_CLOSE
1659 : AppTransition.TRANSIT_TASK_CLOSE, false);
1661 mService.mWindowManager.setAppWillBeHidden(prev.appToken);
1662 mService.mWindowManager.setAppVisibility(prev.appToken, false);
1664 if (DEBUG_TRANSITION) Slog.v(TAG,
1665 "Prepare open transition: prev=" + prev);
1666 if (mNoAnimActivities.contains(next)) {
1668 mService.mWindowManager.prepareAppTransition(
1669 AppTransition.TRANSIT_NONE, false);
1671 mService.mWindowManager.prepareAppTransition(prev.task == next.task
1672 ? AppTransition.TRANSIT_ACTIVITY_OPEN
1673 : AppTransition.TRANSIT_TASK_OPEN, false);
1677 mService.mWindowManager.setAppWillBeHidden(prev.appToken);
1678 mService.mWindowManager.setAppVisibility(prev.appToken, false);
1680 } else if (mHistory.size() > 1) {
1681 if (DEBUG_TRANSITION) Slog.v(TAG,
1682 "Prepare open transition: no previous");
1683 if (mNoAnimActivities.contains(next)) {
1685 mService.mWindowManager.prepareAppTransition(
1686 AppTransition.TRANSIT_NONE, false);
1688 mService.mWindowManager.prepareAppTransition(
1689 AppTransition.TRANSIT_ACTIVITY_OPEN, false);
1693 next.applyOptionsLocked();
1695 next.clearOptionsLocked();
1698 if (next.app != null && next.app.thread != null) {
1699 if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
1701 // This activity is now becoming visible.
1702 mService.mWindowManager.setAppVisibility(next.appToken, true);
1704 // schedule launch ticks to collect information about slow apps.
1705 next.startLaunchTickingLocked();
1707 ActivityRecord lastResumedActivity = mResumedActivity;
1708 ActivityState lastState = next.state;
1710 mService.updateCpuStats();
1712 if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + next + " (in existing)");
1713 next.state = ActivityState.RESUMED;
1714 mResumedActivity = next;
1715 next.task.touchActiveTime();
1717 mService.addRecentTaskLocked(next.task);
1719 mService.updateLruProcessLocked(next.app, true);
1720 updateLRUListLocked(next);
1722 // Have the window manager re-evaluate the orientation of
1723 // the screen based on the new activity order.
1724 boolean updated = false;
1726 synchronized (mService) {
1727 Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
1728 mService.mConfiguration,
1729 next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
1730 if (config != null) {
1731 next.frozenBeforeDestroy = true;
1733 updated = mService.updateConfigurationLocked(config, next, false, false);
1737 // The configuration update wasn't able to keep the existing
1738 // instance of the activity, and instead started a new one.
1739 // We should be all done, but let's just make sure our activity
1740 // is still at the top and schedule another run if something
1742 ActivityRecord nextNext = topRunningActivityLocked(null);
1743 if (DEBUG_SWITCH) Slog.i(TAG,
1744 "Activity config changed during resume: " + next
1745 + ", new next: " + nextNext);
1746 if (nextNext != next) {
1748 mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
1751 mService.setFocusedActivityLocked(next);
1753 ensureActivitiesVisibleLocked(null, 0);
1754 mService.mWindowManager.executeAppTransition();
1755 mNoAnimActivities.clear();
1760 // Deliver all pending results.
1761 ArrayList a = next.results;
1763 final int N = a.size();
1764 if (!next.finishing && N > 0) {
1765 if (DEBUG_RESULTS) Slog.v(
1766 TAG, "Delivering results to " + next
1768 next.app.thread.scheduleSendResult(next.appToken, a);
1772 if (next.newIntents != null) {
1773 next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
1776 EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
1777 next.userId, System.identityHashCode(next),
1778 next.task.taskId, next.shortComponentName);
1780 next.sleeping = false;
1781 showAskCompatModeDialogLocked(next);
1782 next.app.pendingUiClean = true;
1783 next.app.thread.scheduleResumeActivity(next.appToken,
1784 mService.isNextTransitionForward());
1786 checkReadyForSleepLocked();
1788 } catch (Exception e) {
1789 // Whoops, need to restart this activity!
1790 if (DEBUG_STATES) Slog.v(TAG, "Resume failed; resetting state to "
1791 + lastState + ": " + next);
1792 next.state = lastState;
1793 mResumedActivity = lastResumedActivity;
1794 Slog.i(TAG, "Restarting because process died: " + next);
1795 if (!next.hasBeenLaunched) {
1796 next.hasBeenLaunched = true;
1798 if (SHOW_APP_STARTING_PREVIEW && mMainStack) {
1799 mService.mWindowManager.setAppStartingWindow(
1800 next.appToken, next.packageName, next.theme,
1801 mService.compatibilityInfoForPackageLocked(
1802 next.info.applicationInfo),
1803 next.nonLocalizedLabel,
1804 next.labelRes, next.icon, next.windowFlags,
1808 startSpecificActivityLocked(next, true, false);
1812 // From this point on, if something goes wrong there is no way
1813 // to recover the activity.
1815 next.visible = true;
1816 completeResumeLocked(next);
1817 } catch (Exception e) {
1818 // If any exception gets thrown, toss away this
1819 // activity and try the next one.
1820 Slog.w(TAG, "Exception thrown during resume of " + next, e);
1821 requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
1822 "resume-exception", true);
1825 next.stopped = false;
1828 // Whoops, need to restart this activity!
1829 if (!next.hasBeenLaunched) {
1830 next.hasBeenLaunched = true;
1832 if (SHOW_APP_STARTING_PREVIEW) {
1833 mService.mWindowManager.setAppStartingWindow(
1834 next.appToken, next.packageName, next.theme,
1835 mService.compatibilityInfoForPackageLocked(
1836 next.info.applicationInfo),
1837 next.nonLocalizedLabel,
1838 next.labelRes, next.icon, next.windowFlags,
1841 if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
1843 startSpecificActivityLocked(next, true, true);
1849 private final void startActivityLocked(ActivityRecord r, boolean newTask,
1850 boolean doResume, boolean keepCurTransition, Bundle options) {
1851 final int NH = mHistory.size();
1856 // If starting in an existing task, find where that is...
1857 boolean startIt = true;
1858 for (int i = NH-1; i >= 0; i--) {
1859 ActivityRecord p = mHistory.get(i);
1863 if (p.task == r.task) {
1864 // Here it is! Now, if this is not yet visible to the
1865 // user, then just add it without starting; it will
1866 // get started when the user navigates back to it.
1869 if (DEBUG_ADD_REMOVE) {
1870 RuntimeException here = new RuntimeException("here");
1871 here.fillInStackTrace();
1872 Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos,
1875 mHistory.add(addPos, r);
1877 mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
1878 r.info.screenOrientation, r.fullscreen,
1879 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
1880 if (VALIDATE_TOKENS) {
1881 validateAppTokensLocked();
1883 ActivityOptions.abort(options);
1894 // Place a new activity at top of stack, so it is next to interact
1900 // If we are not placing the new activity frontmost, we do not want
1901 // to deliver the onUserLeaving callback to the actual frontmost
1904 mUserLeaving = false;
1905 if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
1908 // Slot the activity into the history stack and proceed
1909 if (DEBUG_ADD_REMOVE) {
1910 RuntimeException here = new RuntimeException("here");
1911 here.fillInStackTrace();
1912 Slog.i(TAG, "Adding activity " + r + " to stack at " + addPos, here);
1914 mHistory.add(addPos, r);
1916 r.frontOfTask = newTask;
1918 // We want to show the starting preview window if we are
1919 // switching to a new task, or the next activity's process is
1920 // not currently running.
1921 boolean showStartingIcon = newTask;
1922 ProcessRecord proc = r.app;
1924 proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
1926 if (proc == null || proc.thread == null) {
1927 showStartingIcon = true;
1929 if (DEBUG_TRANSITION) Slog.v(TAG,
1930 "Prepare open transition: starting " + r);
1931 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
1932 mService.mWindowManager.prepareAppTransition(
1933 AppTransition.TRANSIT_NONE, keepCurTransition);
1934 mNoAnimActivities.add(r);
1936 mService.mWindowManager.prepareAppTransition(newTask
1937 ? AppTransition.TRANSIT_TASK_OPEN
1938 : AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
1939 mNoAnimActivities.remove(r);
1941 r.updateOptionsLocked(options);
1942 mService.mWindowManager.addAppToken(
1943 addPos, r.appToken, r.task.taskId, r.info.screenOrientation, r.fullscreen,
1944 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
1945 boolean doShow = true;
1947 // Even though this activity is starting fresh, we still need
1948 // to reset it to make sure we apply affinities to move any
1949 // existing activities from other tasks in to it.
1950 // If the caller has requested that the target task be
1951 // reset, then do so.
1952 if ((r.intent.getFlags()
1953 &Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1954 resetTaskIfNeededLocked(r, r);
1955 doShow = topRunningNonDelayedActivityLocked(null) == r;
1958 if (SHOW_APP_STARTING_PREVIEW && doShow) {
1959 // Figure out if we are transitioning from another activity that is
1960 // "has the same starting icon" as the next one. This allows the
1961 // window manager to keep the previous window it had previously
1962 // created, if it still had one.
1963 ActivityRecord prev = mResumedActivity;
1965 // We don't want to reuse the previous starting preview if:
1966 // (1) The current activity is in a different task.
1967 if (prev.task != r.task) prev = null;
1968 // (2) The current activity is already displayed.
1969 else if (prev.nowVisible) prev = null;
1971 mService.mWindowManager.setAppStartingWindow(
1972 r.appToken, r.packageName, r.theme,
1973 mService.compatibilityInfoForPackageLocked(
1974 r.info.applicationInfo), r.nonLocalizedLabel,
1975 r.labelRes, r.icon, r.windowFlags,
1976 prev != null ? prev.appToken : null, showStartingIcon);
1979 // If this is the first activity, don't do any fancy animations,
1980 // because there is nothing for it to animate on top of.
1981 mService.mWindowManager.addAppToken(addPos, r.appToken, r.task.taskId,
1982 r.info.screenOrientation, r.fullscreen,
1983 (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0);
1984 ActivityOptions.abort(options);
1986 if (VALIDATE_TOKENS) {
1987 validateAppTokensLocked();
1991 resumeTopActivityLocked(null);
1995 final void validateAppTokensLocked() {
1996 mValidateAppTokens.clear();
1997 mValidateAppTokens.ensureCapacity(mHistory.size());
1998 int taskId = Integer.MIN_VALUE;
1999 TaskGroup task = null;
2000 for (int i=0; i<mHistory.size(); i++) {
2001 final ActivityRecord r = mHistory.get(i);
2002 if (taskId != r.task.taskId) {
2003 taskId = r.task.taskId;
2004 task = new TaskGroup();
2005 task.taskId = taskId;
2006 mValidateAppTokens.add(task);
2008 task.tokens.add(r.appToken);
2010 mService.mWindowManager.validateAppTokens(mValidateAppTokens);
2014 * Perform a reset of the given task, if needed as part of launching it.
2015 * Returns the new HistoryRecord at the top of the task.
2017 private final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
2018 ActivityRecord newActivity) {
2019 boolean forceReset = (newActivity.info.flags
2020 &ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
2021 if (ACTIVITY_INACTIVE_RESET_TIME > 0
2022 && taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
2023 if ((newActivity.info.flags
2024 &ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
2029 final TaskRecord task = taskTop.task;
2031 // We are going to move through the history list so that we can look
2032 // at each activity 'target' with 'below' either the interesting
2033 // activity immediately below it in the stack or null.
2034 ActivityRecord target = null;
2037 int replyChainEnd = -1;
2038 int lastReparentPos = -1;
2039 ActivityOptions topOptions = null;
2040 boolean canMoveOptions = true;
2041 for (int i=mHistory.size()-1; i>=-1; i--) {
2042 ActivityRecord below = i >= 0 ? mHistory.get(i) : null;
2044 if (below != null && below.finishing) {
2047 // Don't check any lower in the stack if we're crossing a user boundary.
2048 if (below != null && below.userId != taskTop.userId) {
2051 if (target == null) {
2054 // If we were in the middle of a reply chain before this
2055 // task, it doesn't appear like the root of the chain wants
2056 // anything interesting, so drop it.
2061 final int flags = target.info.flags;
2063 final boolean finishOnTaskLaunch =
2064 (flags&ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
2065 final boolean allowTaskReparenting =
2066 (flags&ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
2068 if (target.task == task) {
2069 // We are inside of the task being reset... we'll either
2070 // finish this activity, push it out for another task,
2071 // or leave it as-is. We only do this
2072 // for activities that are not the root of the task (since
2073 // if we finish the root, we may no longer have the task!).
2077 if (below != null && below.task == task) {
2078 final boolean clearWhenTaskReset =
2079 (target.intent.getFlags()
2080 &Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
2081 if (!finishOnTaskLaunch && !clearWhenTaskReset && target.resultTo != null) {
2082 // If this activity is sending a reply to a previous
2083 // activity, we can't do anything with it now until
2084 // we reach the start of the reply chain.
2085 // XXX note that we are assuming the result is always
2086 // to the previous activity, which is almost always
2087 // the case but we really shouldn't count on.
2088 if (replyChainEnd < 0) {
2089 replyChainEnd = targetI;
2091 } else if (!finishOnTaskLaunch && !clearWhenTaskReset && allowTaskReparenting
2092 && target.taskAffinity != null
2093 && !target.taskAffinity.equals(task.affinity)) {
2094 // If this activity has an affinity for another
2095 // task, then we need to move it out of here. We will
2096 // move it as far out of the way as possible, to the
2097 // bottom of the activity stack. This also keeps it
2098 // correctly ordered with any activities we previously
2100 ActivityRecord p = mHistory.get(0);
2101 if (target.taskAffinity != null
2102 && target.taskAffinity.equals(p.task.affinity)) {
2103 // If the activity currently at the bottom has the
2104 // same task affinity as the one we are moving,
2105 // then merge it into the same task.
2106 target.setTask(p.task, p.thumbHolder, false);
2107 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
2108 + " out to bottom task " + p.task);
2110 mService.mCurTask++;
2111 if (mService.mCurTask <= 0) {
2112 mService.mCurTask = 1;
2114 target.setTask(new TaskRecord(mService.mCurTask, target.info, null),
2116 target.task.affinityIntent = target.intent;
2117 if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
2118 + " out to new task " + target.task);
2120 mService.mWindowManager.setAppGroupId(target.appToken, task.taskId);
2121 if (replyChainEnd < 0) {
2122 replyChainEnd = targetI;
2125 ThumbnailHolder curThumbHolder = target.thumbHolder;
2126 boolean gotOptions = !canMoveOptions;
2127 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
2128 p = mHistory.get(srcPos);
2132 if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
2133 + " out to target's task " + target.task);
2134 p.setTask(target.task, curThumbHolder, false);
2135 curThumbHolder = p.thumbHolder;
2136 canMoveOptions = false;
2137 if (!gotOptions && topOptions == null) {
2138 topOptions = p.takeOptionsLocked();
2139 if (topOptions != null) {
2143 if (DEBUG_ADD_REMOVE) {
2144 RuntimeException here = new RuntimeException("here");
2145 here.fillInStackTrace();
2146 Slog.i(TAG, "Removing and adding activity " + p + " to stack at "
2149 mHistory.remove(srcPos);
2150 mHistory.add(dstPos, p);
2151 mService.mWindowManager.moveAppToken(dstPos, p.appToken);
2152 mService.mWindowManager.setAppGroupId(p.appToken, p.task.taskId);
2154 if (VALIDATE_TOKENS) {
2155 validateAppTokensLocked();
2162 if (taskTopI == replyChainEnd) {
2166 } else if (forceReset || finishOnTaskLaunch
2167 || clearWhenTaskReset) {
2168 // If the activity should just be removed -- either
2169 // because it asks for it, or the task should be
2170 // cleared -- then finish it and anything that is
2171 // part of its reply chain.
2172 if (clearWhenTaskReset) {
2173 // In this case, we want to finish this activity
2174 // and everything above it, so be sneaky and pretend
2175 // like these are all in the reply chain.
2176 replyChainEnd = targetI+1;
2177 while (replyChainEnd < mHistory.size() &&
2179 replyChainEnd)).task == task) {
2183 } else if (replyChainEnd < 0) {
2184 replyChainEnd = targetI;
2186 ActivityRecord p = null;
2187 boolean gotOptions = !canMoveOptions;
2188 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
2189 p = mHistory.get(srcPos);
2193 canMoveOptions = false;
2194 if (!gotOptions && topOptions == null) {
2195 topOptions = p.takeOptionsLocked();
2196 if (topOptions != null) {
2200 if (finishActivityLocked(p, srcPos,
2201 Activity.RESULT_CANCELED, null, "reset", false)) {
2209 if (taskTopI == replyChainEnd) {
2214 // If we were in the middle of a chain, well the
2215 // activity that started it all doesn't want anything
2216 // special, so leave it all as-is.
2220 // Reached the bottom of the task -- any reply chain
2221 // should be left as-is.
2225 } else if (target.resultTo != null && (below == null
2226 || below.task == target.task)) {
2227 // If this activity is sending a reply to a previous
2228 // activity, we can't do anything with it now until
2229 // we reach the start of the reply chain.
2230 // XXX note that we are assuming the result is always
2231 // to the previous activity, which is almost always
2232 // the case but we really shouldn't count on.
2233 if (replyChainEnd < 0) {
2234 replyChainEnd = targetI;
2237 } else if (taskTopI >= 0 && allowTaskReparenting
2238 && task.affinity != null
2239 && task.affinity.equals(target.taskAffinity)) {
2240 // We are inside of another task... if this activity has
2241 // an affinity for our task, then either remove it if we are
2242 // clearing or move it over to our task. Note that
2243 // we currently punt on the case where we are resetting a
2244 // task that is not at the top but who has activities above
2245 // with an affinity to it... this is really not a normal
2246 // case, and we will need to later pull that task to the front
2247 // and usually at that point we will do the reset and pick
2248 // up those remaining activities. (This only happens if
2249 // someone starts an activity in a new task from an activity
2250 // in a task that is not currently on top.)
2251 if (forceReset || finishOnTaskLaunch) {
2252 if (replyChainEnd < 0) {
2253 replyChainEnd = targetI;
2255 ActivityRecord p = null;
2256 if (DEBUG_TASKS) Slog.v(TAG, "Finishing task at index "
2257 + targetI + " to " + replyChainEnd);
2258 for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
2259 p = mHistory.get(srcPos);
2263 if (finishActivityLocked(p, srcPos,
2264 Activity.RESULT_CANCELED, null, "reset", false)) {
2273 if (replyChainEnd < 0) {
2274 replyChainEnd = targetI;
2276 if (DEBUG_TASKS) Slog.v(TAG, "Reparenting task at index "
2277 + targetI + " to " + replyChainEnd);
2278 for (int srcPos=replyChainEnd; srcPos>=targetI; srcPos--) {
2279 ActivityRecord p = mHistory.get(srcPos);
2283 if (lastReparentPos < 0) {
2284 lastReparentPos = taskTopI;
2289 if (DEBUG_ADD_REMOVE) {
2290 RuntimeException here = new RuntimeException("here");
2291 here.fillInStackTrace();
2292 Slog.i(TAG, "Removing and adding activity " + p + " to stack at "
2293 + lastReparentPos, here);
2295 mHistory.remove(srcPos);
2296 p.setTask(task, null, false);
2297 mHistory.add(lastReparentPos, p);
2298 if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
2299 + " from " + srcPos + " to " + lastReparentPos
2300 + " in to resetting task " + task);
2301 mService.mWindowManager.moveAppToken(lastReparentPos, p.appToken);
2302 mService.mWindowManager.setAppGroupId(p.appToken, p.task.taskId);
2303 if (VALIDATE_TOKENS) {
2304 validateAppTokensLocked();
2309 // Now we've moved it in to place... but what if this is
2310 // a singleTop activity and we have put it on top of another
2311 // instance of the same activity? Then we drop the instance
2312 // below so it remains singleTop.
2313 if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
2314 for (int j=lastReparentPos-1; j>=0; j--) {
2315 ActivityRecord p = mHistory.get(j);
2319 if (p.intent.getComponent().equals(target.intent.getComponent())) {
2320 if (finishActivityLocked(p, j,
2321 Activity.RESULT_CANCELED, null, "replace", false)) {
2330 } else if (below != null && below.task != target.task) {
2331 // We hit the botton of a task; the reply chain can't
2340 if (topOptions != null) {
2341 // If we got some ActivityOptions from an activity on top that
2342 // was removed from the task, propagate them to the new real top.
2343 if (taskTop != null) {
2344 taskTop.updateOptionsLocked(topOptions);
2354 * Perform clear operation as requested by
2355 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
2356 * stack to the given task, then look for
2357 * an instance of that activity in the stack and, if found, finish all
2358 * activities on top of it and return the instance.
2360 * @param newR Description of the new activity being started.
2361 * @return Returns the old activity that should be continued to be used,
2362 * or null if none was found.
2364 private final ActivityRecord performClearTaskLocked(int taskId,
2365 ActivityRecord newR, int launchFlags) {
2366 int i = mHistory.size();
2368 // First find the requested task.
2371 ActivityRecord r = mHistory.get(i);
2372 if (r.task.taskId == taskId) {
2381 ActivityRecord r = mHistory.get(i);
2385 if (r.task.taskId != taskId) {
2388 if (r.realActivity.equals(newR.realActivity)) {
2389 // Here it is! Now finish everything in front...
2390 ActivityRecord ret = r;
2391 while (i < (mHistory.size()-1)) {
2393 r = mHistory.get(i);
2394 if (r.task.taskId != taskId) {
2400 ActivityOptions opts = r.takeOptionsLocked();
2402 ret.updateOptionsLocked(opts);
2404 if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2405 null, "clear", false)) {
2410 // Finally, if this is a normal launch mode (that is, not
2411 // expecting onNewIntent()), then we will finish the current
2412 // instance of the activity so a new fresh one can be started.
2413 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
2414 && (launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0) {
2415 if (!ret.finishing) {
2416 int index = indexOfTokenLocked(ret.appToken);
2418 finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
2419 null, "clear", false);
2433 * Completely remove all activities associated with an existing
2434 * task starting at a specified index.
2436 private final void performClearTaskAtIndexLocked(int taskId, int i) {
2437 while (i < mHistory.size()) {
2438 ActivityRecord r = mHistory.get(i);
2439 if (r.task.taskId != taskId) {
2440 // Whoops hit the end.
2447 if (!finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2448 null, "clear", false)) {
2455 * Completely remove all activities associated with an existing task.
2457 private final void performClearTaskLocked(int taskId) {
2458 int i = mHistory.size();
2460 // First find the requested task.
2463 ActivityRecord r = mHistory.get(i);
2464 if (r.task.taskId == taskId) {
2470 // Now find the start and clear it.
2473 ActivityRecord r = mHistory.get(i);
2477 if (r.task.taskId != taskId) {
2478 // We hit the bottom. Now finish it all...
2479 performClearTaskAtIndexLocked(taskId, i+1);
2486 * Find the activity in the history stack within the given task. Returns
2487 * the index within the history at which it's found, or < 0 if not found.
2489 private final int findActivityInHistoryLocked(ActivityRecord r, int task) {
2490 int i = mHistory.size();
2493 ActivityRecord candidate = mHistory.get(i);
2494 if (candidate.finishing) {
2497 if (candidate.task.taskId != task) {
2500 if (candidate.realActivity.equals(r.realActivity)) {
2509 * Reorder the history stack so that the activity at the given index is
2510 * brought to the front.
2512 private final ActivityRecord moveActivityToFrontLocked(int where) {
2513 ActivityRecord newTop = mHistory.remove(where);
2514 int top = mHistory.size();
2515 ActivityRecord oldTop = mHistory.get(top-1);
2516 if (DEBUG_ADD_REMOVE) {
2517 RuntimeException here = new RuntimeException("here");
2518 here.fillInStackTrace();
2519 Slog.i(TAG, "Removing and adding activity " + newTop + " to stack at "
2522 mHistory.add(top, newTop);
2523 oldTop.frontOfTask = false;
2524 newTop.frontOfTask = true;
2528 final int startActivityLocked(IApplicationThread caller,
2529 Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
2530 String resultWho, int requestCode,
2531 int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
2532 boolean componentSpecified, ActivityRecord[] outActivity) {
2534 int err = ActivityManager.START_SUCCESS;
2536 ProcessRecord callerApp = null;
2537 if (caller != null) {
2538 callerApp = mService.getRecordForAppLocked(caller);
2539 if (callerApp != null) {
2540 callingPid = callerApp.pid;
2541 callingUid = callerApp.info.uid;
2543 Slog.w(TAG, "Unable to find app for caller " + caller
2544 + " (pid=" + callingPid + ") when starting: "
2545 + intent.toString());
2546 err = ActivityManager.START_PERMISSION_DENIED;
2550 if (err == ActivityManager.START_SUCCESS) {
2551 final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
2552 Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
2553 + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
2556 ActivityRecord sourceRecord = null;
2557 ActivityRecord resultRecord = null;
2558 if (resultTo != null) {
2559 int index = indexOfTokenLocked(resultTo);
2560 if (DEBUG_RESULTS) Slog.v(
2561 TAG, "Will send result to " + resultTo + " (index " + index + ")");
2563 sourceRecord = mHistory.get(index);
2564 if (requestCode >= 0 && !sourceRecord.finishing) {
2565 resultRecord = sourceRecord;
2570 int launchFlags = intent.getFlags();
2572 if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
2573 && sourceRecord != null) {
2574 // Transfer the result target from the source activity to the new
2575 // one being started, including any failures.
2576 if (requestCode >= 0) {
2577 ActivityOptions.abort(options);
2578 return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
2580 resultRecord = sourceRecord.resultTo;
2581 resultWho = sourceRecord.resultWho;
2582 requestCode = sourceRecord.requestCode;
2583 sourceRecord.resultTo = null;
2584 if (resultRecord != null) {
2585 resultRecord.removeResultsLocked(
2586 sourceRecord, resultWho, requestCode);
2590 if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
2591 // We couldn't find a class that can handle the given Intent.
2592 // That's the end of that!
2593 err = ActivityManager.START_INTENT_NOT_RESOLVED;
2596 if (err == ActivityManager.START_SUCCESS && aInfo == null) {
2597 // We couldn't find the specific class specified in the Intent.
2598 // Also the end of the line.
2599 err = ActivityManager.START_CLASS_NOT_FOUND;
2602 if (err != ActivityManager.START_SUCCESS) {
2603 if (resultRecord != null) {
2604 sendActivityResultLocked(-1,
2605 resultRecord, resultWho, requestCode,
2606 Activity.RESULT_CANCELED, null);
2608 mDismissKeyguardOnNextActivity = false;
2609 ActivityOptions.abort(options);
2613 final int startAnyPerm = mService.checkPermission(
2614 START_ANY_ACTIVITY, callingPid, callingUid);
2615 final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
2616 callingUid, aInfo.applicationInfo.uid, aInfo.exported);
2617 if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
2618 if (resultRecord != null) {
2619 sendActivityResultLocked(-1,
2620 resultRecord, resultWho, requestCode,
2621 Activity.RESULT_CANCELED, null);
2623 mDismissKeyguardOnNextActivity = false;
2625 if (!aInfo.exported) {
2626 msg = "Permission Denial: starting " + intent.toString()
2627 + " from " + callerApp + " (pid=" + callingPid
2628 + ", uid=" + callingUid + ")"
2629 + " not exported from uid " + aInfo.applicationInfo.uid;
2631 msg = "Permission Denial: starting " + intent.toString()
2632 + " from " + callerApp + " (pid=" + callingPid
2633 + ", uid=" + callingUid + ")"
2634 + " requires " + aInfo.permission;
2637 throw new SecurityException(msg);
2641 if (mService.mController != null) {
2642 boolean abort = false;
2644 // The Intent we give to the watcher has the extra data
2645 // stripped off, since it can contain private information.
2646 Intent watchIntent = intent.cloneFilter();
2647 abort = !mService.mController.activityStarting(watchIntent,
2648 aInfo.applicationInfo.packageName);
2649 } catch (RemoteException e) {
2650 mService.mController = null;
2654 if (resultRecord != null) {
2655 sendActivityResultLocked(-1,
2656 resultRecord, resultWho, requestCode,
2657 Activity.RESULT_CANCELED, null);
2659 // We pretend to the caller that it was really started, but
2660 // they will just get a cancel result.
2661 mDismissKeyguardOnNextActivity = false;
2662 ActivityOptions.abort(options);
2663 return ActivityManager.START_SUCCESS;
2668 ActivityRecord r = new ActivityRecord(mService, this, callerApp, callingUid, callingPackage,
2669 intent, resolvedType, aInfo, mService.mConfiguration,
2670 resultRecord, resultWho, requestCode, componentSpecified);
2671 if (outActivity != null) {
2676 if (mResumedActivity == null
2677 || mResumedActivity.info.applicationInfo.uid != callingUid) {
2678 if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
2679 PendingActivityLaunch pal = new PendingActivityLaunch();
2681 pal.sourceRecord = sourceRecord;
2682 pal.startFlags = startFlags;
2683 mService.mPendingActivityLaunches.add(pal);
2684 mDismissKeyguardOnNextActivity = false;
2685 ActivityOptions.abort(options);
2686 return ActivityManager.START_SWITCHES_CANCELED;
2690 if (mService.mDidAppSwitch) {
2691 // This is the second allowed switch since we stopped switches,
2692 // so now just generally allow switches. Use case: user presses
2693 // home (switches disabled, switch to home, mDidAppSwitch now true);
2694 // user taps a home icon (coming from home so allowed, we hit here
2695 // and now allow anyone to switch again).
2696 mService.mAppSwitchesAllowedTime = 0;
2698 mService.mDidAppSwitch = true;
2701 mService.doPendingActivityLaunchesLocked(false);
2704 err = startActivityUncheckedLocked(r, sourceRecord,
2705 startFlags, true, options);
2706 if (mDismissKeyguardOnNextActivity && mPausingActivity == null) {
2707 // Someone asked to have the keyguard dismissed on the next
2708 // activity start, but we are not actually doing an activity
2709 // switch... just dismiss the keyguard now, because we
2710 // probably want to see whatever is behind it.
2711 mDismissKeyguardOnNextActivity = false;
2712 mService.mWindowManager.dismissKeyguard();
2717 final void moveHomeToFrontFromLaunchLocked(int launchFlags) {
2719 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
2720 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
2721 // Caller wants to appear on home activity, so before starting
2722 // their own activity we will bring home to the front.
2723 moveHomeToFrontLocked();
2727 final int startActivityUncheckedLocked(ActivityRecord r,
2728 ActivityRecord sourceRecord, int startFlags, boolean doResume,
2730 final Intent intent = r.intent;
2731 final int callingUid = r.launchedFromUid;
2733 int launchFlags = intent.getFlags();
2735 // We'll invoke onUserLeaving before onPause only if the launching
2736 // activity did not explicitly state that this is an automated launch.
2737 mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
2738 if (DEBUG_USER_LEAVING) Slog.v(TAG,
2739 "startActivity() => mUserLeaving=" + mUserLeaving);
2741 // If the caller has asked not to resume at this point, we make note
2742 // of this in the record so that we can skip it when trying to find
2743 // the top running activity.
2745 r.delayedResume = true;
2748 ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
2751 // If the onlyIfNeeded flag is set, then we can do this if the activity
2752 // being launched is the same as the one making the call... or, as
2753 // a special case, if we do not know the caller then we count the
2754 // current top activity as the caller.
2755 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
2756 ActivityRecord checkedCaller = sourceRecord;
2757 if (checkedCaller == null) {
2758 checkedCaller = topRunningNonDelayedActivityLocked(notTop);
2760 if (!checkedCaller.realActivity.equals(r.realActivity)) {
2761 // Caller is not the same as launcher, so always needed.
2762 startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
2766 if (sourceRecord == null) {
2767 // This activity is not being started from another... in this
2768 // case we -always- start a new task.
2769 if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
2770 Slog.w(TAG, "startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: "
2772 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
2774 } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
2775 // The original activity who is starting us is running as a single
2776 // instance... this new activity it is starting must go on its
2778 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
2779 } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
2780 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
2781 // The activity being started is a single instance... it always
2782 // gets launched into its own task.
2783 launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
2786 if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
2787 // For whatever reason this activity is being launched into a new
2788 // task... yet the caller has requested a result back. Well, that
2789 // is pretty messed up, so instead immediately send back a cancel
2790 // and let the new task continue launched as normal without a
2791 // dependency on its originator.
2792 Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
2793 sendActivityResultLocked(-1,
2794 r.resultTo, r.resultWho, r.requestCode,
2795 Activity.RESULT_CANCELED, null);
2799 boolean addingToTask = false;
2800 boolean movedHome = false;
2801 TaskRecord reuseTask = null;
2802 if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
2803 (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
2804 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
2805 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
2806 // If bring to front is requested, and no result is requested, and
2807 // we can find a task that was started with this same
2808 // component, then instead of launching bring that one to the front.
2809 if (r.resultTo == null) {
2810 // See if there is a task to bring to the front. If this is
2811 // a SINGLE_INSTANCE activity, there can be one and only one
2812 // instance of it in the history, and it is always in its own
2813 // unique task, so we do a special search.
2814 ActivityRecord taskTop = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
2815 ? findTaskLocked(intent, r.info)
2816 : findActivityLocked(intent, r.info);
2817 if (taskTop != null) {
2818 if (taskTop.task.intent == null) {
2819 // This task was started because of movement of
2820 // the activity based on affinity... now that we
2821 // are actually launching it, we can assign the
2823 taskTop.task.setIntent(intent, r.info);
2825 // If the target task is not in the front, then we need
2826 // to bring it to the front... except... well, with
2827 // SINGLE_TASK_LAUNCH it's not entirely clear. We'd like
2828 // to have the same behavior as if a new instance was
2829 // being started, which means not bringing it to the front
2830 // if the caller is not itself in the front.
2831 ActivityRecord curTop = topRunningNonDelayedActivityLocked(notTop);
2832 if (curTop != null && curTop.task != taskTop.task) {
2833 r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
2834 boolean callerAtFront = sourceRecord == null
2835 || curTop.task == sourceRecord.task;
2836 if (callerAtFront) {
2837 // We really do want to push this one into the
2838 // user's face, right now.
2840 moveHomeToFrontFromLaunchLocked(launchFlags);
2841 moveTaskToFrontLocked(taskTop.task, r, options);
2845 // If the caller has requested that the target task be
2846 // reset, then do so.
2847 if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2848 taskTop = resetTaskIfNeededLocked(taskTop, r);
2850 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
2851 // We don't need to start a new activity, and
2852 // the client said not to do anything if that
2853 // is the case, so this is it! And for paranoia, make
2854 // sure we have correctly resumed the top activity.
2856 resumeTopActivityLocked(null, options);
2858 ActivityOptions.abort(options);
2860 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
2863 (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
2864 == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
2865 // The caller has requested to completely replace any
2866 // existing task with its new activity. Well that should
2867 // not be too hard...
2868 reuseTask = taskTop.task;
2869 performClearTaskLocked(taskTop.task.taskId);
2870 reuseTask.setIntent(r.intent, r.info);
2871 } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
2872 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
2873 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
2874 // In this situation we want to remove all activities
2875 // from the task up to the one being started. In most
2876 // cases this means we are resetting the task to its
2878 ActivityRecord top = performClearTaskLocked(
2879 taskTop.task.taskId, r, launchFlags);
2881 if (top.frontOfTask) {
2882 // Activity aliases may mean we use different
2883 // intents for the top activity, so make sure
2884 // the task now has the identity of the new
2886 top.task.setIntent(r.intent, r.info);
2888 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
2889 top.deliverNewIntentLocked(callingUid, r.intent);
2891 // A special case: we need to
2892 // start the activity because it is not currently
2893 // running, and the caller has asked to clear the
2894 // current task to have this activity at the top.
2895 addingToTask = true;
2896 // Now pretend like this activity is being started
2897 // by the top of its task, so it is put in the
2899 sourceRecord = taskTop;
2901 } else if (r.realActivity.equals(taskTop.task.realActivity)) {
2902 // In this case the top activity on the task is the
2903 // same as the one being launched, so we take that
2904 // as a request to bring the task to the foreground.
2905 // If the top activity in the task is the root
2906 // activity, deliver this new intent to it if it
2908 if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
2909 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
2910 && taskTop.realActivity.equals(r.realActivity)) {
2911 logStartActivity(EventLogTags.AM_NEW_INTENT, r, taskTop.task);
2912 if (taskTop.frontOfTask) {
2913 taskTop.task.setIntent(r.intent, r.info);
2915 taskTop.deliverNewIntentLocked(callingUid, r.intent);
2916 } else if (!r.intent.filterEquals(taskTop.task.intent)) {
2917 // In this case we are launching the root activity
2918 // of the task, but with a different intent. We
2919 // should start a new instance on top.
2920 addingToTask = true;
2921 sourceRecord = taskTop;
2923 } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
2924 // In this case an activity is being launched in to an
2925 // existing task, without resetting that task. This
2926 // is typically the situation of launching an activity
2927 // from a notification or shortcut. We want to place
2928 // the new activity on top of the current task.
2929 addingToTask = true;
2930 sourceRecord = taskTop;
2931 } else if (!taskTop.task.rootWasReset) {
2932 // In this case we are launching in to an existing task
2933 // that has not yet been started from its front door.
2934 // The current task has been brought to the front.
2935 // Ideally, we'd probably like to place this new task
2936 // at the bottom of its stack, but that's a little hard
2937 // to do with the current organization of the code so
2938 // for now we'll just drop it.
2939 taskTop.task.setIntent(r.intent, r.info);
2941 if (!addingToTask && reuseTask == null) {
2942 // We didn't do anything... but it was needed (a.k.a., client
2943 // don't use that intent!) And for paranoia, make
2944 // sure we have correctly resumed the top activity.
2946 resumeTopActivityLocked(null, options);
2948 ActivityOptions.abort(options);
2950 return ActivityManager.START_TASK_TO_FRONT;
2956 //String uri = r.intent.toURI();
2957 //Intent intent2 = new Intent(uri);
2958 //Slog.i(TAG, "Given intent: " + r.intent);
2959 //Slog.i(TAG, "URI is: " + uri);
2960 //Slog.i(TAG, "To intent: " + intent2);
2962 if (r.packageName != null) {
2963 // If the activity being launched is the same as the one currently
2964 // at the top, then we need to check if it should only be launched
2966 ActivityRecord top = topRunningNonDelayedActivityLocked(notTop);
2967 if (top != null && r.resultTo == null) {
2968 if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
2969 if (top.app != null && top.app.thread != null) {
2970 if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
2971 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
2972 || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
2973 logStartActivity(EventLogTags.AM_NEW_INTENT, top, top.task);
2974 // For paranoia, make sure we have correctly
2975 // resumed the top activity.
2977 resumeTopActivityLocked(null);
2979 ActivityOptions.abort(options);
2980 if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
2981 // We don't need to start a new activity, and
2982 // the client said not to do anything if that
2983 // is the case, so this is it!
2984 return ActivityManager.START_RETURN_INTENT_TO_CALLER;
2986 top.deliverNewIntentLocked(callingUid, r.intent);
2987 return ActivityManager.START_DELIVERED_TO_TOP;
2994 if (r.resultTo != null) {
2995 sendActivityResultLocked(-1,
2996 r.resultTo, r.resultWho, r.requestCode,
2997 Activity.RESULT_CANCELED, null);
2999 ActivityOptions.abort(options);
3000 return ActivityManager.START_CLASS_NOT_FOUND;
3003 boolean newTask = false;
3004 boolean keepCurTransition = false;
3006 // Should this be considered a new task?
3007 if (r.resultTo == null && !addingToTask
3008 && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
3009 if (reuseTask == null) {
3010 // todo: should do better management of integers.
3011 mService.mCurTask++;
3012 if (mService.mCurTask <= 0) {
3013 mService.mCurTask = 1;
3015 r.setTask(new TaskRecord(mService.mCurTask, r.info, intent), null, true);
3016 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
3017 + " in new task " + r.task);
3019 r.setTask(reuseTask, reuseTask, true);
3023 moveHomeToFrontFromLaunchLocked(launchFlags);
3026 } else if (sourceRecord != null) {
3027 if (!addingToTask &&
3028 (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
3029 // In this case, we are adding the activity to an existing
3030 // task, but the caller has asked to clear that task if the
3031 // activity is already running.
3032 ActivityRecord top = performClearTaskLocked(
3033 sourceRecord.task.taskId, r, launchFlags);
3034 keepCurTransition = true;
3036 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
3037 top.deliverNewIntentLocked(callingUid, r.intent);
3038 // For paranoia, make sure we have correctly
3039 // resumed the top activity.
3041 resumeTopActivityLocked(null);
3043 ActivityOptions.abort(options);
3044 return ActivityManager.START_DELIVERED_TO_TOP;
3046 } else if (!addingToTask &&
3047 (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
3048 // In this case, we are launching an activity in our own task
3049 // that may already be running somewhere in the history, and
3050 // we want to shuffle it to the front of the stack if so.
3051 int where = findActivityInHistoryLocked(r, sourceRecord.task.taskId);
3053 ActivityRecord top = moveActivityToFrontLocked(where);
3054 logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
3055 top.updateOptionsLocked(options);
3056 top.deliverNewIntentLocked(callingUid, r.intent);
3058 resumeTopActivityLocked(null);
3060 return ActivityManager.START_DELIVERED_TO_TOP;
3063 // An existing activity is starting this new activity, so we want
3064 // to keep the new one in the same task as the one that is starting
3066 r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
3067 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
3068 + " in existing task " + r.task);
3071 // This not being started from an existing activity, and not part
3072 // of a new task... just put it in the top task, though these days
3073 // this case should never happen.
3074 final int N = mHistory.size();
3075 ActivityRecord prev =
3076 N > 0 ? mHistory.get(N-1) : null;
3077 r.setTask(prev != null
3079 : new TaskRecord(mService.mCurTask, r.info, intent), null, true);
3080 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
3081 + " in new guessed " + r.task);
3084 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3085 intent, r.getUriPermissionsLocked());
3088 EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
3090 logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
3091 startActivityLocked(r, newTask, doResume, keepCurTransition, options);
3092 return ActivityManager.START_SUCCESS;
3095 ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
3096 String profileFile, ParcelFileDescriptor profileFd, int userId) {
3097 // Collect information about the target of the Intent.
3101 AppGlobals.getPackageManager().resolveIntent(
3102 intent, resolvedType,
3103 PackageManager.MATCH_DEFAULT_ONLY
3104 | ActivityManagerService.STOCK_PM_FLAGS, userId);
3105 aInfo = rInfo != null ? rInfo.activityInfo : null;
3106 } catch (RemoteException e) {
3110 if (aInfo != null) {
3111 // Store the found target back into the intent, because now that
3112 // we have it we never want to do this again. For example, if the
3113 // user navigates back to this point in the history, we should
3114 // always restart the exact same activity.
3115 intent.setComponent(new ComponentName(
3116 aInfo.applicationInfo.packageName, aInfo.name));
3118 // Don't debug things in the system process
3119 if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
3120 if (!aInfo.processName.equals("system")) {
3121 mService.setDebugApp(aInfo.processName, true, false);
3125 if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
3126 if (!aInfo.processName.equals("system")) {
3127 mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
3131 if (profileFile != null) {
3132 if (!aInfo.processName.equals("system")) {
3133 mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
3134 profileFile, profileFd,
3135 (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
3142 final int startActivityMayWait(IApplicationThread caller, int callingUid,
3143 String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
3144 String resultWho, int requestCode, int startFlags, String profileFile,
3145 ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
3146 Bundle options, int userId) {
3147 // Refuse possible leaked file descriptors
3148 if (intent != null && intent.hasFileDescriptors()) {
3149 throw new IllegalArgumentException("File descriptors passed in Intent");
3151 boolean componentSpecified = intent.getComponent() != null;
3153 // Don't modify the client's object!
3154 intent = new Intent(intent);
3156 // Collect information about the target of the Intent.
3157 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
3158 profileFile, profileFd, userId);
3160 synchronized (mService) {
3162 if (callingUid >= 0) {
3164 } else if (caller == null) {
3165 callingPid = Binder.getCallingPid();
3166 callingUid = Binder.getCallingUid();
3168 callingPid = callingUid = -1;
3171 mConfigWillChange = config != null
3172 && mService.mConfiguration.diff(config) != 0;
3173 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3174 "Starting activity when config will change = " + mConfigWillChange);
3176 final long origId = Binder.clearCallingIdentity();
3178 if (mMainStack && aInfo != null &&
3179 (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
3180 // This may be a heavy-weight process! Check to see if we already
3181 // have another, different heavy-weight process running.
3182 if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
3183 if (mService.mHeavyWeightProcess != null &&
3184 (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
3185 !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
3186 int realCallingPid = callingPid;
3187 int realCallingUid = callingUid;
3188 if (caller != null) {
3189 ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
3190 if (callerApp != null) {
3191 realCallingPid = callerApp.pid;
3192 realCallingUid = callerApp.info.uid;
3194 Slog.w(TAG, "Unable to find app for caller " + caller
3195 + " (pid=" + realCallingPid + ") when starting: "
3196 + intent.toString());
3197 ActivityOptions.abort(options);
3198 return ActivityManager.START_PERMISSION_DENIED;
3202 IIntentSender target = mService.getIntentSenderLocked(
3203 ActivityManager.INTENT_SENDER_ACTIVITY, "android",
3204 realCallingUid, userId, null, null, 0, new Intent[] { intent },
3205 new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
3206 | PendingIntent.FLAG_ONE_SHOT, null);
3208 Intent newIntent = new Intent();
3209 if (requestCode >= 0) {
3210 // Caller is requesting a result.
3211 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
3213 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
3214 new IntentSender(target));
3215 if (mService.mHeavyWeightProcess.activities.size() > 0) {
3216 ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
3217 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
3219 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
3222 newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
3224 newIntent.setFlags(intent.getFlags());
3225 newIntent.setClassName("android",
3226 HeavyWeightSwitcherActivity.class.getName());
3228 resolvedType = null;
3230 callingUid = Binder.getCallingUid();
3231 callingPid = Binder.getCallingPid();
3232 componentSpecified = true;
3235 AppGlobals.getPackageManager().resolveIntent(
3237 PackageManager.MATCH_DEFAULT_ONLY
3238 | ActivityManagerService.STOCK_PM_FLAGS, userId);
3239 aInfo = rInfo != null ? rInfo.activityInfo : null;
3240 aInfo = mService.getActivityInfoForUser(aInfo, userId);
3241 } catch (RemoteException e) {
3248 int res = startActivityLocked(caller, intent, resolvedType,
3249 aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
3250 callingPackage, startFlags, options, componentSpecified, null);
3252 if (mConfigWillChange && mMainStack) {
3253 // If the caller also wants to switch to a new configuration,
3254 // do so now. This allows a clean switch, as we are waiting
3255 // for the current activity to pause (so we will not destroy
3256 // it), and have not yet started the next activity.
3257 mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
3258 "updateConfiguration()");
3259 mConfigWillChange = false;
3260 if (DEBUG_CONFIGURATION) Slog.v(TAG,
3261 "Updating to new configuration after starting activity.");
3262 mService.updateConfigurationLocked(config, null, false, false);
3265 Binder.restoreCallingIdentity(origId);
3267 if (outResult != null) {
3268 outResult.result = res;
3269 if (res == ActivityManager.START_SUCCESS) {
3270 mWaitingActivityLaunched.add(outResult);
3274 } catch (InterruptedException e) {
3276 } while (!outResult.timeout && outResult.who == null);
3277 } else if (res == ActivityManager.START_TASK_TO_FRONT) {
3278 ActivityRecord r = this.topRunningActivityLocked(null);
3280 outResult.timeout = false;
3281 outResult.who = new ComponentName(r.info.packageName, r.info.name);
3282 outResult.totalTime = 0;
3283 outResult.thisTime = 0;
3285 outResult.thisTime = SystemClock.uptimeMillis();
3286 mWaitingActivityVisible.add(outResult);
3290 } catch (InterruptedException e) {
3292 } while (!outResult.timeout && outResult.who == null);
3301 final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
3302 Intent[] intents, String[] resolvedTypes, IBinder resultTo,
3303 Bundle options, int userId) {
3304 if (intents == null) {
3305 throw new NullPointerException("intents is null");
3307 if (resolvedTypes == null) {
3308 throw new NullPointerException("resolvedTypes is null");
3310 if (intents.length != resolvedTypes.length) {
3311 throw new IllegalArgumentException("intents are length different than resolvedTypes");
3314 ActivityRecord[] outActivity = new ActivityRecord[1];
3317 if (callingUid >= 0) {
3319 } else if (caller == null) {
3320 callingPid = Binder.getCallingPid();
3321 callingUid = Binder.getCallingUid();
3323 callingPid = callingUid = -1;
3325 final long origId = Binder.clearCallingIdentity();
3327 synchronized (mService) {
3329 for (int i=0; i<intents.length; i++) {
3330 Intent intent = intents[i];
3331 if (intent == null) {
3335 // Refuse possible leaked file descriptors
3336 if (intent != null && intent.hasFileDescriptors()) {
3337 throw new IllegalArgumentException("File descriptors passed in Intent");
3340 boolean componentSpecified = intent.getComponent() != null;
3342 // Don't modify the client's object!
3343 intent = new Intent(intent);
3345 // Collect information about the target of the Intent.
3346 ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
3347 0, null, null, userId);
3348 // TODO: New, check if this is correct
3349 aInfo = mService.getActivityInfoForUser(aInfo, userId);
3351 if (mMainStack && aInfo != null && (aInfo.applicationInfo.flags
3352 & ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
3353 throw new IllegalArgumentException(
3354 "FLAG_CANT_SAVE_STATE not supported here");
3357 Bundle theseOptions;
3358 if (options != null && i == intents.length-1) {
3359 theseOptions = options;
3361 theseOptions = null;
3363 int res = startActivityLocked(caller, intent, resolvedTypes[i],
3364 aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
3365 0, theseOptions, componentSpecified, outActivity);
3370 resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
3374 Binder.restoreCallingIdentity(origId);
3377 return ActivityManager.START_SUCCESS;
3380 void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
3381 long thisTime, long totalTime) {
3382 for (int i=mWaitingActivityLaunched.size()-1; i>=0; i--) {
3383 WaitResult w = mWaitingActivityLaunched.get(i);
3384 w.timeout = timeout;
3386 w.who = new ComponentName(r.info.packageName, r.info.name);
3388 w.thisTime = thisTime;
3389 w.totalTime = totalTime;
3391 mService.notifyAll();
3394 void reportActivityVisibleLocked(ActivityRecord r) {
3395 for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3396 WaitResult w = mWaitingActivityVisible.get(i);
3399 w.who = new ComponentName(r.info.packageName, r.info.name);
3401 w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3402 w.thisTime = w.totalTime;
3404 mService.notifyAll();
3406 if (mDismissKeyguardOnNextActivity) {
3407 mDismissKeyguardOnNextActivity = false;
3408 mService.mWindowManager.dismissKeyguard();
3412 void sendActivityResultLocked(int callingUid, ActivityRecord r,
3413 String resultWho, int requestCode, int resultCode, Intent data) {
3415 if (callingUid > 0) {
3416 mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3417 data, r.getUriPermissionsLocked());
3420 if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
3421 + " : who=" + resultWho + " req=" + requestCode
3422 + " res=" + resultCode + " data=" + data);
3423 if (mResumedActivity == r && r.app != null && r.app.thread != null) {
3425 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
3426 list.add(new ResultInfo(resultWho, requestCode,
3428 r.app.thread.scheduleSendResult(r.appToken, list);
3430 } catch (Exception e) {
3431 Slog.w(TAG, "Exception thrown sending result to " + r, e);
3435 r.addResultLocked(null, resultWho, requestCode, resultCode, data);
3438 private final void stopActivityLocked(ActivityRecord r) {
3439 if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
3440 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
3441 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
3443 if (!mService.mSleeping) {
3445 Slog.d(TAG, "no-history finish of " + r);
3447 requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
3448 "no-history", false);
3450 if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r
3451 + " on stop because we're just sleeping");
3456 if (r.app != null && r.app.thread != null) {
3458 if (mService.mFocusedActivity == r) {
3459 mService.setFocusedActivityLocked(topRunningActivityLocked(null));
3462 r.resumeKeyDispatchingLocked();
3465 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
3466 + " (stop requested)");
3467 r.state = ActivityState.STOPPING;
3468 if (DEBUG_VISBILITY) Slog.v(
3469 TAG, "Stopping visible=" + r.visible + " for " + r);
3471 mService.mWindowManager.setAppVisibility(r.appToken, false);
3473 r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
3474 if (mService.isSleeping()) {
3475 r.setSleeping(true);
3477 Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG);
3479 mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
3480 } catch (Exception e) {
3481 // Maybe just ignore exceptions here... if the process
3482 // has crashed, our death notification will clean things
3484 Slog.w(TAG, "Exception thrown during pause", e);
3485 // Just in case, assume it to be stopped.
3487 if (DEBUG_STATES) Slog.v(TAG, "Stop failed; moving to STOPPED: " + r);
3488 r.state = ActivityState.STOPPED;
3489 if (r.configDestroy) {
3490 destroyActivityLocked(r, true, false, "stop-except");
3496 final ArrayList<ActivityRecord> processStoppingActivitiesLocked(
3498 int N = mStoppingActivities.size();
3499 if (N <= 0) return null;
3501 ArrayList<ActivityRecord> stops = null;
3503 final boolean nowVisible = mResumedActivity != null
3504 && mResumedActivity.nowVisible
3505 && !mResumedActivity.waitingVisible;
3506 for (int i=0; i<N; i++) {
3507 ActivityRecord s = mStoppingActivities.get(i);
3508 if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
3509 + nowVisible + " waitingVisible=" + s.waitingVisible
3510 + " finishing=" + s.finishing);
3511 if (s.waitingVisible && nowVisible) {
3512 mWaitingVisibleActivities.remove(s);
3513 s.waitingVisible = false;
3515 // If this activity is finishing, it is sitting on top of
3516 // everyone else but we now know it is no longer needed...
3517 // so get rid of it. Otherwise, we need to go through the
3518 // normal flow and hide it once we determine that it is
3519 // hidden by the activities in front of it.
3520 if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
3521 mService.mWindowManager.setAppVisibility(s.appToken, false);
3524 if ((!s.waitingVisible || mService.isSleeping()) && remove) {
3525 if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
3526 if (stops == null) {
3527 stops = new ArrayList<ActivityRecord>();
3530 mStoppingActivities.remove(i);
3539 final void scheduleIdleLocked() {
3540 Message msg = Message.obtain();
3541 msg.what = IDLE_NOW_MSG;
3542 mHandler.sendMessage(msg);
3545 final ActivityRecord activityIdleInternal(IBinder token, boolean fromTimeout,
3546 Configuration config) {
3547 if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
3549 ActivityRecord res = null;
3551 ArrayList<ActivityRecord> stops = null;
3552 ArrayList<ActivityRecord> finishes = null;
3553 ArrayList<ActivityRecord> thumbnails = null;
3554 ArrayList<UserStartedState> startingUsers = null;
3558 IApplicationThread sendThumbnail = null;
3559 boolean booting = false;
3560 boolean enableScreen = false;
3561 boolean activityRemoved = false;
3563 synchronized (mService) {
3564 ActivityRecord r = ActivityRecord.forToken(token);
3566 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
3567 r.finishLaunchTickingLocked();
3570 // Get the activity record.
3571 int index = indexOfActivityLocked(r);
3576 reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
3579 // This is a hack to semi-deal with a race condition
3580 // in the client where it can be constructed with a
3581 // newer configuration from when we asked it to launch.
3582 // We'll update with whatever configuration it now says
3583 // it used to launch.
3584 if (config != null) {
3585 r.configuration = config;
3588 // No longer need to keep the device awake.
3589 if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
3590 mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
3591 mLaunchingActivity.release();
3594 // We are now idle. If someone is waiting for a thumbnail from
3595 // us, we can now deliver.
3597 mService.scheduleAppGcsLocked();
3598 if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
3599 sendThumbnail = r.app.thread;
3600 r.thumbnailNeeded = false;
3603 // If this activity is fullscreen, set up to hide those under it.
3605 if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
3606 ensureActivitiesVisibleLocked(null, 0);
3608 //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
3610 if (!mService.mBooted) {
3611 mService.mBooted = true;
3612 enableScreen = true;
3616 } else if (fromTimeout) {
3617 reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
3620 // Atomically retrieve all of the other things to do.
3621 stops = processStoppingActivitiesLocked(true);
3622 NS = stops != null ? stops.size() : 0;
3623 if ((NF=mFinishingActivities.size()) > 0) {
3624 finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
3625 mFinishingActivities.clear();
3627 if ((NT=mCancelledThumbnails.size()) > 0) {
3628 thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
3629 mCancelledThumbnails.clear();
3633 booting = mService.mBooting;
3634 mService.mBooting = false;
3636 if (mStartingUsers.size() > 0) {
3637 startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
3638 mStartingUsers.clear();
3644 // Send thumbnail if requested.
3645 if (sendThumbnail != null) {
3647 sendThumbnail.requestThumbnail(token);
3648 } catch (Exception e) {
3649 Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
3650 mService.sendPendingThumbnail(null, token, null, null, true);
3654 // Stop any activities that are scheduled to do so but have been
3655 // waiting for the next one to start.
3656 for (i=0; i<NS; i++) {
3657 ActivityRecord r = (ActivityRecord)stops.get(i);
3658 synchronized (mService) {
3660 finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
3662 stopActivityLocked(r);
3667 // Finish any activities that are scheduled to do so but have been
3668 // waiting for the next one to start.
3669 for (i=0; i<NF; i++) {
3670 ActivityRecord r = (ActivityRecord)finishes.get(i);
3671 synchronized (mService) {
3672 activityRemoved = destroyActivityLocked(r, true, false, "finish-idle");
3676 // Report back to any thumbnail receivers.
3677 for (i=0; i<NT; i++) {
3678 ActivityRecord r = (ActivityRecord)thumbnails.get(i);
3679 mService.sendPendingThumbnail(r, null, null, null, true);
3683 mService.finishBooting();
3684 } else if (startingUsers != null) {
3685 for (i=0; i<startingUsers.size(); i++) {
3686 mService.finishUserSwitch(startingUsers.get(i));
3690 mService.trimApplications();
3692 //mWindowManager.dump();
3695 mService.enableScreenAfterBoot();
3698 if (activityRemoved) {
3699 resumeTopActivityLocked(null);
3706 * @return Returns true if the activity is being finished, false if for
3707 * some reason it is being left as-is.
3709 final boolean requestFinishActivityLocked(IBinder token, int resultCode,
3710 Intent resultData, String reason, boolean oomAdj) {
3711 int index = indexOfTokenLocked(token);
3712 if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(
3713 TAG, "Finishing activity @" + index + ": token=" + token
3714 + ", result=" + resultCode + ", data=" + resultData
3715 + ", reason=" + reason);
3719 ActivityRecord r = mHistory.get(index);
3721 finishActivityLocked(r, index, resultCode, resultData, reason, oomAdj);
3725 final void finishSubActivityLocked(IBinder token, String resultWho, int requestCode) {
3726 ActivityRecord self = isInStackLocked(token);
3732 for (i=mHistory.size()-1; i>=0; i--) {
3733 ActivityRecord r = (ActivityRecord)mHistory.get(i);
3734 if (r.resultTo == self && r.requestCode == requestCode) {
3735 if ((r.resultWho == null && resultWho == null) ||
3736 (r.resultWho != null && r.resultWho.equals(resultWho))) {
3737 finishActivityLocked(r, i,
3738 Activity.RESULT_CANCELED, null, "request-sub", false);
3742 mService.updateOomAdjLocked();
3745 final boolean finishActivityAffinityLocked(IBinder token) {
3746 int index = indexOfTokenLocked(token);
3747 if (DEBUG_RESULTS) Slog.v(
3748 TAG, "Finishing activity affinity @" + index + ": token=" + token);
3752 ActivityRecord r = mHistory.get(index);
3754 while (index >= 0) {
3755 ActivityRecord cur = mHistory.get(index);
3756 if (cur.task != r.task) {
3759 if (cur.taskAffinity == null && r.taskAffinity != null) {
3762 if (cur.taskAffinity != null && !cur.taskAffinity.equals(r.taskAffinity)) {
3765 finishActivityLocked(cur, index, Activity.RESULT_CANCELED, null,
3766 "request-affinity", true);
3772 final void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
3774 ActivityRecord resultTo = r.resultTo;
3775 if (resultTo != null) {
3776 if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
3777 + " who=" + r.resultWho + " req=" + r.requestCode
3778 + " res=" + resultCode + " data=" + resultData);
3779 if (r.info.applicationInfo.uid > 0) {
3780 mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
3781 resultTo.packageName, resultData,
3782 resultTo.getUriPermissionsLocked());
3784 resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
3788 else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
3790 // Make sure this HistoryRecord is not holding on to other resources,
3791 // because clients have remote IPC references to this object so we
3792 // can't assume that will go away and want to avoid circular IPC refs.
3794 r.pendingResults = null;
3795 r.newIntents = null;
3800 * @return Returns true if this activity has been removed from the history
3801 * list, or false if it is still in the list and will be removed later.
3803 final boolean finishActivityLocked(ActivityRecord r, int index,
3804 int resultCode, Intent resultData, String reason, boolean oomAdj) {
3805 return finishActivityLocked(r, index, resultCode, resultData, reason, false, oomAdj);
3809 * @return Returns true if this activity has been removed from the history
3810 * list, or false if it is still in the list and will be removed later.
3812 final boolean finishActivityLocked(ActivityRecord r, int index, int resultCode,
3813 Intent resultData, String reason, boolean immediate, boolean oomAdj) {
3815 Slog.w(TAG, "Duplicate finish request for " + r);
3820 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
3821 r.userId, System.identityHashCode(r),
3822 r.task.taskId, r.shortComponentName, reason);
3823 if (index < (mHistory.size()-1)) {
3824 ActivityRecord next = mHistory.get(index+1);
3825 if (next.task == r.task) {
3826 if (r.frontOfTask) {
3827 // The next activity is now the front of the task.
3828 next.frontOfTask = true;
3830 if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
3831 // If the caller asked that this activity (and all above it)
3832 // be cleared when the task is reset, don't lose that information,
3833 // but propagate it up to the next activity.
3834 next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
3839 r.pauseKeyDispatchingLocked();
3841 if (mService.mFocusedActivity == r) {
3842 mService.setFocusedActivityLocked(topRunningActivityLocked(null));
3846 finishActivityResultsLocked(r, resultCode, resultData);
3848 if (mService.mPendingThumbnails.size() > 0) {
3849 // There are clients waiting to receive thumbnails so, in case
3850 // this is an activity that someone is waiting for, add it
3851 // to the pending list so we can correctly update the clients.
3852 mCancelledThumbnails.add(r);
3856 return finishCurrentActivityLocked(r, index,
3857 FINISH_IMMEDIATELY, oomAdj) == null;
3858 } else if (mResumedActivity == r) {
3859 boolean endTask = index <= 0
3860 || (mHistory.get(index-1)).task != r.task;
3861 if (DEBUG_TRANSITION) Slog.v(TAG,
3862 "Prepare close transition: finishing " + r);
3863 mService.mWindowManager.prepareAppTransition(endTask
3864 ? AppTransition.TRANSIT_TASK_CLOSE
3865 : AppTransition.TRANSIT_ACTIVITY_CLOSE, false);
3867 // Tell window manager to prepare for this one to be removed.
3868 mService.mWindowManager.setAppVisibility(r.appToken, false);
3870 if (mPausingActivity == null) {
3871 if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
3872 if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
3873 startPausingLocked(false, false);
3876 } else if (r.state != ActivityState.PAUSING) {
3877 // If the activity is PAUSING, we will complete the finish once
3878 // it is done pausing; else we can just directly finish it here.
3879 if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
3880 return finishCurrentActivityLocked(r, index,
3881 FINISH_AFTER_PAUSE, oomAdj) == null;
3883 if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
3889 private static final int FINISH_IMMEDIATELY = 0;
3890 private static final int FINISH_AFTER_PAUSE = 1;
3891 private static final int FINISH_AFTER_VISIBLE = 2;
3893 private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
3894 int mode, boolean oomAdj) {
3895 final int index = indexOfActivityLocked(r);
3900 return finishCurrentActivityLocked(r, index, mode, oomAdj);
3903 private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
3904 int index, int mode, boolean oomAdj) {
3905 // First things first: if this activity is currently visible,
3906 // and the resumed activity is not yet visible, then hold off on
3907 // finishing until the resumed one becomes visible.
3908 if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
3909 if (!mStoppingActivities.contains(r)) {
3910 mStoppingActivities.add(r);
3911 if (mStoppingActivities.size() > 3) {
3912 // If we already have a few activities waiting to stop,
3913 // then give up on things going idle and start clearing
3915 scheduleIdleLocked();
3917 checkReadyForSleepLocked();
3920 if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
3921 + " (finish requested)");
3922 r.state = ActivityState.STOPPING;
3924 mService.updateOomAdjLocked();
3929 // make sure the record is cleaned out of other places.
3930 mStoppingActivities.remove(r);
3931 mGoingToSleepActivities.remove(r);
3932 mWaitingVisibleActivities.remove(r);
3933 if (mResumedActivity == r) {
3934 mResumedActivity = null;
3936 final ActivityState prevState = r.state;
3937 if (DEBUG_STATES) Slog.v(TAG, "Moving to FINISHING: " + r);
3938 r.state = ActivityState.FINISHING;
3940 if (mode == FINISH_IMMEDIATELY
3941 || prevState == ActivityState.STOPPED
3942 || prevState == ActivityState.INITIALIZING) {
3943 // If this activity is already stopped, we can just finish
3945 boolean activityRemoved = destroyActivityLocked(r, true,
3946 oomAdj, "finish-imm");
3947 if (activityRemoved) {
3948 resumeTopActivityLocked(null);
3950 return activityRemoved ? null : r;
3952 // Need to go through the full pause cycle to get this
3953 // activity into the stopped state and then finish it.
3954 if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
3955 mFinishingActivities.add(r);
3956 resumeTopActivityLocked(null);
3962 * Perform the common clean-up of an activity record. This is called both
3963 * as part of destroyActivityLocked() (when destroying the client-side
3964 * representation) and cleaning things up as a result of its hosting
3965 * processing going away, in which case there is no remaining client-side
3966 * state to destroy so only the cleanup here is needed.
3968 final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices,
3970 if (mResumedActivity == r) {
3971 mResumedActivity = null;
3973 if (mService.mFocusedActivity == r) {
3974 mService.mFocusedActivity = null;
3977 r.configDestroy = false;
3978 r.frozenBeforeDestroy = false;
3981 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (cleaning up)");
3982 r.state = ActivityState.DESTROYED;
3983 if (DEBUG_APP) Slog.v(TAG, "Clearing app during cleanUp for activity " + r);
3987 // Make sure this record is no longer in the pending finishes list.
3988 // This could happen, for example, if we are trimming activities
3989 // down to the max limit while they are still waiting to finish.
3990 mFinishingActivities.remove(r);
3991 mWaitingVisibleActivities.remove(r);
3993 // Remove any pending results.
3994 if (r.finishing && r.pendingResults != null) {
3995 for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
3996 PendingIntentRecord rec = apr.get();
3998 mService.cancelIntentSenderLocked(rec, false);
4001 r.pendingResults = null;
4004 if (cleanServices) {
4005 cleanUpActivityServicesLocked(r);
4008 if (mService.mPendingThumbnails.size() > 0) {
4009 // There are clients waiting to receive thumbnails so, in case
4010 // this is an activity that someone is waiting for, add it
4011 // to the pending list so we can correctly update the clients.
4012 mCancelledThumbnails.add(r);
4015 // Get rid of any pending idle timeouts.
4016 removeTimeoutsForActivityLocked(r);
4019 private void removeTimeoutsForActivityLocked(ActivityRecord r) {
4020 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4021 mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
4022 mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
4023 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
4024 r.finishLaunchTickingLocked();
4027 final void removeActivityFromHistoryLocked(ActivityRecord r) {
4028 finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
4030 if (DEBUG_ADD_REMOVE) {
4031 RuntimeException here = new RuntimeException("here");
4032 here.fillInStackTrace();
4033 Slog.i(TAG, "Removing activity " + r + " from stack");
4036 r.takeFromHistory();
4037 removeTimeoutsForActivityLocked(r);
4038 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
4039 + " (removed from history)");
4040 r.state = ActivityState.DESTROYED;
4041 if (DEBUG_APP) Slog.v(TAG, "Clearing app during remove for activity " + r);
4043 mService.mWindowManager.removeAppToken(r.appToken);
4044 if (VALIDATE_TOKENS) {
4045 validateAppTokensLocked();
4047 cleanUpActivityServicesLocked(r);
4048 r.removeUriPermissionsLocked();
4052 * Perform clean-up of service connections in an activity record.
4054 final void cleanUpActivityServicesLocked(ActivityRecord r) {
4055 // Throw away any services that have been bound by this activity.
4056 if (r.connections != null) {
4057 Iterator<ConnectionRecord> it = r.connections.iterator();
4058 while (it.hasNext()) {
4059 ConnectionRecord c = it.next();
4060 mService.mServices.removeConnectionLocked(c, null, r);
4062 r.connections = null;
4066 final void scheduleDestroyActivities(ProcessRecord owner, boolean oomAdj, String reason) {
4067 Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG);
4068 msg.obj = new ScheduleDestroyArgs(owner, oomAdj, reason);
4069 mHandler.sendMessage(msg);
4072 final void destroyActivitiesLocked(ProcessRecord owner, boolean oomAdj, String reason) {
4073 boolean lastIsOpaque = false;
4074 boolean activityRemoved = false;
4075 for (int i=mHistory.size()-1; i>=0; i--) {
4076 ActivityRecord r = mHistory.get(i);
4081 lastIsOpaque = true;
4083 if (owner != null && r.app != owner) {
4086 if (!lastIsOpaque) {
4089 // We can destroy this one if we have its icicle saved and
4090 // it is not in the process of pausing/stopping/finishing.
4091 if (r.app != null && r != mResumedActivity && r != mPausingActivity
4092 && r.haveState && !r.visible && r.stopped
4093 && r.state != ActivityState.DESTROYING
4094 && r.state != ActivityState.DESTROYED) {
4095 if (DEBUG_SWITCH) Slog.v(TAG, "Destroying " + r + " in state " + r.state
4096 + " resumed=" + mResumedActivity
4097 + " pausing=" + mPausingActivity);
4098 if (destroyActivityLocked(r, true, oomAdj, reason)) {
4099 activityRemoved = true;
4103 if (activityRemoved) {
4104 resumeTopActivityLocked(null);
4109 * Destroy the current CLIENT SIDE instance of an activity. This may be
4110 * called both when actually finishing an activity, or when performing
4111 * a configuration switch where we destroy the current client-side object
4112 * but then create a new client-side object for this same HistoryRecord.
4114 final boolean destroyActivityLocked(ActivityRecord r,
4115 boolean removeFromApp, boolean oomAdj, String reason) {
4116 if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(
4117 TAG, "Removing activity from " + reason + ": token=" + r
4118 + ", app=" + (r.app != null ? r.app.processName : "(null)"));
4119 EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
4120 r.userId, System.identityHashCode(r),
4121 r.task.taskId, r.shortComponentName, reason);
4123 boolean removedFromHistory = false;
4125 cleanUpActivityLocked(r, false, false);
4127 final boolean hadApp = r.app != null;
4130 if (removeFromApp) {
4131 int idx = r.app.activities.indexOf(r);
4133 r.app.activities.remove(idx);
4135 if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
4136 mService.mHeavyWeightProcess = null;
4137 mService.mHandler.sendEmptyMessage(
4138 ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
4140 if (r.app.activities.size() == 0) {
4141 // No longer have activities, so update oom adj.
4142 mService.updateOomAdjLocked();
4146 boolean skipDestroy = false;
4149 if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
4150 r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
4151 r.configChangeFlags);
4152 } catch (Exception e) {
4153 // We can just ignore exceptions here... if the process
4154 // has crashed, our death notification will clean things
4156 //Slog.w(TAG, "Exception thrown during finish", e);
4158 removeActivityFromHistoryLocked(r);
4159 removedFromHistory = true;
4164 r.nowVisible = false;
4166 // If the activity is finishing, we need to wait on removing it
4167 // from the list to give it a chance to do its cleanup. During
4168 // that time it may make calls back with its token so we need to
4169 // be able to find it on the list and so we don't want to remove
4170 // it from the list yet. Otherwise, we can just immediately put
4171 // it in the destroyed state since we are not removing it from the
4173 if (r.finishing && !skipDestroy) {
4174 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYING: " + r
4175 + " (destroy requested)");
4176 r.state = ActivityState.DESTROYING;
4177 Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG);
4179 mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4181 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
4182 + " (destroy skipped)");
4183 r.state = ActivityState.DESTROYED;
4184 if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r);
4188 // remove this record from the history.
4190 removeActivityFromHistoryLocked(r);
4191 removedFromHistory = true;
4193 if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
4195 r.state = ActivityState.DESTROYED;
4196 if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r);
4201 r.configChangeFlags = 0;
4203 if (!mLRUActivities.remove(r) && hadApp) {
4204 Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
4207 return removedFromHistory;
4210 final void activityDestroyed(IBinder token) {
4211 synchronized (mService) {
4212 final long origId = Binder.clearCallingIdentity();
4214 ActivityRecord r = ActivityRecord.forToken(token);
4216 mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
4219 int index = indexOfActivityLocked(r);
4221 if (r.state == ActivityState.DESTROYING) {
4222 cleanUpActivityLocked(r, true, false);
4223 removeActivityFromHistoryLocked(r);
4226 resumeTopActivityLocked(null);
4228 Binder.restoreCallingIdentity(origId);
4233 private void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app,
4235 int i = list.size();
4236 if (DEBUG_CLEANUP) Slog.v(
4237 TAG, "Removing app " + app + " from list " + listName
4238 + " with " + i + " entries");
4241 ActivityRecord r = (ActivityRecord)list.get(i);
4242 if (DEBUG_CLEANUP) Slog.v(TAG, "Record #" + i + " " + r);
4244 if (DEBUG_CLEANUP) Slog.v(TAG, "---> REMOVING this entry!");
4246 removeTimeoutsForActivityLocked(r);
4251 boolean removeHistoryRecordsForAppLocked(ProcessRecord app) {
4252 removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities");
4253 removeHistoryRecordsForAppLocked(mStoppingActivities, app, "mStoppingActivities");
4254 removeHistoryRecordsForAppLocked(mGoingToSleepActivities, app, "mGoingToSleepActivities");
4255 removeHistoryRecordsForAppLocked(mWaitingVisibleActivities, app,
4256 "mWaitingVisibleActivities");
4257 removeHistoryRecordsForAppLocked(mFinishingActivities, app, "mFinishingActivities");
4259 boolean hasVisibleActivities = false;
4261 // Clean out the history list.
4262 int i = mHistory.size();
4263 if (DEBUG_CLEANUP) Slog.v(
4264 TAG, "Removing app " + app + " from history with " + i + " entries");
4267 ActivityRecord r = (ActivityRecord)mHistory.get(i);
4268 if (DEBUG_CLEANUP) Slog.v(
4269 TAG, "Record #" + i + " " + r + ": app=" + r.app);
4272 if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
4273 // Don't currently have state for the activity, or
4274 // it is finishing -- always remove it.
4276 } else if (r.launchCount > 2 &&
4277 r.lastLaunchTime > (SystemClock.uptimeMillis()-60000)) {
4278 // We have launched this activity too many times since it was
4279 // able to run, so give up and remove it.
4282 // The process may be gone, but the activity lives on!
4286 if (ActivityStack.DEBUG_ADD_REMOVE || DEBUG_CLEANUP) {
4287 RuntimeException here = new RuntimeException("here");
4288 here.fillInStackTrace();
4289 Slog.i(TAG, "Removing activity " + r + " from stack at " + i
4290 + ": haveState=" + r.haveState
4291 + " stateNotNeeded=" + r.stateNotNeeded
4292 + " finishing=" + r.finishing
4293 + " state=" + r.state, here);
4296 Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
4297 EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
4298 r.userId, System.identityHashCode(r),
4299 r.task.taskId, r.shortComponentName,
4300 "proc died without state saved");
4302 removeActivityFromHistoryLocked(r);
4305 // We have the current state for this activity, so
4306 // it can be restarted later when needed.
4307 if (localLOGV) Slog.v(
4308 TAG, "Keeping entry, setting app to null");
4310 hasVisibleActivities = true;
4312 if (DEBUG_APP) Slog.v(TAG, "Clearing app during removeHistory for activity "
4315 r.nowVisible = false;
4317 if (ActivityStack.DEBUG_SAVED_STATE) Slog.i(TAG,
4318 "App died, clearing saved state of " + r);
4323 r.stack.cleanUpActivityLocked(r, true, true);
4327 return hasVisibleActivities;
4331 * Move the current home activity's task (if one exists) to the front
4334 final void moveHomeToFrontLocked() {
4335 TaskRecord homeTask = null;
4336 for (int i=mHistory.size()-1; i>=0; i--) {
4337 ActivityRecord hr = mHistory.get(i);
4338 if (hr.isHomeActivity) {
4343 if (homeTask != null) {
4344 moveTaskToFrontLocked(homeTask, null, null);
4348 final void updateTransitLocked(int transit, Bundle options) {
4349 if (options != null) {
4350 ActivityRecord r = topRunningActivityLocked(null);
4351 if (r != null && r.state != ActivityState.RESUMED) {
4352 r.updateOptionsLocked(options);
4354 ActivityOptions.abort(options);
4357 mService.mWindowManager.prepareAppTransition(transit, false);
4360 final boolean findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
4361 for (int i = mHistory.size() - 1; i >= 0; i--) {
4362 ActivityRecord hr = mHistory.get(i);
4363 if (hr.task.taskId == taskId) {
4364 if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
4365 mUserLeaving = true;
4367 if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
4368 // Caller wants the home activity moved with it. To accomplish this,
4369 // we'll just move the home task to the top first.
4370 moveHomeToFrontLocked();
4372 moveTaskToFrontLocked(hr.task, null, options);
4379 final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
4380 if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
4382 final int task = tr.taskId;
4383 int top = mHistory.size()-1;
4385 if (top < 0 || (mHistory.get(top)).task.taskId == task) {
4387 if (reason != null &&
4388 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
4389 ActivityOptions.abort(options);
4391 updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
4396 ArrayList<IBinder> moved = new ArrayList<IBinder>();
4398 // Applying the affinities may have removed entries from the history,
4399 // so get the size again.
4400 top = mHistory.size()-1;
4403 // Shift all activities with this task up to the top
4404 // of the stack, keeping them in the same internal order.
4406 ActivityRecord r = mHistory.get(pos);
4407 if (localLOGV) Slog.v(
4408 TAG, "At " + pos + " ckp " + r.task + ": " + r);
4409 if (r.task.taskId == task) {
4410 if (localLOGV) Slog.v(TAG, "Removing and adding at " + top);
4411 if (DEBUG_ADD_REMOVE) {
4412 RuntimeException here = new RuntimeException("here");
4413 here.fillInStackTrace();
4414 Slog.i(TAG, "Removing and adding activity " + r + " to stack at " + top, here);
4416 mHistory.remove(pos);
4417 mHistory.add(top, r);
4418 moved.add(0, r.appToken);
4424 if (DEBUG_TRANSITION) Slog.v(TAG,
4425 "Prepare to front transition: task=" + tr);
4426 if (reason != null &&
4427 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
4428 mService.mWindowManager.prepareAppTransition(
4429 AppTransition.TRANSIT_NONE, false);
4430 ActivityRecord r = topRunningActivityLocked(null);
4432 mNoAnimActivities.add(r);
4434 ActivityOptions.abort(options);
4436 updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
4439 mService.mWindowManager.moveAppTokensToTop(moved);
4440 if (VALIDATE_TOKENS) {
4441 validateAppTokensLocked();
4444 finishTaskMoveLocked(task);
4445 EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, task);
4448 private final void finishTaskMoveLocked(int task) {
4449 resumeTopActivityLocked(null);
4453 * Worker method for rearranging history stack. Implements the function of moving all
4454 * activities for a specific task (gathering them if disjoint) into a single group at the
4455 * bottom of the stack.
4457 * If a watcher is installed, the action is preflighted and the watcher has an opportunity
4458 * to premeptively cancel the move.
4460 * @param task The taskId to collect and move to the bottom.
4461 * @return Returns true if the move completed, false if not.
4463 final boolean moveTaskToBackLocked(int task, ActivityRecord reason) {
4464 Slog.i(TAG, "moveTaskToBack: " + task);
4466 // If we have a watcher, preflight the move before committing to it. First check
4467 // for *other* available tasks, but if none are available, then try again allowing the
4468 // current task to be selected.
4469 if (mMainStack && mService.mController != null) {
4470 ActivityRecord next = topRunningActivityLocked(null, task);
4472 next = topRunningActivityLocked(null, 0);
4475 // ask watcher if this is allowed
4476 boolean moveOK = true;
4478 moveOK = mService.mController.activityResuming(next.packageName);
4479 } catch (RemoteException e) {
4480 mService.mController = null;
4488 ArrayList<IBinder> moved = new ArrayList<IBinder>();
4490 if (DEBUG_TRANSITION) Slog.v(TAG,
4491 "Prepare to back transition: task=" + task);
4493 final int N = mHistory.size();
4497 // Shift all activities with this task down to the bottom
4498 // of the stack, keeping them in the same internal order.
4500 ActivityRecord r = mHistory.get(pos);
4501 if (localLOGV) Slog.v(
4502 TAG, "At " + pos + " ckp " + r.task + ": " + r);
4503 if (r.task.taskId == task) {
4504 if (localLOGV) Slog.v(TAG, "Removing and adding at " + (N-1));
4505 if (DEBUG_ADD_REMOVE) {
4506 RuntimeException here = new RuntimeException("here");
4507 here.fillInStackTrace();
4508 Slog.i(TAG, "Removing and adding activity " + r + " to stack at "
4511 mHistory.remove(pos);
4512 mHistory.add(bottom, r);
4513 moved.add(r.appToken);
4519 if (reason != null &&
4520 (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
4521 mService.mWindowManager.prepareAppTransition(
4522 AppTransition.TRANSIT_NONE, false);
4523 ActivityRecord r = topRunningActivityLocked(null);
4525 mNoAnimActivities.add(r);
4528 mService.mWindowManager.prepareAppTransition(
4529 AppTransition.TRANSIT_TASK_TO_BACK, false);
4531 mService.mWindowManager.moveAppTokensToBottom(moved);
4532 if (VALIDATE_TOKENS) {
4533 validateAppTokensLocked();
4536 finishTaskMoveLocked(task);
4540 public ActivityManager.TaskThumbnails getTaskThumbnailsLocked(TaskRecord tr) {
4541 TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true);
4542 ActivityRecord resumed = mResumedActivity;
4543 if (resumed != null && resumed.thumbHolder == tr) {
4544 info.mainThumbnail = resumed.stack.screenshotActivities(resumed);
4546 if (info.mainThumbnail == null) {
4547 info.mainThumbnail = tr.lastThumbnail;
4552 public Bitmap getTaskTopThumbnailLocked(TaskRecord tr) {
4553 ActivityRecord resumed = mResumedActivity;
4554 if (resumed != null && resumed.task == tr) {
4555 // This task is the current resumed task, we just need to take
4556 // a screenshot of it and return that.
4557 return resumed.stack.screenshotActivities(resumed);
4559 // Return the information about the task, to figure out the top
4560 // thumbnail to return.
4561 TaskAccessInfo info = getTaskAccessInfoLocked(tr.taskId, true);
4562 if (info.numSubThumbbails <= 0) {
4563 return info.mainThumbnail != null ? info.mainThumbnail : tr.lastThumbnail;
4565 return info.subtasks.get(info.numSubThumbbails-1).holder.lastThumbnail;
4569 public ActivityRecord removeTaskActivitiesLocked(int taskId, int subTaskIndex,
4570 boolean taskRequired) {
4571 TaskAccessInfo info = getTaskAccessInfoLocked(taskId, false);
4572 if (info.root == null) {
4574 Slog.w(TAG, "removeTaskLocked: unknown taskId " + taskId);
4579 if (subTaskIndex < 0) {
4580 // Just remove the entire task.
4581 performClearTaskAtIndexLocked(taskId, info.rootIndex);
4585 if (subTaskIndex >= info.subtasks.size()) {
4587 Slog.w(TAG, "removeTaskLocked: unknown subTaskIndex " + subTaskIndex);
4592 // Remove all of this task's activities starting at the sub task.
4593 TaskAccessInfo.SubTask subtask = info.subtasks.get(subTaskIndex);
4594 performClearTaskAtIndexLocked(taskId, subtask.index);
4595 return subtask.activity;
4598 public TaskAccessInfo getTaskAccessInfoLocked(int taskId, boolean inclThumbs) {
4599 final TaskAccessInfo thumbs = new TaskAccessInfo();
4600 // How many different sub-thumbnails?
4601 final int NA = mHistory.size();
4603 ThumbnailHolder holder = null;
4605 ActivityRecord ar = mHistory.get(j);
4606 if (!ar.finishing && ar.task.taskId == taskId) {
4608 thumbs.rootIndex = j;
4609 holder = ar.thumbHolder;
4610 if (holder != null) {
4611 thumbs.mainThumbnail = holder.lastThumbnail;
4623 ArrayList<TaskAccessInfo.SubTask> subtasks = new ArrayList<TaskAccessInfo.SubTask>();
4624 thumbs.subtasks = subtasks;
4626 ActivityRecord ar = mHistory.get(j);
4631 if (ar.task.taskId != taskId) {
4634 if (ar.thumbHolder != holder && holder != null) {
4635 thumbs.numSubThumbbails++;
4636 holder = ar.thumbHolder;
4637 TaskAccessInfo.SubTask sub = new TaskAccessInfo.SubTask();
4638 sub.holder = holder;
4644 if (thumbs.numSubThumbbails > 0) {
4645 thumbs.retriever = new IThumbnailRetriever.Stub() {
4646 public Bitmap getThumbnail(int index) {
4647 if (index < 0 || index >= thumbs.subtasks.size()) {
4650 TaskAccessInfo.SubTask sub = thumbs.subtasks.get(index);
4651 ActivityRecord resumed = mResumedActivity;
4652 if (resumed != null && resumed.thumbHolder == sub.holder) {
4653 return resumed.stack.screenshotActivities(resumed);
4655 return sub.holder.lastThumbnail;
4662 private final void logStartActivity(int tag, ActivityRecord r,
4664 EventLog.writeEvent(tag,
4665 r.userId, System.identityHashCode(r), task.taskId,
4666 r.shortComponentName, r.intent.getAction(),
4667 r.intent.getType(), r.intent.getDataString(),
4668 r.intent.getFlags());
4672 * Make sure the given activity matches the current configuration. Returns
4673 * false if the activity had to be destroyed. Returns true if the
4674 * configuration is the same, or the activity will remain running as-is
4675 * for whatever reason. Ensures the HistoryRecord is updated with the
4676 * correct configuration and all other bookkeeping is handled.
4678 final boolean ensureActivityConfigurationLocked(ActivityRecord r,
4679 int globalChanges) {
4680 if (mConfigWillChange) {
4681 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4682 "Skipping config check (will change): " + r);
4686 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4687 "Ensuring correct configuration: " + r);
4689 // Short circuit: if the two configurations are the exact same
4690 // object (the common case), then there is nothing to do.
4691 Configuration newConfig = mService.mConfiguration;
4692 if (r.configuration == newConfig && !r.forceNewConfig) {
4693 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4694 "Configuration unchanged in " + r);
4698 // We don't worry about activities that are finishing.
4700 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4701 "Configuration doesn't matter in finishing " + r);
4702 r.stopFreezingScreenLocked(false);
4706 // Okay we now are going to make this activity have the new config.
4707 // But then we need to figure out how it needs to deal with that.
4708 Configuration oldConfig = r.configuration;
4709 r.configuration = newConfig;
4711 // Determine what has changed. May be nothing, if this is a config
4712 // that has come back from the app after going idle. In that case
4713 // we just want to leave the official config object now in the
4714 // activity and do nothing else.
4715 final int changes = oldConfig.diff(newConfig);
4716 if (changes == 0 && !r.forceNewConfig) {
4717 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4718 "Configuration no differences in " + r);
4722 // If the activity isn't currently running, just leave the new
4723 // configuration and it will pick that up next time it starts.
4724 if (r.app == null || r.app.thread == null) {
4725 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4726 "Configuration doesn't matter not running " + r);
4727 r.stopFreezingScreenLocked(false);
4728 r.forceNewConfig = false;
4732 // Figure out how to handle the changes between the configurations.
4733 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
4734 Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
4735 + Integer.toHexString(changes) + ", handles=0x"
4736 + Integer.toHexString(r.info.getRealConfigChanged())
4737 + ", newConfig=" + newConfig);
4739 if ((changes&(~r.info.getRealConfigChanged())) != 0 || r.forceNewConfig) {
4740 // Aha, the activity isn't handling the change, so DIE DIE DIE.
4741 r.configChangeFlags |= changes;
4742 r.startFreezingScreenLocked(r.app, globalChanges);
4743 r.forceNewConfig = false;
4744 if (r.app == null || r.app.thread == null) {
4745 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4746 "Config is destroying non-running " + r);
4747 destroyActivityLocked(r, true, false, "config");
4748 } else if (r.state == ActivityState.PAUSING) {
4749 // A little annoying: we are waiting for this activity to
4750 // finish pausing. Let's not do anything now, but just
4751 // flag that it needs to be restarted when done pausing.
4752 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4753 "Config is skipping already pausing " + r);
4754 r.configDestroy = true;
4756 } else if (r.state == ActivityState.RESUMED) {
4757 // Try to optimize this case: the configuration is changing
4758 // and we need to restart the top, resumed activity.
4759 // Instead of doing the normal handshaking, just say
4761 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4762 "Config is relaunching resumed " + r);
4763 relaunchActivityLocked(r, r.configChangeFlags, true);
4764 r.configChangeFlags = 0;
4766 if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4767 "Config is relaunching non-resumed " + r);
4768 relaunchActivityLocked(r, r.configChangeFlags, false);
4769 r.configChangeFlags = 0;
4772 // All done... tell the caller we weren't able to keep this
4777 // Default case: the activity can handle this new configuration, so
4778 // hand it over. Note that we don't need to give it the new
4779 // configuration, since we always send configuration changes to all
4780 // process when they happen so it can just use whatever configuration
4782 if (r.app != null && r.app.thread != null) {
4784 if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
4785 r.app.thread.scheduleActivityConfigurationChanged(r.appToken);
4786 } catch (RemoteException e) {
4787 // If process died, whatever.
4790 r.stopFreezingScreenLocked(false);
4795 private final boolean relaunchActivityLocked(ActivityRecord r,
4796 int changes, boolean andResume) {
4797 List<ResultInfo> results = null;
4798 List<Intent> newIntents = null;
4800 results = r.results;
4801 newIntents = r.newIntents;
4803 if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
4804 + " with results=" + results + " newIntents=" + newIntents
4805 + " andResume=" + andResume);
4806 EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
4807 : EventLogTags.AM_RELAUNCH_ACTIVITY, r.userId, System.identityHashCode(r),
4808 r.task.taskId, r.shortComponentName);
4810 r.startFreezingScreenLocked(r.app, 0);
4813 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
4814 (andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ")
4816 r.forceNewConfig = false;
4817 r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents,
4818 changes, !andResume, new Configuration(mService.mConfiguration));
4819 // Note: don't need to call pauseIfSleepingLocked() here, because
4820 // the caller will only pass in 'andResume' if this activity is
4821 // currently resumed, which implies we aren't sleeping.
4822 } catch (RemoteException e) {
4823 if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, "Relaunch failed", e);
4828 r.newIntents = null;
4830 mService.reportResumedActivityLocked(r);
4832 r.state = ActivityState.RESUMED;
4834 mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4835 r.state = ActivityState.PAUSED;
4841 public void dismissKeyguardOnNextActivityLocked() {
4842 mDismissKeyguardOnNextActivity = true;
4845 boolean willActivityBeVisibleLocked(IBinder token) {
4847 for (i = mHistory.size() - 1; i >= 0; i--) {
4848 ActivityRecord r = mHistory.get(i);
4849 if (r.appToken == token) {
4852 if (r.fullscreen && !r.finishing) {
4859 void closeSystemDialogsLocked() {
4860 for (int i = mHistory.size() - 1; i >= 0; i--) {
4861 ActivityRecord r = mHistory.get(i);
4862 if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
4863 r.stack.finishActivityLocked(r, i,
4864 Activity.RESULT_CANCELED, null, "close-sys", true);
4869 boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
4870 boolean didSomething = false;
4871 TaskRecord lastTask = null;
4872 final int N = mHistory.size();
4873 for (int i = 0; i < N; i++) {
4874 ActivityRecord r = mHistory.get(i);
4875 final boolean samePackage = r.packageName.equals(name)
4876 || (name == null && r.userId == userId);
4877 if ((userId == UserHandle.USER_ALL || r.userId == userId)
4878 && (samePackage || r.task == lastTask)
4879 && (r.app == null || evenPersistent || !r.app.persistent)) {
4882 // If this activity is just finishing, then it is not
4883 // interesting as far as something to stop.
4888 didSomething = true;
4889 Slog.i(TAG, " Force finishing activity " + r);
4891 if (r.app != null) {
4892 r.app.removed = true;
4897 if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
4898 null, "force-stop", true)) {
4903 return didSomething;
4906 ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
4907 PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
4908 ActivityRecord topRecord = null;
4909 int pos = mHistory.size() - 1;
4910 ActivityRecord next = pos >= 0 ? mHistory.get(pos) : null;
4911 ActivityRecord top = null;
4912 TaskRecord curTask = null;
4913 int numActivities = 0;
4915 while (pos >= 0 && maxNum > 0) {
4916 final ActivityRecord r = next;
4918 next = pos >= 0 ? mHistory.get(pos) : null;
4920 // Initialize state for next task if needed.
4921 if (top == null || (top.state == ActivityState.INITIALIZING && top.task == r.task)) {
4924 numActivities = numRunning = 0;
4927 // Add 'r' into the current task.
4929 if (r.app != null && r.app.thread != null) {
4933 if (localLOGV) Slog.v(
4934 TAG, r.intent.getComponent().flattenToShortString()
4935 + ": task=" + r.task);
4937 // If the next one is a different task, generate a new
4938 // TaskInfo entry for what we have.
4939 if (next == null || next.task != curTask) {
4940 RunningTaskInfo ci = new RunningTaskInfo();
4941 ci.id = curTask.taskId;
4942 ci.baseActivity = r.intent.getComponent();
4943 ci.topActivity = top.intent.getComponent();
4944 if (top.thumbHolder != null) {
4945 ci.description = top.thumbHolder.lastDescription;
4947 ci.numActivities = numActivities;
4948 ci.numRunning = numRunning;
4949 //System.out.println(
4950 // "#" + maxNum + ": " + " descr=" + ci.description);
4951 if (receiver != null) {
4952 if (localLOGV) Slog.v(
4953 TAG, "State=" + top.state + "Idle=" + top.idle
4955 + " thr=" + (top.app != null ? top.app.thread : null));
4956 if (top.state == ActivityState.RESUMED || top.state == ActivityState.PAUSING) {
4957 if (top.idle && top.app != null && top.app.thread != null) {
4960 top.thumbnailNeeded = true;
4963 pending.pendingRecords.add(top);
4973 public void unhandledBackLocked() {
4974 int top = mHistory.size() - 1;
4975 if (DEBUG_SWITCH) Slog.d(
4976 TAG, "Performing unhandledBack(): top activity at " + top);
4978 finishActivityLocked(mHistory.get(top),
4979 top, Activity.RESULT_CANCELED, null, "unhandled-back", true);
4983 void handleAppCrashLocked(ProcessRecord app) {
4984 for (int i = mHistory.size() - 1; i >= 0; i--) {
4985 ActivityRecord r = mHistory.get(i);
4987 Slog.w(TAG, " Force finishing activity "
4988 + r.intent.getComponent().flattenToShortString());
4989 r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
4990 null, "crashed", false);
4995 void dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
4996 boolean dumpClient, String dumpPackage) {
4997 ActivityManagerService.dumpHistoryList(fd, pw, mHistory, " ", "Hist", true, !dumpAll,
4998 dumpClient, dumpPackage);
5001 ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
5002 ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
5004 if ("all".equals(name)) {
5005 for (ActivityRecord r1 : mHistory) {
5008 } else if ("top".equals(name)) {
5009 final int N = mHistory.size();
5011 activities.add(mHistory.get(N-1));
5014 ItemMatcher matcher = new ItemMatcher();
5015 matcher.build(name);
5017 for (ActivityRecord r1 : mHistory) {
5018 if (matcher.match(r1, r1.intent.getComponent())) {
5027 ActivityRecord restartPackage(String packageName) {
5028 ActivityRecord starting = topRunningActivityLocked(null);
5030 // All activities that came from the package must be
5031 // restarted as if there was a config change.
5032 for (int i = mHistory.size() - 1; i >= 0; i--) {
5033 ActivityRecord a = mHistory.get(i);
5034 if (a.info.packageName.equals(packageName)) {
5035 a.forceNewConfig = true;
5036 if (starting != null && a == starting && a.visible) {
5037 a.startFreezingScreenLocked(starting.app, ActivityInfo.CONFIG_SCREEN_LAYOUT);