ActivityStackSupervisor.java revision b3b36ba13895d779159799341d432f6380a0ba8a
1/*
2 * Copyright (C) 2013 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.Intent.FLAG_ACTIVITY_NEW_TASK;
21import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
22import static android.content.pm.PackageManager.PERMISSION_GRANTED;
23import static com.android.server.am.ActivityManagerService.localLOGV;
24import static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION;
25import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
26import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
27import static com.android.server.am.ActivityManagerService.DEBUG_STACK;
28import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
29import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
30import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
31import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
32import static com.android.server.am.ActivityManagerService.TAG;
33
34import android.app.Activity;
35import android.app.ActivityManager;
36import android.app.ActivityOptions;
37import android.app.AppGlobals;
38import android.app.IActivityManager;
39import android.app.IApplicationThread;
40import android.app.IThumbnailReceiver;
41import android.app.PendingIntent;
42import android.app.ActivityManager.RunningTaskInfo;
43import android.app.IActivityManager.WaitResult;
44import android.app.ResultInfo;
45import android.content.ComponentName;
46import android.content.Context;
47import android.content.IIntentSender;
48import android.content.Intent;
49import android.content.IntentSender;
50import android.content.pm.ActivityInfo;
51import android.content.pm.ApplicationInfo;
52import android.content.pm.PackageManager;
53import android.content.pm.ResolveInfo;
54import android.content.res.Configuration;
55import android.os.Binder;
56import android.os.Bundle;
57import android.os.Debug;
58import android.os.Handler;
59import android.os.IBinder;
60import android.os.Looper;
61import android.os.Message;
62import android.os.ParcelFileDescriptor;
63import android.os.PowerManager;
64import android.os.RemoteException;
65import android.os.SystemClock;
66import android.os.UserHandle;
67import android.util.EventLog;
68import android.util.Slog;
69import android.util.SparseArray;
70
71import com.android.internal.app.HeavyWeightSwitcherActivity;
72import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
73import com.android.server.am.ActivityStack.ActivityState;
74import com.android.server.wm.StackBox;
75import com.android.server.wm.WindowManagerService;
76
77import java.io.FileDescriptor;
78import java.io.IOException;
79import java.io.PrintWriter;
80import java.util.ArrayList;
81import java.util.List;
82
83public class ActivityStackSupervisor {
84    static final boolean DEBUG = ActivityManagerService.DEBUG || false;
85    static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
86    static final boolean DEBUG_APP = DEBUG || false;
87    static final boolean DEBUG_SAVED_STATE = DEBUG || false;
88    static final boolean DEBUG_STATES = DEBUG || false;
89    static final boolean DEBUG_IDLE = DEBUG || false;
90
91    public static final int HOME_STACK_ID = 0;
92
93    /** How long we wait until giving up on the last activity telling us it is idle. */
94    static final int IDLE_TIMEOUT = 10*1000;
95
96    /** How long we can hold the sleep wake lock before giving up. */
97    static final int SLEEP_TIMEOUT = 5*1000;
98
99    static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG;
100    static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_STACK_MSG + 1;
101    static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
102    static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
103
104    final ActivityManagerService mService;
105    final Context mContext;
106    final Looper mLooper;
107
108    final ActivityStackSupervisorHandler mHandler;
109
110    /** Short cut */
111    WindowManagerService mWindowManager;
112
113    /** Dismiss the keyguard after the next activity is displayed? */
114    private boolean mDismissKeyguardOnNextActivity = false;
115
116    /** Identifier counter for all ActivityStacks */
117    private int mLastStackId = HOME_STACK_ID;
118
119    /** Task identifier that activities are currently being started in.  Incremented each time a
120     * new task is created. */
121    private int mCurTaskId = 0;
122
123    /** The current user */
124    private int mCurrentUser;
125
126    /** The stack containing the launcher app */
127    private ActivityStack mHomeStack;
128
129    /** The non-home stack currently receiving input or launching the next activity. If home is
130     * in front then mHomeStack overrides mFocusedStack. */
131    private ActivityStack mFocusedStack;
132
133    /** All the non-launcher stacks */
134    private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
135
136    private static final int STACK_STATE_HOME_IN_FRONT = 0;
137    private static final int STACK_STATE_HOME_TO_BACK = 1;
138    private static final int STACK_STATE_HOME_IN_BACK = 2;
139    private static final int STACK_STATE_HOME_TO_FRONT = 3;
140    private int mStackState = STACK_STATE_HOME_IN_FRONT;
141
142    /** List of activities that are waiting for a new activity to become visible before completing
143     * whatever operation they are supposed to do. */
144    final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
145
146    /** List of processes waiting to find out about the next visible activity. */
147    final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible =
148            new ArrayList<IActivityManager.WaitResult>();
149
150    /** List of processes waiting to find out about the next launched activity. */
151    final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched =
152            new ArrayList<IActivityManager.WaitResult>();
153
154    /** List of activities that are ready to be stopped, but waiting for the next activity to
155     * settle down before doing so. */
156    final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
157
158    /** List of activities that are ready to be finished, but waiting for the previous activity to
159     * settle down before doing so.  It contains ActivityRecord objects. */
160    final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<ActivityRecord>();
161
162    /** List of activities that are in the process of going to sleep. */
163    final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<ActivityRecord>();
164
165    /** List of ActivityRecord objects that have been finished and must still report back to a
166     * pending thumbnail receiver. */
167    final ArrayList<ActivityRecord> mCancelledThumbnails = new ArrayList<ActivityRecord>();
168
169    /** Used on user changes */
170    final ArrayList<UserStartedState> mStartingUsers = new ArrayList<UserStartedState>();
171
172    /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
173     * is being brought in front of us. */
174    boolean mUserLeaving = false;
175
176    /** Stacks belonging to users other than mCurrentUser. Indexed by userId. */
177    final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
178
179    /** Set when we have taken too long waiting to go to sleep. */
180    boolean mSleepTimeout = false;
181
182    /**
183     * Set when the system is going to sleep, until we have
184     * successfully paused the current activity and released our wake lock.
185     * At that point the system is allowed to actually sleep.
186     */
187    final PowerManager.WakeLock mGoingToSleep;
188
189    public ActivityStackSupervisor(ActivityManagerService service, Context context,
190            Looper looper) {
191        mService = service;
192        mContext = context;
193        mLooper = looper;
194        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
195        mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
196        mHandler = new ActivityStackSupervisorHandler(looper);
197    }
198
199    void setWindowManager(WindowManagerService wm) {
200        mWindowManager = wm;
201        mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID);
202        mStacks.add(mHomeStack);
203    }
204
205    void dismissKeyguard() {
206        if (mDismissKeyguardOnNextActivity) {
207            mDismissKeyguardOnNextActivity = false;
208            mWindowManager.dismissKeyguard();
209        }
210    }
211
212    ActivityStack getFocusedStack() {
213        if (mFocusedStack == null) {
214            return mHomeStack;
215        }
216        switch (mStackState) {
217            case STACK_STATE_HOME_IN_FRONT:
218            case STACK_STATE_HOME_TO_FRONT:
219                return mHomeStack;
220            case STACK_STATE_HOME_IN_BACK:
221            case STACK_STATE_HOME_TO_BACK:
222            default:
223                return mFocusedStack;
224        }
225    }
226
227    ActivityStack getLastStack() {
228        switch (mStackState) {
229            case STACK_STATE_HOME_IN_FRONT:
230            case STACK_STATE_HOME_TO_BACK:
231                return mHomeStack;
232            case STACK_STATE_HOME_TO_FRONT:
233            case STACK_STATE_HOME_IN_BACK:
234            default:
235                return mFocusedStack;
236        }
237    }
238
239    boolean isFrontStack(ActivityStack stack) {
240        return (stack.mCurrentUser == mCurrentUser) &&
241                !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
242    }
243
244    void moveHomeStack(boolean toFront) {
245        final boolean homeInFront = isFrontStack(mHomeStack);
246        if (homeInFront ^ toFront) {
247            if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: mStackState old=" +
248                    stackStateToString(mStackState) + " new=" + stackStateToString(homeInFront ?
249                    STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT));
250            mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
251        }
252    }
253
254    boolean resumeHomeActivity(ActivityRecord prev) {
255        moveHomeStack(true);
256        if (prev != null) {
257            prev.mLaunchHomeTaskNext = false;
258        }
259        if (mHomeStack.topRunningActivityLocked(null) != null) {
260            return resumeTopActivitiesLocked(mHomeStack, prev, null);
261        }
262        return mService.startHomeActivityLocked(mCurrentUser);
263    }
264
265    final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
266            ActivityStack stack) {
267        if (stack == mHomeStack) {
268            return;
269        }
270        if ((sourceRecord == null && getLastStack() == mHomeStack) ||
271                (sourceRecord != null && sourceRecord.isHomeActivity())) {
272            if (r == null) {
273                r = stack.topRunningActivityLocked(null);
274            }
275            if (r != null && !r.isHomeActivity() && r.isRootActivity()) {
276                r.mLaunchHomeTaskNext = true;
277            }
278        }
279    }
280
281    void setDismissKeyguard(boolean dismiss) {
282        mDismissKeyguardOnNextActivity = dismiss;
283    }
284
285    TaskRecord anyTaskForIdLocked(int id) {
286        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
287            ActivityStack stack = mStacks.get(stackNdx);
288            TaskRecord task = stack.taskForIdLocked(id);
289            if (task != null) {
290                return task;
291            }
292        }
293        return null;
294    }
295
296    ActivityRecord isInAnyStackLocked(IBinder token) {
297        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
298            final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
299            if (r != null) {
300                return r;
301            }
302        }
303        return null;
304    }
305
306    int getNextTaskId() {
307        do {
308            mCurTaskId++;
309            if (mCurTaskId <= 0) {
310                mCurTaskId = 1;
311            }
312        } while (anyTaskForIdLocked(mCurTaskId) != null);
313        return mCurTaskId;
314    }
315
316    void removeTask(TaskRecord task) {
317        mWindowManager.removeTask(task.taskId);
318        final ActivityStack stack = task.stack;
319        final ActivityRecord r = stack.mResumedActivity;
320        if (r != null && r.task == task) {
321            stack.mResumedActivity = null;
322        }
323        if (stack.removeTask(task) && !stack.isHomeStack()) {
324            if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
325            mStacks.remove(stack);
326            final int stackId = stack.mStackId;
327            final int nextStackId = mWindowManager.removeStack(stackId);
328            // TODO: Perhaps we need to let the ActivityManager determine the next focus...
329            if (mFocusedStack.mStackId == stackId) {
330                // If this is the last app stack, set mFocusedStack to null.
331                mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
332            }
333        }
334    }
335
336    ActivityRecord resumedAppLocked() {
337        ActivityStack stack = getFocusedStack();
338        if (stack == null) {
339            return null;
340        }
341        ActivityRecord resumedActivity = stack.mResumedActivity;
342        if (resumedActivity == null || resumedActivity.app == null) {
343            resumedActivity = stack.mPausingActivity;
344            if (resumedActivity == null || resumedActivity.app == null) {
345                resumedActivity = stack.topRunningActivityLocked(null);
346            }
347        }
348        return resumedActivity;
349    }
350
351    boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
352        boolean didSomething = false;
353        final String processName = app.processName;
354        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
355            final ActivityStack stack = mStacks.get(stackNdx);
356            if (!isFrontStack(stack)) {
357                continue;
358            }
359            ActivityRecord hr = stack.topRunningActivityLocked(null);
360            if (hr != null) {
361                if (hr.app == null && app.uid == hr.info.applicationInfo.uid
362                        && processName.equals(hr.processName)) {
363                    try {
364                        if (headless) {
365                            Slog.e(TAG, "Starting activities not supported on headless device: "
366                                    + hr);
367                        } else if (realStartActivityLocked(hr, app, true, true)) {
368                            didSomething = true;
369                        }
370                    } catch (Exception e) {
371                        Slog.w(TAG, "Exception in new application when starting activity "
372                              + hr.intent.getComponent().flattenToShortString(), e);
373                        throw e;
374                    }
375                }
376            }
377        }
378        if (!didSomething) {
379            ensureActivitiesVisibleLocked(null, 0);
380        }
381        return didSomething;
382    }
383
384    boolean allResumedActivitiesIdle() {
385        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
386            final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
387            if (resumedActivity == null || !resumedActivity.idle) {
388                return false;
389            }
390        }
391        return true;
392    }
393
394    boolean allResumedActivitiesComplete() {
395        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
396            final ActivityStack stack = mStacks.get(stackNdx);
397            if (isFrontStack(stack)) {
398                final ActivityRecord r = stack.mResumedActivity;
399                if (r != null && r.state != ActivityState.RESUMED) {
400                    return false;
401                }
402            }
403        }
404        // TODO: Not sure if this should check if all Paused are complete too.
405        switch (mStackState) {
406            case STACK_STATE_HOME_TO_BACK:
407                if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
408                        stackStateToString(STACK_STATE_HOME_TO_BACK) + " new=" +
409                        stackStateToString(STACK_STATE_HOME_IN_BACK));
410                mStackState = STACK_STATE_HOME_IN_BACK;
411                break;
412            case STACK_STATE_HOME_TO_FRONT:
413                if (DEBUG_STACK) Slog.d(TAG, "allResumedActivitiesComplete: mStackState old=" +
414                        stackStateToString(STACK_STATE_HOME_TO_FRONT) + " new=" +
415                        stackStateToString(STACK_STATE_HOME_IN_FRONT));
416                mStackState = STACK_STATE_HOME_IN_FRONT;
417                break;
418        }
419        return true;
420    }
421
422    boolean allResumedActivitiesVisible() {
423        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
424            final ActivityStack stack = mStacks.get(stackNdx);
425            final ActivityRecord r = stack.mResumedActivity;
426            if (r != null && (!r.nowVisible || r.waitingVisible)) {
427                return false;
428            }
429        }
430        return true;
431    }
432
433    boolean pauseBackStacks(boolean userLeaving) {
434        boolean someActivityPaused = false;
435        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
436            final ActivityStack stack = mStacks.get(stackNdx);
437            if (!isFrontStack(stack) && stack.mResumedActivity != null) {
438                stack.startPausingLocked(userLeaving, false);
439                someActivityPaused = true;
440            }
441        }
442        return someActivityPaused;
443    }
444
445    boolean allPausedActivitiesComplete() {
446        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
447            final ActivityStack stack = mStacks.get(stackNdx);
448            final ActivityRecord r = stack.mPausingActivity;
449            if (r != null && r.state != ActivityState.PAUSED
450                    && r.state != ActivityState.STOPPED
451                    && r.state != ActivityState.STOPPING) {
452                return false;
453            }
454        }
455        return true;
456    }
457
458    void reportActivityVisibleLocked(ActivityRecord r) {
459        for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) {
460            WaitResult w = mWaitingActivityVisible.get(i);
461            w.timeout = false;
462            if (r != null) {
463                w.who = new ComponentName(r.info.packageName, r.info.name);
464            }
465            w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
466            w.thisTime = w.totalTime;
467        }
468        mService.notifyAll();
469        dismissKeyguard();
470    }
471
472    void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
473            long thisTime, long totalTime) {
474        for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
475            WaitResult w = mWaitingActivityLaunched.remove(i);
476            w.timeout = timeout;
477            if (r != null) {
478                w.who = new ComponentName(r.info.packageName, r.info.name);
479            }
480            w.thisTime = thisTime;
481            w.totalTime = totalTime;
482        }
483        mService.notifyAll();
484    }
485
486    ActivityRecord topRunningActivityLocked() {
487        final ActivityStack focusedStack = getFocusedStack();
488        ActivityRecord r = focusedStack.topRunningActivityLocked(null);
489        if (r != null) {
490            return r;
491        }
492
493        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
494            final ActivityStack stack = mStacks.get(stackNdx);
495            if (stack.mCurrentUser == mCurrentUser && stack != focusedStack &&
496                    isFrontStack(stack)) {
497                r = stack.topRunningActivityLocked(null);
498                if (r != null) {
499                    return r;
500                }
501            }
502        }
503        return null;
504    }
505
506    ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
507            PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
508        ActivityRecord r = null;
509        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
510            final ActivityStack stack = mStacks.get(stackNdx);
511            final ActivityRecord ar =
512                    stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
513            if (isFrontStack(stack)) {
514                r = ar;
515            }
516        }
517        return r;
518    }
519
520    ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
521            String profileFile, ParcelFileDescriptor profileFd, int userId) {
522        // Collect information about the target of the Intent.
523        ActivityInfo aInfo;
524        try {
525            ResolveInfo rInfo =
526                AppGlobals.getPackageManager().resolveIntent(
527                        intent, resolvedType,
528                        PackageManager.MATCH_DEFAULT_ONLY
529                                    | ActivityManagerService.STOCK_PM_FLAGS, userId);
530            aInfo = rInfo != null ? rInfo.activityInfo : null;
531        } catch (RemoteException e) {
532            aInfo = null;
533        }
534
535        if (aInfo != null) {
536            // Store the found target back into the intent, because now that
537            // we have it we never want to do this again.  For example, if the
538            // user navigates back to this point in the history, we should
539            // always restart the exact same activity.
540            intent.setComponent(new ComponentName(
541                    aInfo.applicationInfo.packageName, aInfo.name));
542
543            // Don't debug things in the system process
544            if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
545                if (!aInfo.processName.equals("system")) {
546                    mService.setDebugApp(aInfo.processName, true, false);
547                }
548            }
549
550            if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
551                if (!aInfo.processName.equals("system")) {
552                    mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
553                }
554            }
555
556            if (profileFile != null) {
557                if (!aInfo.processName.equals("system")) {
558                    mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
559                            profileFile, profileFd,
560                            (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
561                }
562            }
563        }
564        return aInfo;
565    }
566
567    void startHomeActivity(Intent intent, ActivityInfo aInfo) {
568        moveHomeStack(true);
569        startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
570                null, false, null);
571    }
572
573    final int startActivityMayWait(IApplicationThread caller, int callingUid,
574            String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
575            String resultWho, int requestCode, int startFlags, String profileFile,
576            ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
577            Bundle options, int userId) {
578        // Refuse possible leaked file descriptors
579        if (intent != null && intent.hasFileDescriptors()) {
580            throw new IllegalArgumentException("File descriptors passed in Intent");
581        }
582        boolean componentSpecified = intent.getComponent() != null;
583
584        // Don't modify the client's object!
585        intent = new Intent(intent);
586
587        // Collect information about the target of the Intent.
588        ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
589                profileFile, profileFd, userId);
590
591        synchronized (mService) {
592            int callingPid;
593            if (callingUid >= 0) {
594                callingPid = -1;
595            } else if (caller == null) {
596                callingPid = Binder.getCallingPid();
597                callingUid = Binder.getCallingUid();
598            } else {
599                callingPid = callingUid = -1;
600            }
601
602            final ActivityStack stack = getFocusedStack();
603            stack.mConfigWillChange = config != null
604                    && mService.mConfiguration.diff(config) != 0;
605            if (DEBUG_CONFIGURATION) Slog.v(TAG,
606                    "Starting activity when config will change = " + stack.mConfigWillChange);
607
608            final long origId = Binder.clearCallingIdentity();
609
610            if (aInfo != null &&
611                    (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
612                // This may be a heavy-weight process!  Check to see if we already
613                // have another, different heavy-weight process running.
614                if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
615                    if (mService.mHeavyWeightProcess != null &&
616                            (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
617                            !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
618                        int realCallingUid = callingUid;
619                        if (caller != null) {
620                            ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
621                            if (callerApp != null) {
622                                realCallingUid = callerApp.info.uid;
623                            } else {
624                                Slog.w(TAG, "Unable to find app for caller " + caller
625                                      + " (pid=" + callingPid + ") when starting: "
626                                      + intent.toString());
627                                ActivityOptions.abort(options);
628                                return ActivityManager.START_PERMISSION_DENIED;
629                            }
630                        }
631
632                        IIntentSender target = mService.getIntentSenderLocked(
633                                ActivityManager.INTENT_SENDER_ACTIVITY, "android",
634                                realCallingUid, userId, null, null, 0, new Intent[] { intent },
635                                new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
636                                | PendingIntent.FLAG_ONE_SHOT, null);
637
638                        Intent newIntent = new Intent();
639                        if (requestCode >= 0) {
640                            // Caller is requesting a result.
641                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
642                        }
643                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
644                                new IntentSender(target));
645                        if (mService.mHeavyWeightProcess.activities.size() > 0) {
646                            ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
647                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
648                                    hist.packageName);
649                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
650                                    hist.task.taskId);
651                        }
652                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
653                                aInfo.packageName);
654                        newIntent.setFlags(intent.getFlags());
655                        newIntent.setClassName("android",
656                                HeavyWeightSwitcherActivity.class.getName());
657                        intent = newIntent;
658                        resolvedType = null;
659                        caller = null;
660                        callingUid = Binder.getCallingUid();
661                        callingPid = Binder.getCallingPid();
662                        componentSpecified = true;
663                        try {
664                            ResolveInfo rInfo =
665                                AppGlobals.getPackageManager().resolveIntent(
666                                        intent, null,
667                                        PackageManager.MATCH_DEFAULT_ONLY
668                                        | ActivityManagerService.STOCK_PM_FLAGS, userId);
669                            aInfo = rInfo != null ? rInfo.activityInfo : null;
670                            aInfo = mService.getActivityInfoForUser(aInfo, userId);
671                        } catch (RemoteException e) {
672                            aInfo = null;
673                        }
674                    }
675                }
676            }
677
678            int res = startActivityLocked(caller, intent, resolvedType,
679                    aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
680                    callingPackage, startFlags, options, componentSpecified, null);
681
682            if (stack.mConfigWillChange) {
683                // If the caller also wants to switch to a new configuration,
684                // do so now.  This allows a clean switch, as we are waiting
685                // for the current activity to pause (so we will not destroy
686                // it), and have not yet started the next activity.
687                mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
688                        "updateConfiguration()");
689                stack.mConfigWillChange = false;
690                if (DEBUG_CONFIGURATION) Slog.v(TAG,
691                        "Updating to new configuration after starting activity.");
692                mService.updateConfigurationLocked(config, null, false, false);
693            }
694
695            Binder.restoreCallingIdentity(origId);
696
697            if (outResult != null) {
698                outResult.result = res;
699                if (res == ActivityManager.START_SUCCESS) {
700                    mWaitingActivityLaunched.add(outResult);
701                    do {
702                        try {
703                            mService.wait();
704                        } catch (InterruptedException e) {
705                        }
706                    } while (!outResult.timeout && outResult.who == null);
707                } else if (res == ActivityManager.START_TASK_TO_FRONT) {
708                    ActivityRecord r = stack.topRunningActivityLocked(null);
709                    if (r.nowVisible) {
710                        outResult.timeout = false;
711                        outResult.who = new ComponentName(r.info.packageName, r.info.name);
712                        outResult.totalTime = 0;
713                        outResult.thisTime = 0;
714                    } else {
715                        outResult.thisTime = SystemClock.uptimeMillis();
716                        mWaitingActivityVisible.add(outResult);
717                        do {
718                            try {
719                                mService.wait();
720                            } catch (InterruptedException e) {
721                            }
722                        } while (!outResult.timeout && outResult.who == null);
723                    }
724                }
725            }
726
727            return res;
728        }
729    }
730
731    final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
732            Intent[] intents, String[] resolvedTypes, IBinder resultTo,
733            Bundle options, int userId) {
734        if (intents == null) {
735            throw new NullPointerException("intents is null");
736        }
737        if (resolvedTypes == null) {
738            throw new NullPointerException("resolvedTypes is null");
739        }
740        if (intents.length != resolvedTypes.length) {
741            throw new IllegalArgumentException("intents are length different than resolvedTypes");
742        }
743
744
745        int callingPid;
746        if (callingUid >= 0) {
747            callingPid = -1;
748        } else if (caller == null) {
749            callingPid = Binder.getCallingPid();
750            callingUid = Binder.getCallingUid();
751        } else {
752            callingPid = callingUid = -1;
753        }
754        final long origId = Binder.clearCallingIdentity();
755        try {
756            synchronized (mService) {
757                ActivityRecord[] outActivity = new ActivityRecord[1];
758                for (int i=0; i<intents.length; i++) {
759                    Intent intent = intents[i];
760                    if (intent == null) {
761                        continue;
762                    }
763
764                    // Refuse possible leaked file descriptors
765                    if (intent != null && intent.hasFileDescriptors()) {
766                        throw new IllegalArgumentException("File descriptors passed in Intent");
767                    }
768
769                    boolean componentSpecified = intent.getComponent() != null;
770
771                    // Don't modify the client's object!
772                    intent = new Intent(intent);
773
774                    // Collect information about the target of the Intent.
775                    ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
776                            0, null, null, userId);
777                    // TODO: New, check if this is correct
778                    aInfo = mService.getActivityInfoForUser(aInfo, userId);
779
780                    if (aInfo != null &&
781                            (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
782                                    != 0) {
783                        throw new IllegalArgumentException(
784                                "FLAG_CANT_SAVE_STATE not supported here");
785                    }
786
787                    Bundle theseOptions;
788                    if (options != null && i == intents.length-1) {
789                        theseOptions = options;
790                    } else {
791                        theseOptions = null;
792                    }
793                    int res = startActivityLocked(caller, intent, resolvedTypes[i],
794                            aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
795                            0, theseOptions, componentSpecified, outActivity);
796                    if (res < 0) {
797                        return res;
798                    }
799
800                    resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
801                }
802            }
803        } finally {
804            Binder.restoreCallingIdentity(origId);
805        }
806
807        return ActivityManager.START_SUCCESS;
808    }
809
810    final boolean realStartActivityLocked(ActivityRecord r,
811            ProcessRecord app, boolean andResume, boolean checkConfig)
812            throws RemoteException {
813
814        r.startFreezingScreenLocked(app, 0);
815        mWindowManager.setAppVisibility(r.appToken, true);
816
817        // schedule launch ticks to collect information about slow apps.
818        r.startLaunchTickingLocked();
819
820        // Have the window manager re-evaluate the orientation of
821        // the screen based on the new activity order.  Note that
822        // as a result of this, it can call back into the activity
823        // manager with a new orientation.  We don't care about that,
824        // because the activity is not currently running so we are
825        // just restarting it anyway.
826        if (checkConfig) {
827            Configuration config = mWindowManager.updateOrientationFromAppTokens(
828                    mService.mConfiguration,
829                    r.mayFreezeScreenLocked(app) ? r.appToken : null);
830            mService.updateConfigurationLocked(config, r, false, false);
831        }
832
833        r.app = app;
834        app.waitingToKill = null;
835        r.launchCount++;
836        r.lastLaunchTime = SystemClock.uptimeMillis();
837
838        if (localLOGV) Slog.v(TAG, "Launching: " + r);
839
840        int idx = app.activities.indexOf(r);
841        if (idx < 0) {
842            app.activities.add(r);
843        }
844        mService.updateLruProcessLocked(app, true);
845
846        final ActivityStack stack = r.task.stack;
847        try {
848            if (app.thread == null) {
849                throw new RemoteException();
850            }
851            List<ResultInfo> results = null;
852            List<Intent> newIntents = null;
853            if (andResume) {
854                results = r.results;
855                newIntents = r.newIntents;
856            }
857            if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
858                    + " icicle=" + r.icicle
859                    + " with results=" + results + " newIntents=" + newIntents
860                    + " andResume=" + andResume);
861            if (andResume) {
862                EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
863                        r.userId, System.identityHashCode(r),
864                        r.task.taskId, r.shortComponentName);
865            }
866            if (r.isHomeActivity()) {
867                mService.mHomeProcess = app;
868            }
869            mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
870            r.sleeping = false;
871            r.forceNewConfig = false;
872            mService.showAskCompatModeDialogLocked(r);
873            r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
874            String profileFile = null;
875            ParcelFileDescriptor profileFd = null;
876            boolean profileAutoStop = false;
877            if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
878                if (mService.mProfileProc == null || mService.mProfileProc == app) {
879                    mService.mProfileProc = app;
880                    profileFile = mService.mProfileFile;
881                    profileFd = mService.mProfileFd;
882                    profileAutoStop = mService.mAutoStopProfiler;
883                }
884            }
885            app.hasShownUi = true;
886            app.pendingUiClean = true;
887            if (profileFd != null) {
888                try {
889                    profileFd = profileFd.dup();
890                } catch (IOException e) {
891                    if (profileFd != null) {
892                        try {
893                            profileFd.close();
894                        } catch (IOException o) {
895                        }
896                        profileFd = null;
897                    }
898                }
899            }
900            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
901                    System.identityHashCode(r), r.info,
902                    new Configuration(mService.mConfiguration),
903                    r.compat, r.icicle, results, newIntents, !andResume,
904                    mService.isNextTransitionForward(), profileFile, profileFd,
905                    profileAutoStop);
906
907            if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
908                // This may be a heavy-weight process!  Note that the package
909                // manager will ensure that only activity can run in the main
910                // process of the .apk, which is the only thing that will be
911                // considered heavy-weight.
912                if (app.processName.equals(app.info.packageName)) {
913                    if (mService.mHeavyWeightProcess != null
914                            && mService.mHeavyWeightProcess != app) {
915                        Slog.w(TAG, "Starting new heavy weight process " + app
916                                + " when already running "
917                                + mService.mHeavyWeightProcess);
918                    }
919                    mService.mHeavyWeightProcess = app;
920                    Message msg = mService.mHandler.obtainMessage(
921                            ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
922                    msg.obj = r;
923                    mService.mHandler.sendMessage(msg);
924                }
925            }
926
927        } catch (RemoteException e) {
928            if (r.launchFailed) {
929                // This is the second time we failed -- finish activity
930                // and give up.
931                Slog.e(TAG, "Second failure launching "
932                      + r.intent.getComponent().flattenToShortString()
933                      + ", giving up", e);
934                mService.appDiedLocked(app, app.pid, app.thread);
935                stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
936                        "2nd-crash", false);
937                return false;
938            }
939
940            // This is the first time we failed -- restart process and
941            // retry.
942            app.activities.remove(r);
943            throw e;
944        }
945
946        r.launchFailed = false;
947        if (stack.updateLRUListLocked(r)) {
948            Slog.w(TAG, "Activity " + r
949                  + " being launched, but already in LRU list");
950        }
951
952        if (andResume) {
953            // As part of the process of launching, ActivityThread also performs
954            // a resume.
955            stack.minimalResumeActivityLocked(r);
956        } else {
957            // This activity is not starting in the resumed state... which
958            // should look like we asked it to pause+stop (but remain visible),
959            // and it has done so and reported back the current icicle and
960            // other state.
961            if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
962                    + " (starting in stopped state)");
963            r.state = ActivityState.STOPPED;
964            r.stopped = true;
965        }
966
967        // Launch the new version setup screen if needed.  We do this -after-
968        // launching the initial activity (that is, home), so that it can have
969        // a chance to initialize itself while in the background, making the
970        // switch back to it faster and look better.
971        if (isFrontStack(stack)) {
972            mService.startSetupActivityLocked();
973        }
974
975        return true;
976    }
977
978    void startSpecificActivityLocked(ActivityRecord r,
979            boolean andResume, boolean checkConfig) {
980        // Is this activity's application already running?
981        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
982                r.info.applicationInfo.uid);
983
984        r.task.stack.setLaunchTime(r);
985
986        if (app != null && app.thread != null) {
987            try {
988                app.addPackage(r.info.packageName);
989                realStartActivityLocked(r, app, andResume, checkConfig);
990                return;
991            } catch (RemoteException e) {
992                Slog.w(TAG, "Exception when starting activity "
993                        + r.intent.getComponent().flattenToShortString(), e);
994            }
995
996            // If a dead object exception was thrown -- fall through to
997            // restart the application.
998        }
999
1000        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
1001                "activity", r.intent.getComponent(), false, false);
1002    }
1003
1004    final int startActivityLocked(IApplicationThread caller,
1005            Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
1006            String resultWho, int requestCode,
1007            int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
1008            boolean componentSpecified, ActivityRecord[] outActivity) {
1009        int err = ActivityManager.START_SUCCESS;
1010
1011        ProcessRecord callerApp = null;
1012        if (caller != null) {
1013            callerApp = mService.getRecordForAppLocked(caller);
1014            if (callerApp != null) {
1015                callingPid = callerApp.pid;
1016                callingUid = callerApp.info.uid;
1017            } else {
1018                Slog.w(TAG, "Unable to find app for caller " + caller
1019                      + " (pid=" + callingPid + ") when starting: "
1020                      + intent.toString());
1021                err = ActivityManager.START_PERMISSION_DENIED;
1022            }
1023        }
1024
1025        if (err == ActivityManager.START_SUCCESS) {
1026            final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
1027            Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
1028                    + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
1029        }
1030
1031        ActivityRecord sourceRecord = null;
1032        ActivityRecord resultRecord = null;
1033        if (resultTo != null) {
1034            sourceRecord = isInAnyStackLocked(resultTo);
1035            if (DEBUG_RESULTS) Slog.v(
1036                TAG, "Will send result to " + resultTo + " " + sourceRecord);
1037            if (sourceRecord != null) {
1038                if (requestCode >= 0 && !sourceRecord.finishing) {
1039                    resultRecord = sourceRecord;
1040                }
1041            }
1042        }
1043        ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
1044
1045        int launchFlags = intent.getFlags();
1046
1047        if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
1048                && sourceRecord != null) {
1049            // Transfer the result target from the source activity to the new
1050            // one being started, including any failures.
1051            if (requestCode >= 0) {
1052                ActivityOptions.abort(options);
1053                return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
1054            }
1055            resultRecord = sourceRecord.resultTo;
1056            resultWho = sourceRecord.resultWho;
1057            requestCode = sourceRecord.requestCode;
1058            sourceRecord.resultTo = null;
1059            if (resultRecord != null) {
1060                resultRecord.removeResultsLocked(
1061                    sourceRecord, resultWho, requestCode);
1062            }
1063        }
1064
1065        if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
1066            // We couldn't find a class that can handle the given Intent.
1067            // That's the end of that!
1068            err = ActivityManager.START_INTENT_NOT_RESOLVED;
1069        }
1070
1071        if (err == ActivityManager.START_SUCCESS && aInfo == null) {
1072            // We couldn't find the specific class specified in the Intent.
1073            // Also the end of the line.
1074            err = ActivityManager.START_CLASS_NOT_FOUND;
1075        }
1076
1077        if (err != ActivityManager.START_SUCCESS) {
1078            if (resultRecord != null) {
1079                resultStack.sendActivityResultLocked(-1,
1080                    resultRecord, resultWho, requestCode,
1081                    Activity.RESULT_CANCELED, null);
1082            }
1083            setDismissKeyguard(false);
1084            ActivityOptions.abort(options);
1085            return err;
1086        }
1087
1088        final int startAnyPerm = mService.checkPermission(
1089                START_ANY_ACTIVITY, callingPid, callingUid);
1090        final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
1091                callingUid, aInfo.applicationInfo.uid, aInfo.exported);
1092        if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
1093            if (resultRecord != null) {
1094                resultStack.sendActivityResultLocked(-1,
1095                    resultRecord, resultWho, requestCode,
1096                    Activity.RESULT_CANCELED, null);
1097            }
1098            setDismissKeyguard(false);
1099            String msg;
1100            if (!aInfo.exported) {
1101                msg = "Permission Denial: starting " + intent.toString()
1102                        + " from " + callerApp + " (pid=" + callingPid
1103                        + ", uid=" + callingUid + ")"
1104                        + " not exported from uid " + aInfo.applicationInfo.uid;
1105            } else {
1106                msg = "Permission Denial: starting " + intent.toString()
1107                        + " from " + callerApp + " (pid=" + callingPid
1108                        + ", uid=" + callingUid + ")"
1109                        + " requires " + aInfo.permission;
1110            }
1111            Slog.w(TAG, msg);
1112            throw new SecurityException(msg);
1113        }
1114
1115        boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
1116                callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
1117
1118        if (mService.mController != null) {
1119            try {
1120                // The Intent we give to the watcher has the extra data
1121                // stripped off, since it can contain private information.
1122                Intent watchIntent = intent.cloneFilter();
1123                abort |= !mService.mController.activityStarting(watchIntent,
1124                        aInfo.applicationInfo.packageName);
1125            } catch (RemoteException e) {
1126                mService.mController = null;
1127            }
1128        }
1129
1130        if (abort) {
1131            if (resultRecord != null) {
1132                resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
1133                        Activity.RESULT_CANCELED, null);
1134            }
1135            // We pretend to the caller that it was really started, but
1136            // they will just get a cancel result.
1137            setDismissKeyguard(false);
1138            ActivityOptions.abort(options);
1139            return ActivityManager.START_SUCCESS;
1140        }
1141
1142        ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1143                intent, resolvedType, aInfo, mService.mConfiguration,
1144                resultRecord, resultWho, requestCode, componentSpecified, this);
1145        if (outActivity != null) {
1146            outActivity[0] = r;
1147        }
1148
1149        final ActivityStack stack = getFocusedStack();
1150        if (stack.mResumedActivity == null
1151                || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
1152            if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1153                PendingActivityLaunch pal =
1154                        new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
1155                mService.mPendingActivityLaunches.add(pal);
1156                setDismissKeyguard(false);
1157                ActivityOptions.abort(options);
1158                return ActivityManager.START_SWITCHES_CANCELED;
1159            }
1160        }
1161
1162        if (mService.mDidAppSwitch) {
1163            // This is the second allowed switch since we stopped switches,
1164            // so now just generally allow switches.  Use case: user presses
1165            // home (switches disabled, switch to home, mDidAppSwitch now true);
1166            // user taps a home icon (coming from home so allowed, we hit here
1167            // and now allow anyone to switch again).
1168            mService.mAppSwitchesAllowedTime = 0;
1169        } else {
1170            mService.mDidAppSwitch = true;
1171        }
1172
1173        mService.doPendingActivityLaunchesLocked(false);
1174
1175        err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
1176        if (stack.mPausingActivity == null) {
1177            // Someone asked to have the keyguard dismissed on the next
1178            // activity start, but we are not actually doing an activity
1179            // switch...  just dismiss the keyguard now, because we
1180            // probably want to see whatever is behind it.
1181            dismissKeyguard();
1182        }
1183        return err;
1184    }
1185
1186    ActivityStack getCorrectStack(ActivityRecord r) {
1187        if (r.isApplicationActivity() || (r.task != null && r.task.isApplicationTask())) {
1188            int stackNdx;
1189            for (stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
1190                if (mStacks.get(stackNdx).mCurrentUser == mCurrentUser) {
1191                    break;
1192                }
1193            }
1194            if (stackNdx == 0) {
1195                // Time to create the first app stack for this user.
1196                int stackId = mService.createStack(-1, HOME_STACK_ID,
1197                        StackBox.TASK_STACK_GOES_OVER, 1.0f);
1198                mFocusedStack = getStack(stackId);
1199            }
1200            return mFocusedStack;
1201        }
1202        return mHomeStack;
1203    }
1204
1205    void setFocusedStack(ActivityRecord r) {
1206        if (r == null) {
1207            return;
1208        }
1209        if (!r.isApplicationActivity() || (r.task != null && !r.task.isApplicationTask())) {
1210            if (mStackState != STACK_STATE_HOME_IN_FRONT) {
1211                if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
1212                        stackStateToString(mStackState) + " new=" +
1213                        stackStateToString(STACK_STATE_HOME_TO_FRONT) +
1214                        " Callers=" + Debug.getCallers(3));
1215                mStackState = STACK_STATE_HOME_TO_FRONT;
1216            }
1217        } else {
1218            mFocusedStack = r.task.stack;
1219            if (mStackState != STACK_STATE_HOME_IN_BACK) {
1220                if (DEBUG_STACK) Slog.d(TAG, "setFocusedStack: mStackState old=" +
1221                        stackStateToString(mStackState) + " new=" +
1222                        stackStateToString(STACK_STATE_HOME_TO_BACK) +
1223                        " Callers=" + Debug.getCallers(3));
1224                mStackState = STACK_STATE_HOME_TO_BACK;
1225            }
1226        }
1227    }
1228
1229    final int startActivityUncheckedLocked(ActivityRecord r,
1230            ActivityRecord sourceRecord, int startFlags, boolean doResume,
1231            Bundle options) {
1232        final Intent intent = r.intent;
1233        final int callingUid = r.launchedFromUid;
1234
1235        int launchFlags = intent.getFlags();
1236
1237        // We'll invoke onUserLeaving before onPause only if the launching
1238        // activity did not explicitly state that this is an automated launch.
1239        mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1240        if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
1241
1242        // If the caller has asked not to resume at this point, we make note
1243        // of this in the record so that we can skip it when trying to find
1244        // the top running activity.
1245        if (!doResume) {
1246            r.delayedResume = true;
1247        }
1248
1249        ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1250
1251        // If the onlyIfNeeded flag is set, then we can do this if the activity
1252        // being launched is the same as the one making the call...  or, as
1253        // a special case, if we do not know the caller then we count the
1254        // current top activity as the caller.
1255        if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1256            ActivityRecord checkedCaller = sourceRecord;
1257            if (checkedCaller == null) {
1258                checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
1259            }
1260            if (!checkedCaller.realActivity.equals(r.realActivity)) {
1261                // Caller is not the same as launcher, so always needed.
1262                startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1263            }
1264        }
1265
1266        if (sourceRecord == null) {
1267            // This activity is not being started from another...  in this
1268            // case we -always- start a new task.
1269            if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
1270                Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1271                        "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
1272                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1273            }
1274        } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1275            // The original activity who is starting us is running as a single
1276            // instance...  this new activity it is starting must go on its
1277            // own task.
1278            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1279        } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1280                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1281            // The activity being started is a single instance...  it always
1282            // gets launched into its own task.
1283            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1284        }
1285
1286        final ActivityStack sourceStack;
1287        TaskRecord sourceTask;
1288        if (sourceRecord != null) {
1289            sourceTask = sourceRecord.task;
1290            sourceStack = sourceTask.stack;
1291        } else {
1292            sourceTask = null;
1293            sourceStack = null;
1294        }
1295
1296        if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1297            // For whatever reason this activity is being launched into a new
1298            // task...  yet the caller has requested a result back.  Well, that
1299            // is pretty messed up, so instead immediately send back a cancel
1300            // and let the new task continue launched as normal without a
1301            // dependency on its originator.
1302            Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1303            r.resultTo.task.stack.sendActivityResultLocked(-1,
1304                    r.resultTo, r.resultWho, r.requestCode,
1305                Activity.RESULT_CANCELED, null);
1306            r.resultTo = null;
1307        }
1308
1309        boolean addingToTask = false;
1310        boolean movedHome = false;
1311        TaskRecord reuseTask = null;
1312        ActivityStack targetStack;
1313        if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1314                (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1315                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1316                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1317            // If bring to front is requested, and no result is requested, and
1318            // we can find a task that was started with this same
1319            // component, then instead of launching bring that one to the front.
1320            if (r.resultTo == null) {
1321                // See if there is a task to bring to the front.  If this is
1322                // a SINGLE_INSTANCE activity, there can be one and only one
1323                // instance of it in the history, and it is always in its own
1324                // unique task, so we do a special search.
1325                ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1326                        ? findTaskLocked(intent, r.info)
1327                        : findActivityLocked(intent, r.info);
1328                if (intentActivity != null) {
1329                    if (r.task == null) {
1330                        r.task = intentActivity.task;
1331                    }
1332                    targetStack = intentActivity.task.stack;
1333                    moveHomeStack(targetStack.isHomeStack());
1334                    if (intentActivity.task.intent == null) {
1335                        // This task was started because of movement of
1336                        // the activity based on affinity...  now that we
1337                        // are actually launching it, we can assign the
1338                        // base intent.
1339                        intentActivity.task.setIntent(intent, r.info);
1340                    }
1341                    // If the target task is not in the front, then we need
1342                    // to bring it to the front...  except...  well, with
1343                    // SINGLE_TASK_LAUNCH it's not entirely clear.  We'd like
1344                    // to have the same behavior as if a new instance was
1345                    // being started, which means not bringing it to the front
1346                    // if the caller is not itself in the front.
1347                    final ActivityStack lastStack = getLastStack();
1348                    ActivityRecord curTop = lastStack == null?
1349                            null : lastStack.topRunningNonDelayedActivityLocked(notTop);
1350                    if (curTop != null && curTop.task != intentActivity.task) {
1351                        r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1352                        if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
1353                            // We really do want to push this one into the
1354                            // user's face, right now.
1355                            movedHome = true;
1356                            if ((launchFlags &
1357                                    (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1358                                    == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1359                                // Caller wants to appear on home activity, so before starting
1360                                // their own activity we will bring home to the front.
1361                                r.mLaunchHomeTaskNext = true;
1362                            }
1363                            targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1364                            options = null;
1365                        }
1366                    }
1367                    // If the caller has requested that the target task be
1368                    // reset, then do so.
1369                    if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1370                        intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1371                    }
1372                    if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1373                        // We don't need to start a new activity, and
1374                        // the client said not to do anything if that
1375                        // is the case, so this is it!  And for paranoia, make
1376                        // sure we have correctly resumed the top activity.
1377                        if (doResume) {
1378                            setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
1379                            resumeTopActivitiesLocked(targetStack, null, options);
1380                        } else {
1381                            ActivityOptions.abort(options);
1382                        }
1383                        if (r.task == null)  Slog.v(TAG,
1384                                "startActivityUncheckedLocked: task left null",
1385                                new RuntimeException("here").fillInStackTrace());
1386                        return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1387                    }
1388                    if ((launchFlags &
1389                            (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1390                            == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1391                        // The caller has requested to completely replace any
1392                        // existing task with its new activity.  Well that should
1393                        // not be too hard...
1394                        reuseTask = intentActivity.task;
1395                        reuseTask.performClearTaskLocked();
1396                        reuseTask.setIntent(r.intent, r.info);
1397                    } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1398                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1399                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1400                        // In this situation we want to remove all activities
1401                        // from the task up to the one being started.  In most
1402                        // cases this means we are resetting the task to its
1403                        // initial state.
1404                        ActivityRecord top =
1405                                intentActivity.task.performClearTaskLocked(r, launchFlags);
1406                        if (top != null) {
1407                            if (top.frontOfTask) {
1408                                // Activity aliases may mean we use different
1409                                // intents for the top activity, so make sure
1410                                // the task now has the identity of the new
1411                                // intent.
1412                                top.task.setIntent(r.intent, r.info);
1413                            }
1414                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1415                                    r, top.task);
1416                            top.deliverNewIntentLocked(callingUid, r.intent);
1417                        } else {
1418                            // A special case: we need to
1419                            // start the activity because it is not currently
1420                            // running, and the caller has asked to clear the
1421                            // current task to have this activity at the top.
1422                            addingToTask = true;
1423                            // Now pretend like this activity is being started
1424                            // by the top of its task, so it is put in the
1425                            // right place.
1426                            sourceRecord = intentActivity;
1427                        }
1428                    } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1429                        // In this case the top activity on the task is the
1430                        // same as the one being launched, so we take that
1431                        // as a request to bring the task to the foreground.
1432                        // If the top activity in the task is the root
1433                        // activity, deliver this new intent to it if it
1434                        // desires.
1435                        if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1436                                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1437                                && intentActivity.realActivity.equals(r.realActivity)) {
1438                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1439                                    intentActivity.task);
1440                            if (intentActivity.frontOfTask) {
1441                                intentActivity.task.setIntent(r.intent, r.info);
1442                            }
1443                            intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1444                        } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1445                            // In this case we are launching the root activity
1446                            // of the task, but with a different intent.  We
1447                            // should start a new instance on top.
1448                            addingToTask = true;
1449                            sourceRecord = intentActivity;
1450                        }
1451                    } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1452                        // In this case an activity is being launched in to an
1453                        // existing task, without resetting that task.  This
1454                        // is typically the situation of launching an activity
1455                        // from a notification or shortcut.  We want to place
1456                        // the new activity on top of the current task.
1457                        addingToTask = true;
1458                        sourceRecord = intentActivity;
1459                    } else if (!intentActivity.task.rootWasReset) {
1460                        // In this case we are launching in to an existing task
1461                        // that has not yet been started from its front door.
1462                        // The current task has been brought to the front.
1463                        // Ideally, we'd probably like to place this new task
1464                        // at the bottom of its stack, but that's a little hard
1465                        // to do with the current organization of the code so
1466                        // for now we'll just drop it.
1467                        intentActivity.task.setIntent(r.intent, r.info);
1468                    }
1469                    if (!addingToTask && reuseTask == null) {
1470                        // We didn't do anything...  but it was needed (a.k.a., client
1471                        // don't use that intent!)  And for paranoia, make
1472                        // sure we have correctly resumed the top activity.
1473                        if (doResume) {
1474                            setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1475                            targetStack.resumeTopActivityLocked(null, options);
1476                        } else {
1477                            ActivityOptions.abort(options);
1478                        }
1479                        if (r.task == null)  Slog.v(TAG,
1480                            "startActivityUncheckedLocked: task left null",
1481                            new RuntimeException("here").fillInStackTrace());
1482                        return ActivityManager.START_TASK_TO_FRONT;
1483                    }
1484                }
1485            }
1486        }
1487
1488        //String uri = r.intent.toURI();
1489        //Intent intent2 = new Intent(uri);
1490        //Slog.i(TAG, "Given intent: " + r.intent);
1491        //Slog.i(TAG, "URI is: " + uri);
1492        //Slog.i(TAG, "To intent: " + intent2);
1493
1494        if (r.packageName != null) {
1495            // If the activity being launched is the same as the one currently
1496            // at the top, then we need to check if it should only be launched
1497            // once.
1498            ActivityStack topStack = getFocusedStack();
1499            ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
1500            if (top != null && r.resultTo == null) {
1501                if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1502                    if (top.app != null && top.app.thread != null) {
1503                        if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1504                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1505                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1506                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1507                                    top.task);
1508                            // For paranoia, make sure we have correctly
1509                            // resumed the top activity.
1510                            if (doResume) {
1511                                setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
1512                                resumeTopActivitiesLocked();
1513                            }
1514                            ActivityOptions.abort(options);
1515                            if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1516                                // We don't need to start a new activity, and
1517                                // the client said not to do anything if that
1518                                // is the case, so this is it!
1519                                if (r.task == null)  Slog.v(TAG,
1520                                    "startActivityUncheckedLocked: task left null",
1521                                    new RuntimeException("here").fillInStackTrace());
1522                                return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1523                            }
1524                            top.deliverNewIntentLocked(callingUid, r.intent);
1525                            if (r.task == null)  Slog.v(TAG,
1526                                "startActivityUncheckedLocked: task left null",
1527                                new RuntimeException("here").fillInStackTrace());
1528                            return ActivityManager.START_DELIVERED_TO_TOP;
1529                        }
1530                    }
1531                }
1532            }
1533
1534        } else {
1535            if (r.resultTo != null) {
1536                r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1537                        r.requestCode, Activity.RESULT_CANCELED, null);
1538            }
1539            ActivityOptions.abort(options);
1540            if (r.task == null)  Slog.v(TAG,
1541                "startActivityUncheckedLocked: task left null",
1542                new RuntimeException("here").fillInStackTrace());
1543            return ActivityManager.START_CLASS_NOT_FOUND;
1544        }
1545
1546        boolean newTask = false;
1547        boolean keepCurTransition = false;
1548
1549        // Should this be considered a new task?
1550        if (r.resultTo == null && !addingToTask
1551                && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1552            targetStack = getCorrectStack(r);
1553            moveHomeStack(targetStack.isHomeStack());
1554            if (reuseTask == null) {
1555                r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1556                        null, true);
1557                if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1558                        r.task);
1559            } else {
1560                r.setTask(reuseTask, reuseTask, true);
1561            }
1562            newTask = true;
1563            if (!movedHome) {
1564                if ((launchFlags &
1565                        (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1566                        == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1567                    // Caller wants to appear on home activity, so before starting
1568                    // their own activity we will bring home to the front.
1569                    r.mLaunchHomeTaskNext = true;
1570                }
1571            }
1572        } else if (sourceRecord != null) {
1573            sourceTask = sourceRecord.task;
1574            targetStack = sourceTask.stack;
1575            moveHomeStack(targetStack.isHomeStack());
1576            if (!addingToTask &&
1577                    (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1578                // In this case, we are adding the activity to an existing
1579                // task, but the caller has asked to clear that task if the
1580                // activity is already running.
1581                ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
1582                keepCurTransition = true;
1583                if (top != null) {
1584                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1585                    top.deliverNewIntentLocked(callingUid, r.intent);
1586                    // For paranoia, make sure we have correctly
1587                    // resumed the top activity.
1588                    if (doResume) {
1589                        setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
1590                        targetStack.resumeTopActivityLocked(null);
1591                    }
1592                    ActivityOptions.abort(options);
1593                    if (r.task == null)  Slog.v(TAG,
1594                        "startActivityUncheckedLocked: task left null",
1595                        new RuntimeException("here").fillInStackTrace());
1596                    return ActivityManager.START_DELIVERED_TO_TOP;
1597                }
1598            } else if (!addingToTask &&
1599                    (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1600                // In this case, we are launching an activity in our own task
1601                // that may already be running somewhere in the history, and
1602                // we want to shuffle it to the front of the stack if so.
1603                final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
1604                if (top != null) {
1605                    final TaskRecord task = top.task;
1606                    task.moveActivityToFrontLocked(top);
1607                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
1608                    top.updateOptionsLocked(options);
1609                    top.deliverNewIntentLocked(callingUid, r.intent);
1610                    if (doResume) {
1611                        setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
1612                        targetStack.resumeTopActivityLocked(null);
1613                    }
1614                    if (r.task == null)  Slog.v(TAG,
1615                        "startActivityUncheckedLocked: task left null",
1616                        new RuntimeException("here").fillInStackTrace());
1617                    return ActivityManager.START_DELIVERED_TO_TOP;
1618                }
1619            }
1620            // An existing activity is starting this new activity, so we want
1621            // to keep the new one in the same task as the one that is starting
1622            // it.
1623            r.setTask(sourceTask, sourceRecord.thumbHolder, false);
1624            if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1625                    + " in existing task " + r.task);
1626
1627        } else {
1628            // This not being started from an existing activity, and not part
1629            // of a new task...  just put it in the top task, though these days
1630            // this case should never happen.
1631            targetStack = getCorrectStack(r);
1632            moveHomeStack(targetStack.isHomeStack());
1633            ActivityRecord prev = targetStack.topActivity();
1634            r.setTask(prev != null ? prev.task
1635                    : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1636                    null, true);
1637            if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1638                    + " in new guessed " + r.task);
1639        }
1640
1641        mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1642                intent, r.getUriPermissionsLocked());
1643
1644        if (newTask) {
1645            EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1646        }
1647        ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
1648        setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
1649        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
1650        return ActivityManager.START_SUCCESS;
1651    }
1652
1653    // Checked.
1654    final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1655            Configuration config) {
1656        if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1657
1658        ActivityRecord res = null;
1659
1660        ArrayList<ActivityRecord> stops = null;
1661        ArrayList<ActivityRecord> finishes = null;
1662        ArrayList<UserStartedState> startingUsers = null;
1663        int NS = 0;
1664        int NF = 0;
1665        IApplicationThread sendThumbnail = null;
1666        boolean booting = false;
1667        boolean enableScreen = false;
1668        boolean activityRemoved = false;
1669
1670        ActivityRecord r = ActivityRecord.forToken(token);
1671        if (r != null) {
1672            if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" +
1673                    Debug.getCallers(4));
1674            mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1675            r.finishLaunchTickingLocked();
1676            res = r.task.stack.activityIdleInternalLocked(token);
1677            if (res != null) {
1678                if (fromTimeout) {
1679                    reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
1680                }
1681
1682                // This is a hack to semi-deal with a race condition
1683                // in the client where it can be constructed with a
1684                // newer configuration from when we asked it to launch.
1685                // We'll update with whatever configuration it now says
1686                // it used to launch.
1687                if (config != null) {
1688                    r.configuration = config;
1689                }
1690
1691                // We are now idle.  If someone is waiting for a thumbnail from
1692                // us, we can now deliver.
1693                r.idle = true;
1694                if (allResumedActivitiesIdle()) {
1695                    mService.scheduleAppGcsLocked();
1696                }
1697                if (r.thumbnailNeeded && r.app != null && r.app.thread != null) {
1698                    sendThumbnail = r.app.thread;
1699                    r.thumbnailNeeded = false;
1700                }
1701
1702                //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1703                if (!mService.mBooted && isFrontStack(r.task.stack)) {
1704                    mService.mBooted = true;
1705                    enableScreen = true;
1706                }
1707            } else if (fromTimeout) {
1708                reportActivityLaunchedLocked(fromTimeout, null, -1, -1);
1709            }
1710        }
1711
1712        // Atomically retrieve all of the other things to do.
1713        stops = processStoppingActivitiesLocked(true);
1714        NS = stops != null ? stops.size() : 0;
1715        if ((NF=mFinishingActivities.size()) > 0) {
1716            finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1717            mFinishingActivities.clear();
1718        }
1719
1720        final ArrayList<ActivityRecord> thumbnails;
1721        final int NT = mCancelledThumbnails.size();
1722        if (NT > 0) {
1723            thumbnails = new ArrayList<ActivityRecord>(mCancelledThumbnails);
1724            mCancelledThumbnails.clear();
1725        } else {
1726            thumbnails = null;
1727        }
1728
1729        if (isFrontStack(mHomeStack)) {
1730            booting = mService.mBooting;
1731            mService.mBooting = false;
1732        }
1733
1734        if (mStartingUsers.size() > 0) {
1735            startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
1736            mStartingUsers.clear();
1737        }
1738
1739        // Perform the following actions from unsynchronized state.
1740        final IApplicationThread thumbnailThread = sendThumbnail;
1741        mHandler.post(new Runnable() {
1742            @Override
1743            public void run() {
1744                if (thumbnailThread != null) {
1745                    try {
1746                        thumbnailThread.requestThumbnail(token);
1747                    } catch (Exception e) {
1748                        Slog.w(TAG, "Exception thrown when requesting thumbnail", e);
1749                        mService.sendPendingThumbnail(null, token, null, null, true);
1750                    }
1751                }
1752
1753                // Report back to any thumbnail receivers.
1754                for (int i = 0; i < NT; i++) {
1755                    ActivityRecord r = thumbnails.get(i);
1756                    mService.sendPendingThumbnail(r, null, null, null, true);
1757                }
1758            }
1759        });
1760
1761        // Stop any activities that are scheduled to do so but have been
1762        // waiting for the next one to start.
1763        for (int i = 0; i < NS; i++) {
1764            r = stops.get(i);
1765            final ActivityStack stack = r.task.stack;
1766            if (r.finishing) {
1767                stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
1768            } else {
1769                stack.stopActivityLocked(r);
1770            }
1771        }
1772
1773        // Finish any activities that are scheduled to do so but have been
1774        // waiting for the next one to start.
1775        for (int i = 0; i < NF; i++) {
1776            r = finishes.get(i);
1777            activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
1778        }
1779
1780        if (booting) {
1781            mService.finishBooting();
1782        } else if (startingUsers != null) {
1783            for (int i = 0; i < startingUsers.size(); i++) {
1784                mService.finishUserSwitch(startingUsers.get(i));
1785            }
1786        }
1787
1788        mService.trimApplications();
1789        //dump();
1790        //mWindowManager.dump();
1791
1792        if (enableScreen) {
1793            mService.enableScreenAfterBoot();
1794        }
1795
1796        if (activityRemoved) {
1797            resumeTopActivitiesLocked();
1798        }
1799
1800        return res;
1801    }
1802
1803    void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1804        // Just in case.
1805        final int numStacks = mStacks.size();
1806        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1807            mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
1808        }
1809    }
1810
1811    void closeSystemDialogsLocked() {
1812        final int numStacks = mStacks.size();
1813        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1814            final ActivityStack stack = mStacks.get(stackNdx);
1815            stack.closeSystemDialogsLocked();
1816        }
1817    }
1818
1819    /**
1820     * @return true if some activity was finished (or would have finished if doit were true).
1821     */
1822    boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1823        boolean didSomething = false;
1824        final int numStacks = mStacks.size();
1825        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1826            final ActivityStack stack = mStacks.get(stackNdx);
1827            if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1828                didSomething = true;
1829            }
1830        }
1831        return didSomething;
1832    }
1833
1834    boolean resumeTopActivitiesLocked() {
1835        return resumeTopActivitiesLocked(null, null, null);
1836    }
1837
1838    boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
1839            Bundle targetOptions) {
1840        if (targetStack == null) {
1841            targetStack = getFocusedStack();
1842        }
1843        boolean result = false;
1844        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1845            final ActivityStack stack = mStacks.get(stackNdx);
1846            if (isFrontStack(stack)) {
1847                if (stack == targetStack) {
1848                    result = stack.resumeTopActivityLocked(target, targetOptions);
1849                } else {
1850                    stack.resumeTopActivityLocked(null);
1851                }
1852            }
1853        }
1854        return result;
1855    }
1856
1857    void finishTopRunningActivityLocked(ProcessRecord app) {
1858        final int numStacks = mStacks.size();
1859        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1860            final ActivityStack stack = mStacks.get(stackNdx);
1861            stack.finishTopRunningActivityLocked(app);
1862        }
1863    }
1864
1865    void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1866        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1867            if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
1868                return;
1869            }
1870        }
1871    }
1872
1873    ActivityStack getStack(int stackId) {
1874        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1875            final ActivityStack stack = mStacks.get(stackNdx);
1876            if (stack.getStackId() == stackId) {
1877                return stack;
1878            }
1879        }
1880        return null;
1881    }
1882
1883    ArrayList<ActivityStack> getStacks() {
1884        return new ArrayList<ActivityStack>(mStacks);
1885    }
1886
1887    int createStack() {
1888        while (true) {
1889            if (++mLastStackId <= HOME_STACK_ID) {
1890                mLastStackId = HOME_STACK_ID + 1;
1891            }
1892            if (getStack(mLastStackId) == null) {
1893                break;
1894            }
1895        }
1896        mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
1897        return mLastStackId;
1898    }
1899
1900    void moveTaskToStack(int taskId, int stackId, boolean toTop) {
1901        final TaskRecord task = anyTaskForIdLocked(taskId);
1902        if (task == null) {
1903            return;
1904        }
1905        final ActivityStack stack = getStack(stackId);
1906        if (stack == null) {
1907            Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
1908            return;
1909        }
1910        removeTask(task);
1911        stack.addTask(task, toTop);
1912        if (toTop) {
1913            moveHomeStack(stack.isHomeStack());
1914            setFocusedStack(task.getTopActivity());
1915        }
1916        mWindowManager.addTask(taskId, stackId, toTop);
1917        resumeTopActivitiesLocked();
1918    }
1919
1920    ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
1921        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1922            final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info);
1923            if (ar != null) {
1924                return ar;
1925            }
1926        }
1927        return null;
1928    }
1929
1930    ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
1931        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1932            final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
1933            if (ar != null) {
1934                return ar;
1935            }
1936        }
1937        return null;
1938    }
1939
1940    void goingToSleepLocked() {
1941        scheduleSleepTimeout();
1942        if (!mGoingToSleep.isHeld()) {
1943            mGoingToSleep.acquire();
1944            for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1945                final ActivityStack stack = mStacks.get(stackNdx);
1946                if (stack.mResumedActivity != null) {
1947                    stack.stopIfSleepingLocked();
1948                }
1949            }
1950        }
1951    }
1952
1953    boolean shutdownLocked(int timeout) {
1954        boolean timedout = false;
1955        goingToSleepLocked();
1956        checkReadyForSleepLocked();
1957
1958        final long endTime = System.currentTimeMillis() + timeout;
1959        while (true) {
1960            boolean cantShutdown = false;
1961            for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1962                cantShutdown |= mStacks.get(stackNdx).checkReadyForSleepLocked();
1963            }
1964            if (cantShutdown) {
1965                long timeRemaining = endTime - System.currentTimeMillis();
1966                if (timeRemaining > 0) {
1967                    try {
1968                        mService.wait(timeRemaining);
1969                    } catch (InterruptedException e) {
1970                    }
1971                } else {
1972                    Slog.w(TAG, "Activity manager shutdown timed out");
1973                    timedout = true;
1974                    break;
1975                }
1976            } else {
1977                break;
1978            }
1979        }
1980
1981        // Force checkReadyForSleep to complete.
1982        mSleepTimeout = true;
1983        checkReadyForSleepLocked();
1984
1985        return timedout;
1986    }
1987
1988    void comeOutOfSleepIfNeededLocked() {
1989        removeSleepTimeouts();
1990        if (mGoingToSleep.isHeld()) {
1991            mGoingToSleep.release();
1992        }
1993        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1994            final ActivityStack stack = mStacks.get(stackNdx);
1995            stack.awakeFromSleepingLocked();
1996            if (isFrontStack(stack)) {
1997                resumeTopActivitiesLocked();
1998            }
1999        }
2000        mGoingToSleepActivities.clear();
2001    }
2002
2003    void activitySleptLocked(ActivityRecord r) {
2004        mGoingToSleepActivities.remove(r);
2005        checkReadyForSleepLocked();
2006    }
2007
2008    void checkReadyForSleepLocked() {
2009        if (!mService.isSleepingOrShuttingDown()) {
2010            // Do not care.
2011            return;
2012        }
2013
2014        if (!mSleepTimeout) {
2015            boolean dontSleep = false;
2016            for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2017                dontSleep |= mStacks.get(stackNdx).checkReadyForSleepLocked();
2018            }
2019
2020            if (mStoppingActivities.size() > 0) {
2021                // Still need to tell some activities to stop; can't sleep yet.
2022                if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
2023                        + mStoppingActivities.size() + " activities");
2024                scheduleIdleLocked();
2025                dontSleep = true;
2026            }
2027
2028            if (mGoingToSleepActivities.size() > 0) {
2029                // Still need to tell some activities to sleep; can't sleep yet.
2030                if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
2031                        + mGoingToSleepActivities.size() + " activities");
2032                dontSleep = true;
2033            }
2034
2035            if (dontSleep) {
2036                return;
2037            }
2038        }
2039
2040        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2041            mStacks.get(stackNdx).goToSleep();
2042        }
2043
2044        removeSleepTimeouts();
2045
2046        if (mGoingToSleep.isHeld()) {
2047            mGoingToSleep.release();
2048        }
2049        if (mService.mShuttingDown) {
2050            mService.notifyAll();
2051        }
2052    }
2053
2054    boolean reportResumedActivityLocked(ActivityRecord r) {
2055        final ActivityStack stack = r.task.stack;
2056        if (isFrontStack(stack)) {
2057            mService.updateUsageStats(r, true);
2058            mService.setFocusedActivityLocked(r);
2059        }
2060        if (allResumedActivitiesComplete()) {
2061            ensureActivitiesVisibleLocked(null, 0);
2062            mWindowManager.executeAppTransition();
2063            return true;
2064        }
2065        return false;
2066    }
2067
2068    void handleAppCrashLocked(ProcessRecord app) {
2069        final int numStacks = mStacks.size();
2070        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2071            final ActivityStack stack = mStacks.get(stackNdx);
2072            stack.handleAppCrashLocked(app);
2073        }
2074    }
2075
2076    void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
2077        // First the front stacks. In case any are not fullscreen and are in front of home.
2078        boolean showHomeBehindStack = false;
2079        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2080            final ActivityStack stack = mStacks.get(stackNdx);
2081            if (isFrontStack(stack)) {
2082                showHomeBehindStack =
2083                        stack.ensureActivitiesVisibleLocked(starting, configChanges);
2084            }
2085        }
2086        // Now do back stacks.
2087        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2088            final ActivityStack stack = mStacks.get(stackNdx);
2089            if (!isFrontStack(stack)) {
2090                stack.ensureActivitiesVisibleLocked(starting, configChanges, showHomeBehindStack);
2091            }
2092        }
2093    }
2094
2095    void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
2096        final int numStacks = mStacks.size();
2097        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2098            final ActivityStack stack = mStacks.get(stackNdx);
2099            stack.scheduleDestroyActivities(app, false, reason);
2100        }
2101    }
2102
2103    boolean switchUserLocked(int userId, UserStartedState uss) {
2104        mUserStates.put(mCurrentUser, new UserState());
2105        mCurrentUser = userId;
2106        UserState userState = mUserStates.get(userId);
2107        if (userState != null) {
2108            userState.restore();
2109            mUserStates.delete(userId);
2110        } else {
2111            mFocusedStack = null;
2112            if (DEBUG_STACK) Slog.d(TAG, "switchUserLocked: mStackState=" +
2113                    stackStateToString(STACK_STATE_HOME_IN_FRONT));
2114            mStackState = STACK_STATE_HOME_IN_FRONT;
2115        }
2116
2117        mStartingUsers.add(uss);
2118        boolean haveActivities = mHomeStack.switchUserLocked(userId);
2119
2120        resumeTopActivitiesLocked();
2121
2122        return haveActivities;
2123    }
2124
2125    final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
2126        int N = mStoppingActivities.size();
2127        if (N <= 0) return null;
2128
2129        ArrayList<ActivityRecord> stops = null;
2130
2131        final boolean nowVisible = allResumedActivitiesVisible();
2132        for (int i=0; i<N; i++) {
2133            ActivityRecord s = mStoppingActivities.get(i);
2134            if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
2135                    + nowVisible + " waitingVisible=" + s.waitingVisible
2136                    + " finishing=" + s.finishing);
2137            if (s.waitingVisible && nowVisible) {
2138                mWaitingVisibleActivities.remove(s);
2139                s.waitingVisible = false;
2140                if (s.finishing) {
2141                    // If this activity is finishing, it is sitting on top of
2142                    // everyone else but we now know it is no longer needed...
2143                    // so get rid of it.  Otherwise, we need to go through the
2144                    // normal flow and hide it once we determine that it is
2145                    // hidden by the activities in front of it.
2146                    if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
2147                    mWindowManager.setAppVisibility(s.appToken, false);
2148                }
2149            }
2150            if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
2151                if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
2152                if (stops == null) {
2153                    stops = new ArrayList<ActivityRecord>();
2154                }
2155                stops.add(s);
2156                mStoppingActivities.remove(i);
2157                N--;
2158                i--;
2159            }
2160        }
2161
2162        return stops;
2163    }
2164
2165    void validateTopActivitiesLocked() {
2166        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
2167            final ActivityStack stack = mStacks.get(stackNdx);
2168            final ActivityRecord r = stack.topRunningActivityLocked(null);
2169            if (isFrontStack(stack)) {
2170                if (r == null) {
2171                    Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
2172                } else {
2173                    if (stack.mPausingActivity != null) {
2174                        Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
2175                            " state=" + r.state);
2176                    }
2177                    if (r.state != ActivityState.INITIALIZING &&
2178                            r.state != ActivityState.RESUMED) {
2179                        Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
2180                                " state=" + r.state);
2181                    }
2182                }
2183            } else {
2184                if (stack.mResumedActivity != null) {
2185                    Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
2186                        " state=" + r.state);
2187                }
2188                if (r != null && (r.state == ActivityState.INITIALIZING
2189                        || r.state == ActivityState.RESUMED)) {
2190                    Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
2191                            " state=" + r.state);
2192                }
2193            }
2194        }
2195    }
2196
2197    private static String stackStateToString(int stackState) {
2198        switch (stackState) {
2199            case STACK_STATE_HOME_IN_FRONT: return "STACK_STATE_HOME_IN_FRONT";
2200            case STACK_STATE_HOME_TO_BACK: return "STACK_STATE_HOME_TO_BACK";
2201            case STACK_STATE_HOME_IN_BACK: return "STACK_STATE_HOME_IN_BACK";
2202            case STACK_STATE_HOME_TO_FRONT: return "STACK_STATE_HOME_TO_FRONT";
2203            default: return "Unknown stackState=" + stackState;
2204        }
2205    }
2206
2207    public void dump(PrintWriter pw, String prefix) {
2208        pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
2209                pw.println(mDismissKeyguardOnNextActivity);
2210        pw.print(prefix); pw.print("mStackState="); pw.println(stackStateToString(mStackState));
2211    }
2212
2213    ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
2214        return getFocusedStack().getDumpActivitiesLocked(name);
2215    }
2216
2217    boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2218            boolean dumpClient, String dumpPackage) {
2219        pw.print("  mStackState="); pw.println(stackStateToString(mStackState));
2220        if (mGoingToSleepActivities.size() > 0) {
2221            pw.println("  Activities waiting to sleep:");
2222            dumpHistoryList(fd, pw, mGoingToSleepActivities, "  ", "Sleep", false, !dumpAll, false,
2223                    dumpPackage);
2224        }
2225        if (dumpAll) {
2226            pw.println("  mSleepTimeout: " + mSleepTimeout);
2227        }
2228        final int numStacks = mStacks.size();
2229        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2230            final ActivityStack stack = mStacks.get(stackNdx);
2231            pw.print("  Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
2232            stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
2233            pw.println(" ");
2234            pw.println("  Running activities (most recent first):");
2235            dumpHistoryList(fd, pw, stack.mLRUActivities, "  ", "Run", false, !dumpAll, false,
2236                    dumpPackage);
2237
2238            pw.print("  Stack #"); pw.println(mStacks.indexOf(stack));
2239            if (stack.mPausingActivity != null) {
2240                pw.println("  mPausingActivity: " + stack.mPausingActivity);
2241            }
2242            pw.println("  mResumedActivity: " + stack.mResumedActivity);
2243            if (dumpAll) {
2244                pw.println("  mLastPausedActivity: " + stack.mLastPausedActivity);
2245            }
2246        }
2247
2248        if (mFinishingActivities.size() > 0) {
2249            pw.println(" ");
2250            pw.println("  Activities waiting to finish:");
2251            dumpHistoryList(fd, pw, mFinishingActivities, "  ", "Fin", false, !dumpAll, false,
2252                    dumpPackage);
2253        }
2254
2255        if (mStoppingActivities.size() > 0) {
2256            pw.println(" ");
2257            pw.println("  Activities waiting to stop:");
2258            dumpHistoryList(fd, pw, mStoppingActivities, "  ", "Stop", false, !dumpAll, false,
2259                    dumpPackage);
2260        }
2261
2262        if (mWaitingVisibleActivities.size() > 0) {
2263            pw.println(" ");
2264            pw.println("  Activities waiting for another to become visible:");
2265            dumpHistoryList(fd, pw, mWaitingVisibleActivities, "  ", "Wait", false, !dumpAll,
2266                    false, dumpPackage);
2267        }
2268
2269        if (dumpAll) {
2270            pw.println(" ");
2271            pw.println("  mCurTaskId: " + mCurTaskId);
2272        }
2273        return true;
2274    }
2275
2276    static void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
2277            String prefix, String label, boolean complete, boolean brief, boolean client,
2278            String dumpPackage) {
2279        TaskRecord lastTask = null;
2280        boolean needNL = false;
2281        final String innerPrefix = prefix + "      ";
2282        final String[] args = new String[0];
2283        for (int i=list.size()-1; i>=0; i--) {
2284            final ActivityRecord r = list.get(i);
2285            if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2286                continue;
2287            }
2288            final boolean full = !brief && (complete || !r.isInHistory());
2289            if (needNL) {
2290                pw.println(" ");
2291                needNL = false;
2292            }
2293            if (lastTask != r.task) {
2294                lastTask = r.task;
2295                pw.print(prefix);
2296                pw.print(full ? "* " : "  ");
2297                pw.println(lastTask);
2298                if (full) {
2299                    lastTask.dump(pw, prefix + "  ");
2300                } else if (complete) {
2301                    // Complete + brief == give a summary.  Isn't that obvious?!?
2302                    if (lastTask.intent != null) {
2303                        pw.print(prefix); pw.print("  ");
2304                                pw.println(lastTask.intent.toInsecureStringWithClip());
2305                    }
2306                }
2307            }
2308            pw.print(prefix); pw.print(full ? "  * " : "    "); pw.print(label);
2309            pw.print(" #"); pw.print(i); pw.print(": ");
2310            pw.println(r);
2311            if (full) {
2312                r.dump(pw, innerPrefix);
2313            } else if (complete) {
2314                // Complete + brief == give a summary.  Isn't that obvious?!?
2315                pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2316                if (r.app != null) {
2317                    pw.print(innerPrefix); pw.println(r.app);
2318                }
2319            }
2320            if (client && r.app != null && r.app.thread != null) {
2321                // flush anything that is already in the PrintWriter since the thread is going
2322                // to write to the file descriptor directly
2323                pw.flush();
2324                try {
2325                    TransferPipe tp = new TransferPipe();
2326                    try {
2327                        r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2328                                r.appToken, innerPrefix, args);
2329                        // Short timeout, since blocking here can
2330                        // deadlock with the application.
2331                        tp.go(fd, 2000);
2332                    } finally {
2333                        tp.kill();
2334                    }
2335                } catch (IOException e) {
2336                    pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2337                } catch (RemoteException e) {
2338                    pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2339                }
2340                needNL = true;
2341            }
2342        }
2343    }
2344
2345    void scheduleIdleTimeoutLocked(ActivityRecord next) {
2346        if (DEBUG_IDLE) Slog.d(TAG, "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
2347        Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
2348        mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2349    }
2350
2351    final void scheduleIdleLocked() {
2352        mHandler.sendEmptyMessage(IDLE_NOW_MSG);
2353    }
2354
2355    void removeTimeoutsForActivityLocked(ActivityRecord r) {
2356        if (DEBUG_IDLE) Slog.d(TAG, "removeTimeoutsForActivity: Callers=" + Debug.getCallers(4));
2357        mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2358    }
2359
2360    final void scheduleResumeTopActivities() {
2361        mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2362    }
2363
2364    void removeSleepTimeouts() {
2365        mSleepTimeout = false;
2366        mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
2367    }
2368
2369    final void scheduleSleepTimeout() {
2370        removeSleepTimeouts();
2371        mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
2372    }
2373
2374    private final class ActivityStackSupervisorHandler extends Handler {
2375
2376        public ActivityStackSupervisorHandler(Looper looper) {
2377            super(looper);
2378        }
2379
2380        void activityIdleInternal(ActivityRecord r) {
2381            synchronized (mService) {
2382                activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2383            }
2384        }
2385
2386        @Override
2387        public void handleMessage(Message msg) {
2388            switch (msg.what) {
2389                case IDLE_TIMEOUT_MSG: {
2390                    if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_TIMEOUT_MSG: Callers=" +
2391                            Debug.getCallers(4));
2392                    if (mService.mDidDexOpt) {
2393                        mService.mDidDexOpt = false;
2394                        Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2395                        nmsg.obj = msg.obj;
2396                        mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2397                        return;
2398                    }
2399                    // We don't at this point know if the activity is fullscreen,
2400                    // so we need to be conservative and assume it isn't.
2401                    activityIdleInternal((ActivityRecord)msg.obj);
2402                } break;
2403                case IDLE_NOW_MSG: {
2404                    activityIdleInternal((ActivityRecord)msg.obj);
2405                } break;
2406                case RESUME_TOP_ACTIVITY_MSG: {
2407                    synchronized (mService) {
2408                        resumeTopActivitiesLocked();
2409                    }
2410                } break;
2411                case SLEEP_TIMEOUT_MSG: {
2412                    synchronized (mService) {
2413                        if (mService.isSleepingOrShuttingDown()) {
2414                            Slog.w(TAG, "Sleep timeout!  Sleeping now.");
2415                            mSleepTimeout = true;
2416                            checkReadyForSleepLocked();
2417                        }
2418                    }
2419                } break;
2420            }
2421        }
2422    }
2423
2424    private final class UserState {
2425        final ActivityStack mSavedFocusedStack;
2426        final int mSavedStackState;
2427
2428        public UserState() {
2429            ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2430            mSavedFocusedStack = supervisor.mFocusedStack;
2431            mSavedStackState = supervisor.mStackState;
2432        }
2433
2434        void restore() {
2435            ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
2436            supervisor.mFocusedStack = mSavedFocusedStack;
2437            if (DEBUG_STACK) Slog.d(TAG, "UserState.restore: mStackState old=" +
2438                    stackStateToString(mSavedStackState));
2439            supervisor.mStackState = mSavedStackState;
2440        }
2441    }
2442}
2443