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