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