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