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