ActivityStackSupervisor.java revision 20e7227454bf6f3500c6eb97a17483dd8b764341
1de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org/*
29a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com * Copyright (C) 2013 The Android Open Source Project
39a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com *
49a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com * Licensed under the Apache License, Version 2.0 (the "License");
59a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com * you may not use this file except in compliance with the License.
69a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com * You may obtain a copy of the License at
79a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com *
89a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com *      http://www.apache.org/licenses/LICENSE-2.0
99a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com *
109a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com * Unless required by applicable law or agreed to in writing, software
119a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com * distributed under the License is distributed on an "AS IS" BASIS,
129a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com * See the License for the specific language governing permissions and
149a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com * limitations under the License.
159a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com */
169a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
179a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.compackage com.android.server.am;
189a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
199a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comimport static com.android.server.am.ActivityManagerService.DEBUG_CLEANUP;
209a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comimport static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
219a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comimport static com.android.server.am.ActivityManagerService.TAG;
229a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
239a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comimport android.app.IThumbnailReceiver;
249a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comimport android.app.ActivityManager.RunningTaskInfo;
259a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comimport android.content.Context;
269a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comimport android.content.Intent;
279a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comimport android.content.pm.ActivityInfo;
289a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comimport android.os.Bundle;
299a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comimport android.os.Looper;
309a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comimport android.os.RemoteException;
313291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgimport android.util.Slog;
323291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
333291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgimport java.io.FileDescriptor;
343291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgimport java.io.IOException;
353291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgimport java.io.PrintWriter;
363291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgimport java.util.ArrayList;
373291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgimport java.util.List;
383291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
393291210ab99f306b74430ebbc4b7d939629e699fager@chromium.orgpublic class ActivityStackSupervisor {
403291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    public static final int HOME_STACK_ID = 0;
41160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org
423291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    final ActivityManagerService mService;
433291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    final Context mContext;
449a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    final Looper mLooper;
453291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
463291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    /** Dismiss the keyguard after the next activity is displayed? */
47b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    private boolean mDismissKeyguardOnNextActivity = false;
48b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org
49b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    /** Identifier counter for all ActivityStacks */
509a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    private int mLastStackId = 0;
519a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
52de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    /** Task identifier that activities are currently being started in.  Incremented each time a
53de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org     * new task is created. */
54de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    private int mCurTaskId = 0;
559a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
569a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    /** The stack containing the launcher app */
573291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    private ActivityStack mHomeStack;
583291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
593291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    /** The stack currently receiving input or launching the next activity */
603291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    private ActivityStack mMainStack;
61de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
623291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    /** All the non-launcher stacks */
63de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    private ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
64de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
653291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    public ActivityStackSupervisor(ActivityManagerService service, Context context,
663291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            Looper looper) {
679a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        mService = service;
689a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        mContext = context;
69160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org        mLooper = looper;
709a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    }
719a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
72de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    void init() {
73de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org        mHomeStack = new ActivityStack(mService, mContext, mLooper, HOME_STACK_ID, this);
743291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        setMainStack(mHomeStack);
753291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        mStacks.add(mHomeStack);
769a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    }
77a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org
78de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    void dismissKeyguard() {
79de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org        if (mDismissKeyguardOnNextActivity) {
80de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org            mDismissKeyguardOnNextActivity = false;
81de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org            mService.mWindowManager.dismissKeyguard();
82de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org        }
83de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    }
84de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
853291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    boolean isHomeStackMain() {
869a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        return mHomeStack == mMainStack;
879a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    }
889a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
899a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    boolean isMainStack(ActivityStack stack) {
909a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        return stack == mMainStack;
919a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    }
929a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
939a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    ActivityStack getMainStack() {
949a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        return mMainStack;
959a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    }
969a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
979a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    void setMainStack(ActivityStack stack) {
989a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        mMainStack = stack;
999a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    }
1003291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
1013291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    void setDismissKeyguard(boolean dismiss) {
1023291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        mDismissKeyguardOnNextActivity = dismiss;
1033291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    }
1043291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
1053291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    TaskRecord anyTaskForIdLocked(int id) {
1063291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1073291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            ActivityStack stack = mStacks.get(stackNdx);
1083291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            TaskRecord task = stack.taskForIdLocked(id);
1093291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            if (task != null) {
1103291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                return task;
1119a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            }
1129a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        }
1133291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        return null;
1149a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    }
1159a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
116b3284ad36ee358a35b81379ad1c449e4f8021362kasperl@chromium.org    int getNextTaskId() {
1179a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        do {
1189a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            mCurTaskId++;
1199a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            if (mCurTaskId <= 0) {
1203291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                mCurTaskId = 1;
1213291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            }
1223291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        } while (anyTaskForIdLocked(mCurTaskId) != null);
1233291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        return mCurTaskId;
1243291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    }
1253291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
1263291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
1279a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        boolean didSomething = false;
1283291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        final String processName = app.processName;
1299a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1303291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            final ActivityStack stack = mStacks.get(stackNdx);
1319a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            ActivityRecord hr = stack.topRunningActivityLocked(null);
1323291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            if (hr != null) {
1333291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                if (hr.app == null && app.uid == hr.info.applicationInfo.uid
1349a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com                        && processName.equals(hr.processName)) {
1353291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                    try {
1369a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com                        if (headless) {
1373291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                            Slog.e(TAG, "Starting activities not supported on headless device: "
1389a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com                                    + hr);
1393291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                        } else if (stack.realStartActivityLocked(hr, app, true, true)) {
140160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org                            didSomething = true;
1413291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                        }
1423291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                    } catch (Exception e) {
1433291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                        Slog.w(TAG, "Exception in new application when starting activity "
1443291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                              + hr.intent.getComponent().flattenToShortString(), e);
1453291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                        throw e;
146160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org                    }
147160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org                } else {
148160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org                    stack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
149160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org                }
150160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org            }
151160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org        }
152160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org        return didSomething;
153160a7b0747492f3f735353d9582521f3314bf4dfdanno@chromium.org    }
154ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
155ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org    boolean allResumedActivitiesIdle() {
156ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1573291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            if (mStacks.get(stackNdx).mResumedActivity == null ||
1583291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                    !mStacks.get(stackNdx).mResumedActivity.idle) {
1599a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com                return false;
1609a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            }
1619a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        }
1629a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        return true;
163aca4968107b0e84a87cee0bad8e5ca21a02e4053christian.plesner.hansen@gmail.com    }
1649a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
1659a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    ActivityRecord getTasksLocked(int maxNum, IThumbnailReceiver receiver,
1669a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            PendingThumbnailsRecord pending, List<RunningTaskInfo> list) {
1679a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        ActivityRecord r = null;
1689a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        final int numStacks = mStacks.size();
1699a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
1709a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            final ActivityStack stack = mStacks.get(stackNdx);
1719a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            final ActivityRecord ar =
1729a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com                    stack.getTasksLocked(maxNum - list.size(), receiver, pending, list);
1739a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            if (isMainStack(stack)) {
1749a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com                r = ar;
1759a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            }
1769a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        }
1779a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        return r;
1783291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    }
179ddb913d619a6e602f53dd17b0fe71158ce66888dager@chromium.org
1809a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    void startHomeActivity(Intent intent, ActivityInfo aInfo) {
1819a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        mHomeStack.startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
182de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org                null, false, null);
1839a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    }
184aca4968107b0e84a87cee0bad8e5ca21a02e4053christian.plesner.hansen@gmail.com
185aca4968107b0e84a87cee0bad8e5ca21a02e4053christian.plesner.hansen@gmail.com    void handleAppDiedLocked(ProcessRecord app, boolean restarting) {
186aca4968107b0e84a87cee0bad8e5ca21a02e4053christian.plesner.hansen@gmail.com        // Just in case.
187aca4968107b0e84a87cee0bad8e5ca21a02e4053christian.plesner.hansen@gmail.com        final int numStacks = mStacks.size();
188aca4968107b0e84a87cee0bad8e5ca21a02e4053christian.plesner.hansen@gmail.com        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
1899a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            final ActivityStack stack = mStacks.get(stackNdx);
1909a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            if (stack.mPausingActivity != null && stack.mPausingActivity.app == app) {
1919a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com                if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG,
1929a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com                        "App died while pausing: " + stack.mPausingActivity);
1939a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com                stack.mPausingActivity = null;
1949a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            }
1959a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            if (stack.mLastPausedActivity != null && stack.mLastPausedActivity.app == app) {
1969a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com                stack.mLastPausedActivity = null;
1979a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            }
1989a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
1999a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            // Remove this application's activities from active lists.
2009a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            boolean hasVisibleActivities = stack.removeHistoryRecordsForAppLocked(app);
2019a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
2023291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            if (!restarting) {
2033291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                if (!stack.resumeTopActivityLocked(null)) {
2043291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                    // If there was nothing to resume, and we are not already
2053291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                    // restarting this process, but there is a visible activity that
2069a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com                    // is hosted by the process...  then make sure all visible
2079a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com                    // activities are running, taking care of restarting this
2089a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com                    // process.
2093291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                    if (hasVisibleActivities) {
2103291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                        stack.ensureActivitiesVisibleLocked(null, 0);
2119a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com                    }
2123291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org                }
2133291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            }
2143291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        }
2159a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    }
2163291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
2173291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    void closeSystemDialogsLocked() {
2189a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        final int numStacks = mStacks.size();
2193291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2203291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            final ActivityStack stack = mStacks.get(stackNdx);
2213291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            stack.closeSystemDialogsLocked();
2223291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        }
2233291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    }
2243291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org
2253291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    /**
2269a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com     * @return true if some activity was finished (or would have finished if doit were true).
2273291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org     */
2283291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org    boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
2293291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        boolean didSomething = false;
2303291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        final int numStacks = mStacks.size();
2319a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
2329a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            final ActivityStack stack = mStacks.get(stackNdx);
2339a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com            if (stack.forceStopPackageLocked(name, doit, evenPersistent, userId)) {
2349a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com                didSomething = true;
2353291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org            }
2363291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        }
2373291210ab99f306b74430ebbc4b7d939629e699fager@chromium.org        return didSomething;
2389a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    }
2399a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
2409a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    void resumeTopActivityLocked() {
241de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org        final int start, end;
242de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org        if (isHomeStackMain()) {
243de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org            start = 0;
244de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org            end = 1;
245de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org        } else {
246de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org            start = 1;
247de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org            end = mStacks.size();
248de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org        }
249de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org        for (int stackNdx = start; stackNdx < end; ++stackNdx) {
250de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org            mStacks.get(stackNdx).resumeTopActivityLocked(null);
251de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org        }
252de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    }
253de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
254de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    void finishTopRunningActivityLocked(ProcessRecord app) {
255de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org        final int numStacks = mStacks.size();
256de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
257de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org            final ActivityStack stack = mStacks.get(stackNdx);
258de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org            stack.finishTopRunningActivityLocked(app);
259de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org        }
260de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    }
261de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org
262de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    void scheduleIdleLocked() {
263de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
264de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org            mStacks.get(stackNdx).scheduleIdleLocked();
265de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org        }
266de88679a78f9dae12fdf7955610969ac4c79b0bemstarzinger@chromium.org    }
267
268    void findTaskToMoveToFrontLocked(int taskId, int flags, Bundle options) {
269        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
270            if (mStacks.get(stackNdx).findTaskToMoveToFrontLocked(taskId, flags, options)) {
271                return;
272            }
273        }
274    }
275
276    private ActivityStack getStack(int stackId) {
277        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
278            final ActivityStack stack = mStacks.get(stackNdx);
279            if (stack.getStackId() == stackId) {
280                return stack;
281            }
282        }
283        return null;
284    }
285
286    int createStack(int relativeStackId, int position, float weight) {
287        synchronized (this) {
288            while (true) {
289                if (++mLastStackId <= HOME_STACK_ID) {
290                    mLastStackId = HOME_STACK_ID + 1;
291                }
292                if (getStack(mLastStackId) == null) {
293                    break;
294                }
295            }
296            mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId, this));
297            return mLastStackId;
298        }
299    }
300
301    void moveTaskToStack(int taskId, int stackId, boolean toTop) {
302        final ActivityStack stack = getStack(stackId);
303        if (stack == null) {
304            Slog.w(TAG, "moveTaskToStack: no stack for id=" + stackId);
305            return;
306        }
307        stack.moveTask(taskId, toTop);
308    }
309
310    void goingToSleepLocked() {
311        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
312            mStacks.get(stackNdx).stopIfSleepingLocked();
313        }
314    }
315
316    boolean shutdownLocked(int timeout) {
317        boolean timedout = false;
318        final int numStacks = mStacks.size();
319        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
320            final ActivityStack stack = mStacks.get(stackNdx);
321            if (stack.mResumedActivity != null) {
322                stack.stopIfSleepingLocked();
323                final long endTime = System.currentTimeMillis() + timeout;
324                while (stack.mResumedActivity != null || stack.mPausingActivity != null) {
325                    long delay = endTime - System.currentTimeMillis();
326                    if (delay <= 0) {
327                        Slog.w(TAG, "Activity manager shutdown timed out");
328                        timedout = true;
329                        break;
330                    }
331                    try {
332                        mService.wait();
333                    } catch (InterruptedException e) {
334                    }
335                }
336            }
337        }
338        return timedout;
339    }
340
341    void comeOutOfSleepIfNeededLocked() {
342        final int numStacks = mStacks.size();
343        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
344            final ActivityStack stack = mStacks.get(stackNdx);
345            stack.awakeFromSleepingLocked();
346            stack.resumeTopActivityLocked(null);
347        }
348    }
349
350    void handleAppCrashLocked(ProcessRecord app) {
351        final int numStacks = mStacks.size();
352        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
353            final ActivityStack stack = mStacks.get(stackNdx);
354            stack.handleAppCrashLocked(app);
355        }
356    }
357
358    boolean updateConfigurationLocked(int changes, ActivityRecord starting) {
359        boolean kept = true;
360        final int numStacks = mStacks.size();
361        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
362            final ActivityStack stack = mStacks.get(stackNdx);
363            if (changes != 0 && starting == null) {
364                // If the configuration changed, and the caller is not already
365                // in the process of starting an activity, then find the top
366                // activity to check if its configuration needs to change.
367                starting = stack.topRunningActivityLocked(null);
368            }
369
370            if (starting != null) {
371                if (!stack.ensureActivityConfigurationLocked(starting, changes)) {
372                    kept = false;
373                }
374                // And we need to make sure at this point that all other activities
375                // are made visible with the correct configuration.
376                stack.ensureActivitiesVisibleLocked(starting, changes);
377            }
378        }
379        return kept;
380    }
381
382    void scheduleDestroyAllActivities(ProcessRecord app, String reason) {
383        final int numStacks = mStacks.size();
384        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
385            final ActivityStack stack = mStacks.get(stackNdx);
386            stack.scheduleDestroyActivities(app, false, reason);
387        }
388    }
389
390    boolean switchUserLocked(int userId, UserStartedState uss) {
391        boolean haveActivities = false;
392        final int numStacks = mStacks.size();
393        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
394            final ActivityStack stack = mStacks.get(stackNdx);
395            haveActivities |= stack.switchUserLocked(userId, uss);
396        }
397        return haveActivities;
398    }
399
400    public void dump(PrintWriter pw, String prefix) {
401        pw.print(prefix); pw.print("mDismissKeyguardOnNextActivity:");
402                pw.println(mDismissKeyguardOnNextActivity);
403    }
404
405    ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
406        return mMainStack.getDumpActivitiesLocked(name);
407    }
408
409    boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
410            boolean dumpClient, String dumpPackage) {
411        final int numStacks = mStacks.size();
412        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
413            final ActivityStack stack = mStacks.get(stackNdx);
414            pw.print("  Stack #"); pw.print(mStacks.indexOf(stack)); pw.println(":");
415            stack.dumpActivitiesLocked(fd, pw, dumpAll, dumpClient, dumpPackage);
416            pw.println(" ");
417            pw.println("  Running activities (most recent first):");
418            dumpHistoryList(fd, pw, stack.mLRUActivities, "  ", "Run", false, !dumpAll, false,
419                    dumpPackage);
420            if (stack.mWaitingVisibleActivities.size() > 0) {
421                pw.println(" ");
422                pw.println("  Activities waiting for another to become visible:");
423                dumpHistoryList(fd, pw, stack.mWaitingVisibleActivities, "  ", "Wait", false,
424                        !dumpAll, false, dumpPackage);
425            }
426            if (stack.mStoppingActivities.size() > 0) {
427                pw.println(" ");
428                pw.println("  Activities waiting to stop:");
429                dumpHistoryList(fd, pw, stack.mStoppingActivities, "  ", "Stop", false,
430                        !dumpAll, false, dumpPackage);
431            }
432            if (stack.mGoingToSleepActivities.size() > 0) {
433                pw.println(" ");
434                pw.println("  Activities waiting to sleep:");
435                dumpHistoryList(fd, pw, stack.mGoingToSleepActivities, "  ", "Sleep", false,
436                        !dumpAll, false, dumpPackage);
437            }
438            if (stack.mFinishingActivities.size() > 0) {
439                pw.println(" ");
440                pw.println("  Activities waiting to finish:");
441                dumpHistoryList(fd, pw, stack.mFinishingActivities, "  ", "Fin", false,
442                        !dumpAll, false, dumpPackage);
443            }
444        }
445
446        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
447            final ActivityStack stack = mStacks.get(stackNdx);
448            pw.print("  Stack #"); pw.println(mStacks.indexOf(stack));
449            if (stack.mPausingActivity != null) {
450                pw.println("  mPausingActivity: " + stack.mPausingActivity);
451            }
452            pw.println("  mResumedActivity: " + stack.mResumedActivity);
453            if (dumpAll) {
454                pw.println("  mLastPausedActivity: " + stack.mLastPausedActivity);
455                pw.println("  mSleepTimeout: " + stack.mSleepTimeout);
456            }
457        }
458
459        if (dumpAll) {
460            pw.println(" ");
461            pw.println("  mCurTaskId: " + mCurTaskId);
462        }
463        return true;
464    }
465
466    static final void dumpHistoryList(FileDescriptor fd, PrintWriter pw, List<ActivityRecord> list,
467            String prefix, String label, boolean complete, boolean brief, boolean client,
468            String dumpPackage) {
469        TaskRecord lastTask = null;
470        boolean needNL = false;
471        final String innerPrefix = prefix + "      ";
472        final String[] args = new String[0];
473        for (int i=list.size()-1; i>=0; i--) {
474            final ActivityRecord r = list.get(i);
475            if (dumpPackage != null && !dumpPackage.equals(r.packageName)) {
476                continue;
477            }
478            final boolean full = !brief && (complete || !r.isInHistory());
479            if (needNL) {
480                pw.println(" ");
481                needNL = false;
482            }
483            if (lastTask != r.task) {
484                lastTask = r.task;
485                pw.print(prefix);
486                pw.print(full ? "* " : "  ");
487                pw.println(lastTask);
488                if (full) {
489                    lastTask.dump(pw, prefix + "  ");
490                } else if (complete) {
491                    // Complete + brief == give a summary.  Isn't that obvious?!?
492                    if (lastTask.intent != null) {
493                        pw.print(prefix); pw.print("  ");
494                                pw.println(lastTask.intent.toInsecureStringWithClip());
495                    }
496                }
497            }
498            pw.print(prefix); pw.print(full ? "  * " : "    "); pw.print(label);
499            pw.print(" #"); pw.print(i); pw.print(": ");
500            pw.println(r);
501            if (full) {
502                r.dump(pw, innerPrefix);
503            } else if (complete) {
504                // Complete + brief == give a summary.  Isn't that obvious?!?
505                pw.print(innerPrefix); pw.println(r.intent.toInsecureString());
506                if (r.app != null) {
507                    pw.print(innerPrefix); pw.println(r.app);
508                }
509            }
510            if (client && r.app != null && r.app.thread != null) {
511                // flush anything that is already in the PrintWriter since the thread is going
512                // to write to the file descriptor directly
513                pw.flush();
514                try {
515                    TransferPipe tp = new TransferPipe();
516                    try {
517                        r.app.thread.dumpActivity(tp.getWriteFd().getFileDescriptor(),
518                                r.appToken, innerPrefix, args);
519                        // Short timeout, since blocking here can
520                        // deadlock with the application.
521                        tp.go(fd, 2000);
522                    } finally {
523                        tp.kill();
524                    }
525                } catch (IOException e) {
526                    pw.println(innerPrefix + "Failure while dumping the activity: " + e);
527                } catch (RemoteException e) {
528                    pw.println(innerPrefix + "Got a RemoteException while dumping the activity");
529                }
530                needNL = true;
531            }
532        }
533    }
534}
535