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