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