ActivityStackSupervisor.java revision a254cd7e0ffd7d3b131f3c7a69c9fa13dbacc0bd
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_FOCUS;
26import static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
27import static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
28import static com.android.server.am.ActivityManagerService.DEBUG_STACK;
29import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
30import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
31import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
32import static com.android.server.am.ActivityManagerService.FIRST_SUPERVISOR_STACK_MSG;
33import static com.android.server.am.ActivityManagerService.TAG;
34import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
35import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
36import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
37
38import android.app.Activity;
39import android.app.ActivityManager;
40import android.app.ActivityManager.StackInfo;
41import android.app.ActivityOptions;
42import android.app.AppGlobals;
43import android.app.IActivityContainer;
44import android.app.IActivityContainerCallback;
45import android.app.IActivityManager;
46import android.app.IApplicationThread;
47import android.app.PendingIntent;
48import android.app.ActivityManager.RunningTaskInfo;
49import android.app.IActivityManager.WaitResult;
50import android.app.ResultInfo;
51import android.content.ComponentName;
52import android.content.Context;
53import android.content.IIntentSender;
54import android.content.Intent;
55import android.content.IntentSender;
56import android.content.pm.ActivityInfo;
57import android.content.pm.ApplicationInfo;
58import android.content.pm.PackageManager;
59import android.content.pm.ResolveInfo;
60import android.content.res.Configuration;
61import android.graphics.Point;
62import android.hardware.display.DisplayManager;
63import android.hardware.display.DisplayManager.DisplayListener;
64import android.hardware.display.DisplayManagerGlobal;
65import android.hardware.display.VirtualDisplay;
66import android.hardware.input.InputManager;
67import android.hardware.input.InputManagerInternal;
68import android.os.Binder;
69import android.os.Bundle;
70import android.os.Debug;
71import android.os.Handler;
72import android.os.IBinder;
73import android.os.Looper;
74import android.os.Message;
75import android.os.ParcelFileDescriptor;
76import android.os.PowerManager;
77import android.os.Process;
78import android.os.RemoteException;
79import android.os.SystemClock;
80import android.os.UserHandle;
81import android.service.voice.IVoiceInteractionSession;
82import android.util.EventLog;
83import android.util.Slog;
84import android.util.SparseArray;
85
86import android.util.SparseIntArray;
87import android.view.Display;
88import android.view.DisplayInfo;
89import android.view.InputEvent;
90import android.view.Surface;
91import com.android.internal.app.HeavyWeightSwitcherActivity;
92import com.android.internal.app.IVoiceInteractor;
93import com.android.internal.os.TransferPipe;
94import com.android.server.LocalServices;
95import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
96import com.android.server.am.ActivityStack.ActivityState;
97import com.android.server.wm.WindowManagerService;
98
99import java.io.FileDescriptor;
100import java.io.IOException;
101import java.io.PrintWriter;
102import java.util.ArrayList;
103import java.util.List;
104
105public final class ActivityStackSupervisor implements DisplayListener {
106    static final boolean DEBUG = ActivityManagerService.DEBUG || false;
107    static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
108    static final boolean DEBUG_APP = DEBUG || false;
109    static final boolean DEBUG_SAVED_STATE = DEBUG || false;
110    static final boolean DEBUG_STATES = DEBUG || false;
111    static final boolean DEBUG_IDLE = DEBUG || false;
112
113    public static final int HOME_STACK_ID = 0;
114
115    /** How long we wait until giving up on the last activity telling us it is idle. */
116    static final int IDLE_TIMEOUT = 10*1000;
117
118    /** How long we can hold the sleep wake lock before giving up. */
119    static final int SLEEP_TIMEOUT = 5*1000;
120
121    // How long we can hold the launch wake lock before giving up.
122    static final int LAUNCH_TIMEOUT = 10*1000;
123
124    static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG;
125    static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_STACK_MSG + 1;
126    static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_STACK_MSG + 2;
127    static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 3;
128    static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_STACK_MSG + 4;
129    static final int HANDLE_DISPLAY_ADDED = FIRST_SUPERVISOR_STACK_MSG + 5;
130    static final int HANDLE_DISPLAY_CHANGED = FIRST_SUPERVISOR_STACK_MSG + 6;
131    static final int HANDLE_DISPLAY_REMOVED = FIRST_SUPERVISOR_STACK_MSG + 7;
132    static final int CONTAINER_CALLBACK_VISIBILITY = FIRST_SUPERVISOR_STACK_MSG + 8;
133
134    private final static String VIRTUAL_DISPLAY_BASE_NAME = "ActivityViewVirtualDisplay";
135
136    // For debugging to make sure the caller when acquiring/releasing our
137    // wake lock is the system process.
138    static final boolean VALIDATE_WAKE_LOCK_CALLER = false;
139
140    final ActivityManagerService mService;
141
142    final ActivityStackSupervisorHandler mHandler;
143
144    /** Short cut */
145    WindowManagerService mWindowManager;
146    DisplayManager mDisplayManager;
147
148    /** Dismiss the keyguard after the next activity is displayed? */
149    boolean mDismissKeyguardOnNextActivity = false;
150
151    /** Identifier counter for all ActivityStacks */
152    private int mLastStackId = HOME_STACK_ID;
153
154    /** Task identifier that activities are currently being started in.  Incremented each time a
155     * new task is created. */
156    private int mCurTaskId = 0;
157
158    /** The current user */
159    private int mCurrentUser;
160
161    /** The stack containing the launcher app. Assumed to always be attached to
162     * Display.DEFAULT_DISPLAY. */
163    private ActivityStack mHomeStack;
164
165    /** The stack currently receiving input or launching the next activity. */
166    private ActivityStack mFocusedStack;
167
168    /** If this is the same as mFocusedStack then the activity on the top of the focused stack has
169     * been resumed. If stacks are changing position this will hold the old stack until the new
170     * stack becomes resumed after which it will be set to mFocusedStack. */
171    private ActivityStack mLastFocusedStack;
172
173    /** List of activities that are waiting for a new activity to become visible before completing
174     * whatever operation they are supposed to do. */
175    final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
176
177    /** List of processes waiting to find out about the next visible activity. */
178    final ArrayList<IActivityManager.WaitResult> mWaitingActivityVisible =
179            new ArrayList<IActivityManager.WaitResult>();
180
181    /** List of processes waiting to find out about the next launched activity. */
182    final ArrayList<IActivityManager.WaitResult> mWaitingActivityLaunched =
183            new ArrayList<IActivityManager.WaitResult>();
184
185    /** List of activities that are ready to be stopped, but waiting for the next activity to
186     * settle down before doing so. */
187    final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
188
189    /** List of activities that are ready to be finished, but waiting for the previous activity to
190     * settle down before doing so.  It contains ActivityRecord objects. */
191    final ArrayList<ActivityRecord> mFinishingActivities = new ArrayList<ActivityRecord>();
192
193    /** List of activities that are in the process of going to sleep. */
194    final ArrayList<ActivityRecord> mGoingToSleepActivities = new ArrayList<ActivityRecord>();
195
196    /** Used on user changes */
197    final ArrayList<UserStartedState> mStartingUsers = new ArrayList<UserStartedState>();
198
199    /** Used to queue up any background users being started */
200    final ArrayList<UserStartedState> mStartingBackgroundUsers = new ArrayList<UserStartedState>();
201
202    /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
203     * is being brought in front of us. */
204    boolean mUserLeaving = false;
205
206    /** Set when we have taken too long waiting to go to sleep. */
207    boolean mSleepTimeout = false;
208
209    /**
210     * We don't want to allow the device to go to sleep while in the process
211     * of launching an activity.  This is primarily to allow alarm intent
212     * receivers to launch an activity and get that to run before the device
213     * goes back to sleep.
214     */
215    final PowerManager.WakeLock mLaunchingActivity;
216
217    /**
218     * Set when the system is going to sleep, until we have
219     * successfully paused the current activity and released our wake lock.
220     * At that point the system is allowed to actually sleep.
221     */
222    final PowerManager.WakeLock mGoingToSleep;
223
224    /** Stack id of the front stack when user switched, indexed by userId. */
225    SparseIntArray mUserStackInFront = new SparseIntArray(2);
226
227    // TODO: Add listener for removal of references.
228    /** Mapping from (ActivityStack/TaskStack).mStackId to their current state */
229    SparseArray<ActivityContainer> mActivityContainers = new SparseArray<ActivityContainer>();
230
231    /** Mapping from displayId to display current state */
232    private final SparseArray<ActivityDisplay> mActivityDisplays =
233            new SparseArray<ActivityDisplay>();
234
235    InputManagerInternal mInputManagerInternal;
236
237    /** If non-null then the task specified remains in front and no other tasks may be started
238     * until the task exits or #stopLockTaskMode() is called. */
239    private TaskRecord mLockTaskModeTask;
240
241    public ActivityStackSupervisor(ActivityManagerService service) {
242        mService = service;
243        PowerManager pm = (PowerManager)mService.mContext.getSystemService(Context.POWER_SERVICE);
244        mGoingToSleep = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Sleep");
245        mHandler = new ActivityStackSupervisorHandler(mService.mHandler.getLooper());
246        if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
247            throw new IllegalStateException("Calling must be system uid");
248        }
249        mLaunchingActivity =
250                pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "ActivityManager-Launch");
251        mLaunchingActivity.setReferenceCounted(false);
252    }
253
254    void setWindowManager(WindowManagerService wm) {
255        synchronized (mService) {
256            mWindowManager = wm;
257
258            mDisplayManager =
259                    (DisplayManager)mService.mContext.getSystemService(Context.DISPLAY_SERVICE);
260            mDisplayManager.registerDisplayListener(this, null);
261
262            Display[] displays = mDisplayManager.getDisplays();
263            for (int displayNdx = displays.length - 1; displayNdx >= 0; --displayNdx) {
264                final int displayId = displays[displayNdx].getDisplayId();
265                ActivityDisplay activityDisplay = new ActivityDisplay(displayId);
266                mActivityDisplays.put(displayId, activityDisplay);
267            }
268
269            createStackOnDisplay(HOME_STACK_ID, Display.DEFAULT_DISPLAY);
270            mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID);
271
272            mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
273        }
274    }
275
276    void dismissKeyguard() {
277        if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
278        if (mDismissKeyguardOnNextActivity) {
279            mDismissKeyguardOnNextActivity = false;
280            mWindowManager.dismissKeyguard();
281        }
282    }
283
284    ActivityStack getFocusedStack() {
285        return mFocusedStack;
286    }
287
288    ActivityStack getLastStack() {
289        return mLastFocusedStack;
290    }
291
292    // TODO: Split into two methods isFrontStack for any visible stack and isFrontmostStack for the
293    // top of all visible stacks.
294    boolean isFrontStack(ActivityStack stack) {
295        final ActivityRecord parent = stack.mActivityContainer.mParentActivity;
296        if (parent != null) {
297            stack = parent.task.stack;
298        }
299        ArrayList<ActivityStack> stacks = stack.mStacks;
300        if (stacks != null && !stacks.isEmpty()) {
301            return stack == stacks.get(stacks.size() - 1);
302        }
303        return false;
304    }
305
306    void moveHomeStack(boolean toFront) {
307        ArrayList<ActivityStack> stacks = mHomeStack.mStacks;
308        int topNdx = stacks.size() - 1;
309        if (topNdx <= 0) {
310            return;
311        }
312        ActivityStack topStack = stacks.get(topNdx);
313        final boolean homeInFront = topStack == mHomeStack;
314        if (homeInFront != toFront) {
315            mLastFocusedStack = topStack;
316            stacks.remove(mHomeStack);
317            stacks.add(toFront ? topNdx : 0, mHomeStack);
318            mFocusedStack = stacks.get(topNdx);
319            if (DEBUG_STACK) Slog.d(TAG, "moveHomeTask: topStack old=" + topStack + " new="
320                    + mFocusedStack);
321        }
322    }
323
324    void moveHomeStackTaskToTop(int homeStackTaskType) {
325        if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) {
326            mWindowManager.showRecentApps();
327            return;
328        }
329        moveHomeStack(true);
330        mHomeStack.moveHomeStackTaskToTop(homeStackTaskType);
331    }
332
333    boolean resumeHomeStackTask(int homeStackTaskType, ActivityRecord prev) {
334        if (homeStackTaskType == RECENTS_ACTIVITY_TYPE) {
335            mWindowManager.showRecentApps();
336            return false;
337        }
338        moveHomeStackTaskToTop(homeStackTaskType);
339        if (prev != null) {
340            prev.task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
341        }
342
343        ActivityRecord r = mHomeStack.topRunningActivityLocked(null);
344        if (r != null && (r.isHomeActivity() || r.isRecentsActivity())) {
345            mService.setFocusedActivityLocked(r);
346            return resumeTopActivitiesLocked(mHomeStack, prev, null);
347        }
348        return mService.startHomeActivityLocked(mCurrentUser);
349    }
350
351    void setDismissKeyguard(boolean dismiss) {
352        if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen(" dismiss=" + dismiss);
353        mDismissKeyguardOnNextActivity = dismiss;
354    }
355
356    TaskRecord anyTaskForIdLocked(int id) {
357        int numDisplays = mActivityDisplays.size();
358        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
359            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
360            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
361                ActivityStack stack = stacks.get(stackNdx);
362                TaskRecord task = stack.taskForIdLocked(id);
363                if (task != null) {
364                    return task;
365                }
366            }
367        }
368        return null;
369    }
370
371    ActivityRecord isInAnyStackLocked(IBinder token) {
372        int numDisplays = mActivityDisplays.size();
373        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
374            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
375            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
376                final ActivityRecord r = stacks.get(stackNdx).isInStackLocked(token);
377                if (r != null) {
378                    return r;
379                }
380            }
381        }
382        return null;
383    }
384
385    void setNextTaskId(int taskId) {
386        if (taskId > mCurTaskId) {
387            mCurTaskId = taskId;
388        }
389    }
390
391    int getNextTaskId() {
392        do {
393            mCurTaskId++;
394            if (mCurTaskId <= 0) {
395                mCurTaskId = 1;
396            }
397        } while (anyTaskForIdLocked(mCurTaskId) != null);
398        return mCurTaskId;
399    }
400
401    ActivityRecord resumedAppLocked() {
402        ActivityStack stack = getFocusedStack();
403        if (stack == null) {
404            return null;
405        }
406        ActivityRecord resumedActivity = stack.mResumedActivity;
407        if (resumedActivity == null || resumedActivity.app == null) {
408            resumedActivity = stack.mPausingActivity;
409            if (resumedActivity == null || resumedActivity.app == null) {
410                resumedActivity = stack.topRunningActivityLocked(null);
411            }
412        }
413        return resumedActivity;
414    }
415
416    boolean attachApplicationLocked(ProcessRecord app) throws Exception {
417        final String processName = app.processName;
418        boolean didSomething = false;
419        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
420            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
421            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
422                final ActivityStack stack = stacks.get(stackNdx);
423                if (!isFrontStack(stack)) {
424                    continue;
425                }
426                ActivityRecord hr = stack.topRunningActivityLocked(null);
427                if (hr != null) {
428                    if (hr.app == null && app.uid == hr.info.applicationInfo.uid
429                            && processName.equals(hr.processName)) {
430                        try {
431                            if (realStartActivityLocked(hr, app, true, true)) {
432                                didSomething = true;
433                            }
434                        } catch (Exception e) {
435                            Slog.w(TAG, "Exception in new application when starting activity "
436                                  + hr.intent.getComponent().flattenToShortString(), e);
437                            throw e;
438                        }
439                    }
440                }
441            }
442        }
443        if (!didSomething) {
444            ensureActivitiesVisibleLocked(null, 0);
445        }
446        return didSomething;
447    }
448
449    boolean allResumedActivitiesIdle() {
450        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
451            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
452            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
453                final ActivityStack stack = stacks.get(stackNdx);
454                if (!isFrontStack(stack) || stack.numActivities() == 0) {
455                    continue;
456                }
457                final ActivityRecord resumedActivity = stack.mResumedActivity;
458                if (resumedActivity == null || !resumedActivity.idle) {
459                    if (DEBUG_STATES) Slog.d(TAG, "allResumedActivitiesIdle: stack="
460                             + stack.mStackId + " " + resumedActivity + " not idle");
461                    return false;
462                }
463            }
464        }
465        return true;
466    }
467
468    boolean allResumedActivitiesComplete() {
469        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
470            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
471            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
472                final ActivityStack stack = stacks.get(stackNdx);
473                if (isFrontStack(stack)) {
474                    final ActivityRecord r = stack.mResumedActivity;
475                    if (r != null && r.state != ActivityState.RESUMED) {
476                        return false;
477                    }
478                }
479            }
480        }
481        // TODO: Not sure if this should check if all Paused are complete too.
482        if (DEBUG_STACK) Slog.d(TAG,
483                "allResumedActivitiesComplete: mLastFocusedStack changing from=" +
484                mLastFocusedStack + " to=" + mFocusedStack);
485        mLastFocusedStack = mFocusedStack;
486        return true;
487    }
488
489    boolean allResumedActivitiesVisible() {
490        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
491            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
492            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
493                final ActivityStack stack = stacks.get(stackNdx);
494                final ActivityRecord r = stack.mResumedActivity;
495                if (r != null && (!r.nowVisible || r.waitingVisible)) {
496                    return false;
497                }
498            }
499        }
500        return true;
501    }
502
503    /**
504     * Pause all activities in either all of the stacks or just the back stacks.
505     * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
506     * @return true if any activity was paused as a result of this call.
507     */
508    boolean pauseBackStacks(boolean userLeaving) {
509        boolean someActivityPaused = false;
510        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
511            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
512            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
513                final ActivityStack stack = stacks.get(stackNdx);
514                if (!isFrontStack(stack) && stack.mResumedActivity != null) {
515                    if (DEBUG_STATES) Slog.d(TAG, "pauseBackStacks: stack=" + stack +
516                            " mResumedActivity=" + stack.mResumedActivity);
517                    stack.startPausingLocked(userLeaving, false);
518                    someActivityPaused = true;
519                }
520            }
521        }
522        return someActivityPaused;
523    }
524
525    boolean allPausedActivitiesComplete() {
526        boolean pausing = true;
527        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
528            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
529            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
530                final ActivityStack stack = stacks.get(stackNdx);
531                final ActivityRecord r = stack.mPausingActivity;
532                if (r != null && r.state != ActivityState.PAUSED
533                        && r.state != ActivityState.STOPPED
534                        && r.state != ActivityState.STOPPING) {
535                    if (DEBUG_STATES) {
536                        Slog.d(TAG, "allPausedActivitiesComplete: r=" + r + " state=" + r.state);
537                        pausing = false;
538                    } else {
539                        return false;
540                    }
541                }
542            }
543        }
544        return pausing;
545    }
546
547    void pauseChildStacks(ActivityRecord parent, boolean userLeaving, boolean uiSleeping) {
548        // TODO: Put all stacks in supervisor and iterate through them instead.
549        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
550            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
551            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
552                final ActivityStack stack = stacks.get(stackNdx);
553                if (stack.mResumedActivity != null &&
554                        stack.mActivityContainer.mParentActivity == parent) {
555                    stack.startPausingLocked(userLeaving, uiSleeping);
556                }
557            }
558        }
559    }
560
561    void reportActivityVisibleLocked(ActivityRecord r) {
562        for (int i = mWaitingActivityVisible.size()-1; i >= 0; i--) {
563            WaitResult w = mWaitingActivityVisible.get(i);
564            w.timeout = false;
565            if (r != null) {
566                w.who = new ComponentName(r.info.packageName, r.info.name);
567            }
568            w.totalTime = SystemClock.uptimeMillis() - w.thisTime;
569            w.thisTime = w.totalTime;
570        }
571        mService.notifyAll();
572        dismissKeyguard();
573    }
574
575    void reportActivityLaunchedLocked(boolean timeout, ActivityRecord r,
576            long thisTime, long totalTime) {
577        for (int i = mWaitingActivityLaunched.size() - 1; i >= 0; i--) {
578            WaitResult w = mWaitingActivityLaunched.remove(i);
579            w.timeout = timeout;
580            if (r != null) {
581                w.who = new ComponentName(r.info.packageName, r.info.name);
582            }
583            w.thisTime = thisTime;
584            w.totalTime = totalTime;
585        }
586        mService.notifyAll();
587    }
588
589    ActivityRecord topRunningActivityLocked() {
590        final ActivityStack focusedStack = getFocusedStack();
591        ActivityRecord r = focusedStack.topRunningActivityLocked(null);
592        if (r != null) {
593            return r;
594        }
595
596        // Return to the home stack.
597        final ArrayList<ActivityStack> stacks = mHomeStack.mStacks;
598        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
599            final ActivityStack stack = stacks.get(stackNdx);
600            if (stack != focusedStack && isFrontStack(stack)) {
601                r = stack.topRunningActivityLocked(null);
602                if (r != null) {
603                    return r;
604                }
605            }
606        }
607        return null;
608    }
609
610    void getTasksLocked(int maxNum, List<RunningTaskInfo> list, int callingUid, boolean allowed) {
611        // Gather all of the running tasks for each stack into runningTaskLists.
612        ArrayList<ArrayList<RunningTaskInfo>> runningTaskLists =
613                new ArrayList<ArrayList<RunningTaskInfo>>();
614        final int numDisplays = mActivityDisplays.size();
615        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
616            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
617            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
618                final ActivityStack stack = stacks.get(stackNdx);
619                ArrayList<RunningTaskInfo> stackTaskList = new ArrayList<RunningTaskInfo>();
620                runningTaskLists.add(stackTaskList);
621                stack.getTasksLocked(stackTaskList, callingUid, allowed);
622            }
623        }
624
625        // The lists are already sorted from most recent to oldest. Just pull the most recent off
626        // each list and add it to list. Stop when all lists are empty or maxNum reached.
627        while (maxNum > 0) {
628            long mostRecentActiveTime = Long.MIN_VALUE;
629            ArrayList<RunningTaskInfo> selectedStackList = null;
630            final int numTaskLists = runningTaskLists.size();
631            for (int stackNdx = 0; stackNdx < numTaskLists; ++stackNdx) {
632                ArrayList<RunningTaskInfo> stackTaskList = runningTaskLists.get(stackNdx);
633                if (!stackTaskList.isEmpty()) {
634                    final long lastActiveTime = stackTaskList.get(0).lastActiveTime;
635                    if (lastActiveTime > mostRecentActiveTime) {
636                        mostRecentActiveTime = lastActiveTime;
637                        selectedStackList = stackTaskList;
638                    }
639                }
640            }
641            if (selectedStackList != null) {
642                list.add(selectedStackList.remove(0));
643                --maxNum;
644            } else {
645                break;
646            }
647        }
648    }
649
650    ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
651            String profileFile, ParcelFileDescriptor profileFd, int userId) {
652        // Collect information about the target of the Intent.
653        ActivityInfo aInfo;
654        try {
655            ResolveInfo rInfo =
656                AppGlobals.getPackageManager().resolveIntent(
657                        intent, resolvedType,
658                        PackageManager.MATCH_DEFAULT_ONLY
659                                    | ActivityManagerService.STOCK_PM_FLAGS, userId);
660            aInfo = rInfo != null ? rInfo.activityInfo : null;
661        } catch (RemoteException e) {
662            aInfo = null;
663        }
664
665        if (aInfo != null) {
666            // Store the found target back into the intent, because now that
667            // we have it we never want to do this again.  For example, if the
668            // user navigates back to this point in the history, we should
669            // always restart the exact same activity.
670            intent.setComponent(new ComponentName(
671                    aInfo.applicationInfo.packageName, aInfo.name));
672
673            // Don't debug things in the system process
674            if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
675                if (!aInfo.processName.equals("system")) {
676                    mService.setDebugApp(aInfo.processName, true, false);
677                }
678            }
679
680            if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
681                if (!aInfo.processName.equals("system")) {
682                    mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
683                }
684            }
685
686            if (profileFile != null) {
687                if (!aInfo.processName.equals("system")) {
688                    mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
689                            profileFile, profileFd,
690                            (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
691                }
692            }
693        }
694        return aInfo;
695    }
696
697    void startHomeActivity(Intent intent, ActivityInfo aInfo) {
698        moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE);
699        startActivityLocked(null, intent, null, aInfo, null, null, null, null, 0, 0, 0, null, 0,
700                null, false, null, null);
701    }
702
703    final int startActivityMayWait(IApplicationThread caller, int callingUid,
704            String callingPackage, Intent intent, String resolvedType,
705            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
706            IBinder resultTo, String resultWho, int requestCode, int startFlags, String profileFile,
707            ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
708            Bundle options, int userId, IActivityContainer iContainer) {
709        // Refuse possible leaked file descriptors
710        if (intent != null && intent.hasFileDescriptors()) {
711            throw new IllegalArgumentException("File descriptors passed in Intent");
712        }
713        boolean componentSpecified = intent.getComponent() != null;
714
715        // Don't modify the client's object!
716        intent = new Intent(intent);
717
718        // Collect information about the target of the Intent.
719        ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
720                profileFile, profileFd, userId);
721
722        ActivityContainer container = (ActivityContainer)iContainer;
723        synchronized (mService) {
724            int callingPid;
725            if (callingUid >= 0) {
726                callingPid = -1;
727            } else if (caller == null) {
728                callingPid = Binder.getCallingPid();
729                callingUid = Binder.getCallingUid();
730            } else {
731                callingPid = callingUid = -1;
732            }
733
734            final ActivityStack stack;
735            if (container == null || container.mStack.isOnHomeDisplay()) {
736                stack = getFocusedStack();
737            } else {
738                stack = container.mStack;
739            }
740            stack.mConfigWillChange = config != null
741                    && mService.mConfiguration.diff(config) != 0;
742            if (DEBUG_CONFIGURATION) Slog.v(TAG,
743                    "Starting activity when config will change = " + stack.mConfigWillChange);
744
745            final long origId = Binder.clearCallingIdentity();
746
747            if (aInfo != null &&
748                    (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
749                // This may be a heavy-weight process!  Check to see if we already
750                // have another, different heavy-weight process running.
751                if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
752                    if (mService.mHeavyWeightProcess != null &&
753                            (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
754                            !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
755                        int realCallingUid = callingUid;
756                        if (caller != null) {
757                            ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
758                            if (callerApp != null) {
759                                realCallingUid = callerApp.info.uid;
760                            } else {
761                                Slog.w(TAG, "Unable to find app for caller " + caller
762                                      + " (pid=" + callingPid + ") when starting: "
763                                      + intent.toString());
764                                ActivityOptions.abort(options);
765                                return ActivityManager.START_PERMISSION_DENIED;
766                            }
767                        }
768
769                        IIntentSender target = mService.getIntentSenderLocked(
770                                ActivityManager.INTENT_SENDER_ACTIVITY, "android",
771                                realCallingUid, userId, null, null, 0, new Intent[] { intent },
772                                new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
773                                | PendingIntent.FLAG_ONE_SHOT, null);
774
775                        Intent newIntent = new Intent();
776                        if (requestCode >= 0) {
777                            // Caller is requesting a result.
778                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
779                        }
780                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
781                                new IntentSender(target));
782                        if (mService.mHeavyWeightProcess.activities.size() > 0) {
783                            ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
784                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
785                                    hist.packageName);
786                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
787                                    hist.task.taskId);
788                        }
789                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
790                                aInfo.packageName);
791                        newIntent.setFlags(intent.getFlags());
792                        newIntent.setClassName("android",
793                                HeavyWeightSwitcherActivity.class.getName());
794                        intent = newIntent;
795                        resolvedType = null;
796                        caller = null;
797                        callingUid = Binder.getCallingUid();
798                        callingPid = Binder.getCallingPid();
799                        componentSpecified = true;
800                        try {
801                            ResolveInfo rInfo =
802                                AppGlobals.getPackageManager().resolveIntent(
803                                        intent, null,
804                                        PackageManager.MATCH_DEFAULT_ONLY
805                                        | ActivityManagerService.STOCK_PM_FLAGS, userId);
806                            aInfo = rInfo != null ? rInfo.activityInfo : null;
807                            aInfo = mService.getActivityInfoForUser(aInfo, userId);
808                        } catch (RemoteException e) {
809                            aInfo = null;
810                        }
811                    }
812                }
813            }
814
815            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
816                    voiceSession, voiceInteractor, resultTo, resultWho,
817                    requestCode, callingPid, callingUid, callingPackage, startFlags, options,
818                    componentSpecified, null, container);
819
820            if (stack.mConfigWillChange) {
821                // If the caller also wants to switch to a new configuration,
822                // do so now.  This allows a clean switch, as we are waiting
823                // for the current activity to pause (so we will not destroy
824                // it), and have not yet started the next activity.
825                mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
826                        "updateConfiguration()");
827                stack.mConfigWillChange = false;
828                if (DEBUG_CONFIGURATION) Slog.v(TAG,
829                        "Updating to new configuration after starting activity.");
830                mService.updateConfigurationLocked(config, null, false, false);
831            }
832
833            Binder.restoreCallingIdentity(origId);
834
835            if (outResult != null) {
836                outResult.result = res;
837                if (res == ActivityManager.START_SUCCESS) {
838                    mWaitingActivityLaunched.add(outResult);
839                    do {
840                        try {
841                            mService.wait();
842                        } catch (InterruptedException e) {
843                        }
844                    } while (!outResult.timeout && outResult.who == null);
845                } else if (res == ActivityManager.START_TASK_TO_FRONT) {
846                    ActivityRecord r = stack.topRunningActivityLocked(null);
847                    if (r.nowVisible) {
848                        outResult.timeout = false;
849                        outResult.who = new ComponentName(r.info.packageName, r.info.name);
850                        outResult.totalTime = 0;
851                        outResult.thisTime = 0;
852                    } else {
853                        outResult.thisTime = SystemClock.uptimeMillis();
854                        mWaitingActivityVisible.add(outResult);
855                        do {
856                            try {
857                                mService.wait();
858                            } catch (InterruptedException e) {
859                            }
860                        } while (!outResult.timeout && outResult.who == null);
861                    }
862                }
863            }
864
865            return res;
866        }
867    }
868
869    final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
870            Intent[] intents, String[] resolvedTypes, IBinder resultTo,
871            Bundle options, int userId) {
872        if (intents == null) {
873            throw new NullPointerException("intents is null");
874        }
875        if (resolvedTypes == null) {
876            throw new NullPointerException("resolvedTypes is null");
877        }
878        if (intents.length != resolvedTypes.length) {
879            throw new IllegalArgumentException("intents are length different than resolvedTypes");
880        }
881
882
883        int callingPid;
884        if (callingUid >= 0) {
885            callingPid = -1;
886        } else if (caller == null) {
887            callingPid = Binder.getCallingPid();
888            callingUid = Binder.getCallingUid();
889        } else {
890            callingPid = callingUid = -1;
891        }
892        final long origId = Binder.clearCallingIdentity();
893        try {
894            synchronized (mService) {
895                ActivityRecord[] outActivity = new ActivityRecord[1];
896                for (int i=0; i<intents.length; i++) {
897                    Intent intent = intents[i];
898                    if (intent == null) {
899                        continue;
900                    }
901
902                    // Refuse possible leaked file descriptors
903                    if (intent != null && intent.hasFileDescriptors()) {
904                        throw new IllegalArgumentException("File descriptors passed in Intent");
905                    }
906
907                    boolean componentSpecified = intent.getComponent() != null;
908
909                    // Don't modify the client's object!
910                    intent = new Intent(intent);
911
912                    // Collect information about the target of the Intent.
913                    ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
914                            0, null, null, userId);
915                    // TODO: New, check if this is correct
916                    aInfo = mService.getActivityInfoForUser(aInfo, userId);
917
918                    if (aInfo != null &&
919                            (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
920                                    != 0) {
921                        throw new IllegalArgumentException(
922                                "FLAG_CANT_SAVE_STATE not supported here");
923                    }
924
925                    Bundle theseOptions;
926                    if (options != null && i == intents.length-1) {
927                        theseOptions = options;
928                    } else {
929                        theseOptions = null;
930                    }
931                    int res = startActivityLocked(caller, intent, resolvedTypes[i],
932                            aInfo, null, null, resultTo, null, -1, callingPid, callingUid, callingPackage,
933                            0, theseOptions, componentSpecified, outActivity, null);
934                    if (res < 0) {
935                        return res;
936                    }
937
938                    resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
939                }
940            }
941        } finally {
942            Binder.restoreCallingIdentity(origId);
943        }
944
945        return ActivityManager.START_SUCCESS;
946    }
947
948    final boolean realStartActivityLocked(ActivityRecord r,
949            ProcessRecord app, boolean andResume, boolean checkConfig)
950            throws RemoteException {
951
952        r.startFreezingScreenLocked(app, 0);
953        if (false) Slog.d(TAG, "realStartActivity: setting app visibility true");
954        mWindowManager.setAppVisibility(r.appToken, true);
955
956        // schedule launch ticks to collect information about slow apps.
957        r.startLaunchTickingLocked();
958
959        // Have the window manager re-evaluate the orientation of
960        // the screen based on the new activity order.  Note that
961        // as a result of this, it can call back into the activity
962        // manager with a new orientation.  We don't care about that,
963        // because the activity is not currently running so we are
964        // just restarting it anyway.
965        if (checkConfig) {
966            Configuration config = mWindowManager.updateOrientationFromAppTokens(
967                    mService.mConfiguration,
968                    r.mayFreezeScreenLocked(app) ? r.appToken : null);
969            mService.updateConfigurationLocked(config, r, false, false);
970        }
971
972        r.app = app;
973        app.waitingToKill = null;
974        r.launchCount++;
975        r.lastLaunchTime = SystemClock.uptimeMillis();
976
977        if (localLOGV) Slog.v(TAG, "Launching: " + r);
978
979        int idx = app.activities.indexOf(r);
980        if (idx < 0) {
981            app.activities.add(r);
982        }
983        mService.updateLruProcessLocked(app, true, null);
984        mService.updateOomAdjLocked();
985
986        final ActivityStack stack = r.task.stack;
987        try {
988            if (app.thread == null) {
989                throw new RemoteException();
990            }
991            List<ResultInfo> results = null;
992            List<Intent> newIntents = null;
993            if (andResume) {
994                results = r.results;
995                newIntents = r.newIntents;
996            }
997            if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
998                    + " icicle=" + r.icicle
999                    + " with results=" + results + " newIntents=" + newIntents
1000                    + " andResume=" + andResume);
1001            if (andResume) {
1002                EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
1003                        r.userId, System.identityHashCode(r),
1004                        r.task.taskId, r.shortComponentName);
1005            }
1006            if (r.isHomeActivity() && r.isNotResolverActivity()) {
1007                // Home process is the root process of the task.
1008                mService.mHomeProcess = r.task.mActivities.get(0).app;
1009            }
1010            mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
1011            r.sleeping = false;
1012            r.forceNewConfig = false;
1013            mService.showAskCompatModeDialogLocked(r);
1014            r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
1015            String profileFile = null;
1016            ParcelFileDescriptor profileFd = null;
1017            boolean profileAutoStop = false;
1018            if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
1019                if (mService.mProfileProc == null || mService.mProfileProc == app) {
1020                    mService.mProfileProc = app;
1021                    profileFile = mService.mProfileFile;
1022                    profileFd = mService.mProfileFd;
1023                    profileAutoStop = mService.mAutoStopProfiler;
1024                }
1025            }
1026            app.hasShownUi = true;
1027            app.pendingUiClean = true;
1028            if (profileFd != null) {
1029                try {
1030                    profileFd = profileFd.dup();
1031                } catch (IOException e) {
1032                    if (profileFd != null) {
1033                        try {
1034                            profileFd.close();
1035                        } catch (IOException o) {
1036                        }
1037                        profileFd = null;
1038                    }
1039                }
1040            }
1041
1042            app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
1043            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
1044                    System.identityHashCode(r), r.info,
1045                    new Configuration(mService.mConfiguration), r.compat, r.task.voiceInteractor,
1046                    app.repProcState, r.icicle, r.persistentState, results, newIntents, !andResume,
1047                    mService.isNextTransitionForward(), profileFile, profileFd, profileAutoStop
1048            );
1049
1050            if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
1051                // This may be a heavy-weight process!  Note that the package
1052                // manager will ensure that only activity can run in the main
1053                // process of the .apk, which is the only thing that will be
1054                // considered heavy-weight.
1055                if (app.processName.equals(app.info.packageName)) {
1056                    if (mService.mHeavyWeightProcess != null
1057                            && mService.mHeavyWeightProcess != app) {
1058                        Slog.w(TAG, "Starting new heavy weight process " + app
1059                                + " when already running "
1060                                + mService.mHeavyWeightProcess);
1061                    }
1062                    mService.mHeavyWeightProcess = app;
1063                    Message msg = mService.mHandler.obtainMessage(
1064                            ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
1065                    msg.obj = r;
1066                    mService.mHandler.sendMessage(msg);
1067                }
1068            }
1069
1070        } catch (RemoteException e) {
1071            if (r.launchFailed) {
1072                // This is the second time we failed -- finish activity
1073                // and give up.
1074                Slog.e(TAG, "Second failure launching "
1075                      + r.intent.getComponent().flattenToShortString()
1076                      + ", giving up", e);
1077                mService.appDiedLocked(app, app.pid, app.thread);
1078                stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
1079                        "2nd-crash", false);
1080                return false;
1081            }
1082
1083            // This is the first time we failed -- restart process and
1084            // retry.
1085            app.activities.remove(r);
1086            throw e;
1087        }
1088
1089        r.launchFailed = false;
1090        if (stack.updateLRUListLocked(r)) {
1091            Slog.w(TAG, "Activity " + r
1092                  + " being launched, but already in LRU list");
1093        }
1094
1095        if (andResume) {
1096            // As part of the process of launching, ActivityThread also performs
1097            // a resume.
1098            stack.minimalResumeActivityLocked(r);
1099        } else {
1100            // This activity is not starting in the resumed state... which
1101            // should look like we asked it to pause+stop (but remain visible),
1102            // and it has done so and reported back the current icicle and
1103            // other state.
1104            if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
1105                    + " (starting in stopped state)");
1106            r.state = ActivityState.STOPPED;
1107            r.stopped = true;
1108        }
1109
1110        // Launch the new version setup screen if needed.  We do this -after-
1111        // launching the initial activity (that is, home), so that it can have
1112        // a chance to initialize itself while in the background, making the
1113        // switch back to it faster and look better.
1114        if (isFrontStack(stack)) {
1115            mService.startSetupActivityLocked();
1116        }
1117
1118        return true;
1119    }
1120
1121    void startSpecificActivityLocked(ActivityRecord r,
1122            boolean andResume, boolean checkConfig) {
1123        // Is this activity's application already running?
1124        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
1125                r.info.applicationInfo.uid, true);
1126
1127        r.task.stack.setLaunchTime(r);
1128
1129        if (app != null && app.thread != null) {
1130            try {
1131                if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
1132                        || !"android".equals(r.info.packageName)) {
1133                    // Don't add this if it is a platform component that is marked
1134                    // to run in multiple processes, because this is actually
1135                    // part of the framework so doesn't make sense to track as a
1136                    // separate apk in the process.
1137                    app.addPackage(r.info.packageName, mService.mProcessStats);
1138                }
1139                realStartActivityLocked(r, app, andResume, checkConfig);
1140                return;
1141            } catch (RemoteException e) {
1142                Slog.w(TAG, "Exception when starting activity "
1143                        + r.intent.getComponent().flattenToShortString(), e);
1144            }
1145
1146            // If a dead object exception was thrown -- fall through to
1147            // restart the application.
1148        }
1149
1150        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
1151                "activity", r.intent.getComponent(), false, false, true);
1152    }
1153
1154    final int startActivityLocked(IApplicationThread caller,
1155            Intent intent, String resolvedType, ActivityInfo aInfo,
1156            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
1157            IBinder resultTo, String resultWho, int requestCode,
1158            int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
1159            boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container) {
1160        int err = ActivityManager.START_SUCCESS;
1161
1162        ProcessRecord callerApp = null;
1163        if (caller != null) {
1164            callerApp = mService.getRecordForAppLocked(caller);
1165            if (callerApp != null) {
1166                callingPid = callerApp.pid;
1167                callingUid = callerApp.info.uid;
1168            } else {
1169                Slog.w(TAG, "Unable to find app for caller " + caller
1170                      + " (pid=" + callingPid + ") when starting: "
1171                      + intent.toString());
1172                err = ActivityManager.START_PERMISSION_DENIED;
1173            }
1174        }
1175
1176        if (err == ActivityManager.START_SUCCESS) {
1177            final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
1178            Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
1179                    + "} from pid " + (callerApp != null ? callerApp.pid : callingPid)
1180                    + " on display " + (container == null ? (mFocusedStack == null ?
1181                            Display.DEFAULT_DISPLAY : mFocusedStack.mDisplayId) :
1182                            (container.mActivityDisplay == null ? Display.DEFAULT_DISPLAY :
1183                                    container.mActivityDisplay.mDisplayId)));
1184        }
1185
1186        ActivityRecord sourceRecord = null;
1187        ActivityRecord resultRecord = null;
1188        if (resultTo != null) {
1189            sourceRecord = isInAnyStackLocked(resultTo);
1190            if (DEBUG_RESULTS) Slog.v(
1191                TAG, "Will send result to " + resultTo + " " + sourceRecord);
1192            if (sourceRecord != null) {
1193                if (requestCode >= 0 && !sourceRecord.finishing) {
1194                    resultRecord = sourceRecord;
1195                }
1196            }
1197        }
1198        ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
1199
1200        final int launchFlags = intent.getFlags();
1201
1202        if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
1203                && sourceRecord != null) {
1204            // Transfer the result target from the source activity to the new
1205            // one being started, including any failures.
1206            if (requestCode >= 0) {
1207                ActivityOptions.abort(options);
1208                return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
1209            }
1210            resultRecord = sourceRecord.resultTo;
1211            resultWho = sourceRecord.resultWho;
1212            requestCode = sourceRecord.requestCode;
1213            sourceRecord.resultTo = null;
1214            if (resultRecord != null) {
1215                resultRecord.removeResultsLocked(
1216                    sourceRecord, resultWho, requestCode);
1217            }
1218            if (sourceRecord.launchedFromUid == callingUid) {
1219                // The new activity is being launched from the same uid as the previous
1220                // activity in the flow, and asking to forward its result back to the
1221                // previous.  In this case the activity is serving as a trampoline between
1222                // the two, so we also want to update its launchedFromPackage to be the
1223                // same as the previous activity.  Note that this is safe, since we know
1224                // these two packages come from the same uid; the caller could just as
1225                // well have supplied that same package name itself.  This specifially
1226                // deals with the case of an intent picker/chooser being launched in the app
1227                // flow to redirect to an activity picked by the user, where we want the final
1228                // activity to consider it to have been launched by the previous app activity.
1229                callingPackage = sourceRecord.launchedFromPackage;
1230            }
1231        }
1232
1233        if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
1234            // We couldn't find a class that can handle the given Intent.
1235            // That's the end of that!
1236            err = ActivityManager.START_INTENT_NOT_RESOLVED;
1237        }
1238
1239        if (err == ActivityManager.START_SUCCESS && aInfo == null) {
1240            // We couldn't find the specific class specified in the Intent.
1241            // Also the end of the line.
1242            err = ActivityManager.START_CLASS_NOT_FOUND;
1243        }
1244
1245        if (err == ActivityManager.START_SUCCESS && sourceRecord != null
1246                && sourceRecord.task.voiceSession != null) {
1247            // If this activity is being launched as part of a voice session, we need
1248            // to ensure that it is safe to do so.  If the upcoming activity will also
1249            // be part of the voice session, we can only launch it if it has explicitly
1250            // said it supports the VOICE category, or it is a part of the calling app.
1251            if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0
1252                    && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
1253                try {
1254                    if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
1255                            intent, resolvedType)) {
1256                        err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
1257                    }
1258                } catch (RemoteException e) {
1259                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
1260                }
1261            }
1262        }
1263
1264        if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
1265            // If the caller is starting a new voice session, just make sure the target
1266            // is actually allowing it to run this way.
1267            try {
1268                if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
1269                        intent, resolvedType)) {
1270                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
1271                }
1272            } catch (RemoteException e) {
1273                err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
1274            }
1275        }
1276
1277        if (err != ActivityManager.START_SUCCESS) {
1278            if (resultRecord != null) {
1279                resultStack.sendActivityResultLocked(-1,
1280                    resultRecord, resultWho, requestCode,
1281                    Activity.RESULT_CANCELED, null);
1282            }
1283            setDismissKeyguard(false);
1284            ActivityOptions.abort(options);
1285            return err;
1286        }
1287
1288        final int startAnyPerm = mService.checkPermission(
1289                START_ANY_ACTIVITY, callingPid, callingUid);
1290        final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
1291                callingUid, aInfo.applicationInfo.uid, aInfo.exported);
1292        if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
1293            if (resultRecord != null) {
1294                resultStack.sendActivityResultLocked(-1,
1295                    resultRecord, resultWho, requestCode,
1296                    Activity.RESULT_CANCELED, null);
1297            }
1298            setDismissKeyguard(false);
1299            String msg;
1300            if (!aInfo.exported) {
1301                msg = "Permission Denial: starting " + intent.toString()
1302                        + " from " + callerApp + " (pid=" + callingPid
1303                        + ", uid=" + callingUid + ")"
1304                        + " not exported from uid " + aInfo.applicationInfo.uid;
1305            } else {
1306                msg = "Permission Denial: starting " + intent.toString()
1307                        + " from " + callerApp + " (pid=" + callingPid
1308                        + ", uid=" + callingUid + ")"
1309                        + " requires " + aInfo.permission;
1310            }
1311            Slog.w(TAG, msg);
1312            throw new SecurityException(msg);
1313        }
1314
1315        boolean abort = !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
1316                callingPid, resolvedType, aInfo.applicationInfo);
1317
1318        if (mService.mController != null) {
1319            try {
1320                // The Intent we give to the watcher has the extra data
1321                // stripped off, since it can contain private information.
1322                Intent watchIntent = intent.cloneFilter();
1323                abort |= !mService.mController.activityStarting(watchIntent,
1324                        aInfo.applicationInfo.packageName);
1325            } catch (RemoteException e) {
1326                mService.mController = null;
1327            }
1328        }
1329
1330        if (abort) {
1331            if (resultRecord != null) {
1332                resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
1333                        Activity.RESULT_CANCELED, null);
1334            }
1335            // We pretend to the caller that it was really started, but
1336            // they will just get a cancel result.
1337            setDismissKeyguard(false);
1338            ActivityOptions.abort(options);
1339            return ActivityManager.START_SUCCESS;
1340        }
1341
1342        ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1343                intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho,
1344                requestCode, componentSpecified, this, container, options);
1345        if (outActivity != null) {
1346            outActivity[0] = r;
1347        }
1348
1349        final ActivityStack stack = getFocusedStack();
1350        if (voiceSession == null && (stack.mResumedActivity == null
1351                || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
1352            if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1353                PendingActivityLaunch pal =
1354                        new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
1355                mService.mPendingActivityLaunches.add(pal);
1356                setDismissKeyguard(false);
1357                ActivityOptions.abort(options);
1358                return ActivityManager.START_SWITCHES_CANCELED;
1359            }
1360        }
1361
1362        if (mService.mDidAppSwitch) {
1363            // This is the second allowed switch since we stopped switches,
1364            // so now just generally allow switches.  Use case: user presses
1365            // home (switches disabled, switch to home, mDidAppSwitch now true);
1366            // user taps a home icon (coming from home so allowed, we hit here
1367            // and now allow anyone to switch again).
1368            mService.mAppSwitchesAllowedTime = 0;
1369        } else {
1370            mService.mDidAppSwitch = true;
1371        }
1372
1373        mService.doPendingActivityLaunchesLocked(false);
1374
1375        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
1376                startFlags, true, options);
1377
1378        if (allPausedActivitiesComplete()) {
1379            // If someone asked to have the keyguard dismissed on the next
1380            // activity start, but we are not actually doing an activity
1381            // switch...  just dismiss the keyguard now, because we
1382            // probably want to see whatever is behind it.
1383            dismissKeyguard();
1384        }
1385        return err;
1386    }
1387
1388    ActivityStack adjustStackFocus(ActivityRecord r) {
1389        final TaskRecord task = r.task;
1390        if (r.isApplicationActivity() || (task != null && task.isApplicationTask())) {
1391            if (task != null) {
1392                final ActivityStack taskStack = task.stack;
1393                if (taskStack.isOnHomeDisplay()) {
1394                    if (mFocusedStack != taskStack) {
1395                        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: Setting " +
1396                                "focused stack to r=" + r + " task=" + task);
1397                        mFocusedStack = taskStack;
1398                    } else {
1399                        if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1400                            "adjustStackFocus: Focused stack already=" + mFocusedStack);
1401                    }
1402                }
1403                return taskStack;
1404            }
1405
1406            final ActivityContainer container = r.mInitialActivityContainer;
1407            if (container != null) {
1408                // The first time put it on the desired stack, after this put on task stack.
1409                r.mInitialActivityContainer = null;
1410                return container.mStack;
1411            }
1412
1413            if (mFocusedStack != mHomeStack) {
1414                if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1415                        "adjustStackFocus: Have a focused stack=" + mFocusedStack);
1416                return mFocusedStack;
1417            }
1418
1419            final ArrayList<ActivityStack> homeDisplayStacks = mHomeStack.mStacks;
1420            for (int stackNdx = homeDisplayStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1421                final ActivityStack stack = homeDisplayStacks.get(stackNdx);
1422                if (!stack.isHomeStack()) {
1423                    if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG,
1424                            "adjustStackFocus: Setting focused stack=" + stack);
1425                    mFocusedStack = stack;
1426                    return mFocusedStack;
1427                }
1428            }
1429
1430            // Need to create an app stack for this user.
1431            int stackId = createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY);
1432            if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r +
1433                    " stackId=" + stackId);
1434            mFocusedStack = getStack(stackId);
1435            return mFocusedStack;
1436        }
1437        return mHomeStack;
1438    }
1439
1440    void setFocusedStack(ActivityRecord r) {
1441        if (r != null) {
1442            final TaskRecord task = r.task;
1443            boolean isHomeActivity = !r.isApplicationActivity();
1444            if (!isHomeActivity && task != null) {
1445                isHomeActivity = !task.isApplicationTask();
1446            }
1447            if (!isHomeActivity && task != null) {
1448                final ActivityRecord parent = task.stack.mActivityContainer.mParentActivity;
1449                isHomeActivity = parent != null && parent.isHomeActivity();
1450            }
1451            moveHomeStack(isHomeActivity);
1452        }
1453    }
1454
1455    final int startActivityUncheckedLocked(ActivityRecord r,
1456            ActivityRecord sourceRecord,
1457            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
1458            boolean doResume, Bundle options) {
1459        final Intent intent = r.intent;
1460        final int callingUid = r.launchedFromUid;
1461
1462        int launchFlags = intent.getFlags();
1463
1464        // We'll invoke onUserLeaving before onPause only if the launching
1465        // activity did not explicitly state that this is an automated launch.
1466        mUserLeaving = (launchFlags & Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1467        if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
1468
1469        // If the caller has asked not to resume at this point, we make note
1470        // of this in the record so that we can skip it when trying to find
1471        // the top running activity.
1472        if (!doResume) {
1473            r.delayedResume = true;
1474        }
1475
1476        ActivityRecord notTop =
1477                (launchFlags & Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1478
1479        // If the onlyIfNeeded flag is set, then we can do this if the activity
1480        // being launched is the same as the one making the call...  or, as
1481        // a special case, if we do not know the caller then we count the
1482        // current top activity as the caller.
1483        if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1484            ActivityRecord checkedCaller = sourceRecord;
1485            if (checkedCaller == null) {
1486                checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
1487            }
1488            if (!checkedCaller.realActivity.equals(r.realActivity)) {
1489                // Caller is not the same as launcher, so always needed.
1490                startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1491            }
1492        }
1493
1494        switch (r.info.documentLaunchMode) {
1495            case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1496                break;
1497            case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1498                intent.addFlags(
1499                        Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
1500                launchFlags = intent.getFlags();
1501                break;
1502            case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1503                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
1504                launchFlags = intent.getFlags();
1505                break;
1506        }
1507        final boolean newDocument = intent.isDocument();
1508        if (sourceRecord == null) {
1509            // This activity is not being started from another...  in this
1510            // case we -always- start a new task.
1511            if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
1512                Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1513                        "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
1514                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1515            }
1516        } else if (newDocument) {
1517            if (r.launchMode != ActivityInfo.LAUNCH_MULTIPLE) {
1518                Slog.w(TAG, "FLAG_ACTIVITY_NEW_DOCUMENT and launchMode != \"standard\"");
1519                r.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
1520            }
1521        } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1522            // The original activity who is starting us is running as a single
1523            // instance...  this new activity it is starting must go on its
1524            // own task.
1525            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1526        } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1527                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1528            // The activity being started is a single instance...  it always
1529            // gets launched into its own task.
1530            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1531        }
1532
1533        ActivityInfo newTaskInfo = null;
1534        Intent newTaskIntent = null;
1535        final ActivityStack sourceStack;
1536        if (sourceRecord != null) {
1537            if (sourceRecord.finishing) {
1538                // If the source is finishing, we can't further count it as our source.  This
1539                // is because the task it is associated with may now be empty and on its way out,
1540                // so we don't want to blindly throw it in to that task.  Instead we will take
1541                // the NEW_TASK flow and try to find a task for it. But save the task information
1542                // so it can be used when creating the new task.
1543                if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
1544                    Slog.w(TAG, "startActivity called from finishing " + sourceRecord
1545                            + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
1546                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1547                    newTaskInfo = sourceRecord.info;
1548                    newTaskIntent = sourceRecord.task.intent;
1549                }
1550                sourceRecord = null;
1551                sourceStack = null;
1552            } else {
1553                sourceStack = sourceRecord.task.stack;
1554            }
1555        } else {
1556            sourceStack = null;
1557        }
1558
1559        if (r.resultTo != null && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1560            // For whatever reason this activity is being launched into a new
1561            // task...  yet the caller has requested a result back.  Well, that
1562            // is pretty messed up, so instead immediately send back a cancel
1563            // and let the new task continue launched as normal without a
1564            // dependency on its originator.
1565            Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1566            r.resultTo.task.stack.sendActivityResultLocked(-1,
1567                    r.resultTo, r.resultWho, r.requestCode,
1568                Activity.RESULT_CANCELED, null);
1569            r.resultTo = null;
1570        }
1571
1572        boolean addingToTask = false;
1573        boolean movedHome = false;
1574        TaskRecord reuseTask = null;
1575        ActivityStack targetStack;
1576        if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1577                (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1578                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1579                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1580            // If bring to front is requested, and no result is requested, and
1581            // we can find a task that was started with this same
1582            // component, then instead of launching bring that one to the front.
1583            if (r.resultTo == null) {
1584                // See if there is a task to bring to the front.  If this is
1585                // a SINGLE_INSTANCE activity, there can be one and only one
1586                // instance of it in the history, and it is always in its own
1587                // unique task, so we do a special search.
1588                ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1589                        ? findTaskLocked(r)
1590                        : findActivityLocked(intent, r.info);
1591                if (intentActivity != null) {
1592                    if (isLockTaskModeViolation(intentActivity.task)) {
1593                        Slog.e(TAG, "moveTaskToFront: Attempt to violate Lock Task Mode");
1594                        return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
1595                    }
1596                    if (r.task == null) {
1597                        r.task = intentActivity.task;
1598                    }
1599                    targetStack = intentActivity.task.stack;
1600                    targetStack.mLastPausedActivity = null;
1601                    if (DEBUG_TASKS) Slog.d(TAG, "Bring to front target: " + targetStack
1602                            + " from " + intentActivity);
1603                    targetStack.moveToFront();
1604                    if (intentActivity.task.intent == null) {
1605                        // This task was started because of movement of
1606                        // the activity based on affinity...  now that we
1607                        // are actually launching it, we can assign the
1608                        // base intent.
1609                        intentActivity.task.setIntent(intent, r.info);
1610                    }
1611                    // If the target task is not in the front, then we need
1612                    // to bring it to the front...  except...  well, with
1613                    // SINGLE_TASK_LAUNCH it's not entirely clear.  We'd like
1614                    // to have the same behavior as if a new instance was
1615                    // being started, which means not bringing it to the front
1616                    // if the caller is not itself in the front.
1617                    final ActivityStack lastStack = getLastStack();
1618                    ActivityRecord curTop = lastStack == null?
1619                            null : lastStack.topRunningNonDelayedActivityLocked(notTop);
1620                    if (curTop != null && (curTop.task != intentActivity.task ||
1621                            curTop.task != lastStack.topTask())) {
1622                        r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1623                        if (sourceRecord == null || (sourceStack.topActivity() != null &&
1624                                sourceStack.topActivity().task == sourceRecord.task)) {
1625                            // We really do want to push this one into the
1626                            // user's face, right now.
1627                            movedHome = true;
1628                            targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1629                            if ((launchFlags &
1630                                    (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1631                                    == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1632                                // Caller wants to appear on home activity.
1633                                intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1634                            }
1635                            options = null;
1636                        }
1637                    }
1638                    // If the caller has requested that the target task be
1639                    // reset, then do so.
1640                    if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1641                        intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1642                    }
1643                    if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1644                        // We don't need to start a new activity, and
1645                        // the client said not to do anything if that
1646                        // is the case, so this is it!  And for paranoia, make
1647                        // sure we have correctly resumed the top activity.
1648                        if (doResume) {
1649                            resumeTopActivitiesLocked(targetStack, null, options);
1650                        } else {
1651                            ActivityOptions.abort(options);
1652                        }
1653                        return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1654                    }
1655                    if ((launchFlags &
1656                            (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1657                            == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1658                        // The caller has requested to completely replace any
1659                        // existing task with its new activity.  Well that should
1660                        // not be too hard...
1661                        reuseTask = intentActivity.task;
1662                        reuseTask.performClearTaskLocked();
1663                        reuseTask.setIntent(r.intent, r.info);
1664                    } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1665                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1666                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1667                        // In this situation we want to remove all activities
1668                        // from the task up to the one being started.  In most
1669                        // cases this means we are resetting the task to its
1670                        // initial state.
1671                        ActivityRecord top =
1672                                intentActivity.task.performClearTaskLocked(r, launchFlags);
1673                        if (top != null) {
1674                            if (top.frontOfTask) {
1675                                // Activity aliases may mean we use different
1676                                // intents for the top activity, so make sure
1677                                // the task now has the identity of the new
1678                                // intent.
1679                                top.task.setIntent(r.intent, r.info);
1680                            }
1681                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1682                                    r, top.task);
1683                            top.deliverNewIntentLocked(callingUid, r.intent);
1684                        } else {
1685                            // A special case: we need to
1686                            // start the activity because it is not currently
1687                            // running, and the caller has asked to clear the
1688                            // current task to have this activity at the top.
1689                            addingToTask = true;
1690                            // Now pretend like this activity is being started
1691                            // by the top of its task, so it is put in the
1692                            // right place.
1693                            sourceRecord = intentActivity;
1694                        }
1695                    } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1696                        // In this case the top activity on the task is the
1697                        // same as the one being launched, so we take that
1698                        // as a request to bring the task to the foreground.
1699                        // If the top activity in the task is the root
1700                        // activity, deliver this new intent to it if it
1701                        // desires.
1702                        if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1703                                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1704                                && intentActivity.realActivity.equals(r.realActivity)) {
1705                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1706                                    intentActivity.task);
1707                            if (intentActivity.frontOfTask) {
1708                                intentActivity.task.setIntent(r.intent, r.info);
1709                            }
1710                            intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1711                        } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1712                            // In this case we are launching the root activity
1713                            // of the task, but with a different intent.  We
1714                            // should start a new instance on top.
1715                            addingToTask = true;
1716                            sourceRecord = intentActivity;
1717                        }
1718                    } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1719                        // In this case an activity is being launched in to an
1720                        // existing task, without resetting that task.  This
1721                        // is typically the situation of launching an activity
1722                        // from a notification or shortcut.  We want to place
1723                        // the new activity on top of the current task.
1724                        addingToTask = true;
1725                        sourceRecord = intentActivity;
1726                    } else if (!intentActivity.task.rootWasReset) {
1727                        // In this case we are launching in to an existing task
1728                        // that has not yet been started from its front door.
1729                        // The current task has been brought to the front.
1730                        // Ideally, we'd probably like to place this new task
1731                        // at the bottom of its stack, but that's a little hard
1732                        // to do with the current organization of the code so
1733                        // for now we'll just drop it.
1734                        intentActivity.task.setIntent(r.intent, r.info);
1735                    }
1736                    if (!addingToTask && reuseTask == null) {
1737                        // We didn't do anything...  but it was needed (a.k.a., client
1738                        // don't use that intent!)  And for paranoia, make
1739                        // sure we have correctly resumed the top activity.
1740                        if (doResume) {
1741                            targetStack.resumeTopActivityLocked(null, options);
1742                        } else {
1743                            ActivityOptions.abort(options);
1744                        }
1745                        return ActivityManager.START_TASK_TO_FRONT;
1746                    }
1747                }
1748            }
1749        }
1750
1751        //String uri = r.intent.toURI();
1752        //Intent intent2 = new Intent(uri);
1753        //Slog.i(TAG, "Given intent: " + r.intent);
1754        //Slog.i(TAG, "URI is: " + uri);
1755        //Slog.i(TAG, "To intent: " + intent2);
1756
1757        if (r.packageName != null) {
1758            // If the activity being launched is the same as the one currently
1759            // at the top, then we need to check if it should only be launched
1760            // once.
1761            ActivityStack topStack = getFocusedStack();
1762            ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
1763            if (top != null && r.resultTo == null) {
1764                if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1765                    if (top.app != null && top.app.thread != null) {
1766                        if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1767                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1768                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1769                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1770                                    top.task);
1771                            // For paranoia, make sure we have correctly
1772                            // resumed the top activity.
1773                            topStack.mLastPausedActivity = null;
1774                            if (doResume) {
1775                                resumeTopActivitiesLocked();
1776                            }
1777                            ActivityOptions.abort(options);
1778                            if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1779                                // We don't need to start a new activity, and
1780                                // the client said not to do anything if that
1781                                // is the case, so this is it!
1782                                return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1783                            }
1784                            top.deliverNewIntentLocked(callingUid, r.intent);
1785                            return ActivityManager.START_DELIVERED_TO_TOP;
1786                        }
1787                    }
1788                }
1789            }
1790
1791        } else {
1792            if (r.resultTo != null) {
1793                r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1794                        r.requestCode, Activity.RESULT_CANCELED, null);
1795            }
1796            ActivityOptions.abort(options);
1797            return ActivityManager.START_CLASS_NOT_FOUND;
1798        }
1799
1800        boolean newTask = false;
1801        boolean keepCurTransition = false;
1802
1803        // Should this be considered a new task?
1804        if (r.resultTo == null && !addingToTask
1805                && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1806            if (isLockTaskModeViolation(reuseTask)) {
1807                Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
1808                return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
1809            }
1810            targetStack = adjustStackFocus(r);
1811            targetStack.moveToFront();
1812            if (reuseTask == null) {
1813                r.setTask(targetStack.createTaskRecord(getNextTaskId(),
1814                        newTaskInfo != null ? newTaskInfo : r.info,
1815                        newTaskIntent != null ? newTaskIntent : intent,
1816                        voiceSession, voiceInteractor, true), null, true);
1817                if (sourceRecord == null) {
1818                    // Launched from a service or notification or task that is finishing.
1819                    r.task.setTaskToReturnTo(isFrontStack(mHomeStack) ?
1820                            mHomeStack.topTask().taskType : RECENTS_ACTIVITY_TYPE);
1821                }
1822                if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1823                        r.task);
1824            } else {
1825                r.setTask(reuseTask, reuseTask, true);
1826            }
1827            newTask = true;
1828            if (!movedHome) {
1829                if ((launchFlags &
1830                        (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1831                        == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1832                    // Caller wants to appear on home activity, so before starting
1833                    // their own activity we will bring home to the front.
1834                    r.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1835                }
1836            }
1837        } else if (sourceRecord != null) {
1838            TaskRecord sourceTask = sourceRecord.task;
1839            if (isLockTaskModeViolation(sourceTask)) {
1840                Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
1841                return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
1842            }
1843            targetStack = sourceTask.stack;
1844            targetStack.moveToFront();
1845            mWindowManager.moveTaskToTop(targetStack.topTask().taskId);
1846            if (!addingToTask &&
1847                    (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1848                // In this case, we are adding the activity to an existing
1849                // task, but the caller has asked to clear that task if the
1850                // activity is already running.
1851                ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
1852                keepCurTransition = true;
1853                if (top != null) {
1854                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1855                    top.deliverNewIntentLocked(callingUid, r.intent);
1856                    // For paranoia, make sure we have correctly
1857                    // resumed the top activity.
1858                    targetStack.mLastPausedActivity = null;
1859                    if (doResume) {
1860                        targetStack.resumeTopActivityLocked(null);
1861                    }
1862                    ActivityOptions.abort(options);
1863                    return ActivityManager.START_DELIVERED_TO_TOP;
1864                }
1865            } else if (!addingToTask &&
1866                    (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1867                // In this case, we are launching an activity in our own task
1868                // that may already be running somewhere in the history, and
1869                // we want to shuffle it to the front of the stack if so.
1870                final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
1871                if (top != null) {
1872                    final TaskRecord task = top.task;
1873                    task.moveActivityToFrontLocked(top);
1874                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
1875                    top.updateOptionsLocked(options);
1876                    top.deliverNewIntentLocked(callingUid, r.intent);
1877                    targetStack.mLastPausedActivity = null;
1878                    if (doResume) {
1879                        targetStack.resumeTopActivityLocked(null);
1880                    }
1881                    return ActivityManager.START_DELIVERED_TO_TOP;
1882                }
1883            }
1884            // An existing activity is starting this new activity, so we want
1885            // to keep the new one in the same task as the one that is starting
1886            // it.
1887            r.setTask(sourceTask, sourceRecord.thumbHolder, false);
1888            if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1889                    + " in existing task " + r.task + " from source " + sourceRecord);
1890
1891        } else {
1892            // This not being started from an existing activity, and not part
1893            // of a new task...  just put it in the top task, though these days
1894            // this case should never happen.
1895            targetStack = adjustStackFocus(r);
1896            targetStack.moveToFront();
1897            ActivityRecord prev = targetStack.topActivity();
1898            r.setTask(prev != null ? prev.task
1899                    : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, null, null, true),
1900                    null, true);
1901            mWindowManager.moveTaskToTop(r.task.taskId);
1902            if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1903                    + " in new guessed " + r.task);
1904        }
1905
1906        mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1907                intent, r.getUriPermissionsLocked());
1908
1909        if (newTask) {
1910            EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1911        }
1912        ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
1913        targetStack.mLastPausedActivity = null;
1914        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
1915        mService.setFocusedActivityLocked(r);
1916        return ActivityManager.START_SUCCESS;
1917    }
1918
1919    void acquireLaunchWakelock() {
1920        if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
1921            throw new IllegalStateException("Calling must be system uid");
1922        }
1923        mLaunchingActivity.acquire();
1924        if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
1925            // To be safe, don't allow the wake lock to be held for too long.
1926            mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
1927        }
1928    }
1929
1930    // Checked.
1931    final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1932            Configuration config) {
1933        if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1934
1935        ArrayList<ActivityRecord> stops = null;
1936        ArrayList<ActivityRecord> finishes = null;
1937        ArrayList<UserStartedState> startingUsers = null;
1938        int NS = 0;
1939        int NF = 0;
1940        boolean booting = false;
1941        boolean enableScreen = false;
1942        boolean activityRemoved = false;
1943
1944        ActivityRecord r = ActivityRecord.forToken(token);
1945        if (r != null) {
1946            if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" +
1947                    Debug.getCallers(4));
1948            mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1949            r.finishLaunchTickingLocked();
1950            if (fromTimeout) {
1951                reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
1952            }
1953
1954            // This is a hack to semi-deal with a race condition
1955            // in the client where it can be constructed with a
1956            // newer configuration from when we asked it to launch.
1957            // We'll update with whatever configuration it now says
1958            // it used to launch.
1959            if (config != null) {
1960                r.configuration = config;
1961            }
1962
1963            // We are now idle.  If someone is waiting for a thumbnail from
1964            // us, we can now deliver.
1965            r.idle = true;
1966
1967            //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1968            if (!mService.mBooted && isFrontStack(r.task.stack)) {
1969                mService.mBooted = true;
1970                enableScreen = true;
1971            }
1972        }
1973
1974        if (allResumedActivitiesIdle()) {
1975            if (r != null) {
1976                mService.scheduleAppGcsLocked();
1977            }
1978
1979            if (mLaunchingActivity.isHeld()) {
1980                mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
1981                if (VALIDATE_WAKE_LOCK_CALLER &&
1982                        Binder.getCallingUid() != Process.myUid()) {
1983                    throw new IllegalStateException("Calling must be system uid");
1984                }
1985                mLaunchingActivity.release();
1986            }
1987            ensureActivitiesVisibleLocked(null, 0);
1988        }
1989
1990        // Atomically retrieve all of the other things to do.
1991        stops = processStoppingActivitiesLocked(true);
1992        NS = stops != null ? stops.size() : 0;
1993        if ((NF=mFinishingActivities.size()) > 0) {
1994            finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1995            mFinishingActivities.clear();
1996        }
1997
1998        if (isFrontStack(mHomeStack)) {
1999            booting = mService.mBooting;
2000            mService.mBooting = false;
2001        }
2002
2003        if (mStartingUsers.size() > 0) {
2004            startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
2005            mStartingUsers.clear();
2006        }
2007
2008        // Stop any activities that are scheduled to do so but have been
2009        // waiting for the next one to start.
2010        for (int i = 0; i < NS; i++) {
2011            r = stops.get(i);
2012            final ActivityStack stack = r.task.stack;
2013            if (r.finishing) {
2014                stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
2015            } else {
2016                stack.stopActivityLocked(r);
2017            }
2018        }
2019
2020        // Finish any activities that are scheduled to do so but have been
2021        // waiting for the next one to start.
2022        for (int i = 0; i < NF; i++) {
2023            r = finishes.get(i);
2024            activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
2025        }
2026
2027        if (booting) {
2028            mService.finishBooting();
2029        } else {
2030            // Complete user switch
2031            if (startingUsers != null) {
2032                for (int i = 0; i < startingUsers.size(); i++) {
2033                    mService.finishUserSwitch(startingUsers.get(i));
2034                }
2035            }
2036            // Complete starting up of background users
2037            if (mStartingBackgroundUsers.size() > 0) {
2038                startingUsers = new ArrayList<UserStartedState>(mStartingBackgroundUsers);
2039                mStartingBackgroundUsers.clear();
2040                for (int i = 0; i < startingUsers.size(); i++) {
2041                    mService.finishUserBoot(startingUsers.get(i));
2042                }
2043            }
2044        }
2045
2046        mService.trimApplications();
2047        //dump();
2048        //mWindowManager.dump();
2049
2050        if (enableScreen) {
2051            mService.enableScreenAfterBoot();
2052        }
2053
2054        if (activityRemoved) {
2055            resumeTopActivitiesLocked();
2056        }
2057
2058        return r;
2059    }
2060
2061    boolean handleAppDiedLocked(ProcessRecord app) {
2062        boolean hasVisibleActivities = false;
2063        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2064            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2065            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2066                hasVisibleActivities |= stacks.get(stackNdx).handleAppDiedLocked(app);
2067            }
2068        }
2069        return hasVisibleActivities;
2070    }
2071
2072    void closeSystemDialogsLocked() {
2073        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2074            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2075            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2076                stacks.get(stackNdx).closeSystemDialogsLocked();
2077            }
2078        }
2079    }
2080
2081    void removeUserLocked(int userId) {
2082        mUserStackInFront.delete(userId);
2083    }
2084
2085    /**
2086     * @return true if some activity was finished (or would have finished if doit were true).
2087     */
2088    boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
2089        boolean didSomething = false;
2090        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2091            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2092            final int numStacks = stacks.size();
2093            for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2094                final ActivityStack stack = stacks.get(stackNdx);
2095                if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
2096                    didSomething = true;
2097                }
2098            }
2099        }
2100        return didSomething;
2101    }
2102
2103    void updatePreviousProcessLocked(ActivityRecord r) {
2104        // Now that this process has stopped, we may want to consider
2105        // it to be the previous app to try to keep around in case
2106        // the user wants to return to it.
2107
2108        // First, found out what is currently the foreground app, so that
2109        // we don't blow away the previous app if this activity is being
2110        // hosted by the process that is actually still the foreground.
2111        ProcessRecord fgApp = null;
2112        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2113            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2114            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2115                final ActivityStack stack = stacks.get(stackNdx);
2116                if (isFrontStack(stack)) {
2117                    if (stack.mResumedActivity != null) {
2118                        fgApp = stack.mResumedActivity.app;
2119                    } else if (stack.mPausingActivity != null) {
2120                        fgApp = stack.mPausingActivity.app;
2121                    }
2122                    break;
2123                }
2124            }
2125        }
2126
2127        // Now set this one as the previous process, only if that really
2128        // makes sense to.
2129        if (r.app != null && fgApp != null && r.app != fgApp
2130                && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
2131                && r.app != mService.mHomeProcess) {
2132            mService.mPreviousProcess = r.app;
2133            mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
2134        }
2135    }
2136
2137    boolean resumeTopActivitiesLocked() {
2138        return resumeTopActivitiesLocked(null, null, null);
2139    }
2140
2141    boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
2142            Bundle targetOptions) {
2143        if (targetStack == null) {
2144            targetStack = getFocusedStack();
2145        }
2146        // Do targetStack first.
2147        boolean result = false;
2148        if (isFrontStack(targetStack)) {
2149            result = targetStack.resumeTopActivityLocked(target, targetOptions);
2150        }
2151        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2152            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2153            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2154                final ActivityStack stack = stacks.get(stackNdx);
2155                if (stack == targetStack) {
2156                    // Already started above.
2157                    continue;
2158                }
2159                if (isFrontStack(stack)) {
2160                    stack.resumeTopActivityLocked(null);
2161                }
2162            }
2163        }
2164        return result;
2165    }
2166
2167    void finishTopRunningActivityLocked(ProcessRecord app) {
2168        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2169            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2170            final int numStacks = stacks.size();
2171            for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2172                final ActivityStack stack = stacks.get(stackNdx);
2173                stack.finishTopRunningActivityLocked(app);
2174            }
2175        }
2176    }
2177
2178    void findTaskToMoveToFrontLocked(TaskRecord task, int flags, Bundle options) {
2179        if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
2180            mUserLeaving = true;
2181        }
2182        if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
2183            // Caller wants the home activity moved with it.  To accomplish this,
2184            // we'll just indicate that this task returns to the home task.
2185            task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
2186        }
2187        task.stack.moveTaskToFrontLocked(task, null, options);
2188        if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack="
2189                + task.stack);
2190    }
2191
2192    ActivityStack getStack(int stackId) {
2193        ActivityContainer activityContainer = mActivityContainers.get(stackId);
2194        if (activityContainer != null) {
2195            return activityContainer.mStack;
2196        }
2197        return null;
2198    }
2199
2200    ArrayList<ActivityStack> getStacks() {
2201        ArrayList<ActivityStack> allStacks = new ArrayList<ActivityStack>();
2202        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2203            allStacks.addAll(mActivityDisplays.valueAt(displayNdx).mStacks);
2204        }
2205        return allStacks;
2206    }
2207
2208    IBinder getHomeActivityToken() {
2209        final ArrayList<TaskRecord> tasks = mHomeStack.getAllTasks();
2210        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
2211            final TaskRecord task = tasks.get(taskNdx);
2212            if (task.isHomeTask()) {
2213                final ArrayList<ActivityRecord> activities = task.mActivities;
2214                for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
2215                    final ActivityRecord r = activities.get(activityNdx);
2216                    if (r.isHomeActivity()) {
2217                        return r.appToken;
2218                    }
2219                }
2220            }
2221        }
2222        return null;
2223    }
2224
2225    ActivityContainer createActivityContainer(ActivityRecord parentActivity,
2226            IActivityContainerCallback callback) {
2227        ActivityContainer activityContainer = new VirtualActivityContainer(parentActivity, callback);
2228        mActivityContainers.put(activityContainer.mStackId, activityContainer);
2229        parentActivity.mChildContainers.add(activityContainer);
2230        return activityContainer;
2231    }
2232
2233    void removeChildActivityContainers(ActivityRecord parentActivity) {
2234        final ArrayList<ActivityContainer> childStacks = parentActivity.mChildContainers;
2235        for (int containerNdx = childStacks.size() - 1; containerNdx >= 0; --containerNdx) {
2236            ActivityContainer container = childStacks.remove(containerNdx);
2237            container.release();
2238        }
2239    }
2240
2241    void deleteActivityContainer(IActivityContainer container) {
2242        ActivityContainer activityContainer = (ActivityContainer)container;
2243        if (activityContainer != null) {
2244            activityContainer.mStack.finishAllActivitiesLocked();
2245            final ActivityRecord parent = activityContainer.mParentActivity;
2246            if (parent != null) {
2247                parent.mChildContainers.remove(activityContainer);
2248            }
2249            final int stackId = activityContainer.mStackId;
2250            mActivityContainers.remove(stackId);
2251            mWindowManager.removeStack(stackId);
2252        }
2253    }
2254
2255    private int createStackOnDisplay(int stackId, int displayId) {
2256        ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
2257        if (activityDisplay == null) {
2258            return -1;
2259        }
2260
2261        ActivityContainer activityContainer = new ActivityContainer(stackId);
2262        mActivityContainers.put(stackId, activityContainer);
2263        activityContainer.attachToDisplayLocked(activityDisplay);
2264        return stackId;
2265    }
2266
2267    int getNextStackId() {
2268        while (true) {
2269            if (++mLastStackId <= HOME_STACK_ID) {
2270                mLastStackId = HOME_STACK_ID + 1;
2271            }
2272            if (getStack(mLastStackId) == null) {
2273                break;
2274            }
2275        }
2276        return mLastStackId;
2277    }
2278
2279    void createStackForRestoredTaskHistory(ArrayList<TaskRecord> tasks) {
2280        int stackId = createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY);
2281        final ActivityStack stack = getStack(stackId);
2282        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
2283            final TaskRecord task = tasks.get(taskNdx);
2284            stack.addTask(task, false, false);
2285            final int taskId = task.taskId;
2286            final ArrayList<ActivityRecord> activities = task.mActivities;
2287            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
2288                final ActivityRecord r = activities.get(activityNdx);
2289                mWindowManager.addAppToken(0, r.appToken, taskId, stackId,
2290                        r.info.screenOrientation, r.fullscreen,
2291                        (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
2292                        r.userId, r.info.configChanges);
2293            }
2294            mWindowManager.addTask(taskId, stackId, false);
2295        }
2296        resumeHomeStackTask(HOME_ACTIVITY_TYPE, null);
2297    }
2298
2299    void moveTaskToStack(int taskId, int stackId, boolean toTop) {
2300        final TaskRecord task = anyTaskForIdLocked(taskId);
2301        if (task == null) {
2302            return;
2303        }
2304        final ActivityStack stack = getStack(stackId);
2305        if (stack == null) {
2306            Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
2307            return;
2308        }
2309        task.stack.removeTask(task);
2310        stack.addTask(task, toTop, true);
2311        mWindowManager.addTask(taskId, stackId, toTop);
2312        resumeTopActivitiesLocked();
2313    }
2314
2315    ActivityRecord findTaskLocked(ActivityRecord r) {
2316        if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + r);
2317        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2318            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2319            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2320                final ActivityStack stack = stacks.get(stackNdx);
2321                if (!r.isApplicationActivity() && !stack.isHomeStack()) {
2322                    if (DEBUG_TASKS) Slog.d(TAG, "Skipping stack: " + stack);
2323                    continue;
2324                }
2325                final ActivityRecord ar = stack.findTaskLocked(r);
2326                if (ar != null) {
2327                    return ar;
2328                }
2329            }
2330        }
2331        if (DEBUG_TASKS) Slog.d(TAG, "No task found");
2332        return null;
2333    }
2334
2335    ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
2336        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2337            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2338            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2339                final ActivityRecord ar = stacks.get(stackNdx).findActivityLocked(intent, info);
2340                if (ar != null) {
2341                    return ar;
2342                }
2343            }
2344        }
2345        return null;
2346    }
2347
2348    void goingToSleepLocked() {
2349        scheduleSleepTimeout();
2350        if (!mGoingToSleep.isHeld()) {
2351            mGoingToSleep.acquire();
2352            if (mLaunchingActivity.isHeld()) {
2353                if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
2354                    throw new IllegalStateException("Calling must be system uid");
2355                }
2356                mLaunchingActivity.release();
2357                mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
2358            }
2359        }
2360        checkReadyForSleepLocked();
2361    }
2362
2363    boolean shutdownLocked(int timeout) {
2364        goingToSleepLocked();
2365
2366        boolean timedout = false;
2367        final long endTime = System.currentTimeMillis() + timeout;
2368        while (true) {
2369            boolean cantShutdown = false;
2370            for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2371                final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2372                for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2373                    cantShutdown |= stacks.get(stackNdx).checkReadyForSleepLocked();
2374                }
2375            }
2376            if (cantShutdown) {
2377                long timeRemaining = endTime - System.currentTimeMillis();
2378                if (timeRemaining > 0) {
2379                    try {
2380                        mService.wait(timeRemaining);
2381                    } catch (InterruptedException e) {
2382                    }
2383                } else {
2384                    Slog.w(TAG, "Activity manager shutdown timed out");
2385                    timedout = true;
2386                    break;
2387                }
2388            } else {
2389                break;
2390            }
2391        }
2392
2393        // Force checkReadyForSleep to complete.
2394        mSleepTimeout = true;
2395        checkReadyForSleepLocked();
2396
2397        return timedout;
2398    }
2399
2400    void comeOutOfSleepIfNeededLocked() {
2401        removeSleepTimeouts();
2402        if (mGoingToSleep.isHeld()) {
2403            mGoingToSleep.release();
2404        }
2405        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2406            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2407            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2408                final ActivityStack stack = stacks.get(stackNdx);
2409                stack.awakeFromSleepingLocked();
2410                if (isFrontStack(stack)) {
2411                    resumeTopActivitiesLocked();
2412                }
2413            }
2414        }
2415        mGoingToSleepActivities.clear();
2416    }
2417
2418    void activitySleptLocked(ActivityRecord r) {
2419        mGoingToSleepActivities.remove(r);
2420        checkReadyForSleepLocked();
2421    }
2422
2423    void checkReadyForSleepLocked() {
2424        if (!mService.isSleepingOrShuttingDown()) {
2425            // Do not care.
2426            return;
2427        }
2428
2429        if (!mSleepTimeout) {
2430            boolean dontSleep = false;
2431            for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2432                final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2433                for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2434                    dontSleep |= stacks.get(stackNdx).checkReadyForSleepLocked();
2435                }
2436            }
2437
2438            if (mStoppingActivities.size() > 0) {
2439                // Still need to tell some activities to stop; can't sleep yet.
2440                if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
2441                        + mStoppingActivities.size() + " activities");
2442                scheduleIdleLocked();
2443                dontSleep = true;
2444            }
2445
2446            if (mGoingToSleepActivities.size() > 0) {
2447                // Still need to tell some activities to sleep; can't sleep yet.
2448                if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
2449                        + mGoingToSleepActivities.size() + " activities");
2450                dontSleep = true;
2451            }
2452
2453            if (dontSleep) {
2454                return;
2455            }
2456        }
2457
2458        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2459            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2460            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2461                stacks.get(stackNdx).goToSleep();
2462            }
2463        }
2464
2465        removeSleepTimeouts();
2466
2467        if (mGoingToSleep.isHeld()) {
2468            mGoingToSleep.release();
2469        }
2470        if (mService.mShuttingDown) {
2471            mService.notifyAll();
2472        }
2473    }
2474
2475    boolean reportResumedActivityLocked(ActivityRecord r) {
2476        final ActivityStack stack = r.task.stack;
2477        if (isFrontStack(stack)) {
2478            mService.updateUsageStats(r, true);
2479        }
2480        if (allResumedActivitiesComplete()) {
2481            ensureActivitiesVisibleLocked(null, 0);
2482            mWindowManager.executeAppTransition();
2483            return true;
2484        }
2485        return false;
2486    }
2487
2488    void handleAppCrashLocked(ProcessRecord app) {
2489        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2490            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2491            final int numStacks = stacks.size();
2492            for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2493                final ActivityStack stack = stacks.get(stackNdx);
2494                stack.handleAppCrashLocked(app);
2495            }
2496        }
2497    }
2498
2499    void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
2500        // First the front stacks. In case any are not fullscreen and are in front of home.
2501        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2502            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2503            final int topStackNdx = stacks.size() - 1;
2504            for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
2505                final ActivityStack stack = stacks.get(stackNdx);
2506                stack.ensureActivitiesVisibleLocked(starting, configChanges);
2507            }
2508        }
2509    }
2510
2511    void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
2512        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2513            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2514            final int numStacks = stacks.size();
2515            for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2516                final ActivityStack stack = stacks.get(stackNdx);
2517                stack.scheduleDestroyActivities(app, false, reason);
2518            }
2519        }
2520    }
2521
2522    boolean switchUserLocked(int userId, UserStartedState uss) {
2523        mUserStackInFront.put(mCurrentUser, getFocusedStack().getStackId());
2524        final int restoreStackId = mUserStackInFront.get(userId, HOME_STACK_ID);
2525        mCurrentUser = userId;
2526
2527        mStartingUsers.add(uss);
2528        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2529            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2530            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2531                final ActivityStack stack = stacks.get(stackNdx);
2532                stack.switchUserLocked(userId);
2533                TaskRecord task = stack.topTask();
2534                if (task != null) {
2535                    mWindowManager.moveTaskToTop(task.taskId);
2536                }
2537            }
2538        }
2539
2540        ActivityStack stack = getStack(restoreStackId);
2541        if (stack == null) {
2542            stack = mHomeStack;
2543        }
2544        final boolean homeInFront = stack.isHomeStack();
2545        if (stack.isOnHomeDisplay()) {
2546            moveHomeStack(homeInFront);
2547            TaskRecord task = stack.topTask();
2548            if (task != null) {
2549                mWindowManager.moveTaskToTop(task.taskId);
2550            }
2551        } else {
2552            // Stack was moved to another display while user was swapped out.
2553            resumeHomeStackTask(HOME_ACTIVITY_TYPE, null);
2554        }
2555        return homeInFront;
2556    }
2557
2558    /**
2559     * Add background users to send boot completed events to.
2560     * @param userId The user being started in the background
2561     * @param uss The state object for the user.
2562     */
2563    public void startBackgroundUserLocked(int userId, UserStartedState uss) {
2564        mStartingBackgroundUsers.add(uss);
2565    }
2566
2567    final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
2568        int N = mStoppingActivities.size();
2569        if (N <= 0) return null;
2570
2571        ArrayList<ActivityRecord> stops = null;
2572
2573        final boolean nowVisible = allResumedActivitiesVisible();
2574        for (int i=0; i<N; i++) {
2575            ActivityRecord s = mStoppingActivities.get(i);
2576            if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
2577                    + nowVisible + " waitingVisible=" + s.waitingVisible
2578                    + " finishing=" + s.finishing);
2579            if (s.waitingVisible && nowVisible) {
2580                mWaitingVisibleActivities.remove(s);
2581                s.waitingVisible = false;
2582                if (s.finishing) {
2583                    // If this activity is finishing, it is sitting on top of
2584                    // everyone else but we now know it is no longer needed...
2585                    // so get rid of it.  Otherwise, we need to go through the
2586                    // normal flow and hide it once we determine that it is
2587                    // hidden by the activities in front of it.
2588                    if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
2589                    mWindowManager.setAppVisibility(s.appToken, false);
2590                }
2591            }
2592            if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
2593                if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
2594                if (stops == null) {
2595                    stops = new ArrayList<ActivityRecord>();
2596                }
2597                stops.add(s);
2598                mStoppingActivities.remove(i);
2599                N--;
2600                i--;
2601            }
2602        }
2603
2604        return stops;
2605    }
2606
2607    void validateTopActivitiesLocked() {
2608        // FIXME
2609/*        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2610            final ActivityStack stack = stacks.get(stackNdx);
2611            final ActivityRecord r = stack.topRunningActivityLocked(null);
2612            final ActivityState state = r == null ? ActivityState.DESTROYED : r.state;
2613            if (isFrontStack(stack)) {
2614                if (r == null) {
2615                    Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
2616                } else {
2617                    final ActivityRecord pausing = stack.mPausingActivity;
2618                    if (pausing != null && pausing == r) {
2619                        Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
2620                            " state=" + state);
2621                    }
2622                    if (state != ActivityState.INITIALIZING && state != ActivityState.RESUMED) {
2623                        Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
2624                                " state=" + state);
2625                    }
2626                }
2627            } else {
2628                final ActivityRecord resumed = stack.mResumedActivity;
2629                if (resumed != null && resumed == r) {
2630                    Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
2631                        " state=" + state);
2632                }
2633                if (r != null && (state == ActivityState.INITIALIZING
2634                        || state == ActivityState.RESUMED)) {
2635                    Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
2636                            " state=" + state);
2637                }
2638            }
2639        }
2640*/
2641    }
2642
2643    public void dump(PrintWriter pw, String prefix) {
2644        pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity=");
2645                pw.println(mDismissKeyguardOnNextActivity);
2646        pw.print(prefix); pw.print("mFocusedStack=" + mFocusedStack);
2647                pw.print(" mLastFocusedStack="); pw.println(mLastFocusedStack);
2648        pw.print(prefix); pw.println("mSleepTimeout=" + mSleepTimeout);
2649        pw.print(prefix); pw.println("mCurTaskId=" + mCurTaskId);
2650        pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront);
2651        pw.print(prefix); pw.println("mActivityContainers=" + mActivityContainers);
2652    }
2653
2654    ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
2655        return getFocusedStack().getDumpActivitiesLocked(name);
2656    }
2657
2658    static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
2659            boolean needSep, String prefix) {
2660        if (activity != null) {
2661            if (dumpPackage == null || dumpPackage.equals(activity.packageName)) {
2662                if (needSep) {
2663                    pw.println();
2664                }
2665                pw.print(prefix);
2666                pw.println(activity);
2667                return true;
2668            }
2669        }
2670        return false;
2671    }
2672
2673    boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2674            boolean dumpClient, String dumpPackage) {
2675        boolean printed = false;
2676        boolean needSep = false;
2677        for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
2678            ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
2679            pw.print("Display #"); pw.println(activityDisplay.mDisplayId);
2680            ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
2681            final int numStacks = stacks.size();
2682            for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2683                final ActivityStack stack = stacks.get(stackNdx);
2684                StringBuilder stackHeader = new StringBuilder(128);
2685                stackHeader.append("  Stack #");
2686                stackHeader.append(stack.mStackId);
2687                stackHeader.append(":");
2688                printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage,
2689                        needSep, stackHeader.toString());
2690                printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, "    ", "Run", false,
2691                        !dumpAll, false, dumpPackage, true,
2692                        "    Running activities (most recent first):", null);
2693
2694                needSep = printed;
2695                boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
2696                        "    mPausingActivity: ");
2697                if (pr) {
2698                    printed = true;
2699                    needSep = false;
2700                }
2701                pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
2702                        "    mResumedActivity: ");
2703                if (pr) {
2704                    printed = true;
2705                    needSep = false;
2706                }
2707                if (dumpAll) {
2708                    pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
2709                            "    mLastPausedActivity: ");
2710                    if (pr) {
2711                        printed = true;
2712                        needSep = true;
2713                    }
2714                    printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage,
2715                            needSep, "    mLastNoHistoryActivity: ");
2716                }
2717                needSep = printed;
2718            }
2719        }
2720
2721        printed |= dumpHistoryList(fd, pw, mFinishingActivities, "  ", "Fin", false, !dumpAll,
2722                false, dumpPackage, true, "  Activities waiting to finish:", null);
2723        printed |= dumpHistoryList(fd, pw, mStoppingActivities, "  ", "Stop", false, !dumpAll,
2724                false, dumpPackage, true, "  Activities waiting to stop:", null);
2725        printed |= dumpHistoryList(fd, pw, mWaitingVisibleActivities, "  ", "Wait", false, !dumpAll,
2726                false, dumpPackage, true, "  Activities waiting for another to become visible:",
2727                null);
2728        printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, "  ", "Sleep", false, !dumpAll,
2729                false, dumpPackage, true, "  Activities waiting to sleep:", null);
2730        printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, "  ", "Sleep", false, !dumpAll,
2731                false, dumpPackage, true, "  Activities waiting to sleep:", null);
2732
2733        return printed;
2734    }
2735
2736    static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
2737            String prefix, String label, boolean complete, boolean brief, boolean client,
2738            String dumpPackage, boolean needNL, String header1, String header2) {
2739        TaskRecord lastTask = null;
2740        String innerPrefix = null;
2741        String[] args = null;
2742        boolean printed = false;
2743        for (int i=list.size()-1; i>=0; i--) {
2744            final ActivityRecord r = list.get(i);
2745            if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2746                continue;
2747            }
2748            if (innerPrefix == null) {
2749                innerPrefix = prefix + "      ";
2750                args = new String[0];
2751            }
2752            printed = true;
2753            final boolean full = !brief && (complete || !r.isInHistory());
2754            if (needNL) {
2755                pw.println("");
2756                needNL = false;
2757            }
2758            if (header1 != null) {
2759                pw.println(header1);
2760                header1 = null;
2761            }
2762            if (header2 != null) {
2763                pw.println(header2);
2764                header2 = null;
2765            }
2766            if (lastTask != r.task) {
2767                lastTask = r.task;
2768                pw.print(prefix);
2769                pw.print(full ? "* " : "  ");
2770                pw.println(lastTask);
2771                if (full) {
2772                    lastTask.dump(pw, prefix + "  ");
2773                } else if (complete) {
2774                    // Complete + brief == give a summary.  Isn't that obvious?!?
2775                    if (lastTask.intent != null) {
2776                        pw.print(prefix); pw.print("  ");
2777                                pw.println(lastTask.intent.toInsecureStringWithClip());
2778                    }
2779                }
2780            }
2781            pw.print(prefix); pw.print(full ? "  * " : "    "); pw.print(label);
2782            pw.print(" #"); pw.print(i); pw.print(": ");
2783            pw.println(r);
2784            if (full) {
2785                r.dump(pw, innerPrefix);
2786            } else if (complete) {
2787                // Complete + brief == give a summary.  Isn't that obvious?!?
2788                pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2789                if (r.app != null) {
2790                    pw.print(innerPrefix); pw.println(r.app);
2791                }
2792            }
2793            if (client && r.app != null && r.app.thread != null) {
2794                // flush anything that is already in the PrintWriter since the thread is going
2795                // to write to the file descriptor directly
2796                pw.flush();
2797                try {
2798                    TransferPipe tp = new TransferPipe();
2799                    try {
2800                        r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2801                                r.appToken, innerPrefix, args);
2802                        // Short timeout, since blocking here can
2803                        // deadlock with the application.
2804                        tp.go(fd, 2000);
2805                    } finally {
2806                        tp.kill();
2807                    }
2808                } catch (IOException e) {
2809                    pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2810                } catch (RemoteException e) {
2811                    pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2812                }
2813                needNL = true;
2814            }
2815        }
2816        return printed;
2817    }
2818
2819    void scheduleIdleTimeoutLocked(ActivityRecord next) {
2820        if (DEBUG_IDLE) Slog.d(TAG, "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
2821        Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
2822        mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2823    }
2824
2825    final void scheduleIdleLocked() {
2826        mHandler.sendEmptyMessage(IDLE_NOW_MSG);
2827    }
2828
2829    void removeTimeoutsForActivityLocked(ActivityRecord r) {
2830        if (DEBUG_IDLE) Slog.d(TAG, "removeTimeoutsForActivity: Callers=" + Debug.getCallers(4));
2831        mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2832    }
2833
2834    final void scheduleResumeTopActivities() {
2835        if (!mHandler.hasMessages(RESUME_TOP_ACTIVITY_MSG)) {
2836            mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2837        }
2838    }
2839
2840    void removeSleepTimeouts() {
2841        mSleepTimeout = false;
2842        mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
2843    }
2844
2845    final void scheduleSleepTimeout() {
2846        removeSleepTimeouts();
2847        mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
2848    }
2849
2850    @Override
2851    public void onDisplayAdded(int displayId) {
2852        mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_ADDED, displayId, 0));
2853    }
2854
2855    @Override
2856    public void onDisplayRemoved(int displayId) {
2857        mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_REMOVED, displayId, 0));
2858    }
2859
2860    @Override
2861    public void onDisplayChanged(int displayId) {
2862        mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_CHANGED, displayId, 0));
2863    }
2864
2865    public void handleDisplayAddedLocked(int displayId) {
2866        boolean newDisplay;
2867        synchronized (mService) {
2868            newDisplay = mActivityDisplays.get(displayId) == null;
2869            if (newDisplay) {
2870                ActivityDisplay activityDisplay = new ActivityDisplay(displayId);
2871                mActivityDisplays.put(displayId, activityDisplay);
2872            }
2873        }
2874        if (newDisplay) {
2875            mWindowManager.onDisplayAdded(displayId);
2876        }
2877    }
2878
2879    public void handleDisplayRemovedLocked(int displayId) {
2880        synchronized (mService) {
2881            ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
2882            if (activityDisplay != null) {
2883                ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
2884                for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2885                    stacks.get(stackNdx).mActivityContainer.detachLocked();
2886                }
2887                mActivityDisplays.remove(displayId);
2888            }
2889        }
2890        mWindowManager.onDisplayRemoved(displayId);
2891    }
2892
2893    public void handleDisplayChangedLocked(int displayId) {
2894        synchronized (mService) {
2895            ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
2896            if (activityDisplay != null) {
2897                // TODO: Update the bounds.
2898            }
2899        }
2900        mWindowManager.onDisplayChanged(displayId);
2901    }
2902
2903    StackInfo getStackInfo(ActivityStack stack) {
2904        StackInfo info = new StackInfo();
2905        mWindowManager.getStackBounds(stack.mStackId, info.bounds);
2906        info.displayId = Display.DEFAULT_DISPLAY;
2907        info.stackId = stack.mStackId;
2908
2909        ArrayList<TaskRecord> tasks = stack.getAllTasks();
2910        final int numTasks = tasks.size();
2911        int[] taskIds = new int[numTasks];
2912        String[] taskNames = new String[numTasks];
2913        for (int i = 0; i < numTasks; ++i) {
2914            final TaskRecord task = tasks.get(i);
2915            taskIds[i] = task.taskId;
2916            taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString()
2917                    : task.realActivity != null ? task.realActivity.flattenToString()
2918                    : task.getTopActivity() != null ? task.getTopActivity().packageName
2919                    : "unknown";
2920        }
2921        info.taskIds = taskIds;
2922        info.taskNames = taskNames;
2923        return info;
2924    }
2925
2926    StackInfo getStackInfoLocked(int stackId) {
2927        ActivityStack stack = getStack(stackId);
2928        if (stack != null) {
2929            return getStackInfo(stack);
2930        }
2931        return null;
2932    }
2933
2934    ArrayList<StackInfo> getAllStackInfosLocked() {
2935        ArrayList<StackInfo> list = new ArrayList<StackInfo>();
2936        for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
2937            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2938            for (int ndx = stacks.size() - 1; ndx >= 0; --ndx) {
2939                list.add(getStackInfo(stacks.get(ndx)));
2940            }
2941        }
2942        return list;
2943    }
2944
2945    void setLockTaskModeLocked(TaskRecord task) {
2946        if (task == null) {
2947            // Take out of lock task mode.
2948            mLockTaskModeTask = null;
2949            return;
2950        }
2951        if (isLockTaskModeViolation(task)) {
2952            Slog.e(TAG, "setLockTaskMode: Attempt to start a second Lock Task Mode task.");
2953            return;
2954        }
2955        mLockTaskModeTask = task;
2956        findTaskToMoveToFrontLocked(task, 0, null);
2957        resumeTopActivitiesLocked();
2958    }
2959
2960    boolean isLockTaskModeViolation(TaskRecord task) {
2961        return mLockTaskModeTask != null && mLockTaskModeTask != task;
2962    }
2963
2964    void endLockTaskModeIfTaskEnding(TaskRecord task) {
2965        if (mLockTaskModeTask != null && mLockTaskModeTask == task) {
2966            mLockTaskModeTask = null;
2967        }
2968    }
2969
2970    boolean isInLockTaskMode() {
2971        return mLockTaskModeTask != null;
2972    }
2973
2974    private final class ActivityStackSupervisorHandler extends Handler {
2975
2976        public ActivityStackSupervisorHandler(Looper looper) {
2977            super(looper);
2978        }
2979
2980        void activityIdleInternal(ActivityRecord r) {
2981            synchronized (mService) {
2982                activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2983            }
2984        }
2985
2986        @Override
2987        public void handleMessage(Message msg) {
2988            switch (msg.what) {
2989                case IDLE_TIMEOUT_MSG: {
2990                    if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_TIMEOUT_MSG: r=" + msg.obj);
2991                    if (mService.mDidDexOpt) {
2992                        mService.mDidDexOpt = false;
2993                        Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2994                        nmsg.obj = msg.obj;
2995                        mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2996                        return;
2997                    }
2998                    // We don't at this point know if the activity is fullscreen,
2999                    // so we need to be conservative and assume it isn't.
3000                    activityIdleInternal((ActivityRecord)msg.obj);
3001                } break;
3002                case IDLE_NOW_MSG: {
3003                    if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_NOW_MSG: r=" + msg.obj);
3004                    activityIdleInternal((ActivityRecord)msg.obj);
3005                } break;
3006                case RESUME_TOP_ACTIVITY_MSG: {
3007                    synchronized (mService) {
3008                        resumeTopActivitiesLocked();
3009                    }
3010                } break;
3011                case SLEEP_TIMEOUT_MSG: {
3012                    synchronized (mService) {
3013                        if (mService.isSleepingOrShuttingDown()) {
3014                            Slog.w(TAG, "Sleep timeout!  Sleeping now.");
3015                            mSleepTimeout = true;
3016                            checkReadyForSleepLocked();
3017                        }
3018                    }
3019                } break;
3020                case LAUNCH_TIMEOUT_MSG: {
3021                    if (mService.mDidDexOpt) {
3022                        mService.mDidDexOpt = false;
3023                        mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
3024                        return;
3025                    }
3026                    synchronized (mService) {
3027                        if (mLaunchingActivity.isHeld()) {
3028                            Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
3029                            if (VALIDATE_WAKE_LOCK_CALLER
3030                                    && Binder.getCallingUid() != Process.myUid()) {
3031                                throw new IllegalStateException("Calling must be system uid");
3032                            }
3033                            mLaunchingActivity.release();
3034                        }
3035                    }
3036                } break;
3037                case HANDLE_DISPLAY_ADDED: {
3038                    handleDisplayAddedLocked(msg.arg1);
3039                } break;
3040                case HANDLE_DISPLAY_CHANGED: {
3041                    handleDisplayChangedLocked(msg.arg1);
3042                } break;
3043                case HANDLE_DISPLAY_REMOVED: {
3044                    handleDisplayRemovedLocked(msg.arg1);
3045                } break;
3046                case CONTAINER_CALLBACK_VISIBILITY: {
3047                    final ActivityContainer container = (ActivityContainer) msg.obj;
3048                    try {
3049                        // We only send this message if mCallback is non-null.
3050                        container.mCallback.setVisible(container.asBinder(), msg.arg1 == 1);
3051                    } catch (RemoteException e) {
3052                    }
3053                }
3054            }
3055        }
3056    }
3057
3058    class ActivityContainer extends android.app.IActivityContainer.Stub {
3059        final static int FORCE_NEW_TASK_FLAGS = Intent.FLAG_ACTIVITY_NEW_TASK |
3060                Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
3061        final int mStackId;
3062        IActivityContainerCallback mCallback = null;
3063        final ActivityStack mStack;
3064        ActivityRecord mParentActivity = null;
3065        String mIdString;
3066
3067        boolean mVisible = true;
3068
3069        /** Display this ActivityStack is currently on. Null if not attached to a Display. */
3070        ActivityDisplay mActivityDisplay;
3071
3072        final static int CONTAINER_STATE_HAS_SURFACE = 0;
3073        final static int CONTAINER_STATE_NO_SURFACE = 1;
3074        final static int CONTAINER_STATE_FINISHING = 2;
3075        int mContainerState = CONTAINER_STATE_HAS_SURFACE;
3076
3077        ActivityContainer(int stackId) {
3078            synchronized (mService) {
3079                mStackId = stackId;
3080                mStack = new ActivityStack(this);
3081                mIdString = "ActivtyContainer{" + mStackId + "}";
3082                if (DEBUG_STACK) Slog.d(TAG, "Creating " + this);
3083            }
3084        }
3085
3086        void attachToDisplayLocked(ActivityDisplay activityDisplay) {
3087            if (DEBUG_STACK) Slog.d(TAG, "attachToDisplayLocked: " + this
3088                    + " to display=" + activityDisplay);
3089            mActivityDisplay = activityDisplay;
3090            mStack.mDisplayId = activityDisplay.mDisplayId;
3091            mStack.mStacks = activityDisplay.mStacks;
3092
3093            activityDisplay.attachActivities(mStack);
3094            mWindowManager.attachStack(mStackId, activityDisplay.mDisplayId);
3095        }
3096
3097        @Override
3098        public void attachToDisplay(int displayId) {
3099            synchronized (mService) {
3100                ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
3101                if (activityDisplay == null) {
3102                    return;
3103                }
3104                attachToDisplayLocked(activityDisplay);
3105            }
3106        }
3107
3108        @Override
3109        public int getDisplayId() {
3110            if (mActivityDisplay != null) {
3111                return mActivityDisplay.mDisplayId;
3112            }
3113            return -1;
3114        }
3115
3116        @Override
3117        public boolean injectEvent(InputEvent event) {
3118            final long origId = Binder.clearCallingIdentity();
3119            try {
3120                if (mActivityDisplay != null) {
3121                    return mInputManagerInternal.injectInputEvent(event,
3122                            mActivityDisplay.mDisplayId,
3123                            InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
3124                }
3125                return false;
3126            } finally {
3127                Binder.restoreCallingIdentity(origId);
3128            }
3129        }
3130
3131        @Override
3132        public void release() {
3133            mContainerState = CONTAINER_STATE_FINISHING;
3134            mStack.finishAllActivitiesLocked();
3135            detachLocked();
3136            mWindowManager.removeStack(mStackId);
3137        }
3138
3139        private void detachLocked() {
3140            if (DEBUG_STACK) Slog.d(TAG, "detachLocked: " + this + " from display="
3141                    + mActivityDisplay + " Callers=" + Debug.getCallers(2));
3142            if (mActivityDisplay != null) {
3143                mActivityDisplay.detachActivitiesLocked(mStack);
3144                mActivityDisplay = null;
3145                mStack.mDisplayId = -1;
3146                mStack.mStacks = null;
3147                mWindowManager.detachStack(mStackId);
3148            }
3149        }
3150
3151        @Override
3152        public final int startActivity(Intent intent) {
3153            mService.enforceNotIsolatedCaller("ActivityContainer.startActivity");
3154            int userId = mService.handleIncomingUser(Binder.getCallingPid(),
3155                    Binder.getCallingUid(), mCurrentUser, false, true, "ActivityContainer", null);
3156            // TODO: Switch to user app stacks here.
3157            intent.addFlags(FORCE_NEW_TASK_FLAGS);
3158            String mimeType = intent.getType();
3159            if (mimeType == null && intent.getData() != null
3160                    && "content".equals(intent.getData().getScheme())) {
3161                mimeType = mService.getProviderMimeType(intent.getData(), userId);
3162            }
3163            return startActivityMayWait(null, -1, null, intent, mimeType, null, null, null, null, 0, 0, null,
3164                    null, null, null, null, userId, this);
3165        }
3166
3167        @Override
3168        public final int startActivityIntentSender(IIntentSender intentSender) {
3169            mService.enforceNotIsolatedCaller("ActivityContainer.startActivityIntentSender");
3170
3171            if (!(intentSender instanceof PendingIntentRecord)) {
3172                throw new IllegalArgumentException("Bad PendingIntent object");
3173            }
3174
3175            return ((PendingIntentRecord)intentSender).sendInner(0, null, null, null, null, null,
3176                    null, 0, FORCE_NEW_TASK_FLAGS, FORCE_NEW_TASK_FLAGS, null, this);
3177        }
3178
3179        private void checkEmbeddedAllowedInner(Intent intent, String resolvedType) {
3180            int userId = mService.handleIncomingUser(Binder.getCallingPid(),
3181                    Binder.getCallingUid(), mCurrentUser, false, true, "ActivityContainer", null);
3182            if (resolvedType == null) {
3183                resolvedType = intent.getType();
3184                if (resolvedType == null && intent.getData() != null
3185                        && "content".equals(intent.getData().getScheme())) {
3186                    resolvedType = mService.getProviderMimeType(intent.getData(), userId);
3187                }
3188            }
3189            ActivityInfo aInfo = resolveActivity(intent, resolvedType, 0, null, null, userId);
3190            if (aInfo != null && (aInfo.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
3191                throw new SecurityException(
3192                        "Attempt to embed activity that has not set allowEmbedded=\"true\"");
3193            }
3194        }
3195
3196        /** Throw a SecurityException if allowEmbedded is not true */
3197        @Override
3198        public final void checkEmbeddedAllowed(Intent intent) {
3199            checkEmbeddedAllowedInner(intent, null);
3200        }
3201
3202        /** Throw a SecurityException if allowEmbedded is not true */
3203        @Override
3204        public final void checkEmbeddedAllowedIntentSender(IIntentSender intentSender) {
3205            if (!(intentSender instanceof PendingIntentRecord)) {
3206                throw new IllegalArgumentException("Bad PendingIntent object");
3207            }
3208            PendingIntentRecord pendingIntent = (PendingIntentRecord) intentSender;
3209            checkEmbeddedAllowedInner(pendingIntent.key.requestIntent,
3210                    pendingIntent.key.requestResolvedType);
3211        }
3212
3213        @Override
3214        public IBinder asBinder() {
3215            return this;
3216        }
3217
3218        @Override
3219        public void setSurface(Surface surface, int width, int height, int density) {
3220            mService.enforceNotIsolatedCaller("ActivityContainer.attachToSurface");
3221        }
3222
3223        ActivityStackSupervisor getOuter() {
3224            return ActivityStackSupervisor.this;
3225        }
3226
3227        boolean isAttached() {
3228            return mActivityDisplay != null;
3229        }
3230
3231        void getBounds(Point outBounds) {
3232            if (mActivityDisplay != null) {
3233                mActivityDisplay.getBounds(outBounds);
3234            } else {
3235                outBounds.set(0, 0);
3236            }
3237        }
3238
3239        // TODO: Make sure every change to ActivityRecord.visible results in a call to this.
3240        void setVisible(boolean visible) {
3241            if (mVisible != visible) {
3242                mVisible = visible;
3243                if (mCallback != null) {
3244                    mHandler.obtainMessage(CONTAINER_CALLBACK_VISIBILITY, visible ? 1 : 0,
3245                            0 /* unused */, this).sendToTarget();
3246                }
3247            }
3248        }
3249
3250        void setDrawn() {
3251        }
3252
3253        @Override
3254        public String toString() {
3255            return mIdString + (mActivityDisplay == null ? "N" : "A");
3256        }
3257    }
3258
3259    private class VirtualActivityContainer extends ActivityContainer {
3260        Surface mSurface;
3261        boolean mDrawn = false;
3262
3263        VirtualActivityContainer(ActivityRecord parent, IActivityContainerCallback callback) {
3264            super(getNextStackId());
3265            mParentActivity = parent;
3266            mCallback = callback;
3267            mContainerState = CONTAINER_STATE_NO_SURFACE;
3268            mIdString = "VirtualActivtyContainer{" + mStackId + ", parent=" + mParentActivity + "}";
3269        }
3270
3271        @Override
3272        public void setSurface(Surface surface, int width, int height, int density) {
3273            super.setSurface(surface, width, height, density);
3274
3275            synchronized (mService) {
3276                final long origId = Binder.clearCallingIdentity();
3277                try {
3278                    setSurfaceLocked(surface, width, height, density);
3279                } finally {
3280                    Binder.restoreCallingIdentity(origId);
3281                }
3282            }
3283        }
3284
3285        private void setSurfaceLocked(Surface surface, int width, int height, int density) {
3286            if (mContainerState == CONTAINER_STATE_FINISHING) {
3287                return;
3288            }
3289            VirtualActivityDisplay virtualActivityDisplay =
3290                    (VirtualActivityDisplay) mActivityDisplay;
3291            if (virtualActivityDisplay == null) {
3292                virtualActivityDisplay =
3293                        new VirtualActivityDisplay(width, height, density);
3294                mActivityDisplay = virtualActivityDisplay;
3295                mActivityDisplays.put(virtualActivityDisplay.mDisplayId, virtualActivityDisplay);
3296                attachToDisplayLocked(virtualActivityDisplay);
3297            }
3298
3299            if (mSurface != null) {
3300                mSurface.release();
3301            }
3302
3303            mSurface = surface;
3304            if (surface != null) {
3305                mStack.resumeTopActivityLocked(null);
3306            } else {
3307                mContainerState = CONTAINER_STATE_NO_SURFACE;
3308                ((VirtualActivityDisplay) mActivityDisplay).setSurface(null);
3309                if (mStack.mPausingActivity == null && mStack.mResumedActivity != null) {
3310                    mStack.startPausingLocked(false, true);
3311                }
3312            }
3313
3314            setSurfaceIfReady();
3315
3316            if (DEBUG_STACK) Slog.d(TAG, "setSurface: " + this + " to display="
3317                    + virtualActivityDisplay);
3318        }
3319
3320        @Override
3321        boolean isAttached() {
3322            return mSurface != null && super.isAttached();
3323        }
3324
3325        @Override
3326        void setDrawn() {
3327            synchronized (mService) {
3328                mDrawn = true;
3329                setSurfaceIfReady();
3330            }
3331        }
3332
3333        private void setSurfaceIfReady() {
3334            if (DEBUG_STACK) Slog.v(TAG, "setSurfaceIfReady: mDrawn=" + mDrawn +
3335                    " mContainerState=" + mContainerState + " mSurface=" + mSurface);
3336            if (mDrawn && mSurface != null && mContainerState == CONTAINER_STATE_NO_SURFACE) {
3337                ((VirtualActivityDisplay) mActivityDisplay).setSurface(mSurface);
3338                mContainerState = CONTAINER_STATE_HAS_SURFACE;
3339            }
3340        }
3341    }
3342
3343    /** Exactly one of these classes per Display in the system. Capable of holding zero or more
3344     * attached {@link ActivityStack}s */
3345    class ActivityDisplay {
3346        /** Actual Display this object tracks. */
3347        int mDisplayId;
3348        Display mDisplay;
3349        DisplayInfo mDisplayInfo = new DisplayInfo();
3350
3351        /** All of the stacks on this display. Order matters, topmost stack is in front of all other
3352         * stacks, bottommost behind. Accessed directly by ActivityManager package classes */
3353        final ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
3354
3355        ActivityDisplay() {
3356        }
3357
3358        ActivityDisplay(int displayId) {
3359            init(mDisplayManager.getDisplay(displayId));
3360        }
3361
3362        void init(Display display) {
3363            mDisplay = display;
3364            mDisplayId = display.getDisplayId();
3365            mDisplay.getDisplayInfo(mDisplayInfo);
3366        }
3367
3368        void attachActivities(ActivityStack stack) {
3369            if (DEBUG_STACK) Slog.v(TAG, "attachActivities: attaching " + stack + " to displayId="
3370                    + mDisplayId);
3371            mStacks.add(stack);
3372        }
3373
3374        void detachActivitiesLocked(ActivityStack stack) {
3375            if (DEBUG_STACK) Slog.v(TAG, "detachActivitiesLocked: detaching " + stack
3376                    + " from displayId=" + mDisplayId);
3377            mStacks.remove(stack);
3378        }
3379
3380        void getBounds(Point bounds) {
3381            mDisplay.getDisplayInfo(mDisplayInfo);
3382            bounds.x = mDisplayInfo.appWidth;
3383            bounds.y = mDisplayInfo.appHeight;
3384        }
3385
3386        @Override
3387        public String toString() {
3388            return "ActivityDisplay={" + mDisplayId + " numStacks=" + mStacks.size() + "}";
3389        }
3390    }
3391
3392    class VirtualActivityDisplay extends ActivityDisplay {
3393        VirtualDisplay mVirtualDisplay;
3394
3395        VirtualActivityDisplay(int width, int height, int density) {
3396            DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
3397            mVirtualDisplay = dm.createVirtualDisplay(mService.mContext, VIRTUAL_DISPLAY_BASE_NAME,
3398                    width, height, density, null, DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC |
3399                    DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
3400
3401            init(mVirtualDisplay.getDisplay());
3402
3403            mWindowManager.handleDisplayAdded(mDisplayId);
3404        }
3405
3406        void setSurface(Surface surface) {
3407            if (mVirtualDisplay != null) {
3408                mVirtualDisplay.setSurface(surface);
3409            }
3410        }
3411
3412        @Override
3413        void detachActivitiesLocked(ActivityStack stack) {
3414            super.detachActivitiesLocked(stack);
3415            if (mVirtualDisplay != null) {
3416                mVirtualDisplay.release();
3417                mVirtualDisplay = null;
3418            }
3419        }
3420
3421        @Override
3422        public String toString() {
3423            return "VirtualActivityDisplay={" + mDisplayId + "}";
3424        }
3425    }
3426}
3427