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