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