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