blob: 3bc1b2fd47afc76d9f6c7038677837a2a8d51d73 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.am;
18
Winson Chung74666102017-02-22 17:49:24 -080019import android.annotation.IntDef;
Jorim Jaggi0a932142016-02-01 17:42:25 -080020import android.annotation.Nullable;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -070021import android.app.Activity;
Craig Mautner9db9a0b2013-04-29 17:05:56 -070022import android.app.ActivityManager;
Wale Ogunwale3797c222015-10-27 14:21:58 -070023import android.app.ActivityManager.StackId;
Craig Mautner648f69b2014-09-18 14:16:26 -070024import android.app.ActivityManager.TaskDescription;
Jorim Jaggie2c77f92016-12-29 14:57:22 +010025import android.app.ActivityManager.TaskSnapshot;
Wale Ogunwaleff3c66c2015-11-18 19:22:49 -080026import android.app.ActivityManager.TaskThumbnail;
Winsonc809cbb2015-11-02 12:06:15 -080027import android.app.ActivityManager.TaskThumbnailInfo;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -070028import android.app.ActivityOptions;
Dianne Hackborn885fbe52014-08-23 15:23:58 -070029import android.app.AppGlobals;
Jorim Jaggi0a932142016-02-01 17:42:25 -080030import android.app.IActivityManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080031import android.content.ComponentName;
32import android.content.Intent;
33import android.content.pm.ActivityInfo;
Dianne Hackborn885fbe52014-08-23 15:23:58 -070034import android.content.pm.ApplicationInfo;
35import android.content.pm.IPackageManager;
36import android.content.pm.PackageManager;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070037import android.content.res.Configuration;
Craig Mautner9db9a0b2013-04-29 17:05:56 -070038import android.graphics.Bitmap;
Winsonc809cbb2015-11-02 12:06:15 -080039import android.graphics.Point;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -070040import android.graphics.Rect;
Wale Ogunwale0fc365c2015-05-25 19:35:42 -070041import android.os.Debug;
Craig Mautnerc0ffce52014-07-01 12:38:52 -070042import android.os.ParcelFileDescriptor;
Dianne Hackborn885fbe52014-08-23 15:23:58 -070043import android.os.RemoteException;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080044import android.os.Trace;
Dianne Hackbornf02b60a2012-08-16 10:48:27 -070045import android.os.UserHandle;
Suprabh Shukla7745c142016-03-07 18:21:10 -080046import android.provider.Settings;
Dianne Hackborn91097de2014-04-04 18:02:06 -070047import android.service.voice.IVoiceInteractionSession;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -070048import android.util.DisplayMetrics;
Dianne Hackborn7f96b792012-05-29 18:46:45 -070049import android.util.Slog;
Suprabh Shukla23593142015-11-03 17:31:15 -080050
Bryce Lee04ab3462017-04-10 15:06:33 -070051import com.android.internal.annotations.VisibleForTesting;
Dianne Hackborn91097de2014-04-04 18:02:06 -070052import com.android.internal.app.IVoiceInteractor;
Craig Mautner21d24a22014-04-23 11:45:37 -070053import com.android.internal.util.XmlUtils;
Suprabh Shukla23593142015-11-03 17:31:15 -080054
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -080055import com.android.server.wm.AppWindowContainerController;
Wale Ogunwale98d62312017-07-12 09:24:56 -070056import com.android.server.wm.ConfigurationContainer;
Winson Chungbdc646f2017-02-13 12:12:22 -080057import com.android.server.wm.StackWindowController;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080058import com.android.server.wm.TaskWindowContainerController;
Jorim Jaggifb9d78a2017-01-05 18:57:12 +010059import com.android.server.wm.TaskWindowContainerListener;
Winson Chung74666102017-02-22 17:49:24 -080060import com.android.server.wm.WindowManagerService;
Jorim Jaggifb9d78a2017-01-05 18:57:12 +010061
Craig Mautner21d24a22014-04-23 11:45:37 -070062import org.xmlpull.v1.XmlPullParser;
63import org.xmlpull.v1.XmlPullParserException;
64import org.xmlpull.v1.XmlSerializer;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080065
Craig Mautnerc0ffce52014-07-01 12:38:52 -070066import java.io.File;
Craig Mautner21d24a22014-04-23 11:45:37 -070067import java.io.IOException;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068import java.io.PrintWriter;
Winson Chung74666102017-02-22 17:49:24 -080069import java.lang.annotation.Retention;
70import java.lang.annotation.RetentionPolicy;
Craig Mautner5d9c7be2013-02-15 14:02:56 -080071import java.util.ArrayList;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -070072import java.util.Objects;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080074import static android.app.ActivityManager.RESIZE_MODE_FORCED;
Winson Chung74666102017-02-22 17:49:24 -080075import static android.app.ActivityManager.RESIZE_MODE_SYSTEM;
Winson Chung83471632016-12-13 11:02:12 -080076import static android.app.ActivityManager.StackId.ASSISTANT_STACK_ID;
Jorim Jaggi0a932142016-02-01 17:42:25 -080077import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
78import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
79import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
80import static android.app.ActivityManager.StackId.HOME_STACK_ID;
81import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
82import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
Matthew Ngae1ff4f2016-11-10 15:49:14 -080083import static android.app.ActivityManager.StackId.RECENTS_STACK_ID;
Jorim Jaggi0a932142016-02-01 17:42:25 -080084import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
85import static android.content.Intent.FLAG_ACTIVITY_RETAIN_IN_RECENTS;
Wale Ogunwale3eadad72016-10-13 09:16:59 -070086import static android.content.pm.ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
Jorim Jaggi0a932142016-02-01 17:42:25 -080087import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_ALWAYS;
88import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_DEFAULT;
89import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED;
90import static android.content.pm.ActivityInfo.LOCK_TASK_LAUNCH_MODE_NEVER;
skuhne@google.com322347b2016-12-02 12:54:03 -080091import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
92import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
93import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
Wale Ogunwaled829d362016-02-10 19:24:49 -080094import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
Wale Ogunwale625ed0c2016-10-18 08:50:31 -070095import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -080096import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED;
Wale Ogunwale625ed0c2016-10-18 08:50:31 -070097import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
Jorim Jaggi0a932142016-02-01 17:42:25 -080098import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -080099import static android.os.Trace.TRACE_TAG_ACTIVITY_MANAGER;
Bryce Leec857a5b2017-08-16 10:04:52 -0700100import static android.provider.Settings.Global.DEVELOPMENT_FORCE_RESIZABLE_ACTIVITIES;
Suprabh Shukla7745c142016-03-07 18:21:10 -0800101import static android.provider.Settings.Secure.USER_SETUP_COMPLETE;
Andrii Kulian036e3ad2017-04-19 10:55:10 -0700102import static android.view.Display.DEFAULT_DISPLAY;
103
Jorim Jaggi0a932142016-02-01 17:42:25 -0800104import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_ADD_REMOVE;
105import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_LOCKTASK;
106import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_RECENTS;
107import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_TASKS;
108import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_ADD_REMOVE;
109import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_LOCKTASK;
110import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_RECENTS;
111import static com.android.server.am.ActivityManagerDebugConfig.POSTFIX_TASKS;
112import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
113import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
Jorim Jaggi0a932142016-02-01 17:42:25 -0800114import static com.android.server.am.ActivityRecord.APPLICATION_ACTIVITY_TYPE;
Winson Chung83471632016-12-13 11:02:12 -0800115import static com.android.server.am.ActivityRecord.ASSISTANT_ACTIVITY_TYPE;
Jorim Jaggi0a932142016-02-01 17:42:25 -0800116import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
117import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
Wale Ogunwale3b232392016-05-13 15:37:13 -0700118import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN;
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800119import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
Wale Ogunwale56d8d162017-05-30 11:12:20 -0700120import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP;
Winson Chung6954fc92017-03-24 16:22:12 -0700121import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800122import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
Jorim Jaggi0a932142016-02-01 17:42:25 -0800123
Winson Chung74666102017-02-22 17:49:24 -0800124import static java.lang.Integer.MAX_VALUE;
125
Jorim Jaggifb9d78a2017-01-05 18:57:12 +0100126final class TaskRecord extends ConfigurationContainer implements TaskWindowContainerListener {
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800127 private static final String TAG = TAG_WITH_CLASS_NAME ? "TaskRecord" : TAG_AM;
Wale Ogunwale0fc365c2015-05-25 19:35:42 -0700128 private static final String TAG_ADD_REMOVE = TAG + POSTFIX_ADD_REMOVE;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700129 private static final String TAG_RECENTS = TAG + POSTFIX_RECENTS;
Craig Mautnere0570202015-05-13 13:06:11 -0700130 private static final String TAG_LOCKTASK = TAG + POSTFIX_LOCKTASK;
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700131 private static final String TAG_TASKS = TAG + POSTFIX_TASKS;
Wale Ogunwalee23149f2015-03-06 15:39:44 -0800132
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700133 private static final String ATTR_TASKID = "task_id";
Craig Mautner21d24a22014-04-23 11:45:37 -0700134 private static final String TAG_INTENT = "intent";
135 private static final String TAG_AFFINITYINTENT = "affinity_intent";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700136 private static final String ATTR_REALACTIVITY = "real_activity";
137 private static final String ATTR_REALACTIVITY_SUSPENDED = "real_activity_suspended";
Craig Mautner21d24a22014-04-23 11:45:37 -0700138 private static final String ATTR_ORIGACTIVITY = "orig_activity";
Stefan Kuhnee88d1e52015-05-18 10:33:45 -0700139 private static final String TAG_ACTIVITY = "activity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700140 private static final String ATTR_AFFINITY = "affinity";
Dianne Hackborn79228822014-09-16 11:11:23 -0700141 private static final String ATTR_ROOT_AFFINITY = "root_affinity";
Craig Mautner21d24a22014-04-23 11:45:37 -0700142 private static final String ATTR_ROOTHASRESET = "root_has_reset";
Dianne Hackborn13420f22014-07-18 15:43:56 -0700143 private static final String ATTR_AUTOREMOVERECENTS = "auto_remove_recents";
Craig Mautner21d24a22014-04-23 11:45:37 -0700144 private static final String ATTR_ASKEDCOMPATMODE = "asked_compat_mode";
145 private static final String ATTR_USERID = "user_id";
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800146 private static final String ATTR_USER_SETUP_COMPLETE = "user_setup_complete";
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700147 private static final String ATTR_EFFECTIVE_UID = "effective_uid";
Craig Mautner21d24a22014-04-23 11:45:37 -0700148 private static final String ATTR_TASKTYPE = "task_type";
Winson Chungffa2ec62014-07-03 15:54:42 -0700149 private static final String ATTR_FIRSTACTIVETIME = "first_active_time";
Winson Chungf1fbd772014-06-24 18:06:58 -0700150 private static final String ATTR_LASTACTIVETIME = "last_active_time";
Craig Mautner21d24a22014-04-23 11:45:37 -0700151 private static final String ATTR_LASTDESCRIPTION = "last_description";
152 private static final String ATTR_LASTTIMEMOVED = "last_time_moved";
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700153 private static final String ATTR_NEVERRELINQUISH = "never_relinquish_identity";
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700154 private static final String ATTR_TASK_AFFILIATION = "task_affiliation";
Craig Mautnera228ae92014-07-09 05:44:55 -0700155 private static final String ATTR_PREV_AFFILIATION = "prev_affiliation";
156 private static final String ATTR_NEXT_AFFILIATION = "next_affiliation";
Winson Chungec396d62014-08-06 17:08:00 -0700157 private static final String ATTR_TASK_AFFILIATION_COLOR = "task_affiliation_color";
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700158 private static final String ATTR_CALLING_UID = "calling_uid";
159 private static final String ATTR_CALLING_PACKAGE = "calling_package";
Winson Chungd3395382016-12-13 11:49:09 -0800160 private static final String ATTR_SUPPORTS_PICTURE_IN_PICTURE = "supports_picture_in_picture";
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800161 private static final String ATTR_RESIZE_MODE = "resize_mode";
Wale Ogunwalea7afaa22015-05-01 20:39:18 -0700162 private static final String ATTR_PRIVILEGED = "privileged";
Wale Ogunwale706ed792015-08-02 10:29:44 -0700163 private static final String ATTR_NON_FULLSCREEN_BOUNDS = "non_fullscreen_bounds";
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700164 private static final String ATTR_MIN_WIDTH = "min_width";
165 private static final String ATTR_MIN_HEIGHT = "min_height";
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700166 private static final String ATTR_PERSIST_TASK_VERSION = "persist_task_version";
Andrii Kulian18d75122016-03-27 20:20:28 -0700167
Wale Ogunwale625ed0c2016-10-18 08:50:31 -0700168 // Current version of the task record we persist. Used to check if we need to run any upgrade
169 // code.
170 private static final int PERSIST_TASK_VERSION = 1;
Craig Mautner21d24a22014-04-23 11:45:37 -0700171 private static final String TASK_THUMBNAIL_SUFFIX = "_task_thumbnail";
172
Wale Ogunwale18795a22014-12-03 11:38:33 -0800173 static final int INVALID_TASK_ID = -1;
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700174 private static final int INVALID_MIN_SIZE = -1;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800175
Winson Chung74666102017-02-22 17:49:24 -0800176 /**
177 * The modes to control how the stack is moved to the front when calling
178 * {@link TaskRecord#reparent}.
179 */
180 @Retention(RetentionPolicy.SOURCE)
181 @IntDef({
182 REPARENT_MOVE_STACK_TO_FRONT,
183 REPARENT_KEEP_STACK_AT_FRONT,
184 REPARENT_LEAVE_STACK_IN_PLACE
185 })
186 public @interface ReparentMoveStackMode {}
187 // Moves the stack to the front if it was not at the front
188 public static final int REPARENT_MOVE_STACK_TO_FRONT = 0;
189 // Only moves the stack to the front if it was focused or front most already
190 public static final int REPARENT_KEEP_STACK_AT_FRONT = 1;
191 // Do not move the stack as a part of reparenting
192 public static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
193
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800194 final int taskId; // Unique identifier for this task.
Dianne Hackborn79228822014-09-16 11:11:23 -0700195 String affinity; // The affinity name for this task, or null; may change identity.
196 String rootAffinity; // Initial base affinity, or null; does not change from initial root.
Dianne Hackborn91097de2014-04-04 18:02:06 -0700197 final IVoiceInteractionSession voiceSession; // Voice interaction session driving task
198 final IVoiceInteractor voiceInteractor; // Associated interactor to provide to app
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800199 Intent intent; // The original intent that started the task.
200 Intent affinityIntent; // Intent of affinity-moved activity that started this task.
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700201 int effectiveUid; // The current effective uid of the identity of this task.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 ComponentName origActivity; // The non-alias activity component of the intent.
203 ComponentName realActivity; // The actual activity component that started the task.
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +0000204 boolean realActivitySuspended; // True if the actual activity component that started the
205 // task is suspended.
Winson Chung36f3f032016-09-08 23:29:43 +0000206 long firstActiveTime; // First time this task was active.
207 long lastActiveTime; // Last time this task was active, including sleep.
Dianne Hackborn852975d2014-08-22 17:42:43 -0700208 boolean inRecents; // Actually in the recents list?
209 boolean isAvailable; // Is the activity available to be launched?
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 boolean rootWasReset; // True if the intent at the root of the task had
211 // the FLAG_ACTIVITY_RESET_TASK_IF_NEEDED flag.
Dianne Hackborn13420f22014-07-18 15:43:56 -0700212 boolean autoRemoveRecents; // If true, we should automatically remove the task from
213 // recents when activity finishes
Dianne Hackborn36cd41f2011-05-25 21:00:46 -0700214 boolean askedCompatMode;// Have asked the user about compat mode for this task.
Dianne Hackbornd38aed82014-06-10 21:36:35 -0700215 boolean hasBeenVisible; // Set if any activities in the task have been visible to the user.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700217 String stringName; // caching of toString() result.
Dianne Hackborn9da2d402012-03-15 13:43:08 -0700218 int userId; // user for which this task was created
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800219 boolean mUserSetupComplete; // The user set-up is complete as of the last time the task activity
220 // was changed.
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800221
222 int numFullscreen; // Number of fullscreen activities.
223
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800224 int mResizeMode; // The resize mode of this task and its activities.
225 // Based on the {@link ActivityInfo#resizeMode} of the root activity.
Wale Ogunwale069bbd32017-02-03 07:58:14 -0800226 private boolean mSupportsPictureInPicture; // Whether or not this task and its activities
227 // support PiP. Based on the {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} flag
228 // of the root activity.
Jorim Jaggi8202b2a2016-02-03 19:24:31 -0800229 boolean mTemporarilyUnresizable; // Separate flag from mResizeMode used to suppress resize
230 // changes on a temporary basis.
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700231 private int mLockTaskMode; // Which tasklock mode to launch this task in. One of
232 // ActivityManager.LOCK_TASK_LAUNCH_MODE_*
Wale Ogunwalea7afaa22015-05-01 20:39:18 -0700233 private boolean mPrivileged; // The root activity application of this task holds
234 // privileged permissions.
235
Craig Mautner15df08a2015-04-01 12:17:18 -0700236 /** Can't be put in lockTask mode. */
237 final static int LOCK_TASK_AUTH_DONT_LOCK = 0;
Benjamin Franz469dd582015-06-09 14:24:36 +0100238 /** Can enter app pinning with user approval. Can never start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700239 final static int LOCK_TASK_AUTH_PINNABLE = 1;
240 /** Starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing lockTask task. */
241 final static int LOCK_TASK_AUTH_LAUNCHABLE = 2;
Benjamin Franz469dd582015-06-09 14:24:36 +0100242 /** Can enter lockTask without user approval. Can start over existing lockTask task. */
Craig Mautner15df08a2015-04-01 12:17:18 -0700243 final static int LOCK_TASK_AUTH_WHITELISTED = 3;
Benjamin Franz469dd582015-06-09 14:24:36 +0100244 /** Priv-app that starts in LOCK_TASK_MODE_LOCKED automatically. Can start over existing
245 * lockTask task. */
246 final static int LOCK_TASK_AUTH_LAUNCHABLE_PRIV = 4;
Craig Mautner15df08a2015-04-01 12:17:18 -0700247 int mLockTaskAuth = LOCK_TASK_AUTH_PINNABLE;
248
249 int mLockTaskUid = -1; // The uid of the application that called startLockTask().
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800250
Winson Chung03a9bae2014-05-02 09:56:12 -0700251 // This represents the last resolved activity values for this task
252 // NOTE: This value needs to be persisted with each task
Craig Mautner648f69b2014-09-18 14:16:26 -0700253 TaskDescription lastTaskDescription = new TaskDescription();
Winson Chung03a9bae2014-05-02 09:56:12 -0700254
Craig Mautnerd2328952013-03-05 12:46:26 -0800255 /** List of all activities in the task arranged in history order */
Craig Mautner21d24a22014-04-23 11:45:37 -0700256 final ArrayList<ActivityRecord> mActivities;
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800257
Andrii Kulian02b7a832016-10-06 23:11:56 -0700258 /** Current stack. Setter must always be used to update the value. */
259 private ActivityStack mStack;
Craig Mautnerd2328952013-03-05 12:46:26 -0800260
Craig Mautner2c1faed2013-07-23 12:56:02 -0700261 /** Takes on same set of values as ActivityRecord.mActivityType */
Craig Mautner21d24a22014-04-23 11:45:37 -0700262 int taskType;
Craig Mautner1602ec22013-05-12 10:24:27 -0700263
Craig Mautner21d24a22014-04-23 11:45:37 -0700264 /** Takes on same value as first root activity */
265 boolean isPersistable = false;
Craig Mautnerffcfcaa2014-06-05 09:54:38 -0700266 int maxRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700267
268 /** Only used for persistable tasks, otherwise 0. The last time this task was moved. Used for
269 * determining the order when restoring. Sign indicates whether last task movement was to front
270 * (positive) or back (negative). Absolute value indicates time. */
271 long mLastTimeMoved = System.currentTimeMillis();
272
Craig Mautner84984fa2014-06-19 11:19:20 -0700273 /** Indication of what to run next when task exits. Use ActivityRecord types.
274 * ActivityRecord.APPLICATION_ACTIVITY_TYPE indicates to resume the task below this one in the
275 * task stack. */
276 private int mTaskToReturnTo = APPLICATION_ACTIVITY_TYPE;
Craig Mautnerae7ecab2013-09-18 11:48:14 -0700277
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700278 /** If original intent did not allow relinquishing task identity, save that information */
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700279 private boolean mNeverRelinquishIdentity = true;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700280
Craig Mautner362449a2014-06-20 14:04:39 -0700281 // Used in the unique case where we are clearing the task in order to reuse it. In that case we
282 // do not want to delete the stack when the task goes empty.
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -0800283 private boolean mReuseTask = false;
Craig Mautner362449a2014-06-20 14:04:39 -0700284
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700285 private Bitmap mLastThumbnail; // Last thumbnail captured for this item.
Wale Ogunwalebe23ff42014-10-21 16:29:51 -0700286 private final File mLastThumbnailFile; // File containing last thumbnail.
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700287 private final String mFilename;
Winsonc809cbb2015-11-02 12:06:15 -0800288 private TaskThumbnailInfo mLastThumbnailInfo;
Craig Mautnerc0ffce52014-07-01 12:38:52 -0700289 CharSequence lastDescription; // Last description captured for this item.
290
Craig Mautnera228ae92014-07-09 05:44:55 -0700291 int mAffiliatedTaskId; // taskId of parent affiliation or self if no parent.
Winson Chungec396d62014-08-06 17:08:00 -0700292 int mAffiliatedTaskColor; // color of the parent task affiliation.
Craig Mautnera228ae92014-07-09 05:44:55 -0700293 TaskRecord mPrevAffiliate; // previous task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800294 int mPrevAffiliateTaskId = INVALID_TASK_ID; // previous id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700295 TaskRecord mNextAffiliate; // next task in affiliated chain.
Wale Ogunwale18795a22014-12-03 11:38:33 -0800296 int mNextAffiliateTaskId = INVALID_TASK_ID; // next id for persistence.
Craig Mautnera228ae92014-07-09 05:44:55 -0700297
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700298 // For relaunching the task from recents as though it was launched by the original launcher.
299 int mCallingUid;
300 String mCallingPackage;
301
Craig Mautner21d24a22014-04-23 11:45:37 -0700302 final ActivityManagerService mService;
303
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700304 // Whether or not this task covers the entire screen; by default tasks are fullscreen.
305 boolean mFullscreen = true;
306
307 // Bounds of the Task. null for fullscreen tasks.
308 Rect mBounds = null;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -0800309 private final Rect mTmpStableBounds = new Rect();
310 private final Rect mTmpNonDecorBounds = new Rect();
Wale Ogunwale9a08f822016-02-17 19:03:58 -0800311 private final Rect mTmpRect = new Rect();
Jorim Jaggi0a932142016-02-01 17:42:25 -0800312
Wale Ogunwale706ed792015-08-02 10:29:44 -0700313 // Last non-fullscreen bounds the task was launched in or resized to.
314 // The information is persisted and used to determine the appropriate stack to launch the
315 // task into on restore.
316 Rect mLastNonFullscreenBounds = null;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700317 // Minimal width and height of this task when it's resizeable. -1 means it should use the
318 // default minimal width/height.
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700319 int mMinWidth;
320 int mMinHeight;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700321
Chong Zhangfdcc4d42015-10-14 16:50:12 -0700322 // Ranking (from top) of this task among all visible tasks. (-1 means it's not visible)
323 // This number will be assigned when we evaluate OOM scores for all visible tasks.
324 int mLayerRank = -1;
325
Andrii Kulian1779e612016-10-12 21:58:25 -0700326 /** Helper object used for updating override configuration. */
327 private Configuration mTmpConfig = new Configuration();
Wale Ogunwalee4a0c572015-06-30 08:40:31 -0700328
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800329 private TaskWindowContainerController mWindowContainerController;
330
Craig Mautner21d24a22014-04-23 11:45:37 -0700331 TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
Wale Ogunwale72919d22016-12-08 18:58:50 -0800332 IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor, int type) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700333 mService = service;
Craig Mautnera228ae92014-07-09 05:44:55 -0700334 mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
335 TaskPersister.IMAGE_EXTENSION;
Suprabh Shukla23593142015-11-03 17:31:15 -0800336 userId = UserHandle.getUserId(info.applicationInfo.uid);
337 mLastThumbnailFile = new File(TaskPersister.getUserImagesDir(userId), mFilename);
Winsonc809cbb2015-11-02 12:06:15 -0800338 mLastThumbnailInfo = new TaskThumbnailInfo();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339 taskId = _taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700340 mAffiliatedTaskId = _taskId;
Dianne Hackborn91097de2014-04-04 18:02:06 -0700341 voiceSession = _voiceSession;
342 voiceInteractor = _voiceInteractor;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700343 isAvailable = true;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800344 mActivities = new ArrayList<>();
Craig Mautner15df08a2015-04-01 12:17:18 -0700345 mCallingUid = info.applicationInfo.uid;
346 mCallingPackage = info.packageName;
Wale Ogunwale72919d22016-12-08 18:58:50 -0800347 taskType = type;
Martijn Coenend4a69702014-06-30 11:12:17 -0700348 setIntent(_intent, info);
Andrii Kulian2e751b82016-03-16 16:59:32 -0700349 setMinDimensions(info);
Winson730bf062016-03-31 18:04:56 -0700350 touchActiveTime();
Yorke Leebd54c2a2016-10-25 13:49:23 -0700351 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
Craig Mautner21d24a22014-04-23 11:45:37 -0700352 }
353
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700354 TaskRecord(ActivityManagerService service, int _taskId, ActivityInfo info, Intent _intent,
Winsonc809cbb2015-11-02 12:06:15 -0800355 TaskDescription _taskDescription, TaskThumbnailInfo thumbnailInfo) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700356 mService = service;
357 mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
358 TaskPersister.IMAGE_EXTENSION;
Suprabh Shukla23593142015-11-03 17:31:15 -0800359 userId = UserHandle.getUserId(info.applicationInfo.uid);
360 mLastThumbnailFile = new File(TaskPersister.getUserImagesDir(userId), mFilename);
Winsonc809cbb2015-11-02 12:06:15 -0800361 mLastThumbnailInfo = thumbnailInfo;
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700362 taskId = _taskId;
363 mAffiliatedTaskId = _taskId;
364 voiceSession = null;
365 voiceInteractor = null;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700366 isAvailable = true;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800367 mActivities = new ArrayList<>();
Craig Mautner15df08a2015-04-01 12:17:18 -0700368 mCallingUid = info.applicationInfo.uid;
369 mCallingPackage = info.packageName;
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700370 setIntent(_intent, info);
Andrii Kulian2e751b82016-03-16 16:59:32 -0700371 setMinDimensions(info);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700372
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700373 isPersistable = true;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700374 // Clamp to [1, max].
375 maxRecents = Math.min(Math.max(info.maxRecents, 1),
376 ActivityManager.getMaxAppRecentsLimitStatic());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700377
378 taskType = APPLICATION_ACTIVITY_TYPE;
379 mTaskToReturnTo = HOME_ACTIVITY_TYPE;
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700380 lastTaskDescription = _taskDescription;
Winson730bf062016-03-31 18:04:56 -0700381 touchActiveTime();
Yorke Leebd54c2a2016-10-25 13:49:23 -0700382 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -0700383 }
384
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800385 private TaskRecord(ActivityManagerService service, int _taskId, Intent _intent,
386 Intent _affinityIntent, String _affinity, String _rootAffinity,
387 ComponentName _realActivity, ComponentName _origActivity, boolean _rootWasReset,
388 boolean _autoRemoveRecents, boolean _askedCompatMode, int _taskType, int _userId,
389 int _effectiveUid, String _lastDescription, ArrayList<ActivityRecord> activities,
390 long _firstActiveTime, long _lastActiveTime, long lastTimeMoved,
391 boolean neverRelinquishIdentity, TaskDescription _lastTaskDescription,
Winsonc809cbb2015-11-02 12:06:15 -0800392 TaskThumbnailInfo lastThumbnailInfo, int taskAffiliation, int prevTaskId,
393 int nextTaskId, int taskAffiliationColor, int callingUid, String callingPackage,
Winson Chungd3395382016-12-13 11:49:09 -0800394 int resizeMode, boolean supportsPictureInPicture, boolean privileged,
395 boolean _realActivitySuspended, boolean userSetupComplete, int minWidth,
396 int minHeight) {
Craig Mautner21d24a22014-04-23 11:45:37 -0700397 mService = service;
Craig Mautnera228ae92014-07-09 05:44:55 -0700398 mFilename = String.valueOf(_taskId) + TASK_THUMBNAIL_SUFFIX +
399 TaskPersister.IMAGE_EXTENSION;
Suprabh Shukla23593142015-11-03 17:31:15 -0800400 mLastThumbnailFile = new File(TaskPersister.getUserImagesDir(_userId), mFilename);
Winsonc809cbb2015-11-02 12:06:15 -0800401 mLastThumbnailInfo = lastThumbnailInfo;
Craig Mautner21d24a22014-04-23 11:45:37 -0700402 taskId = _taskId;
403 intent = _intent;
404 affinityIntent = _affinityIntent;
405 affinity = _affinity;
Wale Ogunwale9d3de4c2015-02-01 16:49:44 -0800406 rootAffinity = _rootAffinity;
Craig Mautner21d24a22014-04-23 11:45:37 -0700407 voiceSession = null;
408 voiceInteractor = null;
409 realActivity = _realActivity;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800410 realActivitySuspended = _realActivitySuspended;
Craig Mautner21d24a22014-04-23 11:45:37 -0700411 origActivity = _origActivity;
412 rootWasReset = _rootWasReset;
Dianne Hackborn852975d2014-08-22 17:42:43 -0700413 isAvailable = true;
Dianne Hackborn13420f22014-07-18 15:43:56 -0700414 autoRemoveRecents = _autoRemoveRecents;
Craig Mautner21d24a22014-04-23 11:45:37 -0700415 askedCompatMode = _askedCompatMode;
416 taskType = _taskType;
Craig Mautner84984fa2014-06-19 11:19:20 -0700417 mTaskToReturnTo = HOME_ACTIVITY_TYPE;
Craig Mautner21d24a22014-04-23 11:45:37 -0700418 userId = _userId;
Wale Ogunwalef80170f2016-02-04 15:12:29 -0800419 mUserSetupComplete = userSetupComplete;
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700420 effectiveUid = _effectiveUid;
Winson Chungffa2ec62014-07-03 15:54:42 -0700421 firstActiveTime = _firstActiveTime;
Winson Chungf1fbd772014-06-24 18:06:58 -0700422 lastActiveTime = _lastActiveTime;
Craig Mautner21d24a22014-04-23 11:45:37 -0700423 lastDescription = _lastDescription;
424 mActivities = activities;
425 mLastTimeMoved = lastTimeMoved;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700426 mNeverRelinquishIdentity = neverRelinquishIdentity;
Winson Chung2cb86c72014-06-25 12:03:30 -0700427 lastTaskDescription = _lastTaskDescription;
Craig Mautnera228ae92014-07-09 05:44:55 -0700428 mAffiliatedTaskId = taskAffiliation;
Winson Chungec396d62014-08-06 17:08:00 -0700429 mAffiliatedTaskColor = taskAffiliationColor;
Craig Mautnera228ae92014-07-09 05:44:55 -0700430 mPrevAffiliateTaskId = prevTaskId;
431 mNextAffiliateTaskId = nextTaskId;
Craig Mautnerdc00cbe2014-07-20 17:48:47 -0700432 mCallingUid = callingUid;
433 mCallingPackage = callingPackage;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800434 mResizeMode = resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800435 mSupportsPictureInPicture = supportsPictureInPicture;
Wale Ogunwalea7afaa22015-05-01 20:39:18 -0700436 mPrivileged = privileged;
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700437 mMinWidth = minWidth;
438 mMinHeight = minHeight;
Yorke Leebd54c2a2016-10-25 13:49:23 -0700439 mService.mTaskChangeNotificationController.notifyTaskCreated(_taskId, realActivity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 }
441
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800442 TaskWindowContainerController getWindowContainerController() {
443 return mWindowContainerController;
444 }
445
446 void createWindowContainer(boolean onTop, boolean showForAllUsers) {
447 if (mWindowContainerController != null) {
448 throw new IllegalArgumentException("Window container=" + mWindowContainerController
449 + " already created for task=" + this);
450 }
451
452 final Rect bounds = updateOverrideConfigurationFromLaunchBounds();
453 final Configuration overrideConfig = getOverrideConfiguration();
Bryce Lee04ab3462017-04-10 15:06:33 -0700454 setWindowContainerController(new TaskWindowContainerController(taskId, this,
Wale Ogunwale1666e312016-12-16 11:27:18 -0800455 getStack().getWindowContainerController(), userId, bounds, overrideConfig,
Wale Ogunwale069bbd32017-02-03 07:58:14 -0800456 mResizeMode, mSupportsPictureInPicture, isHomeTask(), onTop, showForAllUsers,
Bryce Lee04ab3462017-04-10 15:06:33 -0700457 lastTaskDescription));
458 }
459
460 /**
461 * Should only be invoked from {@link #createWindowContainer(boolean, boolean)}.
462 */
463 @VisibleForTesting
464 protected void setWindowContainerController(TaskWindowContainerController controller) {
465 if (mWindowContainerController != null) {
466 throw new IllegalArgumentException("Window container=" + mWindowContainerController
467 + " already created for task=" + this);
468 }
469
470 mWindowContainerController = controller;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800471 }
472
473 void removeWindowContainer() {
474 mService.mStackSupervisor.removeLockedTaskLocked(this);
475 mWindowContainerController.removeContainer();
476 if (!StackId.persistTaskBounds(getStackId())) {
477 // Reset current bounds for task whose bounds shouldn't be persisted so it uses
478 // default configuration the next time it launches.
479 updateOverrideConfiguration(null);
480 }
481 mService.mTaskChangeNotificationController.notifyTaskRemoved(taskId);
482 mWindowContainerController = null;
483 }
484
Jorim Jaggifb9d78a2017-01-05 18:57:12 +0100485 @Override
486 public void onSnapshotChanged(TaskSnapshot snapshot) {
487 mService.mTaskChangeNotificationController.notifyTaskSnapshotChanged(taskId, snapshot);
488 }
489
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800490 void setResizeMode(int resizeMode) {
491 if (mResizeMode == resizeMode) {
492 return;
493 }
494 mResizeMode = resizeMode;
495 mWindowContainerController.setResizeable(resizeMode);
496 mService.mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
497 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
498 }
499
500 void setTaskDockedResizing(boolean resizing) {
501 mWindowContainerController.setTaskDockedResizing(resizing);
502 }
503
Wale Ogunwale1666e312016-12-16 11:27:18 -0800504 // TODO: Consolidate this with the resize() method below.
505 @Override
506 public void requestResize(Rect bounds, int resizeMode) {
507 mService.resizeTask(taskId, bounds, resizeMode);
508 }
509
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800510 boolean resize(Rect bounds, int resizeMode, boolean preserveWindow, boolean deferResume) {
511 if (!isResizeable()) {
512 Slog.w(TAG, "resizeTask: task " + this + " not resizeable.");
513 return true;
514 }
515
516 // If this is a forced resize, let it go through even if the bounds is not changing,
517 // as we might need a relayout due to surface size change (to/from fullscreen).
518 final boolean forced = (resizeMode & RESIZE_MODE_FORCED) != 0;
519 if (Objects.equals(mBounds, bounds) && !forced) {
520 // Nothing to do here...
521 return true;
522 }
523 bounds = validateBounds(bounds);
524
525 if (mWindowContainerController == null) {
526 // Task doesn't exist in window manager yet (e.g. was restored from recents).
527 // All we can do for now is update the bounds so it can be used when the task is
528 // added to window manager.
529 updateOverrideConfiguration(bounds);
530 if (getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
531 // re-restore the task so it can have the proper stack association.
532 mService.mStackSupervisor.restoreRecentTaskLocked(this,
533 FREEFORM_WORKSPACE_STACK_ID);
534 }
535 return true;
536 }
537
538 if (!canResizeToBounds(bounds)) {
539 throw new IllegalArgumentException("resizeTask: Can not resize task=" + this
540 + " to bounds=" + bounds + " resizeMode=" + mResizeMode);
541 }
542
543 // Do not move the task to another stack here.
544 // This method assumes that the task is already placed in the right stack.
545 // we do not mess with that decision and we only do the resize!
546
547 Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "am.resizeTask_" + taskId);
548
549 final boolean updatedConfig = updateOverrideConfiguration(bounds);
550 // This variable holds information whether the configuration didn't change in a significant
551 // way and the activity was kept the way it was. If it's false, it means the activity had
552 // to be relaunched due to configuration change.
553 boolean kept = true;
554 if (updatedConfig) {
555 final ActivityRecord r = topRunningActivityLocked();
Wale Ogunwaleea3d3fd2017-05-01 07:41:08 -0700556 if (r != null && !deferResume) {
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800557 kept = r.ensureActivityConfigurationLocked(0 /* globalChanges */, preserveWindow);
Wale Ogunwaleea3d3fd2017-05-01 07:41:08 -0700558 mService.mStackSupervisor.ensureActivitiesVisibleLocked(r, 0, !PRESERVE_WINDOWS);
559 if (!kept) {
560 mService.mStackSupervisor.resumeFocusedStackTopActivityLocked();
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800561 }
562 }
563 }
564 mWindowContainerController.resize(mBounds, getOverrideConfiguration(), kept, forced);
565
566 Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
567 return kept;
568 }
569
570 // TODO: Investigate combining with the resize() method above.
571 void resizeWindowContainer() {
572 mWindowContainerController.resize(mBounds, getOverrideConfiguration(), false /* relayout */,
573 false /* forced */);
574 }
575
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800576 void getWindowContainerBounds(Rect bounds) {
577 mWindowContainerController.getBounds(bounds);
578 }
579
Winson Chung74666102017-02-22 17:49:24 -0800580 /**
581 * Convenience method to reparent a task to the top or bottom position of the stack.
582 */
583 boolean reparent(int preferredStackId, boolean toTop, @ReparentMoveStackMode int moveStackMode,
584 boolean animate, boolean deferResume, String reason) {
585 return reparent(preferredStackId, toTop ? MAX_VALUE : 0, moveStackMode, animate,
Winson Chung5af42fc2017-03-24 17:11:33 -0700586 deferResume, true /* schedulePictureInPictureModeChange */, reason);
587 }
588
589 /**
590 * Convenience method to reparent a task to the top or bottom position of the stack, with
591 * an option to skip scheduling the picture-in-picture mode change.
592 */
593 boolean reparent(int preferredStackId, boolean toTop, @ReparentMoveStackMode int moveStackMode,
594 boolean animate, boolean deferResume, boolean schedulePictureInPictureModeChange,
595 String reason) {
596 return reparent(preferredStackId, toTop ? MAX_VALUE : 0, moveStackMode, animate,
597 deferResume, schedulePictureInPictureModeChange, reason);
598 }
599
600 /**
601 * Convenience method to reparent a task to a specific position of the stack.
602 */
603 boolean reparent(int preferredStackId, int position, @ReparentMoveStackMode int moveStackMode,
604 boolean animate, boolean deferResume, String reason) {
605 return reparent(preferredStackId, position, moveStackMode, animate, deferResume,
606 true /* schedulePictureInPictureModeChange */, reason);
Winson Chung74666102017-02-22 17:49:24 -0800607 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800608
Winson Chung74666102017-02-22 17:49:24 -0800609 /**
610 * Reparents the task into a preferred stack, creating it if necessary.
611 *
612 * @param preferredStackId the stack id of the target stack to move this task
613 * @param position the position to place this task in the new stack
614 * @param animate whether or not we should wait for the new window created as a part of the
Winson Chung5af42fc2017-03-24 17:11:33 -0700615 * reparenting to be drawn and animated in
Winson Chung74666102017-02-22 17:49:24 -0800616 * @param moveStackMode whether or not to move the stack to the front always, only if it was
Winson Chung5af42fc2017-03-24 17:11:33 -0700617 * previously focused & in front, or never
Winson Chung74666102017-02-22 17:49:24 -0800618 * @param deferResume whether or not to update the visibility of other tasks and stacks that may
Winson Chung5af42fc2017-03-24 17:11:33 -0700619 * have changed as a result of this reparenting
620 * @param schedulePictureInPictureModeChange specifies whether or not to schedule the PiP mode
621 * change. Callers may set this to false if they are explicitly scheduling PiP mode
622 * changes themselves, like during the PiP animation
Winson Chung74666102017-02-22 17:49:24 -0800623 * @param reason the caller of this reparenting
Winson Chung5af42fc2017-03-24 17:11:33 -0700624 * @return whether the task was reparented
Winson Chung74666102017-02-22 17:49:24 -0800625 */
626 boolean reparent(int preferredStackId, int position, @ReparentMoveStackMode int moveStackMode,
Winson Chung5af42fc2017-03-24 17:11:33 -0700627 boolean animate, boolean deferResume, boolean schedulePictureInPictureModeChange,
628 String reason) {
Winson Chung74666102017-02-22 17:49:24 -0800629 final ActivityStackSupervisor supervisor = mService.mStackSupervisor;
630 final WindowManagerService windowManager = mService.mWindowManager;
631 final ActivityStack sourceStack = getStack();
632 final ActivityStack toStack = supervisor.getReparentTargetStack(this, preferredStackId,
633 position == MAX_VALUE);
634 if (toStack == sourceStack) {
635 return false;
636 }
637
638 final int sourceStackId = getStackId();
639 final int stackId = toStack.getStackId();
640 final ActivityRecord topActivity = getTopActivity();
641
642 final boolean mightReplaceWindow = StackId.replaceWindowsOnTaskMove(sourceStackId, stackId)
643 && topActivity != null;
644 if (mightReplaceWindow) {
645 // We are about to relaunch the activity because its configuration changed due to
646 // being maximized, i.e. size change. The activity will first remove the old window
647 // and then add a new one. This call will tell window manager about this, so it can
648 // preserve the old window until the new one is drawn. This prevents having a gap
649 // between the removal and addition, in which no window is visible. We also want the
650 // entrance of the new window to be properly animated.
651 // Note here we always set the replacing window first, as the flags might be needed
652 // during the relaunch. If we end up not doing any relaunch, we clear the flags later.
653 windowManager.setWillReplaceWindow(topActivity.appToken, animate);
654 }
655
656 windowManager.deferSurfaceLayout();
657 boolean kept = true;
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800658 try {
Winson Chung74666102017-02-22 17:49:24 -0800659 final ActivityRecord r = topRunningActivityLocked();
Winson Chung95f8f0e2017-03-24 09:20:17 -0700660 final boolean wasFocused = r != null && supervisor.isFocusedStack(sourceStack)
Winson Chung74666102017-02-22 17:49:24 -0800661 && (topRunningActivityLocked() == r);
Winson Chung95f8f0e2017-03-24 09:20:17 -0700662 final boolean wasResumed = r != null && sourceStack.mResumedActivity == r;
663 final boolean wasPaused = r != null && sourceStack.mPausingActivity == r;
Winson Chung74666102017-02-22 17:49:24 -0800664
665 // In some cases the focused stack isn't the front stack. E.g. pinned stack.
666 // Whenever we are moving the top activity from the front stack we want to make sure to
667 // move the stack to the front.
Winson Chung95f8f0e2017-03-24 09:20:17 -0700668 final boolean wasFront = r != null && supervisor.isFrontStackOnDisplay(sourceStack)
Winson Chung74666102017-02-22 17:49:24 -0800669 && (sourceStack.topRunningActivityLocked() == r);
670
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800671 // Adjust the position for the new parent stack as needed.
Winson Chung74666102017-02-22 17:49:24 -0800672 position = toStack.getAdjustedPositionForTask(this, position, null /* starting */);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800673
674 // Must reparent first in window manager to avoid a situation where AM can delete the
675 // we are coming from in WM before we reparent because it became empty.
Wale Ogunwale2719cc12017-04-14 09:45:27 -0700676 mWindowContainerController.reparent(toStack.getWindowContainerController(), position,
677 moveStackMode == REPARENT_MOVE_STACK_TO_FRONT);
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800678
Wale Ogunwale56d8d162017-05-30 11:12:20 -0700679 final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
680 || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
Winson Chung74666102017-02-22 17:49:24 -0800681 // Move the task
Wale Ogunwale56d8d162017-05-30 11:12:20 -0700682 sourceStack.removeTask(this, reason, moveStackToFront
683 ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
Winson Chung5af42fc2017-03-24 17:11:33 -0700684 toStack.addTask(this, position, false /* schedulePictureInPictureModeChange */, reason);
Winson Chung74666102017-02-22 17:49:24 -0800685
Winson Chung5af42fc2017-03-24 17:11:33 -0700686 if (schedulePictureInPictureModeChange) {
687 // Notify of picture-in-picture mode changes
688 supervisor.scheduleUpdatePictureInPictureModeIfNeeded(this, sourceStack);
689 }
Winson Chung74666102017-02-22 17:49:24 -0800690
691 // TODO: Ensure that this is actually necessary here
692 // Notify the voice session if required
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800693 if (voiceSession != null) {
694 try {
695 voiceSession.taskStarted(intent, taskId);
696 } catch (RemoteException e) {
697 }
698 }
Winson Chung74666102017-02-22 17:49:24 -0800699
700 // If the task had focus before (or we're requested to move focus), move focus to the
701 // new stack by moving the stack to the front.
Winson Chung95f8f0e2017-03-24 09:20:17 -0700702 if (r != null) {
703 toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed,
704 wasPaused, reason);
705 }
Winson Chung74666102017-02-22 17:49:24 -0800706 if (!animate) {
707 toStack.mNoAnimActivities.add(topActivity);
708 }
709
710 // We might trigger a configuration change. Save the current task bounds for freezing.
711 // TODO: Should this call be moved inside the resize method in WM?
712 toStack.prepareFreezingTaskBounds();
713
714 // Make sure the task has the appropriate bounds/size for the stack it is in.
715 if (stackId == FULLSCREEN_WORKSPACE_STACK_ID
716 && !Objects.equals(mBounds, toStack.mBounds)) {
717 kept = resize(toStack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
718 deferResume);
719 } else if (stackId == FREEFORM_WORKSPACE_STACK_ID) {
720 Rect bounds = getLaunchBounds();
721 if (bounds == null) {
722 toStack.layoutTaskInStack(this, null);
723 bounds = mBounds;
724 }
725 kept = resize(bounds, RESIZE_MODE_FORCED, !mightReplaceWindow, deferResume);
726 } else if (stackId == DOCKED_STACK_ID || stackId == PINNED_STACK_ID) {
Matthew Ng330757d2017-02-28 14:19:17 -0800727 if (stackId == DOCKED_STACK_ID && moveStackMode == REPARENT_KEEP_STACK_AT_FRONT) {
728 // Move recents to front so it is not behind home stack when going into docked
729 // mode
730 mService.mStackSupervisor.moveRecentsStackToFront(reason);
731 }
Winson Chung74666102017-02-22 17:49:24 -0800732 kept = resize(toStack.mBounds, RESIZE_MODE_SYSTEM, !mightReplaceWindow,
733 deferResume);
734 }
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800735 } finally {
Winson Chung74666102017-02-22 17:49:24 -0800736 windowManager.continueSurfaceLayout();
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800737 }
Winson Chung74666102017-02-22 17:49:24 -0800738
739 if (mightReplaceWindow) {
740 // If we didn't actual do a relaunch (indicated by kept==true meaning we kept the old
741 // window), we need to clear the replace window settings. Otherwise, we schedule a
742 // timeout to remove the old window if the replacing window is not coming in time.
743 windowManager.scheduleClearWillReplaceWindows(topActivity.appToken, !kept);
744 }
745
746 if (!deferResume) {
747 // The task might have already been running and its visibility needs to be synchronized
748 // with the visibility of the stack / windows.
749 supervisor.ensureActivitiesVisibleLocked(null, 0, !mightReplaceWindow);
750 supervisor.resumeFocusedStackTopActivityLocked();
751 }
752
Andrii Kulian036e3ad2017-04-19 10:55:10 -0700753 // TODO: Handle incorrect request to move before the actual move, not after.
754 supervisor.handleNonResizableTaskIfNeeded(this, preferredStackId, DEFAULT_DISPLAY, stackId);
Winson Chung74666102017-02-22 17:49:24 -0800755
Matthew Ng330757d2017-02-28 14:19:17 -0800756 boolean successful = (preferredStackId == stackId);
757 if (successful && stackId == DOCKED_STACK_ID) {
758 // If task moved to docked stack - show recents if needed.
759 mService.mWindowManager.showRecentApps(false /* fromHome */);
760 }
761 return successful;
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800762 }
763
764 void cancelWindowTransition() {
765 mWindowContainerController.cancelWindowTransition();
766 }
767
768 void cancelThumbnailTransition() {
769 mWindowContainerController.cancelThumbnailTransition();
770 }
771
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100772 /**
773 * DO NOT HOLD THE ACTIVITY MANAGER LOCK WHEN CALLING THIS METHOD!
774 */
Jorim Jaggi35e3f532017-03-17 17:06:50 +0100775 TaskSnapshot getSnapshot(boolean reducedResolution) {
Jorim Jaggi7361bab2017-01-16 17:17:58 +0100776
777 // TODO: Move this to {@link TaskWindowContainerController} once recent tasks are more
778 // synchronized between AM and WM.
Jorim Jaggi35e3f532017-03-17 17:06:50 +0100779 return mService.mWindowManager.getTaskSnapshot(taskId, userId, reducedResolution);
Jorim Jaggi02886a82016-12-06 09:10:06 -0800780 }
781
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782 void touchActiveTime() {
Winson Chung36f3f032016-09-08 23:29:43 +0000783 lastActiveTime = System.currentTimeMillis();
Winson Chungffa2ec62014-07-03 15:54:42 -0700784 if (firstActiveTime == 0) {
785 firstActiveTime = lastActiveTime;
786 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800787 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700788
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800789 long getInactiveDuration() {
Winson Chung36f3f032016-09-08 23:29:43 +0000790 return System.currentTimeMillis() - lastActiveTime;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -0700792
Winson Chungfee26772014-08-05 12:21:52 -0700793 /** Sets the original intent, and the calling uid and package. */
794 void setIntent(ActivityRecord r) {
Winson Chungfee26772014-08-05 12:21:52 -0700795 mCallingUid = r.launchedFromUid;
796 mCallingPackage = r.launchedFromPackage;
Craig Mautner15df08a2015-04-01 12:17:18 -0700797 setIntent(r.intent, r.info);
Winson Chungfee26772014-08-05 12:21:52 -0700798 }
799
800 /** Sets the original intent, _without_ updating the calling uid or package. */
801 private void setIntent(Intent _intent, ActivityInfo info) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700802 if (intent == null) {
803 mNeverRelinquishIdentity =
Wale Ogunwale3eadad72016-10-13 09:16:59 -0700804 (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -0700805 } else if (mNeverRelinquishIdentity) {
806 return;
807 }
808
809 affinity = info.taskAffinity;
Dianne Hackborn79228822014-09-16 11:11:23 -0700810 if (intent == null) {
811 // If this task already has an intent associated with it, don't set the root
812 // affinity -- we don't want it changing after initially set, but the initially
813 // set value may be null.
814 rootAffinity = affinity;
815 }
Dianne Hackborn885fbe52014-08-23 15:23:58 -0700816 effectiveUid = info.applicationInfo.uid;
Dianne Hackborn1d442e02009-04-20 18:14:05 -0700817 stringName = null;
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800818
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800819 if (info.targetActivity == null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800820 if (_intent != null) {
821 // If this Intent has a selector, we want to clear it for the
822 // recent task since it is not relevant if the user later wants
823 // to re-launch the app.
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700824 if (_intent.getSelector() != null || _intent.getSourceBounds() != null) {
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800825 _intent = new Intent(_intent);
826 _intent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700827 _intent.setSourceBounds(null);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800828 }
829 }
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700830 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Setting Intent of " + this + " to " + _intent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800831 intent = _intent;
832 realActivity = _intent != null ? _intent.getComponent() : null;
833 origActivity = null;
834 } else {
835 ComponentName targetComponent = new ComponentName(
836 info.packageName, info.targetActivity);
837 if (_intent != null) {
838 Intent targetIntent = new Intent(_intent);
839 targetIntent.setComponent(targetComponent);
Dianne Hackbornf5b86712011-12-05 17:42:41 -0800840 targetIntent.setSelector(null);
Dianne Hackbornd367ca82012-05-07 15:49:39 -0700841 targetIntent.setSourceBounds(null);
Wale Ogunwaleee006da2015-03-30 14:49:25 -0700842 if (DEBUG_TASKS) Slog.v(TAG_TASKS,
Dianne Hackborn7f96b792012-05-29 18:46:45 -0700843 "Setting Intent of " + this + " to target " + targetIntent);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800844 intent = targetIntent;
845 realActivity = targetComponent;
846 origActivity = _intent.getComponent();
847 } else {
848 intent = null;
849 realActivity = targetComponent;
850 origActivity = new ComponentName(info.packageName, info.name);
851 }
852 }
Amith Yamasani742a6712011-05-04 14:49:28 -0700853
Craig Mautner47b20ba2014-09-17 17:23:44 -0700854 final int intentFlags = intent == null ? 0 : intent.getFlags();
855 if ((intentFlags & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800856 // Once we are set to an Intent with this flag, we count this
857 // task as having a true root activity.
858 rootWasReset = true;
859 }
Dianne Hackborn09233282014-04-30 11:33:59 -0700860 userId = UserHandle.getUserId(info.applicationInfo.uid);
Winson Chung36f3f032016-09-08 23:29:43 +0000861 mUserSetupComplete = Settings.Secure.getIntForUser(mService.mContext.getContentResolver(),
862 USER_SETUP_COMPLETE, 0, userId) != 0;
Craig Mautner41db4a72014-05-07 17:20:56 -0700863 if ((info.flags & ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS) != 0) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700864 // If the activity itself has requested auto-remove, then just always do it.
865 autoRemoveRecents = true;
Wale Ogunwale843bfb92015-03-27 11:06:48 -0700866 } else if ((intentFlags & (FLAG_ACTIVITY_NEW_DOCUMENT | FLAG_ACTIVITY_RETAIN_IN_RECENTS))
867 == FLAG_ACTIVITY_NEW_DOCUMENT) {
Dianne Hackborn13420f22014-07-18 15:43:56 -0700868 // If the caller has not asked for the document to be retained, then we may
869 // want to turn on auto-remove, depending on whether the target has set its
870 // own document launch mode.
871 if (info.documentLaunchMode != ActivityInfo.DOCUMENT_LAUNCH_NONE) {
872 autoRemoveRecents = false;
873 } else {
874 autoRemoveRecents = true;
875 }
876 } else {
877 autoRemoveRecents = false;
Craig Mautner41db4a72014-05-07 17:20:56 -0700878 }
Wale Ogunwaleb1faf602016-01-27 09:12:31 -0800879 mResizeMode = info.resizeMode;
Winson Chungd3395382016-12-13 11:49:09 -0800880 mSupportsPictureInPicture = info.supportsPictureInPicture();
Craig Mautner15df08a2015-04-01 12:17:18 -0700881 mLockTaskMode = info.lockTaskLaunchMode;
Wale Ogunwalea7afaa22015-05-01 20:39:18 -0700882 mPrivileged = (info.applicationInfo.privateFlags & PRIVATE_FLAG_PRIVILEGED) != 0;
Craig Mautner15df08a2015-04-01 12:17:18 -0700883 setLockTaskAuth();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800884 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -0800885
Andrii Kulian2e751b82016-03-16 16:59:32 -0700886 /** Sets the original minimal width and height. */
887 private void setMinDimensions(ActivityInfo info) {
888 if (info != null && info.windowLayout != null) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700889 mMinWidth = info.windowLayout.minWidth;
890 mMinHeight = info.windowLayout.minHeight;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700891 } else {
Andrii Kulianf66a83d2016-05-17 12:17:44 -0700892 mMinWidth = INVALID_MIN_SIZE;
893 mMinHeight = INVALID_MIN_SIZE;
Andrii Kulian2e751b82016-03-16 16:59:32 -0700894 }
895 }
896
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800897 /**
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700898 * Return true if the input activity has the same intent filter as the intent this task
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800899 * record is based on (normally the root activity intent).
900 */
Andrii Kulian206b9fa2016-06-02 13:18:01 -0700901 boolean isSameIntentFilter(ActivityRecord r) {
Wale Ogunwale715a1dc2016-02-29 14:27:32 -0800902 final Intent intent = new Intent(r.intent);
903 // Correct the activity intent for aliasing. The task record intent will always be based on
904 // the real activity that will be launched not the alias, so we need to use an intent with
905 // the component name pointing to the real activity not the alias in the activity record.
906 intent.setComponent(r.realActivity);
907 return this.intent.filterEquals(intent);
908 }
909
Craig Mautner84984fa2014-06-19 11:19:20 -0700910 void setTaskToReturnTo(int taskToReturnTo) {
Wale Ogunwale673cbd22016-01-30 18:30:55 -0800911 mTaskToReturnTo = (taskToReturnTo == RECENTS_ACTIVITY_TYPE)
912 ? HOME_ACTIVITY_TYPE : taskToReturnTo;
Craig Mautner84984fa2014-06-19 11:19:20 -0700913 }
914
Winson Chung83471632016-12-13 11:02:12 -0800915 void setTaskToReturnTo(ActivityRecord source) {
916 if (source.isRecentsActivity()) {
917 setTaskToReturnTo(RECENTS_ACTIVITY_TYPE);
918 } else if (source.isAssistantActivity()) {
919 setTaskToReturnTo(ASSISTANT_ACTIVITY_TYPE);
920 }
921 }
922
Craig Mautner84984fa2014-06-19 11:19:20 -0700923 int getTaskToReturnTo() {
924 return mTaskToReturnTo;
925 }
926
Craig Mautnera228ae92014-07-09 05:44:55 -0700927 void setPrevAffiliate(TaskRecord prevAffiliate) {
928 mPrevAffiliate = prevAffiliate;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800929 mPrevAffiliateTaskId = prevAffiliate == null ? INVALID_TASK_ID : prevAffiliate.taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700930 }
931
932 void setNextAffiliate(TaskRecord nextAffiliate) {
933 mNextAffiliate = nextAffiliate;
Wale Ogunwale18795a22014-12-03 11:38:33 -0800934 mNextAffiliateTaskId = nextAffiliate == null ? INVALID_TASK_ID : nextAffiliate.taskId;
Craig Mautnera228ae92014-07-09 05:44:55 -0700935 }
936
Andrii Kulian02b7a832016-10-06 23:11:56 -0700937 ActivityStack getStack() {
938 return mStack;
939 }
940
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800941 /**
942 * Must be used for setting parent stack because it performs configuration updates.
943 * Must be called after adding task as a child to the stack.
944 */
Andrii Kulian02b7a832016-10-06 23:11:56 -0700945 void setStack(ActivityStack stack) {
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800946 if (stack != null && !stack.isInStackLocked(this)) {
947 throw new IllegalStateException("Task must be added as a Stack child first.");
948 }
Andrii Kulian02b7a832016-10-06 23:11:56 -0700949 mStack = stack;
Andrii Kulian1779e612016-10-12 21:58:25 -0700950 onParentChanged();
Andrii Kulian02b7a832016-10-06 23:11:56 -0700951 }
952
953 /**
954 * @return Id of current stack, {@link INVALID_STACK_ID} if no stack is set.
955 */
956 int getStackId() {
957 return mStack != null ? mStack.mStackId : INVALID_STACK_ID;
958 }
959
Andrii Kulian1779e612016-10-12 21:58:25 -0700960 @Override
961 protected int getChildCount() {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700962 return mActivities.size();
Andrii Kulian1779e612016-10-12 21:58:25 -0700963 }
964
965 @Override
966 protected ConfigurationContainer getChildAt(int index) {
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700967 return mActivities.get(index);
Andrii Kulian1779e612016-10-12 21:58:25 -0700968 }
969
970 @Override
971 protected ConfigurationContainer getParent() {
972 return mStack;
973 }
974
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800975 @Override
Wale Ogunwale98d62312017-07-12 09:24:56 -0700976 protected void onParentChanged() {
Andrii Kulianfb1bf692017-01-17 11:17:34 -0800977 super.onParentChanged();
978 mService.mStackSupervisor.updateUIDsPresentOnDisplay();
979 }
980
Craig Mautnera228ae92014-07-09 05:44:55 -0700981 // Close up recents linked list.
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700982 private void closeRecentsChain() {
Craig Mautnera228ae92014-07-09 05:44:55 -0700983 if (mPrevAffiliate != null) {
984 mPrevAffiliate.setNextAffiliate(mNextAffiliate);
985 }
986 if (mNextAffiliate != null) {
987 mNextAffiliate.setPrevAffiliate(mPrevAffiliate);
988 }
989 setPrevAffiliate(null);
990 setNextAffiliate(null);
991 }
992
Winson Chung740c3ac2014-11-12 16:14:38 -0800993 void removedFromRecents() {
Dianne Hackborn852975d2014-08-22 17:42:43 -0700994 disposeThumbnail();
995 closeRecentsChain();
996 if (inRecents) {
997 inRecents = false;
Winson Chung740c3ac2014-11-12 16:14:38 -0800998 mService.notifyTaskPersisterLocked(this, false);
Dianne Hackborn852975d2014-08-22 17:42:43 -0700999 }
Jorim Jaggif9084ec2017-01-16 13:16:59 +01001000
1001 // TODO: Use window container controller once tasks are better synced between AM and WM
1002 mService.mWindowManager.notifyTaskRemovedFromRecents(taskId, userId);
Dianne Hackborn852975d2014-08-22 17:42:43 -07001003 }
1004
Craig Mautnera228ae92014-07-09 05:44:55 -07001005 void setTaskToAffiliateWith(TaskRecord taskToAffiliateWith) {
1006 closeRecentsChain();
1007 mAffiliatedTaskId = taskToAffiliateWith.mAffiliatedTaskId;
Winson Chungec396d62014-08-06 17:08:00 -07001008 mAffiliatedTaskColor = taskToAffiliateWith.mAffiliatedTaskColor;
Craig Mautnera228ae92014-07-09 05:44:55 -07001009 // Find the end
1010 while (taskToAffiliateWith.mNextAffiliate != null) {
1011 final TaskRecord nextRecents = taskToAffiliateWith.mNextAffiliate;
1012 if (nextRecents.mAffiliatedTaskId != mAffiliatedTaskId) {
1013 Slog.e(TAG, "setTaskToAffiliateWith: nextRecents=" + nextRecents + " affilTaskId="
1014 + nextRecents.mAffiliatedTaskId + " should be " + mAffiliatedTaskId);
1015 if (nextRecents.mPrevAffiliate == taskToAffiliateWith) {
1016 nextRecents.setPrevAffiliate(null);
1017 }
1018 taskToAffiliateWith.setNextAffiliate(null);
1019 break;
1020 }
1021 taskToAffiliateWith = nextRecents;
1022 }
1023 taskToAffiliateWith.setNextAffiliate(this);
1024 setPrevAffiliate(taskToAffiliateWith);
1025 setNextAffiliate(null);
1026 }
1027
Winson Chung096f36b2014-08-20 15:39:01 -07001028 /**
Winsonc809cbb2015-11-02 12:06:15 -08001029 * Sets the last thumbnail with the current task bounds and the system orientation.
Winson Chung096f36b2014-08-20 15:39:01 -07001030 * @return whether the thumbnail was set
1031 */
Winsonc809cbb2015-11-02 12:06:15 -08001032 boolean setLastThumbnailLocked(Bitmap thumbnail) {
Winsonc809cbb2015-11-02 12:06:15 -08001033 int taskWidth = 0;
1034 int taskHeight = 0;
1035 if (mBounds != null) {
1036 // Non-fullscreen tasks
1037 taskWidth = mBounds.width();
1038 taskHeight = mBounds.height();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001039 } else if (mStack != null) {
Winsonc809cbb2015-11-02 12:06:15 -08001040 // Fullscreen tasks
1041 final Point displaySize = new Point();
Andrii Kulian02b7a832016-10-06 23:11:56 -07001042 mStack.getDisplaySize(displaySize);
Winsonc809cbb2015-11-02 12:06:15 -08001043 taskWidth = displaySize.x;
1044 taskHeight = displaySize.y;
1045 } else {
1046 Slog.e(TAG, "setLastThumbnailLocked() called on Task without stack");
1047 }
Andrii Kulian1779e612016-10-12 21:58:25 -07001048 // We need to provide the current orientation of the display on which this task resides,
1049 // not the orientation of the task.
Andrii Kulian94e82d9b02017-07-13 15:33:06 -07001050 final int orientation = getStack().getDisplay().getConfiguration().orientation;
Andrii Kulian1779e612016-10-12 21:58:25 -07001051 return setLastThumbnailLocked(thumbnail, taskWidth, taskHeight, orientation);
Winsonc809cbb2015-11-02 12:06:15 -08001052 }
1053
1054 /**
1055 * Sets the last thumbnail with the current task bounds.
1056 * @return whether the thumbnail was set
1057 */
1058 private boolean setLastThumbnailLocked(Bitmap thumbnail, int taskWidth, int taskHeight,
1059 int screenOrientation) {
Winson Chung096f36b2014-08-20 15:39:01 -07001060 if (mLastThumbnail != thumbnail) {
1061 mLastThumbnail = thumbnail;
Winsonc809cbb2015-11-02 12:06:15 -08001062 mLastThumbnailInfo.taskWidth = taskWidth;
1063 mLastThumbnailInfo.taskHeight = taskHeight;
1064 mLastThumbnailInfo.screenOrientation = screenOrientation;
Winson Chung096f36b2014-08-20 15:39:01 -07001065 if (thumbnail == null) {
1066 if (mLastThumbnailFile != null) {
1067 mLastThumbnailFile.delete();
1068 }
1069 } else {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001070 mService.mRecentTasks.saveImage(thumbnail, mLastThumbnailFile.getAbsolutePath());
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001071 }
Winson Chung096f36b2014-08-20 15:39:01 -07001072 return true;
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001073 }
Winson Chung096f36b2014-08-20 15:39:01 -07001074 return false;
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001075 }
1076
1077 void getLastThumbnail(TaskThumbnail thumbs) {
1078 thumbs.mainThumbnail = mLastThumbnail;
Winsonc809cbb2015-11-02 12:06:15 -08001079 thumbs.thumbnailInfo = mLastThumbnailInfo;
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001080 thumbs.thumbnailFileDescriptor = null;
Craig Mautnerf4f8bb72014-07-29 10:41:40 -07001081 if (mLastThumbnail == null) {
Suprabh Shukla09a88f52015-12-02 14:36:31 -08001082 thumbs.mainThumbnail = mService.mRecentTasks.getImageFromWriteQueue(
Suprabh Shukla23593142015-11-03 17:31:15 -08001083 mLastThumbnailFile.getAbsolutePath());
Craig Mautnerf4f8bb72014-07-29 10:41:40 -07001084 }
Winson Chung096f36b2014-08-20 15:39:01 -07001085 // Only load the thumbnail file if we don't have a thumbnail
1086 if (thumbs.mainThumbnail == null && mLastThumbnailFile.exists()) {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001087 try {
1088 thumbs.thumbnailFileDescriptor = ParcelFileDescriptor.open(mLastThumbnailFile,
1089 ParcelFileDescriptor.MODE_READ_ONLY);
1090 } catch (IOException e) {
Dianne Hackborn9844d292013-10-04 16:44:22 -07001091 }
1092 }
1093 }
1094
Winsonc809cbb2015-11-02 12:06:15 -08001095 /**
1096 * Removes in-memory thumbnail data when the max number of in-memory task thumbnails is reached.
1097 */
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001098 void freeLastThumbnail() {
1099 mLastThumbnail = null;
1100 }
1101
Winsonc809cbb2015-11-02 12:06:15 -08001102 /**
1103 * Removes all associated thumbnail data when a task is removed or pruned from recents.
1104 */
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001105 void disposeThumbnail() {
Winsonc6a2da02015-11-11 18:11:59 -08001106 mLastThumbnailInfo.reset();
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001107 mLastThumbnail = null;
1108 lastDescription = null;
1109 }
1110
Winson Chung1147c402014-05-14 11:05:00 -07001111 /** Returns the intent for the root activity for this task */
1112 Intent getBaseIntent() {
1113 return intent != null ? intent : affinityIntent;
1114 }
1115
Winson Chung942a85c2017-07-11 15:07:45 -07001116 /**
1117 * @return Whether there are only fullscreen activities in this task.
1118 */
1119 boolean containsOnlyFullscreenActivities() {
1120 for (int i = 0; i < mActivities.size(); i++) {
1121 final ActivityRecord r = mActivities.get(i);
1122 if (!r.finishing && !r.fullscreen) {
1123 return false;
1124 }
1125 }
1126 return true;
1127 }
1128
Winson Chung3b3f4642014-04-22 10:08:18 -07001129 /** Returns the first non-finishing activity from the root. */
1130 ActivityRecord getRootActivity() {
1131 for (int i = 0; i < mActivities.size(); i++) {
1132 final ActivityRecord r = mActivities.get(i);
1133 if (r.finishing) {
1134 continue;
1135 }
1136 return r;
1137 }
1138 return null;
1139 }
1140
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001141 ActivityRecord getTopActivity() {
1142 for (int i = mActivities.size() - 1; i >= 0; --i) {
1143 final ActivityRecord r = mActivities.get(i);
1144 if (r.finishing) {
1145 continue;
1146 }
1147 return r;
1148 }
1149 return null;
1150 }
1151
Filip Gruszczynski3e85ba22015-10-05 22:48:30 -07001152 ActivityRecord topRunningActivityLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001153 if (mStack != null) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001154 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1155 ActivityRecord r = mActivities.get(activityNdx);
Chong Zhang87761972016-08-22 13:53:24 -07001156 if (!r.finishing && r.okToShowLocked()) {
Wale Ogunwale7d701172015-03-11 15:36:30 -07001157 return r;
1158 }
Craig Mautner6b74cb52013-09-27 17:02:21 -07001159 }
1160 }
1161 return null;
1162 }
1163
Jorim Jaggiea039a82017-08-02 14:37:49 +02001164 void getAllRunningVisibleActivitiesLocked(ArrayList<ActivityRecord> outActivities) {
1165 if (mStack != null) {
1166 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1167 ActivityRecord r = mActivities.get(activityNdx);
Jorim Jaggi02f1d2f2017-08-04 14:29:16 +02001168 if (!r.finishing && r.okToShowLocked() && r.visibleIgnoringKeyguard) {
Jorim Jaggiea039a82017-08-02 14:37:49 +02001169 outActivities.add(r);
1170 }
1171 }
1172 }
1173 }
1174
Wale Ogunwale3b232392016-05-13 15:37:13 -07001175 ActivityRecord topRunningActivityWithStartingWindowLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001176 if (mStack != null) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001177 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1178 ActivityRecord r = mActivities.get(activityNdx);
1179 if (r.mStartingWindowState != STARTING_WINDOW_SHOWN
Chong Zhang87761972016-08-22 13:53:24 -07001180 || r.finishing || !r.okToShowLocked()) {
Wale Ogunwale3b232392016-05-13 15:37:13 -07001181 continue;
1182 }
1183 return r;
1184 }
1185 }
1186 return null;
1187 }
1188
Chong Zhang87761972016-08-22 13:53:24 -07001189 boolean okToShowLocked() {
1190 // NOTE: If {@link TaskRecord#topRunningActivityLocked} return is not null then it is
1191 // okay to show the activity when locked.
1192 return mService.mStackSupervisor.isCurrentProfileLocked(userId)
1193 || topRunningActivityLocked() != null;
1194 }
1195
Craig Mautner3b475fe2013-12-16 15:58:31 -08001196 /** Call after activity movement or finish to make sure that frontOfTask is set correctly */
Bryce Leed71317c2017-02-07 14:27:22 -08001197 final void setFrontOfTask() {
1198 boolean foundFront = false;
Craig Mautner3b475fe2013-12-16 15:58:31 -08001199 final int numActivities = mActivities.size();
Craig Mautner704e40b2013-12-18 16:43:51 -08001200 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
Craig Mautner3b475fe2013-12-16 15:58:31 -08001201 final ActivityRecord r = mActivities.get(activityNdx);
1202 if (foundFront || r.finishing) {
1203 r.frontOfTask = false;
1204 } else {
1205 r.frontOfTask = true;
1206 // Set frontOfTask false for every following activity.
1207 foundFront = true;
1208 }
1209 }
Craig Mautner9587ee02014-06-23 15:00:10 +00001210 if (!foundFront && numActivities > 0) {
1211 // All activities of this task are finishing. As we ought to have a frontOfTask
1212 // activity, make the bottom activity front.
1213 mActivities.get(0).frontOfTask = true;
1214 }
Craig Mautner3b475fe2013-12-16 15:58:31 -08001215 }
1216
Craig Mautnerde4ef022013-04-07 19:01:33 -07001217 /**
Craig Mautner3b475fe2013-12-16 15:58:31 -08001218 * Reorder the history stack so that the passed activity is brought to the front.
Craig Mautnerde4ef022013-04-07 19:01:33 -07001219 */
1220 final void moveActivityToFrontLocked(ActivityRecord newTop) {
Wale Ogunwale0fc365c2015-05-25 19:35:42 -07001221 if (DEBUG_ADD_REMOVE) Slog.i(TAG_ADD_REMOVE,
1222 "Removing and adding activity " + newTop
1223 + " to stack at top callers=" + Debug.getCallers(4));
Craig Mautnerde4ef022013-04-07 19:01:33 -07001224
Craig Mautnerde4ef022013-04-07 19:01:33 -07001225 mActivities.remove(newTop);
1226 mActivities.add(newTop);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001227 updateEffectiveIntent();
Craig Mautner3b475fe2013-12-16 15:58:31 -08001228
Bryce Leed71317c2017-02-07 14:27:22 -08001229 setFrontOfTask();
Craig Mautnerde4ef022013-04-07 19:01:33 -07001230 }
1231
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001232 void addActivityAtBottom(ActivityRecord r) {
Craig Mautner77878772013-03-04 19:46:24 -08001233 addActivityAtIndex(0, r);
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001234 }
1235
1236 void addActivityToTop(ActivityRecord r) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001237 addActivityAtIndex(mActivities.size(), r);
1238 }
1239
Winson Chung30480042017-01-26 10:55:34 -08001240 /**
1241 * Adds an activity {@param r} at the given {@param index}. The activity {@param r} must either
1242 * be in the current task or unparented to any task.
1243 */
Craig Mautner1602ec22013-05-12 10:24:27 -07001244 void addActivityAtIndex(int index, ActivityRecord r) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001245 TaskRecord task = r.getTask();
1246 if (task != null && task != this) {
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001247 throw new IllegalArgumentException("Can not add r=" + " to task=" + this
Bryce Leeaf691c02017-03-20 14:20:22 -07001248 + " current parent=" + task);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001249 }
Bryce Leeaf691c02017-03-20 14:20:22 -07001250
1251 r.setTask(this);
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001252
Craig Mautner6170f732013-04-02 13:05:23 -07001253 // Remove r first, and if it wasn't already in the list and it's fullscreen, count it.
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001254 if (!mActivities.remove(r) && r.fullscreen) {
1255 // Was not previously in list.
1256 numFullscreen++;
1257 }
Craig Mautner2c1faed2013-07-23 12:56:02 -07001258 // Only set this based on the first activity
1259 if (mActivities.isEmpty()) {
Craig Mautner21d24a22014-04-23 11:45:37 -07001260 taskType = r.mActivityType;
1261 isPersistable = r.isPersistable();
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001262 mCallingUid = r.launchedFromUid;
1263 mCallingPackage = r.launchedFromPackage;
Dianne Hackborn852975d2014-08-22 17:42:43 -07001264 // Clamp to [1, max].
1265 maxRecents = Math.min(Math.max(r.info.maxRecents, 1),
1266 ActivityManager.getMaxAppRecentsLimitStatic());
Craig Mautner2c1faed2013-07-23 12:56:02 -07001267 } else {
1268 // Otherwise make all added activities match this one.
Craig Mautner21d24a22014-04-23 11:45:37 -07001269 r.mActivityType = taskType;
Craig Mautner78733002013-06-10 13:54:49 -07001270 }
Wale Ogunwale3b232392016-05-13 15:37:13 -07001271
1272 final int size = mActivities.size();
1273
1274 if (index == size && size > 0) {
1275 final ActivityRecord top = mActivities.get(size - 1);
1276 if (top.mTaskOverlay) {
1277 // Place below the task overlay activity since the overlay activity should always
1278 // be on top.
1279 index--;
1280 }
1281 }
1282
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001283 index = Math.min(size, index);
Craig Mautner77878772013-03-04 19:46:24 -08001284 mActivities.add(index, r);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001285 updateEffectiveIntent();
Craig Mautner21d24a22014-04-23 11:45:37 -07001286 if (r.isPersistable()) {
1287 mService.notifyTaskPersisterLocked(this, false);
1288 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -08001289
1290 // Sync. with window manager
1291 updateOverrideConfigurationFromLaunchBounds();
Wale Ogunwalea0cd15e2017-02-01 15:33:08 -08001292 final AppWindowContainerController appController = r.getWindowContainerController();
1293 if (appController != null) {
1294 // Only attempt to move in WM if the child has a controller. It is possible we haven't
1295 // created controller for the activity we are starting yet.
1296 mWindowContainerController.positionChildAt(appController, index);
1297 }
David Stevens82ea6cb2017-03-03 16:18:50 -08001298
1299 // Make sure the list of display UID whitelists is updated
1300 // now that this record is in a new task.
1301 mService.mStackSupervisor.updateUIDsPresentOnDisplay();
Craig Mautner77878772013-03-04 19:46:24 -08001302 }
1303
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001304 /**
Bryce Leeaf691c02017-03-20 14:20:22 -07001305 * Removes the specified activity from this task.
1306 * @param r The {@link ActivityRecord} to remove.
1307 * @return true if this was the last activity in the task.
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001308 */
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001309 boolean removeActivity(ActivityRecord r) {
Bryce Leeaf691c02017-03-20 14:20:22 -07001310 return removeActivity(r, false /*reparenting*/);
1311 }
1312
1313 boolean removeActivity(ActivityRecord r, boolean reparenting) {
1314 if (r.getTask() != this) {
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001315 throw new IllegalArgumentException(
1316 "Activity=" + r + " does not belong to task=" + this);
1317 }
1318
Bryce Leeaf691c02017-03-20 14:20:22 -07001319 r.setTask(null /*task*/, reparenting);
Bryce Leeaa5e8c32017-03-01 16:01:06 -08001320
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001321 if (mActivities.remove(r) && r.fullscreen) {
1322 // Was previously in list.
1323 numFullscreen--;
1324 }
Craig Mautner21d24a22014-04-23 11:45:37 -07001325 if (r.isPersistable()) {
1326 mService.notifyTaskPersisterLocked(this, false);
1327 }
Wale Ogunwale89182d52016-03-11 10:38:36 -08001328
Andrii Kulian02b7a832016-10-06 23:11:56 -07001329 if (getStackId() == PINNED_STACK_ID) {
Wale Ogunwale89182d52016-03-11 10:38:36 -08001330 // We normally notify listeners of task stack changes on pause, however pinned stack
1331 // activities are normally in the paused state so no notification will be sent there
1332 // before the activity is removed. We send it here so instead.
Yorke Leebd54c2a2016-10-25 13:49:23 -07001333 mService.mTaskChangeNotificationController.notifyTaskStackChanged();
Wale Ogunwale89182d52016-03-11 10:38:36 -08001334 }
1335
Craig Mautner41326202014-06-20 14:38:21 -07001336 if (mActivities.isEmpty()) {
Craig Mautner5afcd4d2014-06-21 18:11:33 -07001337 return !mReuseTask;
Craig Mautner41326202014-06-20 14:38:21 -07001338 }
1339 updateEffectiveIntent();
1340 return false;
Craig Mautner5d9c7be2013-02-15 14:02:56 -08001341 }
1342
Winson Chung6954fc92017-03-24 16:22:12 -07001343 /**
1344 * @return whether or not there are ONLY task overlay activities in the stack.
1345 * If {@param excludeFinishing} is set, then ignore finishing activities in the check.
1346 * If there are no task overlay activities, this call returns false.
1347 */
1348 boolean onlyHasTaskOverlayActivities(boolean excludeFinishing) {
1349 int count = 0;
1350 for (int i = mActivities.size() - 1; i >= 0; i--) {
1351 final ActivityRecord r = mActivities.get(i);
1352 if (excludeFinishing && r.finishing) {
1353 continue;
1354 }
1355 if (!r.mTaskOverlay) {
1356 return false;
1357 }
1358 count++;
1359 }
1360 return count > 0;
1361 }
1362
Craig Mautner41db4a72014-05-07 17:20:56 -07001363 boolean autoRemoveFromRecents() {
Dianne Hackbornd38aed82014-06-10 21:36:35 -07001364 // We will automatically remove the task either if it has explicitly asked for
1365 // this, or it is empty and has never contained an activity that got shown to
1366 // the user.
Dianne Hackborn13420f22014-07-18 15:43:56 -07001367 return autoRemoveRecents || (mActivities.isEmpty() && !hasBeenVisible);
Craig Mautner41db4a72014-05-07 17:20:56 -07001368 }
1369
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001370 /**
1371 * Completely remove all activities associated with an existing
1372 * task starting at a specified index.
1373 */
Winson Chung6954fc92017-03-24 16:22:12 -07001374 final void performClearTaskAtIndexLocked(int activityNdx, boolean pauseImmediately) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001375 int numActivities = mActivities.size();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001376 for ( ; activityNdx < numActivities; ++activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001377 final ActivityRecord r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001378 if (r.finishing) {
1379 continue;
1380 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001381 if (mStack == null) {
Craig Mautner21d24a22014-04-23 11:45:37 -07001382 // Task was restored from persistent storage.
1383 r.takeFromHistory();
1384 mActivities.remove(activityNdx);
1385 --activityNdx;
1386 --numActivities;
Winson Chung6954fc92017-03-24 16:22:12 -07001387 } else if (mStack.finishActivityLocked(r, Activity.RESULT_CANCELED, null,
1388 "clear-task-index", false, pauseImmediately)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001389 --activityNdx;
1390 --numActivities;
1391 }
1392 }
1393 }
1394
1395 /**
1396 * Completely remove all activities associated with an existing task.
1397 */
1398 final void performClearTaskLocked() {
Craig Mautner362449a2014-06-20 14:04:39 -07001399 mReuseTask = true;
Winson Chung6954fc92017-03-24 16:22:12 -07001400 performClearTaskAtIndexLocked(0, !PAUSE_IMMEDIATELY);
Craig Mautner362449a2014-06-20 14:04:39 -07001401 mReuseTask = false;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001402 }
1403
Filip Gruszczynskibe9dabd2016-01-19 12:23:10 -08001404 ActivityRecord performClearTaskForReuseLocked(ActivityRecord newR, int launchFlags) {
1405 mReuseTask = true;
1406 final ActivityRecord result = performClearTaskLocked(newR, launchFlags);
1407 mReuseTask = false;
1408 return result;
1409 }
1410
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001411 /**
1412 * Perform clear operation as requested by
1413 * {@link Intent#FLAG_ACTIVITY_CLEAR_TOP}: search from the top of the
1414 * stack to the given task, then look for
1415 * an instance of that activity in the stack and, if found, finish all
1416 * activities on top of it and return the instance.
1417 *
1418 * @param newR Description of the new activity being started.
1419 * @return Returns the old activity that should be continued to be used,
1420 * or null if none was found.
1421 */
1422 final ActivityRecord performClearTaskLocked(ActivityRecord newR, int launchFlags) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001423 int numActivities = mActivities.size();
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001424 for (int activityNdx = numActivities - 1; activityNdx >= 0; --activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001425 ActivityRecord r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001426 if (r.finishing) {
1427 continue;
1428 }
1429 if (r.realActivity.equals(newR.realActivity)) {
1430 // Here it is! Now finish everything in front...
Craig Mautner1602ec22013-05-12 10:24:27 -07001431 final ActivityRecord ret = r;
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001432
1433 for (++activityNdx; activityNdx < numActivities; ++activityNdx) {
Craig Mautner1602ec22013-05-12 10:24:27 -07001434 r = mActivities.get(activityNdx);
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001435 if (r.finishing) {
1436 continue;
1437 }
1438 ActivityOptions opts = r.takeOptionsLocked();
1439 if (opts != null) {
1440 ret.updateOptionsLocked(opts);
1441 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07001442 if (mStack != null && mStack.finishActivityLocked(
Todd Kennedy539db512014-12-15 09:57:55 -08001443 r, Activity.RESULT_CANCELED, null, "clear-task-stack", false)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001444 --activityNdx;
1445 --numActivities;
1446 }
1447 }
1448
1449 // Finally, if this is a normal launch mode (that is, not
1450 // expecting onNewIntent()), then we will finish the current
1451 // instance of the activity so a new fresh one can be started.
1452 if (ret.launchMode == ActivityInfo.LAUNCH_MULTIPLE
Daichi Hirono15a02992016-04-27 18:47:01 +09001453 && (launchFlags & Intent.FLAG_ACTIVITY_SINGLE_TOP) == 0
1454 && !ActivityStarter.isDocumentLaunchesIntoExisting(launchFlags)) {
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001455 if (!ret.finishing) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001456 if (mStack != null) {
1457 mStack.finishActivityLocked(
Wale Ogunwale7d701172015-03-11 15:36:30 -07001458 ret, Activity.RESULT_CANCELED, null, "clear-task-top", false);
1459 }
Craig Mautnerb0f7dc72013-04-01 16:34:45 -07001460 return null;
1461 }
1462 }
1463
1464 return ret;
1465 }
1466 }
1467
1468 return null;
1469 }
1470
Andrii Kulian21713ac2016-10-12 22:05:05 -07001471 TaskThumbnail getTaskThumbnailLocked() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07001472 if (mStack != null) {
1473 final ActivityRecord resumedActivity = mStack.mResumedActivity;
Bryce Leeaf691c02017-03-20 14:20:22 -07001474 if (resumedActivity != null && resumedActivity.getTask() == this) {
Andrii Kulian21713ac2016-10-12 22:05:05 -07001475 final Bitmap thumbnail = resumedActivity.screenshotActivityLocked();
Winsonc809cbb2015-11-02 12:06:15 -08001476 setLastThumbnailLocked(thumbnail);
Craig Mautner21d24a22014-04-23 11:45:37 -07001477 }
Craig Mautner9db9a0b2013-04-29 17:05:56 -07001478 }
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001479 final TaskThumbnail taskThumbnail = new TaskThumbnail();
1480 getLastThumbnail(taskThumbnail);
1481 return taskThumbnail;
Craig Mautner9db9a0b2013-04-29 17:05:56 -07001482 }
1483
Winson Chung6954fc92017-03-24 16:22:12 -07001484 void removeTaskActivitiesLocked(boolean pauseImmediately) {
Craig Mautnerc0ffce52014-07-01 12:38:52 -07001485 // Just remove the entire task.
Winson Chung6954fc92017-03-24 16:22:12 -07001486 performClearTaskAtIndexLocked(0, pauseImmediately);
Craig Mautner9db9a0b2013-04-29 17:05:56 -07001487 }
1488
Craig Mautner432f64e2015-05-20 14:59:57 -07001489 String lockTaskAuthToString() {
1490 switch (mLockTaskAuth) {
1491 case LOCK_TASK_AUTH_DONT_LOCK: return "LOCK_TASK_AUTH_DONT_LOCK";
1492 case LOCK_TASK_AUTH_PINNABLE: return "LOCK_TASK_AUTH_PINNABLE";
1493 case LOCK_TASK_AUTH_LAUNCHABLE: return "LOCK_TASK_AUTH_LAUNCHABLE";
1494 case LOCK_TASK_AUTH_WHITELISTED: return "LOCK_TASK_AUTH_WHITELISTED";
Benjamin Franz469dd582015-06-09 14:24:36 +01001495 case LOCK_TASK_AUTH_LAUNCHABLE_PRIV: return "LOCK_TASK_AUTH_LAUNCHABLE_PRIV";
Craig Mautner432f64e2015-05-20 14:59:57 -07001496 default: return "unknown=" + mLockTaskAuth;
1497 }
1498 }
1499
Craig Mautner15df08a2015-04-01 12:17:18 -07001500 void setLockTaskAuth() {
Benjamin Franz469dd582015-06-09 14:24:36 +01001501 if (!mPrivileged &&
1502 (mLockTaskMode == LOCK_TASK_LAUNCH_MODE_ALWAYS ||
1503 mLockTaskMode == LOCK_TASK_LAUNCH_MODE_NEVER)) {
1504 // Non-priv apps are not allowed to use always or never, fall back to default
1505 mLockTaskMode = LOCK_TASK_LAUNCH_MODE_DEFAULT;
1506 }
Craig Mautner15df08a2015-04-01 12:17:18 -07001507 switch (mLockTaskMode) {
1508 case LOCK_TASK_LAUNCH_MODE_DEFAULT:
1509 mLockTaskAuth = isLockTaskWhitelistedLocked() ?
1510 LOCK_TASK_AUTH_WHITELISTED : LOCK_TASK_AUTH_PINNABLE;
1511 break;
1512
1513 case LOCK_TASK_LAUNCH_MODE_NEVER:
Benjamin Franz469dd582015-06-09 14:24:36 +01001514 mLockTaskAuth = LOCK_TASK_AUTH_DONT_LOCK;
Craig Mautner15df08a2015-04-01 12:17:18 -07001515 break;
1516
1517 case LOCK_TASK_LAUNCH_MODE_ALWAYS:
Benjamin Franz469dd582015-06-09 14:24:36 +01001518 mLockTaskAuth = LOCK_TASK_AUTH_LAUNCHABLE_PRIV;
Craig Mautner15df08a2015-04-01 12:17:18 -07001519 break;
1520
1521 case LOCK_TASK_LAUNCH_MODE_IF_WHITELISTED:
1522 mLockTaskAuth = isLockTaskWhitelistedLocked() ?
1523 LOCK_TASK_AUTH_LAUNCHABLE : LOCK_TASK_AUTH_PINNABLE;
1524 break;
1525 }
Craig Mautner432f64e2015-05-20 14:59:57 -07001526 if (DEBUG_LOCKTASK) Slog.d(TAG_LOCKTASK, "setLockTaskAuth: task=" + this +
1527 " mLockTaskAuth=" + lockTaskAuthToString());
Craig Mautner15df08a2015-04-01 12:17:18 -07001528 }
1529
1530 boolean isLockTaskWhitelistedLocked() {
Benjamin Franz6fd84cc2015-08-06 18:09:03 +01001531 String pkg = (realActivity != null) ? realActivity.getPackageName() : null;
1532 if (pkg == null) {
Craig Mautner15df08a2015-04-01 12:17:18 -07001533 return false;
1534 }
1535 String[] packages = mService.mLockTaskPackages.get(userId);
1536 if (packages == null) {
1537 return false;
1538 }
1539 for (int i = packages.length - 1; i >= 0; --i) {
Benjamin Franz6fd84cc2015-08-06 18:09:03 +01001540 if (pkg.equals(packages[i])) {
Craig Mautner15df08a2015-04-01 12:17:18 -07001541 return true;
1542 }
1543 }
1544 return false;
1545 }
Wale Ogunwale74e26592016-02-05 11:48:37 -08001546
Craig Mautnera82aa092013-09-13 15:34:08 -07001547 boolean isHomeTask() {
Craig Mautner84984fa2014-06-19 11:19:20 -07001548 return taskType == HOME_ACTIVITY_TYPE;
Craig Mautnera82aa092013-09-13 15:34:08 -07001549 }
1550
Wale Ogunwale74e26592016-02-05 11:48:37 -08001551 boolean isRecentsTask() {
1552 return taskType == RECENTS_ACTIVITY_TYPE;
1553 }
1554
Winson Chung83471632016-12-13 11:02:12 -08001555 boolean isAssistantTask() {
1556 return taskType == ASSISTANT_ACTIVITY_TYPE;
1557 }
1558
Craig Mautner86d67a42013-05-14 10:34:38 -07001559 boolean isApplicationTask() {
Craig Mautner84984fa2014-06-19 11:19:20 -07001560 return taskType == APPLICATION_ACTIVITY_TYPE;
1561 }
1562
1563 boolean isOverHomeStack() {
Matthew Ngae1ff4f2016-11-10 15:49:14 -08001564 return mTaskToReturnTo == HOME_ACTIVITY_TYPE;
Craig Mautner1602ec22013-05-12 10:24:27 -07001565 }
1566
Winson Chung83471632016-12-13 11:02:12 -08001567 boolean isOverAssistantStack() {
1568 return mTaskToReturnTo == ASSISTANT_ACTIVITY_TYPE;
1569 }
1570
Winson Chungd3395382016-12-13 11:49:09 -08001571 private boolean isResizeable(boolean checkSupportsPip) {
1572 return (mService.mForceResizableActivities || ActivityInfo.isResizeableMode(mResizeMode)
1573 || (checkSupportsPip && mSupportsPictureInPicture)) && !mTemporarilyUnresizable;
1574 }
1575
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001576 boolean isResizeable() {
Winson Chungd3395382016-12-13 11:49:09 -08001577 return isResizeable(true /* checkSupportsPip */);
1578 }
1579
1580 boolean supportsSplitScreen() {
1581 // A task can not be docked even if it is considered resizeable because it only supports
1582 // picture-in-picture mode but has a non-resizeable resizeMode
1583 return mService.mSupportsSplitScreenMultiWindow
Bryce Leec857a5b2017-08-16 10:04:52 -07001584 && (mService.mForceResizableActivities
1585 || (isResizeable(false /* checkSupportsPip */)
1586 && !ActivityInfo.isPreserveOrientationMode(mResizeMode)));
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001587 }
1588
skuhne@google.com322347b2016-12-02 12:54:03 -08001589 /**
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001590 * Check whether this task can be launched on the specified display.
1591 * @param displayId Target display id.
1592 * @return {@code true} if either it is the default display or this activity is resizeable and
1593 * can be put a secondary screen.
1594 */
1595 boolean canBeLaunchedOnDisplay(int displayId) {
1596 return mService.mStackSupervisor.canPlaceEntityOnDisplay(displayId,
Andrii Kulian02689a72017-07-06 14:28:59 -07001597 isResizeable(false /* checkSupportsPip */), -1 /* don't check PID */,
1598 -1 /* don't check UID */, null /* activityInfo */);
Andrii Kulian036e3ad2017-04-19 10:55:10 -07001599 }
1600
1601 /**
skuhne@google.com322347b2016-12-02 12:54:03 -08001602 * Check that a given bounds matches the application requested orientation.
1603 *
1604 * @param bounds The bounds to be tested.
1605 * @return True if the requested bounds are okay for a resizing request.
1606 */
Wale Ogunwale069bbd32017-02-03 07:58:14 -08001607 private boolean canResizeToBounds(Rect bounds) {
skuhne@google.com322347b2016-12-02 12:54:03 -08001608 if (bounds == null || getStackId() != FREEFORM_WORKSPACE_STACK_ID) {
1609 // Note: If not on the freeform workspace, we ignore the bounds.
1610 return true;
1611 }
1612 final boolean landscape = bounds.width() > bounds.height();
1613 if (mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION) {
1614 return mBounds == null || landscape == (mBounds.width() > mBounds.height());
1615 }
1616 return (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY || !landscape)
1617 && (mResizeMode != RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY || landscape);
1618 }
1619
Craig Mautner525f3d92013-05-07 14:01:50 -07001620 /**
Yorke Leebdef5372017-04-10 16:38:51 -07001621 * @return {@code true} if the task is being cleared for the purposes of being reused.
1622 */
1623 boolean isClearingToReuseTask() {
1624 return mReuseTask;
1625 }
1626
1627 /**
Craig Mautner525f3d92013-05-07 14:01:50 -07001628 * Find the activity in the history stack within the given task. Returns
1629 * the index within the history at which it's found, or < 0 if not found.
1630 */
1631 final ActivityRecord findActivityInHistoryLocked(ActivityRecord r) {
1632 final ComponentName realActivity = r.realActivity;
1633 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
1634 ActivityRecord candidate = mActivities.get(activityNdx);
1635 if (candidate.finishing) {
1636 continue;
1637 }
1638 if (candidate.realActivity.equals(realActivity)) {
1639 return candidate;
1640 }
1641 }
1642 return null;
1643 }
1644
Winson Chunga449dc02014-05-16 11:15:04 -07001645 /** Updates the last task description values. */
1646 void updateTaskDescription() {
1647 // Traverse upwards looking for any break between main task activities and
1648 // utility activities.
1649 int activityNdx;
1650 final int numActivities = mActivities.size();
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001651 final boolean relinquish = numActivities != 0 &&
1652 (mActivities.get(0).info.flags & FLAG_RELINQUISH_TASK_IDENTITY) != 0;
Winson Chunga449dc02014-05-16 11:15:04 -07001653 for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities;
Craig Mautner21d24a22014-04-23 11:45:37 -07001654 ++activityNdx) {
Winson Chunga449dc02014-05-16 11:15:04 -07001655 final ActivityRecord r = mActivities.get(activityNdx);
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001656 if (relinquish && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001657 // This will be the top activity for determining taskDescription. Pre-inc to
1658 // overcome initial decrement below.
1659 ++activityNdx;
1660 break;
1661 }
Winson Chunga449dc02014-05-16 11:15:04 -07001662 if (r.intent != null &&
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001663 (r.intent.getFlags() & Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET) != 0) {
Winson Chunga449dc02014-05-16 11:15:04 -07001664 break;
1665 }
1666 }
1667 if (activityNdx > 0) {
1668 // Traverse downwards starting below break looking for set label, icon.
1669 // Note that if there are activities in the task but none of them set the
1670 // recent activity values, then we do not fall back to the last set
1671 // values in the TaskRecord.
1672 String label = null;
Craig Mautner648f69b2014-09-18 14:16:26 -07001673 String iconFilename = null;
Winson Chunga449dc02014-05-16 11:15:04 -07001674 int colorPrimary = 0;
Winson Chung1af8eda2016-02-05 17:55:56 +00001675 int colorBackground = 0;
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001676 int statusBarColor = 0;
1677 int navigationBarColor = 0;
1678 boolean topActivity = true;
Winson Chunga449dc02014-05-16 11:15:04 -07001679 for (--activityNdx; activityNdx >= 0; --activityNdx) {
1680 final ActivityRecord r = mActivities.get(activityNdx);
1681 if (r.taskDescription != null) {
1682 if (label == null) {
1683 label = r.taskDescription.getLabel();
1684 }
Craig Mautner648f69b2014-09-18 14:16:26 -07001685 if (iconFilename == null) {
1686 iconFilename = r.taskDescription.getIconFilename();
Winson Chunga449dc02014-05-16 11:15:04 -07001687 }
1688 if (colorPrimary == 0) {
1689 colorPrimary = r.taskDescription.getPrimaryColor();
Winson Chunga449dc02014-05-16 11:15:04 -07001690 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001691 if (topActivity) {
Winson Chung1af8eda2016-02-05 17:55:56 +00001692 colorBackground = r.taskDescription.getBackgroundColor();
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001693 statusBarColor = r.taskDescription.getStatusBarColor();
1694 navigationBarColor = r.taskDescription.getNavigationBarColor();
Winson Chung1af8eda2016-02-05 17:55:56 +00001695 }
Winson Chunga449dc02014-05-16 11:15:04 -07001696 }
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001697 topActivity = false;
Winson Chunga449dc02014-05-16 11:15:04 -07001698 }
Winson Chung1af8eda2016-02-05 17:55:56 +00001699 lastTaskDescription = new TaskDescription(label, null, iconFilename, colorPrimary,
Jorim Jaggi30d64f32017-04-07 16:33:17 +02001700 colorBackground, statusBarColor, navigationBarColor);
Jorim Jaggi829b9cd2017-01-23 16:20:53 +01001701 if (mWindowContainerController != null) {
1702 mWindowContainerController.setTaskDescription(lastTaskDescription);
1703 }
Winson Chungec396d62014-08-06 17:08:00 -07001704 // Update the task affiliation color if we are the parent of the group
1705 if (taskId == mAffiliatedTaskId) {
1706 mAffiliatedTaskColor = lastTaskDescription.getPrimaryColor();
1707 }
Winson Chunga449dc02014-05-16 11:15:04 -07001708 }
1709 }
1710
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001711 int findEffectiveRootIndex() {
Craig Mautner4767f4b2014-09-18 15:38:33 -07001712 int effectiveNdx = 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001713 final int topActivityNdx = mActivities.size() - 1;
Dianne Hackborn39569af2014-09-23 10:56:58 -07001714 for (int activityNdx = 0; activityNdx <= topActivityNdx; ++activityNdx) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001715 final ActivityRecord r = mActivities.get(activityNdx);
1716 if (r.finishing) {
1717 continue;
1718 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001719 effectiveNdx = activityNdx;
Wale Ogunwale3eadad72016-10-13 09:16:59 -07001720 if ((r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001721 break;
1722 }
1723 }
Craig Mautner4767f4b2014-09-18 15:38:33 -07001724 return effectiveNdx;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001725 }
1726
1727 void updateEffectiveIntent() {
1728 final int effectiveRootIndex = findEffectiveRootIndex();
1729 final ActivityRecord r = mActivities.get(effectiveRootIndex);
Winson Chungfee26772014-08-05 12:21:52 -07001730 setIntent(r);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001731 }
1732
Craig Mautner21d24a22014-04-23 11:45:37 -07001733 void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
Wale Ogunwaleee006da2015-03-30 14:49:25 -07001734 if (DEBUG_RECENTS) Slog.i(TAG_RECENTS, "Saving task=" + this);
Craig Mautner21d24a22014-04-23 11:45:37 -07001735
1736 out.attribute(null, ATTR_TASKID, String.valueOf(taskId));
1737 if (realActivity != null) {
1738 out.attribute(null, ATTR_REALACTIVITY, realActivity.flattenToShortString());
1739 }
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +00001740 out.attribute(null, ATTR_REALACTIVITY_SUSPENDED, String.valueOf(realActivitySuspended));
Craig Mautner21d24a22014-04-23 11:45:37 -07001741 if (origActivity != null) {
1742 out.attribute(null, ATTR_ORIGACTIVITY, origActivity.flattenToShortString());
1743 }
Dianne Hackborn79228822014-09-16 11:11:23 -07001744 // Write affinity, and root affinity if it is different from affinity.
1745 // We use the special string "@" for a null root affinity, so we can identify
1746 // later whether we were given a root affinity or should just make it the
1747 // same as the affinity.
Craig Mautner21d24a22014-04-23 11:45:37 -07001748 if (affinity != null) {
1749 out.attribute(null, ATTR_AFFINITY, affinity);
Dianne Hackborn79228822014-09-16 11:11:23 -07001750 if (!affinity.equals(rootAffinity)) {
1751 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
1752 }
1753 } else if (rootAffinity != null) {
1754 out.attribute(null, ATTR_ROOT_AFFINITY, rootAffinity != null ? rootAffinity : "@");
Craig Mautner21d24a22014-04-23 11:45:37 -07001755 }
1756 out.attribute(null, ATTR_ROOTHASRESET, String.valueOf(rootWasReset));
Dianne Hackborn13420f22014-07-18 15:43:56 -07001757 out.attribute(null, ATTR_AUTOREMOVERECENTS, String.valueOf(autoRemoveRecents));
Craig Mautner21d24a22014-04-23 11:45:37 -07001758 out.attribute(null, ATTR_ASKEDCOMPATMODE, String.valueOf(askedCompatMode));
1759 out.attribute(null, ATTR_USERID, String.valueOf(userId));
Wale Ogunwalef80170f2016-02-04 15:12:29 -08001760 out.attribute(null, ATTR_USER_SETUP_COMPLETE, String.valueOf(mUserSetupComplete));
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001761 out.attribute(null, ATTR_EFFECTIVE_UID, String.valueOf(effectiveUid));
Craig Mautner21d24a22014-04-23 11:45:37 -07001762 out.attribute(null, ATTR_TASKTYPE, String.valueOf(taskType));
Winson Chungffa2ec62014-07-03 15:54:42 -07001763 out.attribute(null, ATTR_FIRSTACTIVETIME, String.valueOf(firstActiveTime));
Winson Chungf1fbd772014-06-24 18:06:58 -07001764 out.attribute(null, ATTR_LASTACTIVETIME, String.valueOf(lastActiveTime));
Craig Mautner21d24a22014-04-23 11:45:37 -07001765 out.attribute(null, ATTR_LASTTIMEMOVED, String.valueOf(mLastTimeMoved));
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001766 out.attribute(null, ATTR_NEVERRELINQUISH, String.valueOf(mNeverRelinquishIdentity));
Craig Mautner21d24a22014-04-23 11:45:37 -07001767 if (lastDescription != null) {
1768 out.attribute(null, ATTR_LASTDESCRIPTION, lastDescription.toString());
1769 }
Winson Chung2cb86c72014-06-25 12:03:30 -07001770 if (lastTaskDescription != null) {
Craig Mautner648f69b2014-09-18 14:16:26 -07001771 lastTaskDescription.saveToXml(out);
Winson Chung2cb86c72014-06-25 12:03:30 -07001772 }
Winson Chung36f3f032016-09-08 23:29:43 +00001773 mLastThumbnailInfo.saveToXml(out);
Winson Chungec396d62014-08-06 17:08:00 -07001774 out.attribute(null, ATTR_TASK_AFFILIATION_COLOR, String.valueOf(mAffiliatedTaskColor));
Craig Mautnera228ae92014-07-09 05:44:55 -07001775 out.attribute(null, ATTR_TASK_AFFILIATION, String.valueOf(mAffiliatedTaskId));
1776 out.attribute(null, ATTR_PREV_AFFILIATION, String.valueOf(mPrevAffiliateTaskId));
1777 out.attribute(null, ATTR_NEXT_AFFILIATION, String.valueOf(mNextAffiliateTaskId));
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001778 out.attribute(null, ATTR_CALLING_UID, String.valueOf(mCallingUid));
1779 out.attribute(null, ATTR_CALLING_PACKAGE, mCallingPackage == null ? "" : mCallingPackage);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001780 out.attribute(null, ATTR_RESIZE_MODE, String.valueOf(mResizeMode));
Winson Chungd3395382016-12-13 11:49:09 -08001781 out.attribute(null, ATTR_SUPPORTS_PICTURE_IN_PICTURE,
1782 String.valueOf(mSupportsPictureInPicture));
Wale Ogunwalea7afaa22015-05-01 20:39:18 -07001783 out.attribute(null, ATTR_PRIVILEGED, String.valueOf(mPrivileged));
Wale Ogunwale706ed792015-08-02 10:29:44 -07001784 if (mLastNonFullscreenBounds != null) {
1785 out.attribute(
1786 null, ATTR_NON_FULLSCREEN_BOUNDS, mLastNonFullscreenBounds.flattenToString());
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001787 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001788 out.attribute(null, ATTR_MIN_WIDTH, String.valueOf(mMinWidth));
1789 out.attribute(null, ATTR_MIN_HEIGHT, String.valueOf(mMinHeight));
Wale Ogunwale625ed0c2016-10-18 08:50:31 -07001790 out.attribute(null, ATTR_PERSIST_TASK_VERSION, String.valueOf(PERSIST_TASK_VERSION));
Winson Chung2cb86c72014-06-25 12:03:30 -07001791
Craig Mautner21d24a22014-04-23 11:45:37 -07001792 if (affinityIntent != null) {
1793 out.startTag(null, TAG_AFFINITYINTENT);
1794 affinityIntent.saveToXml(out);
1795 out.endTag(null, TAG_AFFINITYINTENT);
1796 }
1797
Winson Chung36f3f032016-09-08 23:29:43 +00001798 out.startTag(null, TAG_INTENT);
1799 intent.saveToXml(out);
1800 out.endTag(null, TAG_INTENT);
Craig Mautner21d24a22014-04-23 11:45:37 -07001801
1802 final ArrayList<ActivityRecord> activities = mActivities;
1803 final int numActivities = activities.size();
1804 for (int activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
1805 final ActivityRecord r = activities.get(activityNdx);
Craig Mautner43e52ed2014-06-16 17:18:52 -07001806 if (r.info.persistableMode == ActivityInfo.PERSIST_ROOT_ONLY || !r.isPersistable() ||
Wale Ogunwale843bfb92015-03-27 11:06:48 -07001807 ((r.intent.getFlags() & FLAG_ACTIVITY_NEW_DOCUMENT
1808 | FLAG_ACTIVITY_RETAIN_IN_RECENTS) == FLAG_ACTIVITY_NEW_DOCUMENT) &&
Craig Mautner43e52ed2014-06-16 17:18:52 -07001809 activityNdx > 0) {
Craig Mautnerf357c0c2014-06-09 09:23:27 -07001810 // Stop at first non-persistable or first break in task (CLEAR_WHEN_TASK_RESET).
Craig Mautner21d24a22014-04-23 11:45:37 -07001811 break;
1812 }
1813 out.startTag(null, TAG_ACTIVITY);
1814 r.saveToXml(out);
1815 out.endTag(null, TAG_ACTIVITY);
1816 }
Craig Mautner21d24a22014-04-23 11:45:37 -07001817 }
1818
Winson Chung36f3f032016-09-08 23:29:43 +00001819 static TaskRecord restoreFromXml(XmlPullParser in, ActivityStackSupervisor stackSupervisor)
1820 throws IOException, XmlPullParserException {
Craig Mautner21d24a22014-04-23 11:45:37 -07001821 Intent intent = null;
1822 Intent affinityIntent = null;
Winsonc809cbb2015-11-02 12:06:15 -08001823 ArrayList<ActivityRecord> activities = new ArrayList<>();
Craig Mautner21d24a22014-04-23 11:45:37 -07001824 ComponentName realActivity = null;
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +00001825 boolean realActivitySuspended = false;
Craig Mautner21d24a22014-04-23 11:45:37 -07001826 ComponentName origActivity = null;
1827 String affinity = null;
Dianne Hackborn79228822014-09-16 11:11:23 -07001828 String rootAffinity = null;
1829 boolean hasRootAffinity = false;
Craig Mautner21d24a22014-04-23 11:45:37 -07001830 boolean rootHasReset = false;
Dianne Hackborn13420f22014-07-18 15:43:56 -07001831 boolean autoRemoveRecents = false;
Craig Mautner21d24a22014-04-23 11:45:37 -07001832 boolean askedCompatMode = false;
1833 int taskType = ActivityRecord.APPLICATION_ACTIVITY_TYPE;
Craig Mautner21d24a22014-04-23 11:45:37 -07001834 int userId = 0;
Wale Ogunwalef80170f2016-02-04 15:12:29 -08001835 boolean userSetupComplete = true;
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001836 int effectiveUid = -1;
Craig Mautner21d24a22014-04-23 11:45:37 -07001837 String lastDescription = null;
Winson Chungffa2ec62014-07-03 15:54:42 -07001838 long firstActiveTime = -1;
Winson Chung2cb86c72014-06-25 12:03:30 -07001839 long lastActiveTime = -1;
Craig Mautner21d24a22014-04-23 11:45:37 -07001840 long lastTimeOnTop = 0;
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001841 boolean neverRelinquishIdentity = true;
Stefan Kuhnee88d1e52015-05-18 10:33:45 -07001842 int taskId = INVALID_TASK_ID;
Craig Mautner21d24a22014-04-23 11:45:37 -07001843 final int outerDepth = in.getDepth();
Craig Mautner648f69b2014-09-18 14:16:26 -07001844 TaskDescription taskDescription = new TaskDescription();
Winsonc809cbb2015-11-02 12:06:15 -08001845 TaskThumbnailInfo thumbnailInfo = new TaskThumbnailInfo();
Wale Ogunwale18795a22014-12-03 11:38:33 -08001846 int taskAffiliation = INVALID_TASK_ID;
Winson Chungec396d62014-08-06 17:08:00 -07001847 int taskAffiliationColor = 0;
Wale Ogunwale18795a22014-12-03 11:38:33 -08001848 int prevTaskId = INVALID_TASK_ID;
1849 int nextTaskId = INVALID_TASK_ID;
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001850 int callingUid = -1;
1851 String callingPackage = "";
Wale Ogunwaled829d362016-02-10 19:24:49 -08001852 int resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
Winson Chungd3395382016-12-13 11:49:09 -08001853 boolean supportsPictureInPicture = false;
Wale Ogunwalea7afaa22015-05-01 20:39:18 -07001854 boolean privileged = false;
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001855 Rect bounds = null;
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001856 int minWidth = INVALID_MIN_SIZE;
1857 int minHeight = INVALID_MIN_SIZE;
Wale Ogunwale625ed0c2016-10-18 08:50:31 -07001858 int persistTaskVersion = 0;
Craig Mautner21d24a22014-04-23 11:45:37 -07001859
1860 for (int attrNdx = in.getAttributeCount() - 1; attrNdx >= 0; --attrNdx) {
1861 final String attrName = in.getAttributeName(attrNdx);
1862 final String attrValue = in.getAttributeValue(attrNdx);
Stefan Kuhnee88d1e52015-05-18 10:33:45 -07001863 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: attribute name=" +
1864 attrName + " value=" + attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001865 if (ATTR_TASKID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001866 if (taskId == INVALID_TASK_ID) taskId = Integer.parseInt(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001867 } else if (ATTR_REALACTIVITY.equals(attrName)) {
1868 realActivity = ComponentName.unflattenFromString(attrValue);
Andrei Stingaceanu4ccec532016-01-13 12:10:21 +00001869 } else if (ATTR_REALACTIVITY_SUSPENDED.equals(attrName)) {
1870 realActivitySuspended = Boolean.valueOf(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001871 } else if (ATTR_ORIGACTIVITY.equals(attrName)) {
1872 origActivity = ComponentName.unflattenFromString(attrValue);
1873 } else if (ATTR_AFFINITY.equals(attrName)) {
1874 affinity = attrValue;
Dianne Hackborn79228822014-09-16 11:11:23 -07001875 } else if (ATTR_ROOT_AFFINITY.equals(attrName)) {
1876 rootAffinity = attrValue;
1877 hasRootAffinity = true;
Craig Mautner21d24a22014-04-23 11:45:37 -07001878 } else if (ATTR_ROOTHASRESET.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001879 rootHasReset = Boolean.parseBoolean(attrValue);
Dianne Hackborn13420f22014-07-18 15:43:56 -07001880 } else if (ATTR_AUTOREMOVERECENTS.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001881 autoRemoveRecents = Boolean.parseBoolean(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001882 } else if (ATTR_ASKEDCOMPATMODE.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001883 askedCompatMode = Boolean.parseBoolean(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001884 } else if (ATTR_USERID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001885 userId = Integer.parseInt(attrValue);
Wale Ogunwalef80170f2016-02-04 15:12:29 -08001886 } else if (ATTR_USER_SETUP_COMPLETE.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001887 userSetupComplete = Boolean.parseBoolean(attrValue);
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001888 } else if (ATTR_EFFECTIVE_UID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001889 effectiveUid = Integer.parseInt(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001890 } else if (ATTR_TASKTYPE.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001891 taskType = Integer.parseInt(attrValue);
Winson Chungffa2ec62014-07-03 15:54:42 -07001892 } else if (ATTR_FIRSTACTIVETIME.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001893 firstActiveTime = Long.parseLong(attrValue);
Winson Chungf1fbd772014-06-24 18:06:58 -07001894 } else if (ATTR_LASTACTIVETIME.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001895 lastActiveTime = Long.parseLong(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001896 } else if (ATTR_LASTDESCRIPTION.equals(attrName)) {
1897 lastDescription = attrValue;
1898 } else if (ATTR_LASTTIMEMOVED.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001899 lastTimeOnTop = Long.parseLong(attrValue);
Craig Mautner9d4e9bc2014-06-18 18:34:56 -07001900 } else if (ATTR_NEVERRELINQUISH.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001901 neverRelinquishIdentity = Boolean.parseBoolean(attrValue);
Winsonc809cbb2015-11-02 12:06:15 -08001902 } else if (attrName.startsWith(TaskThumbnailInfo.ATTR_TASK_THUMBNAILINFO_PREFIX)) {
1903 thumbnailInfo.restoreFromXml(attrName, attrValue);
Craig Mautner648f69b2014-09-18 14:16:26 -07001904 } else if (attrName.startsWith(TaskDescription.ATTR_TASKDESCRIPTION_PREFIX)) {
1905 taskDescription.restoreFromXml(attrName, attrValue);
Craig Mautnera228ae92014-07-09 05:44:55 -07001906 } else if (ATTR_TASK_AFFILIATION.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001907 taskAffiliation = Integer.parseInt(attrValue);
Craig Mautnera228ae92014-07-09 05:44:55 -07001908 } else if (ATTR_PREV_AFFILIATION.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001909 prevTaskId = Integer.parseInt(attrValue);
Craig Mautnera228ae92014-07-09 05:44:55 -07001910 } else if (ATTR_NEXT_AFFILIATION.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001911 nextTaskId = Integer.parseInt(attrValue);
Winson Chungec396d62014-08-06 17:08:00 -07001912 } else if (ATTR_TASK_AFFILIATION_COLOR.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001913 taskAffiliationColor = Integer.parseInt(attrValue);
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001914 } else if (ATTR_CALLING_UID.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001915 callingUid = Integer.parseInt(attrValue);
Craig Mautnerdc00cbe2014-07-20 17:48:47 -07001916 } else if (ATTR_CALLING_PACKAGE.equals(attrName)) {
1917 callingPackage = attrValue;
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08001918 } else if (ATTR_RESIZE_MODE.equals(attrName)) {
Narayan Kamatha09b4d22016-04-15 18:32:45 +01001919 resizeMode = Integer.parseInt(attrValue);
Winson Chungd3395382016-12-13 11:49:09 -08001920 } else if (ATTR_SUPPORTS_PICTURE_IN_PICTURE.equals(attrName)) {
1921 supportsPictureInPicture = Boolean.parseBoolean(attrValue);
Wale Ogunwalea7afaa22015-05-01 20:39:18 -07001922 } else if (ATTR_PRIVILEGED.equals(attrName)) {
Tobias Thierer28532d02016-04-21 14:52:10 +01001923 privileged = Boolean.parseBoolean(attrValue);
Wale Ogunwale706ed792015-08-02 10:29:44 -07001924 } else if (ATTR_NON_FULLSCREEN_BOUNDS.equals(attrName)) {
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07001925 bounds = Rect.unflattenFromString(attrValue);
Andrii Kulianf66a83d2016-05-17 12:17:44 -07001926 } else if (ATTR_MIN_WIDTH.equals(attrName)) {
1927 minWidth = Integer.parseInt(attrValue);
1928 } else if (ATTR_MIN_HEIGHT.equals(attrName)) {
1929 minHeight = Integer.parseInt(attrValue);
Wale Ogunwale625ed0c2016-10-18 08:50:31 -07001930 } else if (ATTR_PERSIST_TASK_VERSION.equals(attrName)) {
1931 persistTaskVersion = Integer.parseInt(attrValue);
Craig Mautner21d24a22014-04-23 11:45:37 -07001932 } else {
1933 Slog.w(TAG, "TaskRecord: Unknown attribute=" + attrName);
1934 }
1935 }
1936
1937 int event;
1938 while (((event = in.next()) != XmlPullParser.END_DOCUMENT) &&
Ben Kwa8814cf42015-07-08 10:54:56 -07001939 (event != XmlPullParser.END_TAG || in.getDepth() >= outerDepth)) {
Craig Mautner21d24a22014-04-23 11:45:37 -07001940 if (event == XmlPullParser.START_TAG) {
1941 final String name = in.getName();
Stefan Kuhnee88d1e52015-05-18 10:33:45 -07001942 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: START_TAG name=" +
1943 name);
Craig Mautner21d24a22014-04-23 11:45:37 -07001944 if (TAG_AFFINITYINTENT.equals(name)) {
1945 affinityIntent = Intent.restoreFromXml(in);
1946 } else if (TAG_INTENT.equals(name)) {
1947 intent = Intent.restoreFromXml(in);
1948 } else if (TAG_ACTIVITY.equals(name)) {
Wale Ogunwale18795a22014-12-03 11:38:33 -08001949 ActivityRecord activity = ActivityRecord.restoreFromXml(in, stackSupervisor);
Stefan Kuhnee88d1e52015-05-18 10:33:45 -07001950 if (TaskPersister.DEBUG) Slog.d(TaskPersister.TAG, "TaskRecord: activity=" +
1951 activity);
Craig Mautner21d24a22014-04-23 11:45:37 -07001952 if (activity != null) {
1953 activities.add(activity);
1954 }
1955 } else {
1956 Slog.e(TAG, "restoreTask: Unexpected name=" + name);
1957 XmlUtils.skipCurrentTag(in);
1958 }
1959 }
1960 }
Dianne Hackborn79228822014-09-16 11:11:23 -07001961 if (!hasRootAffinity) {
1962 rootAffinity = affinity;
1963 } else if ("@".equals(rootAffinity)) {
1964 rootAffinity = null;
1965 }
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001966 if (effectiveUid <= 0) {
1967 Intent checkIntent = intent != null ? intent : affinityIntent;
1968 effectiveUid = 0;
1969 if (checkIntent != null) {
1970 IPackageManager pm = AppGlobals.getPackageManager();
1971 try {
1972 ApplicationInfo ai = pm.getApplicationInfo(
1973 checkIntent.getComponent().getPackageName(),
Amith Yamasani0d1fd8d2016-10-12 14:21:51 -07001974 PackageManager.MATCH_UNINSTALLED_PACKAGES
1975 | PackageManager.MATCH_DISABLED_COMPONENTS, userId);
Dianne Hackborn885fbe52014-08-23 15:23:58 -07001976 if (ai != null) {
1977 effectiveUid = ai.uid;
1978 }
1979 } catch (RemoteException e) {
1980 }
1981 }
1982 Slog.w(TAG, "Updating task #" + taskId + " for " + checkIntent
1983 + ": effectiveUid=" + effectiveUid);
1984 }
1985
Wale Ogunwale625ed0c2016-10-18 08:50:31 -07001986 if (persistTaskVersion < 1) {
1987 // We need to convert the resize mode of home activities saved before version one if
1988 // they are marked as RESIZE_MODE_RESIZEABLE to RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION
1989 // since we didn't have that differentiation before version 1 and the system didn't
1990 // resize home activities before then.
1991 if (taskType == HOME_ACTIVITY_TYPE && resizeMode == RESIZE_MODE_RESIZEABLE) {
1992 resizeMode = RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
1993 }
Winson Chungd3395382016-12-13 11:49:09 -08001994 } else {
1995 // This activity has previously marked itself explicitly as both resizeable and
1996 // supporting picture-in-picture. Since there is no longer a requirement for
1997 // picture-in-picture activities to be resizeable, we can mark this simply as
1998 // resizeable and supporting picture-in-picture separately.
1999 if (resizeMode == RESIZE_MODE_RESIZEABLE_AND_PIPABLE_DEPRECATED) {
2000 resizeMode = RESIZE_MODE_RESIZEABLE;
2001 supportsPictureInPicture = true;
2002 }
Wale Ogunwale625ed0c2016-10-18 08:50:31 -07002003 }
2004
Winson Chung36f3f032016-09-08 23:29:43 +00002005 final TaskRecord task = new TaskRecord(stackSupervisor.mService, taskId, intent,
Dianne Hackborn79228822014-09-16 11:11:23 -07002006 affinityIntent, affinity, rootAffinity, realActivity, origActivity, rootHasReset,
Dianne Hackborn885fbe52014-08-23 15:23:58 -07002007 autoRemoveRecents, askedCompatMode, taskType, userId, effectiveUid, lastDescription,
2008 activities, firstActiveTime, lastActiveTime, lastTimeOnTop, neverRelinquishIdentity,
Winsonc809cbb2015-11-02 12:06:15 -08002009 taskDescription, thumbnailInfo, taskAffiliation, prevTaskId, nextTaskId,
Winson Chungd3395382016-12-13 11:49:09 -08002010 taskAffiliationColor, callingUid, callingPackage, resizeMode,
2011 supportsPictureInPicture, privileged, realActivitySuspended, userSetupComplete,
2012 minWidth, minHeight);
Filip Gruszczynskiaff7f132015-09-02 17:21:21 -07002013 task.updateOverrideConfiguration(bounds);
Craig Mautner21d24a22014-04-23 11:45:37 -07002014
2015 for (int activityNdx = activities.size() - 1; activityNdx >=0; --activityNdx) {
Bryce Leeaf691c02017-03-20 14:20:22 -07002016 activities.get(activityNdx).setTask(task);
Craig Mautner21d24a22014-04-23 11:45:37 -07002017 }
2018
Wale Ogunwaleee006da2015-03-30 14:49:25 -07002019 if (DEBUG_RECENTS) Slog.d(TAG_RECENTS, "Restored task=" + task);
Craig Mautner21d24a22014-04-23 11:45:37 -07002020 return task;
2021 }
2022
Wale Ogunwale9a08f822016-02-17 19:03:58 -08002023 private void adjustForMinimalTaskDimensions(Rect bounds) {
2024 if (bounds == null) {
2025 return;
2026 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07002027 int minWidth = mMinWidth;
2028 int minHeight = mMinHeight;
Robert Carr9c5867d2016-03-10 15:52:46 -08002029 // If the task has no requested minimal size, we'd like to enforce a minimal size
2030 // so that the user can not render the task too small to manipulate. We don't need
2031 // to do this for the pinned stack as the bounds are controlled by the system.
Andrii Kulian02b7a832016-10-06 23:11:56 -07002032 if (getStackId() != PINNED_STACK_ID) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07002033 if (minWidth == INVALID_MIN_SIZE) {
2034 minWidth = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
Andrii Kulian2e751b82016-03-16 16:59:32 -07002035 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07002036 if (minHeight == INVALID_MIN_SIZE) {
2037 minHeight = mService.mStackSupervisor.mDefaultMinSizeOfResizeableTask;
Andrii Kulian2e751b82016-03-16 16:59:32 -07002038 }
Robert Carr9c5867d2016-03-10 15:52:46 -08002039 }
Andrii Kulianf66a83d2016-05-17 12:17:44 -07002040 final boolean adjustWidth = minWidth > bounds.width();
2041 final boolean adjustHeight = minHeight > bounds.height();
Wale Ogunwale9a08f822016-02-17 19:03:58 -08002042 if (!(adjustWidth || adjustHeight)) {
2043 return;
2044 }
2045
2046 if (adjustWidth) {
2047 if (mBounds != null && bounds.right == mBounds.right) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07002048 bounds.left = bounds.right - minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08002049 } else {
2050 // Either left bounds match, or neither match, or the previous bounds were
2051 // fullscreen and we default to keeping left.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07002052 bounds.right = bounds.left + minWidth;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08002053 }
2054 }
2055 if (adjustHeight) {
2056 if (mBounds != null && bounds.bottom == mBounds.bottom) {
Andrii Kulianf66a83d2016-05-17 12:17:44 -07002057 bounds.top = bounds.bottom - minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08002058 } else {
2059 // Either top bounds match, or neither match, or the previous bounds were
2060 // fullscreen and we default to keeping top.
Andrii Kulianf66a83d2016-05-17 12:17:44 -07002061 bounds.bottom = bounds.top + minHeight;
Wale Ogunwale9a08f822016-02-17 19:03:58 -08002062 }
2063 }
2064 }
2065
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07002066 /**
Winson Chung5af42fc2017-03-24 17:11:33 -07002067 * @return a new Configuration for this Task, given the provided {@param bounds} and
2068 * {@param insetBounds}.
2069 */
2070 Configuration computeNewOverrideConfigurationForBounds(Rect bounds, Rect insetBounds) {
2071 // Compute a new override configuration for the given bounds, if fullscreen bounds
2072 // (bounds == null), then leave the override config unset
2073 final Configuration newOverrideConfig = new Configuration();
2074 if (bounds != null) {
2075 newOverrideConfig.setTo(getOverrideConfiguration());
2076 mTmpRect.set(bounds);
2077 adjustForMinimalTaskDimensions(mTmpRect);
2078 computeOverrideConfiguration(newOverrideConfig, mTmpRect, insetBounds,
2079 mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
2080 }
2081
2082 return newOverrideConfig;
2083 }
2084
2085 /**
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07002086 * Update task's override configuration based on the bounds.
Jorim Jaggi0a932142016-02-01 17:42:25 -08002087 * @param bounds The bounds of the task.
Andrii Kulian8072d112016-09-16 11:11:01 -07002088 * @return True if the override configuration was updated.
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07002089 */
Andrii Kulian8072d112016-09-16 11:11:01 -07002090 boolean updateOverrideConfiguration(Rect bounds) {
Jorim Jaggi0a932142016-02-01 17:42:25 -08002091 return updateOverrideConfiguration(bounds, null /* insetBounds */);
2092 }
2093
2094 /**
2095 * Update task's override configuration based on the bounds.
2096 * @param bounds The bounds of the task.
2097 * @param insetBounds The bounds used to calculate the system insets, which is used here to
2098 * subtract the navigation bar/status bar size from the screen size reported
2099 * to the application. See {@link IActivityManager#resizeDockedStack}.
Andrii Kulian8072d112016-09-16 11:11:01 -07002100 * @return True if the override configuration was updated.
Jorim Jaggi0a932142016-02-01 17:42:25 -08002101 */
Andrii Kulian8072d112016-09-16 11:11:01 -07002102 boolean updateOverrideConfiguration(Rect bounds, @Nullable Rect insetBounds) {
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07002103 if (Objects.equals(mBounds, bounds)) {
Andrii Kulian8072d112016-09-16 11:11:01 -07002104 return false;
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07002105 }
Andrii Kulian1779e612016-10-12 21:58:25 -07002106 mTmpConfig.setTo(getOverrideConfiguration());
Wale Ogunwale5f986092015-12-04 15:35:38 -08002107 final boolean oldFullscreen = mFullscreen;
Andrii Kulian1779e612016-10-12 21:58:25 -07002108 final Configuration newConfig = getOverrideConfiguration();
Filip Gruszczynskiebcc8752015-08-25 16:51:05 -07002109
2110 mFullscreen = bounds == null;
Wale Ogunwale706ed792015-08-02 10:29:44 -07002111 if (mFullscreen) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002112 if (mBounds != null && StackId.persistTaskBounds(mStack.mStackId)) {
Wale Ogunwale706ed792015-08-02 10:29:44 -07002113 mLastNonFullscreenBounds = mBounds;
2114 }
2115 mBounds = null;
Andrii Kulian1779e612016-10-12 21:58:25 -07002116 newConfig.unset();
Wale Ogunwale706ed792015-08-02 10:29:44 -07002117 } else {
Wale Ogunwale9a08f822016-02-17 19:03:58 -08002118 mTmpRect.set(bounds);
2119 adjustForMinimalTaskDimensions(mTmpRect);
Chong Zhangb15758a2015-11-17 12:12:03 -08002120 if (mBounds == null) {
Wale Ogunwale9a08f822016-02-17 19:03:58 -08002121 mBounds = new Rect(mTmpRect);
Chong Zhangb15758a2015-11-17 12:12:03 -08002122 } else {
Wale Ogunwale9a08f822016-02-17 19:03:58 -08002123 mBounds.set(mTmpRect);
Chong Zhangb15758a2015-11-17 12:12:03 -08002124 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07002125 if (mStack == null || StackId.persistTaskBounds(mStack.mStackId)) {
Wale Ogunwaleb34a7ad2015-08-14 11:05:30 -07002126 mLastNonFullscreenBounds = mBounds;
2127 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07002128 computeOverrideConfiguration(newConfig, mTmpRect, insetBounds,
Andrii Kuliandaea3572016-04-08 13:20:51 -07002129 mTmpRect.right != bounds.right, mTmpRect.bottom != bounds.bottom);
Wale Ogunwale706ed792015-08-02 10:29:44 -07002130 }
Andrii Kulian1779e612016-10-12 21:58:25 -07002131 onOverrideConfigurationChanged(newConfig);
Wale Ogunwale5f986092015-12-04 15:35:38 -08002132
2133 if (mFullscreen != oldFullscreen) {
Winson Chung5af42fc2017-03-24 17:11:33 -07002134 mService.mStackSupervisor.scheduleUpdateMultiWindowMode(this);
Wale Ogunwale5f986092015-12-04 15:35:38 -08002135 }
2136
Andrii Kulian1779e612016-10-12 21:58:25 -07002137 return !mTmpConfig.equals(newConfig);
Wale Ogunwalee4a0c572015-06-30 08:40:31 -07002138 }
2139
Andrii Kulian1779e612016-10-12 21:58:25 -07002140 /** Clears passed config and fills it with new override values. */
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -07002141 // TODO(b/36505427): TaskRecord.computeOverrideConfiguration() is a utility method that doesn't
2142 // depend on task or stacks, but uses those object to get the display to base the calculation
2143 // on. Probably best to centralize calculations like this in ConfigurationContainer.
2144 void computeOverrideConfiguration(Configuration config, Rect bounds, Rect insetBounds,
Andrii Kuliana8a9bc52016-10-14 11:00:13 -07002145 boolean overrideWidth, boolean overrideHeight) {
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08002146 mTmpNonDecorBounds.set(bounds);
2147 mTmpStableBounds.set(bounds);
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08002148
Andrii Kulian1779e612016-10-12 21:58:25 -07002149 config.unset();
Winson Chungbdc646f2017-02-13 12:12:22 -08002150 final Configuration parentConfig = getParent().getConfiguration();
Bryce Lee7566d762017-03-30 09:34:15 -07002151
Andrii Kulian1779e612016-10-12 21:58:25 -07002152 final float density = parentConfig.densityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08002153
Winson Chungbdc646f2017-02-13 12:12:22 -08002154 if (mStack != null) {
2155 final StackWindowController stackController = mStack.getWindowContainerController();
2156 stackController.adjustConfigurationForBounds(bounds, insetBounds,
2157 mTmpNonDecorBounds, mTmpStableBounds, overrideWidth, overrideHeight, density,
2158 config, parentConfig);
2159 } else {
Bryce Lee7566d762017-03-30 09:34:15 -07002160 throw new IllegalArgumentException("Expected stack when calculating override config");
Winson Chungbdc646f2017-02-13 12:12:22 -08002161 }
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08002162
Winson Chung60c1aba2017-03-14 17:47:42 -07002163 config.orientation = (config.screenWidthDp <= config.screenHeightDp)
2164 ? Configuration.ORIENTATION_PORTRAIT
2165 : Configuration.ORIENTATION_LANDSCAPE;
2166
Jorim Jaggi85639432016-05-06 17:27:55 -07002167 // For calculating screen layout, we need to use the non-decor inset screen area for the
2168 // calculation for compatibility reasons, i.e. screen area without system bars that could
2169 // never go away in Honeycomb.
Winson Chungbdc646f2017-02-13 12:12:22 -08002170 final int compatScreenWidthDp = (int) (mTmpNonDecorBounds.width() / density);
2171 final int compatScreenHeightDp = (int) (mTmpNonDecorBounds.height() / density);
Andrii Kulian1779e612016-10-12 21:58:25 -07002172 // We're only overriding LONG, SIZE and COMPAT parts of screenLayout, so we start override
2173 // calculation with partial default.
2174 final int sl = Configuration.SCREENLAYOUT_LONG_YES | Configuration.SCREENLAYOUT_SIZE_XLARGE;
Jorim Jaggi82c9dc92016-02-05 15:10:33 -08002175 final int longSize = Math.max(compatScreenHeightDp, compatScreenWidthDp);
Andrii Kulian1779e612016-10-12 21:58:25 -07002176 final int shortSize = Math.min(compatScreenHeightDp, compatScreenWidthDp);
Jorim Jaggi85639432016-05-06 17:27:55 -07002177 config.screenLayout = Configuration.reduceScreenLayout(sl, longSize, shortSize);
2178
Jorim Jaggia95ca8d2016-01-15 22:54:46 -08002179 }
2180
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002181 Rect updateOverrideConfigurationFromLaunchBounds() {
2182 final Rect bounds = validateBounds(getLaunchBounds());
2183 updateOverrideConfiguration(bounds);
Andrii Kulian73336d812016-03-24 12:56:08 -07002184 if (bounds != null) {
2185 bounds.set(mBounds);
2186 }
Filip Gruszczynskidce2d162016-01-12 15:40:13 -08002187 return bounds;
2188 }
2189
2190 static Rect validateBounds(Rect bounds) {
2191 if (bounds != null && bounds.isEmpty()) {
2192 Slog.wtf(TAG, "Received strange task bounds: " + bounds, new Throwable());
2193 return null;
2194 }
2195 return bounds;
2196 }
2197
Wale Ogunwale935e5022015-11-10 12:36:10 -08002198 /** Updates the task's bounds and override configuration to match what is expected for the
2199 * input stack. */
2200 void updateOverrideConfigurationForStack(ActivityStack inStack) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002201 if (mStack != null && mStack == inStack) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08002202 return;
2203 }
2204
2205 if (inStack.mStackId == FREEFORM_WORKSPACE_STACK_ID) {
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002206 if (!isResizeable()) {
Wale Ogunwale935e5022015-11-10 12:36:10 -08002207 throw new IllegalArgumentException("Can not position non-resizeable task="
2208 + this + " in stack=" + inStack);
2209 }
2210 if (mBounds != null) {
2211 return;
2212 }
2213 if (mLastNonFullscreenBounds != null) {
2214 updateOverrideConfiguration(mLastNonFullscreenBounds);
2215 } else {
2216 inStack.layoutTaskInStack(this, null);
2217 }
2218 } else {
2219 updateOverrideConfiguration(inStack.mBounds);
2220 }
2221 }
2222
Chong Zhang0fa656b2015-08-31 15:17:21 -07002223 /**
2224 * Returns the correct stack to use based on task type and currently set bounds,
2225 * regardless of the focused stack and current stack association of the task.
2226 * The task will be moved (and stack focus changed) later if necessary.
2227 */
2228 int getLaunchStackId() {
Matthew Ngae1ff4f2016-11-10 15:49:14 -08002229 if (isRecentsTask()) {
2230 return RECENTS_STACK_ID;
2231 }
2232 if (isHomeTask()) {
Wale Ogunwale706ed792015-08-02 10:29:44 -07002233 return HOME_STACK_ID;
2234 }
Winson Chung83471632016-12-13 11:02:12 -08002235 if (isAssistantTask()) {
2236 return ASSISTANT_STACK_ID;
2237 }
Chong Zhang0fa656b2015-08-31 15:17:21 -07002238 if (mBounds != null) {
Wale Ogunwale706ed792015-08-02 10:29:44 -07002239 return FREEFORM_WORKSPACE_STACK_ID;
2240 }
2241 return FULLSCREEN_WORKSPACE_STACK_ID;
2242 }
2243
2244 /** Returns the bounds that should be used to launch this task. */
2245 Rect getLaunchBounds() {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002246 if (mStack == null) {
Chong Zhang7d5f5102016-01-13 10:29:24 -08002247 return null;
2248 }
2249
Andrii Kulian02b7a832016-10-06 23:11:56 -07002250 final int stackId = mStack.mStackId;
Chong Zhang7d5f5102016-01-13 10:29:24 -08002251 if (stackId == HOME_STACK_ID
Matthew Ngae1ff4f2016-11-10 15:49:14 -08002252 || stackId == RECENTS_STACK_ID
Winson Chung83471632016-12-13 11:02:12 -08002253 || stackId == ASSISTANT_STACK_ID
Chong Zhang7d5f5102016-01-13 10:29:24 -08002254 || stackId == FULLSCREEN_WORKSPACE_STACK_ID
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002255 || (stackId == DOCKED_STACK_ID && !isResizeable())) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002256 return isResizeable() ? mStack.mBounds : null;
Wale Ogunwale3797c222015-10-27 14:21:58 -07002257 } else if (!StackId.persistTaskBounds(stackId)) {
Andrii Kulian02b7a832016-10-06 23:11:56 -07002258 return mStack.mBounds;
Wale Ogunwale706ed792015-08-02 10:29:44 -07002259 }
2260 return mLastNonFullscreenBounds;
2261 }
2262
Jorim Jaggi8b702ed2017-01-20 16:59:03 +01002263 void addStartingWindowsForVisibleActivities(boolean taskSwitch) {
2264 for (int activityNdx = mActivities.size() - 1; activityNdx >= 0; --activityNdx) {
2265 final ActivityRecord r = mActivities.get(activityNdx);
2266 if (r.visible) {
2267 r.showStartingWindow(null /* prev */, false /* newTask */, taskSwitch);
2268 }
2269 }
2270 }
2271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002272 void dump(PrintWriter pw, String prefix) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002273 pw.print(prefix); pw.print("userId="); pw.print(userId);
Dianne Hackborn885fbe52014-08-23 15:23:58 -07002274 pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
2275 pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
Suprabh Shukla7745c142016-03-07 18:21:10 -08002276 pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002277 pw.print(" mCallingPackage="); pw.println(mCallingPackage);
Dianne Hackborn79228822014-09-16 11:11:23 -07002278 if (affinity != null || rootAffinity != null) {
2279 pw.print(prefix); pw.print("affinity="); pw.print(affinity);
2280 if (affinity == null || !affinity.equals(rootAffinity)) {
2281 pw.print(" root="); pw.println(rootAffinity);
2282 } else {
2283 pw.println();
2284 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002285 }
Dianne Hackborn91097de2014-04-04 18:02:06 -07002286 if (voiceSession != null || voiceInteractor != null) {
2287 pw.print(prefix); pw.print("VOICE: session=0x");
2288 pw.print(Integer.toHexString(System.identityHashCode(voiceSession)));
2289 pw.print(" interactor=0x");
2290 pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor)));
2291 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002292 if (intent != null) {
2293 StringBuilder sb = new StringBuilder(128);
2294 sb.append(prefix); sb.append("intent={");
Dianne Hackborn21c241e2012-03-08 13:57:23 -08002295 intent.toShortString(sb, false, true, false, true);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002296 sb.append('}');
2297 pw.println(sb.toString());
2298 }
2299 if (affinityIntent != null) {
2300 StringBuilder sb = new StringBuilder(128);
2301 sb.append(prefix); sb.append("affinityIntent={");
Dianne Hackborn21c241e2012-03-08 13:57:23 -08002302 affinityIntent.toShortString(sb, false, true, false, true);
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002303 sb.append('}');
2304 pw.println(sb.toString());
2305 }
2306 if (origActivity != null) {
2307 pw.print(prefix); pw.print("origActivity=");
2308 pw.println(origActivity.flattenToShortString());
2309 }
2310 if (realActivity != null) {
2311 pw.print(prefix); pw.print("realActivity=");
2312 pw.println(realActivity.flattenToShortString());
2313 }
Dianne Hackborn852975d2014-08-22 17:42:43 -07002314 if (autoRemoveRecents || isPersistable || taskType != 0 || mTaskToReturnTo != 0
2315 || numFullscreen != 0) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002316 pw.print(prefix); pw.print("autoRemoveRecents="); pw.print(autoRemoveRecents);
Dianne Hackborn852975d2014-08-22 17:42:43 -07002317 pw.print(" isPersistable="); pw.print(isPersistable);
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002318 pw.print(" numFullscreen="); pw.print(numFullscreen);
2319 pw.print(" taskType="); pw.print(taskType);
2320 pw.print(" mTaskToReturnTo="); pw.println(mTaskToReturnTo);
2321 }
Craig Mautner432f64e2015-05-20 14:59:57 -07002322 if (rootWasReset || mNeverRelinquishIdentity || mReuseTask
2323 || mLockTaskAuth != LOCK_TASK_AUTH_PINNABLE) {
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002324 pw.print(prefix); pw.print("rootWasReset="); pw.print(rootWasReset);
2325 pw.print(" mNeverRelinquishIdentity="); pw.print(mNeverRelinquishIdentity);
Craig Mautner432f64e2015-05-20 14:59:57 -07002326 pw.print(" mReuseTask="); pw.print(mReuseTask);
2327 pw.print(" mLockTaskAuth="); pw.println(lockTaskAuthToString());
Dianne Hackbornaec68bb2014-08-20 15:25:13 -07002328 }
Wale Ogunwale18795a22014-12-03 11:38:33 -08002329 if (mAffiliatedTaskId != taskId || mPrevAffiliateTaskId != INVALID_TASK_ID
2330 || mPrevAffiliate != null || mNextAffiliateTaskId != INVALID_TASK_ID
2331 || mNextAffiliate != null) {
Dianne Hackborn852975d2014-08-22 17:42:43 -07002332 pw.print(prefix); pw.print("affiliation="); pw.print(mAffiliatedTaskId);
2333 pw.print(" prevAffiliation="); pw.print(mPrevAffiliateTaskId);
2334 pw.print(" (");
2335 if (mPrevAffiliate == null) {
2336 pw.print("null");
2337 } else {
2338 pw.print(Integer.toHexString(System.identityHashCode(mPrevAffiliate)));
2339 }
2340 pw.print(") nextAffiliation="); pw.print(mNextAffiliateTaskId);
2341 pw.print(" (");
2342 if (mNextAffiliate == null) {
2343 pw.print("null");
2344 } else {
2345 pw.print(Integer.toHexString(System.identityHashCode(mNextAffiliate)));
2346 }
2347 pw.println(")");
2348 }
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002349 pw.print(prefix); pw.print("Activities="); pw.println(mActivities);
Dianne Hackborn852975d2014-08-22 17:42:43 -07002350 if (!askedCompatMode || !inRecents || !isAvailable) {
2351 pw.print(prefix); pw.print("askedCompatMode="); pw.print(askedCompatMode);
2352 pw.print(" inRecents="); pw.print(inRecents);
2353 pw.print(" isAvailable="); pw.println(isAvailable);
Dianne Hackborn36cd41f2011-05-25 21:00:46 -07002354 }
Craig Mautnerc0ffce52014-07-01 12:38:52 -07002355 pw.print(prefix); pw.print("lastThumbnail="); pw.print(mLastThumbnail);
Dianne Hackborn852975d2014-08-22 17:42:43 -07002356 pw.print(" lastThumbnailFile="); pw.println(mLastThumbnailFile);
2357 if (lastDescription != null) {
2358 pw.print(prefix); pw.print("lastDescription="); pw.println(lastDescription);
2359 }
Andrii Kulian02b7a832016-10-06 23:11:56 -07002360 pw.print(prefix); pw.print("stackId="); pw.println(getStackId());
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002361 pw.print(prefix + "hasBeenVisible=" + hasBeenVisible);
2362 pw.print(" mResizeMode=" + ActivityInfo.resizeModeToString(mResizeMode));
Winson Chungd3395382016-12-13 11:49:09 -08002363 pw.print(" mSupportsPictureInPicture=" + mSupportsPictureInPicture);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002364 pw.print(" isResizeable=" + isResizeable());
daqi961e50e2017-05-30 15:37:23 +08002365 pw.print(" firstActiveTime=" + firstActiveTime);
Wale Ogunwaleb1faf602016-01-27 09:12:31 -08002366 pw.print(" lastActiveTime=" + lastActiveTime);
2367 pw.println(" (inactive for " + (getInactiveDuration() / 1000) + "s)");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002368 }
2369
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002370 @Override
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002371 public String toString() {
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002372 StringBuilder sb = new StringBuilder(128);
Craig Mautnerde4ef022013-04-07 19:01:33 -07002373 if (stringName != null) {
2374 sb.append(stringName);
2375 sb.append(" U=");
2376 sb.append(userId);
Wale Ogunwale6c5eb1c2015-11-10 07:52:22 -08002377 sb.append(" StackId=");
Andrii Kulian02b7a832016-10-06 23:11:56 -07002378 sb.append(getStackId());
Craig Mautnerde4ef022013-04-07 19:01:33 -07002379 sb.append(" sz=");
2380 sb.append(mActivities.size());
2381 sb.append('}');
2382 return sb.toString();
2383 }
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002384 sb.append("TaskRecord{");
2385 sb.append(Integer.toHexString(System.identityHashCode(this)));
2386 sb.append(" #");
2387 sb.append(taskId);
2388 if (affinity != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002389 sb.append(" A=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002390 sb.append(affinity);
2391 } else if (intent != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002392 sb.append(" I=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002393 sb.append(intent.getComponent().flattenToShortString());
2394 } else if (affinityIntent != null) {
Craig Mautner5d9c7be2013-02-15 14:02:56 -08002395 sb.append(" aI=");
Dianne Hackborn1d442e02009-04-20 18:14:05 -07002396 sb.append(affinityIntent.getComponent().flattenToShortString());
2397 } else {
2398 sb.append(" ??");
2399 }
Craig Mautnerde4ef022013-04-07 19:01:33 -07002400 stringName = sb.toString();
2401 return toString();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002402 }
2403}