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