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