ActivityStackSupervisor.java revision a9a3fb1da3d3d41f923e87d5b08b35c3e0c1f72e
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_RESULTS;
26import static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
27import static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
28import static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
29import static com.android.server.am.ActivityManagerService.TAG;
30
31import android.app.Activity;
32import android.app.ActivityManager;
33import android.app.ActivityOptions;
34import android.app.AppGlobals;
35import android.app.IApplicationThread;
36import android.app.IThumbnailReceiver;
37import android.app.PendingIntent;
38import android.app.ActivityManager.RunningTaskInfo;
39import android.app.IActivityManager.WaitResult;
40import android.app.ResultInfo;
41import android.content.ComponentName;
42import android.content.Context;
43import android.content.IIntentSender;
44import android.content.Intent;
45import android.content.IntentSender;
46import android.content.pm.ActivityInfo;
47import android.content.pm.ApplicationInfo;
48import android.content.pm.PackageManager;
49import android.content.pm.ResolveInfo;
50import android.content.res.Configuration;
51import android.os.Binder;
52import android.os.Bundle;
53import android.os.IBinder;
54import android.os.Looper;
55import android.os.Message;
56import android.os.ParcelFileDescriptor;
57import android.os.RemoteException;
58import android.os.SystemClock;
59import android.os.UserHandle;
60import android.util.EventLog;
61import android.util.Slog;
62
63import com.android.internal.app.HeavyWeightSwitcherActivity;
64import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
65import com.android.server.am.ActivityStack.ActivityState;
66import com.android.server.wm.StackBox;
67
68import java.io.FileDescriptor;
69import java.io.IOException;
70import java.io.PrintWriter;
71import java.util.ArrayList;
72import java.util.List;
73
74public class ActivityStackSupervisor {
75    static final boolean DEBUG_STACK = ActivityManagerService.DEBUG_STACK;
76
77    static final boolean DEBUG = ActivityManagerService.DEBUG || false;
78    static final boolean DEBUG_ADD_REMOVE = DEBUG || false;
79    static final boolean DEBUG_APP = DEBUG || false;
80    static final boolean DEBUG_SAVED_STATE = DEBUG || false;
81    static final boolean DEBUG_STATES = DEBUG || false;
82
83    public static final int HOME_STACK_ID = 0;
84
85    final ActivityManagerService mService;
86    final Context mContext;
87    final Looper mLooper;
88
89    /** Dismiss the keyguard after the next activity is displayed? */
90    private boolean mDismissKeyguardOnNextActivity = false;
91
92    /** Identifier counter for all ActivityStacks */
93    private int mLastStackId = HOME_STACK_ID;
94
95    /** Task identifier that activities are currently being started in.  Incremented each time a
96     * new task is created. */
97    private int mCurTaskId = 0;
98
99    /** The current user */
100    private int mCurrentUser;
101
102    /** The stack containing the launcher app */
103    private ActivityStack mHomeStack;
104
105    /** The non-home stack currently receiving input or launching the next activity. If home is
106     * in front then mHomeStack overrides mFocusedStack. */
107    private ActivityStack mFocusedStack;
108
109    /** All the non-launcher stacks */
110    private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
111
112    private static final int STACK_STATE_HOME_IN_FRONT = 0;
113    private static final int STACK_STATE_HOME_TO_BACK = 1;
114    private static final int STACK_STATE_HOME_IN_BACK = 2;
115    private static final int STACK_STATE_HOME_TO_FRONT = 3;
116    private int mStackState = STACK_STATE_HOME_IN_FRONT;
117
118    /** List of activities that are waiting for a new activity to become visible before completing
119     * whatever operation they are supposed to do. */
120    final ArrayList<ActivityRecord> mWaitingVisibleActivities = new ArrayList<ActivityRecord>();
121
122    /** List of activities that are ready to be stopped, but waiting for the next activity to
123     * settle down before doing so. */
124    final ArrayList<ActivityRecord> mStoppingActivities = new ArrayList<ActivityRecord>();
125
126    /** Set to indicate whether to issue an onUserLeaving callback when a newly launched activity
127     * is being brought in front of us. */
128    boolean mUserLeaving = false;
129
130    public ActivityStackSupervisor(ActivityManagerService service, Context context,
131            Looper looper) {
132        mService = service;
133        mContext = context;
134        mLooper = looper;
135    }
136
137    void init(int userId) {
138        mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID, this, userId);
139        mStacks.add(mHomeStack);
140    }
141
142    void dismissKeyguard() {
143        if (mDismissKeyguardOnNextActivity) {
144            mDismissKeyguardOnNextActivity = false;
145            mService.mWindowManager.dismissKeyguard();
146        }
147    }
148
149    ActivityStack getTopStack() {
150        switch (mStackState) {
151            case STACK_STATE_HOME_IN_FRONT:
152            case STACK_STATE_HOME_TO_FRONT:
153                return mHomeStack;
154            case STACK_STATE_HOME_IN_BACK:
155            case STACK_STATE_HOME_TO_BACK:
156            default:
157                return mFocusedStack;
158        }
159    }
160
161    ActivityStack getLastStack() {
162        switch (mStackState) {
163            case STACK_STATE_HOME_IN_FRONT:
164            case STACK_STATE_HOME_TO_BACK:
165                return mHomeStack;
166            case STACK_STATE_HOME_TO_FRONT:
167            case STACK_STATE_HOME_IN_BACK:
168            default:
169                return mFocusedStack;
170        }
171    }
172
173    boolean isFrontStack(ActivityStack stack) {
174        return !(stack.isHomeStack() ^ getTopStack().isHomeStack());
175    }
176
177    boolean homeIsInFront() {
178        return isFrontStack(mHomeStack);
179    }
180
181    void moveHomeStack(boolean toFront) {
182        final boolean homeInFront = isFrontStack(mHomeStack);
183        if (homeInFront ^ toFront) {
184            mStackState = homeInFront ? STACK_STATE_HOME_TO_BACK : STACK_STATE_HOME_TO_FRONT;
185        }
186    }
187
188    final void setLaunchHomeTaskNextFlag(ActivityRecord sourceRecord, ActivityRecord r,
189            ActivityStack stack) {
190        if (stack == mHomeStack) {
191            return;
192        }
193        if ((sourceRecord == null && getLastStack() == mHomeStack) ||
194                (sourceRecord != null && sourceRecord.isHomeActivity)) {
195            if (r == null) {
196                r = stack.topRunningActivityLocked(null);
197            }
198            if (r != null && !r.isHomeActivity && r.isRootActivity()) {
199                r.mLaunchHomeTaskNext = true;
200            }
201        }
202    }
203
204    void setDismissKeyguard(boolean dismiss) {
205        mDismissKeyguardOnNextActivity = dismiss;
206    }
207
208    TaskRecord anyTaskForIdLocked(int id) {
209        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
210            ActivityStack stack = mStacks.get(stackNdx);
211            TaskRecord task = stack.taskForIdLocked(id);
212            if (task != null) {
213                return task;
214            }
215        }
216        return null;
217    }
218
219    ActivityRecord isInAnyStackLocked(IBinder token) {
220        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
221            final ActivityRecord r = mStacks.get(stackNdx).isInStackLocked(token);
222            if (r != null) {
223                return r;
224            }
225        }
226        return null;
227    }
228
229    int getNextTaskId() {
230        do {
231            mCurTaskId++;
232            if (mCurTaskId <= 0) {
233                mCurTaskId = 1;
234            }
235        } while (anyTaskForIdLocked(mCurTaskId) != null);
236        return mCurTaskId;
237    }
238
239    void removeTask(TaskRecord task) {
240        final ActivityStack stack = task.stack;
241        if (stack.removeTask(task) && !stack.isHomeStack()) {
242            if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing stack " + stack);
243            mStacks.remove(stack);
244            final int stackId = stack.mStackId;
245            final int nextStackId = mService.mWindowManager.removeStack(stackId);
246            // TODO: Perhaps we need to let the ActivityManager determine the next focus...
247            if (mFocusedStack.mStackId == stackId) {
248                mFocusedStack = nextStackId == HOME_STACK_ID ? null : getStack(nextStackId);
249            }
250        }
251    }
252
253    ActivityRecord resumedAppLocked() {
254        ActivityStack stack = getTopStack();
255        ActivityRecord resumedActivity = stack.mResumedActivity;
256        if (resumedActivity == null || resumedActivity.app == null) {
257            resumedActivity = stack.mPausingActivity;
258            if (resumedActivity == null || resumedActivity.app == null) {
259                resumedActivity = stack.topRunningActivityLocked(null);
260            }
261        }
262        return resumedActivity;
263    }
264
265    boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
266        boolean didSomething = false;
267        final String processName = app.processName;
268        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
269            final ActivityStack stack = mStacks.get(stackNdx);
270            ActivityRecord hr = stack.topRunningActivityLocked(null);
271            if (hr != null) {
272                if (hr.app == null && app.uid == hr.info.applicationInfo.uid
273                        && processName.equals(hr.processName)) {
274                    try {
275                        if (headless) {
276                            Slog.e(TAG, "Starting activities not supported on headless device: "
277                                    + hr);
278                        } else if (realStartActivityLocked(hr, app, true, true)) {
279                            didSomething = true;
280                        }
281                    } catch (Exception e) {
282                        Slog.w(TAG, "Exception in new application when starting activity "
283                              + hr.intent.getComponent().flattenToShortString(), e);
284                        throw e;
285                    }
286                } else {
287                    stack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
288                }
289            }
290        }
291        return didSomething;
292    }
293
294    boolean allResumedActivitiesIdle() {
295        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
296            final ActivityRecord resumedActivity = mStacks.get(stackNdx).mResumedActivity;
297            if (resumedActivity == null || !resumedActivity.idle) {
298                return false;
299            }
300        }
301        return true;
302    }
303
304    boolean allResumedActivitiesComplete() {
305        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
306            final ActivityStack stack = mStacks.get(stackNdx);
307            if (isFrontStack(stack)) {
308                final ActivityRecord r = stack.mResumedActivity;
309                if (r != null && r.state != ActivityState.RESUMED) {
310                    return false;
311                }
312            }
313        }
314        // TODO: Not sure if this should check if all Paused are complete too.
315        switch (mStackState) {
316            case STACK_STATE_HOME_TO_BACK:
317                mStackState = STACK_STATE_HOME_IN_BACK;
318                break;
319            case STACK_STATE_HOME_TO_FRONT:
320                mStackState = STACK_STATE_HOME_IN_FRONT;
321                break;
322        }
323        return true;
324    }
325
326    boolean allResumedActivitiesVisible() {
327        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
328            final ActivityStack stack = mStacks.get(stackNdx);
329            final ActivityRecord r = stack.mResumedActivity;
330            if (r != null && (!r.nowVisible || r.waitingVisible)) {
331                return false;
332            }
333        }
334        return true;
335    }
336
337    boolean allPausedActivitiesComplete() {
338        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
339            final ActivityStack stack = mStacks.get(stackNdx);
340            if (isFrontStack(stack)) {
341                final ActivityRecord r = stack.mLastPausedActivity;
342                if (r != null && r.state != ActivityState.PAUSED
343                        && r.state != ActivityState.STOPPED
344                        && r.state != ActivityState.STOPPING) {
345                    return false;
346                }
347            }
348        }
349        // TODO: Not sure if this should check if all Resumed are complete too.
350        switch (mStackState) {
351            case STACK_STATE_HOME_TO_BACK:
352                mStackState = STACK_STATE_HOME_IN_BACK;
353                break;
354            case STACK_STATE_HOME_TO_FRONT:
355                mStackState = STACK_STATE_HOME_IN_FRONT;
356                break;
357        }
358        return true;
359    }
360
361    ActivityRecord topRunningActivityLocked() {
362        ActivityRecord r = null;
363        if (mFocusedStack != null) {
364            r = mFocusedStack.topRunningActivityLocked(null);
365            if (r != null) {
366                return r;
367            }
368        }
369        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
370            final ActivityStack stack = mStacks.get(stackNdx);
371            if (stack != mFocusedStack && isFrontStack(stack)) {
372                r = stack.topRunningActivityLocked(null);
373                if (r != null) {
374                    return r;
375                }
376            }
377        }
378        return null;
379    }
380
381    void resumeTopActivitiesLocked() {
382        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
383            final ActivityStack stack = mStacks.get(stackNdx);
384            if (isFrontStack(stack)) {
385                stack.resumeTopActivityLocked(null);
386            }
387        }
388    }
389
390    ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
391            PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
392        ActivityRecord r = null;
393        final int numStacks = mStacks.size();
394        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
395            final ActivityStack stack = mStacks.get(stackNdx);
396            final ActivityRecord ar =
397                    stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
398            if (isFrontStack(stack)) {
399                r = ar;
400            }
401        }
402        return r;
403    }
404
405    ActivityInfo resolveActivity(Intent intent, String resolvedType, int startFlags,
406            String profileFile, ParcelFileDescriptor profileFd, int userId) {
407        // Collect information about the target of the Intent.
408        ActivityInfo aInfo;
409        try {
410            ResolveInfo rInfo =
411                AppGlobals.getPackageManager().resolveIntent(
412                        intent, resolvedType,
413                        PackageManager.MATCH_DEFAULT_ONLY
414                                    | ActivityManagerService.STOCK_PM_FLAGS, userId);
415            aInfo = rInfo != null ? rInfo.activityInfo : null;
416        } catch (RemoteException e) {
417            aInfo = null;
418        }
419
420        if (aInfo != null) {
421            // Store the found target back into the intent, because now that
422            // we have it we never want to do this again.  For example, if the
423            // user navigates back to this point in the history, we should
424            // always restart the exact same activity.
425            intent.setComponent(new ComponentName(
426                    aInfo.applicationInfo.packageName, aInfo.name));
427
428            // Don't debug things in the system process
429            if ((startFlags&ActivityManager.START_FLAG_DEBUG) != 0) {
430                if (!aInfo.processName.equals("system")) {
431                    mService.setDebugApp(aInfo.processName, true, false);
432                }
433            }
434
435            if ((startFlags&ActivityManager.START_FLAG_OPENGL_TRACES) != 0) {
436                if (!aInfo.processName.equals("system")) {
437                    mService.setOpenGlTraceApp(aInfo.applicationInfo, aInfo.processName);
438                }
439            }
440
441            if (profileFile != null) {
442                if (!aInfo.processName.equals("system")) {
443                    mService.setProfileApp(aInfo.applicationInfo, aInfo.processName,
444                            profileFile, profileFd,
445                            (startFlags&ActivityManager.START_FLAG_AUTO_STOP_PROFILER) != 0);
446                }
447            }
448        }
449        return aInfo;
450    }
451
452    void startHomeActivity(Intent intent, ActivityInfo aInfo) {
453        moveHomeStack(true);
454        startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
455                null, false, null);
456    }
457
458    final int startActivityMayWait(IApplicationThread caller, int callingUid,
459            String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
460            String resultWho, int requestCode, int startFlags, String profileFile,
461            ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
462            Bundle options, int userId) {
463        // Refuse possible leaked file descriptors
464        if (intent != null && intent.hasFileDescriptors()) {
465            throw new IllegalArgumentException("File descriptors passed in Intent");
466        }
467        boolean componentSpecified = intent.getComponent() != null;
468
469        // Don't modify the client's object!
470        intent = new Intent(intent);
471
472        // Collect information about the target of the Intent.
473        ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
474                profileFile, profileFd, userId);
475
476        synchronized (mService) {
477            int callingPid;
478            if (callingUid >= 0) {
479                callingPid = -1;
480            } else if (caller == null) {
481                callingPid = Binder.getCallingPid();
482                callingUid = Binder.getCallingUid();
483            } else {
484                callingPid = callingUid = -1;
485            }
486
487            final ActivityStack stack = getTopStack();
488            stack.mConfigWillChange = config != null
489                    && mService.mConfiguration.diff(config) != 0;
490            if (DEBUG_CONFIGURATION) Slog.v(TAG,
491                    "Starting activity when config will change = " + stack.mConfigWillChange);
492
493            final long origId = Binder.clearCallingIdentity();
494
495            if (aInfo != null &&
496                    (aInfo.applicationInfo.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
497                // This may be a heavy-weight process!  Check to see if we already
498                // have another, different heavy-weight process running.
499                if (aInfo.processName.equals(aInfo.applicationInfo.packageName)) {
500                    if (mService.mHeavyWeightProcess != null &&
501                            (mService.mHeavyWeightProcess.info.uid != aInfo.applicationInfo.uid ||
502                            !mService.mHeavyWeightProcess.processName.equals(aInfo.processName))) {
503                        int realCallingPid = callingPid;
504                        int realCallingUid = callingUid;
505                        if (caller != null) {
506                            ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
507                            if (callerApp != null) {
508                                realCallingPid = callerApp.pid;
509                                realCallingUid = callerApp.info.uid;
510                            } else {
511                                Slog.w(TAG, "Unable to find app for caller " + caller
512                                      + " (pid=" + realCallingPid + ") when starting: "
513                                      + intent.toString());
514                                ActivityOptions.abort(options);
515                                return ActivityManager.START_PERMISSION_DENIED;
516                            }
517                        }
518
519                        IIntentSender target = mService.getIntentSenderLocked(
520                                ActivityManager.INTENT_SENDER_ACTIVITY, "android",
521                                realCallingUid, userId, null, null, 0, new Intent[] { intent },
522                                new String[] { resolvedType }, PendingIntent.FLAG_CANCEL_CURRENT
523                                | PendingIntent.FLAG_ONE_SHOT, null);
524
525                        Intent newIntent = new Intent();
526                        if (requestCode >= 0) {
527                            // Caller is requesting a result.
528                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_HAS_RESULT, true);
529                        }
530                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_INTENT,
531                                new IntentSender(target));
532                        if (mService.mHeavyWeightProcess.activities.size() > 0) {
533                            ActivityRecord hist = mService.mHeavyWeightProcess.activities.get(0);
534                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_APP,
535                                    hist.packageName);
536                            newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_CUR_TASK,
537                                    hist.task.taskId);
538                        }
539                        newIntent.putExtra(HeavyWeightSwitcherActivity.KEY_NEW_APP,
540                                aInfo.packageName);
541                        newIntent.setFlags(intent.getFlags());
542                        newIntent.setClassName("android",
543                                HeavyWeightSwitcherActivity.class.getName());
544                        intent = newIntent;
545                        resolvedType = null;
546                        caller = null;
547                        callingUid = Binder.getCallingUid();
548                        callingPid = Binder.getCallingPid();
549                        componentSpecified = true;
550                        try {
551                            ResolveInfo rInfo =
552                                AppGlobals.getPackageManager().resolveIntent(
553                                        intent, null,
554                                        PackageManager.MATCH_DEFAULT_ONLY
555                                        | ActivityManagerService.STOCK_PM_FLAGS, userId);
556                            aInfo = rInfo != null ? rInfo.activityInfo : null;
557                            aInfo = mService.getActivityInfoForUser(aInfo, userId);
558                        } catch (RemoteException e) {
559                            aInfo = null;
560                        }
561                    }
562                }
563            }
564
565            int res = startActivityLocked(caller, intent, resolvedType,
566                    aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
567                    callingPackage, startFlags, options, componentSpecified, null);
568
569            if (stack.mConfigWillChange) {
570                // If the caller also wants to switch to a new configuration,
571                // do so now.  This allows a clean switch, as we are waiting
572                // for the current activity to pause (so we will not destroy
573                // it), and have not yet started the next activity.
574                mService.enforceCallingPermission(android.Manifest.permission.CHANGE_CONFIGURATION,
575                        "updateConfiguration()");
576                stack.mConfigWillChange = false;
577                if (DEBUG_CONFIGURATION) Slog.v(TAG,
578                        "Updating to new configuration after starting activity.");
579                mService.updateConfigurationLocked(config, null, false, false);
580            }
581
582            Binder.restoreCallingIdentity(origId);
583
584            if (outResult != null) {
585                outResult.result = res;
586                if (res == ActivityManager.START_SUCCESS) {
587                    stack.mWaitingActivityLaunched.add(outResult);
588                    do {
589                        try {
590                            mService.wait();
591                        } catch (InterruptedException e) {
592                        }
593                    } while (!outResult.timeout && outResult.who == null);
594                } else if (res == ActivityManager.START_TASK_TO_FRONT) {
595                    ActivityRecord r = stack.topRunningActivityLocked(null);
596                    if (r.nowVisible) {
597                        outResult.timeout = false;
598                        outResult.who = new ComponentName(r.info.packageName, r.info.name);
599                        outResult.totalTime = 0;
600                        outResult.thisTime = 0;
601                    } else {
602                        outResult.thisTime = SystemClock.uptimeMillis();
603                        stack.mWaitingActivityVisible.add(outResult);
604                        do {
605                            try {
606                                mService.wait();
607                            } catch (InterruptedException e) {
608                            }
609                        } while (!outResult.timeout && outResult.who == null);
610                    }
611                }
612            }
613
614            return res;
615        }
616    }
617
618    final int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
619            Intent[] intents, String[] resolvedTypes, IBinder resultTo,
620            Bundle options, int userId) {
621        if (intents == null) {
622            throw new NullPointerException("intents is null");
623        }
624        if (resolvedTypes == null) {
625            throw new NullPointerException("resolvedTypes is null");
626        }
627        if (intents.length != resolvedTypes.length) {
628            throw new IllegalArgumentException("intents are length different than resolvedTypes");
629        }
630
631        ActivityRecord[] outActivity = new ActivityRecord[1];
632
633        int callingPid;
634        if (callingUid >= 0) {
635            callingPid = -1;
636        } else if (caller == null) {
637            callingPid = Binder.getCallingPid();
638            callingUid = Binder.getCallingUid();
639        } else {
640            callingPid = callingUid = -1;
641        }
642        final long origId = Binder.clearCallingIdentity();
643        try {
644            synchronized (mService) {
645
646                for (int i=0; i<intents.length; i++) {
647                    Intent intent = intents[i];
648                    if (intent == null) {
649                        continue;
650                    }
651
652                    // Refuse possible leaked file descriptors
653                    if (intent != null && intent.hasFileDescriptors()) {
654                        throw new IllegalArgumentException("File descriptors passed in Intent");
655                    }
656
657                    boolean componentSpecified = intent.getComponent() != null;
658
659                    // Don't modify the client's object!
660                    intent = new Intent(intent);
661
662                    // Collect information about the target of the Intent.
663                    ActivityInfo aInfo = resolveActivity(intent, resolvedTypes[i],
664                            0, null, null, userId);
665                    // TODO: New, check if this is correct
666                    aInfo = mService.getActivityInfoForUser(aInfo, userId);
667
668                    if (aInfo != null &&
669                            (aInfo.applicationInfo.flags & ApplicationInfo.FLAG_CANT_SAVE_STATE)
670                                    != 0) {
671                        throw new IllegalArgumentException(
672                                "FLAG_CANT_SAVE_STATE not supported here");
673                    }
674
675                    Bundle theseOptions;
676                    if (options != null && i == intents.length-1) {
677                        theseOptions = options;
678                    } else {
679                        theseOptions = null;
680                    }
681                    int res = startActivityLocked(caller, intent, resolvedTypes[i],
682                            aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
683                            0, theseOptions, componentSpecified, outActivity);
684                    if (res < 0) {
685                        return res;
686                    }
687
688                    resultTo = outActivity[0] != null ? outActivity[0].appToken : null;
689                }
690            }
691        } finally {
692            Binder.restoreCallingIdentity(origId);
693        }
694
695        return ActivityManager.START_SUCCESS;
696    }
697
698    final boolean realStartActivityLocked(ActivityRecord r,
699            ProcessRecord app, boolean andResume, boolean checkConfig)
700            throws RemoteException {
701
702        r.startFreezingScreenLocked(app, 0);
703        mService.mWindowManager.setAppVisibility(r.appToken, true);
704
705        // schedule launch ticks to collect information about slow apps.
706        r.startLaunchTickingLocked();
707
708        // Have the window manager re-evaluate the orientation of
709        // the screen based on the new activity order.  Note that
710        // as a result of this, it can call back into the activity
711        // manager with a new orientation.  We don't care about that,
712        // because the activity is not currently running so we are
713        // just restarting it anyway.
714        if (checkConfig) {
715            Configuration config = mService.mWindowManager.updateOrientationFromAppTokens(
716                    mService.mConfiguration,
717                    r.mayFreezeScreenLocked(app) ? r.appToken : null);
718            mService.updateConfigurationLocked(config, r, false, false);
719        }
720
721        r.app = app;
722        app.waitingToKill = null;
723        r.launchCount++;
724        r.lastLaunchTime = SystemClock.uptimeMillis();
725
726        if (localLOGV) Slog.v(TAG, "Launching: " + r);
727
728        int idx = app.activities.indexOf(r);
729        if (idx < 0) {
730            app.activities.add(r);
731        }
732        mService.updateLruProcessLocked(app, true);
733
734        final ActivityStack stack = r.task.stack;
735        try {
736            if (app.thread == null) {
737                throw new RemoteException();
738            }
739            List<ResultInfo> results = null;
740            List<Intent> newIntents = null;
741            if (andResume) {
742                results = r.results;
743                newIntents = r.newIntents;
744            }
745            if (DEBUG_SWITCH) Slog.v(TAG, "Launching: " + r
746                    + " icicle=" + r.icicle
747                    + " with results=" + results + " newIntents=" + newIntents
748                    + " andResume=" + andResume);
749            if (andResume) {
750                EventLog.writeEvent(EventLogTags.AM_RESTART_ACTIVITY,
751                        r.userId, System.identityHashCode(r),
752                        r.task.taskId, r.shortComponentName);
753            }
754            if (r.isHomeActivity) {
755                mService.mHomeProcess = app;
756            }
757            mService.ensurePackageDexOpt(r.intent.getComponent().getPackageName());
758            r.sleeping = false;
759            r.forceNewConfig = false;
760            mService.showAskCompatModeDialogLocked(r);
761            r.compat = mService.compatibilityInfoForPackageLocked(r.info.applicationInfo);
762            String profileFile = null;
763            ParcelFileDescriptor profileFd = null;
764            boolean profileAutoStop = false;
765            if (mService.mProfileApp != null && mService.mProfileApp.equals(app.processName)) {
766                if (mService.mProfileProc == null || mService.mProfileProc == app) {
767                    mService.mProfileProc = app;
768                    profileFile = mService.mProfileFile;
769                    profileFd = mService.mProfileFd;
770                    profileAutoStop = mService.mAutoStopProfiler;
771                }
772            }
773            app.hasShownUi = true;
774            app.pendingUiClean = true;
775            if (profileFd != null) {
776                try {
777                    profileFd = profileFd.dup();
778                } catch (IOException e) {
779                    if (profileFd != null) {
780                        try {
781                            profileFd.close();
782                        } catch (IOException o) {
783                        }
784                        profileFd = null;
785                    }
786                }
787            }
788            app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
789                    System.identityHashCode(r), r.info,
790                    new Configuration(mService.mConfiguration),
791                    r.compat, r.icicle, results, newIntents, !andResume,
792                    mService.isNextTransitionForward(), profileFile, profileFd,
793                    profileAutoStop);
794
795            if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
796                // This may be a heavy-weight process!  Note that the package
797                // manager will ensure that only activity can run in the main
798                // process of the .apk, which is the only thing that will be
799                // considered heavy-weight.
800                if (app.processName.equals(app.info.packageName)) {
801                    if (mService.mHeavyWeightProcess != null
802                            && mService.mHeavyWeightProcess != app) {
803                        Slog.w(TAG, "Starting new heavy weight process " + app
804                                + " when already running "
805                                + mService.mHeavyWeightProcess);
806                    }
807                    mService.mHeavyWeightProcess = app;
808                    Message msg = mService.mHandler.obtainMessage(
809                            ActivityManagerService.POST_HEAVY_NOTIFICATION_MSG);
810                    msg.obj = r;
811                    mService.mHandler.sendMessage(msg);
812                }
813            }
814
815        } catch (RemoteException e) {
816            if (r.launchFailed) {
817                // This is the second time we failed -- finish activity
818                // and give up.
819                Slog.e(TAG, "Second failure launching "
820                      + r.intent.getComponent().flattenToShortString()
821                      + ", giving up", e);
822                mService.appDiedLocked(app, app.pid, app.thread);
823                stack.requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
824                        "2nd-crash", false);
825                return false;
826            }
827
828            // This is the first time we failed -- restart process and
829            // retry.
830            app.activities.remove(r);
831            throw e;
832        }
833
834        r.launchFailed = false;
835        if (stack.updateLRUListLocked(r)) {
836            Slog.w(TAG, "Activity " + r
837                  + " being launched, but already in LRU list");
838        }
839
840        if (andResume) {
841            // As part of the process of launching, ActivityThread also performs
842            // a resume.
843            stack.minimalResumeActivityLocked(r);
844        } else {
845            // This activity is not starting in the resumed state... which
846            // should look like we asked it to pause+stop (but remain visible),
847            // and it has done so and reported back the current icicle and
848            // other state.
849            if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r
850                    + " (starting in stopped state)");
851            r.state = ActivityState.STOPPED;
852            r.stopped = true;
853        }
854
855        // Launch the new version setup screen if needed.  We do this -after-
856        // launching the initial activity (that is, home), so that it can have
857        // a chance to initialize itself while in the background, making the
858        // switch back to it faster and look better.
859        if (isFrontStack(stack)) {
860            mService.startSetupActivityLocked();
861        }
862
863        return true;
864    }
865
866    void startSpecificActivityLocked(ActivityRecord r,
867            boolean andResume, boolean checkConfig) {
868        // Is this activity's application already running?
869        ProcessRecord app = mService.getProcessRecordLocked(r.processName,
870                r.info.applicationInfo.uid);
871
872        r.task.stack.setLaunchTime(r);
873
874        if (app != null && app.thread != null) {
875            try {
876                app.addPackage(r.info.packageName);
877                realStartActivityLocked(r, app, andResume, checkConfig);
878                return;
879            } catch (RemoteException e) {
880                Slog.w(TAG, "Exception when starting activity "
881                        + r.intent.getComponent().flattenToShortString(), e);
882            }
883
884            // If a dead object exception was thrown -- fall through to
885            // restart the application.
886        }
887
888        mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
889                "activity", r.intent.getComponent(), false, false);
890    }
891
892    final int startActivityLocked(IApplicationThread caller,
893            Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
894            String resultWho, int requestCode,
895            int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
896            boolean componentSpecified, ActivityRecord[] outActivity) {
897        int err = ActivityManager.START_SUCCESS;
898
899        ProcessRecord callerApp = null;
900        if (caller != null) {
901            callerApp = mService.getRecordForAppLocked(caller);
902            if (callerApp != null) {
903                callingPid = callerApp.pid;
904                callingUid = callerApp.info.uid;
905            } else {
906                Slog.w(TAG, "Unable to find app for caller " + caller
907                      + " (pid=" + callingPid + ") when starting: "
908                      + intent.toString());
909                err = ActivityManager.START_PERMISSION_DENIED;
910            }
911        }
912
913        if (err == ActivityManager.START_SUCCESS) {
914            final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;
915            Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false)
916                    + "} from pid " + (callerApp != null ? callerApp.pid : callingPid));
917        }
918
919        ActivityRecord sourceRecord = null;
920        ActivityRecord resultRecord = null;
921        if (resultTo != null) {
922            sourceRecord = isInAnyStackLocked(resultTo);
923            if (DEBUG_RESULTS) Slog.v(
924                TAG, "Will send result to " + resultTo + " " + sourceRecord);
925            if (sourceRecord != null) {
926                if (requestCode >= 0 && !sourceRecord.finishing) {
927                    resultRecord = sourceRecord;
928                }
929            }
930        }
931        ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
932
933        int launchFlags = intent.getFlags();
934
935        if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
936                && sourceRecord != null) {
937            // Transfer the result target from the source activity to the new
938            // one being started, including any failures.
939            if (requestCode >= 0) {
940                ActivityOptions.abort(options);
941                return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
942            }
943            resultRecord = sourceRecord.resultTo;
944            resultWho = sourceRecord.resultWho;
945            requestCode = sourceRecord.requestCode;
946            sourceRecord.resultTo = null;
947            if (resultRecord != null) {
948                resultRecord.removeResultsLocked(
949                    sourceRecord, resultWho, requestCode);
950            }
951        }
952
953        if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {
954            // We couldn't find a class that can handle the given Intent.
955            // That's the end of that!
956            err = ActivityManager.START_INTENT_NOT_RESOLVED;
957        }
958
959        if (err == ActivityManager.START_SUCCESS && aInfo == null) {
960            // We couldn't find the specific class specified in the Intent.
961            // Also the end of the line.
962            err = ActivityManager.START_CLASS_NOT_FOUND;
963        }
964
965        if (err != ActivityManager.START_SUCCESS) {
966            if (resultRecord != null) {
967                resultStack.sendActivityResultLocked(-1,
968                    resultRecord, resultWho, requestCode,
969                    Activity.RESULT_CANCELED, null);
970            }
971            setDismissKeyguard(false);
972            ActivityOptions.abort(options);
973            return err;
974        }
975
976        final int startAnyPerm = mService.checkPermission(
977                START_ANY_ACTIVITY, callingPid, callingUid);
978        final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
979                callingUid, aInfo.applicationInfo.uid, aInfo.exported);
980        if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) {
981            if (resultRecord != null) {
982                resultStack.sendActivityResultLocked(-1,
983                    resultRecord, resultWho, requestCode,
984                    Activity.RESULT_CANCELED, null);
985            }
986            setDismissKeyguard(false);
987            String msg;
988            if (!aInfo.exported) {
989                msg = "Permission Denial: starting " + intent.toString()
990                        + " from " + callerApp + " (pid=" + callingPid
991                        + ", uid=" + callingUid + ")"
992                        + " not exported from uid " + aInfo.applicationInfo.uid;
993            } else {
994                msg = "Permission Denial: starting " + intent.toString()
995                        + " from " + callerApp + " (pid=" + callingPid
996                        + ", uid=" + callingUid + ")"
997                        + " requires " + aInfo.permission;
998            }
999            Slog.w(TAG, msg);
1000            throw new SecurityException(msg);
1001        }
1002
1003        boolean abort = !mService.mIntentFirewall.checkStartActivity(intent,
1004                callerApp==null?null:callerApp.info, callingUid, callingPid, resolvedType, aInfo);
1005
1006        if (mService.mController != null) {
1007            try {
1008                // The Intent we give to the watcher has the extra data
1009                // stripped off, since it can contain private information.
1010                Intent watchIntent = intent.cloneFilter();
1011                abort |= !mService.mController.activityStarting(watchIntent,
1012                        aInfo.applicationInfo.packageName);
1013            } catch (RemoteException e) {
1014                mService.mController = null;
1015            }
1016        }
1017
1018        if (abort) {
1019            if (resultRecord != null) {
1020                resultStack.sendActivityResultLocked(-1, resultRecord, resultWho, requestCode,
1021                        Activity.RESULT_CANCELED, null);
1022            }
1023            // We pretend to the caller that it was really started, but
1024            // they will just get a cancel result.
1025            setDismissKeyguard(false);
1026            ActivityOptions.abort(options);
1027            return ActivityManager.START_SUCCESS;
1028        }
1029
1030        ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
1031                intent, resolvedType, aInfo, mService.mConfiguration,
1032                resultRecord, resultWho, requestCode, componentSpecified, this);
1033        if (outActivity != null) {
1034            outActivity[0] = r;
1035        }
1036
1037        final ActivityStack stack = getTopStack();
1038        if (stack.mResumedActivity == null
1039                || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
1040            if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
1041                PendingActivityLaunch pal =
1042                        new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
1043                mService.mPendingActivityLaunches.add(pal);
1044                setDismissKeyguard(false);
1045                ActivityOptions.abort(options);
1046                return ActivityManager.START_SWITCHES_CANCELED;
1047            }
1048        }
1049
1050        if (mService.mDidAppSwitch) {
1051            // This is the second allowed switch since we stopped switches,
1052            // so now just generally allow switches.  Use case: user presses
1053            // home (switches disabled, switch to home, mDidAppSwitch now true);
1054            // user taps a home icon (coming from home so allowed, we hit here
1055            // and now allow anyone to switch again).
1056            mService.mAppSwitchesAllowedTime = 0;
1057        } else {
1058            mService.mDidAppSwitch = true;
1059        }
1060
1061        mService.doPendingActivityLaunchesLocked(false);
1062
1063        err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
1064        if (stack.mPausingActivity == null) {
1065            // Someone asked to have the keyguard dismissed on the next
1066            // activity start, but we are not actually doing an activity
1067            // switch...  just dismiss the keyguard now, because we
1068            // probably want to see whatever is behind it.
1069            dismissKeyguard();
1070        }
1071        return err;
1072    }
1073
1074    ActivityStack getCorrectStack(ActivityRecord r) {
1075        if (!r.isHomeActivity) {
1076            if (mStacks.size() == 1) {
1077                // Time to create the first app stack.
1078                int stackId = mService.createStack(-1, HOME_STACK_ID,
1079                        StackBox.TASK_STACK_GOES_OVER, 1.0f);
1080                mFocusedStack = getStack(stackId);
1081            }
1082            return mFocusedStack;
1083        }
1084        return mHomeStack;
1085    }
1086
1087    void setFocusedStack(ActivityRecord r) {
1088        if (r == null) {
1089            return;
1090        }
1091        if (r.isHomeActivity) {
1092            if (mStackState != STACK_STATE_HOME_IN_FRONT) {
1093                mStackState = STACK_STATE_HOME_TO_FRONT;
1094            }
1095        } else {
1096            mFocusedStack = r.task.stack;
1097            if (mStackState != STACK_STATE_HOME_IN_BACK) {
1098                mStackState = STACK_STATE_HOME_TO_BACK;
1099            }
1100        }
1101    }
1102
1103    final int startActivityUncheckedLocked(ActivityRecord r,
1104            ActivityRecord sourceRecord, int startFlags, boolean doResume,
1105            Bundle options) {
1106        final Intent intent = r.intent;
1107        final int callingUid = r.launchedFromUid;
1108
1109        int launchFlags = intent.getFlags();
1110
1111        // We'll invoke onUserLeaving before onPause only if the launching
1112        // activity did not explicitly state that this is an automated launch.
1113        mUserLeaving = (launchFlags&Intent.FLAG_ACTIVITY_NO_USER_ACTION) == 0;
1114        if (DEBUG_USER_LEAVING) Slog.v(TAG, "startActivity() => mUserLeaving=" + mUserLeaving);
1115
1116        // If the caller has asked not to resume at this point, we make note
1117        // of this in the record so that we can skip it when trying to find
1118        // the top running activity.
1119        if (!doResume) {
1120            r.delayedResume = true;
1121        }
1122
1123        ActivityRecord notTop = (launchFlags&Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP) != 0 ? r : null;
1124
1125        // If the onlyIfNeeded flag is set, then we can do this if the activity
1126        // being launched is the same as the one making the call...  or, as
1127        // a special case, if we do not know the caller then we count the
1128        // current top activity as the caller.
1129        if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1130            ActivityRecord checkedCaller = sourceRecord;
1131            if (checkedCaller == null) {
1132                checkedCaller = getTopStack().topRunningNonDelayedActivityLocked(notTop);
1133            }
1134            if (!checkedCaller.realActivity.equals(r.realActivity)) {
1135                // Caller is not the same as launcher, so always needed.
1136                startFlags &= ~ActivityManager.START_FLAG_ONLY_IF_NEEDED;
1137            }
1138        }
1139
1140        if (sourceRecord == null) {
1141            // This activity is not being started from another...  in this
1142            // case we -always- start a new task.
1143            if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0) {
1144                Slog.w(TAG, "startActivity called from non-Activity context; forcing " +
1145                        "Intent.FLAG_ACTIVITY_NEW_TASK for: " + intent);
1146                launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1147            }
1148        } else if (sourceRecord.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1149            // The original activity who is starting us is running as a single
1150            // instance...  this new activity it is starting must go on its
1151            // own task.
1152            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1153        } else if (r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE
1154                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1155            // The activity being started is a single instance...  it always
1156            // gets launched into its own task.
1157            launchFlags |= Intent.FLAG_ACTIVITY_NEW_TASK;
1158        }
1159
1160        final ActivityStack sourceStack;
1161        final TaskRecord sourceTask;
1162        if (sourceRecord != null) {
1163            sourceTask = sourceRecord.task;
1164            sourceStack = sourceTask.stack;
1165        } else {
1166            sourceTask = null;
1167            sourceStack = null;
1168        }
1169
1170        if (r.resultTo != null && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1171            // For whatever reason this activity is being launched into a new
1172            // task...  yet the caller has requested a result back.  Well, that
1173            // is pretty messed up, so instead immediately send back a cancel
1174            // and let the new task continue launched as normal without a
1175            // dependency on its originator.
1176            Slog.w(TAG, "Activity is launching as a new task, so cancelling activity result.");
1177            r.resultTo.task.stack.sendActivityResultLocked(-1,
1178                    r.resultTo, r.resultWho, r.requestCode,
1179                Activity.RESULT_CANCELED, null);
1180            r.resultTo = null;
1181        }
1182
1183        boolean addingToTask = false;
1184        boolean movedHome = false;
1185        TaskRecord reuseTask = null;
1186        ActivityStack targetStack;
1187        if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
1188                (launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
1189                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1190                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1191            // If bring to front is requested, and no result is requested, and
1192            // we can find a task that was started with this same
1193            // component, then instead of launching bring that one to the front.
1194            if (r.resultTo == null) {
1195                // See if there is a task to bring to the front.  If this is
1196                // a SINGLE_INSTANCE activity, there can be one and only one
1197                // instance of it in the history, and it is always in its own
1198                // unique task, so we do a special search.
1199                ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
1200                        ? findTaskLocked(intent, r.info)
1201                        : findActivityLocked(intent, r.info);
1202                if (intentActivity != null) {
1203                    if (r.task == null) {
1204                        r.task = intentActivity.task;
1205                    }
1206                    targetStack = intentActivity.task.stack;
1207                    moveHomeStack(targetStack.isHomeStack());
1208                    if (intentActivity.task.intent == null) {
1209                        // This task was started because of movement of
1210                        // the activity based on affinity...  now that we
1211                        // are actually launching it, we can assign the
1212                        // base intent.
1213                        intentActivity.task.setIntent(intent, r.info);
1214                    }
1215                    // If the target task is not in the front, then we need
1216                    // to bring it to the front...  except...  well, with
1217                    // SINGLE_TASK_LAUNCH it's not entirely clear.  We'd like
1218                    // to have the same behavior as if a new instance was
1219                    // being started, which means not bringing it to the front
1220                    // if the caller is not itself in the front.
1221                    ActivityRecord curTop =
1222                            targetStack.topRunningNonDelayedActivityLocked(notTop);
1223                    if (curTop != null && curTop.task != intentActivity.task) {
1224                        r.intent.addFlags(Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT);
1225                        if (sourceRecord == null || sourceStack.topActivity() == sourceRecord) {
1226                            // We really do want to push this one into the
1227                            // user's face, right now.
1228                            movedHome = true;
1229                            if ((launchFlags &
1230                                    (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME))
1231                                    == (FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME)) {
1232                                // Caller wants to appear on home activity, so before starting
1233                                // their own activity we will bring home to the front.
1234                                r.mLaunchHomeTaskNext = true;
1235                            }
1236                            targetStack.moveTaskToFrontLocked(intentActivity.task, r, options);
1237                            options = null;
1238                        }
1239                    }
1240                    // If the caller has requested that the target task be
1241                    // reset, then do so.
1242                    if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
1243                        intentActivity = targetStack.resetTaskIfNeededLocked(intentActivity, r);
1244                    }
1245                    if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1246                        // We don't need to start a new activity, and
1247                        // the client said not to do anything if that
1248                        // is the case, so this is it!  And for paranoia, make
1249                        // sure we have correctly resumed the top activity.
1250                        if (doResume) {
1251                            setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
1252                            targetStack.resumeTopActivityLocked(null, options);
1253                        } else {
1254                            ActivityOptions.abort(options);
1255                        }
1256                        if (r.task == null)  Slog.v(TAG,
1257                                "startActivityUncheckedLocked: task left null",
1258                                new RuntimeException("here").fillInStackTrace());
1259                        return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1260                    }
1261                    if ((launchFlags &
1262                            (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK))
1263                            == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK)) {
1264                        // The caller has requested to completely replace any
1265                        // existing task with its new activity.  Well that should
1266                        // not be too hard...
1267                        reuseTask = intentActivity.task;
1268                        reuseTask.performClearTaskLocked();
1269                        reuseTask.setIntent(r.intent, r.info);
1270                    } else if ((launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0
1271                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
1272                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
1273                        // In this situation we want to remove all activities
1274                        // from the task up to the one being started.  In most
1275                        // cases this means we are resetting the task to its
1276                        // initial state.
1277                        ActivityRecord top =
1278                                intentActivity.task.performClearTaskLocked(r, launchFlags);
1279                        if (top != null) {
1280                            if (top.frontOfTask) {
1281                                // Activity aliases may mean we use different
1282                                // intents for the top activity, so make sure
1283                                // the task now has the identity of the new
1284                                // intent.
1285                                top.task.setIntent(r.intent, r.info);
1286                            }
1287                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT,
1288                                    r, top.task);
1289                            top.deliverNewIntentLocked(callingUid, r.intent);
1290                        } else {
1291                            // A special case: we need to
1292                            // start the activity because it is not currently
1293                            // running, and the caller has asked to clear the
1294                            // current task to have this activity at the top.
1295                            addingToTask = true;
1296                            // Now pretend like this activity is being started
1297                            // by the top of its task, so it is put in the
1298                            // right place.
1299                            sourceRecord = intentActivity;
1300                        }
1301                    } else if (r.realActivity.equals(intentActivity.task.realActivity)) {
1302                        // In this case the top activity on the task is the
1303                        // same as the one being launched, so we take that
1304                        // as a request to bring the task to the foreground.
1305                        // If the top activity in the task is the root
1306                        // activity, deliver this new intent to it if it
1307                        // desires.
1308                        if (((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1309                                || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP)
1310                                && intentActivity.realActivity.equals(r.realActivity)) {
1311                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r,
1312                                    intentActivity.task);
1313                            if (intentActivity.frontOfTask) {
1314                                intentActivity.task.setIntent(r.intent, r.info);
1315                            }
1316                            intentActivity.deliverNewIntentLocked(callingUid, r.intent);
1317                        } else if (!r.intent.filterEquals(intentActivity.task.intent)) {
1318                            // In this case we are launching the root activity
1319                            // of the task, but with a different intent.  We
1320                            // should start a new instance on top.
1321                            addingToTask = true;
1322                            sourceRecord = intentActivity;
1323                        }
1324                    } else if ((launchFlags&Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) == 0) {
1325                        // In this case an activity is being launched in to an
1326                        // existing task, without resetting that task.  This
1327                        // is typically the situation of launching an activity
1328                        // from a notification or shortcut.  We want to place
1329                        // the new activity on top of the current task.
1330                        addingToTask = true;
1331                        sourceRecord = intentActivity;
1332                    } else if (!intentActivity.task.rootWasReset) {
1333                        // In this case we are launching in to an existing task
1334                        // that has not yet been started from its front door.
1335                        // The current task has been brought to the front.
1336                        // Ideally, we'd probably like to place this new task
1337                        // at the bottom of its stack, but that's a little hard
1338                        // to do with the current organization of the code so
1339                        // for now we'll just drop it.
1340                        intentActivity.task.setIntent(r.intent, r.info);
1341                    }
1342                    if (!addingToTask && reuseTask == null) {
1343                        // We didn't do anything...  but it was needed (a.k.a., client
1344                        // don't use that intent!)  And for paranoia, make
1345                        // sure we have correctly resumed the top activity.
1346                        if (doResume) {
1347                            setLaunchHomeTaskNextFlag(sourceRecord, intentActivity, targetStack);
1348                            targetStack.resumeTopActivityLocked(null, options);
1349                        } else {
1350                            ActivityOptions.abort(options);
1351                        }
1352                        if (r.task == null)  Slog.v(TAG,
1353                            "startActivityUncheckedLocked: task left null",
1354                            new RuntimeException("here").fillInStackTrace());
1355                        return ActivityManager.START_TASK_TO_FRONT;
1356                    }
1357                }
1358            }
1359        }
1360
1361        //String uri = r.intent.toURI();
1362        //Intent intent2 = new Intent(uri);
1363        //Slog.i(TAG, "Given intent: " + r.intent);
1364        //Slog.i(TAG, "URI is: " + uri);
1365        //Slog.i(TAG, "To intent: " + intent2);
1366
1367        if (r.packageName != null) {
1368            // If the activity being launched is the same as the one currently
1369            // at the top, then we need to check if it should only be launched
1370            // once.
1371            ActivityStack topStack = getTopStack();
1372            ActivityRecord top = topStack.topRunningNonDelayedActivityLocked(notTop);
1373            if (top != null && r.resultTo == null) {
1374                if (top.realActivity.equals(r.realActivity) && top.userId == r.userId) {
1375                    if (top.app != null && top.app.thread != null) {
1376                        if ((launchFlags&Intent.FLAG_ACTIVITY_SINGLE_TOP) != 0
1377                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP
1378                            || r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK) {
1379                            ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, top,
1380                                    top.task);
1381                            // For paranoia, make sure we have correctly
1382                            // resumed the top activity.
1383                            if (doResume) {
1384                                setLaunchHomeTaskNextFlag(sourceRecord, null, topStack);
1385                                topStack.resumeTopActivityLocked(null);
1386                            }
1387                            ActivityOptions.abort(options);
1388                            if ((startFlags&ActivityManager.START_FLAG_ONLY_IF_NEEDED) != 0) {
1389                                // We don't need to start a new activity, and
1390                                // the client said not to do anything if that
1391                                // is the case, so this is it!
1392                                if (r.task == null)  Slog.v(TAG,
1393                                    "startActivityUncheckedLocked: task left null",
1394                                    new RuntimeException("here").fillInStackTrace());
1395                                return ActivityManager.START_RETURN_INTENT_TO_CALLER;
1396                            }
1397                            top.deliverNewIntentLocked(callingUid, r.intent);
1398                            if (r.task == null)  Slog.v(TAG,
1399                                "startActivityUncheckedLocked: task left null",
1400                                new RuntimeException("here").fillInStackTrace());
1401                            return ActivityManager.START_DELIVERED_TO_TOP;
1402                        }
1403                    }
1404                }
1405            }
1406
1407        } else {
1408            if (r.resultTo != null) {
1409                r.resultTo.task.stack.sendActivityResultLocked(-1, r.resultTo, r.resultWho,
1410                        r.requestCode, Activity.RESULT_CANCELED, null);
1411            }
1412            ActivityOptions.abort(options);
1413            if (r.task == null)  Slog.v(TAG,
1414                "startActivityUncheckedLocked: task left null",
1415                new RuntimeException("here").fillInStackTrace());
1416            return ActivityManager.START_CLASS_NOT_FOUND;
1417        }
1418
1419        boolean newTask = false;
1420        boolean keepCurTransition = false;
1421
1422        // Should this be considered a new task?
1423        if (r.resultTo == null && !addingToTask
1424                && (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {
1425            targetStack = getCorrectStack(r);
1426            moveHomeStack(targetStack.isHomeStack());
1427            if (reuseTask == null) {
1428                r.setTask(targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1429                        null, true);
1430                if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
1431                        r.task);
1432            } else {
1433                r.setTask(reuseTask, reuseTask, true);
1434            }
1435            newTask = true;
1436            if (!movedHome) {
1437                if ((launchFlags &
1438                        (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME))
1439                        == (Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_TASK_ON_HOME)) {
1440                    // Caller wants to appear on home activity, so before starting
1441                    // their own activity we will bring home to the front.
1442                    r.mLaunchHomeTaskNext = true;
1443                }
1444            }
1445        } else if (sourceRecord != null) {
1446            targetStack = sourceRecord.task.stack;
1447            moveHomeStack(targetStack.isHomeStack());
1448            if (!addingToTask &&
1449                    (launchFlags&Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
1450                // In this case, we are adding the activity to an existing
1451                // task, but the caller has asked to clear that task if the
1452                // activity is already running.
1453                ActivityRecord top = sourceRecord.task.performClearTaskLocked(r, launchFlags);
1454                keepCurTransition = true;
1455                if (top != null) {
1456                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, top.task);
1457                    top.deliverNewIntentLocked(callingUid, r.intent);
1458                    // For paranoia, make sure we have correctly
1459                    // resumed the top activity.
1460                    if (doResume) {
1461                        setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
1462                        targetStack.resumeTopActivityLocked(null);
1463                    }
1464                    ActivityOptions.abort(options);
1465                    if (r.task == null)  Slog.v(TAG,
1466                        "startActivityUncheckedLocked: task left null",
1467                        new RuntimeException("here").fillInStackTrace());
1468                    return ActivityManager.START_DELIVERED_TO_TOP;
1469                }
1470            } else if (!addingToTask &&
1471                    (launchFlags&Intent.FLAG_ACTIVITY_REORDER_TO_FRONT) != 0) {
1472                // In this case, we are launching an activity in our own task
1473                // that may already be running somewhere in the history, and
1474                // we want to shuffle it to the front of the stack if so.
1475                final ActivityRecord top =
1476                        targetStack.findActivityInHistoryLocked(r, sourceRecord.task);
1477                if (top != null) {
1478                    final TaskRecord task = top.task;
1479                    task.moveActivityToFrontLocked(top);
1480                    ActivityStack.logStartActivity(EventLogTags.AM_NEW_INTENT, r, task);
1481                    top.updateOptionsLocked(options);
1482                    top.deliverNewIntentLocked(callingUid, r.intent);
1483                    if (doResume) {
1484                        setLaunchHomeTaskNextFlag(sourceRecord, null, targetStack);
1485                        targetStack.resumeTopActivityLocked(null);
1486                    }
1487                    if (r.task == null)  Slog.v(TAG,
1488                        "startActivityUncheckedLocked: task left null",
1489                        new RuntimeException("here").fillInStackTrace());
1490                    return ActivityManager.START_DELIVERED_TO_TOP;
1491                }
1492            }
1493            // An existing activity is starting this new activity, so we want
1494            // to keep the new one in the same task as the one that is starting
1495            // it.
1496            r.setTask(sourceRecord.task, sourceRecord.thumbHolder, false);
1497            if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1498                    + " in existing task " + r.task);
1499
1500        } else {
1501            // This not being started from an existing activity, and not part
1502            // of a new task...  just put it in the top task, though these days
1503            // this case should never happen.
1504            targetStack = getLastStack();
1505            moveHomeStack(targetStack.isHomeStack());
1506            ActivityRecord prev = targetStack.topActivity();
1507            r.setTask(prev != null ? prev.task
1508                    : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
1509                    null, true);
1510            if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
1511                    + " in new guessed " + r.task);
1512        }
1513
1514        mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
1515                intent, r.getUriPermissionsLocked());
1516
1517        if (newTask) {
1518            EventLog.writeEvent(EventLogTags.AM_CREATE_TASK, r.userId, r.task.taskId);
1519        }
1520        ActivityStack.logStartActivity(EventLogTags.AM_CREATE_ACTIVITY, r, r.task);
1521        setLaunchHomeTaskNextFlag(sourceRecord, r, targetStack);
1522        targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
1523        return ActivityManager.START_SUCCESS;
1524    }
1525
1526    void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
1527        // Just in case.
1528        final int numStacks = mStacks.size();
1529        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1530            mStacks.get(stackNdx).handleAppDiedLocked(app, restarting);
1531        }
1532    }
1533
1534    void closeSystemDialogsLocked() {
1535        final int numStacks = mStacks.size();
1536        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1537            final ActivityStack stack = mStacks.get(stackNdx);
1538            stack.closeSystemDialogsLocked();
1539        }
1540    }
1541
1542    /**
1543     * @return true if some activity was finished (or would have finished if doit were true).
1544     */
1545    boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
1546        boolean didSomething = false;
1547        final int numStacks = mStacks.size();
1548        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1549            final ActivityStack stack = mStacks.get(stackNdx);
1550            if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
1551                didSomething = true;
1552            }
1553        }
1554        return didSomething;
1555    }
1556
1557    void resumeTopActivityLocked() {
1558        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1559            mStacks.get(stackNdx).resumeTopActivityLocked(null);
1560        }
1561    }
1562
1563    void finishTopRunningActivityLocked(ProcessRecord app) {
1564        final int numStacks = mStacks.size();
1565        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1566            final ActivityStack stack = mStacks.get(stackNdx);
1567            stack.finishTopRunningActivityLocked(app);
1568        }
1569    }
1570
1571    void scheduleIdleLocked() {
1572        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1573            mStacks.get(stackNdx).scheduleIdleLocked();
1574        }
1575    }
1576
1577    void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
1578        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1579            if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
1580                return;
1581            }
1582        }
1583    }
1584
1585    ActivityStack getStack(int stackId) {
1586        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1587            final ActivityStack stack = mStacks.get(stackNdx);
1588            if (stack.getStackId() == stackId) {
1589                return stack;
1590            }
1591        }
1592        return null;
1593    }
1594
1595    ArrayList<ActivityStack> getStacks() {
1596        return new ArrayList<ActivityStack>(mStacks);
1597    }
1598
1599    int createStack() {
1600        synchronized (this) {
1601            while (true) {
1602                if (++mLastStackId <= HOME_STACK_ID) {
1603                    mLastStackId = HOME_STACK_ID + 1;
1604                }
1605                if (getStack(mLastStackId) == null) {
1606                    break;
1607                }
1608            }
1609            mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId, this,
1610                    mCurrentUser));
1611            return mLastStackId;
1612        }
1613    }
1614
1615    void moveTaskToStack(int taskId, int stackId, boolean toTop) {
1616        final ActivityStack stack = getStack(stackId);
1617        if (stack == null) {
1618            Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
1619            return;
1620        }
1621        stack.moveTask(taskId, toTop);
1622        stack.resumeTopActivityLocked(null);
1623    }
1624
1625    ActivityRecord findTaskLocked(Intent intent, ActivityInfo info) {
1626        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1627            final ActivityRecord ar = mStacks.get(stackNdx).findTaskLocked(intent, info);
1628            if (ar != null) {
1629                return ar;
1630            }
1631        }
1632        return null;
1633    }
1634
1635    ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
1636        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1637            final ActivityRecord ar = mStacks.get(stackNdx).findActivityLocked(intent, info);
1638            if (ar != null) {
1639                return ar;
1640            }
1641        }
1642        return null;
1643    }
1644
1645    void goingToSleepLocked() {
1646        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1647            mStacks.get(stackNdx).stopIfSleepingLocked();
1648        }
1649    }
1650
1651    boolean shutdownLocked(int timeout) {
1652        boolean timedout = false;
1653        final int numStacks = mStacks.size();
1654        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1655            final ActivityStack stack = mStacks.get(stackNdx);
1656            if (stack.mResumedActivity != null) {
1657                stack.stopIfSleepingLocked();
1658                final long endTime = System.currentTimeMillis() + timeout;
1659                while (stack.mResumedActivity != null || stack.mPausingActivity != null) {
1660                    long delay = endTime - System.currentTimeMillis();
1661                    if (delay <= 0) {
1662                        Slog.w(TAG, "Activity manager shutdown timed out");
1663                        timedout = true;
1664                        break;
1665                    }
1666                    try {
1667                        mService.wait();
1668                    } catch (InterruptedException e) {
1669                    }
1670                }
1671            }
1672        }
1673        return timedout;
1674    }
1675
1676    void comeOutOfSleepIfNeededLocked() {
1677        final boolean homeIsBack = !homeIsInFront();
1678        final int numStacks = mStacks.size();
1679        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1680            final ActivityStack stack = mStacks.get(stackNdx);
1681            if (stack.isHomeStack() ^ homeIsBack) {
1682                stack.awakeFromSleepingLocked();
1683                stack.resumeTopActivityLocked(null);
1684            }
1685        }
1686    }
1687
1688    void handleAppCrashLocked(ProcessRecord app) {
1689        final int numStacks = mStacks.size();
1690        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1691            final ActivityStack stack = mStacks.get(stackNdx);
1692            stack.handleAppCrashLocked(app);
1693        }
1694    }
1695
1696    void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
1697        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1698            mStacks.get(stackNdx).ensureActivitiesVisibleLocked(starting, configChanges);
1699        }
1700    }
1701
1702    void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
1703        final int numStacks = mStacks.size();
1704        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1705            final ActivityStack stack = mStacks.get(stackNdx);
1706            stack.scheduleDestroyActivities(app, false, reason);
1707        }
1708    }
1709
1710    boolean switchUserLocked(int userId, UserStartedState uss) {
1711        mCurrentUser = userId;
1712        boolean homeInBack = !homeIsInFront();
1713        boolean haveActivities = false;
1714        final int numStacks = mStacks.size();
1715        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1716            final ActivityStack stack = mStacks.get(stackNdx);
1717            if (stack.isHomeStack() ^ homeInBack) {
1718                haveActivities |= stack.switchUserLocked(userId, uss);
1719            }
1720        }
1721        return haveActivities;
1722    }
1723
1724    final ArrayList<ActivityRecord> processStoppingActivitiesLocked(boolean remove) {
1725        int N = mStoppingActivities.size();
1726        if (N <= 0) return null;
1727
1728        ArrayList<ActivityRecord> stops = null;
1729
1730        final boolean nowVisible = allResumedActivitiesVisible();
1731        for (int i=0; i<N; i++) {
1732            ActivityRecord s = mStoppingActivities.get(i);
1733            if (localLOGV) Slog.v(TAG, "Stopping " + s + ": nowVisible="
1734                    + nowVisible + " waitingVisible=" + s.waitingVisible
1735                    + " finishing=" + s.finishing);
1736            if (s.waitingVisible && nowVisible) {
1737                mWaitingVisibleActivities.remove(s);
1738                s.waitingVisible = false;
1739                if (s.finishing) {
1740                    // If this activity is finishing, it is sitting on top of
1741                    // everyone else but we now know it is no longer needed...
1742                    // so get rid of it.  Otherwise, we need to go through the
1743                    // normal flow and hide it once we determine that it is
1744                    // hidden by the activities in front of it.
1745                    if (localLOGV) Slog.v(TAG, "Before stopping, can hide: " + s);
1746                    mService.mWindowManager.setAppVisibility(s.appToken, false);
1747                }
1748            }
1749            if ((!s.waitingVisible || mService.isSleepingOrShuttingDown()) && remove) {
1750                if (localLOGV) Slog.v(TAG, "Ready to stop: " + s);
1751                if (stops == null) {
1752                    stops = new ArrayList<ActivityRecord>();
1753                }
1754                stops.add(s);
1755                mStoppingActivities.remove(i);
1756                N--;
1757                i--;
1758            }
1759        }
1760
1761        return stops;
1762    }
1763
1764    public void dump(PrintWriter pw, String prefix) {
1765        pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
1766                pw.println(mDismissKeyguardOnNextActivity);
1767    }
1768
1769    ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
1770        return getTopStack().getDumpActivitiesLocked(name);
1771    }
1772
1773    boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
1774            boolean dumpClient, String dumpPackage) {
1775        final int numStacks = mStacks.size();
1776        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1777            final ActivityStack stack = mStacks.get(stackNdx);
1778            pw.print("  Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
1779            stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
1780            pw.println(" ");
1781            pw.println("  Running activities (most recent first):");
1782            dumpHistoryList(fd, pw, stack.mLRUActivities, "  ", "Run", false, !dumpAll, false,
1783                    dumpPackage);
1784            if (stack.mGoingToSleepActivities.size() > 0) {
1785                pw.println(" ");
1786                pw.println("  Activities waiting to sleep:");
1787                dumpHistoryList(fd, pw, stack.mGoingToSleepActivities, "  ", "Sleep", false,
1788                        !dumpAll, false, dumpPackage);
1789            }
1790            if (stack.mFinishingActivities.size() > 0) {
1791                pw.println(" ");
1792                pw.println("  Activities waiting to finish:");
1793                dumpHistoryList(fd, pw, stack.mFinishingActivities, "  ", "Fin", false,
1794                        !dumpAll, false, dumpPackage);
1795            }
1796
1797            pw.print("  Stack #"); pw.println(mStacks.indexOf(stack));
1798            if (stack.mPausingActivity != null) {
1799                pw.println("  mPausingActivity: " + stack.mPausingActivity);
1800            }
1801            pw.println("  mResumedActivity: " + stack.mResumedActivity);
1802            if (dumpAll) {
1803                pw.println("  mLastPausedActivity: " + stack.mLastPausedActivity);
1804                pw.println("  mSleepTimeout: " + stack.mSleepTimeout);
1805            }
1806        }
1807
1808        if (mStoppingActivities.size() > 0) {
1809            pw.println(" ");
1810            pw.println("  Activities waiting to stop:");
1811            dumpHistoryList(fd, pw, mStoppingActivities, "  ", "Stop", false, !dumpAll, false,
1812                    dumpPackage);
1813        }
1814
1815        if (mWaitingVisibleActivities.size() > 0) {
1816            pw.println(" ");
1817            pw.println("  Activities waiting for another to become visible:");
1818            dumpHistoryList(fd, pw, mWaitingVisibleActivities, "  ", "Wait", false, !dumpAll,
1819                    false, dumpPackage);
1820        }
1821
1822        if (dumpAll) {
1823            pw.println(" ");
1824            pw.println("  mCurTaskId: " + mCurTaskId);
1825        }
1826        return true;
1827    }
1828
1829    static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
1830            String prefix, String label, boolean complete, boolean brief, boolean client,
1831            String dumpPackage) {
1832        TaskRecord lastTask = null;
1833        boolean needNL = false;
1834        final String innerPrefix = prefix + "      ";
1835        final String[] args = new String[0];
1836        for (int i=list.size()-1; i>=0; i--) {
1837            final ActivityRecord r = list.get(i);
1838            if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
1839                continue;
1840            }
1841            final boolean full = !brief && (complete || !r.isInHistory());
1842            if (needNL) {
1843                pw.println(" ");
1844                needNL = false;
1845            }
1846            if (lastTask != r.task) {
1847                lastTask = r.task;
1848                pw.print(prefix);
1849                pw.print(full ? "* " : "  ");
1850                pw.println(lastTask);
1851                if (full) {
1852                    lastTask.dump(pw, prefix + "  ");
1853                } else if (complete) {
1854                    // Complete + brief == give a summary.  Isn't that obvious?!?
1855                    if (lastTask.intent != null) {
1856                        pw.print(prefix); pw.print("  ");
1857                                pw.println(lastTask.intent.toInsecureStringWithClip());
1858                    }
1859                }
1860            }
1861            pw.print(prefix); pw.print(full ? "  * " : "    "); pw.print(label);
1862            pw.print(" #"); pw.print(i); pw.print(": ");
1863            pw.println(r);
1864            if (full) {
1865                r.dump(pw, innerPrefix);
1866            } else if (complete) {
1867                // Complete + brief == give a summary.  Isn't that obvious?!?
1868                pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
1869                if (r.app != null) {
1870                    pw.print(innerPrefix); pw.println(r.app);
1871                }
1872            }
1873            if (client && r.app != null && r.app.thread != null) {
1874                // flush anything that is already in the PrintWriter since the thread is going
1875                // to write to the file descriptor directly
1876                pw.flush();
1877                try {
1878                    TransferPipe tp = new TransferPipe();
1879                    try {
1880                        r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
1881                                r.appToken, innerPrefix, args);
1882                        // Short timeout, since blocking here can
1883                        // deadlock with the application.
1884                        tp.go(fd, 2000);
1885                    } finally {
1886                        tp.kill();
1887                    }
1888                } catch (IOException e) {
1889                    pw.println(innerPrefix + "Failure while dumping the activity: " + e);
1890                } catch (RemoteException e) {
1891                    pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
1892                }
1893                needNL = true;
1894            }
1895        }
1896    }
1897}
1898