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