ActivityStack.java revision 7922882189a5c1cc62de7e91b067f90d9a3e2f2b
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2010 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * you may not use this file except in compliance with the License.
669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * You may obtain a copy of the License at
769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
1169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS,
1269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * See the License for the specific language governing permissions and
1469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server.am;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityManagerService.TAG;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityManagerService.localLOGV;
210795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopianimport static com.android.server.am.ActivityManagerService.DEBUG_CLEANUP;
220795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopianimport static com.android.server.am.ActivityManagerService.DEBUG_CONFIGURATION;
230795272aa226f4e965968a03daddc53ce30b7cdaMathias Agopianimport static com.android.server.am.ActivityManagerService.DEBUG_PAUSE;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityManagerService.DEBUG_RESULTS;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityManagerService.DEBUG_STACK;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityManagerService.DEBUG_SWITCH;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityManagerService.DEBUG_TASKS;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityManagerService.DEBUG_TRANSITION;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityManagerService.DEBUG_USER_LEAVING;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityManagerService.DEBUG_VISBILITY;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityManagerService.VALIDATE_TOKENS;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
35242d65bf9faf1d2bc3468490e510551140e23462San Mehat
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityStackSupervisor.DEBUG_ADD_REMOVE;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityStackSupervisor.DEBUG_APP;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityStackSupervisor.DEBUG_CONTAINERS;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityStackSupervisor.DEBUG_RELEASE;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityStackSupervisor.DEBUG_SAVED_STATE;
416af763bec7c3f4d50fee8dd0046409bb8a7fe8f6Glenn Kastenimport static com.android.server.am.ActivityStackSupervisor.DEBUG_SCREENSHOTS;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport static com.android.server.am.ActivityStackSupervisor.DEBUG_STATES;
43957e58670baad8c5995f1368e3b5280f0dbd891fSan Mehatimport static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
44160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate
45a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehatimport android.util.ArraySet;
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.app.IVoiceInteractor;
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.os.BatteryStatsImpl;
48160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tateimport com.android.server.Watchdog;
49160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tateimport com.android.server.am.ActivityManagerService.ItemMatcher;
50160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tateimport com.android.server.am.ActivityStackSupervisor.ActivityContainer;
51160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tateimport com.android.server.wm.AppTransition;
52160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tateimport com.android.server.wm.TaskGroup;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.server.wm.WindowManagerService;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.Activity;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ActivityManager;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ActivityOptions;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.AppGlobals;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.IActivityController;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ResultInfo;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ActivityManager.RunningTaskInfo;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.ActivityInfo;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Configuration;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Bitmap;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.net.Uri;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Bundle;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Debug;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
74e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.IBinder;
75e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.Looper;
76e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.Message;
77e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.PersistableBundle;
78e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.RemoteException;
79e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.SystemClock;
80e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.Trace;
81e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.os.UserHandle;
82e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.service.voice.IVoiceInteractionSession;
83e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.util.EventLog;
84e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.util.Slog;
85e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport android.view.Display;
86e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat
87e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport java.io.FileDescriptor;
88e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport java.io.PrintWriter;
89e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport java.lang.ref.WeakReference;
90e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport java.util.ArrayList;
91e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport java.util.Iterator;
92e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport java.util.List;
93e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehatimport java.util.Objects;
94e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * State and management of a single stack of activities.
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectfinal class ActivityStack {
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Ticks during which we check progress while waiting for an app to launch.
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int LAUNCH_TICK = 500;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // How long we wait until giving up on the last activity to pause.  This
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // is short because it directly impacts the responsiveness of starting the
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // next activity.
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int PAUSE_TIMEOUT = 500;
107887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // How long we wait for the activity to tell us it has stopped before
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // giving up.  This is a good amount of time because we really need this
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // from the application in order to get its saved state.
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int STOP_TIMEOUT = 10*1000;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes    // How long we wait until giving up on an activity telling us it has
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // finished destroying itself.
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int DESTROY_TIMEOUT = 10*1000;
11669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // How long until we reset a task when the user returns to it.  Currently
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // disabled.
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final long ACTIVITY_INACTIVE_RESET_TIME = 0;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // How long between activity launches that we consider safe to not warn
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // the user about an unexpected activity being launched on top.
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final long START_WARN_TIME = 5*1000;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Set to false to disable the preview that is shown while a new activity
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // is being started.
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean SHOW_APP_STARTING_PREVIEW = true;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // How long to wait for all background Activities to redraw following a call to
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // convertToTranslucent().
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final long TRANSLUCENT_CONVERSION_TIMEOUT = 2000;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean SCREENSHOT_FORCE_565 = ActivityManager.isLowRamDeviceStatic();
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    enum ActivityState {
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        INITIALIZING,
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        RESUMED,
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PAUSING,
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        PAUSED,
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        STOPPING,
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        STOPPED,
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        FINISHING,
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        DESTROYING,
14469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        DESTROYED
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes    final ActivityManagerService mService;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final WindowManagerService mWindowManager;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The back history of all previous (and possibly still
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * running) activities.  It contains #TaskRecord objects.
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private ArrayList<TaskRecord> mTaskHistory = new ArrayList<TaskRecord>();
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Used for validating app tokens with window manager.
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ArrayList<TaskGroup> mValidateAppTokens = new ArrayList<TaskGroup>();
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * List of running activities, sorted by recent usage.
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The first entry in the list is the least recently used.
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * It contains HistoryRecord objects.
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ArrayList<ActivityRecord> mLRUActivities = new ArrayList<ActivityRecord>();
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Animations that for the current transition have requested not to
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * be considered for the transition animation.
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
172e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat    final ArrayList<ActivityRecord> mNoAnimActivities = new ArrayList<ActivityRecord>();
173e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat
174887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn    /**
175887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn     * When we are in the process of pausing an activity, before starting the
176887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn     * next one, this variable holds the activity that is currently being paused.
177e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat     */
178e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat    ActivityRecord mPausingActivity = null;
179e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat
180e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat    /**
18169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes     * This is the last activity that we put into the paused state.  This is
1823e458241d9930465a20a861ecb42744355d48e48San Mehat     * used to determine if we need to do an activity transition while sleeping,
1833e458241d9930465a20a861ecb42744355d48e48San Mehat     * when we normally hold the top activity paused.
1843e458241d9930465a20a861ecb42744355d48e48San Mehat     */
1853e458241d9930465a20a861ecb42744355d48e48San Mehat    ActivityRecord mLastPausedActivity = null;
1863e458241d9930465a20a861ecb42744355d48e48San Mehat
1873e458241d9930465a20a861ecb42744355d48e48San Mehat    /**
18869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes     * Activities that specify No History must be removed once the user navigates away from them.
1893e458241d9930465a20a861ecb42744355d48e48San Mehat     * If the device goes to sleep with such an activity in the paused state then we save it here
1903e458241d9930465a20a861ecb42744355d48e48San Mehat     * and finish it later if another activity replaces it on wakeup.
1913e458241d9930465a20a861ecb42744355d48e48San Mehat     */
1923e458241d9930465a20a861ecb42744355d48e48San Mehat    ActivityRecord mLastNoHistoryActivity = null;
193a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat
194a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat    /**
195a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat     * Current activity that is resumed, or null if there is none.
196a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat     */
197a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat    ActivityRecord mResumedActivity = null;
198a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat
199a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat    /**
200a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat     * This is the last activity that has been started.  It is only used to
201a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat     * identify when multiple activities are started at once so that the user
202a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat     * can be warned they may not be in the activity they think they are.
203a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat     */
204a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat    ActivityRecord mLastStartedActivity = null;
205a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat
20669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes    // The topmost Activity passed to convertToTranslucent(). When non-null it means we are
207a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat    // waiting for all Activities in mUndrawnActivitiesBelowTopTranslucent to be removed as they
208a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat    // are drawn. When the last member of mUndrawnActivitiesBelowTopTranslucent is removed the
209a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat    // Activity in mTranslucentActivityWaiting is notified via
210a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat    // Activity.onTranslucentConversionComplete(false). If a timeout occurs prior to the last
211a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat    // background activity being drawn then the same call will be made with a true value.
212a5109a878eeff22e32ee5ce1b1cd15e8daad5234San Mehat    ActivityRecord mTranslucentActivityWaiting = null;
2133e458241d9930465a20a861ecb42744355d48e48San Mehat    private ArrayList<ActivityRecord> mUndrawnActivitiesBelowTopTranslucent =
2143e458241d9930465a20a861ecb42744355d48e48San Mehat            new ArrayList<ActivityRecord>();
2151fd0ec738b0a2b97cc28701aa37b1a9869afc684San Mehat
2161fd0ec738b0a2b97cc28701aa37b1a9869afc684San Mehat    /**
2171fd0ec738b0a2b97cc28701aa37b1a9869afc684San Mehat     * Set when we know we are going to be calling updateConfiguration()
2183e458241d9930465a20a861ecb42744355d48e48San Mehat     * soon, so want to skip intermediate config checks.
2193e458241d9930465a20a861ecb42744355d48e48San Mehat     */
2203e458241d9930465a20a861ecb42744355d48e48San Mehat    boolean mConfigWillChange;
2213e458241d9930465a20a861ecb42744355d48e48San Mehat
2227e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    long mLaunchStartTime = 0;
2237e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    long mFullyDrawnStartTime = 0;
2247e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat
2253e458241d9930465a20a861ecb42744355d48e48San Mehat    /**
2263e458241d9930465a20a861ecb42744355d48e48San Mehat     * Save the most recent screenshot for reuse. This keeps Recents from taking two identical
2277e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat     * screenshots, one for the Recents thumbnail and one for the pauseActivity thumbnail.
2287e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat     */
2297e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    private ActivityRecord mLastScreenshotActivity = null;
2307e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    private Bitmap mLastScreenshotBitmap = null;
2317e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat
2327e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    int mCurrentUser;
2331fd0ec738b0a2b97cc28701aa37b1a9869afc684San Mehat
2347e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    final int mStackId;
2357e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    final ActivityContainer mActivityContainer;
2367e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    /** The other stacks, in order, on the attached display. Updated at attach/detach time. */
2377e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    ArrayList<ActivityStack> mStacks;
2387e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    /** The attached Display's unique identifier, or -1 if detached */
2397e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat    int mDisplayId;
2407e63789a0e0689d940609b1daceebc1bc08dcbefSan Mehat
24169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes    /** Run all ActivityStacks through this */
24284bb52ed614f3a13370c923a8bc2a8b7c6db8d30Dianne Hackborn    final ActivityStackSupervisor mStackSupervisor;
243242d65bf9faf1d2bc3468490e510551140e23462San Mehat
2440a42b811aea490a9a605b75f0320101f6eafd283San Mehat    /** Used to keep resumeTopActivityLocked() from being entered recursively */
245242d65bf9faf1d2bc3468490e510551140e23462San Mehat    private boolean inResumeTopActivity;
2463e458241d9930465a20a861ecb42744355d48e48San Mehat
2473e458241d9930465a20a861ecb42744355d48e48San Mehat    static final int PAUSE_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 1;
2483e458241d9930465a20a861ecb42744355d48e48San Mehat    static final int DESTROY_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 2;
2493e458241d9930465a20a861ecb42744355d48e48San Mehat    static final int LAUNCH_TICK_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 3;
250160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate    static final int STOP_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 4;
251160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate    static final int DESTROY_ACTIVITIES_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 5;
252160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate    static final int TRANSLUCENT_TIMEOUT_MSG = ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 6;
253160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate    static final int RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG =
25471f2cf116aab893e224056c38ab146bd1538dd3eSteve Block            ActivityManagerService.FIRST_ACTIVITY_STACK_MSG + 7;
255160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate
256160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate    static class ScheduleDestroyArgs {
257160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate        final ProcessRecord mOwner;
258160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate        final String mReason;
259160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate        ScheduleDestroyArgs(ProcessRecord owner, String reason) {
260160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate            mOwner = owner;
261160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate            mReason = reason;
262160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate        }
263160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate    }
264160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate
265160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate    final Handler mHandler;
266160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final class ActivityStackHandler extends Handler {
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //public Handler() {
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        //    if (localLOGV) Slog.v(TAG, "Handler started!");
270160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate        //}
271160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate        ActivityStackHandler(Looper looper) {
272160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate            super(looper);
273160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate        }
274160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate
275160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate        @Override
276160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate        public void handleMessage(Message msg) {
277160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate            switch (msg.what) {
278160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate                case PAUSE_TIMEOUT_MSG: {
279160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate                    ActivityRecord r = (ActivityRecord)msg.obj;
280160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate                    // We don't at this point know if the activity is fullscreen,
281160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate                    // so we need to be conservative and assume it isn't.
282160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate                    Slog.w(TAG, "Activity pause timeout for " + r);
283160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate                    synchronized (mService) {
284160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate                        if (r.app != null) {
285887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn                            mService.logAppTooSlow(r.app, r.pauseTime, "pausing " + r);
286887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn                        }
287887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn                        activityPausedLocked(r.appToken, true);
288887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn                    }
289887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn                } break;
290887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn                case LAUNCH_TICK_MSG: {
291887f355f99ff83d568ef2885a4fdcaae475583dfDianne Hackborn                    ActivityRecord r = (ActivityRecord)msg.obj;
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    synchronized (mService) {
29369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                        if (r.continueLaunchTickingLocked()) {
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mService.logAppTooSlow(r.app, r.launchTickTime, "launching " + r);
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } break;
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case DESTROY_TIMEOUT_MSG: {
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ActivityRecord r = (ActivityRecord)msg.obj;
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // We don't at this point know if the activity is fullscreen,
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // so we need to be conservative and assume it isn't.
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Slog.w(TAG, "Activity destroy timeout for " + r);
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    synchronized (mService) {
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        activityDestroyedLocked(r != null ? r.appToken : null);
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } break;
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case STOP_TIMEOUT_MSG: {
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ActivityRecord r = (ActivityRecord)msg.obj;
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // We don't at this point know if the activity is fullscreen,
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // so we need to be conservative and assume it isn't.
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Slog.w(TAG, "Activity stop timeout for " + r);
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    synchronized (mService) {
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (r.isInHistory()) {
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            activityStoppedLocked(r, null, null, null);
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } break;
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                case DESTROY_ACTIVITIES_MSG: {
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ScheduleDestroyArgs args = (ScheduleDestroyArgs)msg.obj;
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    synchronized (mService) {
32110e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown                        destroyActivitiesLocked(args.mOwner, args.mReason);
32210e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown                    }
32310e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown                } break;
32410e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown                case TRANSLUCENT_TIMEOUT_MSG: {
32510e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown                    synchronized (mService) {
32610e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown                        notifyActivityDrawnLocked(null);
32710e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown                    }
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } break;
32910e89712863f5b91a2982dc1783fbdfe39c1485dJeff Brown                case RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG: {
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    synchronized (mService) {
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        final ActivityRecord r = getVisibleBehindActivity();
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        Slog.e(TAG, "Timeout waiting for cancelVisibleBehind player=" + r);
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (r != null) {
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mService.killAppAtUsersRequest(r.app, null);
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
33769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                } break;
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
34069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes    }
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int numActivities() {
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int count = 0;
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            count += mTaskHistory.get(taskNdx).mActivities.size();
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return count;
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ActivityStack(ActivityStackSupervisor.ActivityContainer activityContainer) {
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mActivityContainer = activityContainer;
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStackSupervisor = activityContainer.getOuter();
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mService = mStackSupervisor.mService;
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler = new ActivityStackHandler(mService.mHandler.getLooper());
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mWindowManager = mService.mWindowManager;
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStackId = activityContainer.mStackId;
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurrentUser = mService.mCurrentUserId;
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Checks whether the userid is a profile of the current user.
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean isCurrentProfileLocked(int userId) {
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (userId == mCurrentUser) return true;
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < mService.mCurrentProfileIds.length; i++) {
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mService.mCurrentProfileIds[i] == userId) return true;
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
3690bca96bcbfe559f9330a01f723c5c9cba51ec05aMarco Nelissen    }
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean okToShowLocked(ActivityRecord r) {
37269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        return isCurrentProfileLocked(r.userId)
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                || (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0;
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ActivityRecord topRunningActivityLocked(ActivityRecord notTop) {
37769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked(notTop);
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (r != null) {
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return r;
38169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes            }
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ActivityRecord topRunningNonDelayedActivityLocked(ActivityRecord notTop) {
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final TaskRecord task = mTaskHistory.get(taskNdx);
3890bca96bcbfe559f9330a01f723c5c9cba51ec05aMarco Nelissen            final ArrayList<ActivityRecord> activities = task.mActivities;
39069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ActivityRecord r = activities.get(activityNdx);
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!r.finishing && !r.delayedResume && r != notTop && okToShowLocked(r)) {
39369a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                    return r;
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * This is a simplified version of topRunningActivityLocked that provides a number of
4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * optional skip-over modes.  It is intended for use with the ActivityController hook only.
4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param token If non-null, any history records matching this token will be skipped.
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param taskId If non-zero, we'll attempt to skip over records with the same task ID.
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return Returns the HistoryRecord of the next activity on the stack.
4080bca96bcbfe559f9330a01f723c5c9cba51ec05aMarco Nelissen     */
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ActivityRecord topRunningActivityLocked(IBinder token, int taskId) {
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            TaskRecord task = mTaskHistory.get(taskNdx);
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (task.taskId == taskId) {
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ArrayList<ActivityRecord> activities = task.mActivities;
41669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes            for (int i = activities.size() - 1; i >= 0; --i) {
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final ActivityRecord r = activities.get(i);
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Note: the taskId check depends on real taskId fields being non-zero
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!r.finishing && (token != r.appToken) && okToShowLocked(r)) {
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return r;
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
42469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        return null;
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
42669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final ActivityRecord topActivity() {
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
42969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes            ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final ActivityRecord r = activities.get(activityNdx);
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!r.finishing) {
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return r;
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
43669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        }
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final TaskRecord topTask() {
4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int size = mTaskHistory.size();
44269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        if (size > 0) {
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mTaskHistory.get(size - 1);
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
44569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        return null;
4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    TaskRecord taskForIdLocked(int id) {
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final TaskRecord task = mTaskHistory.get(taskNdx);
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (task.taskId == id) {
45269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                return task;
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
45869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes    ActivityRecord isInStackLocked(IBinder token) {
4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ActivityRecord r = ActivityRecord.forToken(token);
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (r != null) {
4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final TaskRecord task = r.task;
46269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes            if (task != null && task.mActivities.contains(r) && mTaskHistory.contains(task)) {
4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (task.stack != this) Slog.w(TAG,
4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    "Illegal state! task does not point to stack it is in.");
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return r;
4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
46769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        }
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final boolean updateLRUListLocked(ActivityRecord r) {
47269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        final boolean hadit = mLRUActivities.remove(r);
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mLRUActivities.add(r);
47469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        return hadit;
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final boolean isHomeStack() {
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mStackId == HOME_STACK_ID;
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
48069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final boolean isOnHomeDisplay() {
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return isAttached() &&
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mActivityContainer.mActivityDisplay.mDisplayId == Display.DEFAULT_DISPLAY;
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
48669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes    final void moveToFront() {
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (isAttached()) {
48869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes            if (isOnHomeDisplay()) {
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStackSupervisor.moveHomeStack(isHomeStack());
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStacks.remove(this);
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStacks.add(this);
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final boolean isAttached() {
497add868cebaf62cffe96e79764ea0b7f2320a03ebAmith Yamasani        return mStacks != null;
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the top activity in any existing task matching the given
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Intent.  Returns null if no such task is found.
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ActivityRecord findTaskLocked(ActivityRecord target) {
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Intent intent = target.intent;
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ActivityInfo info = target.info;
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ComponentName cls = intent.getComponent();
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info.targetActivity != null) {
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cls = new ComponentName(info.packageName, info.targetActivity);
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int userId = UserHandle.getUserId(info.applicationInfo.uid);
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean isDocument = intent != null & intent.isDocument();
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If documentData is non-null then it must match the existing task data.
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Uri documentData = isDocument ? intent.getData() : null;
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + target + " in " + this);
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final TaskRecord task = mTaskHistory.get(taskNdx);
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (task.voiceSession != null) {
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // We never match voice sessions; those always run independently.
52169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": voice session");
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (task.userId != userId) {
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Looking for a different task.
52669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": different user");
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final ActivityRecord r = task.getTopActivity();
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (r == null || r.finishing || r.userId != userId ||
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": mismatch root " + r);
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
53569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final Intent taskIntent = task.intent;
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final Intent affinityIntent = task.affinityIntent;
53869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes            final boolean taskIsDocument;
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final Uri taskDocumentData;
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (taskIntent != null && taskIntent.isDocument()) {
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                taskIsDocument = true;
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                taskDocumentData = taskIntent.getData();
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (affinityIntent != null && affinityIntent.isDocument()) {
54469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                taskIsDocument = true;
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                taskDocumentData = affinityIntent.getData();
54669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes            } else {
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                taskIsDocument = false;
54869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                taskDocumentData = null;
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG_TASKS) Slog.d(TAG, "Comparing existing cls="
55269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                    + taskIntent.getComponent().flattenToShortString()
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + "/aff=" + r.task.rootAffinity + " to new cls="
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!isDocument && !taskIsDocument && task.rootAffinity != null) {
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (task.rootAffinity.equals(target.taskAffinity)) {
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (DEBUG_TASKS) Slog.d(TAG, "Found matching affinity!");
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return r;
55969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                }
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (taskIntent != null && taskIntent.getComponent() != null &&
56169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                    taskIntent.getComponent().compareTo(cls) == 0 &&
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Objects.equals(documentData, taskDocumentData)) {
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //dump();
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + r.intent);
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return r;
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (affinityIntent != null && affinityIntent.getComponent() != null &&
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    affinityIntent.getComponent().compareTo(cls) == 0 &&
57069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                    Objects.equals(documentData, taskDocumentData)) {
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG_TASKS) Slog.d(TAG, "Found matching class!");
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //dump();
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG_TASKS) Slog.d(TAG, "For Intent " + intent + " bringing to top: "
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + r.intent);
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return r;
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (DEBUG_TASKS) {
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Slog.d(TAG, "Not a match: " + task);
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Returns the first activity (starting from the top of the stack) that
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is the same as the given activity.  Returns null if no such activity
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is found.
5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ActivityRecord findActivityLocked(Intent intent, ActivityInfo info) {
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ComponentName cls = intent.getComponent();
59169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        if (info.targetActivity != null) {
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cls = new ComponentName(info.packageName, info.targetActivity);
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int userId = UserHandle.getUserId(info.applicationInfo.uid);
59569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
59769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes            TaskRecord task = mTaskHistory.get(taskNdx);
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!isCurrentProfileLocked(task.userId)) {
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
60169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes            final ArrayList<ActivityRecord> activities = task.mActivities;
6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ActivityRecord r = activities.get(activityNdx);
6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (!r.finishing && r.intent.getComponent().equals(cls) && r.userId == userId) {
6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    //Slog.i(TAG, "Found matching class!");
60669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                    //dump();
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    //Slog.i(TAG, "For Intent " + intent + " bringing to top: " + r.intent);
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    return r;
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
61069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes            }
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /*
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Move the activities around in the stack to bring a user to the foreground.
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final void switchUserLocked(int userId) {
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurrentUser == userId) {
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurrentUser = userId;
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
625c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        // Move userId's tasks to the top.
62669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        int index = mTaskHistory.size();
627c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        for (int i = 0; i < index; ) {
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            TaskRecord task = mTaskHistory.get(i);
62969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes            if (isCurrentProfileLocked(task.userId)) {
6309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG_TASKS) Slog.d(TAG, "switchUserLocked: stack=" + getStackId() +
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        " moving " + task + " to top");
6329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTaskHistory.remove(i);
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mTaskHistory.add(task);
63469a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                --index;
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Use same value for i.
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ++i;
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (VALIDATE_TOKENS) {
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            validateAppTokensLocked();
6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void minimalResumeActivityLocked(ActivityRecord r) {
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        r.state = ActivityState.RESUMED;
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + r
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " (starting new instance)");
6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        r.stopped = false;
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mResumedActivity = r;
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        r.task.touchActiveTime();
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mService.addRecentTaskLocked(r.task);
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        completeResumeLocked(r);
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mStackSupervisor.checkReadyForSleepLocked();
655c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        setLaunchTime(r);
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DEBUG_SAVED_STATE) Slog.i(TAG, "Launch completed; removing icicle of " + r.icicle);
65769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes    }
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
65969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes    private void startLaunchTraces() {
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFullyDrawnStartTime != 0)  {
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "launching", 0);
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Trace.asyncTraceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
667c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    private void stopFullyDrawnTraceIfNeeded() {
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mFullyDrawnStartTime != 0 && mLaunchStartTime == 0) {
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Trace.asyncTraceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER, "drawing", 0);
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mFullyDrawnStartTime = 0;
67169a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        }
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
674c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    void setLaunchTime(ActivityRecord r) {
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (r.displayStartTime == 0) {
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            r.fullyDrawnStartTime = r.displayStartTime = SystemClock.uptimeMillis();
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mLaunchStartTime == 0) {
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                startLaunchTraces();
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLaunchStartTime = mFullyDrawnStartTime = r.displayStartTime;
680c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            }
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mLaunchStartTime == 0) {
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startLaunchTraces();
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLaunchStartTime = mFullyDrawnStartTime = SystemClock.uptimeMillis();
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
68669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes
687c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    void clearLaunchTime(ActivityRecord r) {
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Make sure that there is no activity waiting for this to launch.
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mStackSupervisor.mWaitingActivityLaunched.isEmpty()) {
690c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            r.displayStartTime = r.fullyDrawnStartTime = 0;
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStackSupervisor.removeTimeoutsForActivityLocked(r);
6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStackSupervisor.scheduleIdleTimeoutLocked(r);
6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
69569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes    }
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
69769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes    void awakeFromSleepingLocked() {
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Ensure activities are no longer sleeping.
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                activities.get(activityNdx).setSleeping(false);
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return true if something must be done before going to sleep.
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean checkReadyForSleepLocked() {
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mResumedActivity != null) {
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Still have something resumed; can't sleep until it is paused.
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG_PAUSE) Slog.v(TAG, "Sleep needs to pause " + mResumedActivity);
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG_USER_LEAVING) Slog.v(TAG, "Sleep => pause with userLeaving=false");
7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            startPausingLocked(false, true, false, false);
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
71769a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        }
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPausingActivity != null) {
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Still waiting for something to pause; can't sleep yet.
7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG_PAUSE) Slog.v(TAG, "Sleep still waiting to pause " + mPausingActivity);
7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
72569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes    }
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void goToSleep() {
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ensureActivitiesVisibleLocked(null, 0);
729c64edde69d18498fb2954f71a546357b07ab996aEvan Millar
73069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        // Make sure any stopped but visible activities are now sleeping.
731c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        // This ensures that the activity's onStop() is called.
732c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
733c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
734c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
73569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                final ActivityRecord r = activities.get(activityNdx);
73669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                if (r.state == ActivityState.STOPPING || r.state == ActivityState.STOPPED) {
737c64edde69d18498fb2954f71a546357b07ab996aEvan Millar                    r.setSleeping(true);
73869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                }
739c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            }
74069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        }
741c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    }
742c64edde69d18498fb2954f71a546357b07ab996aEvan Millar
743c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    /**
744c64edde69d18498fb2954f71a546357b07ab996aEvan Millar     * This resets the saved state from the last screenshot, forcing a new screenshot to be taken
745c64edde69d18498fb2954f71a546357b07ab996aEvan Millar     * again when requested.
746c64edde69d18498fb2954f71a546357b07ab996aEvan Millar     */
747c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    private void invalidateLastScreenshot() {
748c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        mLastScreenshotActivity = null;
74969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        if (mLastScreenshotBitmap != null) {
750c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            mLastScreenshotBitmap.recycle();
751c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        }
752c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        mLastScreenshotBitmap = null;
753c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    }
754c64edde69d18498fb2954f71a546357b07ab996aEvan Millar
755c64edde69d18498fb2954f71a546357b07ab996aEvan Millar    public final Bitmap screenshotActivities(ActivityRecord who) {
756c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        if (DEBUG_SCREENSHOTS) Slog.d(TAG, "screenshotActivities: " + who);
757c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        if (who.noDisplay) {
758c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            if (DEBUG_SCREENSHOTS) Slog.d(TAG, "\tNo display");
759c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            return null;
76069a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        }
761c64edde69d18498fb2954f71a546357b07ab996aEvan Millar
762c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        if (isHomeStack()) {
763c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            // This is an optimization -- since we never show Home or Recents within Recents itself,
764c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            // we can just go ahead and skip taking the screenshot if this is the home stack.  In
76569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes            // the case where the most recent task is not the task that was supplied, then the stack
766c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            // has changed, so invalidate the last screenshot().
767c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            invalidateLastScreenshot();
768c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            if (DEBUG_SCREENSHOTS) Slog.d(TAG, "\tIs Home stack? " + isHomeStack());
76969a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes            return null;
770c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        }
771c64edde69d18498fb2954f71a546357b07ab996aEvan Millar
772c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        int w = mService.mThumbnailWidth;
773c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        int h = mService.mThumbnailHeight;
774c64edde69d18498fb2954f71a546357b07ab996aEvan Millar        if (w > 0) {
77569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes            if (who != mLastScreenshotActivity || mLastScreenshotBitmap == null
77669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                    || mLastScreenshotActivity.state == ActivityState.RESUMED
777c64edde69d18498fb2954f71a546357b07ab996aEvan Millar                    || mLastScreenshotBitmap.getWidth() != w
77869a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                    || mLastScreenshotBitmap.getHeight() != h) {
779c64edde69d18498fb2954f71a546357b07ab996aEvan Millar                if (DEBUG_SCREENSHOTS) Slog.d(TAG, "\tUpdating screenshot");
780c64edde69d18498fb2954f71a546357b07ab996aEvan Millar                mLastScreenshotActivity = who;
7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLastScreenshotBitmap = mWindowManager.screenshotApplications(
7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        who.appToken, Display.DEFAULT_DISPLAY, w, h, SCREENSHOT_FORCE_565);
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mLastScreenshotBitmap != null) {
78569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                if (DEBUG_SCREENSHOTS) Slog.d(TAG, "\tReusing last screenshot");
7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return mLastScreenshotBitmap.copy(mLastScreenshotBitmap.getConfig(), true);
7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        Slog.e(TAG, "Invalid thumbnail dimensions: " + w + "x" + h);
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Start pausing the currently resumed activity.  It is an error to call this if there
7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * is already an activity being paused or there is no resumed activity.
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param userLeaving True if this should result in an onUserLeaving to the current activity.
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param uiSleeping True if this is happening with the user interface going to sleep (the
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * screen turning off).
800906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn     * @param resuming True if this is being called as part of resuming the top activity, so
801906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn     * we shouldn't try to instigate a resume here.
802906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn     * @param dontWait True if the caller does not want to wait for the pause to complete.  If
803906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn     * set to true, we will immediately complete the pause here before returning.
804906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn     * @return Returns true if an activity now is in the PAUSING state, and we are waiting for
805906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn     * it to tell us when it is done.
806906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn     */
8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping, boolean resuming,
8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            boolean dontWait) {
8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPausingActivity != null) {
8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity);
8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            completePauseLocked(false);
81269a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes        }
8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ActivityRecord prev = mResumedActivity;
8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (prev == null) {
81569a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes            if (!resuming) {
81669a017bc1d1649350f830dfada5c6ed5eac0b770Elliott Hughes                Slog.wtf(TAG, "Trying to pause when nothing is resumed");
8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mStackSupervisor.resumeTopActivitiesLocked();
8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mActivityContainer.mParentActivity == null) {
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Top level stack, not a child. Look for child stacks.
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mStackSupervisor.pauseChildStacks(prev, userLeaving, uiSleeping, resuming, dontWait);
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSING: " + prev);
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        else if (DEBUG_PAUSE) Slog.v(TAG, "Start pausing: " + prev);
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mResumedActivity = null;
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mPausingActivity = prev;
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mLastPausedActivity = prev;
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mLastNoHistoryActivity = (prev.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                || (prev.info.flags & ActivityInfo.FLAG_NO_HISTORY) != 0 ? prev : null;
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        prev.state = ActivityState.PAUSING;
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        prev.task.touchActiveTime();
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        clearLaunchTime(prev);
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mService.mHasRecents && (next == null || next.noDisplay || next.task != prev.task)) {
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            prev.updateThumbnail(screenshotActivities(prev), null);
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        stopFullyDrawnTraceIfNeeded();
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mService.updateCpuStats();
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (prev.app != null && prev.app.thread != null) {
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending pause: " + prev);
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                EventLog.writeEvent(EventLogTags.AM_PAUSE_ACTIVITY,
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        prev.userId, System.identityHashCode(prev),
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        prev.shortComponentName);
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mService.updateUsageStats(prev, false);
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                prev.app.thread.schedulePauseActivity(prev.appToken, prev.finishing,
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        userLeaving, prev.configChangeFlags, dontWait);
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (Exception e) {
855160edb3645f8b7012bab70ae6e6e8c4a5733082bChristopher Tate                // Ignore exception, if process died other code will cleanup.
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Slog.w(TAG, "Exception thrown during pause", e);
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mPausingActivity = null;
858e9d376b801b7890b1ef5006ed55de4208e64bb63San Mehat                mLastPausedActivity = null;
8593e458241d9930465a20a861ecb42744355d48e48San Mehat                mLastNoHistoryActivity = null;
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mPausingActivity = null;
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastPausedActivity = null;
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastNoHistoryActivity = null;
865906497c574d45d8dfd295b16dece0d0bc32c0895Dianne Hackborn        }
8660bca96bcbfe559f9330a01f723c5c9cba51ec05aMarco Nelissen
8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If we are not going to sleep, we want to ensure the device is
8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // awake until the next activity is started.
8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mService.isSleepingOrShuttingDown()) {
870c64edde69d18498fb2954f71a546357b07ab996aEvan Millar            mStackSupervisor.acquireLaunchWakelock();
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mPausingActivity != null) {
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // Have the window manager pause its key dispatching until the new
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // activity has started.  If we're pausing the activity just because
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // the screen is being turned off and the UI is sleeping, don't interrupt
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // key dispatch; the same activity will pick it up again on wakeup.
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!uiSleeping) {
8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                prev.pauseKeyDispatchingLocked();
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG_PAUSE) Slog.v(TAG, "Key dispatch not paused for screen off");
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
884            if (dontWait) {
885                // If the caller said they don't want to wait for the pause, then complete
886                // the pause now.
887                completePauseLocked(false);
888                return false;
889
890            } else {
891                // Schedule a pause timeout in case the app doesn't respond.
892                // We don't give it much time because this directly impacts the
893                // responsiveness seen by the user.
894                Message msg = mHandler.obtainMessage(PAUSE_TIMEOUT_MSG);
895                msg.obj = prev;
896                prev.pauseTime = SystemClock.uptimeMillis();
897                mHandler.sendMessageDelayed(msg, PAUSE_TIMEOUT);
898                if (DEBUG_PAUSE) Slog.v(TAG, "Waiting for pause to complete...");
899                return true;
900            }
901
902        } else {
903            // This activity failed to schedule the
904            // pause, so just treat it as being paused now.
905            if (DEBUG_PAUSE) Slog.v(TAG, "Activity not running, resuming next.");
906            if (!resuming) {
907                mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null);
908            }
909            return false;
910        }
911    }
912
913    final void activityPausedLocked(IBinder token, boolean timeout) {
914        if (DEBUG_PAUSE) Slog.v(
915            TAG, "Activity paused: token=" + token + ", timeout=" + timeout);
916
917        final ActivityRecord r = isInStackLocked(token);
918        if (r != null) {
919            mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
920            if (mPausingActivity == r) {
921                if (DEBUG_STATES) Slog.v(TAG, "Moving to PAUSED: " + r
922                        + (timeout ? " (due to timeout)" : " (pause complete)"));
923                completePauseLocked(true);
924            } else {
925                EventLog.writeEvent(EventLogTags.AM_FAILED_TO_PAUSE,
926                        r.userId, System.identityHashCode(r), r.shortComponentName,
927                        mPausingActivity != null
928                            ? mPausingActivity.shortComponentName : "(none)");
929            }
930        }
931    }
932
933    final void activityStoppedLocked(ActivityRecord r, Bundle icicle,
934            PersistableBundle persistentState, CharSequence description) {
935        if (r.state != ActivityState.STOPPING) {
936            Slog.i(TAG, "Activity reported stop, but no longer stopping: " + r);
937            mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
938            return;
939        }
940        if (persistentState != null) {
941            r.persistentState = persistentState;
942            mService.notifyTaskPersisterLocked(r.task, false);
943        }
944        if (DEBUG_SAVED_STATE) Slog.i(TAG, "Saving icicle of " + r + ": " + icicle);
945        if (icicle != null) {
946            // If icicle is null, this is happening due to a timeout, so we
947            // haven't really saved the state.
948            r.icicle = icicle;
949            r.haveState = true;
950            r.launchCount = 0;
951            r.updateThumbnail(null, description);
952        }
953        if (!r.stopped) {
954            if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPED: " + r + " (stop complete)");
955            mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
956            r.stopped = true;
957            r.state = ActivityState.STOPPED;
958            if (mActivityContainer.mActivityDisplay.mVisibleBehindActivity == r) {
959                mStackSupervisor.requestVisibleBehindLocked(r, false);
960            }
961            if (r.finishing) {
962                r.clearOptionsLocked();
963            } else {
964                if (r.configDestroy) {
965                    destroyActivityLocked(r, true, "stop-config");
966                    mStackSupervisor.resumeTopActivitiesLocked();
967                } else {
968                    mStackSupervisor.updatePreviousProcessLocked(r);
969                }
970            }
971        }
972    }
973
974    private void completePauseLocked(boolean resumeNext) {
975        ActivityRecord prev = mPausingActivity;
976        if (DEBUG_PAUSE) Slog.v(TAG, "Complete pause: " + prev);
977
978        if (prev != null) {
979            prev.state = ActivityState.PAUSED;
980            if (prev.finishing) {
981                if (DEBUG_PAUSE) Slog.v(TAG, "Executing finish of activity: " + prev);
982                prev = finishCurrentActivityLocked(prev, FINISH_AFTER_VISIBLE, false);
983            } else if (prev.app != null) {
984                if (DEBUG_PAUSE) Slog.v(TAG, "Enqueueing pending stop: " + prev);
985                if (prev.waitingVisible) {
986                    prev.waitingVisible = false;
987                    mStackSupervisor.mWaitingVisibleActivities.remove(prev);
988                    if (DEBUG_SWITCH || DEBUG_PAUSE) Slog.v(
989                            TAG, "Complete pause, no longer waiting: " + prev);
990                }
991                if (prev.configDestroy) {
992                    // The previous is being paused because the configuration
993                    // is changing, which means it is actually stopping...
994                    // To juggle the fact that we are also starting a new
995                    // instance right now, we need to first completely stop
996                    // the current instance before starting the new one.
997                    if (DEBUG_PAUSE) Slog.v(TAG, "Destroying after pause: " + prev);
998                    destroyActivityLocked(prev, true, "pause-config");
999                } else if (!hasVisibleBehindActivity()) {
1000                    // If we were visible then resumeTopActivities will release resources before
1001                    // stopping.
1002                    mStackSupervisor.mStoppingActivities.add(prev);
1003                    if (mStackSupervisor.mStoppingActivities.size() > 3 ||
1004                            prev.frontOfTask && mTaskHistory.size() <= 1) {
1005                        // If we already have a few activities waiting to stop,
1006                        // then give up on things going idle and start clearing
1007                        // them out. Or if r is the last of activity of the last task the stack
1008                        // will be empty and must be cleared immediately.
1009                        if (DEBUG_PAUSE) Slog.v(TAG, "To many pending stops, forcing idle");
1010                        mStackSupervisor.scheduleIdleLocked();
1011                    } else {
1012                        mStackSupervisor.checkReadyForSleepLocked();
1013                    }
1014                }
1015            } else {
1016                if (DEBUG_PAUSE) Slog.v(TAG, "App died during pause, not stopping: " + prev);
1017                prev = null;
1018            }
1019            mPausingActivity = null;
1020        }
1021
1022        if (resumeNext) {
1023            final ActivityStack topStack = mStackSupervisor.getFocusedStack();
1024            if (!mService.isSleepingOrShuttingDown()) {
1025                mStackSupervisor.resumeTopActivitiesLocked(topStack, prev, null);
1026            } else {
1027                mStackSupervisor.checkReadyForSleepLocked();
1028                ActivityRecord top = topStack.topRunningActivityLocked(null);
1029                if (top == null || (prev != null && top != prev)) {
1030                    // If there are no more activities available to run,
1031                    // do resume anyway to start something.  Also if the top
1032                    // activity on the stack is not the just paused activity,
1033                    // we need to go ahead and resume it to ensure we complete
1034                    // an in-flight app switch.
1035                    mStackSupervisor.resumeTopActivitiesLocked(topStack, null, null);
1036                }
1037            }
1038        }
1039
1040        if (prev != null) {
1041            prev.resumeKeyDispatchingLocked();
1042
1043            if (prev.app != null && prev.cpuTimeAtResume > 0
1044                    && mService.mBatteryStatsService.isOnBattery()) {
1045                long diff = mService.mProcessCpuTracker.getCpuTimeForPid(prev.app.pid)
1046                        - prev.cpuTimeAtResume;
1047                if (diff > 0) {
1048                    BatteryStatsImpl bsi = mService.mBatteryStatsService.getActiveStatistics();
1049                    synchronized (bsi) {
1050                        BatteryStatsImpl.Uid.Proc ps =
1051                                bsi.getProcessStatsLocked(prev.info.applicationInfo.uid,
1052                                        prev.info.packageName);
1053                        if (ps != null) {
1054                            ps.addForegroundTimeLocked(diff);
1055                        }
1056                    }
1057                }
1058            }
1059            prev.cpuTimeAtResume = 0; // reset it
1060        }
1061    }
1062
1063    /**
1064     * Once we know that we have asked an application to put an activity in
1065     * the resumed state (either by launching it or explicitly telling it),
1066     * this function updates the rest of our state to match that fact.
1067     */
1068    private void completeResumeLocked(ActivityRecord next) {
1069        next.idle = false;
1070        next.results = null;
1071        next.newIntents = null;
1072
1073        if (next.isHomeActivity() && next.isNotResolverActivity()) {
1074            ProcessRecord app = next.task.mActivities.get(0).app;
1075            if (app != null && app != mService.mHomeProcess) {
1076                mService.mHomeProcess = app;
1077            }
1078        }
1079
1080        if (next.nowVisible) {
1081            // We won't get a call to reportActivityVisibleLocked() so dismiss lockscreen now.
1082            mStackSupervisor.notifyActivityDrawnForKeyguard();
1083        }
1084
1085        // schedule an idle timeout in case the app doesn't do it for us.
1086        mStackSupervisor.scheduleIdleTimeoutLocked(next);
1087
1088        mStackSupervisor.reportResumedActivityLocked(next);
1089
1090        next.resumeKeyDispatchingLocked();
1091        mNoAnimActivities.clear();
1092
1093        // Mark the point when the activity is resuming
1094        // TODO: To be more accurate, the mark should be before the onCreate,
1095        //       not after the onResume. But for subsequent starts, onResume is fine.
1096        if (next.app != null) {
1097            next.cpuTimeAtResume = mService.mProcessCpuTracker.getCpuTimeForPid(next.app.pid);
1098        } else {
1099            next.cpuTimeAtResume = 0; // Couldn't get the cpu time of process
1100        }
1101
1102        // If we are resuming the activity that we had last screenshotted, then we know it will be
1103        // updated, so invalidate the last screenshot to ensure we take a fresh one when requested
1104        if (next == mLastScreenshotActivity) {
1105            invalidateLastScreenshot();
1106        }
1107        next.returningOptions = null;
1108    }
1109
1110    private void setVisibile(ActivityRecord r, boolean visible) {
1111        r.visible = visible;
1112        mWindowManager.setAppVisibility(r.appToken, visible);
1113        final ArrayList<ActivityContainer> containers = r.mChildContainers;
1114        for (int containerNdx = containers.size() - 1; containerNdx >= 0; --containerNdx) {
1115            ActivityContainer container = containers.get(containerNdx);
1116            container.setVisible(visible);
1117        }
1118    }
1119
1120    // Find the first visible activity above the passed activity and if it is translucent return it
1121    // otherwise return null;
1122    ActivityRecord findNextTranslucentActivity(ActivityRecord r) {
1123        TaskRecord task = r.task;
1124        if (task == null) {
1125            return null;
1126        }
1127
1128        ActivityStack stack = task.stack;
1129        if (stack == null) {
1130            return null;
1131        }
1132
1133        int stackNdx = mStacks.indexOf(stack);
1134
1135        ArrayList<TaskRecord> tasks = stack.mTaskHistory;
1136        int taskNdx = tasks.indexOf(task);
1137
1138        ArrayList<ActivityRecord> activities = task.mActivities;
1139        int activityNdx = activities.indexOf(r) + 1;
1140
1141        final int numStacks = mStacks.size();
1142        while (stackNdx < numStacks) {
1143            tasks = mStacks.get(stackNdx).mTaskHistory;
1144            final int numTasks = tasks.size();
1145            while (taskNdx < numTasks) {
1146                activities = tasks.get(taskNdx).mActivities;
1147                final int numActivities = activities.size();
1148                while (activityNdx < numActivities) {
1149                    final ActivityRecord activity = activities.get(activityNdx);
1150                    if (!activity.finishing) {
1151                        return activity.fullscreen ? null : activity;
1152                    }
1153                    ++activityNdx;
1154                }
1155                activityNdx = 0;
1156                ++taskNdx;
1157            }
1158            taskNdx = 0;
1159            ++stackNdx;
1160        }
1161
1162        return null;
1163    }
1164
1165    // Checks if any of the stacks above this one has a fullscreen activity behind it.
1166    // If so, this stack is hidden, otherwise it is visible.
1167    private boolean isStackVisible() {
1168        if (!isAttached()) {
1169            return false;
1170        }
1171
1172        if (mStackSupervisor.isFrontStack(this)) {
1173            return true;
1174        }
1175
1176        /**
1177         * Start at the task above this one and go up, looking for a visible
1178         * fullscreen activity, or a translucent activity that requested the
1179         * wallpaper to be shown behind it.
1180         */
1181        for (int i = mStacks.indexOf(this) + 1; i < mStacks.size(); i++) {
1182            final ArrayList<TaskRecord> tasks = mStacks.get(i).getAllTasks();
1183            for (int taskNdx = 0; taskNdx < tasks.size(); taskNdx++) {
1184                final TaskRecord task = tasks.get(taskNdx);
1185                final ArrayList<ActivityRecord> activities = task.mActivities;
1186                for (int activityNdx = 0; activityNdx < activities.size(); activityNdx++) {
1187                    final ActivityRecord r = activities.get(activityNdx);
1188
1189                    // Conditions for an activity to obscure the stack we're
1190                    // examining:
1191                    // 1. Not Finishing AND Visible AND:
1192                    // 2. Either:
1193                    // - Full Screen Activity OR
1194                    // - On top of Home and our stack is NOT home
1195                    if (!r.finishing && r.visible && (r.fullscreen ||
1196                            (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()))) {
1197                        return false;
1198                    }
1199                }
1200            }
1201        }
1202
1203        return true;
1204    }
1205
1206    /**
1207     * Make sure that all activities that need to be visible (that is, they
1208     * currently can be seen by the user) actually are.
1209     */
1210    final void ensureActivitiesVisibleLocked(ActivityRecord starting, int configChanges) {
1211        ActivityRecord top = topRunningActivityLocked(null);
1212        if (top == null) {
1213            return;
1214        }
1215        if (DEBUG_VISBILITY) Slog.v(
1216                TAG, "ensureActivitiesVisible behind " + top
1217                + " configChanges=0x" + Integer.toHexString(configChanges));
1218
1219        if (mTranslucentActivityWaiting != top) {
1220            mUndrawnActivitiesBelowTopTranslucent.clear();
1221            if (mTranslucentActivityWaiting != null) {
1222                // Call the callback with a timeout indication.
1223                notifyActivityDrawnLocked(null);
1224                mTranslucentActivityWaiting = null;
1225            }
1226            mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
1227        }
1228
1229        // If the top activity is not fullscreen, then we need to
1230        // make sure any activities under it are now visible.
1231        boolean aboveTop = true;
1232        boolean behindFullscreen = !isStackVisible();
1233
1234        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1235            final TaskRecord task = mTaskHistory.get(taskNdx);
1236            final ArrayList<ActivityRecord> activities = task.mActivities;
1237            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1238                final ActivityRecord r = activities.get(activityNdx);
1239                if (r.finishing) {
1240                    continue;
1241                }
1242                if (aboveTop && r != top) {
1243                    continue;
1244                }
1245                aboveTop = false;
1246                // mLaunchingBehind: Activities launching behind are at the back of the task stack
1247                // but must be drawn initially for the animation as though they were visible.
1248                if (!behindFullscreen || r.mLaunchTaskBehind) {
1249                    if (DEBUG_VISBILITY) Slog.v(
1250                            TAG, "Make visible? " + r + " finishing=" + r.finishing
1251                            + " state=" + r.state);
1252
1253                    // First: if this is not the current activity being started, make
1254                    // sure it matches the current configuration.
1255                    if (r != starting) {
1256                        ensureActivityConfigurationLocked(r, 0);
1257                    }
1258
1259                    if (r.app == null || r.app.thread == null) {
1260                        // This activity needs to be visible, but isn't even
1261                        // running...  get it started, but don't resume it
1262                        // at this point.
1263                        if (DEBUG_VISBILITY) Slog.v(TAG, "Start and freeze screen for " + r);
1264                        if (r != starting) {
1265                            r.startFreezingScreenLocked(r.app, configChanges);
1266                        }
1267                        if (!r.visible || r.mLaunchTaskBehind) {
1268                            if (DEBUG_VISBILITY) Slog.v(
1269                                    TAG, "Starting and making visible: " + r);
1270                            setVisibile(r, true);
1271                        }
1272                        if (r != starting) {
1273                            mStackSupervisor.startSpecificActivityLocked(r, false, false);
1274                        }
1275
1276                    } else if (r.visible) {
1277                        // If this activity is already visible, then there is nothing
1278                        // else to do here.
1279                        if (DEBUG_VISBILITY) Slog.v(TAG, "Skipping: already visible at " + r);
1280                        r.stopFreezingScreenLocked(false);
1281                        try {
1282                            if (r.returningOptions != null) {
1283                                r.app.thread.scheduleOnNewActivityOptions(r.appToken,
1284                                        r.returningOptions);
1285                            }
1286                        } catch(RemoteException e) {
1287                        }
1288                    } else {
1289                        // This activity is not currently visible, but is running.
1290                        // Tell it to become visible.
1291                        r.visible = true;
1292                        if (r.state != ActivityState.RESUMED && r != starting) {
1293                            // If this activity is paused, tell it
1294                            // to now show its window.
1295                            if (DEBUG_VISBILITY) Slog.v(
1296                                    TAG, "Making visible and scheduling visibility: " + r);
1297                            try {
1298                                if (mTranslucentActivityWaiting != null) {
1299                                    r.updateOptionsLocked(r.returningOptions);
1300                                    mUndrawnActivitiesBelowTopTranslucent.add(r);
1301                                }
1302                                setVisibile(r, true);
1303                                r.sleeping = false;
1304                                r.app.pendingUiClean = true;
1305                                r.app.thread.scheduleWindowVisibility(r.appToken, true);
1306                                r.stopFreezingScreenLocked(false);
1307                            } catch (Exception e) {
1308                                // Just skip on any failure; we'll make it
1309                                // visible when it next restarts.
1310                                Slog.w(TAG, "Exception thrown making visibile: "
1311                                        + r.intent.getComponent(), e);
1312                            }
1313                        }
1314                    }
1315
1316                    // Aggregate current change flags.
1317                    configChanges |= r.configChangeFlags;
1318
1319                    if (r.fullscreen) {
1320                        // At this point, nothing else needs to be shown
1321                        if (DEBUG_VISBILITY) Slog.v(TAG, "Fullscreen: at " + r);
1322                        behindFullscreen = true;
1323                    } else if (!isHomeStack() && r.frontOfTask && task.isOverHomeStack()) {
1324                        if (DEBUG_VISBILITY) Slog.v(TAG, "Showing home: at " + r);
1325                        behindFullscreen = true;
1326                    }
1327                } else {
1328                    if (DEBUG_VISBILITY) Slog.v(
1329                        TAG, "Make invisible? " + r + " finishing=" + r.finishing
1330                        + " state=" + r.state
1331                        + " behindFullscreen=" + behindFullscreen);
1332                    // Now for any activities that aren't visible to the user, make
1333                    // sure they no longer are keeping the screen frozen.
1334                    if (r.visible) {
1335                        if (DEBUG_VISBILITY) Slog.v(TAG, "Making invisible: " + r);
1336                        try {
1337                            setVisibile(r, false);
1338                            switch (r.state) {
1339                                case STOPPING:
1340                                case STOPPED:
1341                                    if (r.app != null && r.app.thread != null) {
1342                                        if (DEBUG_VISBILITY) Slog.v(
1343                                                TAG, "Scheduling invisibility: " + r);
1344                                        r.app.thread.scheduleWindowVisibility(r.appToken, false);
1345                                    }
1346                                    break;
1347
1348                                case INITIALIZING:
1349                                case RESUMED:
1350                                case PAUSING:
1351                                case PAUSED:
1352                                    // This case created for transitioning activities from
1353                                    // translucent to opaque {@link Activity#convertToOpaque}.
1354                                    if (getVisibleBehindActivity() == r) {
1355                                        releaseBackgroundResources();
1356                                    } else {
1357                                        if (!mStackSupervisor.mStoppingActivities.contains(r)) {
1358                                            mStackSupervisor.mStoppingActivities.add(r);
1359                                        }
1360                                        mStackSupervisor.scheduleIdleLocked();
1361                                    }
1362                                    break;
1363
1364                                default:
1365                                    break;
1366                            }
1367                        } catch (Exception e) {
1368                            // Just skip on any failure; we'll make it
1369                            // visible when it next restarts.
1370                            Slog.w(TAG, "Exception thrown making hidden: "
1371                                    + r.intent.getComponent(), e);
1372                        }
1373                    } else {
1374                        if (DEBUG_VISBILITY) Slog.v(TAG, "Already invisible: " + r);
1375                    }
1376                }
1377            }
1378        }
1379
1380        if (mTranslucentActivityWaiting != null &&
1381                mUndrawnActivitiesBelowTopTranslucent.isEmpty()) {
1382            // Nothing is getting drawn or everything was already visible, don't wait for timeout.
1383            notifyActivityDrawnLocked(null);
1384        }
1385    }
1386
1387    void convertToTranslucent(ActivityRecord r) {
1388        mTranslucentActivityWaiting = r;
1389        mUndrawnActivitiesBelowTopTranslucent.clear();
1390        mHandler.sendEmptyMessageDelayed(TRANSLUCENT_TIMEOUT_MSG, TRANSLUCENT_CONVERSION_TIMEOUT);
1391    }
1392
1393    /**
1394     * Called as activities below the top translucent activity are redrawn. When the last one is
1395     * redrawn notify the top activity by calling
1396     * {@link Activity#onTranslucentConversionComplete}.
1397     *
1398     * @param r The most recent background activity to be drawn. Or, if r is null then a timeout
1399     * occurred and the activity will be notified immediately.
1400     */
1401    void notifyActivityDrawnLocked(ActivityRecord r) {
1402        mActivityContainer.setDrawn();
1403        if ((r == null)
1404                || (mUndrawnActivitiesBelowTopTranslucent.remove(r) &&
1405                        mUndrawnActivitiesBelowTopTranslucent.isEmpty())) {
1406            // The last undrawn activity below the top has just been drawn. If there is an
1407            // opaque activity at the top, notify it that it can become translucent safely now.
1408            final ActivityRecord waitingActivity = mTranslucentActivityWaiting;
1409            mTranslucentActivityWaiting = null;
1410            mUndrawnActivitiesBelowTopTranslucent.clear();
1411            mHandler.removeMessages(TRANSLUCENT_TIMEOUT_MSG);
1412
1413            if (waitingActivity != null) {
1414                mWindowManager.setWindowOpaque(waitingActivity.appToken, false);
1415                if (waitingActivity.app != null && waitingActivity.app.thread != null) {
1416                    try {
1417                        waitingActivity.app.thread.scheduleTranslucentConversionComplete(
1418                                waitingActivity.appToken, r != null);
1419                    } catch (RemoteException e) {
1420                    }
1421                }
1422            }
1423        }
1424    }
1425
1426    /** If any activities below the top running one are in the INITIALIZING state and they have a
1427     * starting window displayed then remove that starting window. It is possible that the activity
1428     * in this state will never resumed in which case that starting window will be orphaned. */
1429    void cancelInitializingActivities() {
1430        final ActivityRecord topActivity = topRunningActivityLocked(null);
1431        boolean aboveTop = true;
1432        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1433            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
1434            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
1435                final ActivityRecord r = activities.get(activityNdx);
1436                if (aboveTop) {
1437                    if (r == topActivity) {
1438                        aboveTop = false;
1439                    }
1440                    continue;
1441                }
1442
1443                if (r.state == ActivityState.INITIALIZING && r.mStartingWindowShown) {
1444                    if (DEBUG_VISBILITY) Slog.w(TAG, "Found orphaned starting window " + r);
1445                    r.mStartingWindowShown = false;
1446                    mWindowManager.removeAppStartingWindow(r.appToken);
1447                }
1448            }
1449        }
1450    }
1451
1452    /**
1453     * Ensure that the top activity in the stack is resumed.
1454     *
1455     * @param prev The previously resumed activity, for when in the process
1456     * of pausing; can be null to call from elsewhere.
1457     *
1458     * @return Returns true if something is being resumed, or false if
1459     * nothing happened.
1460     */
1461    final boolean resumeTopActivityLocked(ActivityRecord prev) {
1462        return resumeTopActivityLocked(prev, null);
1463    }
1464
1465    final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
1466        if (inResumeTopActivity) {
1467            // Don't even start recursing.
1468            return false;
1469        }
1470
1471        boolean result = false;
1472        try {
1473            // Protect against recursion.
1474            inResumeTopActivity = true;
1475            result = resumeTopActivityInnerLocked(prev, options);
1476        } finally {
1477            inResumeTopActivity = false;
1478        }
1479        return result;
1480    }
1481
1482    final boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
1483        if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
1484
1485        ActivityRecord parent = mActivityContainer.mParentActivity;
1486        if ((parent != null && parent.state != ActivityState.RESUMED) ||
1487                !mActivityContainer.isAttachedLocked()) {
1488            // Do not resume this stack if its parent is not resumed.
1489            // TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st.
1490            return false;
1491        }
1492
1493        cancelInitializingActivities();
1494
1495        // Find the first activity that is not finishing.
1496        ActivityRecord next = topRunningActivityLocked(null);
1497
1498        // Remember how we'll process this pause/resume situation, and ensure
1499        // that the state is reset however we wind up proceeding.
1500        final boolean userLeaving = mStackSupervisor.mUserLeaving;
1501        mStackSupervisor.mUserLeaving = false;
1502
1503        final TaskRecord prevTask = prev != null ? prev.task : null;
1504        if (next == null) {
1505            // There are no more activities!  Let's just start up the
1506            // Launcher...
1507            ActivityOptions.abort(options);
1508            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home");
1509            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1510            // Only resume home if on home display
1511            final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
1512                    HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
1513            return isOnHomeDisplay() &&
1514                    mStackSupervisor.resumeHomeStackTask(returnTaskType, prev);
1515        }
1516
1517        next.delayedResume = false;
1518
1519        // If the top activity is the resumed one, nothing to do.
1520        if (mResumedActivity == next && next.state == ActivityState.RESUMED &&
1521                    mStackSupervisor.allResumedActivitiesComplete()) {
1522            // Make sure we have executed any pending transitions, since there
1523            // should be nothing left to do at this point.
1524            mWindowManager.executeAppTransition();
1525            mNoAnimActivities.clear();
1526            ActivityOptions.abort(options);
1527            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Top activity resumed " + next);
1528            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1529
1530            // Make sure to notify Keyguard as well if it is waiting for an activity to be drawn.
1531            mStackSupervisor.notifyActivityDrawnForKeyguard();
1532            return false;
1533        }
1534
1535        final TaskRecord nextTask = next.task;
1536        if (prevTask != null && prevTask.stack == this &&
1537                prevTask.isOverHomeStack() && prev.finishing && prev.frontOfTask) {
1538            if (DEBUG_STACK)  mStackSupervisor.validateTopActivitiesLocked();
1539            if (prevTask == nextTask) {
1540                prevTask.setFrontOfTask();
1541            } else if (prevTask != topTask()) {
1542                // This task is going away but it was supposed to return to the home stack.
1543                // Now the task above it has to return to the home task instead.
1544                final int taskNdx = mTaskHistory.indexOf(prevTask) + 1;
1545                mTaskHistory.get(taskNdx).setTaskToReturnTo(HOME_ACTIVITY_TYPE);
1546            } else {
1547                if (DEBUG_STATES && isOnHomeDisplay()) Slog.d(TAG,
1548                        "resumeTopActivityLocked: Launching home next");
1549                // Only resume home if on home display
1550                final int returnTaskType = prevTask == null || !prevTask.isOverHomeStack() ?
1551                        HOME_ACTIVITY_TYPE : prevTask.getTaskToReturnTo();
1552                return isOnHomeDisplay() &&
1553                        mStackSupervisor.resumeHomeStackTask(returnTaskType, prev);
1554            }
1555        }
1556
1557        // If we are sleeping, and there is no resumed activity, and the top
1558        // activity is paused, well that is the state we want.
1559        if (mService.isSleepingOrShuttingDown()
1560                && mLastPausedActivity == next
1561                && mStackSupervisor.allPausedActivitiesComplete()) {
1562            // Make sure we have executed any pending transitions, since there
1563            // should be nothing left to do at this point.
1564            mWindowManager.executeAppTransition();
1565            mNoAnimActivities.clear();
1566            ActivityOptions.abort(options);
1567            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Going to sleep and all paused");
1568            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1569            return false;
1570        }
1571
1572        // Make sure that the user who owns this activity is started.  If not,
1573        // we will just leave it as is because someone should be bringing
1574        // another user's activities to the top of the stack.
1575        if (mService.mStartedUsers.get(next.userId) == null) {
1576            Slog.w(TAG, "Skipping resume of top activity " + next
1577                    + ": user " + next.userId + " is stopped");
1578            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1579            return false;
1580        }
1581
1582        // The activity may be waiting for stop, but that is no longer
1583        // appropriate for it.
1584        mStackSupervisor.mStoppingActivities.remove(next);
1585        mStackSupervisor.mGoingToSleepActivities.remove(next);
1586        next.sleeping = false;
1587        mStackSupervisor.mWaitingVisibleActivities.remove(next);
1588
1589        if (DEBUG_SWITCH) Slog.v(TAG, "Resuming " + next);
1590
1591        // If we are currently pausing an activity, then don't do anything
1592        // until that is done.
1593        if (!mStackSupervisor.allPausedActivitiesComplete()) {
1594            if (DEBUG_SWITCH || DEBUG_PAUSE || DEBUG_STATES) Slog.v(TAG,
1595                    "resumeTopActivityLocked: Skip resume: some activity pausing.");
1596            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1597            return false;
1598        }
1599
1600        // Okay we are now going to start a switch, to 'next'.  We may first
1601        // have to pause the current activity, but this is an important point
1602        // where we have decided to go to 'next' so keep track of that.
1603        // XXX "App Redirected" dialog is getting too many false positives
1604        // at this point, so turn off for now.
1605        if (false) {
1606            if (mLastStartedActivity != null && !mLastStartedActivity.finishing) {
1607                long now = SystemClock.uptimeMillis();
1608                final boolean inTime = mLastStartedActivity.startTime != 0
1609                        && (mLastStartedActivity.startTime + START_WARN_TIME) >= now;
1610                final int lastUid = mLastStartedActivity.info.applicationInfo.uid;
1611                final int nextUid = next.info.applicationInfo.uid;
1612                if (inTime && lastUid != nextUid
1613                        && lastUid != next.launchedFromUid
1614                        && mService.checkPermission(
1615                                android.Manifest.permission.STOP_APP_SWITCHES,
1616                                -1, next.launchedFromUid)
1617                        != PackageManager.PERMISSION_GRANTED) {
1618                    mService.showLaunchWarningLocked(mLastStartedActivity, next);
1619                } else {
1620                    next.startTime = now;
1621                    mLastStartedActivity = next;
1622                }
1623            } else {
1624                next.startTime = SystemClock.uptimeMillis();
1625                mLastStartedActivity = next;
1626            }
1627        }
1628
1629        // We need to start pausing the current activity so the top one
1630        // can be resumed...
1631        boolean dontWaitForPause = (next.info.flags&ActivityInfo.FLAG_RESUME_WHILE_PAUSING) != 0;
1632        boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving, true, dontWaitForPause);
1633        if (mResumedActivity != null) {
1634            pausing |= startPausingLocked(userLeaving, false, true, dontWaitForPause);
1635            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Pausing " + mResumedActivity);
1636        }
1637        if (pausing) {
1638            if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG,
1639                    "resumeTopActivityLocked: Skip resume: need to start pausing");
1640            // At this point we want to put the upcoming activity's process
1641            // at the top of the LRU list, since we know we will be needing it
1642            // very soon and it would be a waste to let it get killed if it
1643            // happens to be sitting towards the end.
1644            if (next.app != null && next.app.thread != null) {
1645                mService.updateLruProcessLocked(next.app, true, null);
1646            }
1647            if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1648            return true;
1649        }
1650
1651        // If the most recent activity was noHistory but was only stopped rather
1652        // than stopped+finished because the device went to sleep, we need to make
1653        // sure to finish it as we're making a new activity topmost.
1654        if (mService.isSleeping() && mLastNoHistoryActivity != null &&
1655                !mLastNoHistoryActivity.finishing) {
1656            if (DEBUG_STATES) Slog.d(TAG, "no-history finish of " + mLastNoHistoryActivity +
1657                    " on new resume");
1658            requestFinishActivityLocked(mLastNoHistoryActivity.appToken, Activity.RESULT_CANCELED,
1659                    null, "no-history", false);
1660            mLastNoHistoryActivity = null;
1661        }
1662
1663        if (prev != null && prev != next) {
1664            if (!prev.waitingVisible && next != null && !next.nowVisible) {
1665                prev.waitingVisible = true;
1666                mStackSupervisor.mWaitingVisibleActivities.add(prev);
1667                if (DEBUG_SWITCH) Slog.v(
1668                        TAG, "Resuming top, waiting visible to hide: " + prev);
1669            } else {
1670                // The next activity is already visible, so hide the previous
1671                // activity's windows right now so we can show the new one ASAP.
1672                // We only do this if the previous is finishing, which should mean
1673                // it is on top of the one being resumed so hiding it quickly
1674                // is good.  Otherwise, we want to do the normal route of allowing
1675                // the resumed activity to be shown so we can decide if the
1676                // previous should actually be hidden depending on whether the
1677                // new one is found to be full-screen or not.
1678                if (prev.finishing) {
1679                    mWindowManager.setAppVisibility(prev.appToken, false);
1680                    if (DEBUG_SWITCH) Slog.v(TAG, "Not waiting for visible to hide: "
1681                            + prev + ", waitingVisible="
1682                            + (prev != null ? prev.waitingVisible : null)
1683                            + ", nowVisible=" + next.nowVisible);
1684                } else {
1685                    if (DEBUG_SWITCH) Slog.v(TAG, "Previous already visible but still waiting to hide: "
1686                        + prev + ", waitingVisible="
1687                        + (prev != null ? prev.waitingVisible : null)
1688                        + ", nowVisible=" + next.nowVisible);
1689                }
1690            }
1691        }
1692
1693        // Launching this app's activity, make sure the app is no longer
1694        // considered stopped.
1695        try {
1696            AppGlobals.getPackageManager().setPackageStoppedState(
1697                    next.packageName, false, next.userId); /* TODO: Verify if correct userid */
1698        } catch (RemoteException e1) {
1699        } catch (IllegalArgumentException e) {
1700            Slog.w(TAG, "Failed trying to unstop package "
1701                    + next.packageName + ": " + e);
1702        }
1703
1704        // We are starting up the next activity, so tell the window manager
1705        // that the previous one will be hidden soon.  This way it can know
1706        // to ignore it when computing the desired screen orientation.
1707        boolean anim = true;
1708        if (prev != null) {
1709            if (prev.finishing) {
1710                if (DEBUG_TRANSITION) Slog.v(TAG,
1711                        "Prepare close transition: prev=" + prev);
1712                if (mNoAnimActivities.contains(prev)) {
1713                    anim = false;
1714                    mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
1715                } else {
1716                    mWindowManager.prepareAppTransition(prev.task == next.task
1717                            ? AppTransition.TRANSIT_ACTIVITY_CLOSE
1718                            : AppTransition.TRANSIT_TASK_CLOSE, false);
1719                }
1720                mWindowManager.setAppWillBeHidden(prev.appToken);
1721                mWindowManager.setAppVisibility(prev.appToken, false);
1722            } else {
1723                if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: prev=" + prev);
1724                if (mNoAnimActivities.contains(next)) {
1725                    anim = false;
1726                    mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
1727                } else {
1728                    mWindowManager.prepareAppTransition(prev.task == next.task
1729                            ? AppTransition.TRANSIT_ACTIVITY_OPEN
1730                            : next.mLaunchTaskBehind
1731                                    ? AppTransition.TRANSIT_TASK_OPEN_BEHIND
1732                                    : AppTransition.TRANSIT_TASK_OPEN, false);
1733                }
1734            }
1735            if (false) {
1736                mWindowManager.setAppWillBeHidden(prev.appToken);
1737                mWindowManager.setAppVisibility(prev.appToken, false);
1738            }
1739        } else {
1740            if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare open transition: no previous");
1741            if (mNoAnimActivities.contains(next)) {
1742                anim = false;
1743                mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
1744            } else {
1745                mWindowManager.prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_OPEN, false);
1746            }
1747        }
1748
1749        Bundle resumeAnimOptions = null;
1750        if (anim) {
1751            ActivityOptions opts = next.getOptionsForTargetActivityLocked();
1752            if (opts != null) {
1753                resumeAnimOptions = opts.toBundle();
1754            }
1755            next.applyOptionsLocked();
1756        } else {
1757            next.clearOptionsLocked();
1758        }
1759
1760        ActivityStack lastStack = mStackSupervisor.getLastStack();
1761        if (next.app != null && next.app.thread != null) {
1762            if (DEBUG_SWITCH) Slog.v(TAG, "Resume running: " + next);
1763
1764            // This activity is now becoming visible.
1765            mWindowManager.setAppVisibility(next.appToken, true);
1766
1767            // schedule launch ticks to collect information about slow apps.
1768            next.startLaunchTickingLocked();
1769
1770            ActivityRecord lastResumedActivity =
1771                    lastStack == null ? null :lastStack.mResumedActivity;
1772            ActivityState lastState = next.state;
1773
1774            mService.updateCpuStats();
1775
1776            if (DEBUG_STATES) Slog.v(TAG, "Moving to RESUMED: " + next + " (in existing)");
1777            next.state = ActivityState.RESUMED;
1778            mResumedActivity = next;
1779            next.task.touchActiveTime();
1780            mService.addRecentTaskLocked(next.task);
1781            mService.updateLruProcessLocked(next.app, true, null);
1782            updateLRUListLocked(next);
1783            mService.updateOomAdjLocked();
1784
1785            // Have the window manager re-evaluate the orientation of
1786            // the screen based on the new activity order.
1787            boolean notUpdated = true;
1788            if (mStackSupervisor.isFrontStack(this)) {
1789                Configuration config = mWindowManager.updateOrientationFromAppTokens(
1790                        mService.mConfiguration,
1791                        next.mayFreezeScreenLocked(next.app) ? next.appToken : null);
1792                if (config != null) {
1793                    next.frozenBeforeDestroy = true;
1794                }
1795                notUpdated = !mService.updateConfigurationLocked(config, next, false, false);
1796            }
1797
1798            if (notUpdated) {
1799                // The configuration update wasn't able to keep the existing
1800                // instance of the activity, and instead started a new one.
1801                // We should be all done, but let's just make sure our activity
1802                // is still at the top and schedule another run if something
1803                // weird happened.
1804                ActivityRecord nextNext = topRunningActivityLocked(null);
1805                if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
1806                        "Activity config changed during resume: " + next
1807                        + ", new next: " + nextNext);
1808                if (nextNext != next) {
1809                    // Do over!
1810                    mStackSupervisor.scheduleResumeTopActivities();
1811                }
1812                if (mStackSupervisor.reportResumedActivityLocked(next)) {
1813                    mNoAnimActivities.clear();
1814                    if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1815                    return true;
1816                }
1817                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1818                return false;
1819            }
1820
1821            try {
1822                // Deliver all pending results.
1823                ArrayList<ResultInfo> a = next.results;
1824                if (a != null) {
1825                    final int N = a.size();
1826                    if (!next.finishing && N > 0) {
1827                        if (DEBUG_RESULTS) Slog.v(
1828                                TAG, "Delivering results to " + next
1829                                + ": " + a);
1830                        next.app.thread.scheduleSendResult(next.appToken, a);
1831                    }
1832                }
1833
1834                if (next.newIntents != null) {
1835                    next.app.thread.scheduleNewIntent(next.newIntents, next.appToken);
1836                }
1837
1838                EventLog.writeEvent(EventLogTags.AM_RESUME_ACTIVITY,
1839                        next.userId, System.identityHashCode(next),
1840                        next.task.taskId, next.shortComponentName);
1841
1842                next.sleeping = false;
1843                mService.showAskCompatModeDialogLocked(next);
1844                next.app.pendingUiClean = true;
1845                next.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_TOP);
1846                next.clearOptionsLocked();
1847                next.app.thread.scheduleResumeActivity(next.appToken, next.app.repProcState,
1848                        mService.isNextTransitionForward(), resumeAnimOptions);
1849
1850                mStackSupervisor.checkReadyForSleepLocked();
1851
1852                if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Resumed " + next);
1853            } catch (Exception e) {
1854                // Whoops, need to restart this activity!
1855                if (DEBUG_STATES) Slog.v(TAG, "Resume failed; resetting state to "
1856                        + lastState + ": " + next);
1857                next.state = lastState;
1858                if (lastStack != null) {
1859                    lastStack.mResumedActivity = lastResumedActivity;
1860                }
1861                Slog.i(TAG, "Restarting because process died: " + next);
1862                if (!next.hasBeenLaunched) {
1863                    next.hasBeenLaunched = true;
1864                } else  if (SHOW_APP_STARTING_PREVIEW && lastStack != null &&
1865                        mStackSupervisor.isFrontStack(lastStack)) {
1866                    mWindowManager.setAppStartingWindow(
1867                            next.appToken, next.packageName, next.theme,
1868                            mService.compatibilityInfoForPackageLocked(next.info.applicationInfo),
1869                            next.nonLocalizedLabel, next.labelRes, next.icon, next.logo,
1870                            next.windowFlags, null, true);
1871                }
1872                mStackSupervisor.startSpecificActivityLocked(next, true, false);
1873                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1874                return true;
1875            }
1876
1877            // From this point on, if something goes wrong there is no way
1878            // to recover the activity.
1879            try {
1880                next.visible = true;
1881                completeResumeLocked(next);
1882            } catch (Exception e) {
1883                // If any exception gets thrown, toss away this
1884                // activity and try the next one.
1885                Slog.w(TAG, "Exception thrown during resume of " + next, e);
1886                requestFinishActivityLocked(next.appToken, Activity.RESULT_CANCELED, null,
1887                        "resume-exception", true);
1888                if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1889                return true;
1890            }
1891            next.stopped = false;
1892
1893        } else {
1894            // Whoops, need to restart this activity!
1895            if (!next.hasBeenLaunched) {
1896                next.hasBeenLaunched = true;
1897            } else {
1898                if (SHOW_APP_STARTING_PREVIEW) {
1899                    mWindowManager.setAppStartingWindow(
1900                            next.appToken, next.packageName, next.theme,
1901                            mService.compatibilityInfoForPackageLocked(
1902                                    next.info.applicationInfo),
1903                            next.nonLocalizedLabel,
1904                            next.labelRes, next.icon, next.logo, next.windowFlags,
1905                            null, true);
1906                }
1907                if (DEBUG_SWITCH) Slog.v(TAG, "Restarting: " + next);
1908            }
1909            if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: Restarting " + next);
1910            mStackSupervisor.startSpecificActivityLocked(next, true, true);
1911        }
1912
1913        if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked();
1914        return true;
1915    }
1916
1917    private void insertTaskAtTop(TaskRecord task) {
1918        // If this is being moved to the top by another activity or being launched from the home
1919        // activity, set mOnTopOfHome accordingly.
1920        if (isOnHomeDisplay()) {
1921            ActivityStack lastStack = mStackSupervisor.getLastStack();
1922            final boolean fromHome = lastStack.isHomeStack();
1923            if (!isHomeStack() && (fromHome || topTask() != task)) {
1924                task.setTaskToReturnTo(fromHome
1925                        ? lastStack.topTask() == null
1926                                ? HOME_ACTIVITY_TYPE
1927                                : lastStack.topTask().taskType
1928                        : APPLICATION_ACTIVITY_TYPE);
1929            }
1930        } else {
1931            task.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
1932        }
1933
1934        mTaskHistory.remove(task);
1935        // Now put task at top.
1936        int taskNdx = mTaskHistory.size();
1937        if (!isCurrentProfileLocked(task.userId)) {
1938            // Put non-current user tasks below current user tasks.
1939            while (--taskNdx >= 0) {
1940                if (!isCurrentProfileLocked(mTaskHistory.get(taskNdx).userId)) {
1941                    break;
1942                }
1943            }
1944            ++taskNdx;
1945        }
1946        mTaskHistory.add(taskNdx, task);
1947        updateTaskMovement(task, true);
1948    }
1949
1950    final void startActivityLocked(ActivityRecord r, boolean newTask,
1951            boolean doResume, boolean keepCurTransition, Bundle options) {
1952        TaskRecord rTask = r.task;
1953        final int taskId = rTask.taskId;
1954        // mLaunchTaskBehind tasks get placed at the back of the task stack.
1955        if (!r.mLaunchTaskBehind && (taskForIdLocked(taskId) == null || newTask)) {
1956            // Last activity in task had been removed or ActivityManagerService is reusing task.
1957            // Insert or replace.
1958            // Might not even be in.
1959            insertTaskAtTop(rTask);
1960            mWindowManager.moveTaskToTop(taskId);
1961        }
1962        TaskRecord task = null;
1963        if (!newTask) {
1964            // If starting in an existing task, find where that is...
1965            boolean startIt = true;
1966            for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
1967                task = mTaskHistory.get(taskNdx);
1968                if (task.getTopActivity() == null) {
1969                    // All activities in task are finishing.
1970                    continue;
1971                }
1972                if (task == r.task) {
1973                    // Here it is!  Now, if this is not yet visible to the
1974                    // user, then just add it without starting; it will
1975                    // get started when the user navigates back to it.
1976                    if (!startIt) {
1977                        if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to task "
1978                                + task, new RuntimeException("here").fillInStackTrace());
1979                        task.addActivityToTop(r);
1980                        r.putInHistory();
1981                        mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
1982                                r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
1983                                (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0,
1984                                r.userId, r.info.configChanges, task.voiceSession != null,
1985                                r.mLaunchTaskBehind);
1986                        if (VALIDATE_TOKENS) {
1987                            validateAppTokensLocked();
1988                        }
1989                        ActivityOptions.abort(options);
1990                        return;
1991                    }
1992                    break;
1993                } else if (task.numFullscreen > 0) {
1994                    startIt = false;
1995                }
1996            }
1997        }
1998
1999        // Place a new activity at top of stack, so it is next to interact
2000        // with the user.
2001
2002        // If we are not placing the new activity frontmost, we do not want
2003        // to deliver the onUserLeaving callback to the actual frontmost
2004        // activity
2005        if (task == r.task && mTaskHistory.indexOf(task) != (mTaskHistory.size() - 1)) {
2006            mStackSupervisor.mUserLeaving = false;
2007            if (DEBUG_USER_LEAVING) Slog.v(TAG,
2008                    "startActivity() behind front, mUserLeaving=false");
2009        }
2010
2011        task = r.task;
2012
2013        // Slot the activity into the history stack and proceed
2014        if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Adding activity " + r + " to stack to task " + task,
2015                new RuntimeException("here").fillInStackTrace());
2016        task.addActivityToTop(r);
2017        task.setFrontOfTask();
2018
2019        r.putInHistory();
2020        if (!isHomeStack() || numActivities() > 0) {
2021            // We want to show the starting preview window if we are
2022            // switching to a new task, or the next activity's process is
2023            // not currently running.
2024            boolean showStartingIcon = newTask;
2025            ProcessRecord proc = r.app;
2026            if (proc == null) {
2027                proc = mService.mProcessNames.get(r.processName, r.info.applicationInfo.uid);
2028            }
2029            if (proc == null || proc.thread == null) {
2030                showStartingIcon = true;
2031            }
2032            if (DEBUG_TRANSITION) Slog.v(TAG,
2033                    "Prepare open transition: starting " + r);
2034            if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
2035                mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, keepCurTransition);
2036                mNoAnimActivities.add(r);
2037            } else {
2038                mWindowManager.prepareAppTransition(newTask
2039                        ? r.mLaunchTaskBehind
2040                                ? AppTransition.TRANSIT_TASK_OPEN_BEHIND
2041                                : AppTransition.TRANSIT_TASK_OPEN
2042                        : AppTransition.TRANSIT_ACTIVITY_OPEN, keepCurTransition);
2043                mNoAnimActivities.remove(r);
2044            }
2045            mWindowManager.addAppToken(task.mActivities.indexOf(r),
2046                    r.appToken, r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
2047                    (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId,
2048                    r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);
2049            boolean doShow = true;
2050            if (newTask) {
2051                // Even though this activity is starting fresh, we still need
2052                // to reset it to make sure we apply affinities to move any
2053                // existing activities from other tasks in to it.
2054                // If the caller has requested that the target task be
2055                // reset, then do so.
2056                if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
2057                    resetTaskIfNeededLocked(r, r);
2058                    doShow = topRunningNonDelayedActivityLocked(null) == r;
2059                }
2060            } else if (options != null && new ActivityOptions(options).getAnimationType()
2061                    == ActivityOptions.ANIM_SCENE_TRANSITION) {
2062                doShow = false;
2063            }
2064            if (r.mLaunchTaskBehind) {
2065                // Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
2066                // tell WindowManager that r is visible even though it is at the back of the stack.
2067                mWindowManager.setAppVisibility(r.appToken, true);
2068                ensureActivitiesVisibleLocked(null, 0);
2069            } else if (SHOW_APP_STARTING_PREVIEW && doShow) {
2070                // Figure out if we are transitioning from another activity that is
2071                // "has the same starting icon" as the next one.  This allows the
2072                // window manager to keep the previous window it had previously
2073                // created, if it still had one.
2074                ActivityRecord prev = mResumedActivity;
2075                if (prev != null) {
2076                    // We don't want to reuse the previous starting preview if:
2077                    // (1) The current activity is in a different task.
2078                    if (prev.task != r.task) {
2079                        prev = null;
2080                    }
2081                    // (2) The current activity is already displayed.
2082                    else if (prev.nowVisible) {
2083                        prev = null;
2084                    }
2085                }
2086                mWindowManager.setAppStartingWindow(
2087                        r.appToken, r.packageName, r.theme,
2088                        mService.compatibilityInfoForPackageLocked(
2089                                r.info.applicationInfo), r.nonLocalizedLabel,
2090                        r.labelRes, r.icon, r.logo, r.windowFlags,
2091                        prev != null ? prev.appToken : null, showStartingIcon);
2092                r.mStartingWindowShown = true;
2093            }
2094        } else {
2095            // If this is the first activity, don't do any fancy animations,
2096            // because there is nothing for it to animate on top of.
2097            mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
2098                    r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
2099                    (r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId,
2100                    r.info.configChanges, task.voiceSession != null, r.mLaunchTaskBehind);
2101            ActivityOptions.abort(options);
2102            options = null;
2103        }
2104        if (VALIDATE_TOKENS) {
2105            validateAppTokensLocked();
2106        }
2107
2108        if (doResume) {
2109            mStackSupervisor.resumeTopActivitiesLocked(this, r, options);
2110        }
2111    }
2112
2113    final void validateAppTokensLocked() {
2114        mValidateAppTokens.clear();
2115        mValidateAppTokens.ensureCapacity(numActivities());
2116        final int numTasks = mTaskHistory.size();
2117        for (int taskNdx = 0; taskNdx < numTasks; ++taskNdx) {
2118            TaskRecord task = mTaskHistory.get(taskNdx);
2119            final ArrayList<ActivityRecord> activities = task.mActivities;
2120            if (activities.isEmpty()) {
2121                continue;
2122            }
2123            TaskGroup group = new TaskGroup();
2124            group.taskId = task.taskId;
2125            mValidateAppTokens.add(group);
2126            final int numActivities = activities.size();
2127            for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
2128                final ActivityRecord r = activities.get(activityNdx);
2129                group.tokens.add(r.appToken);
2130            }
2131        }
2132        mWindowManager.validateAppTokens(mStackId, mValidateAppTokens);
2133    }
2134
2135    /**
2136     * Perform a reset of the given task, if needed as part of launching it.
2137     * Returns the new HistoryRecord at the top of the task.
2138     */
2139    /**
2140     * Helper method for #resetTaskIfNeededLocked.
2141     * We are inside of the task being reset...  we'll either finish this activity, push it out
2142     * for another task, or leave it as-is.
2143     * @param task The task containing the Activity (taskTop) that might be reset.
2144     * @param forceReset
2145     * @return An ActivityOptions that needs to be processed.
2146     */
2147    final ActivityOptions resetTargetTaskIfNeededLocked(TaskRecord task, boolean forceReset) {
2148        ActivityOptions topOptions = null;
2149
2150        int replyChainEnd = -1;
2151        boolean canMoveOptions = true;
2152
2153        // We only do this for activities that are not the root of the task (since if we finish
2154        // the root, we may no longer have the task!).
2155        final ArrayList<ActivityRecord> activities = task.mActivities;
2156        final int numActivities = activities.size();
2157        final int rootActivityNdx = task.findEffectiveRootIndex();
2158        for (int i = numActivities - 1; i > rootActivityNdx; --i ) {
2159            ActivityRecord target = activities.get(i);
2160            if (target.frontOfTask)
2161                break;
2162
2163            final int flags = target.info.flags;
2164            final boolean finishOnTaskLaunch =
2165                    (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
2166            final boolean allowTaskReparenting =
2167                    (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
2168            final boolean clearWhenTaskReset =
2169                    (target.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0;
2170
2171            if (!finishOnTaskLaunch
2172                    && !clearWhenTaskReset
2173                    && target.resultTo != null) {
2174                // If this activity is sending a reply to a previous
2175                // activity, we can't do anything with it now until
2176                // we reach the start of the reply chain.
2177                // XXX note that we are assuming the result is always
2178                // to the previous activity, which is almost always
2179                // the case but we really shouldn't count on.
2180                if (replyChainEnd < 0) {
2181                    replyChainEnd = i;
2182                }
2183            } else if (!finishOnTaskLaunch
2184                    && !clearWhenTaskReset
2185                    && allowTaskReparenting
2186                    && target.taskAffinity != null
2187                    && !target.taskAffinity.equals(task.affinity)) {
2188                // If this activity has an affinity for another
2189                // task, then we need to move it out of here.  We will
2190                // move it as far out of the way as possible, to the
2191                // bottom of the activity stack.  This also keeps it
2192                // correctly ordered with any activities we previously
2193                // moved.
2194                final TaskRecord targetTask;
2195                final ActivityRecord bottom =
2196                        !mTaskHistory.isEmpty() && !mTaskHistory.get(0).mActivities.isEmpty() ?
2197                                mTaskHistory.get(0).mActivities.get(0) : null;
2198                if (bottom != null && target.taskAffinity != null
2199                        && target.taskAffinity.equals(bottom.task.affinity)) {
2200                    // If the activity currently at the bottom has the
2201                    // same task affinity as the one we are moving,
2202                    // then merge it into the same task.
2203                    targetTask = bottom.task;
2204                    if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
2205                            + " out to bottom task " + bottom.task);
2206                } else {
2207                    targetTask = createTaskRecord(mStackSupervisor.getNextTaskId(), target.info,
2208                            null, null, null, false);
2209                    targetTask.affinityIntent = target.intent;
2210                    if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
2211                            + " out to new task " + target.task);
2212                }
2213
2214                final int targetTaskId = targetTask.taskId;
2215                mWindowManager.setAppGroupId(target.appToken, targetTaskId);
2216
2217                boolean noOptions = canMoveOptions;
2218                final int start = replyChainEnd < 0 ? i : replyChainEnd;
2219                for (int srcPos = start; srcPos >= i; --srcPos) {
2220                    final ActivityRecord p = activities.get(srcPos);
2221                    if (p.finishing) {
2222                        continue;
2223                    }
2224
2225                    canMoveOptions = false;
2226                    if (noOptions && topOptions == null) {
2227                        topOptions = p.takeOptionsLocked();
2228                        if (topOptions != null) {
2229                            noOptions = false;
2230                        }
2231                    }
2232                    if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing activity " + p + " from task="
2233                            + task + " adding to task=" + targetTask
2234                            + " Callers=" + Debug.getCallers(4));
2235                    if (DEBUG_TASKS) Slog.v(TAG, "Pushing next activity " + p
2236                            + " out to target's task " + target.task);
2237                    p.setTask(targetTask, null);
2238                    targetTask.addActivityAtBottom(p);
2239
2240                    mWindowManager.setAppGroupId(p.appToken, targetTaskId);
2241                }
2242
2243                mWindowManager.moveTaskToBottom(targetTaskId);
2244                if (VALIDATE_TOKENS) {
2245                    validateAppTokensLocked();
2246                }
2247
2248                replyChainEnd = -1;
2249            } else if (forceReset || finishOnTaskLaunch || clearWhenTaskReset) {
2250                // If the activity should just be removed -- either
2251                // because it asks for it, or the task should be
2252                // cleared -- then finish it and anything that is
2253                // part of its reply chain.
2254                int end;
2255                if (clearWhenTaskReset) {
2256                    // In this case, we want to finish this activity
2257                    // and everything above it, so be sneaky and pretend
2258                    // like these are all in the reply chain.
2259                    end = numActivities - 1;
2260                } else if (replyChainEnd < 0) {
2261                    end = i;
2262                } else {
2263                    end = replyChainEnd;
2264                }
2265                boolean noOptions = canMoveOptions;
2266                for (int srcPos = i; srcPos <= end; srcPos++) {
2267                    ActivityRecord p = activities.get(srcPos);
2268                    if (p.finishing) {
2269                        continue;
2270                    }
2271                    canMoveOptions = false;
2272                    if (noOptions && topOptions == null) {
2273                        topOptions = p.takeOptionsLocked();
2274                        if (topOptions != null) {
2275                            noOptions = false;
2276                        }
2277                    }
2278                    if (DEBUG_TASKS) Slog.w(TAG,
2279                            "resetTaskIntendedTask: calling finishActivity on " + p);
2280                    if (finishActivityLocked(p, Activity.RESULT_CANCELED, null, "reset", false)) {
2281                        end--;
2282                        srcPos--;
2283                    }
2284                }
2285                replyChainEnd = -1;
2286            } else {
2287                // If we were in the middle of a chain, well the
2288                // activity that started it all doesn't want anything
2289                // special, so leave it all as-is.
2290                replyChainEnd = -1;
2291            }
2292        }
2293
2294        return topOptions;
2295    }
2296
2297    /**
2298     * Helper method for #resetTaskIfNeededLocked. Processes all of the activities in a given
2299     * TaskRecord looking for an affinity with the task of resetTaskIfNeededLocked.taskTop.
2300     * @param affinityTask The task we are looking for an affinity to.
2301     * @param task Task that resetTaskIfNeededLocked.taskTop belongs to.
2302     * @param topTaskIsHigher True if #task has already been processed by resetTaskIfNeededLocked.
2303     * @param forceReset Flag passed in to resetTaskIfNeededLocked.
2304     */
2305    private int resetAffinityTaskIfNeededLocked(TaskRecord affinityTask, TaskRecord task,
2306            boolean topTaskIsHigher, boolean forceReset, int taskInsertionPoint) {
2307        int replyChainEnd = -1;
2308        final int taskId = task.taskId;
2309        final String taskAffinity = task.affinity;
2310
2311        final ArrayList<ActivityRecord> activities = affinityTask.mActivities;
2312        final int numActivities = activities.size();
2313        final int rootActivityNdx = affinityTask.findEffectiveRootIndex();
2314
2315        // Do not operate on or below the effective root Activity.
2316        for (int i = numActivities - 1; i > rootActivityNdx; --i) {
2317            ActivityRecord target = activities.get(i);
2318            if (target.frontOfTask)
2319                break;
2320
2321            final int flags = target.info.flags;
2322            boolean finishOnTaskLaunch = (flags & ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH) != 0;
2323            boolean allowTaskReparenting = (flags & ActivityInfo.FLAG_ALLOW_TASK_REPARENTING) != 0;
2324
2325            if (target.resultTo != null) {
2326                // If this activity is sending a reply to a previous
2327                // activity, we can't do anything with it now until
2328                // we reach the start of the reply chain.
2329                // XXX note that we are assuming the result is always
2330                // to the previous activity, which is almost always
2331                // the case but we really shouldn't count on.
2332                if (replyChainEnd < 0) {
2333                    replyChainEnd = i;
2334                }
2335            } else if (topTaskIsHigher
2336                    && allowTaskReparenting
2337                    && taskAffinity != null
2338                    && taskAffinity.equals(target.taskAffinity)) {
2339                // This activity has an affinity for our task. Either remove it if we are
2340                // clearing or move it over to our task.  Note that
2341                // we currently punt on the case where we are resetting a
2342                // task that is not at the top but who has activities above
2343                // with an affinity to it...  this is really not a normal
2344                // case, and we will need to later pull that task to the front
2345                // and usually at that point we will do the reset and pick
2346                // up those remaining activities.  (This only happens if
2347                // someone starts an activity in a new task from an activity
2348                // in a task that is not currently on top.)
2349                if (forceReset || finishOnTaskLaunch) {
2350                    final int start = replyChainEnd >= 0 ? replyChainEnd : i;
2351                    if (DEBUG_TASKS) Slog.v(TAG, "Finishing task at index " + start + " to " + i);
2352                    for (int srcPos = start; srcPos >= i; --srcPos) {
2353                        final ActivityRecord p = activities.get(srcPos);
2354                        if (p.finishing) {
2355                            continue;
2356                        }
2357                        finishActivityLocked(p, Activity.RESULT_CANCELED, null, "reset", false);
2358                    }
2359                } else {
2360                    if (taskInsertionPoint < 0) {
2361                        taskInsertionPoint = task.mActivities.size();
2362
2363                    }
2364
2365                    final int start = replyChainEnd >= 0 ? replyChainEnd : i;
2366                    if (DEBUG_TASKS) Slog.v(TAG, "Reparenting from task=" + affinityTask + ":"
2367                            + start + "-" + i + " to task=" + task + ":" + taskInsertionPoint);
2368                    for (int srcPos = start; srcPos >= i; --srcPos) {
2369                        final ActivityRecord p = activities.get(srcPos);
2370                        p.setTask(task, null);
2371                        task.addActivityAtIndex(taskInsertionPoint, p);
2372
2373                        if (DEBUG_ADD_REMOVE) Slog.i(TAG, "Removing and adding activity " + p
2374                                + " to stack at " + task,
2375                                new RuntimeException("here").fillInStackTrace());
2376                        if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p + " from " + srcPos
2377                                + " in to resetting task " + task);
2378                        mWindowManager.setAppGroupId(p.appToken, taskId);
2379                    }
2380                    mWindowManager.moveTaskToTop(taskId);
2381                    if (VALIDATE_TOKENS) {
2382                        validateAppTokensLocked();
2383                    }
2384
2385                    // Now we've moved it in to place...  but what if this is
2386                    // a singleTop activity and we have put it on top of another
2387                    // instance of the same activity?  Then we drop the instance
2388                    // below so it remains singleTop.
2389                    if (target.info.launchMode == ActivityInfo.LAUNCH_SINGLE_TOP) {
2390                        ArrayList<ActivityRecord> taskActivities = task.mActivities;
2391                        int targetNdx = taskActivities.indexOf(target);
2392                        if (targetNdx > 0) {
2393                            ActivityRecord p = taskActivities.get(targetNdx - 1);
2394                            if (p.intent.getComponent().equals(target.intent.getComponent())) {
2395                                finishActivityLocked(p, Activity.RESULT_CANCELED, null, "replace",
2396                                        false);
2397                            }
2398                        }
2399                    }
2400                }
2401
2402                replyChainEnd = -1;
2403            }
2404        }
2405        return taskInsertionPoint;
2406    }
2407
2408    final ActivityRecord resetTaskIfNeededLocked(ActivityRecord taskTop,
2409            ActivityRecord newActivity) {
2410        boolean forceReset =
2411                (newActivity.info.flags & ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH) != 0;
2412        if (ACTIVITY_INACTIVE_RESET_TIME > 0
2413                && taskTop.task.getInactiveDuration() > ACTIVITY_INACTIVE_RESET_TIME) {
2414            if ((newActivity.info.flags & ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE) == 0) {
2415                forceReset = true;
2416            }
2417        }
2418
2419        final TaskRecord task = taskTop.task;
2420
2421        /** False until we evaluate the TaskRecord associated with taskTop. Switches to true
2422         * for remaining tasks. Used for later tasks to reparent to task. */
2423        boolean taskFound = false;
2424
2425        /** If ActivityOptions are moved out and need to be aborted or moved to taskTop. */
2426        ActivityOptions topOptions = null;
2427
2428        // Preserve the location for reparenting in the new task.
2429        int reparentInsertionPoint = -1;
2430
2431        for (int i = mTaskHistory.size() - 1; i >= 0; --i) {
2432            final TaskRecord targetTask = mTaskHistory.get(i);
2433
2434            if (targetTask == task) {
2435                topOptions = resetTargetTaskIfNeededLocked(task, forceReset);
2436                taskFound = true;
2437            } else {
2438                reparentInsertionPoint = resetAffinityTaskIfNeededLocked(targetTask, task,
2439                        taskFound, forceReset, reparentInsertionPoint);
2440            }
2441        }
2442
2443        int taskNdx = mTaskHistory.indexOf(task);
2444        do {
2445            taskTop = mTaskHistory.get(taskNdx--).getTopActivity();
2446        } while (taskTop == null && taskNdx >= 0);
2447
2448        if (topOptions != null) {
2449            // If we got some ActivityOptions from an activity on top that
2450            // was removed from the task, propagate them to the new real top.
2451            if (taskTop != null) {
2452                taskTop.updateOptionsLocked(topOptions);
2453            } else {
2454                topOptions.abort();
2455            }
2456        }
2457
2458        return taskTop;
2459    }
2460
2461    void sendActivityResultLocked(int callingUid, ActivityRecord r,
2462            String resultWho, int requestCode, int resultCode, Intent data) {
2463
2464        if (callingUid > 0) {
2465            mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,
2466                    data, r.getUriPermissionsLocked(), r.userId);
2467        }
2468
2469        if (DEBUG_RESULTS) Slog.v(TAG, "Send activity result to " + r
2470                + " : who=" + resultWho + " req=" + requestCode
2471                + " res=" + resultCode + " data=" + data);
2472        if (mResumedActivity == r && r.app != null && r.app.thread != null) {
2473            try {
2474                ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
2475                list.add(new ResultInfo(resultWho, requestCode,
2476                        resultCode, data));
2477                r.app.thread.scheduleSendResult(r.appToken, list);
2478                return;
2479            } catch (Exception e) {
2480                Slog.w(TAG, "Exception thrown sending result to " + r, e);
2481            }
2482        }
2483
2484        r.addResultLocked(null, resultWho, requestCode, resultCode, data);
2485    }
2486
2487    private void adjustFocusedActivityLocked(ActivityRecord r) {
2488        if (mStackSupervisor.isFrontStack(this) && mService.mFocusedActivity == r) {
2489            ActivityRecord next = topRunningActivityLocked(null);
2490            if (next != r) {
2491                final TaskRecord task = r.task;
2492                if (r.frontOfTask && task == topTask() && task.isOverHomeStack()) {
2493                    mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo());
2494                }
2495            }
2496            ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
2497            if (top != null) {
2498                mService.setFocusedActivityLocked(top);
2499            }
2500        }
2501    }
2502
2503    final void stopActivityLocked(ActivityRecord r) {
2504        if (DEBUG_SWITCH) Slog.d(TAG, "Stopping: " + r);
2505        if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
2506                || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
2507            if (!r.finishing) {
2508                if (!mService.isSleeping()) {
2509                    if (DEBUG_STATES) {
2510                        Slog.d(TAG, "no-history finish of " + r);
2511                    }
2512                    requestFinishActivityLocked(r.appToken, Activity.RESULT_CANCELED, null,
2513                            "no-history", false);
2514                } else {
2515                    if (DEBUG_STATES) Slog.d(TAG, "Not finishing noHistory " + r
2516                            + " on stop because we're just sleeping");
2517                }
2518            }
2519        }
2520
2521        if (r.app != null && r.app.thread != null) {
2522            adjustFocusedActivityLocked(r);
2523            r.resumeKeyDispatchingLocked();
2524            try {
2525                r.stopped = false;
2526                if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
2527                        + " (stop requested)");
2528                r.state = ActivityState.STOPPING;
2529                if (DEBUG_VISBILITY) Slog.v(
2530                        TAG, "Stopping visible=" + r.visible + " for " + r);
2531                if (!r.visible) {
2532                    mWindowManager.setAppVisibility(r.appToken, false);
2533                }
2534                r.app.thread.scheduleStopActivity(r.appToken, r.visible, r.configChangeFlags);
2535                if (mService.isSleepingOrShuttingDown()) {
2536                    r.setSleeping(true);
2537                }
2538                Message msg = mHandler.obtainMessage(STOP_TIMEOUT_MSG, r);
2539                mHandler.sendMessageDelayed(msg, STOP_TIMEOUT);
2540            } catch (Exception e) {
2541                // Maybe just ignore exceptions here...  if the process
2542                // has crashed, our death notification will clean things
2543                // up.
2544                Slog.w(TAG, "Exception thrown during pause", e);
2545                // Just in case, assume it to be stopped.
2546                r.stopped = true;
2547                if (DEBUG_STATES) Slog.v(TAG, "Stop failed; moving to STOPPED: " + r);
2548                r.state = ActivityState.STOPPED;
2549                if (r.configDestroy) {
2550                    destroyActivityLocked(r, true, "stop-except");
2551                }
2552            }
2553        }
2554    }
2555
2556    /**
2557     * @return Returns true if the activity is being finished, false if for
2558     * some reason it is being left as-is.
2559     */
2560    final boolean requestFinishActivityLocked(IBinder token, int resultCode,
2561            Intent resultData, String reason, boolean oomAdj) {
2562        ActivityRecord r = isInStackLocked(token);
2563        if (DEBUG_RESULTS || DEBUG_STATES) Slog.v(
2564                TAG, "Finishing activity token=" + token + " r="
2565                + ", result=" + resultCode + ", data=" + resultData
2566                + ", reason=" + reason);
2567        if (r == null) {
2568            return false;
2569        }
2570
2571        finishActivityLocked(r, resultCode, resultData, reason, oomAdj);
2572        return true;
2573    }
2574
2575    final void finishSubActivityLocked(ActivityRecord self, String resultWho, int requestCode) {
2576        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
2577            ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
2578            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
2579                ActivityRecord r = activities.get(activityNdx);
2580                if (r.resultTo == self && r.requestCode == requestCode) {
2581                    if ((r.resultWho == null && resultWho == null) ||
2582                        (r.resultWho != null && r.resultWho.equals(resultWho))) {
2583                        finishActivityLocked(r, Activity.RESULT_CANCELED, null, "request-sub",
2584                                false);
2585                    }
2586                }
2587            }
2588        }
2589        mService.updateOomAdjLocked();
2590    }
2591
2592    final void finishTopRunningActivityLocked(ProcessRecord app) {
2593        ActivityRecord r = topRunningActivityLocked(null);
2594        if (r != null && r.app == app) {
2595            // If the top running activity is from this crashing
2596            // process, then terminate it to avoid getting in a loop.
2597            Slog.w(TAG, "  Force finishing activity "
2598                    + r.intent.getComponent().flattenToShortString());
2599            int taskNdx = mTaskHistory.indexOf(r.task);
2600            int activityNdx = r.task.mActivities.indexOf(r);
2601            finishActivityLocked(r, Activity.RESULT_CANCELED, null, "crashed", false);
2602            // Also terminate any activities below it that aren't yet
2603            // stopped, to avoid a situation where one will get
2604            // re-start our crashing activity once it gets resumed again.
2605            --activityNdx;
2606            if (activityNdx < 0) {
2607                do {
2608                    --taskNdx;
2609                    if (taskNdx < 0) {
2610                        break;
2611                    }
2612                    activityNdx = mTaskHistory.get(taskNdx).mActivities.size() - 1;
2613                } while (activityNdx < 0);
2614            }
2615            if (activityNdx >= 0) {
2616                r = mTaskHistory.get(taskNdx).mActivities.get(activityNdx);
2617                if (r.state == ActivityState.RESUMED
2618                        || r.state == ActivityState.PAUSING
2619                        || r.state == ActivityState.PAUSED) {
2620                    if (!r.isHomeActivity() || mService.mHomeProcess != r.app) {
2621                        Slog.w(TAG, "  Force finishing activity "
2622                                + r.intent.getComponent().flattenToShortString());
2623                        finishActivityLocked(r, Activity.RESULT_CANCELED, null, "crashed", false);
2624                    }
2625                }
2626            }
2627        }
2628    }
2629
2630    final void finishVoiceTask(IVoiceInteractionSession session) {
2631        IBinder sessionBinder = session.asBinder();
2632        boolean didOne = false;
2633        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
2634            TaskRecord tr = mTaskHistory.get(taskNdx);
2635            if (tr.voiceSession != null && tr.voiceSession.asBinder() == sessionBinder) {
2636                for (int activityNdx = tr.mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
2637                    ActivityRecord r = tr.mActivities.get(activityNdx);
2638                    if (!r.finishing) {
2639                        finishActivityLocked(r, Activity.RESULT_CANCELED, null, "finish-voice",
2640                                false);
2641                        didOne = true;
2642                    }
2643                }
2644            }
2645        }
2646        if (didOne) {
2647            mService.updateOomAdjLocked();
2648        }
2649    }
2650
2651    final boolean finishActivityAffinityLocked(ActivityRecord r) {
2652        ArrayList<ActivityRecord> activities = r.task.mActivities;
2653        for (int index = activities.indexOf(r); index >= 0; --index) {
2654            ActivityRecord cur = activities.get(index);
2655            if (!Objects.equals(cur.taskAffinity, r.taskAffinity)) {
2656                break;
2657            }
2658            finishActivityLocked(cur, Activity.RESULT_CANCELED, null, "request-affinity", true);
2659        }
2660        return true;
2661    }
2662
2663    final void finishActivityResultsLocked(ActivityRecord r, int resultCode, Intent resultData) {
2664        // send the result
2665        ActivityRecord resultTo = r.resultTo;
2666        if (resultTo != null) {
2667            if (DEBUG_RESULTS) Slog.v(TAG, "Adding result to " + resultTo
2668                    + " who=" + r.resultWho + " req=" + r.requestCode
2669                    + " res=" + resultCode + " data=" + resultData);
2670            if (resultTo.userId != r.userId) {
2671                if (resultData != null) {
2672                    resultData.setContentUserHint(r.userId);
2673                }
2674            }
2675            if (r.info.applicationInfo.uid > 0) {
2676                mService.grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
2677                        resultTo.packageName, resultData,
2678                        resultTo.getUriPermissionsLocked(), resultTo.userId);
2679            }
2680            resultTo.addResultLocked(r, r.resultWho, r.requestCode, resultCode,
2681                                     resultData);
2682            r.resultTo = null;
2683        }
2684        else if (DEBUG_RESULTS) Slog.v(TAG, "No result destination from " + r);
2685
2686        // Make sure this HistoryRecord is not holding on to other resources,
2687        // because clients have remote IPC references to this object so we
2688        // can't assume that will go away and want to avoid circular IPC refs.
2689        r.results = null;
2690        r.pendingResults = null;
2691        r.newIntents = null;
2692        r.icicle = null;
2693    }
2694
2695    /**
2696     * @return Returns true if this activity has been removed from the history
2697     * list, or false if it is still in the list and will be removed later.
2698     */
2699    final boolean finishActivityLocked(ActivityRecord r, int resultCode, Intent resultData,
2700            String reason, boolean oomAdj) {
2701        if (r.finishing) {
2702            Slog.w(TAG, "Duplicate finish request for " + r);
2703            return false;
2704        }
2705
2706        r.makeFinishing();
2707        final TaskRecord task = r.task;
2708        EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
2709                r.userId, System.identityHashCode(r),
2710                task.taskId, r.shortComponentName, reason);
2711        final ArrayList<ActivityRecord> activities = task.mActivities;
2712        final int index = activities.indexOf(r);
2713        if (index < (activities.size() - 1)) {
2714            task.setFrontOfTask();
2715            if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
2716                // If the caller asked that this activity (and all above it)
2717                // be cleared when the task is reset, don't lose that information,
2718                // but propagate it up to the next activity.
2719                ActivityRecord next = activities.get(index+1);
2720                next.intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
2721            }
2722        }
2723
2724        r.pauseKeyDispatchingLocked();
2725
2726        adjustFocusedActivityLocked(r);
2727
2728        finishActivityResultsLocked(r, resultCode, resultData);
2729
2730        if (mResumedActivity == r) {
2731            boolean endTask = index <= 0;
2732            if (DEBUG_VISBILITY || DEBUG_TRANSITION) Slog.v(TAG,
2733                    "Prepare close transition: finishing " + r);
2734            mWindowManager.prepareAppTransition(endTask
2735                    ? AppTransition.TRANSIT_TASK_CLOSE
2736                    : AppTransition.TRANSIT_ACTIVITY_CLOSE, false);
2737
2738            // Tell window manager to prepare for this one to be removed.
2739            mWindowManager.setAppVisibility(r.appToken, false);
2740
2741            if (mPausingActivity == null) {
2742                if (DEBUG_PAUSE) Slog.v(TAG, "Finish needs to pause: " + r);
2743                if (DEBUG_USER_LEAVING) Slog.v(TAG, "finish() => pause with userLeaving=false");
2744                startPausingLocked(false, false, false, false);
2745            }
2746
2747            if (endTask) {
2748                mStackSupervisor.endLockTaskModeIfTaskEnding(task);
2749            }
2750        } else if (r.state != ActivityState.PAUSING) {
2751            // If the activity is PAUSING, we will complete the finish once
2752            // it is done pausing; else we can just directly finish it here.
2753            if (DEBUG_PAUSE) Slog.v(TAG, "Finish not pausing: " + r);
2754            return finishCurrentActivityLocked(r, FINISH_AFTER_PAUSE, oomAdj) == null;
2755        } else {
2756            if (DEBUG_PAUSE) Slog.v(TAG, "Finish waiting for pause of: " + r);
2757        }
2758
2759        return false;
2760    }
2761
2762    static final int FINISH_IMMEDIATELY = 0;
2763    static final int FINISH_AFTER_PAUSE = 1;
2764    static final int FINISH_AFTER_VISIBLE = 2;
2765
2766    final ActivityRecord finishCurrentActivityLocked(ActivityRecord r, int mode, boolean oomAdj) {
2767        // First things first: if this activity is currently visible,
2768        // and the resumed activity is not yet visible, then hold off on
2769        // finishing until the resumed one becomes visible.
2770        if (mode == FINISH_AFTER_VISIBLE && r.nowVisible) {
2771            if (!mStackSupervisor.mStoppingActivities.contains(r)) {
2772                mStackSupervisor.mStoppingActivities.add(r);
2773                if (mStackSupervisor.mStoppingActivities.size() > 3
2774                        || r.frontOfTask && mTaskHistory.size() <= 1) {
2775                    // If we already have a few activities waiting to stop,
2776                    // then give up on things going idle and start clearing
2777                    // them out. Or if r is the last of activity of the last task the stack
2778                    // will be empty and must be cleared immediately.
2779                    mStackSupervisor.scheduleIdleLocked();
2780                } else {
2781                    mStackSupervisor.checkReadyForSleepLocked();
2782                }
2783            }
2784            if (DEBUG_STATES) Slog.v(TAG, "Moving to STOPPING: " + r
2785                    + " (finish requested)");
2786            r.state = ActivityState.STOPPING;
2787            if (oomAdj) {
2788                mService.updateOomAdjLocked();
2789            }
2790            return r;
2791        }
2792
2793        // make sure the record is cleaned out of other places.
2794        mStackSupervisor.mStoppingActivities.remove(r);
2795        mStackSupervisor.mGoingToSleepActivities.remove(r);
2796        mStackSupervisor.mWaitingVisibleActivities.remove(r);
2797        if (mResumedActivity == r) {
2798            mResumedActivity = null;
2799        }
2800        final ActivityState prevState = r.state;
2801        if (DEBUG_STATES) Slog.v(TAG, "Moving to FINISHING: " + r);
2802        r.state = ActivityState.FINISHING;
2803
2804        if (mode == FINISH_IMMEDIATELY
2805                || prevState == ActivityState.STOPPED
2806                || prevState == ActivityState.INITIALIZING) {
2807            // If this activity is already stopped, we can just finish
2808            // it right now.
2809            r.makeFinishing();
2810            boolean activityRemoved = destroyActivityLocked(r, true, "finish-imm");
2811            if (activityRemoved) {
2812                mStackSupervisor.resumeTopActivitiesLocked();
2813            }
2814            if (DEBUG_CONTAINERS) Slog.d(TAG,
2815                    "destroyActivityLocked: finishCurrentActivityLocked r=" + r +
2816                    " destroy returned removed=" + activityRemoved);
2817            return activityRemoved ? null : r;
2818        }
2819
2820        // Need to go through the full pause cycle to get this
2821        // activity into the stopped state and then finish it.
2822        if (localLOGV) Slog.v(TAG, "Enqueueing pending finish: " + r);
2823        mStackSupervisor.mFinishingActivities.add(r);
2824        r.resumeKeyDispatchingLocked();
2825        mStackSupervisor.getFocusedStack().resumeTopActivityLocked(null);
2826        return r;
2827    }
2828
2829    void finishAllActivitiesLocked(boolean immediately) {
2830        boolean noActivitiesInStack = true;
2831        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
2832            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
2833            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
2834                final ActivityRecord r = activities.get(activityNdx);
2835                noActivitiesInStack = false;
2836                if (r.finishing && !immediately) {
2837                    continue;
2838                }
2839                Slog.d(TAG, "finishAllActivitiesLocked: finishing " + r + " immediately");
2840                finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
2841            }
2842        }
2843        if (noActivitiesInStack) {
2844            mActivityContainer.onTaskListEmptyLocked();
2845        }
2846    }
2847
2848    final boolean shouldUpRecreateTaskLocked(ActivityRecord srec, String destAffinity) {
2849        // Basic case: for simple app-centric recents, we need to recreate
2850        // the task if the affinity has changed.
2851        if (srec == null || srec.task.affinity == null ||
2852                !srec.task.affinity.equals(destAffinity)) {
2853            return true;
2854        }
2855        // Document-centric case: an app may be split in to multiple documents;
2856        // they need to re-create their task if this current activity is the root
2857        // of a document, unless simply finishing it will return them to the the
2858        // correct app behind.
2859        if (srec.frontOfTask && srec.task != null) {
2860            // Okay, this activity is at the root of its task.  What to do, what to do...
2861            if (srec.task.getTaskToReturnTo() != ActivityRecord.APPLICATION_ACTIVITY_TYPE) {
2862                // Finishing won't return to an application, so we need to recreate.
2863                return true;
2864            }
2865            // We now need to get the task below it to determine what to do.
2866            int taskIdx = mTaskHistory.indexOf(srec.task);
2867            if (taskIdx <= 0) {
2868                Slog.w(TAG, "shouldUpRecreateTask: task not in history for " + srec);
2869                return false;
2870            }
2871            if (taskIdx == 0) {
2872                // At the bottom of the stack, nothing to go back to.
2873                return true;
2874            }
2875            TaskRecord prevTask = mTaskHistory.get(taskIdx);
2876            if (!srec.task.affinity.equals(prevTask.affinity)) {
2877                // These are different apps, so need to recreate.
2878                return true;
2879            }
2880        }
2881        return false;
2882    }
2883
2884    final boolean navigateUpToLocked(IBinder token, Intent destIntent, int resultCode,
2885            Intent resultData) {
2886        final ActivityRecord srec = ActivityRecord.forToken(token);
2887        final TaskRecord task = srec.task;
2888        final ArrayList<ActivityRecord> activities = task.mActivities;
2889        final int start = activities.indexOf(srec);
2890        if (!mTaskHistory.contains(task) || (start < 0)) {
2891            return false;
2892        }
2893        int finishTo = start - 1;
2894        ActivityRecord parent = finishTo < 0 ? null : activities.get(finishTo);
2895        boolean foundParentInTask = false;
2896        final ComponentName dest = destIntent.getComponent();
2897        if (start > 0 && dest != null) {
2898            for (int i = finishTo; i >= 0; i--) {
2899                ActivityRecord r = activities.get(i);
2900                if (r.info.packageName.equals(dest.getPackageName()) &&
2901                        r.info.name.equals(dest.getClassName())) {
2902                    finishTo = i;
2903                    parent = r;
2904                    foundParentInTask = true;
2905                    break;
2906                }
2907            }
2908        }
2909
2910        IActivityController controller = mService.mController;
2911        if (controller != null) {
2912            ActivityRecord next = topRunningActivityLocked(srec.appToken, 0);
2913            if (next != null) {
2914                // ask watcher if this is allowed
2915                boolean resumeOK = true;
2916                try {
2917                    resumeOK = controller.activityResuming(next.packageName);
2918                } catch (RemoteException e) {
2919                    mService.mController = null;
2920                    Watchdog.getInstance().setActivityController(null);
2921                }
2922
2923                if (!resumeOK) {
2924                    return false;
2925                }
2926            }
2927        }
2928        final long origId = Binder.clearCallingIdentity();
2929        for (int i = start; i > finishTo; i--) {
2930            ActivityRecord r = activities.get(i);
2931            requestFinishActivityLocked(r.appToken, resultCode, resultData, "navigate-up", true);
2932            // Only return the supplied result for the first activity finished
2933            resultCode = Activity.RESULT_CANCELED;
2934            resultData = null;
2935        }
2936
2937        if (parent != null && foundParentInTask) {
2938            final int parentLaunchMode = parent.info.launchMode;
2939            final int destIntentFlags = destIntent.getFlags();
2940            if (parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE ||
2941                    parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TASK ||
2942                    parentLaunchMode == ActivityInfo.LAUNCH_SINGLE_TOP ||
2943                    (destIntentFlags & Intent.FLAG_ACTIVITY_CLEAR_TOP) != 0) {
2944                parent.deliverNewIntentLocked(srec.info.applicationInfo.uid, destIntent);
2945            } else {
2946                try {
2947                    ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
2948                            destIntent.getComponent(), 0, srec.userId);
2949                    int res = mStackSupervisor.startActivityLocked(srec.app.thread, destIntent,
2950                            null, aInfo, null, null, parent.appToken, null,
2951                            0, -1, parent.launchedFromUid, parent.launchedFromPackage,
2952                            0, null, true, null, null, null);
2953                    foundParentInTask = res == ActivityManager.START_SUCCESS;
2954                } catch (RemoteException e) {
2955                    foundParentInTask = false;
2956                }
2957                requestFinishActivityLocked(parent.appToken, resultCode,
2958                        resultData, "navigate-up", true);
2959            }
2960        }
2961        Binder.restoreCallingIdentity(origId);
2962        return foundParentInTask;
2963    }
2964    /**
2965     * Perform the common clean-up of an activity record.  This is called both
2966     * as part of destroyActivityLocked() (when destroying the client-side
2967     * representation) and cleaning things up as a result of its hosting
2968     * processing going away, in which case there is no remaining client-side
2969     * state to destroy so only the cleanup here is needed.
2970     */
2971    final void cleanUpActivityLocked(ActivityRecord r, boolean cleanServices,
2972            boolean setState) {
2973        if (mResumedActivity == r) {
2974            mResumedActivity = null;
2975        }
2976        if (mPausingActivity == r) {
2977            mPausingActivity = null;
2978        }
2979        mService.clearFocusedActivity(r);
2980
2981        r.configDestroy = false;
2982        r.frozenBeforeDestroy = false;
2983
2984        if (setState) {
2985            if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (cleaning up)");
2986            r.state = ActivityState.DESTROYED;
2987            if (DEBUG_APP) Slog.v(TAG, "Clearing app during cleanUp for activity " + r);
2988            r.app = null;
2989        }
2990
2991        // Make sure this record is no longer in the pending finishes list.
2992        // This could happen, for example, if we are trimming activities
2993        // down to the max limit while they are still waiting to finish.
2994        mStackSupervisor.mFinishingActivities.remove(r);
2995        mStackSupervisor.mWaitingVisibleActivities.remove(r);
2996
2997        // Remove any pending results.
2998        if (r.finishing && r.pendingResults != null) {
2999            for (WeakReference<PendingIntentRecord> apr : r.pendingResults) {
3000                PendingIntentRecord rec = apr.get();
3001                if (rec != null) {
3002                    mService.cancelIntentSenderLocked(rec, false);
3003                }
3004            }
3005            r.pendingResults = null;
3006        }
3007
3008        if (cleanServices) {
3009            cleanUpActivityServicesLocked(r);
3010        }
3011
3012        // Get rid of any pending idle timeouts.
3013        removeTimeoutsForActivityLocked(r);
3014        if (getVisibleBehindActivity() == r) {
3015            mStackSupervisor.requestVisibleBehindLocked(r, false);
3016        }
3017    }
3018
3019    private void removeTimeoutsForActivityLocked(ActivityRecord r) {
3020        mStackSupervisor.removeTimeoutsForActivityLocked(r);
3021        mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
3022        mHandler.removeMessages(STOP_TIMEOUT_MSG, r);
3023        mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
3024        r.finishLaunchTickingLocked();
3025    }
3026
3027    private void removeActivityFromHistoryLocked(ActivityRecord r) {
3028        mStackSupervisor.removeChildActivityContainers(r);
3029        finishActivityResultsLocked(r, Activity.RESULT_CANCELED, null);
3030        r.makeFinishing();
3031        if (DEBUG_ADD_REMOVE) {
3032            RuntimeException here = new RuntimeException("here");
3033            here.fillInStackTrace();
3034            Slog.i(TAG, "Removing activity " + r + " from stack");
3035        }
3036        r.takeFromHistory();
3037        removeTimeoutsForActivityLocked(r);
3038        if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (removed from history)");
3039        r.state = ActivityState.DESTROYED;
3040        if (DEBUG_APP) Slog.v(TAG, "Clearing app during remove for activity " + r);
3041        r.app = null;
3042        mWindowManager.removeAppToken(r.appToken);
3043        if (VALIDATE_TOKENS) {
3044            validateAppTokensLocked();
3045        }
3046        final TaskRecord task = r.task;
3047        if (task != null && task.removeActivity(r)) {
3048            if (DEBUG_STACK) Slog.i(TAG,
3049                    "removeActivityFromHistoryLocked: last activity removed from " + this);
3050            if (mStackSupervisor.isFrontStack(this) && task == topTask() &&
3051                    task.isOverHomeStack()) {
3052                mStackSupervisor.moveHomeStackTaskToTop(task.getTaskToReturnTo());
3053            }
3054            removeTask(task);
3055        }
3056        cleanUpActivityServicesLocked(r);
3057        r.removeUriPermissionsLocked();
3058    }
3059
3060    /**
3061     * Perform clean-up of service connections in an activity record.
3062     */
3063    final void cleanUpActivityServicesLocked(ActivityRecord r) {
3064        // Throw away any services that have been bound by this activity.
3065        if (r.connections != null) {
3066            Iterator<ConnectionRecord> it = r.connections.iterator();
3067            while (it.hasNext()) {
3068                ConnectionRecord c = it.next();
3069                mService.mServices.removeConnectionLocked(c, null, r);
3070            }
3071            r.connections = null;
3072        }
3073    }
3074
3075    final void scheduleDestroyActivities(ProcessRecord owner, String reason) {
3076        Message msg = mHandler.obtainMessage(DESTROY_ACTIVITIES_MSG);
3077        msg.obj = new ScheduleDestroyArgs(owner, reason);
3078        mHandler.sendMessage(msg);
3079    }
3080
3081    final void destroyActivitiesLocked(ProcessRecord owner, String reason) {
3082        boolean lastIsOpaque = false;
3083        boolean activityRemoved = false;
3084        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3085            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3086            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3087                final ActivityRecord r = activities.get(activityNdx);
3088                if (r.finishing) {
3089                    continue;
3090                }
3091                if (r.fullscreen) {
3092                    lastIsOpaque = true;
3093                }
3094                if (owner != null && r.app != owner) {
3095                    continue;
3096                }
3097                if (!lastIsOpaque) {
3098                    continue;
3099                }
3100                if (r.isDestroyable()) {
3101                    if (DEBUG_SWITCH) Slog.v(TAG, "Destroying " + r + " in state " + r.state
3102                            + " resumed=" + mResumedActivity
3103                            + " pausing=" + mPausingActivity + " for reason " + reason);
3104                    if (destroyActivityLocked(r, true, reason)) {
3105                        activityRemoved = true;
3106                    }
3107                }
3108            }
3109        }
3110        if (activityRemoved) {
3111            mStackSupervisor.resumeTopActivitiesLocked();
3112        }
3113    }
3114
3115    final boolean safelyDestroyActivityLocked(ActivityRecord r, String reason) {
3116        if (r.isDestroyable()) {
3117            if (DEBUG_SWITCH) Slog.v(TAG, "Destroying " + r + " in state " + r.state
3118                    + " resumed=" + mResumedActivity
3119                    + " pausing=" + mPausingActivity + " for reason " + reason);
3120            return destroyActivityLocked(r, true, reason);
3121        }
3122        return false;
3123    }
3124
3125    final int releaseSomeActivitiesLocked(ProcessRecord app, ArraySet<TaskRecord> tasks,
3126            String reason) {
3127        // Iterate over tasks starting at the back (oldest) first.
3128        if (DEBUG_RELEASE) Slog.d(TAG, "Trying to release some activities in " + app);
3129        int maxTasks = tasks.size() / 4;
3130        if (maxTasks < 1) {
3131            maxTasks = 1;
3132        }
3133        int numReleased = 0;
3134        for (int taskNdx = 0; taskNdx < mTaskHistory.size() && maxTasks > 0; taskNdx++) {
3135            final TaskRecord task = mTaskHistory.get(taskNdx);
3136            if (!tasks.contains(task)) {
3137                continue;
3138            }
3139            if (DEBUG_RELEASE) Slog.d(TAG, "Looking for activities to release in " + task);
3140            int curNum = 0;
3141            final ArrayList<ActivityRecord> activities = task.mActivities;
3142            for (int actNdx = 0; actNdx < activities.size(); actNdx++) {
3143                final ActivityRecord activity = activities.get(actNdx);
3144                if (activity.app == app && activity.isDestroyable()) {
3145                    if (DEBUG_RELEASE) Slog.v(TAG, "Destroying " + activity
3146                            + " in state " + activity.state + " resumed=" + mResumedActivity
3147                            + " pausing=" + mPausingActivity + " for reason " + reason);
3148                    destroyActivityLocked(activity, true, reason);
3149                    if (activities.get(actNdx) != activity) {
3150                        // Was removed from list, back up so we don't miss the next one.
3151                        actNdx--;
3152                    }
3153                    curNum++;
3154                }
3155            }
3156            if (curNum > 0) {
3157                numReleased += curNum;
3158                maxTasks--;
3159                if (mTaskHistory.get(taskNdx) != task) {
3160                    // The entire task got removed, back up so we don't miss the next one.
3161                    taskNdx--;
3162                }
3163            }
3164        }
3165        if (DEBUG_RELEASE) Slog.d(TAG, "Done releasing: did " + numReleased + " activities");
3166        return numReleased;
3167    }
3168
3169    /**
3170     * Destroy the current CLIENT SIDE instance of an activity.  This may be
3171     * called both when actually finishing an activity, or when performing
3172     * a configuration switch where we destroy the current client-side object
3173     * but then create a new client-side object for this same HistoryRecord.
3174     */
3175    final boolean destroyActivityLocked(ActivityRecord r, boolean removeFromApp, String reason) {
3176        if (DEBUG_SWITCH || DEBUG_CLEANUP) Slog.v(
3177            TAG, "Removing activity from " + reason + ": token=" + r
3178              + ", app=" + (r.app != null ? r.app.processName : "(null)"));
3179        EventLog.writeEvent(EventLogTags.AM_DESTROY_ACTIVITY,
3180                r.userId, System.identityHashCode(r),
3181                r.task.taskId, r.shortComponentName, reason);
3182
3183        boolean removedFromHistory = false;
3184
3185        cleanUpActivityLocked(r, false, false);
3186
3187        final boolean hadApp = r.app != null;
3188
3189        if (hadApp) {
3190            if (removeFromApp) {
3191                r.app.activities.remove(r);
3192                if (mService.mHeavyWeightProcess == r.app && r.app.activities.size() <= 0) {
3193                    mService.mHeavyWeightProcess = null;
3194                    mService.mHandler.sendEmptyMessage(
3195                            ActivityManagerService.CANCEL_HEAVY_NOTIFICATION_MSG);
3196                }
3197                if (r.app.activities.isEmpty()) {
3198                    // Update any services we are bound to that might care about whether
3199                    // their client may have activities.
3200                    mService.mServices.updateServiceConnectionActivitiesLocked(r.app);
3201                    // No longer have activities, so update LRU list and oom adj.
3202                    mService.updateLruProcessLocked(r.app, false, null);
3203                    mService.updateOomAdjLocked();
3204                }
3205            }
3206
3207            boolean skipDestroy = false;
3208
3209            try {
3210                if (DEBUG_SWITCH) Slog.i(TAG, "Destroying: " + r);
3211                r.app.thread.scheduleDestroyActivity(r.appToken, r.finishing,
3212                        r.configChangeFlags);
3213            } catch (Exception e) {
3214                // We can just ignore exceptions here...  if the process
3215                // has crashed, our death notification will clean things
3216                // up.
3217                //Slog.w(TAG, "Exception thrown during finish", e);
3218                if (r.finishing) {
3219                    removeActivityFromHistoryLocked(r);
3220                    removedFromHistory = true;
3221                    skipDestroy = true;
3222                }
3223            }
3224
3225            r.nowVisible = false;
3226
3227            // If the activity is finishing, we need to wait on removing it
3228            // from the list to give it a chance to do its cleanup.  During
3229            // that time it may make calls back with its token so we need to
3230            // be able to find it on the list and so we don't want to remove
3231            // it from the list yet.  Otherwise, we can just immediately put
3232            // it in the destroyed state since we are not removing it from the
3233            // list.
3234            if (r.finishing && !skipDestroy) {
3235                if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYING: " + r
3236                        + " (destroy requested)");
3237                r.state = ActivityState.DESTROYING;
3238                Message msg = mHandler.obtainMessage(DESTROY_TIMEOUT_MSG, r);
3239                mHandler.sendMessageDelayed(msg, DESTROY_TIMEOUT);
3240            } else {
3241                if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (destroy skipped)");
3242                r.state = ActivityState.DESTROYED;
3243                if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r);
3244                r.app = null;
3245            }
3246        } else {
3247            // remove this record from the history.
3248            if (r.finishing) {
3249                removeActivityFromHistoryLocked(r);
3250                removedFromHistory = true;
3251            } else {
3252                if (DEBUG_STATES) Slog.v(TAG, "Moving to DESTROYED: " + r + " (no app)");
3253                r.state = ActivityState.DESTROYED;
3254                if (DEBUG_APP) Slog.v(TAG, "Clearing app during destroy for activity " + r);
3255                r.app = null;
3256            }
3257        }
3258
3259        r.configChangeFlags = 0;
3260
3261        if (!mLRUActivities.remove(r) && hadApp) {
3262            Slog.w(TAG, "Activity " + r + " being finished, but not in LRU list");
3263        }
3264
3265        return removedFromHistory;
3266    }
3267
3268    final void activityDestroyedLocked(IBinder token) {
3269        final long origId = Binder.clearCallingIdentity();
3270        try {
3271            ActivityRecord r = ActivityRecord.forToken(token);
3272            if (r != null) {
3273                mHandler.removeMessages(DESTROY_TIMEOUT_MSG, r);
3274            }
3275            if (DEBUG_CONTAINERS) Slog.d(TAG, "activityDestroyedLocked: r=" + r);
3276
3277            if (isInStackLocked(token) != null) {
3278                if (r.state == ActivityState.DESTROYING) {
3279                    cleanUpActivityLocked(r, true, false);
3280                    removeActivityFromHistoryLocked(r);
3281                }
3282            }
3283            mStackSupervisor.resumeTopActivitiesLocked();
3284        } finally {
3285            Binder.restoreCallingIdentity(origId);
3286        }
3287    }
3288
3289    void releaseBackgroundResources() {
3290        if (hasVisibleBehindActivity() &&
3291                !mHandler.hasMessages(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG)) {
3292            final ActivityRecord r = getVisibleBehindActivity();
3293            if (DEBUG_STATES) Slog.d(TAG, "releaseBackgroundResources activtyDisplay=" +
3294                    mActivityContainer.mActivityDisplay + " visibleBehind=" + r + " app=" + r.app +
3295                    " thread=" + r.app.thread);
3296            if (r != null && r.app != null && r.app.thread != null) {
3297                try {
3298                    r.app.thread.scheduleCancelVisibleBehind(r.appToken);
3299                } catch (RemoteException e) {
3300                }
3301                mHandler.sendEmptyMessageDelayed(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG, 500);
3302            } else {
3303                Slog.e(TAG, "releaseBackgroundResources: activity " + r + " no longer running");
3304                backgroundResourcesReleased(r.appToken);
3305            }
3306        }
3307    }
3308
3309    final void backgroundResourcesReleased(IBinder token) {
3310        mHandler.removeMessages(RELEASE_BACKGROUND_RESOURCES_TIMEOUT_MSG);
3311        final ActivityRecord r = getVisibleBehindActivity();
3312        if (r != null) {
3313            mStackSupervisor.mStoppingActivities.add(r);
3314            setVisibleBehindActivity(null);
3315        }
3316        mStackSupervisor.resumeTopActivitiesLocked();
3317    }
3318
3319    boolean hasVisibleBehindActivity() {
3320        return isAttached() && mActivityContainer.mActivityDisplay.hasVisibleBehindActivity();
3321    }
3322
3323    void setVisibleBehindActivity(ActivityRecord r) {
3324        if (isAttached()) {
3325            mActivityContainer.mActivityDisplay.setVisibleBehindActivity(r);
3326        }
3327    }
3328
3329    ActivityRecord getVisibleBehindActivity() {
3330        return isAttached() ? mActivityContainer.mActivityDisplay.mVisibleBehindActivity : null;
3331    }
3332
3333    private void removeHistoryRecordsForAppLocked(ArrayList<ActivityRecord> list,
3334            ProcessRecord app, String listName) {
3335        int i = list.size();
3336        if (DEBUG_CLEANUP) Slog.v(
3337            TAG, "Removing app " + app + " from list " + listName
3338            + " with " + i + " entries");
3339        while (i > 0) {
3340            i--;
3341            ActivityRecord r = list.get(i);
3342            if (DEBUG_CLEANUP) Slog.v(TAG, "Record #" + i + " " + r);
3343            if (r.app == app) {
3344                if (DEBUG_CLEANUP) Slog.v(TAG, "---> REMOVING this entry!");
3345                list.remove(i);
3346                removeTimeoutsForActivityLocked(r);
3347            }
3348        }
3349    }
3350
3351    boolean removeHistoryRecordsForAppLocked(ProcessRecord app) {
3352        removeHistoryRecordsForAppLocked(mLRUActivities, app, "mLRUActivities");
3353        removeHistoryRecordsForAppLocked(mStackSupervisor.mStoppingActivities, app,
3354                "mStoppingActivities");
3355        removeHistoryRecordsForAppLocked(mStackSupervisor.mGoingToSleepActivities, app,
3356                "mGoingToSleepActivities");
3357        removeHistoryRecordsForAppLocked(mStackSupervisor.mWaitingVisibleActivities, app,
3358                "mWaitingVisibleActivities");
3359        removeHistoryRecordsForAppLocked(mStackSupervisor.mFinishingActivities, app,
3360                "mFinishingActivities");
3361
3362        boolean hasVisibleActivities = false;
3363
3364        // Clean out the history list.
3365        int i = numActivities();
3366        if (DEBUG_CLEANUP) Slog.v(
3367            TAG, "Removing app " + app + " from history with " + i + " entries");
3368        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3369            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3370            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3371                final ActivityRecord r = activities.get(activityNdx);
3372                --i;
3373                if (DEBUG_CLEANUP) Slog.v(
3374                    TAG, "Record #" + i + " " + r + ": app=" + r.app);
3375                if (r.app == app) {
3376                    boolean remove;
3377                    if ((!r.haveState && !r.stateNotNeeded) || r.finishing) {
3378                        // Don't currently have state for the activity, or
3379                        // it is finishing -- always remove it.
3380                        remove = true;
3381                    } else if (r.launchCount > 2 &&
3382                            r.lastLaunchTime > (SystemClock.uptimeMillis()-60000)) {
3383                        // We have launched this activity too many times since it was
3384                        // able to run, so give up and remove it.
3385                        remove = true;
3386                    } else {
3387                        // The process may be gone, but the activity lives on!
3388                        remove = false;
3389                    }
3390                    if (remove) {
3391                        if (DEBUG_ADD_REMOVE || DEBUG_CLEANUP) {
3392                            RuntimeException here = new RuntimeException("here");
3393                            here.fillInStackTrace();
3394                            Slog.i(TAG, "Removing activity " + r + " from stack at " + i
3395                                    + ": haveState=" + r.haveState
3396                                    + " stateNotNeeded=" + r.stateNotNeeded
3397                                    + " finishing=" + r.finishing
3398                                    + " state=" + r.state, here);
3399                        }
3400                        if (!r.finishing) {
3401                            Slog.w(TAG, "Force removing " + r + ": app died, no saved state");
3402                            EventLog.writeEvent(EventLogTags.AM_FINISH_ACTIVITY,
3403                                    r.userId, System.identityHashCode(r),
3404                                    r.task.taskId, r.shortComponentName,
3405                                    "proc died without state saved");
3406                            if (r.state == ActivityState.RESUMED) {
3407                                mService.updateUsageStats(r, false);
3408                            }
3409                        }
3410                        removeActivityFromHistoryLocked(r);
3411
3412                    } else {
3413                        // We have the current state for this activity, so
3414                        // it can be restarted later when needed.
3415                        if (localLOGV) Slog.v(
3416                            TAG, "Keeping entry, setting app to null");
3417                        if (r.visible) {
3418                            hasVisibleActivities = true;
3419                        }
3420                        if (DEBUG_APP) Slog.v(TAG, "Clearing app during removeHistory for activity "
3421                                + r);
3422                        r.app = null;
3423                        r.nowVisible = false;
3424                        if (!r.haveState) {
3425                            if (DEBUG_SAVED_STATE) Slog.i(TAG,
3426                                    "App died, clearing saved state of " + r);
3427                            r.icicle = null;
3428                        }
3429                    }
3430
3431                    cleanUpActivityLocked(r, true, true);
3432                }
3433            }
3434        }
3435
3436        return hasVisibleActivities;
3437    }
3438
3439    final void updateTransitLocked(int transit, Bundle options) {
3440        if (options != null) {
3441            ActivityRecord r = topRunningActivityLocked(null);
3442            if (r != null && r.state != ActivityState.RESUMED) {
3443                r.updateOptionsLocked(options);
3444            } else {
3445                ActivityOptions.abort(options);
3446            }
3447        }
3448        mWindowManager.prepareAppTransition(transit, false);
3449    }
3450
3451    void updateTaskMovement(TaskRecord task, boolean toFront) {
3452        if (task.isPersistable) {
3453            task.mLastTimeMoved = System.currentTimeMillis();
3454            // Sign is used to keep tasks sorted when persisted. Tasks sent to the bottom most
3455            // recently will be most negative, tasks sent to the bottom before that will be less
3456            // negative. Similarly for recent tasks moved to the top which will be most positive.
3457            if (!toFront) {
3458                task.mLastTimeMoved *= -1;
3459            }
3460        }
3461    }
3462
3463    void moveHomeStackTaskToTop(int homeStackTaskType) {
3464        final int top = mTaskHistory.size() - 1;
3465        for (int taskNdx = top; taskNdx >= 0; --taskNdx) {
3466            final TaskRecord task = mTaskHistory.get(taskNdx);
3467            if (task.taskType == homeStackTaskType) {
3468                if (DEBUG_TASKS || DEBUG_STACK)
3469                    Slog.d(TAG, "moveHomeStackTaskToTop: moving " + task);
3470                mTaskHistory.remove(taskNdx);
3471                mTaskHistory.add(top, task);
3472                updateTaskMovement(task, true);
3473                mWindowManager.moveTaskToTop(task.taskId);
3474                return;
3475            }
3476        }
3477    }
3478
3479    final void moveTaskToFrontLocked(TaskRecord tr, ActivityRecord reason, Bundle options) {
3480        if (DEBUG_SWITCH) Slog.v(TAG, "moveTaskToFront: " + tr);
3481
3482        final int numTasks = mTaskHistory.size();
3483        final int index = mTaskHistory.indexOf(tr);
3484        if (numTasks == 0 || index < 0)  {
3485            // nothing to do!
3486            if (reason != null &&
3487                    (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
3488                ActivityOptions.abort(options);
3489            } else {
3490                updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
3491            }
3492            return;
3493        }
3494
3495        moveToFront();
3496
3497        // Shift all activities with this task up to the top
3498        // of the stack, keeping them in the same internal order.
3499        insertTaskAtTop(tr);
3500
3501        if (DEBUG_TRANSITION) Slog.v(TAG, "Prepare to front transition: task=" + tr);
3502        if (reason != null &&
3503                (reason.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
3504            mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
3505            ActivityRecord r = topRunningActivityLocked(null);
3506            if (r != null) {
3507                mNoAnimActivities.add(r);
3508            }
3509            ActivityOptions.abort(options);
3510        } else {
3511            updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
3512        }
3513
3514        mWindowManager.moveTaskToTop(tr.taskId);
3515
3516        mStackSupervisor.resumeTopActivitiesLocked();
3517        EventLog.writeEvent(EventLogTags.AM_TASK_TO_FRONT, tr.userId, tr.taskId);
3518
3519        if (VALIDATE_TOKENS) {
3520            validateAppTokensLocked();
3521        }
3522    }
3523
3524    /**
3525     * Worker method for rearranging history stack. Implements the function of moving all
3526     * activities for a specific task (gathering them if disjoint) into a single group at the
3527     * bottom of the stack.
3528     *
3529     * If a watcher is installed, the action is preflighted and the watcher has an opportunity
3530     * to premeptively cancel the move.
3531     *
3532     * @param taskId The taskId to collect and move to the bottom.
3533     * @return Returns true if the move completed, false if not.
3534     */
3535    final boolean moveTaskToBackLocked(int taskId, ActivityRecord reason) {
3536        final TaskRecord tr = taskForIdLocked(taskId);
3537        if (tr == null) {
3538            Slog.i(TAG, "moveTaskToBack: bad taskId=" + taskId);
3539            return false;
3540        }
3541
3542        Slog.i(TAG, "moveTaskToBack: " + tr);
3543
3544        mStackSupervisor.endLockTaskModeIfTaskEnding(tr);
3545
3546        // If we have a watcher, preflight the move before committing to it.  First check
3547        // for *other* available tasks, but if none are available, then try again allowing the
3548        // current task to be selected.
3549        if (mStackSupervisor.isFrontStack(this) && mService.mController != null) {
3550            ActivityRecord next = topRunningActivityLocked(null, taskId);
3551            if (next == null) {
3552                next = topRunningActivityLocked(null, 0);
3553            }
3554            if (next != null) {
3555                // ask watcher if this is allowed
3556                boolean moveOK = true;
3557                try {
3558                    moveOK = mService.mController.activityResuming(next.packageName);
3559                } catch (RemoteException e) {
3560                    mService.mController = null;
3561                    Watchdog.getInstance().setActivityController(null);
3562                }
3563                if (!moveOK) {
3564                    return false;
3565                }
3566            }
3567        }
3568
3569        if (DEBUG_TRANSITION) Slog.v(TAG,
3570                "Prepare to back transition: task=" + taskId);
3571
3572        mTaskHistory.remove(tr);
3573        mTaskHistory.add(0, tr);
3574        updateTaskMovement(tr, false);
3575
3576        // There is an assumption that moving a task to the back moves it behind the home activity.
3577        // We make sure here that some activity in the stack will launch home.
3578        int numTasks = mTaskHistory.size();
3579        for (int taskNdx = numTasks - 1; taskNdx >= 1; --taskNdx) {
3580            final TaskRecord task = mTaskHistory.get(taskNdx);
3581            if (task.isOverHomeStack()) {
3582                break;
3583            }
3584            if (taskNdx == 1) {
3585                // Set the last task before tr to go to home.
3586                task.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
3587            }
3588        }
3589
3590        if (reason != null &&
3591                (reason.intent.getFlags() & Intent.FLAG_ACTIVITY_NO_ANIMATION) != 0) {
3592            mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
3593            ActivityRecord r = topRunningActivityLocked(null);
3594            if (r != null) {
3595                mNoAnimActivities.add(r);
3596            }
3597        } else {
3598            mWindowManager.prepareAppTransition(AppTransition.TRANSIT_TASK_TO_BACK, false);
3599        }
3600        mWindowManager.moveTaskToBottom(taskId);
3601
3602        if (VALIDATE_TOKENS) {
3603            validateAppTokensLocked();
3604        }
3605
3606        final TaskRecord task = mResumedActivity != null ? mResumedActivity.task : null;
3607        if (task == tr && tr.isOverHomeStack() || numTasks <= 1 && isOnHomeDisplay()) {
3608            final int taskToReturnTo = tr.getTaskToReturnTo();
3609            tr.setTaskToReturnTo(APPLICATION_ACTIVITY_TYPE);
3610            return mStackSupervisor.resumeHomeStackTask(taskToReturnTo, null);
3611        }
3612
3613        mStackSupervisor.resumeTopActivitiesLocked();
3614        return true;
3615    }
3616
3617    static final void logStartActivity(int tag, ActivityRecord r,
3618            TaskRecord task) {
3619        final Uri data = r.intent.getData();
3620        final String strData = data != null ? data.toSafeString() : null;
3621
3622        EventLog.writeEvent(tag,
3623                r.userId, System.identityHashCode(r), task.taskId,
3624                r.shortComponentName, r.intent.getAction(),
3625                r.intent.getType(), strData, r.intent.getFlags());
3626    }
3627
3628    /**
3629     * Make sure the given activity matches the current configuration.  Returns
3630     * false if the activity had to be destroyed.  Returns true if the
3631     * configuration is the same, or the activity will remain running as-is
3632     * for whatever reason.  Ensures the HistoryRecord is updated with the
3633     * correct configuration and all other bookkeeping is handled.
3634     */
3635    final boolean ensureActivityConfigurationLocked(ActivityRecord r,
3636            int globalChanges) {
3637        if (mConfigWillChange) {
3638            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3639                    "Skipping config check (will change): " + r);
3640            return true;
3641        }
3642
3643        if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3644                "Ensuring correct configuration: " + r);
3645
3646        // Short circuit: if the two configurations are the exact same
3647        // object (the common case), then there is nothing to do.
3648        Configuration newConfig = mService.mConfiguration;
3649        if (r.configuration == newConfig && !r.forceNewConfig) {
3650            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3651                    "Configuration unchanged in " + r);
3652            return true;
3653        }
3654
3655        // We don't worry about activities that are finishing.
3656        if (r.finishing) {
3657            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3658                    "Configuration doesn't matter in finishing " + r);
3659            r.stopFreezingScreenLocked(false);
3660            return true;
3661        }
3662
3663        // Okay we now are going to make this activity have the new config.
3664        // But then we need to figure out how it needs to deal with that.
3665        Configuration oldConfig = r.configuration;
3666        r.configuration = newConfig;
3667
3668        // Determine what has changed.  May be nothing, if this is a config
3669        // that has come back from the app after going idle.  In that case
3670        // we just want to leave the official config object now in the
3671        // activity and do nothing else.
3672        final int changes = oldConfig.diff(newConfig);
3673        if (changes == 0 && !r.forceNewConfig) {
3674            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3675                    "Configuration no differences in " + r);
3676            return true;
3677        }
3678
3679        // If the activity isn't currently running, just leave the new
3680        // configuration and it will pick that up next time it starts.
3681        if (r.app == null || r.app.thread == null) {
3682            if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3683                    "Configuration doesn't matter not running " + r);
3684            r.stopFreezingScreenLocked(false);
3685            r.forceNewConfig = false;
3686            return true;
3687        }
3688
3689        // Figure out how to handle the changes between the configurations.
3690        if (DEBUG_SWITCH || DEBUG_CONFIGURATION) {
3691            Slog.v(TAG, "Checking to restart " + r.info.name + ": changed=0x"
3692                    + Integer.toHexString(changes) + ", handles=0x"
3693                    + Integer.toHexString(r.info.getRealConfigChanged())
3694                    + ", newConfig=" + newConfig);
3695        }
3696        if ((changes&(~r.info.getRealConfigChanged())) != 0 || r.forceNewConfig) {
3697            // Aha, the activity isn't handling the change, so DIE DIE DIE.
3698            r.configChangeFlags |= changes;
3699            r.startFreezingScreenLocked(r.app, globalChanges);
3700            r.forceNewConfig = false;
3701            if (r.app == null || r.app.thread == null) {
3702                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3703                        "Config is destroying non-running " + r);
3704                destroyActivityLocked(r, true, "config");
3705            } else if (r.state == ActivityState.PAUSING) {
3706                // A little annoying: we are waiting for this activity to
3707                // finish pausing.  Let's not do anything now, but just
3708                // flag that it needs to be restarted when done pausing.
3709                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3710                        "Config is skipping already pausing " + r);
3711                r.configDestroy = true;
3712                return true;
3713            } else if (r.state == ActivityState.RESUMED) {
3714                // Try to optimize this case: the configuration is changing
3715                // and we need to restart the top, resumed activity.
3716                // Instead of doing the normal handshaking, just say
3717                // "restart!".
3718                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3719                        "Config is relaunching resumed " + r);
3720                relaunchActivityLocked(r, r.configChangeFlags, true);
3721                r.configChangeFlags = 0;
3722            } else {
3723                if (DEBUG_SWITCH || DEBUG_CONFIGURATION) Slog.v(TAG,
3724                        "Config is relaunching non-resumed " + r);
3725                relaunchActivityLocked(r, r.configChangeFlags, false);
3726                r.configChangeFlags = 0;
3727            }
3728
3729            // All done...  tell the caller we weren't able to keep this
3730            // activity around.
3731            return false;
3732        }
3733
3734        // Default case: the activity can handle this new configuration, so
3735        // hand it over.  Note that we don't need to give it the new
3736        // configuration, since we always send configuration changes to all
3737        // process when they happen so it can just use whatever configuration
3738        // it last got.
3739        if (r.app != null && r.app.thread != null) {
3740            try {
3741                if (DEBUG_CONFIGURATION) Slog.v(TAG, "Sending new config to " + r);
3742                r.app.thread.scheduleActivityConfigurationChanged(r.appToken);
3743            } catch (RemoteException e) {
3744                // If process died, whatever.
3745            }
3746        }
3747        r.stopFreezingScreenLocked(false);
3748
3749        return true;
3750    }
3751
3752    private boolean relaunchActivityLocked(ActivityRecord r,
3753            int changes, boolean andResume) {
3754        List<ResultInfo> results = null;
3755        List<Intent> newIntents = null;
3756        if (andResume) {
3757            results = r.results;
3758            newIntents = r.newIntents;
3759        }
3760        if (DEBUG_SWITCH) Slog.v(TAG, "Relaunching: " + r
3761                + " with results=" + results + " newIntents=" + newIntents
3762                + " andResume=" + andResume);
3763        EventLog.writeEvent(andResume ? EventLogTags.AM_RELAUNCH_RESUME_ACTIVITY
3764                : EventLogTags.AM_RELAUNCH_ACTIVITY, r.userId, System.identityHashCode(r),
3765                r.task.taskId, r.shortComponentName);
3766
3767        r.startFreezingScreenLocked(r.app, 0);
3768
3769        mStackSupervisor.removeChildActivityContainers(r);
3770
3771        try {
3772            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG,
3773                    (andResume ? "Relaunching to RESUMED " : "Relaunching to PAUSED ")
3774                    + r);
3775            r.forceNewConfig = false;
3776            r.app.thread.scheduleRelaunchActivity(r.appToken, results, newIntents,
3777                    changes, !andResume, new Configuration(mService.mConfiguration));
3778            // Note: don't need to call pauseIfSleepingLocked() here, because
3779            // the caller will only pass in 'andResume' if this activity is
3780            // currently resumed, which implies we aren't sleeping.
3781        } catch (RemoteException e) {
3782            if (DEBUG_SWITCH || DEBUG_STATES) Slog.i(TAG, "Relaunch failed", e);
3783        }
3784
3785        if (andResume) {
3786            r.results = null;
3787            r.newIntents = null;
3788            r.state = ActivityState.RESUMED;
3789        } else {
3790            mHandler.removeMessages(PAUSE_TIMEOUT_MSG, r);
3791            r.state = ActivityState.PAUSED;
3792        }
3793
3794        return true;
3795    }
3796
3797    boolean willActivityBeVisibleLocked(IBinder token) {
3798        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3799            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3800            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3801                final ActivityRecord r = activities.get(activityNdx);
3802                if (r.appToken == token) {
3803                    return true;
3804                }
3805                if (r.fullscreen && !r.finishing) {
3806                    return false;
3807                }
3808            }
3809        }
3810        final ActivityRecord r = ActivityRecord.forToken(token);
3811        if (r == null) {
3812            return false;
3813        }
3814        if (r.finishing) Slog.e(TAG, "willActivityBeVisibleLocked: Returning false,"
3815                + " would have returned true for r=" + r);
3816        return !r.finishing;
3817    }
3818
3819    void closeSystemDialogsLocked() {
3820        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3821            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3822            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3823                final ActivityRecord r = activities.get(activityNdx);
3824                if ((r.info.flags&ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS) != 0) {
3825                    finishActivityLocked(r, Activity.RESULT_CANCELED, null, "close-sys", true);
3826                }
3827            }
3828        }
3829    }
3830
3831    boolean forceStopPackageLocked(String name, boolean doit, boolean evenPersistent, int userId) {
3832        boolean didSomething = false;
3833        TaskRecord lastTask = null;
3834        ComponentName homeActivity = null;
3835        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3836            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3837            int numActivities = activities.size();
3838            for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
3839                ActivityRecord r = activities.get(activityNdx);
3840                final boolean samePackage = r.packageName.equals(name)
3841                        || (name == null && r.userId == userId);
3842                if ((userId == UserHandle.USER_ALL || r.userId == userId)
3843                        && (samePackage || r.task == lastTask)
3844                        && (r.app == null || evenPersistent || !r.app.persistent)) {
3845                    if (!doit) {
3846                        if (r.finishing) {
3847                            // If this activity is just finishing, then it is not
3848                            // interesting as far as something to stop.
3849                            continue;
3850                        }
3851                        return true;
3852                    }
3853                    if (r.isHomeActivity()) {
3854                        if (homeActivity != null && homeActivity.equals(r.realActivity)) {
3855                            Slog.i(TAG, "Skip force-stop again " + r);
3856                            continue;
3857                        } else {
3858                            homeActivity = r.realActivity;
3859                        }
3860                    }
3861                    didSomething = true;
3862                    Slog.i(TAG, "  Force finishing activity " + r);
3863                    if (samePackage) {
3864                        if (r.app != null) {
3865                            r.app.removed = true;
3866                        }
3867                        r.app = null;
3868                    }
3869                    lastTask = r.task;
3870                    if (finishActivityLocked(r, Activity.RESULT_CANCELED, null, "force-stop",
3871                            true)) {
3872                        // r has been deleted from mActivities, accommodate.
3873                        --numActivities;
3874                        --activityNdx;
3875                    }
3876                }
3877            }
3878        }
3879        return didSomething;
3880    }
3881
3882    void getTasksLocked(List<RunningTaskInfo> list, int callingUid, boolean allowed) {
3883        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3884            final TaskRecord task = mTaskHistory.get(taskNdx);
3885            ActivityRecord r = null;
3886            ActivityRecord top = null;
3887            int numActivities = 0;
3888            int numRunning = 0;
3889            final ArrayList<ActivityRecord> activities = task.mActivities;
3890            if (activities.isEmpty()) {
3891                continue;
3892            }
3893            if (!allowed && !task.isHomeTask() && task.effectiveUid != callingUid) {
3894                continue;
3895            }
3896            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3897                r = activities.get(activityNdx);
3898
3899                // Initialize state for next task if needed.
3900                if (top == null || (top.state == ActivityState.INITIALIZING)) {
3901                    top = r;
3902                    numActivities = numRunning = 0;
3903                }
3904
3905                // Add 'r' into the current task.
3906                numActivities++;
3907                if (r.app != null && r.app.thread != null) {
3908                    numRunning++;
3909                }
3910
3911                if (localLOGV) Slog.v(
3912                    TAG, r.intent.getComponent().flattenToShortString()
3913                    + ": task=" + r.task);
3914            }
3915
3916            RunningTaskInfo ci = new RunningTaskInfo();
3917            ci.id = task.taskId;
3918            ci.baseActivity = r.intent.getComponent();
3919            ci.topActivity = top.intent.getComponent();
3920            ci.lastActiveTime = task.lastActiveTime;
3921
3922            if (top.task != null) {
3923                ci.description = top.task.lastDescription;
3924            }
3925            ci.numActivities = numActivities;
3926            ci.numRunning = numRunning;
3927            //System.out.println(
3928            //    "#" + maxNum + ": " + " descr=" + ci.description);
3929            list.add(ci);
3930        }
3931    }
3932
3933    public void unhandledBackLocked() {
3934        final int top = mTaskHistory.size() - 1;
3935        if (DEBUG_SWITCH) Slog.d(
3936            TAG, "Performing unhandledBack(): top activity at " + top);
3937        if (top >= 0) {
3938            final ArrayList<ActivityRecord> activities = mTaskHistory.get(top).mActivities;
3939            int activityTop = activities.size() - 1;
3940            if (activityTop > 0) {
3941                finishActivityLocked(activities.get(activityTop), Activity.RESULT_CANCELED, null,
3942                        "unhandled-back", true);
3943            }
3944        }
3945    }
3946
3947    /**
3948     * Reset local parameters because an app's activity died.
3949     * @param app The app of the activity that died.
3950     * @return result from removeHistoryRecordsForAppLocked.
3951     */
3952    boolean handleAppDiedLocked(ProcessRecord app) {
3953        if (mPausingActivity != null && mPausingActivity.app == app) {
3954            if (DEBUG_PAUSE || DEBUG_CLEANUP) Slog.v(TAG,
3955                    "App died while pausing: " + mPausingActivity);
3956            mPausingActivity = null;
3957        }
3958        if (mLastPausedActivity != null && mLastPausedActivity.app == app) {
3959            mLastPausedActivity = null;
3960            mLastNoHistoryActivity = null;
3961        }
3962
3963        return removeHistoryRecordsForAppLocked(app);
3964    }
3965
3966    void handleAppCrashLocked(ProcessRecord app) {
3967        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3968            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
3969            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
3970                final ActivityRecord r = activities.get(activityNdx);
3971                if (r.app == app) {
3972                    Slog.w(TAG, "  Force finishing activity "
3973                            + r.intent.getComponent().flattenToShortString());
3974                    // Force the destroy to skip right to removal.
3975                    r.app = null;
3976                    finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
3977                }
3978            }
3979        }
3980    }
3981
3982    boolean dumpActivitiesLocked(FileDescriptor fd, PrintWriter pw, boolean dumpAll,
3983            boolean dumpClient, String dumpPackage, boolean needSep, String header) {
3984        boolean printed = false;
3985        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
3986            final TaskRecord task = mTaskHistory.get(taskNdx);
3987            printed |= ActivityStackSupervisor.dumpHistoryList(fd, pw,
3988                    mTaskHistory.get(taskNdx).mActivities, "    ", "Hist", true, !dumpAll,
3989                    dumpClient, dumpPackage, needSep, header,
3990                    "    Task id #" + task.taskId);
3991            if (printed) {
3992                header = null;
3993            }
3994        }
3995        return printed;
3996    }
3997
3998    ArrayList<ActivityRecord> getDumpActivitiesLocked(String name) {
3999        ArrayList<ActivityRecord> activities = new ArrayList<ActivityRecord>();
4000
4001        if ("all".equals(name)) {
4002            for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4003                activities.addAll(mTaskHistory.get(taskNdx).mActivities);
4004            }
4005        } else if ("top".equals(name)) {
4006            final int top = mTaskHistory.size() - 1;
4007            if (top >= 0) {
4008                final ArrayList<ActivityRecord> list = mTaskHistory.get(top).mActivities;
4009                int listTop = list.size() - 1;
4010                if (listTop >= 0) {
4011                    activities.add(list.get(listTop));
4012                }
4013            }
4014        } else {
4015            ItemMatcher matcher = new ItemMatcher();
4016            matcher.build(name);
4017
4018            for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4019                for (ActivityRecord r1 : mTaskHistory.get(taskNdx).mActivities) {
4020                    if (matcher.match(r1, r1.intent.getComponent())) {
4021                        activities.add(r1);
4022                    }
4023                }
4024            }
4025        }
4026
4027        return activities;
4028    }
4029
4030    ActivityRecord restartPackage(String packageName) {
4031        ActivityRecord starting = topRunningActivityLocked(null);
4032
4033        // All activities that came from the package must be
4034        // restarted as if there was a config change.
4035        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
4036            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
4037            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
4038                final ActivityRecord a = activities.get(activityNdx);
4039                if (a.info.packageName.equals(packageName)) {
4040                    a.forceNewConfig = true;
4041                    if (starting != null && a == starting && a.visible) {
4042                        a.startFreezingScreenLocked(starting.app,
4043                                ActivityInfo.CONFIG_SCREEN_LAYOUT);
4044                    }
4045                }
4046            }
4047        }
4048
4049        return starting;
4050    }
4051
4052    void removeTask(TaskRecord task) {
4053        mStackSupervisor.endLockTaskModeIfTaskEnding(task);
4054        mWindowManager.removeTask(task.taskId);
4055        final ActivityRecord r = mResumedActivity;
4056        if (r != null && r.task == task) {
4057            mResumedActivity = null;
4058        }
4059
4060        final int taskNdx = mTaskHistory.indexOf(task);
4061        final int topTaskNdx = mTaskHistory.size() - 1;
4062        if (task.isOverHomeStack() && taskNdx < topTaskNdx) {
4063            final TaskRecord nextTask = mTaskHistory.get(taskNdx + 1);
4064            if (!nextTask.isOverHomeStack()) {
4065                nextTask.setTaskToReturnTo(HOME_ACTIVITY_TYPE);
4066            }
4067        }
4068        mTaskHistory.remove(task);
4069        updateTaskMovement(task, true);
4070
4071        if (task.mActivities.isEmpty()) {
4072            final boolean isVoiceSession = task.voiceSession != null;
4073            if (isVoiceSession) {
4074                try {
4075                    task.voiceSession.taskFinished(task.intent, task.taskId);
4076                } catch (RemoteException e) {
4077                }
4078            }
4079            if (task.autoRemoveFromRecents() || isVoiceSession) {
4080                // Task creator asked to remove this when done, or this task was a voice
4081                // interaction, so it should not remain on the recent tasks list.
4082                mService.mRecentTasks.remove(task);
4083                task.removedFromRecents(mService.mTaskPersister);
4084            }
4085        }
4086
4087        if (mTaskHistory.isEmpty()) {
4088            if (DEBUG_STACK) Slog.i(TAG, "removeTask: moving to back stack=" + this);
4089            if (isOnHomeDisplay()) {
4090                mStackSupervisor.moveHomeStack(!isHomeStack());
4091            }
4092            if (mStacks != null) {
4093                mStacks.remove(this);
4094                mStacks.add(0, this);
4095            }
4096            mActivityContainer.onTaskListEmptyLocked();
4097        }
4098    }
4099
4100    TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
4101            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
4102            boolean toTop) {
4103        TaskRecord task = new TaskRecord(mService, taskId, info, intent, voiceSession,
4104                voiceInteractor);
4105        addTask(task, toTop, false);
4106        return task;
4107    }
4108
4109    ArrayList<TaskRecord> getAllTasks() {
4110        return new ArrayList<TaskRecord>(mTaskHistory);
4111    }
4112
4113    void addTask(final TaskRecord task, final boolean toTop, boolean moving) {
4114        task.stack = this;
4115        if (toTop) {
4116            insertTaskAtTop(task);
4117        } else {
4118            mTaskHistory.add(0, task);
4119            updateTaskMovement(task, false);
4120        }
4121        if (!moving && task.voiceSession != null) {
4122            try {
4123                task.voiceSession.taskStarted(task.intent, task.taskId);
4124            } catch (RemoteException e) {
4125            }
4126        }
4127    }
4128
4129    public int getStackId() {
4130        return mStackId;
4131    }
4132
4133    @Override
4134    public String toString() {
4135        return "ActivityStack{" + Integer.toHexString(System.identityHashCode(this))
4136                + " stackId=" + mStackId + ", " + mTaskHistory.size() + " tasks}";
4137    }
4138}
4139