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