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