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