ActivityStackSupervisor.java revision e67a784eb2c914c04c62ea5dfa1e3751df5582cc
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 = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1477
1478        // If the onlyIfNeeded flag is set, then we can do this if the activity
1479        // being launched is the same as the one making the call...  or, as
1480        // a special case, if we do not know the caller then we count the
1481        // current top activity as the caller.
1482        if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1483            ActivityRecord checkedCaller = sourceRecord;
1484            if (checkedCaller == null) {
1485                checkedCaller = getFocusedStack().topRunningNonDelayedActivityLocked(notTop);
1486            }
1487            if (!checkedCaller.realActivity.equals(r.realActivity)) {
1488                // Caller is not the same as launcher, so always needed.
1489                startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1490            }
1491        }
1492
1493        switch (r.info.documentLaunchMode) {
1494            case ActivityInfo.DOCUMENT_LAUNCH_NONE:
1495                break;
1496            case ActivityInfo.DOCUMENT_LAUNCH_ALWAYS:
1497                intent.addFlags(
1498                        Intent.FLAG_ACTIVITY_NEW_DOCUMENT | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
1499                break;
1500            case ActivityInfo.DOCUMENT_LAUNCH_INTO_EXISTING:
1501                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
1502                break;
1503        }
1504        final boolean newDocument = intent.isDocument();
1505        if (sourceRecord == null) {
1506            // This activity is not being started from another...  in this
1507            // case we -always- start a new task.
1508            if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
1509                Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1510                        "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
1511                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1512            }
1513        } else if (newDocument) {
1514            if (r.launchMode != ActivityInfo.LAUNCH_MULTIPLE) {
1515                Slog.w(TAG, "FLAG_ACTIVITY_NEW_DOCUMENT and launchMode != \"standard\"");
1516                r.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
1517            }
1518        } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1519            // The original activity who is starting us is running as a single
1520            // instance...  this new activity it is starting must go on its
1521            // own task.
1522            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1523        } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1524                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1525            // The activity being started is a single instance...  it always
1526            // gets launched into its own task.
1527            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1528        }
1529
1530        ActivityInfo newTaskInfo = null;
1531        Intent newTaskIntent = null;
1532        final ActivityStack sourceStack;
1533        if (sourceRecord != null) {
1534            if (sourceRecord.finishing) {
1535                // If the source is finishing, we can't further count it as our source.  This
1536                // is because the task it is associated with may now be empty and on its way out,
1537                // so we don't want to blindly throw it in to that task.  Instead we will take
1538                // the NEW_TASK flow and try to find a task for it. But save the task information
1539                // so it can be used when creating the new task.
1540                if ((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
1541                    Slog.w(TAG, "startActivity called from finishing " + sourceRecord
1542                            + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
1543                    launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1544                    newTaskInfo = sourceRecord.info;
1545                    newTaskIntent = sourceRecord.task.intent;
1546                }
1547                sourceRecord = null;
1548                sourceStack = null;
1549            } else {
1550                sourceStack = sourceRecord.task.stack;
1551            }
1552        } else {
1553            sourceStack = null;
1554        }
1555
1556        if (r.resultTo != null && (launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1557            // For whatever reason this activity is being launched into a new
1558            // task...  yet the caller has requested a result back.  Well, that
1559            // is pretty messed up, so instead immediately send back a cancel
1560            // and let the new task continue launched as normal without a
1561            // dependency on its originator.
1562            Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1563            r.resultTo.task.stack.sendActivityResultLocked(-1,
1564                    r.resultTo, r.resultWho, r.requestCode,
1565                Activity.RESULT_CANCELED, null);
1566            r.resultTo = null;
1567        }
1568
1569        boolean addingToTask = false;
1570        boolean movedHome = false;
1571        TaskRecord reuseTask = null;
1572        ActivityStack targetStack;
1573        if (((launchFlags & Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1574                (launchFlags & Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1575                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1576                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1577            // If bring to front is requested, and no result is requested, and
1578            // we can find a task that was started with this same
1579            // component, then instead of launching bring that one to the front.
1580            if (r.resultTo == null) {
1581                // See if there is a task to bring to the front.  If this is
1582                // a SINGLE_INSTANCE activity, there can be one and only one
1583                // instance of it in the history, and it is always in its own
1584                // unique task, so we do a special search.
1585                ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1586                        ? findTaskLocked(r)
1587                        : findActivityLocked(intent, r.info);
1588                if (intentActivity != null) {
1589                    if (isLockTaskModeViolation(intentActivity.task)) {
1590                        Slog.e(TAG, "moveTaskToFront: Attempt to violate Lock Task Mode");
1591                        return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
1592                    }
1593                    if (r.task == null) {
1594                        r.task = intentActivity.task;
1595                    }
1596                    targetStack = intentActivity.task.stack;
1597                    targetStack.mLastPausedActivity = null;
1598                    if (DEBUG_TASKS) Slog.d(TAG, "Bring to front target: " + targetStack
1599                            + " from " + intentActivity);
1600                    targetStack.moveToFront();
1601                    if (intentActivity.task.intent == null) {
1602                        // This task was started because of movement of
1603                        // the activity based on affinity...  now that we
1604                        // are actually launching it, we can assign the
1605                        // base intent.
1606                        intentActivity.task.setIntent(intent, r.info);
1607                    }
1608                    // If the target task is not in the front, then we need
1609                    // to bring it to the front...  except...  well, with
1610                    // SINGLE_TASK_LAUNCH it's not entirely clear.  We'd like
1611                    // to have the same behavior as if a new instance was
1612                    // being started, which means not bringing it to the front
1613                    // if the caller is not itself in the front.
1614                    final ActivityStack lastStack = getLastStack();
1615                    ActivityRecord curTop = lastStack == null?
1616                            null : lastStack.topRunningNonDelayedActivityLocked(notTop);
1617                    if (curTop != null && (curTop.task != intentActivity.task ||
1618                            curTop.task != lastStack.topTask())) {
1619                        r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1620                        if (sourceRecord == null || (sourceStack.topActivity() != null &&
1621                                sourceStack.topActivity().task == sourceRecord.task)) {
1622                            // We really do want to push this one into the
1623                            // user's face, right now.
1624                            movedHome = true;
1625                            targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1626                            if ((launchFlags &
1627                                    (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1628                                    == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1629                                // Caller wants to appear on home activity.
1630                                intentActivity.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1631                            }
1632                            options = null;
1633                        }
1634                    }
1635                    // If the caller has requested that the target task be
1636                    // reset, then do so.
1637                    if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1638                        intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1639                    }
1640                    if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1641                        // We don't need to start a new activity, and
1642                        // the client said not to do anything if that
1643                        // is the case, so this is it!  And for paranoia, make
1644                        // sure we have correctly resumed the top activity.
1645                        if (doResume) {
1646                            resumeTopActivitiesLocked(targetStack, null, options);
1647                        } else {
1648                            ActivityOptions.abort(options);
1649                        }
1650                        return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1651                    }
1652                    if ((launchFlags &
1653                            (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1654                            == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1655                        // The caller has requested to completely replace any
1656                        // existing task with its new activity.  Well that should
1657                        // not be too hard...
1658                        reuseTask = intentActivity.task;
1659                        reuseTask.performClearTaskLocked();
1660                        reuseTask.setIntent(r.intent, r.info);
1661                    } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1662                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1663                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1664                        // In this situation we want to remove all activities
1665                        // from the task up to the one being started.  In most
1666                        // cases this means we are resetting the task to its
1667                        // initial state.
1668                        ActivityRecord top =
1669                                intentActivity.task.performClearTaskLocked(r, launchFlags);
1670                        if (top != null) {
1671                            if (top.frontOfTask) {
1672                                // Activity aliases may mean we use different
1673                                // intents for the top activity, so make sure
1674                                // the task now has the identity of the new
1675                                // intent.
1676                                top.task.setIntent(r.intent, r.info);
1677                            }
1678                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1679                                    r, top.task);
1680                            top.deliverNewIntentLocked(callingUid, r.intent);
1681                        } else {
1682                            // A special case: we need to
1683                            // start the activity because it is not currently
1684                            // running, and the caller has asked to clear the
1685                            // current task to have this activity at the top.
1686                            addingToTask = true;
1687                            // Now pretend like this activity is being started
1688                            // by the top of its task, so it is put in the
1689                            // right place.
1690                            sourceRecord = intentActivity;
1691                        }
1692                    } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1693                        // In this case the top activity on the task is the
1694                        // same as the one being launched, so we take that
1695                        // as a request to bring the task to the foreground.
1696                        // If the top activity in the task is the root
1697                        // activity, deliver this new intent to it if it
1698                        // desires.
1699                        if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1700                                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1701                                && intentActivity.realActivity.equals(r.realActivity)) {
1702                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1703                                    intentActivity.task);
1704                            if (intentActivity.frontOfTask) {
1705                                intentActivity.task.setIntent(r.intent, r.info);
1706                            }
1707                            intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1708                        } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1709                            // In this case we are launching the root activity
1710                            // of the task, but with a different intent.  We
1711                            // should start a new instance on top.
1712                            addingToTask = true;
1713                            sourceRecord = intentActivity;
1714                        }
1715                    } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1716                        // In this case an activity is being launched in to an
1717                        // existing task, without resetting that task.  This
1718                        // is typically the situation of launching an activity
1719                        // from a notification or shortcut.  We want to place
1720                        // the new activity on top of the current task.
1721                        addingToTask = true;
1722                        sourceRecord = intentActivity;
1723                    } else if (!intentActivity.task.rootWasReset) {
1724                        // In this case we are launching in to an existing task
1725                        // that has not yet been started from its front door.
1726                        // The current task has been brought to the front.
1727                        // Ideally, we'd probably like to place this new task
1728                        // at the bottom of its stack, but that's a little hard
1729                        // to do with the current organization of the code so
1730                        // for now we'll just drop it.
1731                        intentActivity.task.setIntent(r.intent, r.info);
1732                    }
1733                    if (!addingToTask && reuseTask == null) {
1734                        // We didn't do anything...  but it was needed (a.k.a., client
1735                        // don't use that intent!)  And for paranoia, make
1736                        // sure we have correctly resumed the top activity.
1737                        if (doResume) {
1738                            targetStack.resumeTopActivityLocked(null, options);
1739                        } else {
1740                            ActivityOptions.abort(options);
1741                        }
1742                        return ActivityManager.START_TASK_TO_FRONT;
1743                    }
1744                }
1745            }
1746        }
1747
1748        //String uri = r.intent.toURI();
1749        //Intent intent2 = new Intent(uri);
1750        //Slog.i(TAG, "Given intent: " + r.intent);
1751        //Slog.i(TAG, "URI is: " + uri);
1752        //Slog.i(TAG, "To intent: " + intent2);
1753
1754        if (r.packageName != null) {
1755            // If the activity being launched is the same as the one currently
1756            // at the top, then we need to check if it should only be launched
1757            // once.
1758            ActivityStack topStack = getFocusedStack();
1759            ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
1760            if (top != null && r.resultTo == null) {
1761                if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1762                    if (top.app != null && top.app.thread != null) {
1763                        if ((launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1764                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1765                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1766                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1767                                    top.task);
1768                            // For paranoia, make sure we have correctly
1769                            // resumed the top activity.
1770                            topStack.mLastPausedActivity = null;
1771                            if (doResume) {
1772                                resumeTopActivitiesLocked();
1773                            }
1774                            ActivityOptions.abort(options);
1775                            if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1776                                // We don't need to start a new activity, and
1777                                // the client said not to do anything if that
1778                                // is the case, so this is it!
1779                                return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1780                            }
1781                            top.deliverNewIntentLocked(callingUid, r.intent);
1782                            return ActivityManager.START_DELIVERED_TO_TOP;
1783                        }
1784                    }
1785                }
1786            }
1787
1788        } else {
1789            if (r.resultTo != null) {
1790                r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1791                        r.requestCode, Activity.RESULT_CANCELED, null);
1792            }
1793            ActivityOptions.abort(options);
1794            return ActivityManager.START_CLASS_NOT_FOUND;
1795        }
1796
1797        boolean newTask = false;
1798        boolean keepCurTransition = false;
1799
1800        // Should this be considered a new task?
1801        if (r.resultTo == null && !addingToTask
1802                && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1803            if (isLockTaskModeViolation(reuseTask)) {
1804                Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
1805                return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
1806            }
1807            targetStack = adjustStackFocus(r);
1808            targetStack.moveToFront();
1809            if (reuseTask == null) {
1810                r.setTask(targetStack.createTaskRecord(getNextTaskId(),
1811                        newTaskInfo != null ? newTaskInfo : r.info,
1812                        newTaskIntent != null ? newTaskIntent : intent,
1813                        voiceSession, voiceInteractor, true), null, true);
1814                if (sourceRecord == null) {
1815                    // Launched from a service or notification or task that is finishing.
1816                    r.task.setTaskToReturnTo(isFrontStack(mHomeStack) ?
1817                            mHomeStack.topTask().taskType : RECENTS_ACTIVITY_TYPE);
1818                }
1819                if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1820                        r.task);
1821            } else {
1822                r.setTask(reuseTask, reuseTask, true);
1823            }
1824            newTask = true;
1825            if (!movedHome) {
1826                if ((launchFlags &
1827                        (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1828                        == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1829                    // Caller wants to appear on home activity, so before starting
1830                    // their own activity we will bring home to the front.
1831                    r.task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1832                }
1833            }
1834        } else if (sourceRecord != null) {
1835            TaskRecord sourceTask = sourceRecord.task;
1836            if (isLockTaskModeViolation(sourceTask)) {
1837                Slog.e(TAG, "Attempted Lock Task Mode violation r=" + r);
1838                return ActivityManager.START_RETURN_LOCK_TASK_MODE_VIOLATION;
1839            }
1840            targetStack = sourceTask.stack;
1841            targetStack.moveToFront();
1842            mWindowManager.moveTaskToTop(targetStack.topTask().taskId);
1843            if (!addingToTask &&
1844                    (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1845                // In this case, we are adding the activity to an existing
1846                // task, but the caller has asked to clear that task if the
1847                // activity is already running.
1848                ActivityRecord top = sourceTask.performClearTaskLocked(r, launchFlags);
1849                keepCurTransition = true;
1850                if (top != null) {
1851                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1852                    top.deliverNewIntentLocked(callingUid, r.intent);
1853                    // For paranoia, make sure we have correctly
1854                    // resumed the top activity.
1855                    targetStack.mLastPausedActivity = null;
1856                    if (doResume) {
1857                        targetStack.resumeTopActivityLocked(null);
1858                    }
1859                    ActivityOptions.abort(options);
1860                    return ActivityManager.START_DELIVERED_TO_TOP;
1861                }
1862            } else if (!addingToTask &&
1863                    (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1864                // In this case, we are launching an activity in our own task
1865                // that may already be running somewhere in the history, and
1866                // we want to shuffle it to the front of the stack if so.
1867                final ActivityRecord top = sourceTask.findActivityInHistoryLocked(r);
1868                if (top != null) {
1869                    final TaskRecord task = top.task;
1870                    task.moveActivityToFrontLocked(top);
1871                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
1872                    top.updateOptionsLocked(options);
1873                    top.deliverNewIntentLocked(callingUid, r.intent);
1874                    targetStack.mLastPausedActivity = null;
1875                    if (doResume) {
1876                        targetStack.resumeTopActivityLocked(null);
1877                    }
1878                    return ActivityManager.START_DELIVERED_TO_TOP;
1879                }
1880            }
1881            // An existing activity is starting this new activity, so we want
1882            // to keep the new one in the same task as the one that is starting
1883            // it.
1884            r.setTask(sourceTask, sourceRecord.thumbHolder, false);
1885            if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1886                    + " in existing task " + r.task + " from source " + sourceRecord);
1887
1888        } else {
1889            // This not being started from an existing activity, and not part
1890            // of a new task...  just put it in the top task, though these days
1891            // this case should never happen.
1892            targetStack = adjustStackFocus(r);
1893            targetStack.moveToFront();
1894            ActivityRecord prev = targetStack.topActivity();
1895            r.setTask(prev != null ? prev.task
1896                    : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, null, null, true),
1897                    null, true);
1898            mWindowManager.moveTaskToTop(r.task.taskId);
1899            if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1900                    + " in new guessed " + r.task);
1901        }
1902
1903        mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1904                intent, r.getUriPermissionsLocked());
1905
1906        if (newTask) {
1907            EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1908        }
1909        ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
1910        targetStack.mLastPausedActivity = null;
1911        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
1912        mService.setFocusedActivityLocked(r);
1913        return ActivityManager.START_SUCCESS;
1914    }
1915
1916    void acquireLaunchWakelock() {
1917        if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
1918            throw new IllegalStateException("Calling must be system uid");
1919        }
1920        mLaunchingActivity.acquire();
1921        if (!mHandler.hasMessages(LAUNCH_TIMEOUT_MSG)) {
1922            // To be safe, don't allow the wake lock to be held for too long.
1923            mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
1924        }
1925    }
1926
1927    // Checked.
1928    final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
1929            Configuration config) {
1930        if (localLOGV) Slog.v(TAG, "Activity idle: " + token);
1931
1932        ArrayList<ActivityRecord> stops = null;
1933        ArrayList<ActivityRecord> finishes = null;
1934        ArrayList<UserStartedState> startingUsers = null;
1935        int NS = 0;
1936        int NF = 0;
1937        boolean booting = false;
1938        boolean enableScreen = false;
1939        boolean activityRemoved = false;
1940
1941        ActivityRecord r = ActivityRecord.forToken(token);
1942        if (r != null) {
1943            if (DEBUG_IDLE) Slog.d(TAG, "activityIdleInternalLocked: Callers=" +
1944                    Debug.getCallers(4));
1945            mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
1946            r.finishLaunchTickingLocked();
1947            if (fromTimeout) {
1948                reportActivityLaunchedLocked(fromTimeout, r, -1, -1);
1949            }
1950
1951            // This is a hack to semi-deal with a race condition
1952            // in the client where it can be constructed with a
1953            // newer configuration from when we asked it to launch.
1954            // We'll update with whatever configuration it now says
1955            // it used to launch.
1956            if (config != null) {
1957                r.configuration = config;
1958            }
1959
1960            // We are now idle.  If someone is waiting for a thumbnail from
1961            // us, we can now deliver.
1962            r.idle = true;
1963
1964            //Slog.i(TAG, "IDLE: mBooted=" + mBooted + ", fromTimeout=" + fromTimeout);
1965            if (!mService.mBooted && isFrontStack(r.task.stack)) {
1966                mService.mBooted = true;
1967                enableScreen = true;
1968            }
1969        }
1970
1971        if (allResumedActivitiesIdle()) {
1972            if (r != null) {
1973                mService.scheduleAppGcsLocked();
1974            }
1975
1976            if (mLaunchingActivity.isHeld()) {
1977                mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
1978                if (VALIDATE_WAKE_LOCK_CALLER &&
1979                        Binder.getCallingUid() != Process.myUid()) {
1980                    throw new IllegalStateException("Calling must be system uid");
1981                }
1982                mLaunchingActivity.release();
1983            }
1984            ensureActivitiesVisibleLocked(null, 0);
1985        }
1986
1987        // Atomically retrieve all of the other things to do.
1988        stops = processStoppingActivitiesLocked(true);
1989        NS = stops != null ? stops.size() : 0;
1990        if ((NF=mFinishingActivities.size()) > 0) {
1991            finishes = new ArrayList<ActivityRecord>(mFinishingActivities);
1992            mFinishingActivities.clear();
1993        }
1994
1995        if (isFrontStack(mHomeStack)) {
1996            booting = mService.mBooting;
1997            mService.mBooting = false;
1998        }
1999
2000        if (mStartingUsers.size() > 0) {
2001            startingUsers = new ArrayList<UserStartedState>(mStartingUsers);
2002            mStartingUsers.clear();
2003        }
2004
2005        // Stop any activities that are scheduled to do so but have been
2006        // waiting for the next one to start.
2007        for (int i = 0; i < NS; i++) {
2008            r = stops.get(i);
2009            final ActivityStack stack = r.task.stack;
2010            if (r.finishing) {
2011                stack.finishCurrentActivityLocked(r, ActivityStack.FINISH_IMMEDIATELY, false);
2012            } else {
2013                stack.stopActivityLocked(r);
2014            }
2015        }
2016
2017        // Finish any activities that are scheduled to do so but have been
2018        // waiting for the next one to start.
2019        for (int i = 0; i < NF; i++) {
2020            r = finishes.get(i);
2021            activityRemoved |= r.task.stack.destroyActivityLocked(r, true, false, "finish-idle");
2022        }
2023
2024        if (booting) {
2025            mService.finishBooting();
2026        } else {
2027            // Complete user switch
2028            if (startingUsers != null) {
2029                for (int i = 0; i < startingUsers.size(); i++) {
2030                    mService.finishUserSwitch(startingUsers.get(i));
2031                }
2032            }
2033            // Complete starting up of background users
2034            if (mStartingBackgroundUsers.size() > 0) {
2035                startingUsers = new ArrayList<UserStartedState>(mStartingBackgroundUsers);
2036                mStartingBackgroundUsers.clear();
2037                for (int i = 0; i < startingUsers.size(); i++) {
2038                    mService.finishUserBoot(startingUsers.get(i));
2039                }
2040            }
2041        }
2042
2043        mService.trimApplications();
2044        //dump();
2045        //mWindowManager.dump();
2046
2047        if (enableScreen) {
2048            mService.enableScreenAfterBoot();
2049        }
2050
2051        if (activityRemoved) {
2052            resumeTopActivitiesLocked();
2053        }
2054
2055        return r;
2056    }
2057
2058    boolean handleAppDiedLocked(ProcessRecord app) {
2059        boolean hasVisibleActivities = false;
2060        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2061            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2062            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2063                hasVisibleActivities |= stacks.get(stackNdx).handleAppDiedLocked(app);
2064            }
2065        }
2066        return hasVisibleActivities;
2067    }
2068
2069    void closeSystemDialogsLocked() {
2070        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2071            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2072            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2073                stacks.get(stackNdx).closeSystemDialogsLocked();
2074            }
2075        }
2076    }
2077
2078    void removeUserLocked(int userId) {
2079        mUserStackInFront.delete(userId);
2080    }
2081
2082    /**
2083     * @return true if some activity was finished (or would have finished if doit were true).
2084     */
2085    boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
2086        boolean didSomething = false;
2087        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2088            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2089            final int numStacks = stacks.size();
2090            for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2091                final ActivityStack stack = stacks.get(stackNdx);
2092                if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
2093                    didSomething = true;
2094                }
2095            }
2096        }
2097        return didSomething;
2098    }
2099
2100    void updatePreviousProcessLocked(ActivityRecord r) {
2101        // Now that this process has stopped, we may want to consider
2102        // it to be the previous app to try to keep around in case
2103        // the user wants to return to it.
2104
2105        // First, found out what is currently the foreground app, so that
2106        // we don't blow away the previous app if this activity is being
2107        // hosted by the process that is actually still the foreground.
2108        ProcessRecord fgApp = null;
2109        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2110            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2111            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2112                final ActivityStack stack = stacks.get(stackNdx);
2113                if (isFrontStack(stack)) {
2114                    if (stack.mResumedActivity != null) {
2115                        fgApp = stack.mResumedActivity.app;
2116                    } else if (stack.mPausingActivity != null) {
2117                        fgApp = stack.mPausingActivity.app;
2118                    }
2119                    break;
2120                }
2121            }
2122        }
2123
2124        // Now set this one as the previous process, only if that really
2125        // makes sense to.
2126        if (r.app != null && fgApp != null && r.app != fgApp
2127                && r.lastVisibleTime > mService.mPreviousProcessVisibleTime
2128                && r.app != mService.mHomeProcess) {
2129            mService.mPreviousProcess = r.app;
2130            mService.mPreviousProcessVisibleTime = r.lastVisibleTime;
2131        }
2132    }
2133
2134    boolean resumeTopActivitiesLocked() {
2135        return resumeTopActivitiesLocked(null, null, null);
2136    }
2137
2138    boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
2139            Bundle targetOptions) {
2140        if (targetStack == null) {
2141            targetStack = getFocusedStack();
2142        }
2143        // Do targetStack first.
2144        boolean result = false;
2145        if (isFrontStack(targetStack)) {
2146            result = targetStack.resumeTopActivityLocked(target, targetOptions);
2147        }
2148        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2149            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2150            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2151                final ActivityStack stack = stacks.get(stackNdx);
2152                if (stack == targetStack) {
2153                    // Already started above.
2154                    continue;
2155                }
2156                if (isFrontStack(stack)) {
2157                    stack.resumeTopActivityLocked(null);
2158                }
2159            }
2160        }
2161        return result;
2162    }
2163
2164    void finishTopRunningActivityLocked(ProcessRecord app) {
2165        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2166            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2167            final int numStacks = stacks.size();
2168            for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2169                final ActivityStack stack = stacks.get(stackNdx);
2170                stack.finishTopRunningActivityLocked(app);
2171            }
2172        }
2173    }
2174
2175    void findTaskToMoveToFrontLocked(TaskRecord task, int flags, Bundle options) {
2176        if ((flags & ActivityManager.MOVE_TASK_NO_USER_ACTION) == 0) {
2177            mUserLeaving = true;
2178        }
2179        if ((flags & ActivityManager.MOVE_TASK_WITH_HOME) != 0) {
2180            // Caller wants the home activity moved with it.  To accomplish this,
2181            // we'll just indicate that this task returns to the home task.
2182            task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
2183        }
2184        task.stack.moveTaskToFrontLocked(task, null, options);
2185        if (DEBUG_STACK) Slog.d(TAG, "findTaskToMoveToFront: moved to front of stack="
2186                + task.stack);
2187    }
2188
2189    ActivityStack getStack(int stackId) {
2190        ActivityContainer activityContainer = mActivityContainers.get(stackId);
2191        if (activityContainer != null) {
2192            return activityContainer.mStack;
2193        }
2194        return null;
2195    }
2196
2197    ArrayList<ActivityStack> getStacks() {
2198        ArrayList<ActivityStack> allStacks = new ArrayList<ActivityStack>();
2199        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2200            allStacks.addAll(mActivityDisplays.valueAt(displayNdx).mStacks);
2201        }
2202        return allStacks;
2203    }
2204
2205    IBinder getHomeActivityToken() {
2206        final ArrayList<TaskRecord> tasks = mHomeStack.getAllTasks();
2207        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
2208            final TaskRecord task = tasks.get(taskNdx);
2209            if (task.isHomeTask()) {
2210                final ArrayList<ActivityRecord> activities = task.mActivities;
2211                for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
2212                    final ActivityRecord r = activities.get(activityNdx);
2213                    if (r.isHomeActivity()) {
2214                        return r.appToken;
2215                    }
2216                }
2217            }
2218        }
2219        return null;
2220    }
2221
2222    ActivityContainer createActivityContainer(ActivityRecord parentActivity,
2223            IActivityContainerCallback callback) {
2224        ActivityContainer activityContainer = new VirtualActivityContainer(parentActivity, callback);
2225        mActivityContainers.put(activityContainer.mStackId, activityContainer);
2226        parentActivity.mChildContainers.add(activityContainer);
2227        return activityContainer;
2228    }
2229
2230    void removeChildActivityContainers(ActivityRecord parentActivity) {
2231        final ArrayList<ActivityContainer> childStacks = parentActivity.mChildContainers;
2232        for (int containerNdx = childStacks.size() - 1; containerNdx >= 0; --containerNdx) {
2233            ActivityContainer container = childStacks.remove(containerNdx);
2234            container.release();
2235        }
2236    }
2237
2238    void deleteActivityContainer(IActivityContainer container) {
2239        ActivityContainer activityContainer = (ActivityContainer)container;
2240        if (activityContainer != null) {
2241            activityContainer.mStack.finishAllActivitiesLocked();
2242            final ActivityRecord parent = activityContainer.mParentActivity;
2243            if (parent != null) {
2244                parent.mChildContainers.remove(activityContainer);
2245            }
2246            final int stackId = activityContainer.mStackId;
2247            mActivityContainers.remove(stackId);
2248            mWindowManager.removeStack(stackId);
2249        }
2250    }
2251
2252    private int createStackOnDisplay(int stackId, int displayId) {
2253        ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
2254        if (activityDisplay == null) {
2255            return -1;
2256        }
2257
2258        ActivityContainer activityContainer = new ActivityContainer(stackId);
2259        mActivityContainers.put(stackId, activityContainer);
2260        activityContainer.attachToDisplayLocked(activityDisplay);
2261        return stackId;
2262    }
2263
2264    int getNextStackId() {
2265        while (true) {
2266            if (++mLastStackId <= HOME_STACK_ID) {
2267                mLastStackId = HOME_STACK_ID + 1;
2268            }
2269            if (getStack(mLastStackId) == null) {
2270                break;
2271            }
2272        }
2273        return mLastStackId;
2274    }
2275
2276    void createStackForRestoredTaskHistory(ArrayList<TaskRecord> tasks) {
2277        int stackId = createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY);
2278        final ActivityStack stack = getStack(stackId);
2279        for (int taskNdx = tasks.size() - 1; taskNdx >= 0; --taskNdx) {
2280            final TaskRecord task = tasks.get(taskNdx);
2281            stack.addTask(task, false, false);
2282            final int taskId = task.taskId;
2283            final ArrayList<ActivityRecord> activities = task.mActivities;
2284            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
2285                final ActivityRecord r = activities.get(activityNdx);
2286                mWindowManager.addAppToken(0, r.appToken, taskId, stackId,
2287                        r.info.screenOrientation, r.fullscreen,
2288                        (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
2289                        r.userId, r.info.configChanges);
2290            }
2291            mWindowManager.addTask(taskId, stackId, false);
2292        }
2293        resumeHomeStackTask(HOME_ACTIVITY_TYPE, null);
2294    }
2295
2296    void moveTaskToStack(int taskId, int stackId, boolean toTop) {
2297        final TaskRecord task = anyTaskForIdLocked(taskId);
2298        if (task == null) {
2299            return;
2300        }
2301        final ActivityStack stack = getStack(stackId);
2302        if (stack == null) {
2303            Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
2304            return;
2305        }
2306        task.stack.removeTask(task);
2307        stack.addTask(task, toTop, true);
2308        mWindowManager.addTask(taskId, stackId, toTop);
2309        resumeTopActivitiesLocked();
2310    }
2311
2312    ActivityRecord findTaskLocked(ActivityRecord r) {
2313        if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + r);
2314        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2315            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2316            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2317                final ActivityStack stack = stacks.get(stackNdx);
2318                if (!r.isApplicationActivity() && !stack.isHomeStack()) {
2319                    if (DEBUG_TASKS) Slog.d(TAG, "Skipping stack: " + stack);
2320                    continue;
2321                }
2322                final ActivityRecord ar = stack.findTaskLocked(r);
2323                if (ar != null) {
2324                    return ar;
2325                }
2326            }
2327        }
2328        if (DEBUG_TASKS) Slog.d(TAG, "No task found");
2329        return null;
2330    }
2331
2332    ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
2333        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2334            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2335            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2336                final ActivityRecord ar = stacks.get(stackNdx).findActivityLocked(intent, info);
2337                if (ar != null) {
2338                    return ar;
2339                }
2340            }
2341        }
2342        return null;
2343    }
2344
2345    void goingToSleepLocked() {
2346        scheduleSleepTimeout();
2347        if (!mGoingToSleep.isHeld()) {
2348            mGoingToSleep.acquire();
2349            if (mLaunchingActivity.isHeld()) {
2350                if (VALIDATE_WAKE_LOCK_CALLER && Binder.getCallingUid() != Process.myUid()) {
2351                    throw new IllegalStateException("Calling must be system uid");
2352                }
2353                mLaunchingActivity.release();
2354                mService.mHandler.removeMessages(LAUNCH_TIMEOUT_MSG);
2355            }
2356        }
2357        checkReadyForSleepLocked();
2358    }
2359
2360    boolean shutdownLocked(int timeout) {
2361        goingToSleepLocked();
2362
2363        boolean timedout = false;
2364        final long endTime = System.currentTimeMillis() + timeout;
2365        while (true) {
2366            boolean cantShutdown = false;
2367            for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2368                final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2369                for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2370                    cantShutdown |= stacks.get(stackNdx).checkReadyForSleepLocked();
2371                }
2372            }
2373            if (cantShutdown) {
2374                long timeRemaining = endTime - System.currentTimeMillis();
2375                if (timeRemaining > 0) {
2376                    try {
2377                        mService.wait(timeRemaining);
2378                    } catch (InterruptedException e) {
2379                    }
2380                } else {
2381                    Slog.w(TAG, "Activity manager shutdown timed out");
2382                    timedout = true;
2383                    break;
2384                }
2385            } else {
2386                break;
2387            }
2388        }
2389
2390        // Force checkReadyForSleep to complete.
2391        mSleepTimeout = true;
2392        checkReadyForSleepLocked();
2393
2394        return timedout;
2395    }
2396
2397    void comeOutOfSleepIfNeededLocked() {
2398        removeSleepTimeouts();
2399        if (mGoingToSleep.isHeld()) {
2400            mGoingToSleep.release();
2401        }
2402        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2403            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2404            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2405                final ActivityStack stack = stacks.get(stackNdx);
2406                stack.awakeFromSleepingLocked();
2407                if (isFrontStack(stack)) {
2408                    resumeTopActivitiesLocked();
2409                }
2410            }
2411        }
2412        mGoingToSleepActivities.clear();
2413    }
2414
2415    void activitySleptLocked(ActivityRecord r) {
2416        mGoingToSleepActivities.remove(r);
2417        checkReadyForSleepLocked();
2418    }
2419
2420    void checkReadyForSleepLocked() {
2421        if (!mService.isSleepingOrShuttingDown()) {
2422            // Do not care.
2423            return;
2424        }
2425
2426        if (!mSleepTimeout) {
2427            boolean dontSleep = false;
2428            for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2429                final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2430                for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2431                    dontSleep |= stacks.get(stackNdx).checkReadyForSleepLocked();
2432                }
2433            }
2434
2435            if (mStoppingActivities.size() > 0) {
2436                // Still need to tell some activities to stop; can't sleep yet.
2437                if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to stop "
2438                        + mStoppingActivities.size() + " activities");
2439                scheduleIdleLocked();
2440                dontSleep = true;
2441            }
2442
2443            if (mGoingToSleepActivities.size() > 0) {
2444                // Still need to tell some activities to sleep; can't sleep yet.
2445                if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still need to sleep "
2446                        + mGoingToSleepActivities.size() + " activities");
2447                dontSleep = true;
2448            }
2449
2450            if (dontSleep) {
2451                return;
2452            }
2453        }
2454
2455        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2456            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2457            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2458                stacks.get(stackNdx).goToSleep();
2459            }
2460        }
2461
2462        removeSleepTimeouts();
2463
2464        if (mGoingToSleep.isHeld()) {
2465            mGoingToSleep.release();
2466        }
2467        if (mService.mShuttingDown) {
2468            mService.notifyAll();
2469        }
2470    }
2471
2472    boolean reportResumedActivityLocked(ActivityRecord r) {
2473        final ActivityStack stack = r.task.stack;
2474        if (isFrontStack(stack)) {
2475            mService.updateUsageStats(r, true);
2476        }
2477        if (allResumedActivitiesComplete()) {
2478            ensureActivitiesVisibleLocked(null, 0);
2479            mWindowManager.executeAppTransition();
2480            return true;
2481        }
2482        return false;
2483    }
2484
2485    void handleAppCrashLocked(ProcessRecord app) {
2486        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2487            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2488            final int numStacks = stacks.size();
2489            for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2490                final ActivityStack stack = stacks.get(stackNdx);
2491                stack.handleAppCrashLocked(app);
2492            }
2493        }
2494    }
2495
2496    void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
2497        // First the front stacks. In case any are not fullscreen and are in front of home.
2498        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2499            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2500            final int topStackNdx = stacks.size() - 1;
2501            for (int stackNdx = topStackNdx; stackNdx >= 0; --stackNdx) {
2502                final ActivityStack stack = stacks.get(stackNdx);
2503                stack.ensureActivitiesVisibleLocked(starting, configChanges);
2504            }
2505        }
2506    }
2507
2508    void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
2509        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2510            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2511            final int numStacks = stacks.size();
2512            for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2513                final ActivityStack stack = stacks.get(stackNdx);
2514                stack.scheduleDestroyActivities(app, false, reason);
2515            }
2516        }
2517    }
2518
2519    boolean switchUserLocked(int userId, UserStartedState uss) {
2520        mUserStackInFront.put(mCurrentUser, getFocusedStack().getStackId());
2521        final int restoreStackId = mUserStackInFront.get(userId, HOME_STACK_ID);
2522        mCurrentUser = userId;
2523
2524        mStartingUsers.add(uss);
2525        for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
2526            final ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2527            for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2528                final ActivityStack stack = stacks.get(stackNdx);
2529                stack.switchUserLocked(userId);
2530                TaskRecord task = stack.topTask();
2531                if (task != null) {
2532                    mWindowManager.moveTaskToTop(task.taskId);
2533                }
2534            }
2535        }
2536
2537        ActivityStack stack = getStack(restoreStackId);
2538        if (stack == null) {
2539            stack = mHomeStack;
2540        }
2541        final boolean homeInFront = stack.isHomeStack();
2542        if (stack.isOnHomeDisplay()) {
2543            moveHomeStack(homeInFront);
2544            TaskRecord task = stack.topTask();
2545            if (task != null) {
2546                mWindowManager.moveTaskToTop(task.taskId);
2547            }
2548        } else {
2549            // Stack was moved to another display while user was swapped out.
2550            resumeHomeStackTask(HOME_ACTIVITY_TYPE, null);
2551        }
2552        return homeInFront;
2553    }
2554
2555    /**
2556     * Add background users to send boot completed events to.
2557     * @param userId The user being started in the background
2558     * @param uss The state object for the user.
2559     */
2560    public void startBackgroundUserLocked(int userId, UserStartedState uss) {
2561        mStartingBackgroundUsers.add(uss);
2562    }
2563
2564    final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
2565        int N = mStoppingActivities.size();
2566        if (N <= 0) return null;
2567
2568        ArrayList<ActivityRecord> stops = null;
2569
2570        final boolean nowVisible = allResumedActivitiesVisible();
2571        for (int i=0; i<N; i++) {
2572            ActivityRecord s = mStoppingActivities.get(i);
2573            if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
2574                    + nowVisible + " waitingVisible=" + s.waitingVisible
2575                    + " finishing=" + s.finishing);
2576            if (s.waitingVisible && nowVisible) {
2577                mWaitingVisibleActivities.remove(s);
2578                s.waitingVisible = false;
2579                if (s.finishing) {
2580                    // If this activity is finishing, it is sitting on top of
2581                    // everyone else but we now know it is no longer needed...
2582                    // so get rid of it.  Otherwise, we need to go through the
2583                    // normal flow and hide it once we determine that it is
2584                    // hidden by the activities in front of it.
2585                    if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
2586                    mWindowManager.setAppVisibility(s.appToken, false);
2587                }
2588            }
2589            if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
2590                if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
2591                if (stops == null) {
2592                    stops = new ArrayList<ActivityRecord>();
2593                }
2594                stops.add(s);
2595                mStoppingActivities.remove(i);
2596                N--;
2597                i--;
2598            }
2599        }
2600
2601        return stops;
2602    }
2603
2604    void validateTopActivitiesLocked() {
2605        // FIXME
2606/*        for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2607            final ActivityStack stack = stacks.get(stackNdx);
2608            final ActivityRecord r = stack.topRunningActivityLocked(null);
2609            final ActivityState state = r == null ? ActivityState.DESTROYED : r.state;
2610            if (isFrontStack(stack)) {
2611                if (r == null) {
2612                    Slog.e(TAG, "validateTop...: null top activity, stack=" + stack);
2613                } else {
2614                    final ActivityRecord pausing = stack.mPausingActivity;
2615                    if (pausing != null && pausing == r) {
2616                        Slog.e(TAG, "validateTop...: top stack has pausing activity r=" + r +
2617                            " state=" + state);
2618                    }
2619                    if (state != ActivityState.INITIALIZING && state != ActivityState.RESUMED) {
2620                        Slog.e(TAG, "validateTop...: activity in front not resumed r=" + r +
2621                                " state=" + state);
2622                    }
2623                }
2624            } else {
2625                final ActivityRecord resumed = stack.mResumedActivity;
2626                if (resumed != null && resumed == r) {
2627                    Slog.e(TAG, "validateTop...: back stack has resumed activity r=" + r +
2628                        " state=" + state);
2629                }
2630                if (r != null && (state == ActivityState.INITIALIZING
2631                        || state == ActivityState.RESUMED)) {
2632                    Slog.e(TAG, "validateTop...: activity in back resumed r=" + r +
2633                            " state=" + state);
2634                }
2635            }
2636        }
2637*/
2638    }
2639
2640    public void dump(PrintWriter pw, String prefix) {
2641        pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity=");
2642                pw.println(mDismissKeyguardOnNextActivity);
2643        pw.print(prefix); pw.print("mFocusedStack=" + mFocusedStack);
2644                pw.print(" mLastFocusedStack="); pw.println(mLastFocusedStack);
2645        pw.print(prefix); pw.println("mSleepTimeout=" + mSleepTimeout);
2646        pw.print(prefix); pw.println("mCurTaskId=" + mCurTaskId);
2647        pw.print(prefix); pw.println("mUserStackInFront=" + mUserStackInFront);
2648        pw.print(prefix); pw.println("mActivityContainers=" + mActivityContainers);
2649    }
2650
2651    ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
2652        return getFocusedStack().getDumpActivitiesLocked(name);
2653    }
2654
2655    static boolean printThisActivity(PrintWriter pw, ActivityRecord activity, String dumpPackage,
2656            boolean needSep, String prefix) {
2657        if (activity != null) {
2658            if (dumpPackage == null || dumpPackage.equals(activity.packageName)) {
2659                if (needSep) {
2660                    pw.println();
2661                }
2662                pw.print(prefix);
2663                pw.println(activity);
2664                return true;
2665            }
2666        }
2667        return false;
2668    }
2669
2670    boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
2671            boolean dumpClient, String dumpPackage) {
2672        boolean printed = false;
2673        boolean needSep = false;
2674        for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
2675            ActivityDisplay activityDisplay = mActivityDisplays.valueAt(displayNdx);
2676            pw.print("Display #"); pw.println(activityDisplay.mDisplayId);
2677            ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
2678            final int numStacks = stacks.size();
2679            for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2680                final ActivityStack stack = stacks.get(stackNdx);
2681                StringBuilder stackHeader = new StringBuilder(128);
2682                stackHeader.append("  Stack #");
2683                stackHeader.append(stack.mStackId);
2684                stackHeader.append(":");
2685                printed |= stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage,
2686                        needSep, stackHeader.toString());
2687                printed |= dumpHistoryList(fd, pw, stack.mLRUActivities, "    ", "Run", false,
2688                        !dumpAll, false, dumpPackage, true,
2689                        "    Running activities (most recent first):", null);
2690
2691                needSep = printed;
2692                boolean pr = printThisActivity(pw, stack.mPausingActivity, dumpPackage, needSep,
2693                        "    mPausingActivity: ");
2694                if (pr) {
2695                    printed = true;
2696                    needSep = false;
2697                }
2698                pr = printThisActivity(pw, stack.mResumedActivity, dumpPackage, needSep,
2699                        "    mResumedActivity: ");
2700                if (pr) {
2701                    printed = true;
2702                    needSep = false;
2703                }
2704                if (dumpAll) {
2705                    pr = printThisActivity(pw, stack.mLastPausedActivity, dumpPackage, needSep,
2706                            "    mLastPausedActivity: ");
2707                    if (pr) {
2708                        printed = true;
2709                        needSep = true;
2710                    }
2711                    printed |= printThisActivity(pw, stack.mLastNoHistoryActivity, dumpPackage,
2712                            needSep, "    mLastNoHistoryActivity: ");
2713                }
2714                needSep = printed;
2715            }
2716        }
2717
2718        printed |= dumpHistoryList(fd, pw, mFinishingActivities, "  ", "Fin", false, !dumpAll,
2719                false, dumpPackage, true, "  Activities waiting to finish:", null);
2720        printed |= dumpHistoryList(fd, pw, mStoppingActivities, "  ", "Stop", false, !dumpAll,
2721                false, dumpPackage, true, "  Activities waiting to stop:", null);
2722        printed |= dumpHistoryList(fd, pw, mWaitingVisibleActivities, "  ", "Wait", false, !dumpAll,
2723                false, dumpPackage, true, "  Activities waiting for another to become visible:",
2724                null);
2725        printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, "  ", "Sleep", false, !dumpAll,
2726                false, dumpPackage, true, "  Activities waiting to sleep:", null);
2727        printed |= dumpHistoryList(fd, pw, mGoingToSleepActivities, "  ", "Sleep", false, !dumpAll,
2728                false, dumpPackage, true, "  Activities waiting to sleep:", null);
2729
2730        return printed;
2731    }
2732
2733    static boolean dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
2734            String prefix, String label, boolean complete, boolean brief, boolean client,
2735            String dumpPackage, boolean needNL, String header1, String header2) {
2736        TaskRecord lastTask = null;
2737        String innerPrefix = null;
2738        String[] args = null;
2739        boolean printed = false;
2740        for (int i=list.size()-1; i>=0; i--) {
2741            final ActivityRecord r = list.get(i);
2742            if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
2743                continue;
2744            }
2745            if (innerPrefix == null) {
2746                innerPrefix = prefix + "      ";
2747                args = new String[0];
2748            }
2749            printed = true;
2750            final boolean full = !brief && (complete || !r.isInHistory());
2751            if (needNL) {
2752                pw.println("");
2753                needNL = false;
2754            }
2755            if (header1 != null) {
2756                pw.println(header1);
2757                header1 = null;
2758            }
2759            if (header2 != null) {
2760                pw.println(header2);
2761                header2 = null;
2762            }
2763            if (lastTask != r.task) {
2764                lastTask = r.task;
2765                pw.print(prefix);
2766                pw.print(full ? "* " : "  ");
2767                pw.println(lastTask);
2768                if (full) {
2769                    lastTask.dump(pw, prefix + "  ");
2770                } else if (complete) {
2771                    // Complete + brief == give a summary.  Isn't that obvious?!?
2772                    if (lastTask.intent != null) {
2773                        pw.print(prefix); pw.print("  ");
2774                                pw.println(lastTask.intent.toInsecureStringWithClip());
2775                    }
2776                }
2777            }
2778            pw.print(prefix); pw.print(full ? "  * " : "    "); pw.print(label);
2779            pw.print(" #"); pw.print(i); pw.print(": ");
2780            pw.println(r);
2781            if (full) {
2782                r.dump(pw, innerPrefix);
2783            } else if (complete) {
2784                // Complete + brief == give a summary.  Isn't that obvious?!?
2785                pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
2786                if (r.app != null) {
2787                    pw.print(innerPrefix); pw.println(r.app);
2788                }
2789            }
2790            if (client && r.app != null && r.app.thread != null) {
2791                // flush anything that is already in the PrintWriter since the thread is going
2792                // to write to the file descriptor directly
2793                pw.flush();
2794                try {
2795                    TransferPipe tp = new TransferPipe();
2796                    try {
2797                        r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
2798                                r.appToken, innerPrefix, args);
2799                        // Short timeout, since blocking here can
2800                        // deadlock with the application.
2801                        tp.go(fd, 2000);
2802                    } finally {
2803                        tp.kill();
2804                    }
2805                } catch (IOException e) {
2806                    pw.println(innerPrefix + "Failure while dumping the activity: " + e);
2807                } catch (RemoteException e) {
2808                    pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
2809                }
2810                needNL = true;
2811            }
2812        }
2813        return printed;
2814    }
2815
2816    void scheduleIdleTimeoutLocked(ActivityRecord next) {
2817        if (DEBUG_IDLE) Slog.d(TAG, "scheduleIdleTimeoutLocked: Callers=" + Debug.getCallers(4));
2818        Message msg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG, next);
2819        mHandler.sendMessageDelayed(msg, IDLE_TIMEOUT);
2820    }
2821
2822    final void scheduleIdleLocked() {
2823        mHandler.sendEmptyMessage(IDLE_NOW_MSG);
2824    }
2825
2826    void removeTimeoutsForActivityLocked(ActivityRecord r) {
2827        if (DEBUG_IDLE) Slog.d(TAG, "removeTimeoutsForActivity: Callers=" + Debug.getCallers(4));
2828        mHandler.removeMessages(IDLE_TIMEOUT_MSG, r);
2829    }
2830
2831    final void scheduleResumeTopActivities() {
2832        if (!mHandler.hasMessages(RESUME_TOP_ACTIVITY_MSG)) {
2833            mHandler.sendEmptyMessage(RESUME_TOP_ACTIVITY_MSG);
2834        }
2835    }
2836
2837    void removeSleepTimeouts() {
2838        mSleepTimeout = false;
2839        mHandler.removeMessages(SLEEP_TIMEOUT_MSG);
2840    }
2841
2842    final void scheduleSleepTimeout() {
2843        removeSleepTimeouts();
2844        mHandler.sendEmptyMessageDelayed(SLEEP_TIMEOUT_MSG, SLEEP_TIMEOUT);
2845    }
2846
2847    @Override
2848    public void onDisplayAdded(int displayId) {
2849        mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_ADDED, displayId, 0));
2850    }
2851
2852    @Override
2853    public void onDisplayRemoved(int displayId) {
2854        mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_REMOVED, displayId, 0));
2855    }
2856
2857    @Override
2858    public void onDisplayChanged(int displayId) {
2859        mHandler.sendMessage(mHandler.obtainMessage(HANDLE_DISPLAY_CHANGED, displayId, 0));
2860    }
2861
2862    public void handleDisplayAddedLocked(int displayId) {
2863        boolean newDisplay;
2864        synchronized (mService) {
2865            newDisplay = mActivityDisplays.get(displayId) == null;
2866            if (newDisplay) {
2867                ActivityDisplay activityDisplay = new ActivityDisplay(displayId);
2868                mActivityDisplays.put(displayId, activityDisplay);
2869            }
2870        }
2871        if (newDisplay) {
2872            mWindowManager.onDisplayAdded(displayId);
2873        }
2874    }
2875
2876    public void handleDisplayRemovedLocked(int displayId) {
2877        synchronized (mService) {
2878            ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
2879            if (activityDisplay != null) {
2880                ArrayList<ActivityStack> stacks = activityDisplay.mStacks;
2881                for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {
2882                    stacks.get(stackNdx).mActivityContainer.detachLocked();
2883                }
2884                mActivityDisplays.remove(displayId);
2885            }
2886        }
2887        mWindowManager.onDisplayRemoved(displayId);
2888    }
2889
2890    public void handleDisplayChangedLocked(int displayId) {
2891        synchronized (mService) {
2892            ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
2893            if (activityDisplay != null) {
2894                // TODO: Update the bounds.
2895            }
2896        }
2897        mWindowManager.onDisplayChanged(displayId);
2898    }
2899
2900    StackInfo getStackInfo(ActivityStack stack) {
2901        StackInfo info = new StackInfo();
2902        mWindowManager.getStackBounds(stack.mStackId, info.bounds);
2903        info.displayId = Display.DEFAULT_DISPLAY;
2904        info.stackId = stack.mStackId;
2905
2906        ArrayList<TaskRecord> tasks = stack.getAllTasks();
2907        final int numTasks = tasks.size();
2908        int[] taskIds = new int[numTasks];
2909        String[] taskNames = new String[numTasks];
2910        for (int i = 0; i < numTasks; ++i) {
2911            final TaskRecord task = tasks.get(i);
2912            taskIds[i] = task.taskId;
2913            taskNames[i] = task.origActivity != null ? task.origActivity.flattenToString()
2914                    : task.realActivity != null ? task.realActivity.flattenToString()
2915                    : task.getTopActivity() != null ? task.getTopActivity().packageName
2916                    : "unknown";
2917        }
2918        info.taskIds = taskIds;
2919        info.taskNames = taskNames;
2920        return info;
2921    }
2922
2923    StackInfo getStackInfoLocked(int stackId) {
2924        ActivityStack stack = getStack(stackId);
2925        if (stack != null) {
2926            return getStackInfo(stack);
2927        }
2928        return null;
2929    }
2930
2931    ArrayList<StackInfo> getAllStackInfosLocked() {
2932        ArrayList<StackInfo> list = new ArrayList<StackInfo>();
2933        for (int displayNdx = 0; displayNdx < mActivityDisplays.size(); ++displayNdx) {
2934            ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
2935            for (int ndx = stacks.size() - 1; ndx >= 0; --ndx) {
2936                list.add(getStackInfo(stacks.get(ndx)));
2937            }
2938        }
2939        return list;
2940    }
2941
2942    void setLockTaskModeLocked(TaskRecord task) {
2943        if (task == null) {
2944            // Take out of lock task mode.
2945            mLockTaskModeTask = null;
2946            return;
2947        }
2948        if (isLockTaskModeViolation(task)) {
2949            Slog.e(TAG, "setLockTaskMode: Attempt to start a second Lock Task Mode task.");
2950            return;
2951        }
2952        mLockTaskModeTask = task;
2953        findTaskToMoveToFrontLocked(task, 0, null);
2954        resumeTopActivitiesLocked();
2955    }
2956
2957    boolean isLockTaskModeViolation(TaskRecord task) {
2958        return mLockTaskModeTask != null && mLockTaskModeTask != task;
2959    }
2960
2961    void endLockTaskModeIfTaskEnding(TaskRecord task) {
2962        if (mLockTaskModeTask != null && mLockTaskModeTask == task) {
2963            mLockTaskModeTask = null;
2964        }
2965    }
2966
2967    boolean isInLockTaskMode() {
2968        return mLockTaskModeTask != null;
2969    }
2970
2971    private final class ActivityStackSupervisorHandler extends Handler {
2972
2973        public ActivityStackSupervisorHandler(Looper looper) {
2974            super(looper);
2975        }
2976
2977        void activityIdleInternal(ActivityRecord r) {
2978            synchronized (mService) {
2979                activityIdleInternalLocked(r != null ? r.appToken : null, true, null);
2980            }
2981        }
2982
2983        @Override
2984        public void handleMessage(Message msg) {
2985            switch (msg.what) {
2986                case IDLE_TIMEOUT_MSG: {
2987                    if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_TIMEOUT_MSG: r=" + msg.obj);
2988                    if (mService.mDidDexOpt) {
2989                        mService.mDidDexOpt = false;
2990                        Message nmsg = mHandler.obtainMessage(IDLE_TIMEOUT_MSG);
2991                        nmsg.obj = msg.obj;
2992                        mHandler.sendMessageDelayed(nmsg, IDLE_TIMEOUT);
2993                        return;
2994                    }
2995                    // We don't at this point know if the activity is fullscreen,
2996                    // so we need to be conservative and assume it isn't.
2997                    activityIdleInternal((ActivityRecord)msg.obj);
2998                } break;
2999                case IDLE_NOW_MSG: {
3000                    if (DEBUG_IDLE) Slog.d(TAG, "handleMessage: IDLE_NOW_MSG: r=" + msg.obj);
3001                    activityIdleInternal((ActivityRecord)msg.obj);
3002                } break;
3003                case RESUME_TOP_ACTIVITY_MSG: {
3004                    synchronized (mService) {
3005                        resumeTopActivitiesLocked();
3006                    }
3007                } break;
3008                case SLEEP_TIMEOUT_MSG: {
3009                    synchronized (mService) {
3010                        if (mService.isSleepingOrShuttingDown()) {
3011                            Slog.w(TAG, "Sleep timeout!  Sleeping now.");
3012                            mSleepTimeout = true;
3013                            checkReadyForSleepLocked();
3014                        }
3015                    }
3016                } break;
3017                case LAUNCH_TIMEOUT_MSG: {
3018                    if (mService.mDidDexOpt) {
3019                        mService.mDidDexOpt = false;
3020                        mHandler.sendEmptyMessageDelayed(LAUNCH_TIMEOUT_MSG, LAUNCH_TIMEOUT);
3021                        return;
3022                    }
3023                    synchronized (mService) {
3024                        if (mLaunchingActivity.isHeld()) {
3025                            Slog.w(TAG, "Launch timeout has expired, giving up wake lock!");
3026                            if (VALIDATE_WAKE_LOCK_CALLER
3027                                    && Binder.getCallingUid() != Process.myUid()) {
3028                                throw new IllegalStateException("Calling must be system uid");
3029                            }
3030                            mLaunchingActivity.release();
3031                        }
3032                    }
3033                } break;
3034                case HANDLE_DISPLAY_ADDED: {
3035                    handleDisplayAddedLocked(msg.arg1);
3036                } break;
3037                case HANDLE_DISPLAY_CHANGED: {
3038                    handleDisplayChangedLocked(msg.arg1);
3039                } break;
3040                case HANDLE_DISPLAY_REMOVED: {
3041                    handleDisplayRemovedLocked(msg.arg1);
3042                } break;
3043                case CONTAINER_CALLBACK_VISIBILITY: {
3044                    final ActivityContainer container = (ActivityContainer) msg.obj;
3045                    try {
3046                        // We only send this message if mCallback is non-null.
3047                        container.mCallback.setVisible(container.asBinder(), msg.arg1 == 1);
3048                    } catch (RemoteException e) {
3049                    }
3050                }
3051            }
3052        }
3053    }
3054
3055    class ActivityContainer extends android.app.IActivityContainer.Stub {
3056        final static int FORCE_NEW_TASK_FLAGS = Intent.FLAG_ACTIVITY_NEW_TASK |
3057                Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
3058        final int mStackId;
3059        IActivityContainerCallback mCallback = null;
3060        final ActivityStack mStack;
3061        ActivityRecord mParentActivity = null;
3062        String mIdString;
3063
3064        boolean mVisible = true;
3065
3066        /** Display this ActivityStack is currently on. Null if not attached to a Display. */
3067        ActivityDisplay mActivityDisplay;
3068
3069        final static int CONTAINER_STATE_HAS_SURFACE = 0;
3070        final static int CONTAINER_STATE_NO_SURFACE = 1;
3071        final static int CONTAINER_STATE_FINISHING = 2;
3072        int mContainerState = CONTAINER_STATE_HAS_SURFACE;
3073
3074        ActivityContainer(int stackId) {
3075            synchronized (mService) {
3076                mStackId = stackId;
3077                mStack = new ActivityStack(this);
3078                mIdString = "ActivtyContainer{" + mStackId + "}";
3079                if (DEBUG_STACK) Slog.d(TAG, "Creating " + this);
3080            }
3081        }
3082
3083        void attachToDisplayLocked(ActivityDisplay activityDisplay) {
3084            if (DEBUG_STACK) Slog.d(TAG, "attachToDisplayLocked: " + this
3085                    + " to display=" + activityDisplay);
3086            mActivityDisplay = activityDisplay;
3087            mStack.mDisplayId = activityDisplay.mDisplayId;
3088            mStack.mStacks = activityDisplay.mStacks;
3089
3090            activityDisplay.attachActivities(mStack);
3091            mWindowManager.attachStack(mStackId, activityDisplay.mDisplayId);
3092        }
3093
3094        @Override
3095        public void attachToDisplay(int displayId) {
3096            synchronized (mService) {
3097                ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
3098                if (activityDisplay == null) {
3099                    return;
3100                }
3101                attachToDisplayLocked(activityDisplay);
3102            }
3103        }
3104
3105        @Override
3106        public int getDisplayId() {
3107            if (mActivityDisplay != null) {
3108                return mActivityDisplay.mDisplayId;
3109            }
3110            return -1;
3111        }
3112
3113        @Override
3114        public boolean injectEvent(InputEvent event) {
3115            final long origId = Binder.clearCallingIdentity();
3116            try {
3117                if (mActivityDisplay != null) {
3118                    return mInputManagerInternal.injectInputEvent(event,
3119                            mActivityDisplay.mDisplayId,
3120                            InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);
3121                }
3122                return false;
3123            } finally {
3124                Binder.restoreCallingIdentity(origId);
3125            }
3126        }
3127
3128        @Override
3129        public void release() {
3130            mContainerState = CONTAINER_STATE_FINISHING;
3131            mStack.finishAllActivitiesLocked();
3132            detachLocked();
3133            mWindowManager.removeStack(mStackId);
3134        }
3135
3136        private void detachLocked() {
3137            if (DEBUG_STACK) Slog.d(TAG, "detachLocked: " + this + " from display="
3138                    + mActivityDisplay + " Callers=" + Debug.getCallers(2));
3139            if (mActivityDisplay != null) {
3140                mActivityDisplay.detachActivitiesLocked(mStack);
3141                mActivityDisplay = null;
3142                mStack.mDisplayId = -1;
3143                mStack.mStacks = null;
3144                mWindowManager.detachStack(mStackId);
3145            }
3146        }
3147
3148        @Override
3149        public final int startActivity(Intent intent) {
3150            mService.enforceNotIsolatedCaller("ActivityContainer.startActivity");
3151            int userId = mService.handleIncomingUser(Binder.getCallingPid(),
3152                    Binder.getCallingUid(), mCurrentUser, false, true, "ActivityContainer", null);
3153            // TODO: Switch to user app stacks here.
3154            intent.addFlags(FORCE_NEW_TASK_FLAGS);
3155            String mimeType = intent.getType();
3156            if (mimeType == null && intent.getData() != null
3157                    && "content".equals(intent.getData().getScheme())) {
3158                mimeType = mService.getProviderMimeType(intent.getData(), userId);
3159            }
3160            return startActivityMayWait(null, -1, null, intent, mimeType, null, null, null, null, 0, 0, null,
3161                    null, null, null, null, userId, this);
3162        }
3163
3164        @Override
3165        public final int startActivityIntentSender(IIntentSender intentSender) {
3166            mService.enforceNotIsolatedCaller("ActivityContainer.startActivityIntentSender");
3167
3168            if (!(intentSender instanceof PendingIntentRecord)) {
3169                throw new IllegalArgumentException("Bad PendingIntent object");
3170            }
3171
3172            return ((PendingIntentRecord)intentSender).sendInner(0, null, null, null, null, null,
3173                    null, 0, FORCE_NEW_TASK_FLAGS, FORCE_NEW_TASK_FLAGS, null, this);
3174        }
3175
3176        private void checkEmbeddedAllowedInner(Intent intent, String resolvedType) {
3177            int userId = mService.handleIncomingUser(Binder.getCallingPid(),
3178                    Binder.getCallingUid(), mCurrentUser, false, true, "ActivityContainer", null);
3179            if (resolvedType == null) {
3180                resolvedType = intent.getType();
3181                if (resolvedType == null && intent.getData() != null
3182                        && "content".equals(intent.getData().getScheme())) {
3183                    resolvedType = mService.getProviderMimeType(intent.getData(), userId);
3184                }
3185            }
3186            ActivityInfo aInfo = resolveActivity(intent, resolvedType, 0, null, null, userId);
3187            if (aInfo != null && (aInfo.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
3188                throw new SecurityException(
3189                        "Attempt to embed activity that has not set allowEmbedded=\"true\"");
3190            }
3191        }
3192
3193        /** Throw a SecurityException if allowEmbedded is not true */
3194        @Override
3195        public final void checkEmbeddedAllowed(Intent intent) {
3196            checkEmbeddedAllowedInner(intent, null);
3197        }
3198
3199        /** Throw a SecurityException if allowEmbedded is not true */
3200        @Override
3201        public final void checkEmbeddedAllowedIntentSender(IIntentSender intentSender) {
3202            if (!(intentSender instanceof PendingIntentRecord)) {
3203                throw new IllegalArgumentException("Bad PendingIntent object");
3204            }
3205            PendingIntentRecord pendingIntent = (PendingIntentRecord) intentSender;
3206            checkEmbeddedAllowedInner(pendingIntent.key.requestIntent,
3207                    pendingIntent.key.requestResolvedType);
3208        }
3209
3210        @Override
3211        public IBinder asBinder() {
3212            return this;
3213        }
3214
3215        @Override
3216        public void setSurface(Surface surface, int width, int height, int density) {
3217            mService.enforceNotIsolatedCaller("ActivityContainer.attachToSurface");
3218        }
3219
3220        ActivityStackSupervisor getOuter() {
3221            return ActivityStackSupervisor.this;
3222        }
3223
3224        boolean isAttached() {
3225            return mActivityDisplay != null;
3226        }
3227
3228        void getBounds(Point outBounds) {
3229            if (mActivityDisplay != null) {
3230                mActivityDisplay.getBounds(outBounds);
3231            } else {
3232                outBounds.set(0, 0);
3233            }
3234        }
3235
3236        // TODO: Make sure every change to ActivityRecord.visible results in a call to this.
3237        void setVisible(boolean visible) {
3238            if (mVisible != visible) {
3239                mVisible = visible;
3240                if (mCallback != null) {
3241                    mHandler.obtainMessage(CONTAINER_CALLBACK_VISIBILITY, visible ? 1 : 0,
3242                            0 /* unused */, this).sendToTarget();
3243                }
3244            }
3245        }
3246
3247        void setDrawn() {
3248        }
3249
3250        @Override
3251        public String toString() {
3252            return mIdString + (mActivityDisplay == null ? "N" : "A");
3253        }
3254    }
3255
3256    private class VirtualActivityContainer extends ActivityContainer {
3257        Surface mSurface;
3258        boolean mDrawn = false;
3259
3260        VirtualActivityContainer(ActivityRecord parent, IActivityContainerCallback callback) {
3261            super(getNextStackId());
3262            mParentActivity = parent;
3263            mCallback = callback;
3264            mContainerState = CONTAINER_STATE_NO_SURFACE;
3265            mIdString = "VirtualActivtyContainer{" + mStackId + ", parent=" + mParentActivity + "}";
3266        }
3267
3268        @Override
3269        public void setSurface(Surface surface, int width, int height, int density) {
3270            super.setSurface(surface, width, height, density);
3271
3272            synchronized (mService) {
3273                final long origId = Binder.clearCallingIdentity();
3274                try {
3275                    setSurfaceLocked(surface, width, height, density);
3276                } finally {
3277                    Binder.restoreCallingIdentity(origId);
3278                }
3279            }
3280        }
3281
3282        private void setSurfaceLocked(Surface surface, int width, int height, int density) {
3283            if (mContainerState == CONTAINER_STATE_FINISHING) {
3284                return;
3285            }
3286            VirtualActivityDisplay virtualActivityDisplay =
3287                    (VirtualActivityDisplay) mActivityDisplay;
3288            if (virtualActivityDisplay == null) {
3289                virtualActivityDisplay =
3290                        new VirtualActivityDisplay(width, height, density);
3291                mActivityDisplay = virtualActivityDisplay;
3292                mActivityDisplays.put(virtualActivityDisplay.mDisplayId, virtualActivityDisplay);
3293                attachToDisplayLocked(virtualActivityDisplay);
3294            }
3295
3296            if (mSurface != null) {
3297                mSurface.release();
3298            }
3299
3300            mSurface = surface;
3301            if (surface != null) {
3302                mStack.resumeTopActivityLocked(null);
3303            } else {
3304                mContainerState = CONTAINER_STATE_NO_SURFACE;
3305                ((VirtualActivityDisplay) mActivityDisplay).setSurface(null);
3306                if (mStack.mPausingActivity == null && mStack.mResumedActivity != null) {
3307                    mStack.startPausingLocked(false, true);
3308                }
3309            }
3310
3311            setSurfaceIfReady();
3312
3313            if (DEBUG_STACK) Slog.d(TAG, "setSurface: " + this + " to display="
3314                    + virtualActivityDisplay);
3315        }
3316
3317        @Override
3318        boolean isAttached() {
3319            return mSurface != null && super.isAttached();
3320        }
3321
3322        @Override
3323        void setDrawn() {
3324            synchronized (mService) {
3325                mDrawn = true;
3326                setSurfaceIfReady();
3327            }
3328        }
3329
3330        private void setSurfaceIfReady() {
3331            if (DEBUG_STACK) Slog.v(TAG, "setSurfaceIfReady: mDrawn=" + mDrawn +
3332                    " mContainerState=" + mContainerState + " mSurface=" + mSurface);
3333            if (mDrawn && mSurface != null && mContainerState == CONTAINER_STATE_NO_SURFACE) {
3334                ((VirtualActivityDisplay) mActivityDisplay).setSurface(mSurface);
3335                mContainerState = CONTAINER_STATE_HAS_SURFACE;
3336            }
3337        }
3338    }
3339
3340    /** Exactly one of these classes per Display in the system. Capable of holding zero or more
3341     * attached {@link ActivityStack}s */
3342    class ActivityDisplay {
3343        /** Actual Display this object tracks. */
3344        int mDisplayId;
3345        Display mDisplay;
3346        DisplayInfo mDisplayInfo = new DisplayInfo();
3347
3348        /** All of the stacks on this display. Order matters, topmost stack is in front of all other
3349         * stacks, bottommost behind. Accessed directly by ActivityManager package classes */
3350        final ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
3351
3352        ActivityDisplay() {
3353        }
3354
3355        ActivityDisplay(int displayId) {
3356            init(mDisplayManager.getDisplay(displayId));
3357        }
3358
3359        void init(Display display) {
3360            mDisplay = display;
3361            mDisplayId = display.getDisplayId();
3362            mDisplay.getDisplayInfo(mDisplayInfo);
3363        }
3364
3365        void attachActivities(ActivityStack stack) {
3366            if (DEBUG_STACK) Slog.v(TAG, "attachActivities: attaching " + stack + " to displayId="
3367                    + mDisplayId);
3368            mStacks.add(stack);
3369        }
3370
3371        void detachActivitiesLocked(ActivityStack stack) {
3372            if (DEBUG_STACK) Slog.v(TAG, "detachActivitiesLocked: detaching " + stack
3373                    + " from displayId=" + mDisplayId);
3374            mStacks.remove(stack);
3375        }
3376
3377        void getBounds(Point bounds) {
3378            mDisplay.getDisplayInfo(mDisplayInfo);
3379            bounds.x = mDisplayInfo.appWidth;
3380            bounds.y = mDisplayInfo.appHeight;
3381        }
3382
3383        @Override
3384        public String toString() {
3385            return "ActivityDisplay={" + mDisplayId + " numStacks=" + mStacks.size() + "}";
3386        }
3387    }
3388
3389    class VirtualActivityDisplay extends ActivityDisplay {
3390        VirtualDisplay mVirtualDisplay;
3391
3392        VirtualActivityDisplay(int width, int height, int density) {
3393            DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
3394            mVirtualDisplay = dm.createVirtualDisplay(mService.mContext, VIRTUAL_DISPLAY_BASE_NAME,
3395                    width, height, density, null, DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC |
3396                    DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
3397
3398            init(mVirtualDisplay.getDisplay());
3399
3400            mWindowManager.handleDisplayAdded(mDisplayId);
3401        }
3402
3403        void setSurface(Surface surface) {
3404            if (mVirtualDisplay != null) {
3405                mVirtualDisplay.setSurface(surface);
3406            }
3407        }
3408
3409        @Override
3410        void detachActivitiesLocked(ActivityStack stack) {
3411            super.detachActivitiesLocked(stack);
3412            if (mVirtualDisplay != null) {
3413                mVirtualDisplay.release();
3414                mVirtualDisplay = null;
3415            }
3416        }
3417
3418        @Override
3419        public String toString() {
3420            return "VirtualActivityDisplay={" + mDisplayId + "}";
3421        }
3422    }
3423}
3424