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