ActivityStack.java revision cae015fea398e1d99c0b538991535330f31fe543
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
19import static android.Manifest.permission.START_ANY_ACTIVITY;
20import static android.content.pm.PackageManager.PERMISSION_GRANTED;
21
22import com.android.internal.app.HeavyWeightSwitcherActivity;
23import com.android.internal.os.BatteryStatsImpl;
24import com.android.server.am.ActivityManagerService.ItemMatcher;
25import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
26import com.android.server.wm.AppTransition;
27
28import android.app.Activity;
29import android.app.ActivityManager;
30import android.app.ActivityOptions;
31import android.app.AppGlobals;
32import android.app.IActivityManager;
33import android.app.IThumbnailReceiver;
34import android.app.IThumbnailRetriever;
35import android.app.IApplicationThread;
36import android.app.PendingIntent;
37import android.app.ResultInfo;
38import android.app.ActivityManager.RunningTaskInfo;
39import android.app.IActivityManager.WaitResult;
40import android.content.ComponentName;
41import android.content.Context;
42import android.content.IIntentSender;
43import android.content.Intent;
44import android.content.IntentSender;
45import android.content.pm.ActivityInfo;
46import android.content.pm.ApplicationInfo;
47import android.content.pm.PackageManager;
48import android.content.pm.ResolveInfo;
49import android.content.res.Configuration;
50import android.content.res.Resources;
51import android.graphics.Bitmap;
52import android.graphics.Bitmap.Config;
53import android.os.Binder;
54import android.os.Bundle;
55import android.os.Handler;
56import android.os.IBinder;
57import android.os.Looper;
58import android.os.Message;
59import android.os.ParcelFileDescriptor;
60import android.os.PowerManager;
61import android.os.RemoteException;
62import android.os.SystemClock;
63import android.os.UserHandle;
64import android.util.EventLog;
65import android.util.Log;
66import android.util.Slog;
67import android.view.Display;
68
69import java.io.FileDescriptor;
70import java.io.IOException;
71import java.io.PrintWriter;
72import java.lang.ref.WeakReference;
73import java.util.ArrayList;
74import java.util.Iterator;
75import java.util.List;
76
77/**
78 * State and management of a single stack of activities.
79 */
80final 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;
92
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;
97
98    static final boolean VALIDATE_TOKENS = ActivityManagerService.VALIDATE_TOKENS;
99
100    // How long we wait until giving up on the last activity telling us it
101    // is idle.
102    static final int IDLE_TIMEOUT = 10*1000;
103
104    // Ticks during which we check progress while waiting for an app to launch.
105    static final int LAUNCH_TICK = 500;
106
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
109    // next activity.
110    static final int PAUSE_TIMEOUT = 500;
111
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;
116
117    // How long we can hold the sleep wake lock before giving up.
118    static final int SLEEP_TIMEOUT = 5*1000;
119
120    // How long we can hold the launch wake lock before giving up.
121    static final int LAUNCH_TIMEOUT = 10*1000;
122
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;
126
127    // How long until we reset a task when the user returns to it.  Currently
128    // disabled.
129    static final long ACTIVITY_INACTIVE_RESET_TIME = 0;
130
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;
134
135    // Set to false to disable the preview that is shown while a new activity
136    // is being started.
137    static final boolean SHOW_APP_STARTING_PREVIEW = true;
138
139    enum ActivityState {
140        INITIALIZING,
141        RESUMED,
142        PAUSING,
143        PAUSED,
144        STOPPING,
145        STOPPED,
146        FINISHING,
147        DESTROYING,
148        DESTROYED
149    }
150
151    final ActivityManagerService mService;
152    final boolean mMainStack;
153
154    final Context mContext;
155
156    /**
157     * The back history of all previous (and possibly still
158     * running) activities.  It contains #ActivityRecord objects.
159     */
160    private final ArrayList<ActivityRecord> mHistory = new ArrayList<ActivityRecord>();
161
162    /**
163     * Used for validating app tokens with window manager.
164     */
165    final ArrayList<TaskGroup> mValidateAppTokens = new ArrayList<TaskGroup>();
166
167    /**
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.
171     */
172    final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<ActivityRecord>();
173
174    /**
175     * List of activities that are waiting for a new activity
176     * to become visible before completing whatever operation they are
177     * supposed to do.
178     */
179    final ArrayList<ActivityRecord> mWaitingVisibleActivities
180            = new ArrayList<ActivityRecord>();
181
182    /**
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.
186     */
187    final ArrayList<ActivityRecord> mStoppingActivities
188            = new ArrayList<ActivityRecord>();
189
190    /**
191     * List of activities that are in the process of going to sleep.
192     */
193    final ArrayList<ActivityRecord> mGoingToSleepActivities
194            = new ArrayList<ActivityRecord>();
195
196    /**
197     * Animations that for the current transition have requested not to
198     * be considered for the transition animation.
199     */
200    final ArrayList<ActivityRecord> mNoAnimActivities
201            = new ArrayList<ActivityRecord>();
202
203    /**
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.
207     */
208    final ArrayList<ActivityRecord> mFinishingActivities
209            = new ArrayList<ActivityRecord>();
210
211    /**
212     * List of people waiting to find out about the next launched activity.
213     */
214    final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched
215            = new ArrayList<IActivityManager.WaitResult>();
216
217    /**
218     * List of people waiting to find out about the next visible activity.
219     */
220    final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible
221            = new ArrayList<IActivityManager.WaitResult>();
222
223    final ArrayList<UserStartedState> mStartingUsers
224            = new ArrayList<UserStartedState>();
225
226    /**
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.
230     */
231    final PowerManager.WakeLock mGoingToSleep;
232
233    /**
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.
238     */
239    final PowerManager.WakeLock mLaunchingActivity;
240
241    /**
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.
244     */
245    ActivityRecord mPausingActivity = null;
246
247    /**
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.
251     */
252    ActivityRecord mLastPausedActivity = null;
253
254    /**
255     * Current activity that is resumed, or null if there is none.
256     */
257    ActivityRecord mResumedActivity = null;
258
259    /**
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.
263     */
264    ActivityRecord mLastStartedActivity = null;
265
266    /**
267     * Set when we know we are going to be calling updateConfiguration()
268     * soon, so want to skip intermediate config checks.
269     */
270    boolean mConfigWillChange;
271
272    /**
273     * Set to indicate whether to issue an onUserLeaving callback when a
274     * newly launched activity is being brought in front of us.
275     */
276    boolean mUserLeaving = false;
277
278    long mInitialStartTime = 0;
279
280    /**
281     * Set when we have taken too long waiting to go to sleep.
282     */
283    boolean mSleepTimeout = false;
284
285    /**
286     * Dismiss the keyguard after the next activity is displayed?
287     */
288    boolean mDismissKeyguardOnNextActivity = false;
289
290    /**
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.
293     */
294    private ActivityRecord mLastScreenshotActivity = null;
295    private Bitmap mLastScreenshotBitmap = null;
296
297    /**
298     * List of ActivityRecord objects that have been finished and must
299     * still report back to a pending thumbnail receiver.
300     */
301    private final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
302
303    int mThumbnailWidth = -1;
304    int mThumbnailHeight = -1;
305
306    private int mCurrentUser;
307
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;
318
319    static class ScheduleDestroyArgs {
320        final ProcessRecord mOwner;
321        final boolean mOomAdj;
322        final String mReason;
323        ScheduleDestroyArgs(ProcessRecord owner, boolean oomAdj, String reason) {
324            mOwner = owner;
325            mOomAdj = oomAdj;
326            mReason = reason;
327        }
328    }
329
330    final Handler mHandler;
331
332    final class ActivityStackHandler extends Handler {
333        //public Handler() {
334        //    if (localLOGV) Slog.v(TAG, "Handler started!");
335        //}
336        public ActivityStackHandler(Looper looper) {
337            super(looper);
338        }
339
340        @Override
341        public void handleMessage(Message msg) {
342            switch (msg.what) {
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();
349                        }
350                    }
351                } break;
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) {
358                        if (r.app != null) {
359                            mService.logAppTooSlow(r.app, r.pauseTime,
360                                    "pausing " + r);
361                        }
362                    }
363
364                    activityPaused(r != null ? r.appToken : null, true);
365                } break;
366                case IDLE_TIMEOUT_MSG: {
367                    if (mService.mDidDexOpt) {
368                        mService.mDidDexOpt = false;
369                        Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
370                        nmsg.obj = msg.obj;
371                        mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
372                        return;
373                    }
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);
379                } break;
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,
385                                    "launching " + r);
386                        }
387                    }
388                } break;
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);
395                } break;
396                case IDLE_NOW_MSG: {
397                    ActivityRecord r = (ActivityRecord)msg.obj;
398                    activityIdleInternal(r != null ? r.appToken : null, false, null);
399                } break;
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);
405                        return;
406                    }
407                    synchronized (mService) {
408                        if (mLaunchingActivity.isHeld()) {
409                            Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
410                            mLaunchingActivity.release();
411                        }
412                    }
413                } break;
414                case RESUME_TOP_ACTIVITY_MSG: {
415                    synchronized (mService) {
416                        resumeTopActivityLocked(null);
417                    }
418                } break;
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);
427                        }
428                    }
429                } break;
430                case DESTROY_ACTIVITIES_MSG: {
431                    ScheduleDestroyArgs args = (ScheduleDestroyArgs)msg.obj;
432                    synchronized (mService) {
433                        destroyActivitiesLocked(args.mOwner, args.mOomAdj, args.mReason);
434                    }
435                }
436            }
437        }
438    }
439
440    ActivityStack(ActivityManagerService service, Context context, boolean mainStack, Looper looper) {
441        mHandler = new ActivityStackHandler(looper);
442        mService = service;
443        mContext = context;
444        mMainStack = mainStack;
445        PowerManager pm =
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);
450    }
451
452    private boolean okToShow(ActivityRecord r) {
453        return r.userId == mCurrentUser
454                || (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0;
455    }
456
457    final ActivityRecord topRunningActivityLocked(ActivityRecord notTop) {
458        int i = mHistory.size()-1;
459        while (i >= 0) {
460            ActivityRecord r = mHistory.get(i);
461            if (!r.finishing && r != notTop && okToShow(r)) {
462                return r;
463            }
464            i--;
465        }
466        return null;
467    }
468
469    final ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
470        int i = mHistory.size()-1;
471        while (i >= 0) {
472            ActivityRecord r = mHistory.get(i);
473            if (!r.finishing && !r.delayedResume && r != notTop && okToShow(r)) {
474                return r;
475            }
476            i--;
477        }
478        return null;
479    }
480
481    /**
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.
484     *
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.
487     *
488     * @return Returns the HistoryRecord of the next activity on the stack.
489     */
490    final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
491        int i = mHistory.size()-1;
492        while (i >= 0) {
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)
496                    && okToShow(r)) {
497                return r;
498            }
499            i--;
500        }
501        return null;
502    }
503
504    final int indexOfTokenLocked(IBinder token) {
505        return mHistory.indexOf(ActivityRecord.forToken(token));
506    }
507
508    final int indexOfActivityLocked(ActivityRecord r) {
509        return mHistory.indexOf(r);
510    }
511
512    final ActivityRecord isInStackLocked(IBinder token) {
513        ActivityRecord r = ActivityRecord.forToken(token);
514        if (mHistory.contains(r)) {
515            return r;
516        }
517        return null;
518    }
519
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);
524        }
525        return null;
526    }
527
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;
536                }
537                return -1;
538            }
539            lastTask = r.task;
540        }
541
542        return -1;
543    }
544
545    private final boolean updateLRUListLocked(ActivityRecord r) {
546        final boolean hadit = mLRUActivities.remove(r);
547        mLRUActivities.add(r);
548        return hadit;
549    }
550
551    /**
552     * Returns the top activity in any existing task matching the given
553     * Intent.  Returns null if no such task is found.
554     */
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);
559        }
560
561        TaskRecord cp = null;
562
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) {
569                cp = r.task;
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!");
576                        return r;
577                    }
578                } else if (r.task.intent != null
579                        && r.task.intent.getComponent().equals(cls)) {
580                    //Slog.i(TAG, "Found matching class!");
581                    //dump();
582                    //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
583                    return r;
584                } else if (r.task.affinityIntent != null
585                        && r.task.affinityIntent.getComponent().equals(cls)) {
586                    //Slog.i(TAG, "Found matching class!");
587                    //dump();
588                    //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
589                    return r;
590                }
591            }
592        }
593
594        return null;
595    }
596
597    /**
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
600     * is found.
601     */
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);
606        }
607        final int userId = UserHandle.getUserId(info.applicationInfo.uid);
608
609        final int N = mHistory.size();
610        for (int i=(N-1); i>=0; i--) {
611            ActivityRecord r = mHistory.get(i);
612            if (!r.finishing) {
613                if (r.intent.getComponent().equals(cls) && r.userId == userId) {
614                    //Slog.i(TAG, "Found matching class!");
615                    //dump();
616                    //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
617                    return r;
618                }
619            }
620        }
621
622        return null;
623    }
624
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);
630    }
631
632    /*
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.
635     */
636    final boolean switchUserLocked(int userId, UserStartedState uss) {
637        mCurrentUser = userId;
638        mStartingUsers.add(uss);
639
640        // Only one activity? Nothing to do...
641        if (mHistory.size() < 2)
642            return false;
643
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();
650        int i = 0;
651        while (i < N) {
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
657                N--;
658                haveActivities = true;
659            } else {
660                i++;
661            }
662        }
663        // Transition from the old top to the new top
664        resumeTopActivityLocked(top);
665        return haveActivities;
666    }
667
668    final boolean realStartActivityLocked(ActivityRecord r,
669            ProcessRecord app, boolean andResume, boolean checkConfig)
670            throws RemoteException {
671
672        r.startFreezingScreenLocked(app, 0);
673        mService.mWindowManager.setAppVisibility(r.appToken, true);
674
675        // schedule launch ticks to collect information about slow apps.
676        r.startLaunchTickingLocked();
677
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.
684        if (checkConfig) {
685            Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
686                    mService.mConfiguration,
687                    r.mayFreezeScreenLocked(app) ? r.appToken : null);
688            mService.updateConfigurationLocked(config, r, false, false);
689        }
690
691        r.app = app;
692        app.waitingToKill = null;
693        r.launchCount++;
694        r.lastLaunchTime = SystemClock.uptimeMillis();
695
696        if (localLOGV) Slog.v(TAG, "Launching: " + r);
697
698        int idx = app.activities.indexOf(r);
699        if (idx < 0) {
700            app.activities.add(r);
701        }
702        mService.updateLruProcessLocked(app, true);
703
704        try {
705            if (app.thread == null) {
706                throw new RemoteException();
707            }
708            List<ResultInfo> results = null;
709            List<Intent> newIntents = null;
710            if (andResume) {
711                results = r.results;
712                newIntents = r.newIntents;
713            }
714            if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
715                    + " icicle=" + r.icicle
716                    + " with results=" + results + " newIntents=" + newIntents
717                    + " andResume=" + andResume);
718            if (andResume) {
719                EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
720                        r.userId, System.identityHashCode(r),
721                        r.task.taskId, r.shortComponentName);
722            }
723            if (r.isHomeActivity) {
724                mService.mHomeProcess = app;
725            }
726            mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
727            r.sleeping = false;
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;
740                }
741            }
742            app.hasShownUi = true;
743            app.pendingUiClean = true;
744            if (profileFd != null) {
745                try {
746                    profileFd = profileFd.dup();
747                } catch (IOException e) {
748                    profileFd = null;
749                }
750            }
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,
756                    profileAutoStop);
757
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);
769                    }
770                    mService.mHeavyWeightProcess = app;
771                    Message msg = mService.mHandler.obtainMessage(
772                            ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
773                    msg.obj = r;
774                    mService.mHandler.sendMessage(msg);
775                }
776            }
777
778        } catch (RemoteException e) {
779            if (r.launchFailed) {
780                // This is the second time we failed -- finish activity
781                // and give up.
782                Slog.e(TAG, "Second failure launching "
783                      + r.intent.getComponent().flattenToShortString()
784                      + ", giving up", e);
785                mService.appDiedLocked(app, app.pid, app.thread);
786                requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
787                        "2nd-crash", false);
788                return false;
789            }
790
791            // This is the first time we failed -- restart process and
792            // retry.
793            app.activities.remove(r);
794            throw e;
795        }
796
797        r.launchFailed = false;
798        if (updateLRUListLocked(r)) {
799            Slog.w(TAG, "Activity " + r
800                  + " being launched, but already in LRU list");
801        }
802
803        if (andResume) {
804            // As part of the process of launching, ActivityThread also performs
805            // a resume.
806            r.state = ActivityState.RESUMED;
807            if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + r
808                    + " (starting new instance)");
809            r.stopped = false;
810            mResumedActivity = r;
811            r.task.touchActiveTime();
812            if (mMainStack) {
813                mService.addRecentTaskLocked(r.task);
814            }
815            completeResumeLocked(r);
816            checkReadyForSleepLocked();
817            if (DEBUG_SAVED_STATE) Slog.i(TAG, "Launch completed; removing icicle of " + r.icicle);
818        } else {
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
822            // other state.
823            if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
824                    + " (starting in stopped state)");
825            r.state = ActivityState.STOPPED;
826            r.stopped = true;
827        }
828
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.
833        if (mMainStack) {
834            mService.startSetupActivityLocked();
835        }
836
837        return true;
838    }
839
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);
845
846        if (r.launchTime == 0) {
847            r.launchTime = SystemClock.uptimeMillis();
848            if (mInitialStartTime == 0) {
849                mInitialStartTime = r.launchTime;
850            }
851        } else if (mInitialStartTime == 0) {
852            mInitialStartTime = SystemClock.uptimeMillis();
853        }
854
855        if (app != null && app.thread != null) {
856            try {
857                app.addPackage(r.info.packageName);
858                realStartActivityLocked(r, app, andResume, checkConfig);
859                return;
860            } catch (RemoteException e) {
861                Slog.w(TAG, "Exception when starting activity "
862                        + r.intent.getComponent().flattenToShortString(), e);
863            }
864
865            // If a dead object exception was thrown -- fall through to
866            // restart the application.
867        }
868
869        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
870                "activity", r.intent.getComponent(), false, false);
871    }
872
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);
880                }
881            }
882            mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
883            Message msg = mHandler.obtainMessage(SLEEP_TIMEOUT_MSG);
884            mHandler.sendMessageDelayed(msg, SLEEP_TIMEOUT);
885            checkReadyForSleepLocked();
886        }
887    }
888
889    void awakeFromSleepingLocked() {
890        mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
891        mSleepTimeout = false;
892        if (mGoingToSleep.isHeld()) {
893            mGoingToSleep.release();
894        }
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);
899        }
900        mGoingToSleepActivities.clear();
901    }
902
903    void activitySleptLocked(ActivityRecord r) {
904        mGoingToSleepActivities.remove(r);
905        checkReadyForSleepLocked();
906    }
907
908    void checkReadyForSleepLocked() {
909        if (!mService.isSleeping()) {
910            // Do not care.
911            return;
912        }
913
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);
920                return;
921            }
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);
925                return;
926            }
927
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();
933                return;
934            }
935
936            ensureActivitiesVisibleLocked(null, 0);
937
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) {
943                    r.setSleeping(true);
944                }
945            }
946
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");
951                return;
952            }
953        }
954
955        mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
956
957        if (mGoingToSleep.isHeld()) {
958            mGoingToSleep.release();
959        }
960        if (mService.mShuttingDown) {
961            mService.notifyAll();
962        }
963    }
964
965    public final Bitmap screenshotActivities(ActivityRecord who) {
966        if (who.noDisplay) {
967            return null;
968        }
969
970        Resources res = mService.mContext.getResources();
971        int w = mThumbnailWidth;
972        int h = mThumbnailHeight;
973        if (w < 0) {
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);
978        }
979
980        if (w > 0) {
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);
987            }
988            if (mLastScreenshotBitmap != null) {
989                return mLastScreenshotBitmap.copy(Config.ARGB_8888, true);
990            }
991        }
992        return null;
993    }
994
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);
1000        }
1001        ActivityRecord prev = mResumedActivity;
1002        if (prev == null) {
1003            RuntimeException e = new RuntimeException();
1004            Slog.e(TAG, "Trying to pause when nothing is resumed", e);
1005            resumeTopActivityLocked(null);
1006            return;
1007        }
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);
1016
1017        mService.updateCpuStats();
1018
1019        if (prev.app != null && prev.app.thread != null) {
1020            if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
1021            try {
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);
1027                if (mMainStack) {
1028                    mService.updateUsageStats(prev, false);
1029                }
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;
1035            }
1036        } else {
1037            mPausingActivity = null;
1038            mLastPausedActivity = null;
1039        }
1040
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);
1049            }
1050        }
1051
1052
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.
1058            if (!uiSleeping) {
1059                prev.pauseKeyDispatchingLocked();
1060            } else {
1061                if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
1062            }
1063
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);
1068            msg.obj = prev;
1069            prev.pauseTime = SystemClock.uptimeMillis();
1070            mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
1071            if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
1072        } else {
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);
1077        }
1078    }
1079
1080    final void activityResumed(IBinder token) {
1081        ActivityRecord r = null;
1082
1083        synchronized (mService) {
1084            int index = indexOfTokenLocked(token);
1085            if (index >= 0) {
1086                r = mHistory.get(index);
1087                if (DEBUG_SAVED_STATE) Slog.i(TAG, "Resumed activity; dropping state of: " + r);
1088                r.icicle = null;
1089                r.haveState = false;
1090            }
1091        }
1092    }
1093
1094    final void activityPaused(IBinder token, boolean timeout) {
1095        if (DEBUG_PAUSE) Slog.v(
1096            TAG, "Activity paused: token=" + token + ", timeout=" + timeout);
1097
1098        ActivityRecord r = null;
1099
1100        synchronized (mService) {
1101            int index = indexOfTokenLocked(token);
1102            if (index >= 0) {
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();
1110                } else {
1111                    EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
1112                            r.userId, System.identityHashCode(r), r.shortComponentName,
1113                            mPausingActivity != null
1114                                ? mPausingActivity.shortComponentName : "(none)");
1115                }
1116            }
1117        }
1118    }
1119
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);
1125            return;
1126        }
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.
1131            r.icicle = icicle;
1132            r.haveState = true;
1133            r.launchCount = 0;
1134            r.updateThumbnail(thumbnail, description);
1135        }
1136        if (!r.stopped) {
1137            if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (stop complete)");
1138            mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
1139            r.stopped = true;
1140            r.state = ActivityState.STOPPED;
1141            if (r.finishing) {
1142                r.clearOptionsLocked();
1143            } else {
1144                if (r.configDestroy) {
1145                    destroyActivityLocked(r, true, false, "stop-config");
1146                    resumeTopActivityLocked(null);
1147                } else {
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;
1156                    }
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;
1162                    }
1163                }
1164            }
1165        }
1166    }
1167
1168    private final void completePauseLocked() {
1169        ActivityRecord prev = mPausingActivity;
1170        if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
1171
1172        if (prev != null) {
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);
1183                }
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");
1192                } else {
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
1197                        // them out.
1198                        if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
1199                        scheduleIdleLocked();
1200                    } else {
1201                        checkReadyForSleepLocked();
1202                    }
1203                }
1204            } else {
1205                if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
1206                prev = null;
1207            }
1208            mPausingActivity = null;
1209        }
1210
1211        if (!mService.isSleeping()) {
1212            resumeTopActivityLocked(prev);
1213        } else {
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);
1223            }
1224        }
1225
1226        if (prev != null) {
1227            prev.resumeKeyDispatchingLocked();
1228        }
1229
1230        if (prev.app != null && prev.cpuTimeAtResume > 0
1231                && mService.mBatteryStatsService.isOnBattery()) {
1232            long diff = 0;
1233            synchronized (mService.mProcessStatsThread) {
1234                diff = mService.mProcessStats.getCpuTimeForPid(prev.app.pid)
1235                        - prev.cpuTimeAtResume;
1236            }
1237            if (diff > 0) {
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);
1243                    if (ps != null) {
1244                        ps.addForegroundTimeLocked(diff);
1245                    }
1246                }
1247            }
1248        }
1249        prev.cpuTimeAtResume = 0; // reset it
1250    }
1251
1252    /**
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.
1256     */
1257    private final void completeResumeLocked(ActivityRecord next) {
1258        next.idle = false;
1259        next.results = null;
1260        next.newIntents = null;
1261
1262        // schedule an idle timeout in case the app doesn't do it for us.
1263        Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
1264        msg.obj = next;
1265        mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
1266
1267        if (false) {
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
1271            // idle.
1272            msg = mHandler.obtainMessage(IDLE_NOW_MSG);
1273            msg.obj = next;
1274            mHandler.sendMessage(msg);
1275        }
1276
1277        if (mMainStack) {
1278            mService.reportResumedActivityLocked(next);
1279        }
1280
1281        if (mMainStack) {
1282            mService.setFocusedActivityLocked(next);
1283        }
1284        next.resumeKeyDispatchingLocked();
1285        ensureActivitiesVisibleLocked(null, 0);
1286        mService.mWindowManager.executeAppTransition();
1287        mNoAnimActivities.clear();
1288
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);
1295            }
1296        } else {
1297            next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
1298        }
1299    }
1300
1301    /**
1302     * Make sure that all activities that need to be visible (that is, they
1303     * currently can be seen by the user) actually are.
1304     */
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));
1310
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();
1314        int i = count-1;
1315        while (mHistory.get(i) != top) {
1316            i--;
1317        }
1318        ActivityRecord r;
1319        boolean behindFullscreen = false;
1320        for (; i>=0; i--) {
1321            r = mHistory.get(i);
1322            if (DEBUG_VISBILITY) Slog.v(
1323                    TAG, "Make visible? " + r + " finishing=" + r.finishing
1324                    + " state=" + r.state);
1325            if (r.finishing) {
1326                continue;
1327            }
1328
1329            final boolean doThisProcess = onlyThisProcess == null
1330                    || onlyThisProcess.equals(r.processName);
1331
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);
1336            }
1337
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
1343                    // at this point.
1344                    if (DEBUG_VISBILITY) Slog.v(
1345                            TAG, "Start and freeze screen for " + r);
1346                    if (r != starting) {
1347                        r.startFreezingScreenLocked(r.app, configChanges);
1348                    }
1349                    if (!r.visible) {
1350                        if (DEBUG_VISBILITY) Slog.v(
1351                                TAG, "Starting and making visible: " + r);
1352                        mService.mWindowManager.setAppVisibility(r.appToken, true);
1353                    }
1354                    if (r != starting) {
1355                        startSpecificActivityLocked(r, false, false);
1356                    }
1357                }
1358
1359            } else if (r.visible) {
1360                // If this activity is already visible, then there is nothing
1361                // else to do here.
1362                if (DEBUG_VISBILITY) Slog.v(
1363                        TAG, "Skipping: already visible at " + r);
1364                r.stopFreezingScreenLocked(false);
1365
1366            } else if (onlyThisProcess == null) {
1367                // This activity is not currently visible, but is running.
1368                // Tell it to become visible.
1369                r.visible = true;
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);
1375                    try {
1376                        mService.mWindowManager.setAppVisibility(r.appToken, true);
1377                        r.sleeping = false;
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);
1386                    }
1387                }
1388            }
1389
1390            // Aggregate current change flags.
1391            configChanges |= r.configChangeFlags;
1392
1393            if (r.fullscreen) {
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;
1398                i--;
1399                break;
1400            }
1401        }
1402
1403        // Now for any activities that aren't visible to the user, make
1404        // sure they no longer are keeping the screen frozen.
1405        while (i >= 0) {
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);
1411            if (!r.finishing) {
1412                if (behindFullscreen) {
1413                    if (r.visible) {
1414                        if (DEBUG_VISBILITY) Slog.v(
1415                                TAG, "Making invisible: " + r);
1416                        r.visible = false;
1417                        try {
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);
1425                            }
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);
1431                        }
1432                    } else {
1433                        if (DEBUG_VISBILITY) Slog.v(
1434                                TAG, "Already invisible: " + r);
1435                    }
1436                } else if (r.fullscreen) {
1437                    if (DEBUG_VISBILITY) Slog.v(
1438                            TAG, "Now behindFullscreen: " + r);
1439                    behindFullscreen = true;
1440                }
1441            }
1442            i--;
1443        }
1444    }
1445
1446    /**
1447     * Version of ensureActivitiesVisible that can easily be called anywhere.
1448     */
1449    final void ensureActivitiesVisibleLocked(ActivityRecord starting,
1450            int configChanges) {
1451        ActivityRecord r = topRunningActivityLocked(null);
1452        if (r != null) {
1453            ensureActivitiesVisibleLocked(r, starting, null, configChanges);
1454        }
1455    }
1456
1457    /**
1458     * Ensure that the top activity in the stack is resumed.
1459     *
1460     * @param prev The previously resumed activity, for when in the process
1461     * of pausing; can be null to call from elsewhere.
1462     *
1463     * @return Returns true if something is being resumed, or false if
1464     * nothing happened.
1465     */
1466    final boolean resumeTopActivityLocked(ActivityRecord prev) {
1467        return resumeTopActivityLocked(prev, null);
1468    }
1469
1470    final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
1471        // Find the first activity that is not finishing.
1472        ActivityRecord next = topRunningActivityLocked(null);
1473
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;
1478
1479        if (next == null) {
1480            // There are no more activities!  Let's just start up the
1481            // Launcher...
1482            if (mMainStack) {
1483                ActivityOptions.abort(options);
1484                return mService.startHomeActivityLocked(mCurrentUser);
1485            }
1486        }
1487
1488        next.delayedResume = false;
1489
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);
1497            return false;
1498        }
1499
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);
1512            return false;
1513        }
1514
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");
1521            return false;
1522        }
1523
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);
1530
1531        next.updateOptionsLocked(options);
1532
1533        if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
1534
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);
1540            return false;
1541        }
1542
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.
1548        if (false) {
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);
1562                } else {
1563                    next.startTime = now;
1564                    mLastStartedActivity = next;
1565                }
1566            } else {
1567                next.startTime = SystemClock.uptimeMillis();
1568                mLastStartedActivity = next;
1569            }
1570        }
1571
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);
1584            }
1585            startPausingLocked(userLeaving, false);
1586            return true;
1587        }
1588
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) {
1596                if (DEBUG_STATES) {
1597                    Slog.d(TAG, "no-history finish of " + last + " on new resume");
1598                }
1599                requestFinishActivityLocked(last.appToken, Activity.RESULT_CANCELED, null,
1600                        "no-history", false);
1601            }
1602        }
1603
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);
1610            } else {
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);
1625                } else {
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);
1630                }
1631            }
1632        }
1633
1634        // Launching this app's activity, make sure the app is no longer
1635        // considered stopped.
1636        try {
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);
1643        }
1644
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;
1649        if (prev != null) {
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);
1656                } else {
1657                    mService.mWindowManager.prepareAppTransition(prev.task == next.task
1658                            ? AppTransition.TRANSIT_ACTIVITY_CLOSE
1659                            : AppTransition.TRANSIT_TASK_CLOSE, false);
1660                }
1661                mService.mWindowManager.setAppWillBeHidden(prev.appToken);
1662                mService.mWindowManager.setAppVisibility(prev.appToken, false);
1663            } else {
1664                if (DEBUG_TRANSITION) Slog.v(TAG,
1665                        "Prepare open transition: prev=" + prev);
1666                if (mNoAnimActivities.contains(next)) {
1667                    noAnim = true;
1668                    mService.mWindowManager.prepareAppTransition(
1669                            AppTransition.TRANSIT_NONE, false);
1670                } else {
1671                    mService.mWindowManager.prepareAppTransition(prev.task == next.task
1672                            ? AppTransition.TRANSIT_ACTIVITY_OPEN
1673                            : AppTransition.TRANSIT_TASK_OPEN, false);
1674                }
1675            }
1676            if (false) {
1677                mService.mWindowManager.setAppWillBeHidden(prev.appToken);
1678                mService.mWindowManager.setAppVisibility(prev.appToken, false);
1679            }
1680        } else if (mHistory.size() > 1) {
1681            if (DEBUG_TRANSITION) Slog.v(TAG,
1682                    "Prepare open transition: no previous");
1683            if (mNoAnimActivities.contains(next)) {
1684                noAnim = true;
1685                mService.mWindowManager.prepareAppTransition(
1686                        AppTransition.TRANSIT_NONE, false);
1687            } else {
1688                mService.mWindowManager.prepareAppTransition(
1689                        AppTransition.TRANSIT_ACTIVITY_OPEN, false);
1690            }
1691        }
1692        if (!noAnim) {
1693            next.applyOptionsLocked();
1694        } else {
1695            next.clearOptionsLocked();
1696        }
1697
1698        if (next.app != null && next.app.thread != null) {
1699            if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
1700
1701            // This activity is now becoming visible.
1702            mService.mWindowManager.setAppVisibility(next.appToken, true);
1703
1704            // schedule launch ticks to collect information about slow apps.
1705            next.startLaunchTickingLocked();
1706
1707            ActivityRecord lastResumedActivity = mResumedActivity;
1708            ActivityState lastState = next.state;
1709
1710            mService.updateCpuStats();
1711
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();
1716            if (mMainStack) {
1717                mService.addRecentTaskLocked(next.task);
1718            }
1719            mService.updateLruProcessLocked(next.app, true);
1720            updateLRUListLocked(next);
1721
1722            // Have the window manager re-evaluate the orientation of
1723            // the screen based on the new activity order.
1724            boolean updated = false;
1725            if (mMainStack) {
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;
1732                    }
1733                    updated = mService.updateConfigurationLocked(config, next, false, false);
1734                }
1735            }
1736            if (!updated) {
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
1741                // weird happened.
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) {
1747                    // Do over!
1748                    mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
1749                }
1750                if (mMainStack) {
1751                    mService.setFocusedActivityLocked(next);
1752                }
1753                ensureActivitiesVisibleLocked(null, 0);
1754                mService.mWindowManager.executeAppTransition();
1755                mNoAnimActivities.clear();
1756                return true;
1757            }
1758
1759            try {
1760                // Deliver all pending results.
1761                ArrayList a = next.results;
1762                if (a != null) {
1763                    final int N = a.size();
1764                    if (!next.finishing && N > 0) {
1765                        if (DEBUG_RESULTS) Slog.v(
1766                                TAG, "Delivering results to " + next
1767                                + ": " + a);
1768                        next.app.thread.scheduleSendResult(next.appToken, a);
1769                    }
1770                }
1771
1772                if (next.newIntents != null) {
1773                    next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
1774                }
1775
1776                EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
1777                        next.userId, System.identityHashCode(next),
1778                        next.task.taskId, next.shortComponentName);
1779
1780                next.sleeping = false;
1781                showAskCompatModeDialogLocked(next);
1782                next.app.pendingUiClean = true;
1783                next.app.thread.scheduleResumeActivity(next.appToken,
1784                        mService.isNextTransitionForward());
1785
1786                checkReadyForSleepLocked();
1787
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;
1797                } else {
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,
1805                                null, true);
1806                    }
1807                }
1808                startSpecificActivityLocked(next, true, false);
1809                return true;
1810            }
1811
1812            // From this point on, if something goes wrong there is no way
1813            // to recover the activity.
1814            try {
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);
1823                return true;
1824            }
1825            next.stopped = false;
1826
1827        } else {
1828            // Whoops, need to restart this activity!
1829            if (!next.hasBeenLaunched) {
1830                next.hasBeenLaunched = true;
1831            } else {
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,
1839                            null, true);
1840                }
1841                if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
1842            }
1843            startSpecificActivityLocked(next, true, true);
1844        }
1845
1846        return true;
1847    }
1848
1849    private final void startActivityLocked(ActivityRecord r, boolean newTask,
1850            boolean doResume, boolean keepCurTransition, Bundle options) {
1851        final int NH = mHistory.size();
1852
1853        int addPos = -1;
1854
1855        if (!newTask) {
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);
1860                if (p.finishing) {
1861                    continue;
1862                }
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.
1867                    addPos = i+1;
1868                    if (!startIt) {
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,
1873                                    here);
1874                        }
1875                        mHistory.add(addPos, r);
1876                        r.putInHistory();
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();
1882                        }
1883                        ActivityOptions.abort(options);
1884                        return;
1885                    }
1886                    break;
1887                }
1888                if (p.fullscreen) {
1889                    startIt = false;
1890                }
1891            }
1892        }
1893
1894        // Place a new activity at top of stack, so it is next to interact
1895        // with the user.
1896        if (addPos < 0) {
1897            addPos = NH;
1898        }
1899
1900        // If we are not placing the new activity frontmost, we do not want
1901        // to deliver the onUserLeaving callback to the actual frontmost
1902        // activity
1903        if (addPos < NH) {
1904            mUserLeaving = false;
1905            if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() behind front, mUserLeaving=false");
1906        }
1907
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);
1913        }
1914        mHistory.add(addPos, r);
1915        r.putInHistory();
1916        r.frontOfTask = newTask;
1917        if (NH > 0) {
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;
1923            if (proc == null) {
1924                proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
1925            }
1926            if (proc == null || proc.thread == null) {
1927                showStartingIcon = true;
1928            }
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);
1935            } else {
1936                mService.mWindowManager.prepareAppTransition(newTask
1937                        ? AppTransition.TRANSIT_TASK_OPEN
1938                        : AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
1939                mNoAnimActivities.remove(r);
1940            }
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;
1946            if (newTask) {
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;
1956                }
1957            }
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;
1964                if (prev != null) {
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;
1970                }
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);
1977            }
1978        } else {
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);
1985        }
1986        if (VALIDATE_TOKENS) {
1987            validateAppTokensLocked();
1988        }
1989
1990        if (doResume) {
1991            resumeTopActivityLocked(null);
1992        }
1993    }
1994
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);
2007            }
2008            task.tokens.add(r.appToken);
2009        }
2010        mService.mWindowManager.validateAppTokens(mValidateAppTokens);
2011    }
2012
2013    /**
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.
2016     */
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) {
2025                forceReset = true;
2026            }
2027        }
2028
2029        final TaskRecord task = taskTop.task;
2030
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;
2035        int targetI = 0;
2036        int taskTopI = -1;
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;
2043
2044            if (below != null && below.finishing) {
2045                continue;
2046            }
2047            // Don't check any lower in the stack if we're crossing a user boundary.
2048            if (below != null && below.userId != taskTop.userId) {
2049                break;
2050            }
2051            if (target == null) {
2052                target = below;
2053                targetI = i;
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.
2057                replyChainEnd = -1;
2058                continue;
2059            }
2060
2061            final int flags = target.info.flags;
2062
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;
2067
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!).
2074                if (taskTopI < 0) {
2075                    taskTopI = targetI;
2076                }
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;
2090                        }
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
2099                        // moved.
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);
2109                        } else {
2110                            mService.mCurTask++;
2111                            if (mService.mCurTask <= 0) {
2112                                mService.mCurTask = 1;
2113                            }
2114                            target.setTask(new TaskRecord(mService.mCurTask, target.info, null),
2115                                    null, false);
2116                            target.task.affinityIntent = target.intent;
2117                            if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
2118                                    + " out to new task " + target.task);
2119                        }
2120                        mService.mWindowManager.setAppGroupId(target.appToken, task.taskId);
2121                        if (replyChainEnd < 0) {
2122                            replyChainEnd = targetI;
2123                        }
2124                        int dstPos = 0;
2125                        ThumbnailHolder curThumbHolder = target.thumbHolder;
2126                        boolean gotOptions = !canMoveOptions;
2127                        for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
2128                            p = mHistory.get(srcPos);
2129                            if (p.finishing) {
2130                                continue;
2131                            }
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) {
2140                                    gotOptions = true;
2141                                }
2142                            }
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 "
2147                                        + dstPos, here);
2148                            }
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);
2153                            dstPos++;
2154                            if (VALIDATE_TOKENS) {
2155                                validateAppTokensLocked();
2156                            }
2157                            i++;
2158                        }
2159                        if (taskTop == p) {
2160                            taskTop = below;
2161                        }
2162                        if (taskTopI == replyChainEnd) {
2163                            taskTopI = -1;
2164                        }
2165                        replyChainEnd = -1;
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() &&
2178                                    (mHistory.get(
2179                                                replyChainEnd)).task == task) {
2180                                replyChainEnd++;
2181                            }
2182                            replyChainEnd--;
2183                        } else if (replyChainEnd < 0) {
2184                            replyChainEnd = targetI;
2185                        }
2186                        ActivityRecord p = null;
2187                        boolean gotOptions = !canMoveOptions;
2188                        for (int srcPos=targetI; srcPos<=replyChainEnd; srcPos++) {
2189                            p = mHistory.get(srcPos);
2190                            if (p.finishing) {
2191                                continue;
2192                            }
2193                            canMoveOptions = false;
2194                            if (!gotOptions && topOptions == null) {
2195                                topOptions = p.takeOptionsLocked();
2196                                if (topOptions != null) {
2197                                    gotOptions = true;
2198                                }
2199                            }
2200                            if (finishActivityLocked(p, srcPos,
2201                                    Activity.RESULT_CANCELED, null, "reset", false)) {
2202                                replyChainEnd--;
2203                                srcPos--;
2204                            }
2205                        }
2206                        if (taskTop == p) {
2207                            taskTop = below;
2208                        }
2209                        if (taskTopI == replyChainEnd) {
2210                            taskTopI = -1;
2211                        }
2212                        replyChainEnd = -1;
2213                    } else {
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.
2217                        replyChainEnd = -1;
2218                    }
2219                } else {
2220                    // Reached the bottom of the task -- any reply chain
2221                    // should be left as-is.
2222                    replyChainEnd = -1;
2223                }
2224
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;
2235                }
2236
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;
2254                    }
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);
2260                        if (p.finishing) {
2261                            continue;
2262                        }
2263                        if (finishActivityLocked(p, srcPos,
2264                                Activity.RESULT_CANCELED, null, "reset", false)) {
2265                            taskTopI--;
2266                            lastReparentPos--;
2267                            replyChainEnd--;
2268                            srcPos--;
2269                        }
2270                    }
2271                    replyChainEnd = -1;
2272                } else {
2273                    if (replyChainEnd < 0) {
2274                        replyChainEnd = targetI;
2275                    }
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);
2280                        if (p.finishing) {
2281                            continue;
2282                        }
2283                        if (lastReparentPos < 0) {
2284                            lastReparentPos = taskTopI;
2285                            taskTop = p;
2286                        } else {
2287                            lastReparentPos--;
2288                        }
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);
2294                        }
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();
2305                        }
2306                    }
2307                    replyChainEnd = -1;
2308
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);
2316                            if (p.finishing) {
2317                                continue;
2318                            }
2319                            if (p.intent.getComponent().equals(target.intent.getComponent())) {
2320                                if (finishActivityLocked(p, j,
2321                                        Activity.RESULT_CANCELED, null, "replace", false)) {
2322                                    taskTopI--;
2323                                    lastReparentPos--;
2324                                }
2325                            }
2326                        }
2327                    }
2328                }
2329
2330            } else if (below != null && below.task != target.task) {
2331                // We hit the botton of a task; the reply chain can't
2332                // pass through it.
2333                replyChainEnd = -1;
2334            }
2335
2336            target = below;
2337            targetI = i;
2338        }
2339
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);
2345            } else {
2346                topOptions.abort();
2347            }
2348        }
2349
2350        return taskTop;
2351    }
2352
2353    /**
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.
2359     *
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.
2363     */
2364    private final ActivityRecord performClearTaskLocked(int taskId,
2365            ActivityRecord newR, int launchFlags) {
2366        int i = mHistory.size();
2367
2368        // First find the requested task.
2369        while (i > 0) {
2370            i--;
2371            ActivityRecord r = mHistory.get(i);
2372            if (r.task.taskId == taskId) {
2373                i++;
2374                break;
2375            }
2376        }
2377
2378        // Now clear it.
2379        while (i > 0) {
2380            i--;
2381            ActivityRecord r = mHistory.get(i);
2382            if (r.finishing) {
2383                continue;
2384            }
2385            if (r.task.taskId != taskId) {
2386                return null;
2387            }
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)) {
2392                    i++;
2393                    r = mHistory.get(i);
2394                    if (r.task.taskId != taskId) {
2395                        break;
2396                    }
2397                    if (r.finishing) {
2398                        continue;
2399                    }
2400                    ActivityOptions opts = r.takeOptionsLocked();
2401                    if (opts != null) {
2402                        ret.updateOptionsLocked(opts);
2403                    }
2404                    if (finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2405                            null, "clear", false)) {
2406                        i--;
2407                    }
2408                }
2409
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);
2417                        if (index >= 0) {
2418                            finishActivityLocked(ret, index, Activity.RESULT_CANCELED,
2419                                    null, "clear", false);
2420                        }
2421                        return null;
2422                    }
2423                }
2424
2425                return ret;
2426            }
2427        }
2428
2429        return null;
2430    }
2431
2432    /**
2433     * Completely remove all activities associated with an existing
2434     * task starting at a specified index.
2435     */
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.
2441                return;
2442            }
2443            if (r.finishing) {
2444                i++;
2445                continue;
2446            }
2447            if (!finishActivityLocked(r, i, Activity.RESULT_CANCELED,
2448                    null, "clear", false)) {
2449                i++;
2450            }
2451        }
2452    }
2453
2454    /**
2455     * Completely remove all activities associated with an existing task.
2456     */
2457    private final void performClearTaskLocked(int taskId) {
2458        int i = mHistory.size();
2459
2460        // First find the requested task.
2461        while (i > 0) {
2462            i--;
2463            ActivityRecord r = mHistory.get(i);
2464            if (r.task.taskId == taskId) {
2465                i++;
2466                break;
2467            }
2468        }
2469
2470        // Now find the start and clear it.
2471        while (i > 0) {
2472            i--;
2473            ActivityRecord r = mHistory.get(i);
2474            if (r.finishing) {
2475                continue;
2476            }
2477            if (r.task.taskId != taskId) {
2478                // We hit the bottom.  Now finish it all...
2479                performClearTaskAtIndexLocked(taskId, i+1);
2480                return;
2481            }
2482        }
2483    }
2484
2485    /**
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.
2488     */
2489    private final int findActivityInHistoryLocked(ActivityRecord r, int task) {
2490        int i = mHistory.size();
2491        while (i > 0) {
2492            i--;
2493            ActivityRecord candidate = mHistory.get(i);
2494            if (candidate.finishing) {
2495                continue;
2496            }
2497            if (candidate.task.taskId != task) {
2498                break;
2499            }
2500            if (candidate.realActivity.equals(r.realActivity)) {
2501                return i;
2502            }
2503        }
2504
2505        return -1;
2506    }
2507
2508    /**
2509     * Reorder the history stack so that the activity at the given index is
2510     * brought to the front.
2511     */
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 "
2520                    + top, here);
2521        }
2522        mHistory.add(top, newTop);
2523        oldTop.frontOfTask = false;
2524        newTop.frontOfTask = true;
2525        return newTop;
2526    }
2527
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) {
2533
2534        int err = ActivityManager.START_SUCCESS;
2535
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;
2542            } else {
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;
2547            }
2548        }
2549
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));
2554        }
2555
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 + ")");
2562            if (index >= 0) {
2563                sourceRecord = mHistory.get(index);
2564                if (requestCode >= 0 && !sourceRecord.finishing) {
2565                    resultRecord = sourceRecord;
2566                }
2567            }
2568        }
2569
2570        int launchFlags = intent.getFlags();
2571
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;
2579            }
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);
2587            }
2588        }
2589
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;
2594        }
2595
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;
2600        }
2601
2602        if (err != ActivityManager.START_SUCCESS) {
2603            if (resultRecord != null) {
2604                sendActivityResultLocked(-1,
2605                    resultRecord, resultWho, requestCode,
2606                    Activity.RESULT_CANCELED, null);
2607            }
2608            mDismissKeyguardOnNextActivity = false;
2609            ActivityOptions.abort(options);
2610            return err;
2611        }
2612
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);
2622            }
2623            mDismissKeyguardOnNextActivity = false;
2624            String msg;
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;
2630            } else {
2631                msg = "Permission Denial: starting " + intent.toString()
2632                        + " from " + callerApp + " (pid=" + callingPid
2633                        + ", uid=" + callingUid + ")"
2634                        + " requires " + aInfo.permission;
2635            }
2636            Slog.w(TAG, msg);
2637            throw new SecurityException(msg);
2638        }
2639
2640        if (mMainStack) {
2641            if (mService.mController != null) {
2642                boolean abort = false;
2643                try {
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;
2651                }
2652
2653                if (abort) {
2654                    if (resultRecord != null) {
2655                        sendActivityResultLocked(-1,
2656                            resultRecord, resultWho, requestCode,
2657                            Activity.RESULT_CANCELED, null);
2658                    }
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;
2664                }
2665            }
2666        }
2667
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) {
2672            outActivity[0] = r;
2673        }
2674
2675        if (mMainStack) {
2676            if (mResumedActivity == null
2677                    || mResumedActivity.info.applicationInfo.uid != callingUid) {
2678                if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
2679                    PendingActivityLaunch pal = new PendingActivityLaunch();
2680                    pal.r = r;
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;
2687                }
2688            }
2689
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;
2697            } else {
2698                mService.mDidAppSwitch = true;
2699            }
2700
2701            mService.doPendingActivityLaunchesLocked(false);
2702        }
2703
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();
2713        }
2714        return err;
2715    }
2716
2717    final void moveHomeToFrontFromLaunchLocked(int launchFlags) {
2718        if ((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();
2724        }
2725    }
2726
2727    final int startActivityUncheckedLocked(ActivityRecord r,
2728            ActivityRecord sourceRecord, int startFlags, boolean doResume,
2729            Bundle options) {
2730        final Intent intent = r.intent;
2731        final int callingUid = r.launchedFromUid;
2732
2733        int launchFlags = intent.getFlags();
2734
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);
2740
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.
2744        if (!doResume) {
2745            r.delayedResume = true;
2746        }
2747
2748        ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP)
2749                != 0 ? r : null;
2750
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);
2759            }
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;
2763            }
2764        }
2765
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: "
2771                      + intent);
2772                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
2773            }
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
2777            // own task.
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;
2784        }
2785
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);
2796            r.resultTo = null;
2797        }
2798
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
2822                        // base intent.
2823                        taskTop.task.setIntent(intent, r.info);
2824                    }
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.
2839                            movedHome = true;
2840                            moveHomeToFrontFromLaunchLocked(launchFlags);
2841                            moveTaskToFrontLocked(taskTop.task, r, options);
2842                            options = null;
2843                        }
2844                    }
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);
2849                    }
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.
2855                        if (doResume) {
2856                            resumeTopActivityLocked(null, options);
2857                        } else {
2858                            ActivityOptions.abort(options);
2859                        }
2860                        return ActivityManager.START_RETURN_INTENT_TO_CALLER;
2861                    }
2862                    if ((launchFlags &
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
2877                        // initial state.
2878                        ActivityRecord top = performClearTaskLocked(
2879                                taskTop.task.taskId, r, launchFlags);
2880                        if (top != null) {
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
2885                                // intent.
2886                                top.task.setIntent(r.intent, r.info);
2887                            }
2888                            logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
2889                            top.deliverNewIntentLocked(callingUid, r.intent);
2890                        } else {
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
2898                            // right place.
2899                            sourceRecord = taskTop;
2900                        }
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
2907                        // desires.
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);
2914                            }
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;
2922                        }
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);
2940                    }
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.
2945                        if (doResume) {
2946                            resumeTopActivityLocked(null, options);
2947                        } else {
2948                            ActivityOptions.abort(options);
2949                        }
2950                        return ActivityManager.START_TASK_TO_FRONT;
2951                    }
2952                }
2953            }
2954        }
2955
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);
2961
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
2965            // once.
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.
2976                            if (doResume) {
2977                                resumeTopActivityLocked(null);
2978                            }
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;
2985                            }
2986                            top.deliverNewIntentLocked(callingUid, r.intent);
2987                            return ActivityManager.START_DELIVERED_TO_TOP;
2988                        }
2989                    }
2990                }
2991            }
2992
2993        } else {
2994            if (r.resultTo != null) {
2995                sendActivityResultLocked(-1,
2996                        r.resultTo, r.resultWho, r.requestCode,
2997                    Activity.RESULT_CANCELED, null);
2998            }
2999            ActivityOptions.abort(options);
3000            return ActivityManager.START_CLASS_NOT_FOUND;
3001        }
3002
3003        boolean newTask = false;
3004        boolean keepCurTransition = false;
3005
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;
3014                }
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);
3018            } else {
3019                r.setTask(reuseTask, reuseTask, true);
3020            }
3021            newTask = true;
3022            if (!movedHome) {
3023                moveHomeToFrontFromLaunchLocked(launchFlags);
3024            }
3025
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;
3035                if (top != null) {
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.
3040                    if (doResume) {
3041                        resumeTopActivityLocked(null);
3042                    }
3043                    ActivityOptions.abort(options);
3044                    return ActivityManager.START_DELIVERED_TO_TOP;
3045                }
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);
3052                if (where >= 0) {
3053                    ActivityRecord top = moveActivityToFrontLocked(where);
3054                    logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
3055                    top.updateOptionsLocked(options);
3056                    top.deliverNewIntentLocked(callingUid, r.intent);
3057                    if (doResume) {
3058                        resumeTopActivityLocked(null);
3059                    }
3060                    return ActivityManager.START_DELIVERED_TO_TOP;
3061                }
3062            }
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
3065            // it.
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);
3069
3070        } else {
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
3078                    ? prev.task
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);
3082        }
3083
3084        mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3085                intent, r.getUriPermissionsLocked());
3086
3087        if (newTask) {
3088            EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
3089        }
3090        logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
3091        startActivityLocked(r, newTask, doResume, keepCurTransition, options);
3092        return ActivityManager.START_SUCCESS;
3093    }
3094
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.
3098        ActivityInfo aInfo;
3099        try {
3100            ResolveInfo rInfo =
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) {
3107            aInfo = null;
3108        }
3109
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));
3117
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);
3122                }
3123            }
3124
3125            if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
3126                if (!aInfo.processName.equals("system")) {
3127                    mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
3128                }
3129            }
3130
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);
3136                }
3137            }
3138        }
3139        return aInfo;
3140    }
3141
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");
3150        }
3151        boolean componentSpecified = intent.getComponent() != null;
3152
3153        // Don't modify the client's object!
3154        intent = new Intent(intent);
3155
3156        // Collect information about the target of the Intent.
3157        ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
3158                profileFile, profileFd, userId);
3159
3160        synchronized (mService) {
3161            int callingPid;
3162            if (callingUid >= 0) {
3163                callingPid = -1;
3164            } else if (caller == null) {
3165                callingPid = Binder.getCallingPid();
3166                callingUid = Binder.getCallingUid();
3167            } else {
3168                callingPid = callingUid = -1;
3169            }
3170
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);
3175
3176            final long origId = Binder.clearCallingIdentity();
3177
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;
3193                            } else {
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;
3199                            }
3200                        }
3201
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);
3207
3208                        Intent newIntent = new Intent();
3209                        if (requestCode >= 0) {
3210                            // Caller is requesting a result.
3211                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
3212                        }
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,
3218                                    hist.packageName);
3219                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
3220                                    hist.task.taskId);
3221                        }
3222                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
3223                                aInfo.packageName);
3224                        newIntent.setFlags(intent.getFlags());
3225                        newIntent.setClassName("android",
3226                                HeavyWeightSwitcherActivity.class.getName());
3227                        intent = newIntent;
3228                        resolvedType = null;
3229                        caller = null;
3230                        callingUid = Binder.getCallingUid();
3231                        callingPid = Binder.getCallingPid();
3232                        componentSpecified = true;
3233                        try {
3234                            ResolveInfo rInfo =
3235                                AppGlobals.getPackageManager().resolveIntent(
3236                                        intent, null,
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) {
3242                            aInfo = null;
3243                        }
3244                    }
3245                }
3246            }
3247
3248            int res = startActivityLocked(caller, intent, resolvedType,
3249                    aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
3250                    callingPackage, startFlags, options, componentSpecified, null);
3251
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);
3263            }
3264
3265            Binder.restoreCallingIdentity(origId);
3266
3267            if (outResult != null) {
3268                outResult.result = res;
3269                if (res == ActivityManager.START_SUCCESS) {
3270                    mWaitingActivityLaunched.add(outResult);
3271                    do {
3272                        try {
3273                            mService.wait();
3274                        } catch (InterruptedException e) {
3275                        }
3276                    } while (!outResult.timeout && outResult.who == null);
3277                } else if (res == ActivityManager.START_TASK_TO_FRONT) {
3278                    ActivityRecord r = this.topRunningActivityLocked(null);
3279                    if (r.nowVisible) {
3280                        outResult.timeout = false;
3281                        outResult.who = new ComponentName(r.info.packageName, r.info.name);
3282                        outResult.totalTime = 0;
3283                        outResult.thisTime = 0;
3284                    } else {
3285                        outResult.thisTime = SystemClock.uptimeMillis();
3286                        mWaitingActivityVisible.add(outResult);
3287                        do {
3288                            try {
3289                                mService.wait();
3290                            } catch (InterruptedException e) {
3291                            }
3292                        } while (!outResult.timeout && outResult.who == null);
3293                    }
3294                }
3295            }
3296
3297            return res;
3298        }
3299    }
3300
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");
3306        }
3307        if (resolvedTypes == null) {
3308            throw new NullPointerException("resolvedTypes is null");
3309        }
3310        if (intents.length != resolvedTypes.length) {
3311            throw new IllegalArgumentException("intents are length different than resolvedTypes");
3312        }
3313
3314        ActivityRecord[] outActivity = new ActivityRecord[1];
3315
3316        int callingPid;
3317        if (callingUid >= 0) {
3318            callingPid = -1;
3319        } else if (caller == null) {
3320            callingPid = Binder.getCallingPid();
3321            callingUid = Binder.getCallingUid();
3322        } else {
3323            callingPid = callingUid = -1;
3324        }
3325        final long origId = Binder.clearCallingIdentity();
3326        try {
3327            synchronized (mService) {
3328
3329                for (int i=0; i<intents.length; i++) {
3330                    Intent intent = intents[i];
3331                    if (intent == null) {
3332                        continue;
3333                    }
3334
3335                    // Refuse possible leaked file descriptors
3336                    if (intent != null && intent.hasFileDescriptors()) {
3337                        throw new IllegalArgumentException("File descriptors passed in Intent");
3338                    }
3339
3340                    boolean componentSpecified = intent.getComponent() != null;
3341
3342                    // Don't modify the client's object!
3343                    intent = new Intent(intent);
3344
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);
3350
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");
3355                    }
3356
3357                    Bundle theseOptions;
3358                    if (options != null && i == intents.length-1) {
3359                        theseOptions = options;
3360                    } else {
3361                        theseOptions = null;
3362                    }
3363                    int res = startActivityLocked(caller, intent, resolvedTypes[i],
3364                            aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
3365                            0, theseOptions, componentSpecified, outActivity);
3366                    if (res < 0) {
3367                        return res;
3368                    }
3369
3370                    resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
3371                }
3372            }
3373        } finally {
3374            Binder.restoreCallingIdentity(origId);
3375        }
3376
3377        return ActivityManager.START_SUCCESS;
3378    }
3379
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;
3385            if (r != null) {
3386                w.who = new ComponentName(r.info.packageName, r.info.name);
3387            }
3388            w.thisTime = thisTime;
3389            w.totalTime = totalTime;
3390        }
3391        mService.notifyAll();
3392    }
3393
3394    void reportActivityVisibleLocked(ActivityRecord r) {
3395        for (int i=mWaitingActivityVisible.size()-1; i>=0; i--) {
3396            WaitResult w = mWaitingActivityVisible.get(i);
3397            w.timeout = false;
3398            if (r != null) {
3399                w.who = new ComponentName(r.info.packageName, r.info.name);
3400            }
3401            w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
3402            w.thisTime = w.totalTime;
3403        }
3404        mService.notifyAll();
3405
3406        if (mDismissKeyguardOnNextActivity) {
3407            mDismissKeyguardOnNextActivity = false;
3408            mService.mWindowManager.dismissKeyguard();
3409        }
3410    }
3411
3412    void sendActivityResultLocked(int callingUid, ActivityRecord r,
3413            String resultWho, int requestCode, int resultCode, Intent data) {
3414
3415        if (callingUid > 0) {
3416            mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
3417                    data, r.getUriPermissionsLocked());
3418        }
3419
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) {
3424            try {
3425                ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
3426                list.add(new ResultInfo(resultWho, requestCode,
3427                        resultCode, data));
3428                r.app.thread.scheduleSendResult(r.appToken, list);
3429                return;
3430            } catch (Exception e) {
3431                Slog.w(TAG, "Exception thrown sending result to " + r, e);
3432            }
3433        }
3434
3435        r.addResultLocked(null, resultWho, requestCode, resultCode, data);
3436    }
3437
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) {
3442            if (!r.finishing) {
3443                if (!mService.mSleeping) {
3444                    if (DEBUG_STATES) {
3445                        Slog.d(TAG, "no-history finish of " + r);
3446                    }
3447                    requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
3448                            "no-history", false);
3449                } else {
3450                    if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r
3451                            + " on stop because we're just sleeping");
3452                }
3453            }
3454        }
3455
3456        if (r.app != null && r.app.thread != null) {
3457            if (mMainStack) {
3458                if (mService.mFocusedActivity == r) {
3459                    mService.setFocusedActivityLocked(topRunningActivityLocked(null));
3460                }
3461            }
3462            r.resumeKeyDispatchingLocked();
3463            try {
3464                r.stopped = false;
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);
3470                if (!r.visible) {
3471                    mService.mWindowManager.setAppVisibility(r.appToken, false);
3472                }
3473                r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
3474                if (mService.isSleeping()) {
3475                    r.setSleeping(true);
3476                }
3477                Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG);
3478                msg.obj = r;
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
3483                // up.
3484                Slog.w(TAG, "Exception thrown during pause", e);
3485                // Just in case, assume it to be stopped.
3486                r.stopped = true;
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");
3491                }
3492            }
3493        }
3494    }
3495
3496    final ArrayList<ActivityRecord> processStoppingActivitiesLocked(
3497            boolean remove) {
3498        int N = mStoppingActivities.size();
3499        if (N <= 0) return null;
3500
3501        ArrayList<ActivityRecord> stops = null;
3502
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;
3514                if (s.finishing) {
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);
3522                }
3523            }
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>();
3528                }
3529                stops.add(s);
3530                mStoppingActivities.remove(i);
3531                N--;
3532                i--;
3533            }
3534        }
3535
3536        return stops;
3537    }
3538
3539    final void scheduleIdleLocked() {
3540        Message msg = Message.obtain();
3541        msg.what = IDLE_NOW_MSG;
3542        mHandler.sendMessage(msg);
3543    }
3544
3545    final ActivityRecord activityIdleInternal(IBinder token, boolean fromTimeout,
3546            Configuration config) {
3547        if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
3548
3549        ActivityRecord res = null;
3550
3551        ArrayList<ActivityRecord> stops = null;
3552        ArrayList<ActivityRecord> finishes = null;
3553        ArrayList<ActivityRecord> thumbnails = null;
3554        ArrayList<UserStartedState> startingUsers = null;
3555        int NS = 0;
3556        int NF = 0;
3557        int NT = 0;
3558        IApplicationThread sendThumbnail = null;
3559        boolean booting = false;
3560        boolean enableScreen = false;
3561        boolean activityRemoved = false;
3562
3563        synchronized (mService) {
3564            ActivityRecord r = ActivityRecord.forToken(token);
3565            if (r != null) {
3566                mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
3567                r.finishLaunchTickingLocked();
3568            }
3569
3570            // Get the activity record.
3571            int index = indexOfActivityLocked(r);
3572            if (index >= 0) {
3573                res = r;
3574
3575                if (fromTimeout) {
3576                    reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
3577                }
3578
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;
3586                }
3587
3588                // No longer need to keep the device awake.
3589                if (mResumedActivity == r && mLaunchingActivity.isHeld()) {
3590                    mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
3591                    mLaunchingActivity.release();
3592                }
3593
3594                // We are now idle.  If someone is waiting for a thumbnail from
3595                // us, we can now deliver.
3596                r.idle = true;
3597                mService.scheduleAppGcsLocked();
3598                if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
3599                    sendThumbnail = r.app.thread;
3600                    r.thumbnailNeeded = false;
3601                }
3602
3603                // If this activity is fullscreen, set up to hide those under it.
3604
3605                if (DEBUG_VISBILITY) Slog.v(TAG, "Idle activity for " + r);
3606                ensureActivitiesVisibleLocked(null, 0);
3607
3608                //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
3609                if (mMainStack) {
3610                    if (!mService.mBooted) {
3611                        mService.mBooted = true;
3612                        enableScreen = true;
3613                    }
3614                }
3615
3616            } else if (fromTimeout) {
3617                reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
3618            }
3619
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();
3626            }
3627            if ((NT=mCancelledThumbnails.size()) > 0) {
3628                thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
3629                mCancelledThumbnails.clear();
3630            }
3631
3632            if (mMainStack) {
3633                booting = mService.mBooting;
3634                mService.mBooting = false;
3635            }
3636            if (mStartingUsers.size() > 0) {
3637                startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
3638                mStartingUsers.clear();
3639            }
3640        }
3641
3642        int i;
3643
3644        // Send thumbnail if requested.
3645        if (sendThumbnail != null) {
3646            try {
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);
3651            }
3652        }
3653
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) {
3659                if (r.finishing) {
3660                    finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
3661                } else {
3662                    stopActivityLocked(r);
3663                }
3664            }
3665        }
3666
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");
3673            }
3674        }
3675
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);
3680        }
3681
3682        if (booting) {
3683            mService.finishBooting();
3684        } else if (startingUsers != null) {
3685            for (i=0; i<startingUsers.size(); i++) {
3686                mService.finishUserSwitch(startingUsers.get(i));
3687            }
3688        }
3689
3690        mService.trimApplications();
3691        //dump();
3692        //mWindowManager.dump();
3693
3694        if (enableScreen) {
3695            mService.enableScreenAfterBoot();
3696        }
3697
3698        if (activityRemoved) {
3699            resumeTopActivityLocked(null);
3700        }
3701
3702        return res;
3703    }
3704
3705    /**
3706     * @return Returns true if the activity is being finished, false if for
3707     * some reason it is being left as-is.
3708     */
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);
3716        if (index < 0) {
3717            return false;
3718        }
3719        ActivityRecord r = mHistory.get(index);
3720
3721        finishActivityLocked(r, index, resultCode, resultData, reason, oomAdj);
3722        return true;
3723    }
3724
3725    final void finishSubActivityLocked(IBinder token, String resultWho, int requestCode) {
3726        ActivityRecord self = isInStackLocked(token);
3727        if (self == null) {
3728            return;
3729        }
3730
3731        int i;
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);
3739                }
3740            }
3741        }
3742        mService.updateOomAdjLocked();
3743    }
3744
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);
3749        if (index < 0) {
3750            return false;
3751        }
3752        ActivityRecord r = mHistory.get(index);
3753
3754        while (index >= 0) {
3755            ActivityRecord cur = mHistory.get(index);
3756            if (cur.task != r.task) {
3757                break;
3758            }
3759            if (cur.taskAffinity == null && r.taskAffinity != null) {
3760                break;
3761            }
3762            if (cur.taskAffinity != null && !cur.taskAffinity.equals(r.taskAffinity)) {
3763                break;
3764            }
3765            finishActivityLocked(cur, index, Activity.RESULT_CANCELED, null,
3766                    "request-affinity", true);
3767            index--;
3768        }
3769        return true;
3770    }
3771
3772    final void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
3773        // send the result
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());
3783            }
3784            resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
3785                                     resultData);
3786            r.resultTo = null;
3787        }
3788        else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
3789
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.
3793        r.results = null;
3794        r.pendingResults = null;
3795        r.newIntents = null;
3796        r.icicle = null;
3797    }
3798
3799    /**
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.
3802     */
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);
3806    }
3807
3808    /**
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.
3811     */
3812    final boolean finishActivityLocked(ActivityRecord r, int index, int resultCode,
3813            Intent resultData, String reason, boolean immediate, boolean oomAdj) {
3814        if (r.finishing) {
3815            Slog.w(TAG, "Duplicate finish request for " + r);
3816            return false;
3817        }
3818
3819        r.makeFinishing();
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;
3829                }
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);
3835                }
3836            }
3837        }
3838
3839        r.pauseKeyDispatchingLocked();
3840        if (mMainStack) {
3841            if (mService.mFocusedActivity == r) {
3842                mService.setFocusedActivityLocked(topRunningActivityLocked(null));
3843            }
3844        }
3845
3846        finishActivityResultsLocked(r, resultCode, resultData);
3847
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);
3853        }
3854
3855        if (immediate) {
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);
3866
3867            // Tell window manager to prepare for this one to be removed.
3868            mService.mWindowManager.setAppVisibility(r.appToken, false);
3869
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);
3874            }
3875
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;
3882        } else {
3883            if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
3884        }
3885
3886        return false;
3887    }
3888
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;
3892
3893    private final ActivityRecord finishCurrentActivityLocked(ActivityRecord r,
3894            int mode, boolean oomAdj) {
3895        final int index = indexOfActivityLocked(r);
3896        if (index < 0) {
3897            return null;
3898        }
3899
3900        return finishCurrentActivityLocked(r, index, mode, oomAdj);
3901    }
3902
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
3914                    // them out.
3915                    scheduleIdleLocked();
3916                } else {
3917                    checkReadyForSleepLocked();
3918                }
3919            }
3920            if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
3921                    + " (finish requested)");
3922            r.state = ActivityState.STOPPING;
3923            if (oomAdj) {
3924                mService.updateOomAdjLocked();
3925            }
3926            return r;
3927        }
3928
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;
3935        }
3936        final ActivityState prevState = r.state;
3937        if (DEBUG_STATES) Slog.v(TAG, "Moving to FINISHING: " + r);
3938        r.state = ActivityState.FINISHING;
3939
3940        if (mode == FINISH_IMMEDIATELY
3941                || prevState == ActivityState.STOPPED
3942                || prevState == ActivityState.INITIALIZING) {
3943            // If this activity is already stopped, we can just finish
3944            // it right now.
3945            boolean activityRemoved = destroyActivityLocked(r, true,
3946                    oomAdj, "finish-imm");
3947            if (activityRemoved) {
3948                resumeTopActivityLocked(null);
3949            }
3950            return activityRemoved ? null : r;
3951        } else {
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);
3957        }
3958        return r;
3959    }
3960
3961    /**
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.
3967     */
3968    final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices,
3969            boolean setState) {
3970        if (mResumedActivity == r) {
3971            mResumedActivity = null;
3972        }
3973        if (mService.mFocusedActivity == r) {
3974            mService.mFocusedActivity = null;
3975        }
3976
3977        r.configDestroy = false;
3978        r.frozenBeforeDestroy = false;
3979
3980        if (setState) {
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);
3984            r.app = null;
3985        }
3986
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);
3992
3993        // Remove any pending results.
3994        if (r.finishing && r.pendingResults != null) {
3995            for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
3996                PendingIntentRecord rec = apr.get();
3997                if (rec != null) {
3998                    mService.cancelIntentSenderLocked(rec, false);
3999                }
4000            }
4001            r.pendingResults = null;
4002        }
4003
4004        if (cleanServices) {
4005            cleanUpActivityServicesLocked(r);
4006        }
4007
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);
4013        }
4014
4015        // Get rid of any pending idle timeouts.
4016        removeTimeoutsForActivityLocked(r);
4017    }
4018
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();
4025    }
4026
4027    final void removeActivityFromHistoryLocked(ActivityRecord r) {
4028        finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
4029        r.makeFinishing();
4030        if (DEBUG_ADD_REMOVE) {
4031            RuntimeException here = new RuntimeException("here");
4032            here.fillInStackTrace();
4033            Slog.i(TAG, "Removing activity " + r + " from stack");
4034        }
4035        mHistory.remove(r);
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);
4042        r.app = null;
4043        mService.mWindowManager.removeAppToken(r.appToken);
4044        if (VALIDATE_TOKENS) {
4045            validateAppTokensLocked();
4046        }
4047        cleanUpActivityServicesLocked(r);
4048        r.removeUriPermissionsLocked();
4049    }
4050
4051    /**
4052     * Perform clean-up of service connections in an activity record.
4053     */
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);
4061            }
4062            r.connections = null;
4063        }
4064    }
4065
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);
4070    }
4071
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);
4077            if (r.finishing) {
4078                continue;
4079            }
4080            if (r.fullscreen) {
4081                lastIsOpaque = true;
4082            }
4083            if (owner != null && r.app != owner) {
4084                continue;
4085            }
4086            if (!lastIsOpaque) {
4087                continue;
4088            }
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;
4100                }
4101            }
4102        }
4103        if (activityRemoved) {
4104            resumeTopActivityLocked(null);
4105        }
4106    }
4107
4108    /**
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.
4113     */
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);
4122
4123        boolean removedFromHistory = false;
4124
4125        cleanUpActivityLocked(r, false, false);
4126
4127        final boolean hadApp = r.app != null;
4128
4129        if (hadApp) {
4130            if (removeFromApp) {
4131                int idx = r.app.activities.indexOf(r);
4132                if (idx >= 0) {
4133                    r.app.activities.remove(idx);
4134                }
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);
4139                }
4140                if (r.app.activities.size() == 0) {
4141                    // No longer have activities, so update oom adj.
4142                    mService.updateOomAdjLocked();
4143                }
4144            }
4145
4146            boolean skipDestroy = false;
4147
4148            try {
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
4155                // up.
4156                //Slog.w(TAG, "Exception thrown during finish", e);
4157                if (r.finishing) {
4158                    removeActivityFromHistoryLocked(r);
4159                    removedFromHistory = true;
4160                    skipDestroy = true;
4161                }
4162            }
4163
4164            r.nowVisible = false;
4165
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
4172            // list.
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);
4178                msg.obj = r;
4179                mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
4180            } else {
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);
4185                r.app = null;
4186            }
4187        } else {
4188            // remove this record from the history.
4189            if (r.finishing) {
4190                removeActivityFromHistoryLocked(r);
4191                removedFromHistory = true;
4192            } else {
4193                if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r
4194                        + " (no app)");
4195                r.state = ActivityState.DESTROYED;
4196                if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r);
4197                r.app = null;
4198            }
4199        }
4200
4201        r.configChangeFlags = 0;
4202
4203        if (!mLRUActivities.remove(r) && hadApp) {
4204            Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
4205        }
4206
4207        return removedFromHistory;
4208    }
4209
4210    final void activityDestroyed(IBinder token) {
4211        synchronized (mService) {
4212            final long origId = Binder.clearCallingIdentity();
4213            try {
4214                ActivityRecord r = ActivityRecord.forToken(token);
4215                if (r != null) {
4216                    mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
4217                }
4218
4219                int index = indexOfActivityLocked(r);
4220                if (index >= 0) {
4221                    if (r.state == ActivityState.DESTROYING) {
4222                        cleanUpActivityLocked(r, true, false);
4223                        removeActivityFromHistoryLocked(r);
4224                    }
4225                }
4226                resumeTopActivityLocked(null);
4227            } finally {
4228                Binder.restoreCallingIdentity(origId);
4229            }
4230        }
4231    }
4232
4233    private void removeHistoryRecordsForAppLocked(ArrayList list, ProcessRecord app,
4234            String listName) {
4235        int i = list.size();
4236        if (DEBUG_CLEANUP) Slog.v(
4237            TAG, "Removing app " + app + " from list " + listName
4238            + " with " + i + " entries");
4239        while (i > 0) {
4240            i--;
4241            ActivityRecord r = (ActivityRecord)list.get(i);
4242            if (DEBUG_CLEANUP) Slog.v(TAG, "Record #" + i + " " + r);
4243            if (r.app == app) {
4244                if (DEBUG_CLEANUP) Slog.v(TAG, "---> REMOVING this entry!");
4245                list.remove(i);
4246                removeTimeoutsForActivityLocked(r);
4247            }
4248        }
4249    }
4250
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");
4258
4259        boolean hasVisibleActivities = false;
4260
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");
4265        while (i > 0) {
4266            i--;
4267            ActivityRecord r = (ActivityRecord)mHistory.get(i);
4268            if (DEBUG_CLEANUP) Slog.v(
4269                TAG, "Record #" + i + " " + r + ": app=" + r.app);
4270            if (r.app == app) {
4271                boolean remove;
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.
4275                    remove = true;
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.
4280                    remove = true;
4281                } else {
4282                    // The process may be gone, but the activity lives on!
4283                    remove = false;
4284                }
4285                if (remove) {
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);
4294                    }
4295                    if (!r.finishing) {
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");
4301                    }
4302                    removeActivityFromHistoryLocked(r);
4303
4304                } else {
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");
4309                    if (r.visible) {
4310                        hasVisibleActivities = true;
4311                    }
4312                    if (DEBUG_APP) Slog.v(TAG, "Clearing app during removeHistory for activity "
4313                            + r);
4314                    r.app = null;
4315                    r.nowVisible = false;
4316                    if (!r.haveState) {
4317                        if (ActivityStack.DEBUG_SAVED_STATE) Slog.i(TAG,
4318                                "App died, clearing saved state of " + r);
4319                        r.icicle = null;
4320                    }
4321                }
4322
4323                r.stack.cleanUpActivityLocked(r, true, true);
4324            }
4325        }
4326
4327        return hasVisibleActivities;
4328    }
4329
4330    /**
4331     * Move the current home activity's task (if one exists) to the front
4332     * of the stack.
4333     */
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) {
4339                homeTask = hr.task;
4340                break;
4341            }
4342        }
4343        if (homeTask != null) {
4344            moveTaskToFrontLocked(homeTask, null, null);
4345        }
4346    }
4347
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);
4353            } else {
4354                ActivityOptions.abort(options);
4355            }
4356        }
4357        mService.mWindowManager.prepareAppTransition(transit, false);
4358    }
4359
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;
4366                }
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();
4371                }
4372                moveTaskToFrontLocked(hr.task, null, options);
4373                return true;
4374            }
4375        }
4376        return false;
4377    }
4378
4379    final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
4380        if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
4381
4382        final int task = tr.taskId;
4383        int top = mHistory.size()-1;
4384
4385        if (top < 0 || (mHistory.get(top)).task.taskId == task) {
4386            // nothing to do!
4387            if (reason != null &&
4388                    (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
4389                ActivityOptions.abort(options);
4390            } else {
4391                updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
4392            }
4393            return;
4394        }
4395
4396        ArrayList<IBinder> moved = new ArrayList<IBinder>();
4397
4398        // Applying the affinities may have removed entries from the history,
4399        // so get the size again.
4400        top = mHistory.size()-1;
4401        int pos = top;
4402
4403        // Shift all activities with this task up to the top
4404        // of the stack, keeping them in the same internal order.
4405        while (pos >= 0) {
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);
4415                }
4416                mHistory.remove(pos);
4417                mHistory.add(top, r);
4418                moved.add(0, r.appToken);
4419                top--;
4420            }
4421            pos--;
4422        }
4423
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);
4431            if (r != null) {
4432                mNoAnimActivities.add(r);
4433            }
4434            ActivityOptions.abort(options);
4435        } else {
4436            updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
4437        }
4438
4439        mService.mWindowManager.moveAppTokensToTop(moved);
4440        if (VALIDATE_TOKENS) {
4441            validateAppTokensLocked();
4442        }
4443
4444        finishTaskMoveLocked(task);
4445        EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, task);
4446    }
4447
4448    private final void finishTaskMoveLocked(int task) {
4449        resumeTopActivityLocked(null);
4450    }
4451
4452    /**
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.
4456     *
4457     * If a watcher is installed, the action is preflighted and the watcher has an opportunity
4458     * to premeptively cancel the move.
4459     *
4460     * @param task The taskId to collect and move to the bottom.
4461     * @return Returns true if the move completed, false if not.
4462     */
4463    final boolean moveTaskToBackLocked(int task, ActivityRecord reason) {
4464        Slog.i(TAG, "moveTaskToBack: " + task);
4465
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);
4471            if (next == null) {
4472                next = topRunningActivityLocked(null, 0);
4473            }
4474            if (next != null) {
4475                // ask watcher if this is allowed
4476                boolean moveOK = true;
4477                try {
4478                    moveOK = mService.mController.activityResuming(next.packageName);
4479                } catch (RemoteException e) {
4480                    mService.mController = null;
4481                }
4482                if (!moveOK) {
4483                    return false;
4484                }
4485            }
4486        }
4487
4488        ArrayList<IBinder> moved = new ArrayList<IBinder>();
4489
4490        if (DEBUG_TRANSITION) Slog.v(TAG,
4491                "Prepare to back transition: task=" + task);
4492
4493        final int N = mHistory.size();
4494        int bottom = 0;
4495        int pos = 0;
4496
4497        // Shift all activities with this task down to the bottom
4498        // of the stack, keeping them in the same internal order.
4499        while (pos < N) {
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 "
4509                            + bottom, here);
4510                }
4511                mHistory.remove(pos);
4512                mHistory.add(bottom, r);
4513                moved.add(r.appToken);
4514                bottom++;
4515            }
4516            pos++;
4517        }
4518
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);
4524            if (r != null) {
4525                mNoAnimActivities.add(r);
4526            }
4527        } else {
4528            mService.mWindowManager.prepareAppTransition(
4529                    AppTransition.TRANSIT_TASK_TO_BACK, false);
4530        }
4531        mService.mWindowManager.moveAppTokensToBottom(moved);
4532        if (VALIDATE_TOKENS) {
4533            validateAppTokensLocked();
4534        }
4535
4536        finishTaskMoveLocked(task);
4537        return true;
4538    }
4539
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);
4545        }
4546        if (info.mainThumbnail == null) {
4547            info.mainThumbnail = tr.lastThumbnail;
4548        }
4549        return info;
4550    }
4551
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);
4558        }
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;
4564        } else {
4565            return info.subtasks.get(info.numSubThumbbails-1).holder.lastThumbnail;
4566        }
4567    }
4568
4569    public ActivityRecord removeTaskActivitiesLocked(int taskId, int subTaskIndex,
4570            boolean taskRequired) {
4571        TaskAccessInfo info = getTaskAccessInfoLocked(taskId, false);
4572        if (info.root == null) {
4573            if (taskRequired) {
4574                Slog.w(TAG, "removeTaskLocked: unknown taskId " + taskId);
4575            }
4576            return null;
4577        }
4578
4579        if (subTaskIndex < 0) {
4580            // Just remove the entire task.
4581            performClearTaskAtIndexLocked(taskId, info.rootIndex);
4582            return info.root;
4583        }
4584
4585        if (subTaskIndex >= info.subtasks.size()) {
4586            if (taskRequired) {
4587                Slog.w(TAG, "removeTaskLocked: unknown subTaskIndex " + subTaskIndex);
4588            }
4589            return null;
4590        }
4591
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;
4596    }
4597
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();
4602        int j = 0;
4603        ThumbnailHolder holder = null;
4604        while (j < NA) {
4605            ActivityRecord ar = mHistory.get(j);
4606            if (!ar.finishing && ar.task.taskId == taskId) {
4607                thumbs.root = ar;
4608                thumbs.rootIndex = j;
4609                holder = ar.thumbHolder;
4610                if (holder != null) {
4611                    thumbs.mainThumbnail = holder.lastThumbnail;
4612                }
4613                j++;
4614                break;
4615            }
4616            j++;
4617        }
4618
4619        if (j >= NA) {
4620            return thumbs;
4621        }
4622
4623        ArrayList<TaskAccessInfo.SubTask> subtasks = new ArrayList<TaskAccessInfo.SubTask>();
4624        thumbs.subtasks = subtasks;
4625        while (j < NA) {
4626            ActivityRecord ar = mHistory.get(j);
4627            j++;
4628            if (ar.finishing) {
4629                continue;
4630            }
4631            if (ar.task.taskId != taskId) {
4632                break;
4633            }
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;
4639                sub.activity = ar;
4640                sub.index = j-1;
4641                subtasks.add(sub);
4642            }
4643        }
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()) {
4648                        return null;
4649                    }
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);
4654                    }
4655                    return sub.holder.lastThumbnail;
4656                }
4657            };
4658        }
4659        return thumbs;
4660    }
4661
4662    private final void logStartActivity(int tag, ActivityRecord r,
4663            TaskRecord task) {
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());
4669    }
4670
4671    /**
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.
4677     */
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);
4683            return true;
4684        }
4685
4686        if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4687                "Ensuring correct configuration: " + r);
4688
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);
4695            return true;
4696        }
4697
4698        // We don't worry about activities that are finishing.
4699        if (r.finishing) {
4700            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
4701                    "Configuration doesn't matter in finishing " + r);
4702            r.stopFreezingScreenLocked(false);
4703            return true;
4704        }
4705
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;
4710
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);
4719            return true;
4720        }
4721
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;
4729            return true;
4730        }
4731
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);
4738        }
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;
4755                return 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
4760                // "restart!".
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;
4765            } else {
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;
4770            }
4771
4772            // All done...  tell the caller we weren't able to keep this
4773            // activity around.
4774            return false;
4775        }
4776
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
4781        // it last got.
4782        if (r.app != null && r.app.thread != null) {
4783            try {
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.
4788            }
4789        }
4790        r.stopFreezingScreenLocked(false);
4791
4792        return true;
4793    }
4794
4795    private final boolean relaunchActivityLocked(ActivityRecord r,
4796            int changes, boolean andResume) {
4797        List<ResultInfo> results = null;
4798        List<Intent> newIntents = null;
4799        if (andResume) {
4800            results = r.results;
4801            newIntents = r.newIntents;
4802        }
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);
4809
4810        r.startFreezingScreenLocked(r.app, 0);
4811
4812        try {
4813            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
4814                    (andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ")
4815                    + r);
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);
4824        }
4825
4826        if (andResume) {
4827            r.results = null;
4828            r.newIntents = null;
4829            if (mMainStack) {
4830                mService.reportResumedActivityLocked(r);
4831            }
4832            r.state = ActivityState.RESUMED;
4833        } else {
4834            mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
4835            r.state = ActivityState.PAUSED;
4836        }
4837
4838        return true;
4839    }
4840
4841    public void dismissKeyguardOnNextActivityLocked() {
4842        mDismissKeyguardOnNextActivity = true;
4843    }
4844
4845    boolean willActivityBeVisibleLocked(IBinder token) {
4846        int i;
4847        for (i = mHistory.size() - 1; i >= 0; i--) {
4848            ActivityRecord r = mHistory.get(i);
4849            if (r.appToken == token) {
4850                    return true;
4851            }
4852            if (r.fullscreen && !r.finishing) {
4853                return false;
4854            }
4855        }
4856        return true;
4857    }
4858
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);
4865            }
4866        }
4867    }
4868
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)) {
4880                if (!doit) {
4881                    if (r.finishing) {
4882                        // If this activity is just finishing, then it is not
4883                        // interesting as far as something to stop.
4884                        continue;
4885                    }
4886                    return true;
4887                }
4888                didSomething = true;
4889                Slog.i(TAG, "  Force finishing activity " + r);
4890                if (samePackage) {
4891                    if (r.app != null) {
4892                        r.app.removed = true;
4893                    }
4894                    r.app = null;
4895                }
4896                lastTask = r.task;
4897                if (r.stack.finishActivityLocked(r, i, Activity.RESULT_CANCELED,
4898                        null, "force-stop", true)) {
4899                    i--;
4900                }
4901            }
4902        }
4903        return didSomething;
4904    }
4905
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;
4914        int numRunning = 0;
4915        while (pos >= 0 && maxNum > 0) {
4916            final ActivityRecord r = next;
4917            pos--;
4918            next = pos >= 0 ? mHistory.get(pos) : null;
4919
4920            // Initialize state for next task if needed.
4921            if (top == null || (top.state == ActivityState.INITIALIZING && top.task == r.task)) {
4922                top = r;
4923                curTask = r.task;
4924                numActivities = numRunning = 0;
4925            }
4926
4927            // Add 'r' into the current task.
4928            numActivities++;
4929            if (r.app != null && r.app.thread != null) {
4930                numRunning++;
4931            }
4932
4933            if (localLOGV) Slog.v(
4934                TAG, r.intent.getComponent().flattenToShortString()
4935                + ": task=" + r.task);
4936
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;
4946                }
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
4954                        + " app=" + top.app
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) {
4958                            topRecord = top;
4959                        } else {
4960                            top.thumbnailNeeded = true;
4961                        }
4962                    }
4963                    pending.pendingRecords.add(top);
4964                }
4965                list.add(ci);
4966                maxNum--;
4967                top = null;
4968            }
4969        }
4970        return topRecord;
4971    }
4972
4973    public void unhandledBackLocked() {
4974        int top = mHistory.size() - 1;
4975        if (DEBUG_SWITCH) Slog.d(
4976            TAG, "Performing unhandledBack(): top activity at " + top);
4977        if (top > 0) {
4978            finishActivityLocked(mHistory.get(top),
4979                        top, Activity.RESULT_CANCELED, null, "unhandled-back", true);
4980        }
4981    }
4982
4983    void handleAppCrashLocked(ProcessRecord app) {
4984        for (int i = mHistory.size() - 1; i >= 0; i--) {
4985            ActivityRecord r = mHistory.get(i);
4986            if (r.app == app) {
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);
4991            }
4992        }
4993    }
4994
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);
4999    }
5000
5001    ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
5002        ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
5003
5004        if ("all".equals(name)) {
5005            for (ActivityRecord r1 : mHistory) {
5006                activities.add(r1);
5007            }
5008        } else if ("top".equals(name)) {
5009            final int N = mHistory.size();
5010            if (N > 0) {
5011                activities.add(mHistory.get(N-1));
5012            }
5013        } else {
5014            ItemMatcher matcher = new ItemMatcher();
5015            matcher.build(name);
5016
5017            for (ActivityRecord r1 : mHistory) {
5018                if (matcher.match(r1, r1.intent.getComponent())) {
5019                    activities.add(r1);
5020                }
5021            }
5022        }
5023
5024        return activities;
5025    }
5026
5027    ActivityRecord restartPackage(String packageName) {
5028        ActivityRecord starting = topRunningActivityLocked(null);
5029
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);
5038                }
5039            }
5040        }
5041
5042        return starting;
5043    }
5044}
5045